sumCurrencyIO method

Result<Map<AssetId, Coin>, String> sumCurrencyIO({
  1. required BlockchainCache cache,
  2. Coin fee = 0,
  3. Logger? logger,
})

Sum currency amounts accross transaction. The sums should all be zero if the transaction is balanced. All transactions referenced by the inputs must be in the cache.

Implementation

Result<Map<AssetId, Coin>, String> sumCurrencyIO({
  required BlockchainCache cache,
  Coin fee = 0,
  Logger? logger,
}) {
  logger ??= Logger();
  Map<AssetId, Coin> sums = {};
  for (final input in inputs) {
    RawTransaction? tx = cache.cachedTransaction(input.transactionId);
    if (tx == null) {
      return Err("transaction '${input.transactionId}' not in cache");
    }
    if (tx.outputs.length <= input.index) {
      return Err(
          "transaction '${input.transactionId}' index[${input.index}] out of range[0..${tx.outputs.length - 1}]");
    }
    final output = tx.outputs[input.index];
    for (final amount in output.amounts) {
      sums[amount.unit] = amount.quantity + (sums[amount.unit] ?? coinZero);
    }
  }
  for (final ShelleyTransactionOutput output in outputs) {
    sums[lovelaceHex] = (sums[lovelaceHex] ?? coinZero) - output.value.coin;
    for (final assets in output.value.multiAssets) {
      final policyId = assets.policyId;
      for (final asset in assets.assets) {
        final assetId = policyId + asset.name;
        sums[assetId] = (sums[assetId] ?? coinZero) - asset.value;
      }
    }
  }
  logger.i(" ====> sumCurrencyIO - should all be zero if balanced:");
  for (final assetId in sums.keys) {
    if (assetId == lovelaceHex) {
      logger.i(
          "   ==> lovelace: ${sums[assetId]} - fee($fee) = ${(sums[lovelaceHex] ?? coinZero) - fee}");
    } else {
      logger.i("   ==> $assetId: ${sums[assetId]}");
    }
  }
  sums[lovelaceHex] = (sums[lovelaceHex] ?? coinZero) - fee;
  return Ok(sums);
}