text: // @flow
  
  import {AuxiliaryData, BigNum, LinearFee} from '@emurgo/react-native-haskell-shelley'
  import {BigNumber} from 'bignumber.js'
  
  import type {CardanoHaskellShelleyNetwork} from '../../config/networks'
  import assert from '../../utils/assert'
  import {Logger} from '../../utils/logging'
  import {builtSendTokenList, hasSendAllDefault} from '../commonUtils'
  import {CardanoError, InsufficientFunds, NoOutputsError} from '../errors'
  import type {DefaultTokenEntry} from '../MultiToken'
  import type {AddressedUtxo, Addressing, SendTokenList} from '../types'
  import {HaskellShelleyTxSignRequest} from './HaskellShelleyTxSignRequest'
  import {newAdaUnsignedTx, sendAllUnsignedTx} from './transactions'
  import {multiTokenFromRemote} from './utils'
  
  export type CreateUnsignedTxRequest = {|
    changeAddr: {
      address: string,
      ...Addressing,
    },
    absSlotNumber: BigNumber,
    receiver: string,
    addressedUtxos: Array<AddressedUtxo>,
    defaultToken: DefaultTokenEntry,
    tokens: SendTokenList,
    auxiliaryData: AuxiliaryData | void,
    networkConfig: CardanoHaskellShelleyNetwork,
  |}
  
  export type CreateUnsignedTxResponse = HaskellShelleyTxSignRequest
  
  export const createUnsignedTx = async (request: CreateUnsignedTxRequest): Promise<CreateUnsignedTxResponse> => {
    Logger.debug('createUnsignedTx called', request)
    const {changeAddr, receiver, addressedUtxos, absSlotNumber, auxiliaryData, networkConfig} = request
    try {
      const KEY_DEPOSIT = networkConfig.KEY_DEPOSIT
      const POOL_DEPOSIT = networkConfig.POOL_DEPOSIT
      const LINEAR_FEE = networkConfig.LINEAR_FEE
      const MINIMUM_UTXO_VAL = networkConfig.MINIMUM_UTXO_VAL
      const NETWORK_ID = networkConfig.NETWORK_ID
      const CHAIN_NETWORK_ID = networkConfig.CHAIN_NETWORK_ID
  
      const protocolParams = {
        keyDeposit: await BigNum.from_str(KEY_DEPOSIT),
        linearFee: await LinearFee.new(
          await BigNum.from_str(LINEAR_FEE.COEFFICIENT),
          await BigNum.from_str(LINEAR_FEE.CONSTANT),
        ),
        minimumUtxoVal: await BigNum.from_str(MINIMUM_UTXO_VAL),
        poolDeposit: await BigNum.from_str(POOL_DEPOSIT),
        networkId: NETWORK_ID,
      }
  
      let unsignedTxResponse
      if (hasSendAllDefault(request.tokens)) {
        assert.assert(receiver != null, 'sendAll requires a receiver address')
        unsignedTxResponse = await sendAllUnsignedTx(
          {address: receiver},
          addressedUtxos,
          absSlotNumber,
          protocolParams,
          auxiliaryData,
        )
      } else {
        assert.assert(
          changeAddr.address != null && changeAddr.addressing != null,
          'change address missing, should never happen',
        )
        unsignedTxResponse = await newAdaUnsignedTx(
          [
            {
              address: receiver,
              amount: builtSendTokenList(
                request.defaultToken,
                request.tokens,
                addressedUtxos.map((utxo) => multiTokenFromRemote(utxo, protocolParams.networkId)),
              ),
            },
          ],
          {
            address: changeAddr.address,
            addressing: changeAddr.addressing,
          },
          addressedUtxos,
          absSlotNumber,
          protocolParams,
          [], // no certificates
          [], // no withdrawals
          false, // do not allow no outputs
          auxiliaryData,
        )
      }
  
      Logger.debug(`createUnsignedTx success: ${JSON.stringify(unsignedTxResponse)}`)
      return new HaskellShelleyTxSignRequest({
        senderUtxos: unsignedTxResponse.senderUtxos,
        unsignedTx: unsignedTxResponse.txBuilder,
        changeAddr: unsignedTxResponse.changeAddr,
        auxiliaryData,
        networkSettingSnapshot: {
          NetworkId: NETWORK_ID,
          ChainNetworkId: Number.parseInt(CHAIN_NETWORK_ID, 10),
          KeyDeposit: new BigNumber(KEY_DEPOSIT),
          PoolDeposit: new BigNumber(POOL_DEPOSIT),
        },
        neededStakingKeyHashes: {
          neededHashes: new Set(),
          wits: new Set(),
        },
      })
    } catch (e) {
      if (e instanceof InsufficientFunds || e instanceof NoOutputsError) throw e
      Logger.error(`shelley::createUnsignedTx:: ${e.message}`, e)
      throw new CardanoError(e.message)
    }
  }
  