Quick Start
Create your first AURA treasury and submit a proposal in under 5 minutes using the TypeScript SDK.
Install
npm install @aura-protocol/sdk-ts @solana/web3.js bn.jsCurrent published version: @aura-protocol/sdk-ts@0.2.13
Connect
import { Connection, Keypair } from "@solana/web3.js";
import { Aura, AURA_PROGRAM_ID } from "@aura-protocol/sdk-ts";
// Load your funded devnet keypair
const keypair = Keypair.fromSecretKey(/* your secret key bytes */);
const aura = new Aura({
rpcUrl: "https://api.devnet.solana.com",
keypair,
// programId defaults to AURA_PROGRAM_ID = EaRoLVwL8EErDUeEMPHJ5QJeLVQZWJMtZcgmFzT9bhHs
});Create a treasury
Aura.treasury.create injects timestamps automatically and applies sensible defaults for unspecified limits.
const { treasury, signature } = await aura.treasury.create({
agentId: "my-agent-1", // unique per owner — used in PDA seed
dailyLimitUsd: 10_000, // USD cents = $100/day
perTxLimitUsd: 1_000, // USD cents = $10/tx
// Optional — defaults shown:
// daytimeHourlyLimitUsd: dailyLimitUsd / 10 → 1_000
// nighttimeHourlyLimitUsd: dailyLimitUsd / 20 → 500
// velocityLimitUsd: dailyLimitUsd / 2 → 5_000
// allowedProtocolBitmap: 31 → all 5 protocols
// maxSlippageBps: 100 → 1%
// maxQuoteAgeSecs: 300 → 5 minutes
// maxCounterpartyRiskScore: 70 → 0–100 scale
// bitcoinManualReviewThresholdUsd: 5_000 → $50
// pendingTransactionTtlSecs: 900 → 15 minutes
});
console.log("Treasury PDA:", treasury.toBase58());
// Seeds: ["treasury", keypair.publicKey, "my-agent-1"]Register a dWallet
Each chain needs its own DwalletRecord before proposals can be approved for that chain.
await aura.dwallet.register({
treasury,
chain: 2, // 0=Solana 1=Bitcoin 2=Ethereum 3=Polygon 4=Arbitrum 5=Optimism
dwalletId: "dwallet-abc123", // from Ika dWallet provisioning
address: "0xYourEthAddress", // native address on the target chain
balanceUsd: 5_000, // USD cents — balance hint
});Propose a transaction
const signature = await aura.treasury.propose({
treasury,
amountUsd: 250, // USD cents = $2.50
chain: 2, // Ethereum
recipient: "0xRecipientAddress",
txType: 0, // 0=Transfer 1=DeFiSwap 2=LendingDeposit 3=NFTPurchase 4=ContractInteraction
// Optional policy telemetry:
// counterpartyRiskScore: 15, // 0–100
// quoteAgeSecs: 60, // seconds since price quote
// expectedOutputUsd: 248, // for slippage check
// actualOutputUsd: 247,
});The proposal goes through evaluate_transaction in aura-policy:
- Scoped pause check
- Budget envelope check
- Per-tx limit:
250 ≤ 1_000✓ - Daily limit:
spent_today + 250 ≤ 10_000✓ - Time window, protocol, slippage, quote freshness, counterparty risk...
- Velocity limit check
If all pass, a PendingTransaction account is created on-chain.
Read treasury state
const account = await aura.treasury.get(treasury);
console.log("Agent ID:", account.agentId);
console.log("Paused:", account.paused);
console.log("Total transactions:", account.totalTransactions.toString());
console.log("Daily limit:", account.policyConfig.dailyLimitUsd.toString());Or derive the PDA and fetch by owner + agentId:
const { treasury: pda, account } = await aura.treasury.getForOwner(
keypair.publicKey,
"my-agent-1",
);Using the Low-Level Client
For full control — all 67 instructions, manual BN values, instruction composition:
import { AuraClient, AURA_PROGRAM_ID, deriveTreasuryAddress } from "@aura-protocol/sdk-ts";
import { Connection } from "@solana/web3.js";
import BN from "bn.js";
const client = new AuraClient({
connection: new Connection("https://api.devnet.solana.com", "confirmed"),
programId: AURA_PROGRAM_ID,
});
// Derive the treasury PDA manually
const [treasury] = deriveTreasuryAddress(owner.publicKey, "my-agent-1");
// Build and send an instruction without broadcasting
const { instruction } = await client.createTreasuryInstruction({
owner: owner.publicKey,
args: { /* full CreateTreasuryArgs with BN values */ },
});
// Compose with other instructions in one transaction
await client.sendInstructions(owner, [instruction, otherInstruction]);Error Handling
Program errors start at code 6000. Use AuraErrorCode and isAuraError:
import { AuraErrorCode, isAuraError } from "@aura-protocol/sdk-ts";
try {
await aura.treasury.propose({ ... });
} catch (err) {
if (isAuraError(err, AuraErrorCode.PendingTransactionExists)) {
console.log("A proposal is already pending — cancel it first");
} else if (isAuraError(err, AuraErrorCode.ExecutionPaused)) {
console.log("Treasury is paused");
}
}Common errors:
| Code | Name | Meaning |
|---|---|---|
| 6004 | PendingTransactionExists | Only one pending proposal allowed at a time |
| 6005 | NoPendingTransaction | No proposal to execute or cancel |
| 6006 | DWalletNotConfigured | No dWallet registered for the target chain |
| 6015 | ConfidentialGuardrailsNotConfigured | Confidential path requires ciphertext accounts |
| 6017 | ExecutionPaused | Treasury is paused |
| 6018 | PendingTransactionExpired | Proposal TTL elapsed |
| 6027 | TimelockNotElapsed | Dangerous config change timelock still active |