Quickstart: Create Your First Vault
This 15-minute tutorial will guide you through creating your first Aegis vault and executing a transaction with your AI agent.
Prerequisites
- Node.js 18+ installed
- Basic understanding of TypeScript
- A Solana wallet (we'll create one for testing)
- 1-2 SOL on devnet (get from faucet (opens in a new tab))
What You'll Build
By the end of this tutorial, you'll have:
- A funded Aegis vault with spending policies
- An AI agent that can execute transactions
- Understanding of the override flow when transactions are blocked
Step 1: Install the SDK
Create a new project and install dependencies:
mkdir aegis-quickstart
cd aegis-quickstart
npm init -y
npm install @aegis-vaults/sdk @solana/web3.js @coral-xyz/anchor bn.js typescript tsxStep 2: Generate Keypairs
Create a file generate-keys.ts:
import { Keypair } from '@solana/web3.js';
import * as fs from 'fs';
// Generate vault owner keypair
const ownerKeypair = Keypair.generate();
console.log('Vault Owner Public Key:', ownerKeypair.publicKey.toBase58());
console.log('Vault Owner Secret (save this!):', JSON.stringify(Array.from(ownerKeypair.secretKey)));
// Generate AI agent keypair
const agentKeypair = Keypair.generate();
console.log('\nAI Agent Public Key:', agentKeypair.publicKey.toBase58());
console.log('AI Agent Secret (save this!):', JSON.stringify(Array.from(agentKeypair.secretKey)));
// Save to files for convenience
fs.writeFileSync('owner.json', JSON.stringify(Array.from(ownerKeypair.secretKey)));
fs.writeFileSync('agent.json', JSON.stringify(Array.from(agentKeypair.secretKey)));
console.log('\nKeypairs saved to owner.json and agent.json');Run it:
npx tsx generate-keys.tsSave the output! You'll need these keys for the next steps.
Step 3: Fund the Owner Wallet
Use the Solana CLI or web faucet to get devnet SOL:
# Using Solana CLI (if installed)
solana airdrop 2 <OWNER_PUBLIC_KEY> --url devnet
# Or visit: https://faucet.solana.comStep 4: Create a Vault
Create create-vault.ts:
import { AegisClient } from '@aegis-vaults/sdk';
import { Keypair } from '@solana/web3.js';
import * as fs from 'fs';
async function main() {
// Load owner keypair
const ownerSecret = JSON.parse(fs.readFileSync('owner.json', 'utf-8'));
const ownerKeypair = Keypair.fromSecretKey(Uint8Array.from(ownerSecret));
// Load agent public key
const agentSecret = JSON.parse(fs.readFileSync('agent.json', 'utf-8'));
const agentKeypair = Keypair.fromSecretKey(Uint8Array.from(agentSecret));
// Initialize Aegis client
const client = new AegisClient({
cluster: 'devnet',
guardianApiUrl: 'https://aegis-guardian-production.up.railway.app',
});
// Wrap owner keypair in Wallet and set as signer
const { Wallet } = await import('@coral-xyz/anchor');
const ownerWallet = new Wallet(ownerKeypair);
client.setWallet(ownerWallet);
console.log('Creating vault...');
// Create vault with 0.5 SOL daily limit
const result = await client.createVault({
name: 'My First AI Agent Vault',
agentSigner: agentKeypair.publicKey.toBase58(),
dailyLimit: 500_000_000, // 0.5 SOL per day
});
console.log('\nβ
Vault created successfully!');
console.log('Vault Address:', result.vaultAddress);
console.log('Deposit Address:', result.depositAddress);
console.log('Vault Nonce:', result.nonce);
console.log('\nπ Save these values to .env file:');
console.log(`VAULT_ADDRESS=${result.vaultAddress}`);
console.log(`VAULT_NONCE=${result.nonce}`);
console.log(`DEPOSIT_ADDRESS=${result.depositAddress}`);
// Save to .env file
const envContent = `VAULT_ADDRESS=${result.vaultAddress}
VAULT_NONCE=${result.nonce}
DEPOSIT_ADDRESS=${result.depositAddress}
`;
fs.writeFileSync('.env', envContent);
console.log('\nβ
Saved to .env file');
}
main().catch(console.error);Run it:
npx tsx create-vault.tsStep 5: Fund the Vault
Send SOL to the Deposit Address (not the vault address!):
# Using Solana CLI
solana transfer <DEPOSIT_ADDRESS> 1 --url devnet --keypair owner.json
# Or transfer from your wallet manuallyStep 6: Whitelist a Recipient
Create setup-policy.ts:
import { AegisClient } from '@aegis-vaults/sdk';
import { Keypair, PublicKey } from '@solana/web3.js';
import * as fs from 'fs';
async function main() {
// Load owner keypair
const ownerSecret = JSON.parse(fs.readFileSync('owner.json', 'utf-8'));
const ownerKeypair = Keypair.fromSecretKey(Uint8Array.from(ownerSecret));
// Load vault info
const vaultAddress = process.env.VAULT_ADDRESS || '';
const vaultNonce = process.env.VAULT_NONCE || '';
// Initialize client
const client = new AegisClient({
cluster: 'devnet',
guardianApiUrl: 'https://aegis-guardian-production.up.railway.app',
});
// Wrap keypair in Wallet before passing to client
const { Wallet } = await import('@coral-xyz/anchor');
const ownerWallet = new Wallet(ownerKeypair);
client.setWallet(ownerWallet);
// Example recipient address (replace with real address)
const recipient = new PublicKey('7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU');
console.log('Adding recipient to whitelist...');
await client.addToWhitelist(vaultAddress, vaultNonce, recipient.toBase58());
console.log('β
Recipient added to whitelist:', recipient.toBase58());
// Check vault status
const vault = await client.getVault(vaultAddress);
console.log('\nπ Vault Status:');
console.log('Daily Limit:', vault.dailyLimit.toString(), 'lamports');
console.log('Whitelist Count:', vault.whitelistCount);
console.log('Paused:', vault.paused);
}
main().catch(console.error);Run it:
npx tsx setup-policy.tsStep 7: Execute an Agent Transaction
Create agent-transfer.ts:
import { AegisClient } from '@aegis-vaults/sdk';
import { Keypair, PublicKey } from '@solana/web3.js';
import * as fs from 'fs';
async function main() {
// Load agent keypair
const agentSecret = JSON.parse(fs.readFileSync('agent.json', 'utf-8'));
const agentKeypair = Keypair.fromSecretKey(Uint8Array.from(agentSecret));
// Load vault info
const vaultAddress = process.env.VAULT_ADDRESS || '';
const vaultNonce = process.env.VAULT_NONCE || '';
// Initialize client with agent wallet
const client = new AegisClient({
cluster: 'devnet',
guardianApiUrl: 'https://aegis-guardian-production.up.railway.app',
autoRequestOverride: true, // Auto-notify Guardian on blocked tx
});
// Wrap agent keypair in Wallet before passing to client
const { Wallet } = await import('@coral-xyz/anchor');
const agentWallet = new Wallet(agentKeypair);
client.setWallet(agentWallet);
// Recipient (must be whitelisted!)
const recipient = new PublicKey('7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU');
console.log('Executing agent transaction...');
console.log('From Vault:', vaultAddress);
console.log('To:', recipient.toBase58());
console.log('Amount: 0.01 SOL\n');
try {
const signature = await client.executeAgent({
vault: vaultAddress,
destination: recipient.toBase58(),
amount: 10_000_000, // 0.01 SOL
vaultNonce: vaultNonce,
purpose: 'Test payment from AI agent',
});
console.log('β
Transaction successful!');
console.log('Signature:', signature);
console.log('View on Explorer:', `https://explorer.solana.com/tx/${signature}?cluster=devnet`);
// Check updated vault status
const vault = await client.getVault(vaultAddress);
console.log('\nπ Vault Status After Transaction:');
console.log('Spent Today:', vault.spentToday.toString(), 'lamports');
const balance = await client.getVaultBalance(vaultAddress);
console.log('Remaining Balance:', (balance / 1e9).toFixed(4), 'SOL');
} catch (error: any) {
if (error.overrideRequested) {
console.log('β³ Transaction blocked by policy');
console.log('π± Override requested. Vault owner will receive notification.');
console.log('π Blink URL:', error.blinkUrl);
console.log('\nπ‘ Vault owner can approve by clicking the Blink URL');
} else {
console.error('β Transaction failed:', error.message);
}
}
}
main().catch(console.error);Run it:
npx tsx agent-transfer.tsStep 8: Test the Override Flow
Now let's test what happens when a transaction is blocked. Try sending to a non-whitelisted address:
// In agent-transfer.ts, change the recipient to a new address:
const recipient = Keypair.generate().publicKey; // NOT whitelisted!Run again:
npx tsx agent-transfer.tsYou should see:
β³ Transaction blocked by policy
π± Override requested. Vault owner will receive notification.
π Blink URL: https://aegis-guardian-production.up.railway.app/api/actions/...The vault owner would receive this Blink URL via email, Telegram, Discord, or webhook, and can approve it in their wallet.
What's Happening Behind the Scenes?
When you execute a transaction:
- SDK signs transaction with agent keypair
- Aegis Protocol (on-chain) checks:
- Is agent signer authorized?
- Is destination whitelisted?
- Would this exceed daily limit?
- Is vault paused?
- If PASSES: Transaction executes, SOL transfers, fees collected
- If BLOCKED:
- SDK notifies Guardian API
- Guardian generates Blink URL
- Guardian sends multi-channel notifications
- Owner approves via Blink
- Transaction executes
Congratulations!
You've successfully:
- β Created an Aegis vault with spending policies
- β Funded the vault and configured whitelist
- β Executed agent transactions within policy
- β Tested the override flow for blocked transactions
Next Steps
π€ AI Framework Integration
Add Aegis to your OpenAI or LangChain agent View Integrations β
π SDK API Reference
Explore all available methods View SDK Docs β
π Security Best Practices
Learn how to secure your vaults Security Guide β
π§ͺ Build Tutorials
Build a trading bot or DeFi agent View Tutorials β
Troubleshooting
"Insufficient balance" error
Make sure you sent SOL to the Deposit Address, not the Vault Address.
# Check balance
solana balance <DEPOSIT_ADDRESS> --url devnet"Not whitelisted" error
The destination address must be added to the whitelist first:
npx tsx setup-policy.ts"Unauthorized signer" error
Make sure you're using the correct agent keypair that matches the agentSigner set during vault creation.
Transaction timeout
Devnet can be slow. If a transaction times out but you see the signature, check the explorer - it likely succeeded.