Loading...
Loading...
Guides usage of @aptos-labs/ts-sdk for interacting with the Aptos blockchain from TypeScript/JavaScript applications. Covers client setup, account management, transaction building & submission, view functions, event queries, coin/token operations, wallet adapter integration, and error handling. Triggers on: 'typescript sdk', 'ts-sdk', 'aptos sdk', 'aptos client', 'sdk setup', 'interact with contract', 'call aptos', 'aptos javascript', 'frontend integration', 'wallet adapter', 'connect wallet'.
npx skill4agent add iskysun96/aptos-agent-skills use-typescript-sdk@aptos-labs/ts-sdkaptosAptoslib/aptos.tsAptosConfigNetwork.TESTNETaptos.getBalance()getAccountCoinAmountgetAccountAPTAmountwaitForTransactiontransaction.build.simple()signAndSubmitTransaction()VITE_process.envbigintnumberObject<T>functionArguments@aptos-labs/wallet-adapter-reactAptosWalletAdapterProvideruseWallet()npm install @aptos-labs/ts-sdkAptoslib/aptos.tsaptos.view()aptos.transaction.build.simple()aptos.signAndSubmitTransaction()@aptos-labs/wallet-adapter-react// lib/aptos.ts - Singleton client (create once, import everywhere)
import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
function getNetwork(): Network {
const network = import.meta.env.VITE_APP_NETWORK;
switch (network) {
case "mainnet":
return Network.MAINNET;
case "testnet":
return Network.TESTNET;
case "devnet":
return Network.DEVNET;
default:
return Network.TESTNET;
}
}
const config = new AptosConfig({ network: getNetwork() });
export const aptos = new Aptos(config);
export const MODULE_ADDRESS = import.meta.env.VITE_MODULE_ADDRESS;// view-functions/getCount.ts
import { aptos, MODULE_ADDRESS } from "../lib/aptos";
export async function getCount(accountAddress: string): Promise<number> {
const result = await aptos.view({
payload: {
function: `${MODULE_ADDRESS}::counter::get_count`,
functionArguments: [accountAddress]
}
});
return Number(result[0]);
}
// With type arguments
export async function getCoinBalance(accountAddress: string, coinType: string): Promise<bigint> {
const result = await aptos.view({
payload: {
function: "0x1::coin::balance",
typeArguments: [coinType],
functionArguments: [accountAddress]
}
});
return BigInt(result[0] as string);
}
// Multiple return values
// Move: public fun get_listing(addr): (address, u64, bool)
export async function getListing(nftAddress: string): Promise<{ seller: string; price: number; isActive: boolean }> {
const [seller, price, isActive] = await aptos.view({
payload: {
function: `${MODULE_ADDRESS}::marketplace::get_listing`,
functionArguments: [nftAddress]
}
});
return {
seller: seller as string,
price: Number(price),
isActive: isActive as boolean
};
}import { Account, Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
const config = new AptosConfig({ network: Network.TESTNET });
const aptos = new Aptos(config);
// Build transaction
const transaction = await aptos.transaction.build.simple({
sender: account.accountAddress,
data: {
function: `${MODULE_ADDRESS}::counter::increment`,
functionArguments: []
}
});
// Sign and submit
const pendingTx = await aptos.signAndSubmitTransaction({
signer: account,
transaction
});
// ALWAYS wait for confirmation
const committedTx = await aptos.waitForTransaction({
transactionHash: pendingTx.hash
});
console.log("Success:", committedTx.success);// entry-functions/increment.ts
import { InputTransactionData } from "@aptos-labs/wallet-adapter-react";
import { MODULE_ADDRESS } from "../lib/aptos";
export function buildIncrementPayload(): InputTransactionData {
return {
data: {
function: `${MODULE_ADDRESS}::counter::increment`,
functionArguments: [],
},
};
}
// Component usage
import { useWallet } from "@aptos-labs/wallet-adapter-react";
import { aptos } from "../lib/aptos";
import { buildIncrementPayload } from "../entry-functions/increment";
function IncrementButton() {
const { signAndSubmitTransaction } = useWallet();
const handleClick = async () => {
try {
const response = await signAndSubmitTransaction(
buildIncrementPayload(),
);
await aptos.waitForTransaction({
transactionHash: response.hash,
});
} catch (error) {
console.error("Transaction failed:", error);
}
};
return <button onClick={handleClick}>Increment</button>;
}// main.tsx or App.tsx
import { AptosWalletAdapterProvider } from "@aptos-labs/wallet-adapter-react";
import { Network } from "@aptos-labs/ts-sdk";
function App() {
return (
<AptosWalletAdapterProvider
autoConnect={true}
dappConfig={{
network: Network.TESTNET,
}}
onError={(error) => console.error("Wallet error:", error)}
>
<YourApp />
</AptosWalletAdapterProvider>
);
}
// In any child component
import { useWallet } from "@aptos-labs/wallet-adapter-react";
function WalletInfo() {
const { account, connected, connect, disconnect, wallet, wallets } =
useWallet();
if (!connected) {
return (
<div>
{wallets.map((w) => (
<button key={w.name} onClick={() => connect(w.name)}>
Connect {w.name}
</button>
))}
</div>
);
}
return (
<div>
<p>Connected: {account?.address}</p>
<p>Wallet: {wallet?.name}</p>
<button onClick={disconnect}>Disconnect</button>
</div>
);
}import { Account, Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET }));
// 1. Build with fee payer flag
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 signatures
const pendingTx = await aptos.transaction.submit.simple({
transaction,
senderAuthenticator: senderAuth,
feePayerAuthenticator: feePayerAuth
});
await aptos.waitForTransaction({ transactionHash: pendingTx.hash });// 1. Build multi-agent transaction
const transaction = await aptos.transaction.build.multiAgent({
sender: alice.accountAddress,
secondarySignerAddresses: [bob.accountAddress],
data: {
function: `${MODULE_ADDRESS}::escrow::exchange`,
functionArguments: [itemAddress, paymentAmount]
}
});
// 2. Each agent signs
const aliceAuth = aptos.transaction.sign({
signer: alice,
transaction
});
const bobAuth = aptos.transaction.sign({
signer: bob,
transaction
});
// 3. Submit with all signatures
const pendingTx = await aptos.transaction.submit.multiAgent({
transaction,
senderAuthenticator: aliceAuth,
additionalSignersAuthenticators: [bobAuth]
});
await aptos.waitForTransaction({ transactionHash: pendingTx.hash });| Move Type | TypeScript Type | Example |
|---|---|---|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | Use |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | Object address as hex string |
| | Value or |
// Build transaction
const transaction = await aptos.transaction.build.simple({
sender: account.accountAddress,
data: {
function: `${MODULE_ADDRESS}::counter::increment`,
functionArguments: []
}
});
// Simulate to check for errors and estimate gas
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 estimate:", simResult.gas_used);// Profile gas usage of a transaction (useful for optimization)
const gasProfile = await aptos.gasProfile({
sender: account.accountAddress,
data: {
function: `${MODULE_ADDRESS}::module::function_name`,
functionArguments: []
}
});
console.log("Gas profile:", gasProfile);aptos@aptos-labs/ts-sdkwaitForTransactionVITE_MODULE_ADDRESSnumberbigintAptosVITE_PRIVATE_KEYAccount.generate()aptos.signAndSubmitTransactionsignAndSubmitTransactionscriptComposergetAccountCoinAmountgetAccountAPTAmountgetBalance()| Scenario | Check | Action |
|---|---|---|
| Resource not found | | Return default value or null |
| Module not deployed | | Show "contract not deployed" message |
| Function not found | | Check function name and module address |
| Move abort | | Parse abort code, map to user-friendly error |
| Out of gas | | Increase |
| Sequence number error | | Retry after fetching fresh sequence number |
| Network timeout | | Retry with exponential backoff |
| Account does not exist | | Fund account or prompt user to create one |
| Insufficient balance | | Show balance and required amount |
| User rejected in wallet | Wallet-specific rejection error | Show "transaction cancelled" message |
async function submitTransaction(
aptos: Aptos,
signer: Account,
payload: InputGenerateTransactionPayloadData
): Promise<string> {
try {
const transaction = await aptos.transaction.build.simple({
sender: signer.accountAddress,
data: payload
});
const pendingTx = await aptos.signAndSubmitTransaction({
signer,
transaction
});
const committed = await aptos.waitForTransaction({
transactionHash: pendingTx.hash
});
if (!committed.success) {
throw new Error(`Transaction failed: ${committed.vm_status}`);
}
return pendingTx.hash;
} catch (error) {
if (error instanceof Error) {
if (error.message.includes("RESOURCE_NOT_FOUND")) {
throw new Error("Resource does not exist at the specified address");
}
if (error.message.includes("MODULE_NOT_FOUND")) {
throw new Error("Contract is not deployed at the specified address");
}
if (error.message.includes("ABORTED")) {
const match = error.message.match(/code: (\d+)/);
const code = match ? match[1] : "unknown";
throw new Error(`Contract error (code ${code})`);
}
}
throw error;
}
}src/
lib/
aptos.ts # Singleton Aptos client + MODULE_ADDRESS
view-functions/
getCount.ts # One file per view function
getListing.ts
entry-functions/
increment.ts # One file per entry function
createListing.ts
hooks/
useCounter.ts # React hooks wrapping view functions
useListing.ts
components/
WalletProvider.tsx # AptosWalletAdapterProvider wrapper
IncrementButton.tsx # Components calling entry functions// CORRECT (v5.1+)
const balance = await aptos.getBalance({
accountAddress: account.accountAddress
});
// Returns bigint in octas (1 APT = 100_000_000 octas)
// DEPRECATED - do NOT use
// await aptos.getAccountCoinAmount(...)
// await aptos.getAccountAPTAmount(...)toString()const key = new Ed25519PrivateKey("0x...");
key.toString(); // Returns AIP-80 prefixed format, NOT raw hexAccountAddress.fromString()AccountAddress.from()// CORRECT
const addr = AccountAddress.from("0x1"); // Accepts any format
const addr2 = AccountAddress.fromString("0x000000000000000000000000000000000000000000000000000000000000001"); // SHORT format only
// MAY FAIL in v1.32+
// AccountAddress.fromString("0x1") -- too short for SHORT format// Transfer between FA stores directly
await aptos.transferFungibleAssetBetweenStores({
sender: account,
fungibleAssetMetadataAddress: metadataAddr,
senderStoreAddress: fromStore,
recipientStoreAddress: toStore,
amount: 1000n
});const config = new AptosConfig({
network: Network.TESTNET,
clientConfig: { http2: false }
});aptos.abstraction// Check if AA is enabled for an account
const isEnabled = await aptos.abstraction.isAccountAbstractionEnabled({
accountAddress: "0x...",
authenticationFunction: `${MODULE_ADDRESS}::auth::authenticate`
});
// Enable AA on an account
const enableTxn = await aptos.abstraction.enableAccountAbstractionTransaction({
accountAddress: account.accountAddress,
authenticationFunction: `${MODULE_ADDRESS}::auth::authenticate`
});
// Disable AA
const disableTxn = await aptos.abstraction.disableAccountAbstractionTransaction({
accountAddress: account.accountAddress,
authenticationFunction: `${MODULE_ADDRESS}::auth::authenticate`
});
// Use AbstractedAccount for signing with custom auth logic
import { AbstractedAccount } from "@aptos-labs/ts-sdk";references/wallet-adapter.mdreferences/transaction-patterns.mdreferences/type-mappings.md../../../patterns/fullstack/TYPESCRIPT_SDK.mdwrite-contractsdeploy-contractsscaffold-project