@usesigil/kit 0.8.1 → 0.11.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.
Files changed (109) hide show
  1. package/README.md +350 -164
  2. package/dist/alt-config.d.ts +4 -2
  3. package/dist/alt-config.d.ts.map +1 -1
  4. package/dist/alt-config.js +4 -2
  5. package/dist/alt-config.js.map +1 -1
  6. package/dist/alt-loader.d.ts.map +1 -1
  7. package/dist/alt-loader.js +2 -1
  8. package/dist/alt-loader.js.map +1 -1
  9. package/dist/balance-tracker.d.ts.map +1 -1
  10. package/dist/balance-tracker.js +2 -1
  11. package/dist/balance-tracker.js.map +1 -1
  12. package/dist/create-vault.d.ts +40 -3
  13. package/dist/create-vault.d.ts.map +1 -1
  14. package/dist/create-vault.js +52 -18
  15. package/dist/create-vault.js.map +1 -1
  16. package/dist/dashboard/discover.d.ts.map +1 -1
  17. package/dist/dashboard/discover.js +2 -1
  18. package/dist/dashboard/discover.js.map +1 -1
  19. package/dist/dashboard/from-json.d.ts +1 -0
  20. package/dist/dashboard/from-json.d.ts.map +1 -1
  21. package/dist/dashboard/from-json.js +3 -1
  22. package/dist/dashboard/from-json.js.map +1 -1
  23. package/dist/dashboard/mutations.d.ts.map +1 -1
  24. package/dist/dashboard/mutations.js +2 -1
  25. package/dist/dashboard/mutations.js.map +1 -1
  26. package/dist/dashboard/reads.d.ts.map +1 -1
  27. package/dist/dashboard/reads.js +5 -4
  28. package/dist/dashboard/reads.js.map +1 -1
  29. package/dist/errors/codes.d.ts +8 -2
  30. package/dist/errors/codes.d.ts.map +1 -1
  31. package/dist/errors/codes.js +6 -0
  32. package/dist/errors/codes.js.map +1 -1
  33. package/dist/errors/context.d.ts +17 -1
  34. package/dist/errors/context.d.ts.map +1 -1
  35. package/dist/errors/public.d.ts +24 -0
  36. package/dist/errors/public.d.ts.map +1 -0
  37. package/dist/errors/public.js +30 -0
  38. package/dist/errors/public.js.map +1 -0
  39. package/dist/errors/walk.d.ts.map +1 -1
  40. package/dist/errors/walk.js +2 -1
  41. package/dist/errors/walk.js.map +1 -1
  42. package/dist/helpers/ata.d.ts +73 -0
  43. package/dist/helpers/ata.d.ts.map +1 -0
  44. package/dist/helpers/ata.js +107 -0
  45. package/dist/helpers/ata.js.map +1 -0
  46. package/dist/helpers/parse-usd.d.ts +43 -0
  47. package/dist/helpers/parse-usd.d.ts.map +1 -0
  48. package/dist/helpers/parse-usd.js +81 -0
  49. package/dist/helpers/parse-usd.js.map +1 -0
  50. package/dist/helpers/validate-cap-aggregate.d.ts +41 -0
  51. package/dist/helpers/validate-cap-aggregate.d.ts.map +1 -0
  52. package/dist/helpers/validate-cap-aggregate.js +61 -0
  53. package/dist/helpers/validate-cap-aggregate.js.map +1 -0
  54. package/dist/hooks.d.ts +114 -0
  55. package/dist/hooks.d.ts.map +1 -0
  56. package/dist/hooks.js +118 -0
  57. package/dist/hooks.js.map +1 -0
  58. package/dist/index.d.ts +17 -4
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +42 -17
  61. package/dist/index.js.map +1 -1
  62. package/dist/logger.d.ts +77 -0
  63. package/dist/logger.d.ts.map +1 -0
  64. package/dist/logger.js +153 -0
  65. package/dist/logger.js.map +1 -0
  66. package/dist/plugin.d.ts +110 -0
  67. package/dist/plugin.d.ts.map +1 -0
  68. package/dist/plugin.js +119 -0
  69. package/dist/plugin.js.map +1 -0
  70. package/dist/presets.d.ts +73 -6
  71. package/dist/presets.d.ts.map +1 -1
  72. package/dist/presets.js +75 -6
  73. package/dist/presets.js.map +1 -1
  74. package/dist/priority-fees.d.ts.map +1 -1
  75. package/dist/priority-fees.js +3 -2
  76. package/dist/priority-fees.js.map +1 -1
  77. package/dist/react/index.d.ts +69 -0
  78. package/dist/react/index.d.ts.map +1 -0
  79. package/dist/react/index.js +118 -0
  80. package/dist/react/index.js.map +1 -0
  81. package/dist/seal.d.ts +113 -15
  82. package/dist/seal.d.ts.map +1 -1
  83. package/dist/seal.js +269 -10
  84. package/dist/seal.js.map +1 -1
  85. package/dist/shield.d.ts.map +1 -1
  86. package/dist/shield.js +8 -7
  87. package/dist/shield.js.map +1 -1
  88. package/dist/sigil.d.ts +187 -0
  89. package/dist/sigil.d.ts.map +1 -0
  90. package/dist/sigil.js +194 -0
  91. package/dist/sigil.js.map +1 -0
  92. package/dist/tee/verify.d.ts.map +1 -1
  93. package/dist/tee/verify.js +6 -5
  94. package/dist/tee/verify.js.map +1 -1
  95. package/dist/transaction-executor.d.ts.map +1 -1
  96. package/dist/transaction-executor.js +3 -2
  97. package/dist/transaction-executor.js.map +1 -1
  98. package/dist/types.d.ts +3 -31
  99. package/dist/types.d.ts.map +1 -1
  100. package/dist/types.js +45 -106
  101. package/dist/types.js.map +1 -1
  102. package/dist/vault-handle.d.ts +123 -0
  103. package/dist/vault-handle.d.ts.map +1 -0
  104. package/dist/vault-handle.js +136 -0
  105. package/dist/vault-handle.js.map +1 -0
  106. package/dist/x402/shielded-fetch.d.ts.map +1 -1
  107. package/dist/x402/shielded-fetch.js +7 -4
  108. package/dist/x402/shielded-fetch.js.map +1 -1
  109. package/package.json +21 -3
