@veil-cash/sdk 0.4.0 → 0.6.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 +130 -464
- package/SDK.md +365 -0
- package/dist/cli/index.cjs +2260 -955
- package/dist/index.cjs +561 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +486 -1
- package/dist/index.d.ts +486 -1
- package/dist/index.js +544 -27
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/skills/veil/SKILL.md +526 -0
- package/skills/veil/reference.md +231 -0
- package/src/abi.ts +172 -0
- package/src/addresses.ts +20 -2
- package/src/balance.ts +4 -4
- package/src/cli/commands/balance.ts +126 -38
- package/src/cli/commands/deposit.ts +136 -63
- package/src/cli/commands/init.ts +95 -72
- package/src/cli/commands/keypair.ts +34 -16
- package/src/cli/commands/private-balance.ts +37 -35
- package/src/cli/commands/queue-balance.ts +48 -36
- package/src/cli/commands/register.ts +67 -53
- package/src/cli/commands/status.ts +196 -70
- package/src/cli/commands/subaccount.ts +354 -0
- package/src/cli/commands/transfer.ts +62 -53
- package/src/cli/commands/withdraw.ts +32 -30
- package/src/cli/config.ts +85 -5
- package/src/cli/errors.ts +8 -0
- package/src/cli/index.ts +27 -5
- package/src/cli/output.ts +87 -0
- package/src/cli/wallet.ts +75 -16
- package/src/index.ts +41 -1
- package/src/prover.ts +3 -0
- package/src/relay.ts +36 -24
- package/src/subaccount.ts +476 -0
- package/src/types.ts +134 -0
package/SDK.md
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# SDK Guide
|
|
2
|
+
|
|
3
|
+
This package ships both a CLI and a TypeScript SDK.
|
|
4
|
+
|
|
5
|
+
If you are looking for the CLI first-run flow, go back to the main [README](./README.md).
|
|
6
|
+
|
|
7
|
+
## SDK Quick Start
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import {
|
|
11
|
+
Keypair, buildRegisterTx, buildDepositETHTx,
|
|
12
|
+
buildDepositUSDCTx, buildApproveUSDCTx,
|
|
13
|
+
withdraw, transfer, getSubaccountStatus,
|
|
14
|
+
} from '@veil-cash/sdk';
|
|
15
|
+
import { createWalletClient, http } from 'viem';
|
|
16
|
+
import { base } from 'viem/chains';
|
|
17
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
18
|
+
|
|
19
|
+
// 1. Generate a Veil keypair (do this once, save securely!)
|
|
20
|
+
const keypair = new Keypair();
|
|
21
|
+
console.log('Veil Private Key:', keypair.privkey); // SAVE THIS!
|
|
22
|
+
console.log('Deposit Key:', keypair.depositKey()); // Register this on-chain
|
|
23
|
+
|
|
24
|
+
// 2. Setup your Ethereum wallet
|
|
25
|
+
const account = privateKeyToAccount('0x...');
|
|
26
|
+
const client = createWalletClient({
|
|
27
|
+
account,
|
|
28
|
+
chain: base,
|
|
29
|
+
transport: http(),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// 3. Register your deposit key (one-time)
|
|
33
|
+
const registerTx = buildRegisterTx(keypair.depositKey(), account.address);
|
|
34
|
+
await client.sendTransaction(registerTx);
|
|
35
|
+
|
|
36
|
+
// 4. Deposit ETH
|
|
37
|
+
const depositTx = buildDepositETHTx({
|
|
38
|
+
depositKey: keypair.depositKey(),
|
|
39
|
+
amount: '0.1',
|
|
40
|
+
});
|
|
41
|
+
await client.sendTransaction({ ...depositTx, value: depositTx.value });
|
|
42
|
+
|
|
43
|
+
// 4b. Deposit USDC (approve first)
|
|
44
|
+
const approveTx = buildApproveUSDCTx({ amount: '100' });
|
|
45
|
+
await client.sendTransaction(approveTx);
|
|
46
|
+
const usdcTx = buildDepositUSDCTx({
|
|
47
|
+
depositKey: keypair.depositKey(),
|
|
48
|
+
amount: '100',
|
|
49
|
+
});
|
|
50
|
+
await client.sendTransaction(usdcTx);
|
|
51
|
+
|
|
52
|
+
// 5. Withdraw (sent via relayer, no wallet signing needed)
|
|
53
|
+
const withdrawResult = await withdraw({
|
|
54
|
+
amount: '0.05',
|
|
55
|
+
recipient: '0xRecipientAddress',
|
|
56
|
+
keypair,
|
|
57
|
+
pool: 'eth', // 'eth' | 'usdc' (default: 'eth')
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// 6. Transfer privately
|
|
61
|
+
const transferResult = await transfer({
|
|
62
|
+
amount: '0.02',
|
|
63
|
+
recipientAddress: '0xRecipientAddress',
|
|
64
|
+
senderKeypair: keypair,
|
|
65
|
+
pool: 'eth', // 'eth' | 'usdc' (default: 'eth')
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// 7. Inspect a deterministic subaccount slot
|
|
69
|
+
const subaccount = await getSubaccountStatus({
|
|
70
|
+
rootPrivateKey: keypair.privkey as `0x${string}`,
|
|
71
|
+
slot: 0,
|
|
72
|
+
});
|
|
73
|
+
console.log(subaccount.slot.forwarderAddress);
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## SDK API Reference
|
|
78
|
+
|
|
79
|
+
### Keypair
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { Keypair, VEIL_SIGNED_MESSAGE } from '@veil-cash/sdk';
|
|
83
|
+
import type { MessageSigner } from '@veil-cash/sdk';
|
|
84
|
+
|
|
85
|
+
// Generate random keypair
|
|
86
|
+
const keypair = new Keypair();
|
|
87
|
+
|
|
88
|
+
// Restore from saved Veil private key
|
|
89
|
+
const restored = new Keypair(savedVeilKey);
|
|
90
|
+
|
|
91
|
+
// Derive from wallet key (same keypair as frontend login)
|
|
92
|
+
const derived = await Keypair.fromWalletKey('0xYOUR_WALLET_KEY');
|
|
93
|
+
|
|
94
|
+
// Derive from a raw EIP-191 signature
|
|
95
|
+
const fromSig = Keypair.fromSignature('0xSIGNATURE...');
|
|
96
|
+
|
|
97
|
+
// Derive from any external signer (agent framework, MPC, custodial, etc.)
|
|
98
|
+
const fromSigner = await Keypair.fromSigner(async (message) => {
|
|
99
|
+
// Sign `message` using any personal_sign provider and return the signature
|
|
100
|
+
return await mySigningService.personalSign(message);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Get deposit key (for registration)
|
|
104
|
+
keypair.depositKey(); // '0x...' (130 hex chars)
|
|
105
|
+
|
|
106
|
+
// Veil private key (store securely!)
|
|
107
|
+
keypair.privkey; // '0x...'
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Transaction Builders
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import {
|
|
114
|
+
buildRegisterTx, buildChangeDepositKeyTx, buildDepositETHTx, buildDepositTx,
|
|
115
|
+
buildDepositUSDCTx, buildApproveUSDCTx,
|
|
116
|
+
} from '@veil-cash/sdk';
|
|
117
|
+
|
|
118
|
+
// Register deposit key (first time)
|
|
119
|
+
const registerTx = buildRegisterTx(depositKey, ownerAddress);
|
|
120
|
+
// -> { to: '0x...', data: '0x...' }
|
|
121
|
+
|
|
122
|
+
// Change deposit key (must already be registered)
|
|
123
|
+
const changeTx = buildChangeDepositKeyTx(newDepositKey, ownerAddress);
|
|
124
|
+
// -> { to: '0x...', data: '0x...' }
|
|
125
|
+
|
|
126
|
+
// Deposit ETH
|
|
127
|
+
const depositTx = buildDepositETHTx({
|
|
128
|
+
depositKey: keypair.depositKey(),
|
|
129
|
+
amount: '0.1',
|
|
130
|
+
});
|
|
131
|
+
// -> { to: '0x...', data: '0x...', value: 100000000000000000n }
|
|
132
|
+
|
|
133
|
+
// Deposit USDC (approve + deposit)
|
|
134
|
+
const approveUsdcTx = buildApproveUSDCTx({ amount: '100' });
|
|
135
|
+
const depositUsdcTx = buildDepositUSDCTx({
|
|
136
|
+
depositKey: keypair.depositKey(),
|
|
137
|
+
amount: '100',
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Generic builder (routes by token)
|
|
141
|
+
const tx = buildDepositTx({
|
|
142
|
+
depositKey: keypair.depositKey(),
|
|
143
|
+
amount: '0.1',
|
|
144
|
+
token: 'ETH', // 'ETH' | 'USDC'
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Withdraw & Transfer
|
|
149
|
+
|
|
150
|
+
All withdraw, transfer, and merge functions accept an optional `pool` parameter (`'eth'` | `'usdc'`), defaulting to `'eth'`.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { withdraw, transfer, mergeUtxos } from '@veil-cash/sdk';
|
|
154
|
+
|
|
155
|
+
// Withdraw ETH to public address
|
|
156
|
+
const withdrawResult = await withdraw({
|
|
157
|
+
amount: '0.05',
|
|
158
|
+
recipient: '0xRecipientAddress',
|
|
159
|
+
keypair,
|
|
160
|
+
pool: 'eth', // default
|
|
161
|
+
onProgress: (stage, detail) => console.log(stage, detail),
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Withdraw USDC
|
|
165
|
+
const withdrawUsdc = await withdraw({
|
|
166
|
+
amount: '50',
|
|
167
|
+
recipient: '0xRecipientAddress',
|
|
168
|
+
keypair,
|
|
169
|
+
pool: 'usdc',
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Merge UTXOs (consolidate small balances)
|
|
173
|
+
const mergeResult = await mergeUtxos({
|
|
174
|
+
amount: '0.1',
|
|
175
|
+
keypair,
|
|
176
|
+
pool: 'eth',
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Balance Queries
|
|
181
|
+
|
|
182
|
+
Balance functions accept an optional `pool` parameter (`'eth'` | `'usdc'`), defaulting to `'eth'`.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { getQueueBalance, getPrivateBalance } from '@veil-cash/sdk';
|
|
186
|
+
|
|
187
|
+
// Check ETH queue balance (pending deposits)
|
|
188
|
+
const queueBalance = await getQueueBalance({
|
|
189
|
+
address: '0x...',
|
|
190
|
+
pool: 'eth', // default
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Check USDC private balance (requires keypair)
|
|
194
|
+
const privateBalance = await getPrivateBalance({
|
|
195
|
+
keypair,
|
|
196
|
+
pool: 'usdc',
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Subaccounts
|
|
201
|
+
|
|
202
|
+
Subaccounts are deterministic child slots derived from your main Veil key:
|
|
203
|
+
|
|
204
|
+
`root key -> slot -> child key -> child deposit key -> forwarder`
|
|
205
|
+
|
|
206
|
+
Base mainnet only. Status shows the forwarder wallet and queue state only. Deploy and sweep are relay-backed. Recovery signs a forwarder withdraw request with the child key and returns a direct transaction for your gas payer to submit.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import {
|
|
210
|
+
deriveSubaccountSlot,
|
|
211
|
+
getSubaccountStatus,
|
|
212
|
+
deploySubaccountForwarder,
|
|
213
|
+
sweepSubaccountForwarder,
|
|
214
|
+
buildSubaccountRecoveryTx,
|
|
215
|
+
} from '@veil-cash/sdk';
|
|
216
|
+
|
|
217
|
+
const slot = await deriveSubaccountSlot({
|
|
218
|
+
rootPrivateKey: veilKey,
|
|
219
|
+
slot: 0,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const status = await getSubaccountStatus({
|
|
223
|
+
rootPrivateKey: veilKey,
|
|
224
|
+
slot: 0,
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
await deploySubaccountForwarder({
|
|
228
|
+
rootPrivateKey: veilKey,
|
|
229
|
+
slot: 0,
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
await sweepSubaccountForwarder({
|
|
233
|
+
forwarderAddress: slot.forwarderAddress,
|
|
234
|
+
asset: 'eth',
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const recovery = await buildSubaccountRecoveryTx({
|
|
238
|
+
rootPrivateKey: veilKey,
|
|
239
|
+
slot: 0,
|
|
240
|
+
asset: 'usdc',
|
|
241
|
+
to: '0xRecipientAddress',
|
|
242
|
+
amount: '25',
|
|
243
|
+
});
|
|
244
|
+
// Send recovery.transaction with your wallet client
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Addresses
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { getAddresses, getPoolAddress, getQueueAddress } from '@veil-cash/sdk';
|
|
251
|
+
|
|
252
|
+
const addresses = getAddresses();
|
|
253
|
+
console.log(addresses.entry); // Entry contract
|
|
254
|
+
console.log(addresses.ethPool); // ETH pool
|
|
255
|
+
console.log(addresses.usdcPool); // USDC pool
|
|
256
|
+
|
|
257
|
+
// Helper functions to resolve by pool name
|
|
258
|
+
console.log(getPoolAddress('eth')); // ETH pool address
|
|
259
|
+
console.log(getPoolAddress('usdc')); // USDC pool address
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## For AI Agents
|
|
263
|
+
|
|
264
|
+
This SDK is designed to work with AI agent frameworks and external signers.
|
|
265
|
+
|
|
266
|
+
### Non-Interactive CLI
|
|
267
|
+
|
|
268
|
+
Human-readable output is the CLI default. Use `--json` for machine-readable responses and `--unsigned` for transaction payload generation:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Generate keypair as JSON (no prompts, no file save)
|
|
272
|
+
veil init --json
|
|
273
|
+
|
|
274
|
+
# Get unsigned transaction payloads for agent signing
|
|
275
|
+
SIGNER_ADDRESS=0x... veil register --unsigned
|
|
276
|
+
veil deposit ETH 0.1 --unsigned
|
|
277
|
+
veil deposit USDC 100 --unsigned # Outputs approve + deposit payloads
|
|
278
|
+
|
|
279
|
+
# Request machine-readable status or balances
|
|
280
|
+
veil balance --json
|
|
281
|
+
veil balance --pool usdc --json
|
|
282
|
+
veil withdraw ETH 0.05 0xRecipient --json
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
`SIGNER_ADDRESS` can be used for address-only agent flows such as `veil status`, `veil balance`, and `veil register --unsigned` when the signer manages the wallet externally. `WALLET_KEY` and `SIGNER_ADDRESS` are mutually exclusive, and signed commands still require `WALLET_KEY`.
|
|
286
|
+
|
|
287
|
+
`veil status` shows a **Signing** row that reflects the active mode (`local (WALLET_KEY)`, `external (SIGNER_ADDRESS)`, or `not configured`), plus public ETH balance when it can be resolved.
|
|
288
|
+
|
|
289
|
+
### Bankr Integration
|
|
290
|
+
|
|
291
|
+
#### Keypair Derivation via Bankr Sign API
|
|
292
|
+
|
|
293
|
+
Use `Keypair.fromSigner()` with Bankr's `POST /agent/sign` endpoint to derive the same keypair as the frontend:
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
import { Keypair } from '@veil-cash/sdk';
|
|
297
|
+
|
|
298
|
+
const keypair = await Keypair.fromSigner(async (message) => {
|
|
299
|
+
const res = await fetch('https://api.bankr.bot/agent/sign', {
|
|
300
|
+
method: 'POST',
|
|
301
|
+
headers: { 'X-API-Key': BANKR_API_KEY, 'Content-Type': 'application/json' },
|
|
302
|
+
body: JSON.stringify({ signatureType: 'personal_sign', message }),
|
|
303
|
+
});
|
|
304
|
+
return (await res.json()).signature;
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Or via CLI (two-step):
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# 1. Get signature from Bankr sign API
|
|
312
|
+
SIG=$(curl -s -X POST "https://api.bankr.bot/agent/sign" \
|
|
313
|
+
-H "X-API-Key: $BANKR_API_KEY" \
|
|
314
|
+
-H "Content-Type: application/json" \
|
|
315
|
+
-d "{\"signatureType\":\"personal_sign\",\"message\":\"$(node -e "const{VEIL_SIGNED_MESSAGE}=require('@veil-cash/sdk');console.log(VEIL_SIGNED_MESSAGE)")\"}" \
|
|
316
|
+
| jq -r '.signature')
|
|
317
|
+
|
|
318
|
+
# 2. Derive keypair from signature
|
|
319
|
+
veil init --signature $SIG
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
#### Unsigned Transaction Payloads
|
|
323
|
+
|
|
324
|
+
Use `--unsigned` to get signer-compatible transaction payloads:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
SIGNER_ADDRESS=0x... veil register --unsigned
|
|
328
|
+
SIGNER_ADDRESS=0x... veil register --unsigned --force
|
|
329
|
+
veil deposit ETH 0.1 --unsigned
|
|
330
|
+
# {"to":"0x...","data":"0x...","value":"100000000000000000","chainId":8453}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
The `--unsigned` flag outputs a standard `{to, data, value, chainId}` payload compatible with any signer that accepts arbitrary transactions.
|
|
334
|
+
When `SIGNER_ADDRESS` is set, `veil register --unsigned` no longer requires the `--address` flag.
|
|
335
|
+
For `veil register --unsigned --force`, the CLI checks on-chain registration state first and emits `changeDepositKey` only when the address is already registered; otherwise it falls back to `register`.
|
|
336
|
+
|
|
337
|
+
### Programmatic SDK Usage
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { Keypair, buildDepositETHTx, buildDepositTx, withdraw } from '@veil-cash/sdk';
|
|
341
|
+
|
|
342
|
+
// For deposits: build transaction, let agent sign via your signer
|
|
343
|
+
const keypair = new Keypair(veilKey);
|
|
344
|
+
const tx = buildDepositETHTx({
|
|
345
|
+
depositKey: keypair.depositKey(),
|
|
346
|
+
amount: '0.1',
|
|
347
|
+
});
|
|
348
|
+
// -> { to, data, value } - pass to your signer
|
|
349
|
+
|
|
350
|
+
// Generic builder works for any asset
|
|
351
|
+
const usdcTx = buildDepositTx({
|
|
352
|
+
depositKey: keypair.depositKey(),
|
|
353
|
+
amount: '100',
|
|
354
|
+
token: 'USDC',
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
// For withdrawals: SDK handles ZK proofs, submits to relayer
|
|
358
|
+
const result = await withdraw({
|
|
359
|
+
amount: '0.05',
|
|
360
|
+
recipient: '0xRecipient',
|
|
361
|
+
keypair,
|
|
362
|
+
pool: 'eth', // 'eth' | 'usdc'
|
|
363
|
+
});
|
|
364
|
+
// -> { success, transactionHash, blockNumber }
|
|
365
|
+
```
|