prepareTxsForSigningImpl method

  1. @SquadronMethod.new()
  2. @txSigningBundleMarshaler
Future<TxSigningBundle> prepareTxsForSigningImpl(
  1. String walletBech32Address,
  2. String drepCredential,
  3. String constitutionalCommitteeColdCredential,
  4. String constitutionalCommitteeHotCredential,
  5. @networkIdMarshaler NetworkId networkId,
  6. @cardanoTransactionListMarshaler List<CardanoTransaction> txs,
  7. @utxoListMarshaler List<Utxo> utxos,
)

Implementation

@SquadronMethod()
@txSigningBundleMarshaler
Future<TxSigningBundle> prepareTxsForSigningImpl(
  String walletBech32Address,
  String drepCredential,
  String constitutionalCommitteeColdCredential,
  String constitutionalCommitteeHotCredential,
  @networkIdMarshaler NetworkId networkId,
  @cardanoTransactionListMarshaler List<CardanoTransaction> txs,
  @utxoListMarshaler List<Utxo> utxos,
) async {
  final bech32Address = walletBech32Address;

  final txsPreparedForSigning = List<TxPreparedForSigning>.empty(growable: true);

  var walletUtxosBeforeTx = utxos;

  for (final CardanoTransaction tx in txs) {
    final txHash = tx.body.blake2bHash256Hex();

    final usedUtxosTxAndId = tx.body.inputs.data.map((e) => "${e.transactionHash}#${e.index}").toSet();
    final collateralUtxosTxAndId = tx.body.collateral?.data.map((e) => "${e.transactionHash}#${e.index}").toSet();

    final txUtxos = {...usedUtxosTxAndId, ...?collateralUtxosTxAndId};
    final Set<String> signatureAddresses = walletUtxosBeforeTx
        // find all wallet utxos used in this tx
        .where((e) => txUtxos.contains("${e.identifier.transactionHash}#${e.identifier.index}"))
        // get the wallet addresses needed to sign the used wallet utxos
        .map((e) => e.content.addressBytes.addressBase58Orbech32Encode())
        .toSet();

    final List<Utxo> notUsedUserUtxos = walletUtxosBeforeTx
        .where((e) => !usedUtxosTxAndId.contains("${e.identifier.transactionHash}#${e.identifier.index}"))
        .toList();
    final List<Utxo> generatedUserUtxos = tx.body.outputs
        .mapIndexed<Utxo?>(
          (utxoIndex, e) => e.addressBytes.addressBase58Orbech32Encode() != bech32Address
              ? null
              : Utxo(
                  identifier: CardanoTransactionInput(transactionHash: txHash, index: utxoIndex),
                  content: e,
                ),
        )
        .nonNulls
        .toList();

    txsPreparedForSigning.add(
      TxPreparedForSigning(
        tx: tx,
        txDiff: tx.diff(
          receiveAddressBech32: bech32Address,
          walletUtxos: walletUtxosBeforeTx,
          drepCredential: drepCredential,
          constitutionalCommitteeColdCredential: constitutionalCommitteeColdCredential,
          constitutionalCommitteeHotCredential: constitutionalCommitteeHotCredential,
        ),
        utxosBeforeTx: walletUtxosBeforeTx,
        signingAddressesRequired: signatureAddresses,
      ),
    );

    // for next iteration, update the utxos
    walletUtxosBeforeTx = [...notUsedUserUtxos, ...generatedUserUtxos];
  }

  final txsTotalDiff = txsPreparedForSigning.reduceSafe(
    initialValue: Value.v0(lovelace: BigInt.zero),
    combine: (aggregator, e) => aggregator + e.txDiff.diff,
  );

  return TxSigningBundle(
    receiveAddressBech32: bech32Address,
    networkId: networkId,
    txsData: txsPreparedForSigning,
    totalDiff: txsTotalDiff,
    stakeDelegationPoolId: txsPreparedForSigning.map((e) => e.txDiff.stakeDelegationPoolId).nonNulls.lastOrNull,
    dRepDeregistration: txsPreparedForSigning.any((e) => e.txDiff.dRepDeregistration),
    stakeDeregistration: txsPreparedForSigning.any((e) => e.txDiff.stakeDeregistration),
    authorizeConstitutionalCommitteeHot: txsPreparedForSigning
        .map((e) => e.txDiff.authorizeConstitutionalCommitteeHot)
        .nonNulls
        .lastOrNull,
    resignConstitutionalCommitteeCold: txsPreparedForSigning
        .map((e) => e.txDiff.resignConstitutionalCommitteeCold)
        .nonNulls
        .lastOrNull,
    dRepDelegation: txsPreparedForSigning.map((e) => e.txDiff.dRepDelegation).nonNulls.lastOrNull,
    dRepRegistration: txsPreparedForSigning.map((e) => e.txDiff.dRepRegistration).nonNulls.lastOrNull,
    dRepUpdate: txsPreparedForSigning.map((e) => e.txDiff.dRepUpdate).nonNulls.lastOrNull,
    votes: txsPreparedForSigning.map((e) => e.txDiff.votes).nonNulls.flattened.toList(),
    proposals: txsPreparedForSigning.map((e) => e.txDiff.proposals).nonNulls.flattened.toList(),
  );
}