package/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # @usesigil/kit
2
2
 
3
- Kit-native TypeScript SDK for Sigil — on-chain spending limits and permission policies for AI agent wallets on Solana.
3
+ Kit-native TypeScript SDK for **Sigil** — on-chain spending limits, permission policies, and audit trails for AI-agent wallets on Solana.
4
4
 
5
- Sigil wraps arbitrary DeFi instructions with security guardrails. Your agents trade through Jupiter, Flash Trade, Drift, or any Solana protocol while vault policies enforce spending caps, permission bitmasks, and protocol allowlists.
5
+ > **Sigil is a security wrapper, not a DeFi SDK.** Your agents keep using Jupiter, Flash Trade, Drift, or any Solana protocol. Sigil wraps the instructions they produce with a validate-and-authorize gate, enforces the policies the vault owner configured, and records the outcome — all without touching the underlying DeFi logic.
6
+
7
+ ---
6
8
 
7
9
  ## Install
8
10
 
@@ -12,243 +14,427 @@ npm install @usesigil/kit @solana/kit
12
14
 
13
15
  `@solana/kit ^6.2.0` is a peer dependency. Node >= 18.
14
16
 
17
+ ---
18
+
19
+ ## Mental model
20
+
21
+ Sigil separates **authority** (owner) from **execution** (agents), enforced at the Solana transaction boundary rather than only in application code.
22
+
23
+ ```
24
+ ┌──────────────────────────────────────────────────────────────────┐
25
+ │ OWNER (human or DAO) │
26
+ │ - Creates vault, sets policy (caps / timelock / allowlist) │
27
+ │ - Registers agent signing keys │
28
+ │ - Withdraws funds, freezes vault, revokes agents │
29
+ │ - Cannot be impersonated by any agent │
30
+ └──────────────────────────┬───────────────────────────────────────┘
31
+ │ owner-signed transactions
32
+
33
+ ┌──────────────────────────────────────────────────────────────────┐
34
+ │ SIGIL ON-CHAIN PROGRAM │
35
+ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────────────┐ │
36
+ │ │ AgentVault │ │ PolicyConfig │ │ SpendTracker │ │
37
+ │ │ (funds) │ │ (limits) │ │ (rolling 24 h) │ │
38
+ │ └──────────────┘ └──────────────┘ └─────────────────────┘ │
39
+ │ │
40
+ │ Every spending tx is `[validate, <DeFi ix>, finalize]`. │
41
+ │ The sandwich cannot be decomposed — all succeed or all revert. │
42
+ └──────────────────────────┬───────────────────────────────────────┘
43
+ │ validated tx
44
+
45
+ ┌──────────────────────────────────────────────────────────────────┐
46
+ │ DeFi protocols (Jupiter, Flash Trade, Drift, …) │
47
+ │ Sigil does not touch this layer — no protocol SDK needed. │
48
+ └──────────────────────────────────────────────────────────────────┘
49
+ ```
50
+
51
+ Nothing an agent does can bypass the on-chain gate. If the validate instruction rejects — cap exceeded, protocol not allowed, agent paused — the entire transaction reverts before any funds move.
52
+
53
+ ---
54
+
15
55
  ## Quickstart
16
56
 
17
- ```typescript
57
+ Provision a vault and execute your first agent-authorized swap:
58
+
59
+ ```ts
18
60
  import {
19
- SigilClient,
20
61
  createAndSendVault,
21
- ActionType,
22
- toAgentError,
23
- formatUsd,
24
- USDC_MINT_DEVNET,
62
+ SigilClient,
63
+ SAFETY_PRESETS,
64
+ parseUsd,
65
+ createConsoleLogger,
25
66
  } from "@usesigil/kit";
26
- import { address, createSolanaRpc } from "@solana/kit";
27
67
 
