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).
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"));
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"));
@shb Thank you for the response. Two follow-up questions:
- 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?
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.
@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)
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.
To perform this operation efficiently, you can use Programmable Transaction Blocks (PTBs) to split and transfer a portion of a gas coin. Here’s a concise explanation:
- Split the Coin: Use
splitCoins
to isolate the specific value you want to send. - Transfer the Coin: Use
transferObjects
to send the split coin to the desired address.
Here’s a sample code snippet from the Sui Documentation:
const [coin] = txb.splitCoins(txb.gas, [txb.pure(100)]);
txb.transferObjects([coin], txb.pure("0xSomeSuiAddress"));
In this example, splitCoins
splits off 100 units of the gas coin, and transferObjects
transfers it to the specified address. This method is efficient for managing and transferring digital assets, including NFTs
. For more details, check the “Building Programmable Transaction Blocks” section in the Sui Documentation.