How do I merge and split coins on Sui?
November 11, 2026
On Sui each coin is its own object, so you merge and split them with transactions. From the CLI, sui client merge-coin --primary-coin <ID> --coin-to-merge <ID> and sui client split-coin --coin-id <ID> --amounts ... do the job. In code, use the SplitCoins and MergeCoins PTB commands (tx.splitCoins and tx.mergeCoins in TypeScript). Address balances are now live on mainnet, so most apps can skip manual coin handling: tx.coin({ balance }) takes funds from coins and the address balance automatically.
CLI
# See your SUI coins
sui client gas
# Merge one coin into another
sui client merge-coin --primary-coin 0xPRIMARY --coin-to-merge 0xOTHER
# Split specific amounts (in MIST) off a coin
sui client split-coin --coin-id 0xCOIN --amounts 1000000000 500000000
# Or split into N equal coins
sui client split-coin --coin-id 0xCOIN --count 4Both commands take the usual --gas-budget, --gas (choose gas coins) and --dry-run options. For more than two coins, a PTB merges them in one transaction:
sui client ptb --merge-coins @0xPRIMARY "[@0xA, @0xB, @0xC]"
sui client ptb --split-coins gas "[1000, 2000]" --assign parts \
--transfer-objects "[parts.0, parts.1]" @0xRECIPIENTgas refers to the coin paying for gas. Splitting from it is the quickest way to get an exact amount of SUI.
TypeScript (@mysten/sui v2)
import { Transaction } from '@mysten/sui/transactions'
const tx = new Transaction()
// Split two coins off the gas coin and send them to different people
const [a, b] = tx.splitCoins(tx.gas, [1_000_000_000, 2_000_000_000])
tx.transferObjects([a], ALICE)
tx.transferObjects([b], BOB)
// Merge several coins of the same type into one
tx.mergeCoins(tx.object(PRIMARY_COIN), [tx.object(COIN_2), tx.object(COIN_3)])
await client.signAndExecuteTransaction({ signer, transaction: tx })To list coins for an address, call client.listCoins({ owner, coinType }) on SuiGrpcClient.
The easier route: tx.coin()
You usually just need "a Coin<T> worth X". tx.coin() handles the coin selection:
const tx = new Transaction()
tx.transferObjects([tx.coin({ balance: 1_000_000_000n })], RECIPIENT) // 1 SUI
tx.transferObjects(
[tx.coin({ type: '0xPKG::usdc::USDC', balance: 5_000_000n })],
RECIPIENT,
)At build time the SDK uses your address balance if it covers the amount. Otherwise it merges your coins, tops up from the address balance and splits off the exact amount. tx.balance() does the same for functions that take a Balance<T>.
Gas smashing: merging while paying gas
If you give several SUI coins as gas payment (up to 256), Sui merges them into the first one before charging gas, even if the transaction then fails. That's an easy way to clean up dust coins. With address-balance gas you don't need it, because no coin objects are involved.
In Move
use sui::coin::Coin;
use sui::sui::SUI;
public fun pay_exact(c: &mut Coin<SUI>, amount: u64, to: address, ctx: &mut TxContext) {
let part = c.split(amount, ctx); // coin::split
transfer::public_transfer(part, to);
}
public fun combine(c: &mut Coin<SUI>, other: Coin<SUI>) {
c.join(other); // coin::join
}coin::divide_into_n splits a coin into equal parts. The sui::pay module has ready-made entry functions such as split_vec and join_vec.
Gotchas
- Only coins of the same type can merge.
Coin<SUI>andCoin<USDC>stay separate. - The gas coin has restrictions. Any command can borrow it (
&or&mut), but the only way to take it by value isTransferObjects(orcoin::send_funds). If a Move function needs an ownedCoin<SUI>, split one off first. Don't usetx.gasat all in sponsored transactions, because it belongs to the sponsor. - Fragmentation causes contention. Many small coins mean more inputs, and reusing one coin in parallel transactions causes object version errors. Merge periodically or use address balances.
- Merging pays you back. Deleting the merged-away coin objects returns most of their storage fee as a rebate.
Sources
- Coins and Balances, Sui TypeScript SDK
- client_commands.rs (
merge-coin,split-coin), Sui CLI source - Gas Smashing, Sui documentation
- coin.move, Sui framework source