28
- // 1. Create a vault (owner operation — run once)
29
- const rpc = createSolanaRpc("https://api.devnet.solana.com");
30
- const vault = await createAndSendVault({
31
- rpc,
68
+ // 1. Owner provisions the vault on devnet.
69
+ const { vaultAddress } = await createAndSendVault({
70
+ rpc, // Rpc<SolanaRpcApi> from @solana/kit
32
71
  network: "devnet",
33
- owner, // TransactionSigner (vault authority)
34
- agent, // TransactionSigner (AI agent key)
35
- dailySpendingCapUsd: 500_000_000n, // $500 in USDC base units
72
+ owner: ownerSigner, // TransactionSigner
73
+ agent: agentSigner, // TransactionSigner separate key from owner
74
+ // Required safety posture (v0.9.0 — no silent defaults):
75
+ ...SAFETY_PRESETS.development,
36
76
  });
37
- console.log(`Vault created: ${vault.vaultAddress}`);
38
77
 
39
- // 2. Wrap a Jupiter swap (agent operation per trade)
40
- const client = new SigilClient({
78
+ // 2. Agent opens an async client with genesis-hash verification.
79
+ const client = await SigilClient.create({
41
80
  rpc,
42
- vault: vault.vaultAddress,
43
- agent,
81
+ vault: vaultAddress,
82
+ agent: agentSigner,
44
83
  network: "devnet",
84
+ logger: createConsoleLogger(), // opt in to structured warnings
45
85
  });
46
86
 
47
- const jupiterInstructions = /* from Jupiter /swap-instructions API */;
87
+ // 3. Wrap arbitrary DeFi instructions from Jupiter, SAK, MCP, etc.
88
+ const jupiterInstructions = await buildJupiterSwap(/* your call */);
48
89
  const { signature } = await client.executeAndConfirm(jupiterInstructions, {
49
90
  tokenMint: USDC_MINT_DEVNET,
50
- amount: 100_000_000n, // $100 USDC
51
- actionType: ActionType.Swap,
52
- protocolAltAddresses: jupiterResponse.addressLookupTableAddresses,
91
+ amount: parseUsd("$10"), // strict parser → 10_000_000n base units
53
92
  });
54
-
55
- // 3. Check P&L
56
- const pnl = await client.getPnL();
57
- console.log(`P&L: ${formatUsd(pnl.pnl)}`);
58
93
  ```
59
94
 
60
- See [`examples/jupiter-swap.ts`](./examples/jupiter-swap.ts) for a complete, runnable example with Jupiter API calls, instruction parsing, ALT extraction, and error handling.
95
+ The agent's signing key is never enough on its own Sigil's validate instruction in the same transaction has to authorize the spend, and the finalize instruction has to record it. A leaked agent key cannot exceed the owner-configured daily cap or transfer to a non-allowed destination.
61
96
 
62
- ## Architecture
97
+ ---
63
98
 
99
+ ## Sigil Facade (v0.11.0)
100
+
101
+ The six-step quickstart above is fine, but v0.11.0 ships a single-call facade that wraps it. `Sigil.quickstart()` provisions the vault + returns a handle; `Sigil.fromVault()` binds a handle to an existing vault:
102
+
103
+ ```ts
104
+ import {
105
+ Sigil,
106
+ SAFETY_PRESETS,
107
+ parseUsd,
108
+ USDC_MINT_DEVNET,
109
+ } from "@usesigil/kit";
110
+
111
+ // Provision + get a handle in one call.
112
+ const { vault, funded, signatures } = await Sigil.quickstart({
113
+ rpc,
114
+ network: "devnet",
115
+ owner: ownerSigner,
116
+ agent: agentSigner,
117
+ ...SAFETY_PRESETS.development,
118
+ initialFundingUsd: parseUsd("$100"), // optional — zero or omit to skip
119
+ fundingMint: USDC_MINT_DEVNET, // defaults to USDC on target network
120
+ });
121
+
122
+ if (!funded.funded) {
123
+ console.warn("Vault live but not funded:", funded.reason, funded.error);
124
+ }
125
+
126
+ // Use the handle directly — no separate SigilClient / OwnerClient to wire.
127
+ const result = await vault.execute(jupiterInstructions, {
128
+ tokenMint: USDC_MINT_DEVNET,
129
+ amount: parseUsd("$10"),
130
+ });
131
+
132
+ const overview = await vault.overview(); // owner-only — throws OWNER_REQUIRED without owner
133
+ const budget = await vault.budget(); // cheapest read — agent-only works
64
134
  ```
65
- Transaction = [validate_and_authorize, ...defiInstructions, finalize_session]
135
+
136
+ Bind a handle to an existing vault:
137
+
138
+ ```ts
139
+ const vault = await Sigil.fromVault({
140
+ rpc,
141
+ network: "devnet",
142
+ address: existingVaultAddress,
143
+ agent: agentSigner,
144
+ owner: ownerSigner, // optional — required by vault.freeze() / vault.fund() / vault.overview()
145
+ });
66
146
  ```
67
147
 
68
- Sigil wraps arbitrary DeFi instructions from any source (Jupiter API, Solana Agent Kit, MCP servers) and sandwiches them with on-chain security checks. All instructions succeed or all revert atomically. The SDK handles instruction composition, ATA rewriting, ALT compression, and pre-flight validation.
148
+ Enumerate an owner's vaults:
69
149
 
70
- ## API Overview
150
+ ```ts
151
+ const vaults = await Sigil.discoverVaults(rpc, ownerAddress, "devnet");
152
+ ```
71
153
 
72
- ### Core Create vaults, wrap instructions, execute
154
+ Presets are reachable through the same namespace:
73
155
 
74
- | Export | Description |
75
- | ------------------------- | ---------------------------------------------------------------------------------------- |
76
- | `SigilClient` | Stateful clientholds vault/agent/network, manages caches. Recommended for production. |
77
- | `wrap()` | Stateless wrapping function — takes DeFi instructions, returns a composed transaction. |
78
- | `createVault()` | Build vault creation instructions (caller signs and sends). |
79
- | `createAndSendVault()` | One-call vault creation — build, sign, send, confirm. |
80
- | `buildOwnerTransaction()` | Compose owner-only transactions (policy updates, agent management). |
81
- | `withVault()` | Policy-guided vault creation — policies in, wrapped client out. |
156
+ ```ts
157
+ Sigil.presets.safety.development; // { timelockDuration: 1800, ... }
158
+ Sigil.presets.safety.production; // null capscaller supplies
159
+ Sigil.presets.vault["perps-trader"]; // VAULT_PRESETS entry
160
+ Sigil.presets.applySafetyPreset("production", {
161
+ spendingLimitUsd,
162
+ dailySpendingCapUsd,
163
+ });
164
+ ```
82
165
 
83
- ### StateQuery vaults, budgets, spending
166
+ `Sigil` is a frozen namespace object no instance state, no `new Sigil()`, tree-shakeable.
167
+
168
+ ---
169
+
170
+ ## Lifecycle hooks (v0.11.0)
171
+
172
+ `SealHooks` observe the transaction lifecycle. Pass hooks at client-config level (fire on every call) or per-call (compose on top of client-level hooks):
173
+
174
+ ```ts
175
+ import type { SealHooks } from "@usesigil/kit";
176
+
177
+ const hooks: SealHooks = {
178
+ onBeforeBuild(ctx, params) {
179
+ // Runs before any RPC. Return { skipSeal: true, reason } to abort cleanly.
180
+ if (isDryRunMode()) return { skipSeal: true, reason: "dry-run" };
181
+ },
182
+ onBeforeSign(ctx, tx) {
183
+ // Observational — fires after build + size check, before signing.
184
+ },
185
+ onAfterSend(ctx, signature) {
186
+ // Fires as soon as the signature is obtained — good for starting traces.
187
+ startTrace(ctx.correlationId, signature);
188
+ },
189
+ onFinalize(ctx, result) {
190
+ // Fires on the success path after confirmation.
191
+ closeTrace(ctx.correlationId, result.signature);
192
+ },
193
+ onError(ctx, err) {
194
+ // Fires in every failure path. Error is always rethrown after the hook.
195
+ },
196
+ };
197
+
198
+ // Register at client level — fire on every vault.execute()
199
+ const vault = await Sigil.fromVault({ ..., hooks });
200
+
201
+ // Or per-call — composes with client-level hooks (client runs first, then per-call)
202
+ await vault.execute(instructions, { ..., hooks: perCallHooks });
203
+ ```
84
204
 
85
- | Export | Description |
86
- | ----------------------------- | ----------------------------------------------------------------------------- |
87
- | `resolveVaultState()` | Fetch complete vault state (accounts, policy, tracker, overlay, constraints). |
88
- | `resolveVaultBudget()` | Per-agent budget: rolling 24h spend, cap, remaining headroom. |
89
- | `getSpendingHistory()` | 144-epoch circular buffer to chart-ready time series. |
90
- | `findVaultsByOwner()` | Enumerate all vaults owned by an address. |
91
- | `resolveVaultStateForOwner()` | Vault state with pending policy/constraint updates for dashboards. |
205
+ **Semantics:**
92
206
 
93
- ### Analytics Security checks, agent metrics, portfolio
207
+ - **Observe-only by default.** A hook that throws is caught, logged via the injected logger, and swallowed. Hook exceptions never corrupt `seal()`'s atomic-transaction guarantee.
208
+ - **`onBeforeBuild` is the only hook that may abort.** Returning `{ skipSeal: true, reason }` throws `SigilSdkDomainError(SIGIL_ERROR__SDK__HOOK_ABORTED)` before any RPC round-trip. Use for consent flows, feature flags, or dry-run mode.
209
+ - **`ctx.correlationId`** is stable across every hook for a single seal invocation — use it to correlate `onBeforeBuild` → `onAfterSend` → `onFinalize` in distributed traces.
94
210
 
95
- | Export | Description |
96
- | ------------------------ | ------------------------------------------------------------------- |
97
- | `getSecurityPosture()` | 13-point security assessment with pass/fail, severity, remediation. |
98
- | `getVaultHealth()` | Risk score, liquidity, utilization. |
99
- | `getAgentProfile()` | Single agent stats — spend, tx count, errors. |
100
- | `getAgentLeaderboard()` | Top agents by spend or profit. |
101
- | `getPortfolioOverview()` | Cross-vault summary for multi-vault operators. |
102
- | `getAuditTrail()` | Chronological audit log filtered by category, actor, or time range. |
103
- | `getSpendingVelocity()` | Rate of spend over configurable time windows. |
211
+ ---
104
212
 
105
- 7 analytics modules with 42 functions total — see source for the full list.
213
+ ## Policy plugins (v0.11.0)
106
214
 
107
- ### SafetyPre-flight checks, error handling
215
+ `SigilPolicyPlugin` is the rejection surface distinct from `SealHooks` which observe. Plugins run after state resolution; the first rejection short-circuits `seal()` with `SigilSdkDomainError(SIGIL_ERROR__SDK__PLUGIN_REJECTED)`:
108
216
 
109
- | Export | Description |
110
- | ---------------------- | ------------------------------------------------------------------------------------------------- |
111
- | `shield()` | Client-side policy gate — evaluate instructions before signing. |
112
- | `simulateBeforeSend()` | RPC simulation with error extraction. |
113
- | `detectDrainAttempt()` | Heuristic drain detection from balance deltas. |
114
- | `toAgentError()` | Convert any error to structured `AgentError` with category, retryable flag, and recovery actions. |
217
+ ```ts
218
+ import type { SigilPolicyPlugin } from "@usesigil/kit";
115
219
 
116
- ### Formatting Display helpers (11 functions)
220
+ const maxAmountPlugin: SigilPolicyPlugin = {
221
+ name: "max-amount-plugin",
222
+ check(ctx) {
223
+ if (ctx.amount > 1_000_000_000n) {
224
+ return {
225
+ allow: false,
226
+ reason: "Amount exceeds $1,000 safety threshold",
227
+ };
228
+ }
229
+ return { allow: true };
230
+ },
231
+ };
117
232
 
118
- | Export | Description |
119
- | --------------------- | ------------------------------- |
120
- | `formatUsd()` | `$1,234.56` with full precision |
121
- | `formatUsdCompact()` | `$1.2M`, `$500K` |
122
- | `formatPercent()` | `12.34%` |
123
- | `formatDuration()` | `1d 2h 3m` |
124
- | `formatAddress()` | `4ZeV...wrHL` |
125
- | `formatTokenAmount()` | `1,000.000000 USDC` |
233
+ const vault = await Sigil.fromVault({ ..., plugins: [maxAmountPlugin] });
234
+ // Calls to vault.execute() with amount > $1,000 throw PLUGIN_REJECTED.
235
+ ```
126
236
 
127
- Plus: `formatUsdSigned`, `formatPercentSigned`, `formatRelativeTime`, `formatTimeUntil`, `formatTokenAmountCompact`.
237
+ Plugin semantics:
128
238
 
129
- ### PresetsVault templates
239
+ - **Enforce, not observe.** First `{ allow: false }` short-circuits the chain downstream plugins don't run.
240
+ - **Async `check()` allowed** — plugins can call feature-flag servers or compliance APIs. A plugin that takes >1 second logs a warning (target is sub-second).
241
+ - **Plugin throws become hard rejects.** The runner catches them and treats the message as the rejection reason.
242
+ - **Plugin names must be unique per client.** Config validation at handle construction rejects duplicates.
130
243
 
131
- 4 pre-configured vault templates for common use cases:
244
+ ---
132
245
 
133
- | Preset | Permissions | Daily Cap | Slippage |
134
- | ------------------- | ---------------- | --------- | -------- |
135
- | `jupiter-swap-bot` | Swap only | $500 | 2% |
136
- | `perps-trader` | Perps + Swap | $5,000 | 5% |
137
- | `lending-optimizer` | Deposit/Withdraw | $2,000 | 1% |
138
- | `full-access` | All 21 actions | $10,000 | 5% |
246
+ ## React hooks (v0.11.0, optional subpath)
139
247
 
140
- ```typescript
141
- import { getPreset, presetToCreateVaultFields } from "@usesigil/kit";
248
+ Install React + TanStack Query as optional peer dependencies, then import from `@usesigil/kit/react`:
142
249
 
143
- const preset = getPreset("jupiter-swap-bot");
144
- const fields = presetToCreateVaultFields(preset);
250
+ ```bash
251
+ npm install react @tanstack/react-query
145
252
  ```
146
253
 
147
- ### HTTP 402 Payments (x402)
254
+ ```tsx
255
+ import { useVaultBudget, useOverview, useExecute } from "@usesigil/kit/react";
256
+
257
+ function VaultDashboard({ vault }: { vault: SigilVault }) {
258
+ const budget = useVaultBudget(vault); // { data, isLoading, error }
259
+ const overview = useOverview(vault); // owner-only
260
+ const execute = useExecute(vault); // { mutate, mutateAsync, isPending }
261
+
262
+ if (budget.isLoading) return <div>Loading...</div>;
263
+ return (
264
+ <button
265
+ onClick={() =>
266
+ execute.mutate({
267
+ instructions: myJupiterInstructions,
268
+ opts: { tokenMint: USDC_MINT_DEVNET, amount: parseUsd("$10") },
269
+ })
270
+ }
271
+ disabled={execute.isPending}
272
+ >
273
+ Swap $10
274
+ </button>
275
+ );
276
+ }
277
+ ```
148
278
 
149
- Sigil supports the [x402 standard](https://www.x402.org/) for automatic HTTP 402 payment negotiation on Solana. Use `shieldedFetch()` to handle payment-required responses transparently spending limits and vault policies are enforced on every payment.
279
+ Query keys are namespaced under `"sigil"` so they never collide with the consumer app's TanStack cache. Cache invalidation is the consumer's responsibility wrap `useExecute` with a custom `onSuccess` that invalidates the specific vault keys you want refetched.
150
280
 
151
- ```typescript
152
- import { shieldedFetch, createShieldedFetch } from "@usesigil/kit/x402";
281
+ Consumers who don't use React never install the peer deps and never see a warning.
153
282
 
154
- // One-shot: fetch a paywalled URL, auto-negotiate payment
155
- const response = await shieldedFetch(url, {
156
- vault,
157
- agent,
158
- rpc,
159
- network: "devnet",
160
- maxPaymentUsd: 1_000_000n, // $1 max per request
161
- });
283
+ ---
162
284
 
163
- if (response.x402?.paid) {
164
- console.log(`Paid ${response.x402.amount} to ${response.x402.payTo}`);
165
- }
285
+ ## Security boundary
166
286
 
167
- // Reusable: create a pre-configured fetch function
168
- const fetch402 = createShieldedFetch({ vault, agent, rpc, network: "devnet" });
169
- const res = await fetch402("https://api.example.com/premium-data");
170
- ```
287
+ **What the on-chain program enforces:**
171
288
 
172
- The x402 subpath exports codec functions (header parsing), payment selectors, nonce tracking, amount validation, and 5 typed error classes (`X402ParseError`, `X402PaymentError`, `X402UnsupportedError`, `X402DestinationBlockedError`, `X402ReplayError`). See [INSTRUCTIONS.md](../docs/INSTRUCTIONS.md) for the full 12-step `shieldedFetch()` flow.
289
+ - Daily and per-transaction spending caps (`dailySpendingCapUsd`, `maxTransactionSizeUsd`)
290
+ - Per-agent spending limits (`spendingLimitUsd`)
291
+ - Protocol allowlist / denylist (`protocols`, `protocolMode`)
292
+ - Slippage tolerance on Jupiter swaps (`maxSlippageBps`)
293
+ - Session expiry, position counters, leverage limits
294
+ - Owner timelock on policy changes (`timelockDuration`)
173
295
 
174
- ## Branded Types
296
+ **What the SDK enforces pre-submission:**
175
297
 
176
- All USD amounts, capability tiers, and slot numbers are branded bigint types that prevent accidental misuse at compile time:
298
+ - Agent capability check (2-bit enum: Disabled / Observer / Operator)
299
+ - Genesis-hash assertion on `SigilClient.create()` — prevents cluster mismatch
300
+ - Strict USD parsing (`parseUsd`) — no `parseFloat` rounding
301
+ - Aggregate cap guard — sum of per-agent caps ≤ vault cap
302
+ - SPL token-operation detection — blocks non-whitelisted transfer patterns
177
303
 
178
- ```typescript
179
- import {
180
- usd,
181
- capability,
182
- slot,
183
- type UsdBaseUnits,
184
- type CapabilityTier,
185
- } from "@usesigil/kit";
304
+ **What the SDK does NOT attempt:**
186
305
 
187
- const cap: UsdBaseUnits = usd(500_000_000n); // $500
188
- const tier: CapabilityTier = capability(2n); // Operator
306
+ - Key custody bring your own `TransactionSigner` (Turnkey, Crossmint, Privy, or a local keypair)
307
+ - Transaction simulation outcome trust — simulation is a hint, not a guarantee; on-chain enforcement is the source of truth
308
+ - Replay prevention outside a session — agents must start a new session per transaction
189
309
 
190
- // TypeScript ERRORthese types are not interchangeable:
191
- // addAgent(agent, cap, tier); // cap and tier swapped → compile error
192
- addAgent(agent, tier, cap); // correct order → compiles
193
- ```
310
+ If a piece of SDK logic is wrong, the worst a consumer loses is some UX clarity the on-chain program still rejects the bad transaction. The boundary is deliberate.
194
311
 
195
- Zero runtime cost — the brand is a phantom type that TypeScript erases at compile time.
312
+ ---
196
313
 
197
- ## MCP Round-Trip (fromJSON)
314
+ ## Configuration presets
198
315
 
199
- When AI agents consume Sigil via MCP, they receive JSON from tool responses and pass data back to subsequent calls. The `fromJSON` functions rehydrate bigints, typed addresses, and `toJSON()` methods:
316
+ ### Use-case presets (`VAULT_PRESETS`)
200
317
 
201
- ```typescript
202
- import { overviewDataFromJSON } from "@usesigil/kit/dashboard";
318
+ Starting templates for specific agent roles. Each sets capability, allowlist, slippage, and caps appropriate for the use case:
203
319
 
204
- // MCP tool response JSON rehydrated live types
205
- const overview = overviewDataFromJSON(toolResponse.data);
206
- console.log(overview.spending.global.today); // bigint, not string
207
- ```
320
+ - `jupiter-swap-bot` Jupiter only, conservative caps ($500/day, $100/tx)
321
+ - `perps-trader` Jupiter + Flash Trade, 10× leverage, $5,000/day
322
+ - `lending-optimizer` — Jupiter Lend + Kamino, 1% slippage, $2,000/day
323
+ - `full-access` — every protocol allowed, $10,000/day, 20× leverage
208
324
 
209
- 10 fromJSON functions cover all dashboard types. Available from `@usesigil/kit/dashboard`.
325
+ ### Safety presets (`SAFETY_PRESETS`) v0.9.0
210
326
 
211
- ## Error Handling
327
+ Orthogonal to the use-case presets. Picks safe defaults for timelock and caps without prescribing a use case:
212
328
 
213
- All errors from `wrap()` and `executeAndConfirm()` convert to structured `AgentError`:
329
+ - `development` 30-min timelock, $100/agent, $500/day. Safe for devnet / CI.
330
+ - `production` — 24-hour timelock, caps explicitly `null`. You must supply real values via `applySafetyPreset("production", { ... })` — the SDK will throw if you try to use an unfilled production preset with `createVault`.
214
331
 
215
- ```typescript
216
- import { toAgentError } from "@usesigil/kit";
332
+ Compose them:
217
333
 
218
- try {
219
- await client.executeAndConfirm(instructions, opts);
220
- } catch (err) {
221
- const e = toAgentError(err);
222
- console.log(e.category); // "PERMISSION" | "SPENDING_CAP" | "INPUT_VALIDATION" | ...
223
- console.log(e.retryable); // boolean
224
- console.log(e.recovery_actions); // [{ action, description, tool? }]
225
- }
334
+ ```ts
335
+ import { createVault, VAULT_PRESETS, applySafetyPreset } from "@usesigil/kit";
336
+
337
+ const presetFields = VAULT_PRESETS["jupiter-swap-bot"];
338
+ const safety = applySafetyPreset("production", {
339
+ spendingLimitUsd: 1_000_000_000n, // $1,000 per agent
340
+ dailySpendingCapUsd: 10_000_000_000n, // $10,000 vault-wide
341
+ });
342
+ await createVault({
343
+ rpc,
344
+ network: "mainnet",
345
+ owner,
346
+ agent,
347
+ ...presetFields,
348
+ ...safety,
349
+ });
226
350
  ```
227
351
 
228
- 10 error categories with recovery guidance. 71 on-chain error codes (6000-6070) mapped.
352
+ ---
229
353
 
230
- ## Testing
354
+ ## Jupiter integration
231
355
 
232
- ```typescript
233
- // Browser-safe mocks (no node:fs, no @solana/web3.js)
234
- import { createMockRpc, createMockVaultState } from "@usesigil/kit/testing";
356
+ `@usesigil/kit` does not wrap Jupiter. Use the official [`@jup-ag/api`](https://www.npmjs.com/package/@jup-ag/api) client to build swap instructions, then pipe the `Instruction[]` through `seal()`:
235
357
 
236
- // Real devnet helpers (Node-only)
237
- import { provisionVault, createDevnetRpc } from "@usesigil/kit/testing/devnet";
358
+ ```ts
359
+ import { createJupiterApiClient } from "@jup-ag/api";
360
+ import { seal } from "@usesigil/kit";
361
+
362
+ const jupiter = createJupiterApiClient();
363
+ const { swapTransaction, addressLookupTableAddresses } = await jupiter.swapPost(
364
+ { quoteResponse, userPublicKey: vault },
365
+ );
366
+
367
+ // Extract instructions from the serialized swapTransaction (helper omitted
368
+ // for brevity — decode with @solana/kit's `getCompiledTransactionMessageDecoder`
369
+ // then convert each CompiledInstruction to the Kit Instruction shape).
370
+ const jupiterIxs: Instruction[] = decodeSwapInstructions(swapTransaction);
371
+
372
+ const sealed = await seal({
373
+ rpc,
374
+ network: "devnet",
375
+ vault,
376
+ agent: agentSigner,
377
+ instructions: jupiterIxs,
378
+ tokenMint: USDC_MINT_DEVNET,
379
+ amount: 10_000_000n, // $10 in base units
380
+ protocolAltAddresses: addressLookupTableAddresses, // rotate per-route
381
+ });
238
382
  ```
239
383
 
240
- `@usesigil/kit/testing` provides mock factories for unit tests. `@usesigil/kit/testing/devnet` provides real devnet helpers (vault provisioning, funded agents, USDC airdrops). The devnet subpath imports `node:fs` and `@solana/web3.js` — keep it out of browser bundles.
384
+ Any Jupiter-supported protocol flows through the same path; Sigil treats the instructions opaquely and enforces policy on the account touches Jupiter actually makes.
385
+
386
+ ---
387
+
388
+ ## Subpath imports
389
+
390
+ | Import | Use for |
391
+ | ------------------------------ | -------------------------------------------------------------------- |
392
+ | `@usesigil/kit` | Main API: `seal`, `SigilClient`, `createVault`, analytics, presets |
393
+ | `@usesigil/kit/errors` | The 52 `SIGIL_ERROR__*` code constants for `catch`-block narrowing |
394
+ | `@usesigil/kit/dashboard` | `OwnerClient` for vault management (reads + owner mutations) |
395
+ | `@usesigil/kit/x402` | HTTP 402 Payment Required helpers (`shieldedFetch`, payment parsing) |
396
+ | `@usesigil/kit/react` | TanStack Query hooks (v0.11.0) — optional React peer deps |
397
+ | `@usesigil/kit/testing` | Mock RPCs and fixtures for unit tests |
398
+ | `@usesigil/kit/testing/devnet` | Devnet test harness (browser-incompatible — Node only) |
399
+
400
+ ---
401
+
402
+ ## v0.10 → v0.11 migration
403
+
404
+ v0.11.0 is additive. Existing v0.10.0 consumers do not need to change code to upgrade — `Sigil` facade, `SigilVault`, hooks, plugins, and the `/react` subpath all sit on top of the existing `createSigilClient` / `createOwnerClient` / `seal()` primitives.
405
+
406
+ Recommended migration path:
407
+
408
+ 1. Replace bespoke `createAndSendVault` + `SigilClient.create` + `createOwnerClient` plumbing with `Sigil.quickstart()` / `Sigil.fromVault()` for new call sites.
409
+ 2. Add lifecycle hooks to your existing `SigilClientConfig` or `SigilVault.execute()` options for telemetry.
410
+ 3. Move React consumers off ad-hoc `useEffect` loops onto `@usesigil/kit/react` hooks.
411
+
412
+ v0.11.0 also added three new error codes to `/errors` (for a total of 52):
413
+
414
+ - `SIGIL_ERROR__SDK__HOOK_ABORTED` — onBeforeBuild returned `{ skipSeal: true }`
415
+ - `SIGIL_ERROR__SDK__PLUGIN_REJECTED` — a plugin returned `{ allow: false }`
416
+ - `SIGIL_ERROR__SDK__OWNER_REQUIRED` — an owner-only SigilVault method was called on an agent-only handle
417
+
418
+ ---
419
+
420
+ ## v0.8 → v0.9 migration
241
421
 
242
- ## Examples
422
+ v0.9.0 is a breaking release. The headline changes:
243
423
 
244
- - [`examples/jupiter-swap.ts`](./examples/jupiter-swap.ts) Complete Jupiter V6 swap via Sigil with error handling and P&L tracking
424
+ 1. **`createVault` now requires three fields** that previously had silent defaults: `spendingLimitUsd`, `dailySpendingCapUsd`, `timelockDuration`. Set them explicitly or spread `SAFETY_PRESETS.development` / `applySafetyPreset("production", {...})`.
425
+ 2. **`SigilClient.create(config)` is the new preferred entry point** — it asserts the RPC's genesis hash matches the configured network. `new SigilClient(config)` is deprecated (removal in Sprint 2) and logs a warning.
426
+ 3. **49 `SIGIL_ERROR__*` constants moved from the root barrel** to the `./errors` subpath. Update imports:
427
+ ```diff
428
+ - import { SIGIL_ERROR__SDK__CAP_EXCEEDED } from "@usesigil/kit";
429
+ + import { SIGIL_ERROR__SDK__CAP_EXCEEDED } from "@usesigil/kit/errors";
430
+ ```
431
+ 4. **Root barrel lost ~325 exports** (Codama instruction builders, event/struct types, hex error constants). Consumers who imported generated internals should migrate to `seal()` / `createVault()` / `OwnerClient`. Account decoders stay at root.
432
+ 5. **Structured logger replaces `console.warn`** inside the SDK. Pass `logger: createConsoleLogger()` to `SigilClient.create()` (or your preferred logger matching the `SigilLogger` interface) to receive diagnostic output.
245
433
 
246
- ## Links
434
+ See `CHANGELOG.md` and the upgrade checklist for every grep you need to run.
247
435
 
248
- - [GitHub](https://github.com/Sigil-Trade/sigil)
249
- - [npm](https://www.npmjs.com/package/@usesigil/kit)
250
- - [Issues](https://github.com/Sigil-Trade/sigil/issues)
436
+ ---
251
437
 
252
438
  ## License
253
439
 
254
- Apache-2.0
440
+ Apache-2.0. Copyright 2024-2026 Kaleb Rupe.
@@ -29,10 +29,12 @@ export declare const EXPECTED_ALT_CONTENTS_DEVNET: Address[];
29
29
  /**
30
30
  * Expected contents of the mainnet Sigil ALT.
31
31
  * Uses mainnet mints; treasury is the same across networks.
32
- * TODO: Add TREASURY_USDC_ATA_MAINNET and TREASURY_USDT_ATA_MAINNET
33
- * after deploying and extending the mainnet ALT. Derive from:
32
+ *
33
+ * Pre-mainnet task: extend this array with TREASURY_USDC_ATA_MAINNET and
34
+ * TREASURY_USDT_ATA_MAINNET after deploying the mainnet ALT. Derive via:
34
35
  * getAssociatedTokenAddress(USDC_MINT_MAINNET, PROTOCOL_TREASURY, true)
35
36
  * getAssociatedTokenAddress(USDT_MINT_MAINNET, PROTOCOL_TREASURY, true)
37
+ * Tracked alongside mainnet deployment checklist (D3 — upgrade authority transfer).
36
38
  */
37
39
  export declare const EXPECTED_ALT_CONTENTS_MAINNET: Address[];
38
40
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"alt-config.d.ts","sourceRoot":"","sources":["../src/alt-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAW1C,sGAAsG;AACtG,eAAO,MAAM,gBAAgB,EACuB,OAAO,CAAC;AAE5D,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,EAAyC,OAAO,CAAC;AAU/E;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAQ5D;AAYD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,OAAO,EAQjD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,EAAE,OAAO,EAMlD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,CAIlE"}
1
+ {"version":3,"file":"alt-config.d.ts","sourceRoot":"","sources":["../src/alt-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAW1C,sGAAsG;AACtG,eAAO,MAAM,gBAAgB,EACuB,OAAO,CAAC;AAE5D,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,EAAyC,OAAO,CAAC;AAU/E;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAQ5D;AAYD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,OAAO,EAQjD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,EAAE,OAAO,EAMlD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,CAIlE"}
@@ -54,10 +54,12 @@ export const EXPECTED_ALT_CONTENTS_DEVNET = [
54
54
  /**
55
55
  * Expected contents of the mainnet Sigil ALT.
56
56
  * Uses mainnet mints; treasury is the same across networks.
57
- * TODO: Add TREASURY_USDC_ATA_MAINNET and TREASURY_USDT_ATA_MAINNET
58
- * after deploying and extending the mainnet ALT. Derive from:
57
+ *
58
+ * Pre-mainnet task: extend this array with TREASURY_USDC_ATA_MAINNET and
59
+ * TREASURY_USDT_ATA_MAINNET after deploying the mainnet ALT. Derive via:
59
60
  * getAssociatedTokenAddress(USDC_MINT_MAINNET, PROTOCOL_TREASURY, true)
60
61
  * getAssociatedTokenAddress(USDT_MINT_MAINNET, PROTOCOL_TREASURY, true)
62
+ * Tracked alongside mainnet deployment checklist (D3 — upgrade authority transfer).
61
63
  */
62
64
  export const EXPECTED_ALT_CONTENTS_MAINNET = [
63
65
  USDC_MINT_MAINNET,