@veil-cash/sdk 0.6.4 → 0.7.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 +47 -5
- package/SDK.md +77 -11
- package/dist/cli/index.cjs +229 -237
- package/dist/index.cjs +386 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +131 -38
- package/dist/index.d.ts +131 -38
- package/dist/index.js +355 -40
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/skills/veil/SKILL.md +1 -3
- package/skills/veil/reference.md +3 -3
- package/src/abi.ts +0 -8
- package/src/balance.ts +0 -48
- package/src/cli/commands/deposit.ts +8 -27
- package/src/compat.ts +23 -0
- package/src/ffjavascript.d.ts +13 -8
- package/src/index.ts +21 -1
- package/src/keypair.ts +1 -1
- package/src/types.ts +5 -0
- package/src/utils.ts +4 -2
- package/src/withdraw.ts +2 -1
- package/src/x402.ts +546 -0
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ SDK and CLI for interacting with [Veil Cash](https://veil.cash) privacy pools on
|
|
|
8
8
|
|
|
9
9
|
Generate keypairs, register, deposit, withdraw, transfer, and merge ETH and USDC privately.
|
|
10
10
|
|
|
11
|
+
`0.7.0` adds Coinbase-compatible x402 payments from private USDC balances via deterministic fresh payer EOAs.
|
|
12
|
+
|
|
11
13
|
`0.6.2` adds `mergeSubaccount` — transfer a subaccount's private pool balance back to the main wallet via a ZK proof. Also adds `veil subaccount merge` CLI command.
|
|
12
14
|
|
|
13
15
|
`0.6.0` adds SDK-first subaccount support for deterministic slot derivation, forwarder status, relay-backed deploy/sweep, and direct recovery.
|
|
@@ -91,7 +93,10 @@ veil subaccount sweep --slot 0 --asset eth
|
|
|
91
93
|
veil subaccount merge --slot 0 --pool eth
|
|
92
94
|
veil subaccount recover --slot 0 --asset usdc --to 0xRecipientAddress --amount 25
|
|
93
95
|
|
|
94
|
-
# 9.
|
|
96
|
+
# 9. Pay an x402 resource from private USDC in application code
|
|
97
|
+
# See SDK.md for payX402Resource().
|
|
98
|
+
|
|
99
|
+
# 10. Use JSON or unsigned modes when you need automation
|
|
95
100
|
veil status --json
|
|
96
101
|
veil deposit ETH 0.1 --unsigned --address 0x...
|
|
97
102
|
veil subaccount status --slot 0 --json
|
|
@@ -142,11 +147,11 @@ SIGNER_ADDRESS=0x... veil register --unsigned
|
|
|
142
147
|
|
|
143
148
|
In `--unsigned` mode, `--address` is optional when `SIGNER_ADDRESS` is set. `veil register --force` checks on-chain state first and emits a `changeDepositKey` payload only if the address is already registered; otherwise it emits a normal `register` payload.
|
|
144
149
|
|
|
145
|
-
Deposit ETH or USDC into Veil. The amount you specify is the **net** amount that arrives in your Veil balance. A 0.3% protocol fee is
|
|
150
|
+
Deposit ETH or USDC into Veil. The amount you specify is the **net** amount that arrives in your Veil balance. A 0.3% protocol fee is added on top:
|
|
146
151
|
|
|
147
152
|
```bash
|
|
148
|
-
veil deposit ETH 0.1 # 0.1 ETH lands in pool (
|
|
149
|
-
veil deposit USDC 100 # 100 USDC lands in pool (
|
|
153
|
+
veil deposit ETH 0.1 # 0.1 ETH lands in pool (~0.1003 ETH sent)
|
|
154
|
+
veil deposit USDC 100 # 100 USDC lands in pool (~100.30 USDC sent)
|
|
150
155
|
veil deposit ETH 0.1 --json
|
|
151
156
|
veil deposit ETH 0.1 --unsigned --address 0x...
|
|
152
157
|
SIGNER_ADDRESS=0x... veil deposit ETH 0.1 --unsigned
|
|
@@ -205,6 +210,43 @@ veil merge USDC 100
|
|
|
205
210
|
veil merge ETH 0.1 --json
|
|
206
211
|
```
|
|
207
212
|
|
|
213
|
+
Pay a Coinbase-compatible x402 resource from private USDC:
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { payX402Resource } from '@veil-cash/sdk';
|
|
217
|
+
|
|
218
|
+
const result = await payX402Resource({
|
|
219
|
+
url: 'https://merchant.example/paid-resource',
|
|
220
|
+
rootPrivateKey: process.env.VEIL_KEY as `0x${string}`,
|
|
221
|
+
payerIndex: 0n,
|
|
222
|
+
maxPayment: '0.10', // reject if the resource demands more than 0.10 USDC
|
|
223
|
+
relayUrl: process.env.X402_RELAY_URL,
|
|
224
|
+
rpcUrl: process.env.RPC_URL,
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
console.log(result.response.status, result.payerAddress);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
The helper withdraws the exact x402 amount to a deterministic fresh payer EOA,
|
|
231
|
+
then signs a standard x402 v2 Base USDC `exact` payment from that EOA. Use a
|
|
232
|
+
new `payerIndex` per payment. Pass `maxPayment` (a decimal USDC string) to cap
|
|
233
|
+
exposure; the payment is rejected before any funds move if the requirement
|
|
234
|
+
exceeds the cap. The withdrawal and payment legs are public and can be correlated
|
|
235
|
+
by amount and timing, but the source private balance remains hidden.
|
|
236
|
+
|
|
237
|
+
Use `quoteX402Resource({ url, rpcUrl, maxPayment, init })` to probe a resource
|
|
238
|
+
for its price and payment requirement without funding a payer or paying. It
|
|
239
|
+
returns the parsed requirement for a supported `402` or the raw status/body
|
|
240
|
+
otherwise.
|
|
241
|
+
|
|
242
|
+
If a payment is funded but delivery fails, the USDC stays on the payer EOA. Retry
|
|
243
|
+
with `reuseExistingBalance: true` and the same `payerIndex` to pay from that
|
|
244
|
+
balance without a second withdrawal; it throws if the balance is insufficient.
|
|
245
|
+
|
|
246
|
+
To surface funds left on a payer after a failed payment, use
|
|
247
|
+
`getX402PayerBalances({ rootPrivateKey, startIndex, count, nonZeroOnly })`, which
|
|
248
|
+
returns the Base USDC balance of each derived payer EOA. It is read-only.
|
|
249
|
+
|
|
208
250
|
### Subaccounts
|
|
209
251
|
|
|
210
252
|
Subaccounts are deterministic child slots derived from your main `VEIL_KEY`:
|
|
@@ -297,7 +339,7 @@ The CLI is the main entrypoint for most users. If you are integrating Veil progr
|
|
|
297
339
|
2. **Derive Keypair**: Run `veil init` to derive and save your Veil keypair
|
|
298
340
|
3. **Register**: Run `veil register` to link your deposit key on-chain (one-time)
|
|
299
341
|
4. **Check Status**: Run `veil status` to verify your setup
|
|
300
|
-
5. **Deposit**: Run `veil deposit <asset> <amount>` — the amount is what lands in your balance (e.g., `veil deposit ETH 0.1` deposits 0.1 ETH;
|
|
342
|
+
5. **Deposit**: Run `veil deposit <asset> <amount>` — the amount is what lands in your balance (e.g., `veil deposit ETH 0.1` deposits 0.1 ETH; a 0.3% protocol fee is added on top automatically)
|
|
301
343
|
6. **Wait**: The Veil deposit engine processes your deposit
|
|
302
344
|
7. **Done**: Your deposit is accepted into the privacy pool
|
|
303
345
|
|
package/SDK.md
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
Keypair, buildRegisterTx, buildDepositETHTx,
|
|
12
12
|
buildDepositUSDCTx, buildApproveUSDCTx,
|
|
13
13
|
withdraw, transfer, getSubaccountStatus, mergeSubaccount,
|
|
14
|
+
payX402Resource,
|
|
14
15
|
} from '@veil-cash/sdk';
|
|
15
16
|
import { createWalletClient, http } from 'viem';
|
|
16
17
|
import { base } from 'viem/chains';
|
|
@@ -72,6 +73,14 @@ const subaccount = await getSubaccountStatus({
|
|
|
72
73
|
});
|
|
73
74
|
console.log(subaccount.slot.forwarderAddress);
|
|
74
75
|
|
|
76
|
+
// 8. Pay an x402 resource from private USDC
|
|
77
|
+
const paid = await payX402Resource({
|
|
78
|
+
url: 'https://merchant.example/paid-resource',
|
|
79
|
+
rootPrivateKey: keypair.privkey as `0x${string}`,
|
|
80
|
+
payerIndex: 0n,
|
|
81
|
+
relayUrl: process.env.X402_RELAY_URL,
|
|
82
|
+
});
|
|
83
|
+
console.log(paid.response.status, paid.payerAddress);
|
|
75
84
|
```
|
|
76
85
|
|
|
77
86
|
## SDK API Reference
|
|
@@ -109,10 +118,9 @@ keypair.privkey; // '0x...'
|
|
|
109
118
|
|
|
110
119
|
### Transaction Builders
|
|
111
120
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
> user has free slots, pass the net amount directly (no fee markup needed).
|
|
121
|
+
The CLI treats deposit amounts as net amounts and adds the 0.3% protocol fee
|
|
122
|
+
automatically. The low-level transaction builders use the amount you pass as the
|
|
123
|
+
gross amount sent to the Entry contract.
|
|
116
124
|
|
|
117
125
|
```typescript
|
|
118
126
|
import {
|
|
@@ -182,6 +190,70 @@ const mergeResult = await mergeUtxos({
|
|
|
182
190
|
});
|
|
183
191
|
```
|
|
184
192
|
|
|
193
|
+
### x402 Payments
|
|
194
|
+
|
|
195
|
+
`payX402Resource()` pays standard x402 v2 Base USDC `exact` resources from a
|
|
196
|
+
private Veil USDC balance while remaining compatible with Coinbase-facilitated
|
|
197
|
+
merchants.
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
import {
|
|
201
|
+
deriveX402PayerAddress,
|
|
202
|
+
payX402Resource,
|
|
203
|
+
usdcAtomicToDecimalString,
|
|
204
|
+
} from '@veil-cash/sdk';
|
|
205
|
+
|
|
206
|
+
const payerAddress = deriveX402PayerAddress(
|
|
207
|
+
process.env.VEIL_KEY as `0x${string}`,
|
|
208
|
+
42n,
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
const amount = usdcAtomicToDecimalString('1000'); // "0.001"
|
|
212
|
+
|
|
213
|
+
const result = await payX402Resource({
|
|
214
|
+
url: 'https://merchant.example/paid-resource',
|
|
215
|
+
rootPrivateKey: process.env.VEIL_KEY as `0x${string}`,
|
|
216
|
+
payerIndex: 42n,
|
|
217
|
+
maxPayment: '0.10', // cap exposure; reject if the resource demands more
|
|
218
|
+
relayUrl: process.env.X402_RELAY_URL,
|
|
219
|
+
rpcUrl: process.env.RPC_URL,
|
|
220
|
+
onProgress: (stage, detail) => console.log(stage, detail),
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
console.log({
|
|
224
|
+
status: result.response.status,
|
|
225
|
+
payerAddress: result.payerAddress,
|
|
226
|
+
relayTx: result.relayTransactionHash,
|
|
227
|
+
paymentTx: result.paymentTransactionHash,
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
The payer key uses the `veil-x402-payer` derivation domain, separate from
|
|
232
|
+
subaccounts. Use a fresh, persisted `payerIndex` for each payment. Set
|
|
233
|
+
`maxPayment` (a decimal USDC string) to cap exposure; the payment is rejected
|
|
234
|
+
before any funds move if the requirement exceeds the cap. The helper currently
|
|
235
|
+
supports x402 v2 `exact` requirements on Base mainnet USDC only; it rejects other
|
|
236
|
+
assets, networks, and schemes.
|
|
237
|
+
|
|
238
|
+
`quoteX402Resource({ url, rpcUrl, maxPayment, init })` probes a resource without
|
|
239
|
+
funding a payer or signing a payment. For a supported `402` it returns the price
|
|
240
|
+
and requirement (`amount`, `amountAtomic`, `payTo`, `network`, `asset`, and
|
|
241
|
+
`exceedsMax` when `maxPayment` is set); for any other status it returns the raw
|
|
242
|
+
`status` and parsed `body`. Use it to validate a request and confirm cost before
|
|
243
|
+
committing a withdrawal. A merchant that validates the request body only after
|
|
244
|
+
payment will still return `402` here, so a quote cannot catch post-payment errors.
|
|
245
|
+
|
|
246
|
+
To retry a payment whose funding succeeded but whose delivery failed (the USDC is
|
|
247
|
+
still on the payer EOA), pass `reuseExistingBalance: true` with the same
|
|
248
|
+
`payerIndex`. When the payer already holds at least the required amount,
|
|
249
|
+
`payX402Resource` skips the withdrawal and pays directly from that balance
|
|
250
|
+
(`relayTransactionHash` is empty); it throws if the balance is insufficient.
|
|
251
|
+
|
|
252
|
+
`getX402PayerBalances({ rootPrivateKey, startIndex, count, nonZeroOnly })`
|
|
253
|
+
inspects the Base USDC balance held by each derived payer EOA, which is useful
|
|
254
|
+
for surfacing funds left on a payer after a failed payment. It is read-only and
|
|
255
|
+
does not move funds.
|
|
256
|
+
|
|
185
257
|
### Browser Proof Generation
|
|
186
258
|
|
|
187
259
|
`withdraw()`, `transfer()`, `mergeUtxos()`, `mergeSubaccount()`, `buildWithdrawProof()`,
|
|
@@ -232,7 +304,7 @@ such as `circomlib`, `eth-sig-util`, and `fixed-merkle-tree`.
|
|
|
232
304
|
Balance functions accept an optional `pool` parameter (`'eth'` | `'usdc'`), defaulting to `'eth'`.
|
|
233
305
|
|
|
234
306
|
```typescript
|
|
235
|
-
import { getQueueBalance, getPrivateBalance
|
|
307
|
+
import { getQueueBalance, getPrivateBalance } from '@veil-cash/sdk';
|
|
236
308
|
|
|
237
309
|
// Check ETH queue balance (pending deposits)
|
|
238
310
|
const queueBalance = await getQueueBalance({
|
|
@@ -246,12 +318,6 @@ const privateBalance = await getPrivateBalance({
|
|
|
246
318
|
pool: 'usdc',
|
|
247
319
|
});
|
|
248
320
|
|
|
249
|
-
// Check how many fee-free deposits the user has left today
|
|
250
|
-
const freeRemaining = await getDailyFreeRemaining({
|
|
251
|
-
address: '0x...',
|
|
252
|
-
pool: 'eth', // default
|
|
253
|
-
});
|
|
254
|
-
// freeRemaining: number — 0 when all free slots are used or the feature is disabled
|
|
255
321
|
```
|
|
256
322
|
|
|
257
323
|
### Subaccounts
|