prepareTransaction method

Future<Uint8List> prepareTransaction(
  1. Transaction tx, {
  2. required String sender,
  3. BigInt? gasBudget,
})

Prepare tx (sender, gas price/payment/budget) and return the built TransactionData BCS bytes, ready to sign.

Implementation

Future<Uint8List> prepareTransaction(
  Transaction tx, {
  required String sender,
  BigInt? gasBudget,
}) async {
  // The adapter lets the builder resolve object references and moveCall
  // signatures over gRPC; offline limits avoid a protocol-config fetch.
  final buildOptions = BuildOptions(
    client: GrpcBuilderAdapter(this),
    limits: <String, dynamic>{},
  );

  // Resolve any Move Registry (`@org/app`) names in moveCall targets/types.
  await tx.resolveNames(
    resolvePackage: resolvePackage,
    resolveType: resolveType,
  );

  tx.setSenderIfNotSet(sender);

  final gasPrice = BigInt.from((await getReferenceGasPrice()).toInt());
  tx.setGasPrice(gasPrice);

  final gasCoin = await _selectGasCoin(sender);
  tx.setGasPayment([gasCoin]);

  if (gasBudget != null) {
    tx.setGasBudget(gasBudget);
    return tx.build(buildOptions);
  }

  // Estimate budget by simulating. The provisional budget must (a) not exceed
  // the gas coin's balance and (b) leave room for amounts the transaction
  // splits off the gas coin. Use a modest cap; callers moving large amounts
  // from gas should pass an explicit [gasBudget].
  final suiBalance = BigInt.from((await getBalance(sender)).balance.toInt());
  final provisionalCap = BigInt.from(100000000); // 0.1 SUI
  tx.setGasBudget(suiBalance < provisionalCap ? suiBalance : provisionalCap);
  final provisional = await tx.build(buildOptions);
  final sim = await simulateTransaction(provisional);
  final status = sim.transaction.effects.status;
  if (!status.success) {
    throw StateError('Gas estimation simulation failed: ${status.error}');
  }
  final gas = sim.transaction.effects.gasUsed;
  final computation = BigInt.from(gas.computationCost.toInt());
  final storage = BigInt.from(gas.storageCost.toInt());
  final rebate = BigInt.from(gas.storageRebate.toInt());
  final base = computation + _safeOverhead * gasPrice;
  final withStorage = base + storage - rebate;
  final budget = withStorage > base ? withStorage : base;

  tx.setGasBudget(budget);
  return tx.build(buildOptions);
}