generateL2Transaction function

Future<Set<Map<String, dynamic>>> generateL2Transaction(
  1. Map tx,
  2. String? bjj,
  3. Token token
)

Prepares a transaction to be ready to be sent to a Coordinator.

@param {Object} transaction - ethAddress and babyPubKey together @param {String} transaction.from - The account index that's sending the transaction e.g hez:DAI:4444 @param {String} transaction.to - The account index of the receiver e.g hez:DAI:2156. If it's an Exit, set to a falseable value @param {String} transaction.amount - The amount being sent as a BigInt string @param {Number} transaction.fee - The amount of tokens to be sent as a fee to the Coordinator @param {Number} transaction.nonce - The current nonce of the sender's token account @param {String} bJJ - The compressed BabyJubJub in hexadecimal format of the transaction sender @param {Object} token - The token information object as returned from the Coordinator.

@return {Object} - Contains transaction and encodedTransaction. transaction is the object almost ready to be sent to the Coordinator. encodedTransaction is needed to sign the transaction

Implementation

Future<Set<Map<String, dynamic>>> generateL2Transaction(
    Map tx, String? bjj, Token token) async {
  final type = tx['type'] != null ? tx['type'] : getTransactionType(tx);
  final nonce = await getNonce(tx['nonce'], tx['from'], bjj, token.id);
  final toAccountIndex = isHermezAccountIndex(tx['to']) ? tx['to'] : null;
  final decompressedAmount =
      HermezCompressedAmount.decompressAmount(tx['amount']);
  final feeBigInt = getTokenAmountBigInt(tx['fee'], token.decimals!);

  String? toHezEthereumAddress;
  if (type == 'TransferToEthAddr') {
    toHezEthereumAddress = tx['to'];
  }
  /* else if (type == 'TransferToBJJ') {
    toHezEthereumAddress = tx['toAuxEthAddr'] != null
        ? tx['toAuxEthAddr']
        : INTERNAL_ACCOUNT_ETH_ADDR;
  }*/

  Map<String, dynamic> transaction = {};
  transaction.putIfAbsent('type', () => type);
  transaction.putIfAbsent('tokenId', () => token.id);
  transaction.putIfAbsent('fromAccountIndex', () => tx['from']);
  transaction.putIfAbsent('toAccountIndex',
      () => type == 'Exit' ? 'hez:${token.symbol}:1' : toAccountIndex);
  transaction.putIfAbsent('toHezEthereumAddress', () => toHezEthereumAddress);
  transaction.putIfAbsent(
      'toBjj', () => type == 'TransferToBJJ' ? tx['to'] : null);
  // Corrects precision errors using the same system used in the Coordinator
  transaction.putIfAbsent(
      'amount', () => decompressedAmount.toString().replaceAll(".0", ""));
  transaction.putIfAbsent(
      'fee', () => getFeeIndex(feeBigInt.toDouble(), decompressedAmount));
  transaction.putIfAbsent('nonce', () => nonce);
  transaction.putIfAbsent('requestFromAccountIndex', () => null);
  transaction.putIfAbsent('requestToAccountIndex', () => null);
  transaction.putIfAbsent('requestToHezEthereumAddress', () => null);
  transaction.putIfAbsent('requestToBjj', () => null);
  transaction.putIfAbsent('requestTokenId', () => null);
  transaction.putIfAbsent('requestAmount', () => null);
  transaction.putIfAbsent('requestFee', () => null);
  transaction.putIfAbsent('requestNonce', () => null);
  Map<String, dynamic> encodedTransaction = encodeTransaction(transaction);
  transaction.putIfAbsent(
      'id',
      () => getL2TxId(
          encodedTransaction['fromAccountIndex'],
          encodedTransaction['tokenId'],
          decompressedAmount,
          encodedTransaction['nonce'],
          encodedTransaction['fee']));
  return {transaction, encodedTransaction};
}