Sending coin object as function parameter when there is only one coin object

Using sui SDK in a react app, I want to call a function that takes a coin as an argument. Now the wallet I connected most of the time only has one coin object. Now if send the coin object as an argument I get an error probably because there is no gas object. Is there any syntax that the SDK would automatically handle the gas payment and still send the coin object? Since splitting the coin would prompt the wallet twice though (maybe sending two transactions and signing once might be a solution, but I am not sure the syntax allows this).

1 Like

The easiest way to do this is to build a PTB that first splits off a piece of the (single) input gas coin with the value you want to send, and then transfers the piece. The code from Building Programmable Transaction Blocks | Sui Documentation is a good reference for this:

const [coin] = txb.splitCoins(txb.gas, [txb.pure(100)]);
txb.transferObjects([coin], txb.pure("0xSomeSuiAddress"));
1 Like

However, if your intention is to transfer the entire gas coin (not a specific amount), you would do something like

txb.transferObjects([txb.gas], txb.pure("0xSomeSuiAddress"));
1 Like

@shb Thank you for the response. Two follow-up questions:

  1. Is 0xSomeSuiAddress referring to my own address? Cause I want to send the coin object in the function call later on like:
trx.moveCall({
        target: `${PACKAGE_ID}::protocol::mint`,
        arguments: [
          trx.pure(name),
          trx.object(coinObjectId),
        ],
      });

Here coinObjectId is the only coin object owned by the address.
2. More importantly, if you think about this happening from the frontend’s perspective, if we do go for the split coin approach, the user has to sign twice - one for splitting the coin and two for signing the tx to use the splited coin object and execute the function from the Package. IN what approach we make this a single signing experience?

1 Like

You can do something like

const [coin] = trx.splitCoins(txb.gas, [txb.pure(100)]);
trx.moveCall({
   target: `${PACKAGE_ID}::protocol::mint`,
        arguments: [
          trx.pure(name),
          coin,
        ],
});
signer.signAndExecuteTransactionBlock({ transactionBlock: trx });

This will not require the user to sign twice–the split, Move call, and any other commands you make will be packed into a single programmable transaction block that is signed once and executed atomically.

2 Likes

@shb I am getting the following error:

Dry run failed, could not automatically determine a
 budget: UnusedValueWithoutDrop { result_idx: 0, secondary_idx: 0 } 
(code: -1)
1 Like

Not a Move expert, but this is what I think happens. After the move call, you need to do something with the new object that was minted - that’s what UnusedValueWithoutDrop tells you - you have an object that is not dropped but also not transferred to an address / another object. Likely, you want to transfer it to some address to hold it.

2 Likes