executeRegisterBlobTransaction method

Future<({String blobObjectId, String digest})> executeRegisterBlobTransaction({
  1. required int size,
  2. required int epochs,
  3. required String blobId,
  4. required Uint8List rootHash,
  5. required bool deletable,
  6. required SuiAccount signer,
  7. String? owner,
  8. String? walCoinObjectId,
  9. Map<String, String?>? attributes,
})

Execute a transaction that registers a blob on-chain.

Builds a register blob transaction with proper WAL payment, signs and executes it.

Returns the transaction digest and the created blob object ID.

Mirrors the TS SDK's executeRegisterBlobTransaction().

Implementation

Future<({String digest, String blobObjectId})>
executeRegisterBlobTransaction({
  required int size,
  required int epochs,
  required String blobId,
  required Uint8List rootHash,
  required bool deletable,
  required SuiAccount signer,
  String? owner,
  String? walCoinObjectId,
  Map<String, String?>? attributes,
}) async {
  final txBuilder = await _ensureTxBuilder();
  final costs = await storageCost(size, epochs);
  final effectiveOwner = owner ?? signer.getAddress();

  // Resolve WAL coin.
  final walCoin =
      walCoinObjectId ?? await findWalCoin(effectiveOwner, costs.totalCost);

  if (walCoin == null) {
    throw InsufficientWalBalanceError(
      ownerAddress: effectiveOwner,
      requiredAmount: costs.totalCost,
      message:
          'No WAL coin with sufficient balance for blob registration. '
          'Need ${costs.totalCost} WAL '
          '(storage: ${costs.storageCost}, write: ${costs.writeCost}).',
    );
  }

  final systemState = await _stateReader.systemState();
  final encodedSize = encodedBlobLength(size, systemState.nShards);

  final tx = txBuilder.registerBlobWithWal(
    RegisterBlobOptions(
      size: size,
      epochs: epochs,
      blobId: blobId,
      rootHash: rootHash,
      deletable: deletable,
      owner: effectiveOwner,
    ),
    walCoinObjectId: walCoin,
    walType: await getWalType(),
    storageCost: costs.storageCost,
    writeCost: costs.writeCost,
    encodedSize: encodedSize,
  );

  // Write attributes if provided.
  if (attributes != null && attributes.isNotEmpty) {
    // The blob object is the last result in the transaction.
    // We need to add metadata to it before the transfer.
    // For attributes, we build a separate follow-up transaction
    // after the blob is created. The TS SDK combines them in
    // one PTB, but for robustness, we separate them.
  }

  tx.setSender(signer.getAddress());

  final result = await suiClient.signAndExecuteTransactionBlock(
    signer,
    tx,
    responseOptions: SuiTransactionBlockResponseOptions(
      showEffects: true,
      showObjectChanges: true,
    ),
  );

  final blobObjectId = _extractBlobObjectId(result);

  // Write attributes in a follow-up transaction if provided.
  if (attributes != null && attributes.isNotEmpty) {
    await executeWriteBlobAttributesTransaction(
      blobObjectId: blobObjectId,
      attributes: attributes,
      signer: signer,
    );
  }

  return (digest: result.digest, blobObjectId: blobObjectId);
}