From aptos-agent-skills
Builds, signs, submits, and simulates transactions using @aptos-labs/ts-sdk for Aptos blockchain. Covers build.simple(), sponsored transactions, multi-agent, simulation, and waitForTransaction.
npx claudepluginhub aptos-labs/aptos-agent-skills --plugin aptos-agent-skillsThis skill uses the workspace's default tool permissions.
Guide **building, signing, submitting, and simulating** transactions with `@aptos-labs/ts-sdk`. Use the build → sign →
Orchestrates @aptos-labs/ts-sdk integration for Aptos dApps, routing to granular skills for client setup, accounts, transactions, view functions, types, and wallet adapters. For fullstack dApp development.
Signs messages (personal_sign), EIP-712 typed data, transactions via Bankr API /agent/sign endpoint and submits raw transactions via /agent/submit using TypeScript fetch patterns.
Integrates SmoothSend SDK to sponsor gas fees for Aptos dApp users via wallet adapter transactionSubmitter, enabling gasless transactions in React apps.
Share bugs, ideas, or general feedback.
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.ts