How to build, sign, submit, and simulate transactions in @aptos-labs/ts-sdk. Covers build.simple(), signAndSubmitTransaction(), waitForTransaction(), simulate, sponsored (fee payer), and multi-agent. Triggers on: 'build.simple', 'signAndSubmitTransaction', 'transaction.build', 'waitForTransaction', 'signAsFeePayer', 'SDK transaction', 'sponsored transaction', 'multi-agent transaction'.
78
100%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
Guide building, signing, submitting, and simulating transactions with @aptos-labs/ts-sdk. Use the build → sign → submit → wait pattern; optionally simulate before submit.
aptos.waitForTransaction({ transactionHash }) after submit – do not assume transaction is committed after signAndSubmitTransaction.aptos.transaction.build.simple() for entry function payloads – pass sender and data: { function, functionArguments, typeArguments? }.aptos.transaction.simulate.simple() and check success and vm_status.sender address when building (e.g. account.accountAddress as sender, account as signer).waitForTransaction – submission returns when the tx is accepted, not when it is committed.scriptComposer (removed in v6) – use separate transactions or batch patterns.number for u64/u128/u256 in functionArguments – use bigint where required to avoid precision loss.import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET }));
const MODULE_ADDRESS = "0x...";
// 1. Build
const transaction = await aptos.transaction.build.simple({
sender: account.accountAddress,
data: {
function: `${MODULE_ADDRESS}::counter::increment`,
functionArguments: [],
},
});
// 2. Sign and submit
const pendingTx = await aptos.signAndSubmitTransaction({
signer: account,
transaction,
});
// 3. Wait for commitment
const committedTx = await aptos.waitForTransaction({
transactionHash: pendingTx.hash,
});
if (!committedTx.success) {
throw new Error(`Tx failed: ${committedTx.vm_status}`);
}// With type arguments (e.g. coin type)
const transaction = await aptos.transaction.build.simple({
sender: account.accountAddress,
data: {
function: "0x1::coin::transfer",
typeArguments: ["0x1::aptos_coin::AptosCoin"],
functionArguments: [recipientAddress, amount],
},
});
// Optional: max gas, expiry, etc. (see SDK types for full options)
const transactionWithOptions = await aptos.transaction.build.simple({
sender: account.accountAddress,
data: { function: "...", functionArguments: [] },
options: {
maxGasAmount: 2000n,
gasUnitPrice: 100n,
expireTimestamp: BigInt(Math.floor(Date.now() / 1000) + 600),
},
});const transaction = await aptos.transaction.build.simple({
sender: account.accountAddress,
data: {
function: `${MODULE_ADDRESS}::counter::increment`,
functionArguments: [],
},
});
const [simResult] = await aptos.transaction.simulate.simple({
signerPublicKey: account.publicKey,
transaction,
});
if (!simResult.success) {
throw new Error(`Simulation failed: ${simResult.vm_status}`);
}
console.log("Gas used:", simResult.gas_used);// 1. Build with fee payer
const transaction = await aptos.transaction.build.simple({
sender: sender.accountAddress,
withFeePayer: true,
data: {
function: `${MODULE_ADDRESS}::counter::increment`,
functionArguments: [],
},
});
// 2. Sender signs
const senderAuth = aptos.transaction.sign({
signer: sender,
transaction,
});
// 3. Fee payer signs (different method)
const feePayerAuth = aptos.transaction.signAsFeePayer({
signer: feePayer,
transaction,
});
// 4. Submit with both authenticators
const pendingTx = await aptos.transaction.submit.simple({
transaction,
senderAuthenticator: senderAuth,
feePayerAuthenticator: feePayerAuth,
});
await aptos.waitForTransaction({ transactionHash: pendingTx.hash });const transaction = await aptos.transaction.build.multiAgent({
sender: alice.accountAddress,
secondarySignerAddresses: [bob.accountAddress],
data: {
function: `${MODULE_ADDRESS}::escrow::exchange`,
functionArguments: [itemAddress, amount],
},
});
const aliceAuth = aptos.transaction.sign({ signer: alice, transaction });
const bobAuth = aptos.transaction.sign({ signer: bob, transaction });
const pendingTx = await aptos.transaction.submit.multiAgent({
transaction,
senderAuthenticator: aliceAuth,
additionalSignersAuthenticators: [bobAuth],
});
await aptos.waitForTransaction({ transactionHash: pendingTx.hash });const committed = await aptos.waitForTransaction({
transactionHash: pendingTx.hash,
options: {
timeoutSecs: 60,
checkSuccess: true, // throw if tx failed
},
});const gasProfile = await aptos.gasProfile({
sender: account.accountAddress,
data: {
function: `${MODULE_ADDRESS}::module::function_name`,
functionArguments: [],
},
});
console.log("Gas profile:", gasProfile);| Mistake | Correct approach |
|---|---|
| Not calling waitForTransaction | Always wait and check committedTx.success |
| Using number for large amounts | Use bigint for u64/u128/u256 in functionArguments |
| Wrong signer for submit | Use the Account whose address is the sender (or fee payer / additional signer as appropriate) |
| Assuming scriptComposer exists | Use separate transactions or batch; scriptComposer removed in v6 |
src/api/transaction.ts, src/internal/transactionSubmission.ts, src/internal/transaction.ts919362b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.