@axonfi/sdk 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -10
- package/dist/index.cjs +77 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -1
- package/dist/index.d.ts +61 -1
- package/dist/index.js +75 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,23 +24,109 @@ Your agents pay. You stay in control.
|
|
|
24
24
|
npm install @axonfi/sdk
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
##
|
|
27
|
+
## Setup
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
There are two ways to set up an Axon vault: through the **dashboard** (UI) or entirely through the **SDK** (programmatic). Both produce the same on-chain result.
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
### Option A: Dashboard Setup
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
1. Go to [app.axonfi.xyz](https://app.axonfi.xyz), connect your wallet, deploy a vault
|
|
34
|
+
2. Fund the vault — send USDC, ETH, or any ERC-20 to the vault address
|
|
35
|
+
3. Register a bot — generate a keypair or bring your own key
|
|
36
|
+
4. Configure policies — per-tx caps, daily limits, AI threshold
|
|
37
|
+
5. Give the bot key to your agent
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
- **Generate a new keypair** (recommended) — the dashboard creates a key and downloads an encrypted keystore JSON file. You set the passphrase.
|
|
37
|
-
- **Bring your own key** — paste an existing public key if you manage keys externally.
|
|
39
|
+
### Option B: Full SDK Setup (Programmatic)
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
Everything can be done from code — no dashboard needed. An agent can bootstrap its own vault end-to-end.
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
```typescript
|
|
44
|
+
import {
|
|
45
|
+
AxonClient, deployVault, addBot, deposit,
|
|
46
|
+
createAxonPublicClient, createAxonWalletClient,
|
|
47
|
+
NATIVE_ETH, USDC, WINDOW, Chain,
|
|
48
|
+
} from '@axonfi/sdk';
|
|
49
|
+
import { parseUnits } from 'viem';
|
|
50
|
+
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
51
|
+
|
|
52
|
+
// ── 1. Owner wallet (funded with ETH for gas) ─────────────────────
|
|
53
|
+
const ownerKey = '0x...'; // or generate: generatePrivateKey()
|
|
54
|
+
const chainId = Chain.BaseSepolia;
|
|
55
|
+
const ownerWallet = createAxonWalletClient(ownerKey, chainId);
|
|
56
|
+
const publicClient = createAxonPublicClient(chainId, 'https://sepolia.base.org');
|
|
57
|
+
|
|
58
|
+
// ── 2. Deploy vault (on-chain tx, ~0.001 ETH gas) ─────────────────
|
|
59
|
+
const FACTORY = '0x...'; // AxonVaultFactory address for your chain
|
|
60
|
+
const vaultAddress = await deployVault(ownerWallet, publicClient, FACTORY);
|
|
61
|
+
console.log('Vault deployed:', vaultAddress);
|
|
62
|
+
|
|
63
|
+
// ── 3. Generate a bot keypair ──────────────────────────────────────
|
|
64
|
+
const botKey = generatePrivateKey();
|
|
65
|
+
const botAddress = privateKeyToAccount(botKey).address;
|
|
66
|
+
|
|
67
|
+
// ── 4. Accept Terms of Service (wallet signature, no gas) ─────────
|
|
68
|
+
const axon = new AxonClient({ vaultAddress, chainId, botPrivateKey: botKey });
|
|
69
|
+
await axon.acceptTos(ownerWallet, ownerWallet.account!.address);
|
|
70
|
+
|
|
71
|
+
// ── 5. Register the bot on the vault (on-chain tx, ~0.0005 ETH gas)
|
|
72
|
+
await addBot(ownerWallet, publicClient, vaultAddress, botAddress, {
|
|
73
|
+
maxPerTxAmount: parseUnits('100', 6), // $100 hard cap per tx
|
|
74
|
+
maxRebalanceAmount: 0n, // no rebalance cap
|
|
75
|
+
spendingLimits: [{
|
|
76
|
+
amount: parseUnits('1000', 6), // $1,000/day rolling limit
|
|
77
|
+
maxCount: 0n, // no tx count limit
|
|
78
|
+
windowSeconds: WINDOW.ONE_DAY,
|
|
79
|
+
}],
|
|
80
|
+
aiTriggerThreshold: parseUnits('50', 6), // AI scan above $50
|
|
81
|
+
requireAiVerification: false,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// ── 6. Deposit funds (on-chain tx, ~0.0005 ETH gas) ───────────────
|
|
85
|
+
// Option A: Deposit ETH (vault accepts native ETH directly)
|
|
86
|
+
await deposit(ownerWallet, publicClient, vaultAddress,
|
|
87
|
+
NATIVE_ETH, parseUnits('0.1', 18));
|
|
88
|
+
|
|
89
|
+
// Option B: Deposit USDC (SDK handles approve + deposit)
|
|
90
|
+
await deposit(ownerWallet, publicClient, vaultAddress,
|
|
91
|
+
USDC[chainId], parseUnits('500', 6));
|
|
92
|
+
|
|
93
|
+
// ── 7. Bot is ready — gasless from here ────────────────────────────
|
|
94
|
+
// Save botKey securely. The bot never needs ETH.
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### What Needs Gas vs. What's Gasless
|
|
98
|
+
|
|
99
|
+
| Step | Who pays gas | Notes |
|
|
100
|
+
|------|-------------|-------|
|
|
101
|
+
| Deploy vault | Owner | ~0.001 ETH. One-time. |
|
|
102
|
+
| Accept ToS | Owner | Wallet signature only (no gas). |
|
|
103
|
+
| Register bot | Owner | ~0.0005 ETH. One per bot. |
|
|
104
|
+
| Configure bot | Owner | ~0.0003 ETH. Only when changing limits. |
|
|
105
|
+
| Deposit ETH | Depositor | Anyone can deposit. ETH sent directly. |
|
|
106
|
+
| Deposit ERC-20 | Depositor | Anyone can deposit. SDK handles approve + deposit. |
|
|
107
|
+
| **Pay** | **Free (relayer)** | **Bot signs EIP-712 intent. Axon pays gas.** |
|
|
108
|
+
| **Execute (DeFi)** | **Free (relayer)** | **Bot signs intent. Axon pays gas.** |
|
|
109
|
+
| **Swap (rebalance)** | **Free (relayer)** | **Bot signs intent. Axon pays gas.** |
|
|
110
|
+
| Pause/unpause | Owner | ~0.0002 ETH. Emergency only. |
|
|
111
|
+
| Withdraw | Owner | ~0.0003 ETH. Owner-only. |
|
|
112
|
+
|
|
113
|
+
**The key insight:** Setup operations (deploy, add bot, deposit) require gas from the owner. Once setup is complete, all bot operations (payments, DeFi, swaps) are gasless — the bot never needs ETH. The relayer pays all execution gas.
|
|
114
|
+
|
|
115
|
+
### Depositing ETH
|
|
116
|
+
|
|
117
|
+
Vaults accept native ETH directly — no wrapping needed. You can start a vault with only ETH:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// Deploy vault + deposit ETH — no USDC needed
|
|
121
|
+
const vault = await deployVault(ownerWallet, publicClient, factory);
|
|
122
|
+
await addBot(ownerWallet, publicClient, vault, botAddress, config);
|
|
123
|
+
await deposit(ownerWallet, publicClient, vault, NATIVE_ETH, parseUnits('0.5', 18));
|
|
124
|
+
|
|
125
|
+
// Bot can now pay in any token — the relayer swaps ETH → USDC automatically
|
|
126
|
+
await axon.pay({ to: '0x...', token: 'USDC', amount: 10 });
|
|
127
|
+
```
|
|
42
128
|
|
|
43
|
-
|
|
129
|
+
When a bot pays in a token the vault doesn't hold directly (e.g., USDC when the vault only has ETH), the relayer automatically routes through a swap. The bot doesn't need to know or care what tokens are in the vault.
|
|
44
130
|
|
|
45
131
|
## Quick Start
|
|
46
132
|
|
package/dist/index.cjs
CHANGED
|
@@ -2546,8 +2546,6 @@ var AxonVaultFactoryAbi = [
|
|
|
2546
2546
|
"inputs": []
|
|
2547
2547
|
}
|
|
2548
2548
|
];
|
|
2549
|
-
|
|
2550
|
-
// src/vault.ts
|
|
2551
2549
|
function getChain(chainId) {
|
|
2552
2550
|
switch (chainId) {
|
|
2553
2551
|
case 8453:
|
|
@@ -2751,6 +2749,79 @@ async function deployVault(walletClient, publicClient, factoryAddress) {
|
|
|
2751
2749
|
}
|
|
2752
2750
|
throw new Error("VaultDeployed event not found in transaction receipt");
|
|
2753
2751
|
}
|
|
2752
|
+
async function addBot(walletClient, publicClient, vaultAddress, botAddress, config) {
|
|
2753
|
+
if (!walletClient.account) {
|
|
2754
|
+
throw new Error("walletClient has no account attached");
|
|
2755
|
+
}
|
|
2756
|
+
const hash = await walletClient.writeContract({
|
|
2757
|
+
address: vaultAddress,
|
|
2758
|
+
abi: AxonVaultAbi,
|
|
2759
|
+
functionName: "addBot",
|
|
2760
|
+
args: [botAddress, config],
|
|
2761
|
+
account: walletClient.account,
|
|
2762
|
+
chain: walletClient.chain ?? null
|
|
2763
|
+
});
|
|
2764
|
+
await publicClient.waitForTransactionReceipt({ hash });
|
|
2765
|
+
return hash;
|
|
2766
|
+
}
|
|
2767
|
+
async function updateBotConfig(walletClient, publicClient, vaultAddress, botAddress, config) {
|
|
2768
|
+
if (!walletClient.account) {
|
|
2769
|
+
throw new Error("walletClient has no account attached");
|
|
2770
|
+
}
|
|
2771
|
+
const hash = await walletClient.writeContract({
|
|
2772
|
+
address: vaultAddress,
|
|
2773
|
+
abi: AxonVaultAbi,
|
|
2774
|
+
functionName: "updateBotConfig",
|
|
2775
|
+
args: [botAddress, config],
|
|
2776
|
+
account: walletClient.account,
|
|
2777
|
+
chain: walletClient.chain ?? null
|
|
2778
|
+
});
|
|
2779
|
+
await publicClient.waitForTransactionReceipt({ hash });
|
|
2780
|
+
return hash;
|
|
2781
|
+
}
|
|
2782
|
+
async function removeBot(walletClient, publicClient, vaultAddress, botAddress) {
|
|
2783
|
+
if (!walletClient.account) {
|
|
2784
|
+
throw new Error("walletClient has no account attached");
|
|
2785
|
+
}
|
|
2786
|
+
const hash = await walletClient.writeContract({
|
|
2787
|
+
address: vaultAddress,
|
|
2788
|
+
abi: AxonVaultAbi,
|
|
2789
|
+
functionName: "removeBot",
|
|
2790
|
+
args: [botAddress],
|
|
2791
|
+
account: walletClient.account,
|
|
2792
|
+
chain: walletClient.chain ?? null
|
|
2793
|
+
});
|
|
2794
|
+
await publicClient.waitForTransactionReceipt({ hash });
|
|
2795
|
+
return hash;
|
|
2796
|
+
}
|
|
2797
|
+
async function deposit(walletClient, publicClient, vaultAddress, token, amount, ref = "0x0000000000000000000000000000000000000000000000000000000000000000") {
|
|
2798
|
+
if (!walletClient.account) {
|
|
2799
|
+
throw new Error("walletClient has no account attached");
|
|
2800
|
+
}
|
|
2801
|
+
const isEth = token.toLowerCase() === NATIVE_ETH.toLowerCase();
|
|
2802
|
+
if (!isEth) {
|
|
2803
|
+
const approveTx = await walletClient.writeContract({
|
|
2804
|
+
address: token,
|
|
2805
|
+
abi: viem.erc20Abi,
|
|
2806
|
+
functionName: "approve",
|
|
2807
|
+
args: [vaultAddress, amount],
|
|
2808
|
+
account: walletClient.account,
|
|
2809
|
+
chain: walletClient.chain ?? null
|
|
2810
|
+
});
|
|
2811
|
+
await publicClient.waitForTransactionReceipt({ hash: approveTx });
|
|
2812
|
+
}
|
|
2813
|
+
const hash = await walletClient.writeContract({
|
|
2814
|
+
address: vaultAddress,
|
|
2815
|
+
abi: AxonVaultAbi,
|
|
2816
|
+
functionName: "deposit",
|
|
2817
|
+
args: [token, amount, ref],
|
|
2818
|
+
account: walletClient.account,
|
|
2819
|
+
chain: walletClient.chain ?? null,
|
|
2820
|
+
...isEth ? { value: amount } : {}
|
|
2821
|
+
});
|
|
2822
|
+
await publicClient.waitForTransactionReceipt({ hash });
|
|
2823
|
+
return hash;
|
|
2824
|
+
}
|
|
2754
2825
|
|
|
2755
2826
|
// src/tokens.ts
|
|
2756
2827
|
var Token = /* @__PURE__ */ ((Token2) => {
|
|
@@ -4402,10 +4473,12 @@ exports.USDC_EIP712_DOMAIN = USDC_EIP712_DOMAIN;
|
|
|
4402
4473
|
exports.WINDOW = WINDOW;
|
|
4403
4474
|
exports.WITNESS_TYPE_STRING = WITNESS_TYPE_STRING;
|
|
4404
4475
|
exports.X402_PROXY_ADDRESS = X402_PROXY_ADDRESS;
|
|
4476
|
+
exports.addBot = addBot;
|
|
4405
4477
|
exports.createAxonPublicClient = createAxonPublicClient;
|
|
4406
4478
|
exports.createAxonWalletClient = createAxonWalletClient;
|
|
4407
4479
|
exports.decryptKeystore = decryptKeystore;
|
|
4408
4480
|
exports.deployVault = deployVault;
|
|
4481
|
+
exports.deposit = deposit;
|
|
4409
4482
|
exports.encodeRef = encodeRef;
|
|
4410
4483
|
exports.encryptKeystore = encryptKeystore;
|
|
4411
4484
|
exports.extractX402Metadata = extractX402Metadata;
|
|
@@ -4432,6 +4505,7 @@ exports.parseChainId = parseChainId;
|
|
|
4432
4505
|
exports.parsePaymentRequired = parsePaymentRequired;
|
|
4433
4506
|
exports.randomNonce = randomNonce;
|
|
4434
4507
|
exports.randomPermit2Nonce = randomPermit2Nonce;
|
|
4508
|
+
exports.removeBot = removeBot;
|
|
4435
4509
|
exports.resolveToken = resolveToken;
|
|
4436
4510
|
exports.resolveTokenDecimals = resolveTokenDecimals;
|
|
4437
4511
|
exports.signExecuteIntent = signExecuteIntent;
|
|
@@ -4439,5 +4513,6 @@ exports.signPayment = signPayment;
|
|
|
4439
4513
|
exports.signPermit2WitnessTransfer = signPermit2WitnessTransfer;
|
|
4440
4514
|
exports.signSwapIntent = signSwapIntent;
|
|
4441
4515
|
exports.signTransferWithAuthorization = signTransferWithAuthorization;
|
|
4516
|
+
exports.updateBotConfig = updateBotConfig;
|
|
4442
4517
|
//# sourceMappingURL=index.cjs.map
|
|
4443
4518
|
//# sourceMappingURL=index.cjs.map
|