@veil-cash/sdk 0.4.0 → 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/SDK.md ADDED
@@ -0,0 +1,311 @@
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,
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
+ ```
69
+
70
+ ## SDK API Reference
71
+
72
+ ### Keypair
73
+
74
+ ```typescript
75
+ import { Keypair, VEIL_SIGNED_MESSAGE } from '@veil-cash/sdk';
76
+ import type { MessageSigner } from '@veil-cash/sdk';
77
+
78
+ // Generate random keypair
79
+ const keypair = new Keypair();
80
+
81
+ // Restore from saved Veil private key
82
+ const restored = new Keypair(savedVeilKey);
83
+
84
+ // Derive from wallet key (same keypair as frontend login)
85
+ const derived = await Keypair.fromWalletKey('0xYOUR_WALLET_KEY');
86
+
87
+ // Derive from a raw EIP-191 signature
88
+ const fromSig = Keypair.fromSignature('0xSIGNATURE...');
89
+
90
+ // Derive from any external signer (agent framework, MPC, custodial, etc.)
91
+ const fromSigner = await Keypair.fromSigner(async (message) => {
92
+ // Sign `message` using any personal_sign provider and return the signature
93
+ return await mySigningService.personalSign(message);
94
+ });
95
+
96
+ // Get deposit key (for registration)
97
+ keypair.depositKey(); // '0x...' (130 hex chars)
98
+
99
+ // Veil private key (store securely!)
100
+ keypair.privkey; // '0x...'
101
+ ```
102
+
103
+ ### Transaction Builders
104
+
105
+ ```typescript
106
+ import {
107
+ buildRegisterTx, buildChangeDepositKeyTx, buildDepositETHTx, buildDepositTx,
108
+ buildDepositUSDCTx, buildApproveUSDCTx,
109
+ } from '@veil-cash/sdk';
110
+
111
+ // Register deposit key (first time)
112
+ const registerTx = buildRegisterTx(depositKey, ownerAddress);
113
+ // -> { to: '0x...', data: '0x...' }
114
+
115
+ // Change deposit key (must already be registered)
116
+ const changeTx = buildChangeDepositKeyTx(newDepositKey, ownerAddress);
117
+ // -> { to: '0x...', data: '0x...' }
118
+
119
+ // Deposit ETH
120
+ const depositTx = buildDepositETHTx({
121
+ depositKey: keypair.depositKey(),
122
+ amount: '0.1',
123
+ });
124
+ // -> { to: '0x...', data: '0x...', value: 100000000000000000n }
125
+
126
+ // Deposit USDC (approve + deposit)
127
+ const approveUsdcTx = buildApproveUSDCTx({ amount: '100' });
128
+ const depositUsdcTx = buildDepositUSDCTx({
129
+ depositKey: keypair.depositKey(),
130
+ amount: '100',
131
+ });
132
+
133
+ // Generic builder (routes by token)
134
+ const tx = buildDepositTx({
135
+ depositKey: keypair.depositKey(),
136
+ amount: '0.1',
137
+ token: 'ETH', // 'ETH' | 'USDC'
138
+ });
139
+ ```
140
+
141
+ ### Withdraw & Transfer
142
+
143
+ All withdraw, transfer, and merge functions accept an optional `pool` parameter (`'eth'` | `'usdc'`), defaulting to `'eth'`.
144
+
145
+ ```typescript
146
+ import { withdraw, transfer, mergeUtxos } from '@veil-cash/sdk';
147
+
148
+ // Withdraw ETH to public address
149
+ const withdrawResult = await withdraw({
150
+ amount: '0.05',
151
+ recipient: '0xRecipientAddress',
152
+ keypair,
153
+ pool: 'eth', // default
154
+ onProgress: (stage, detail) => console.log(stage, detail),
155
+ });
156
+
157
+ // Withdraw USDC
158
+ const withdrawUsdc = await withdraw({
159
+ amount: '50',
160
+ recipient: '0xRecipientAddress',
161
+ keypair,
162
+ pool: 'usdc',
163
+ });
164
+
165
+ // Merge UTXOs (consolidate small balances)
166
+ const mergeResult = await mergeUtxos({
167
+ amount: '0.1',
168
+ keypair,
169
+ pool: 'eth',
170
+ });
171
+ ```
172
+
173
+ ### Balance Queries
174
+
175
+ Balance functions accept an optional `pool` parameter (`'eth'` | `'usdc'`), defaulting to `'eth'`.
176
+
177
+ ```typescript
178
+ import { getQueueBalance, getPrivateBalance } from '@veil-cash/sdk';
179
+
180
+ // Check ETH queue balance (pending deposits)
181
+ const queueBalance = await getQueueBalance({
182
+ address: '0x...',
183
+ pool: 'eth', // default
184
+ });
185
+
186
+ // Check USDC private balance (requires keypair)
187
+ const privateBalance = await getPrivateBalance({
188
+ keypair,
189
+ pool: 'usdc',
190
+ });
191
+ ```
192
+
193
+ ### Addresses
194
+
195
+ ```typescript
196
+ import { getAddresses, getPoolAddress, getQueueAddress } from '@veil-cash/sdk';
197
+
198
+ const addresses = getAddresses();
199
+ console.log(addresses.entry); // Entry contract
200
+ console.log(addresses.ethPool); // ETH pool
201
+ console.log(addresses.usdcPool); // USDC pool
202
+
203
+ // Helper functions to resolve by pool name
204
+ console.log(getPoolAddress('eth')); // ETH pool address
205
+ console.log(getPoolAddress('usdc')); // USDC pool address
206
+ ```
207
+
208
+ ## For AI Agents
209
+
210
+ This SDK is designed to work with AI agent frameworks and external signers.
211
+
212
+ ### Non-Interactive CLI
213
+
214
+ Human-readable output is the CLI default. Use `--json` for machine-readable responses and `--unsigned` for transaction payload generation:
215
+
216
+ ```bash
217
+ # Generate keypair as JSON (no prompts, no file save)
218
+ veil init --json
219
+
220
+ # Get unsigned transaction payloads for agent signing
221
+ SIGNER_ADDRESS=0x... veil register --unsigned
222
+ veil deposit ETH 0.1 --unsigned
223
+ veil deposit USDC 100 --unsigned # Outputs approve + deposit payloads
224
+
225
+ # Request machine-readable status or balances
226
+ veil balance --json
227
+ veil balance --pool usdc --json
228
+ veil withdraw ETH 0.05 0xRecipient --json
229
+ ```
230
+
231
+ `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`.
232
+
233
+ `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.
234
+
235
+ ### Bankr Integration
236
+
237
+ #### Keypair Derivation via Bankr Sign API
238
+
239
+ Use `Keypair.fromSigner()` with Bankr's `POST /agent/sign` endpoint to derive the same keypair as the frontend:
240
+
241
+ ```typescript
242
+ import { Keypair } from '@veil-cash/sdk';
243
+
244
+ const keypair = await Keypair.fromSigner(async (message) => {
245
+ const res = await fetch('https://api.bankr.bot/agent/sign', {
246
+ method: 'POST',
247
+ headers: { 'X-API-Key': BANKR_API_KEY, 'Content-Type': 'application/json' },
248
+ body: JSON.stringify({ signatureType: 'personal_sign', message }),
249
+ });
250
+ return (await res.json()).signature;
251
+ });
252
+ ```
253
+
254
+ Or via CLI (two-step):
255
+
256
+ ```bash
257
+ # 1. Get signature from Bankr sign API
258
+ SIG=$(curl -s -X POST "https://api.bankr.bot/agent/sign" \
259
+ -H "X-API-Key: $BANKR_API_KEY" \
260
+ -H "Content-Type: application/json" \
261
+ -d "{\"signatureType\":\"personal_sign\",\"message\":\"$(node -e "const{VEIL_SIGNED_MESSAGE}=require('@veil-cash/sdk');console.log(VEIL_SIGNED_MESSAGE)")\"}" \
262
+ | jq -r '.signature')
263
+
264
+ # 2. Derive keypair from signature
265
+ veil init --signature $SIG
266
+ ```
267
+
268
+ #### Unsigned Transaction Payloads
269
+
270
+ Use `--unsigned` to get signer-compatible transaction payloads:
271
+
272
+ ```bash
273
+ SIGNER_ADDRESS=0x... veil register --unsigned
274
+ SIGNER_ADDRESS=0x... veil register --unsigned --force
275
+ veil deposit ETH 0.1 --unsigned
276
+ # {"to":"0x...","data":"0x...","value":"100000000000000000","chainId":8453}
277
+ ```
278
+
279
+ The `--unsigned` flag outputs a standard `{to, data, value, chainId}` payload compatible with any signer that accepts arbitrary transactions.
280
+ When `SIGNER_ADDRESS` is set, `veil register --unsigned` no longer requires the `--address` flag.
281
+ 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`.
282
+
283
+ ### Programmatic SDK Usage
284
+
285
+ ```typescript
286
+ import { Keypair, buildDepositETHTx, buildDepositTx, withdraw } from '@veil-cash/sdk';
287
+
288
+ // For deposits: build transaction, let agent sign via your signer
289
+ const keypair = new Keypair(veilKey);
290
+ const tx = buildDepositETHTx({
291
+ depositKey: keypair.depositKey(),
292
+ amount: '0.1',
293
+ });
294
+ // -> { to, data, value } - pass to your signer
295
+
296
+ // Generic builder works for any asset
297
+ const usdcTx = buildDepositTx({
298
+ depositKey: keypair.depositKey(),
299
+ amount: '100',
300
+ token: 'USDC',
301
+ });
302
+
303
+ // For withdrawals: SDK handles ZK proofs, submits to relayer
304
+ const result = await withdraw({
305
+ amount: '0.05',
306
+ recipient: '0xRecipient',
307
+ keypair,
308
+ pool: 'eth', // 'eth' | 'usdc'
309
+ });
310
+ // -> { success, transactionHash, blockNumber }
311
+ ```