code: def handle_lock_expired(
          payment_state: InitiatorPaymentState,
          state_change: ReceiveLockExpired,
          channelidentifiers_to_channels: ChannelMap,
          block_number: BlockNumber,
  ) -> TransitionResult[InitiatorPaymentState]:
      
      initiator_state = payment_state.initiator_transfers.get(state_change.secrethash)
      if not initiator_state:
          return TransitionResult(payment_state, list())
  
      channel_identifier = initiator_state.channel_identifier
      channel_state = channelidentifiers_to_channels.get(channel_identifier)
  
      if not channel_state:
          return TransitionResult(payment_state, list())
  
      secrethash = initiator_state.transfer.lock.secrethash
      result = channel.handle_receive_lock_expired(
          channel_state=channel_state,
          state_change=state_change,
          block_number=block_number,
      )
      assert result.new_state, 'handle_receive_lock_expired should not delete the task'
  
      if not channel.get_lock(result.new_state.partner_state, secrethash):
          transfer = initiator_state.transfer
          unlock_failed = EventUnlockClaimFailed(
              identifier=transfer.payment_identifier,
              secrethash=transfer.lock.secrethash,
              reason='Lock expired',
          )
          result.events.append(unlock_failed)
  
      return TransitionResult(payment_state, result.events)
docs: Initiator also needs to handle LockExpired messages when refund transfers are involved.
  
      A -> B -> C
  
      - A sends locked transfer to B
      - B attempted to forward to C but has not enough capacity
      - B sends a refund transfer with the same secrethash back to A
      - When the lock expires B will also send a LockExpired message to A
      - A needs to be able to properly process it
  
      Related issue: https://github.com/raiden-network/raiden/issues/3183