@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veil-cash/sdk",
3
- "version": "0.6.4",
3
+ "version": "0.7.0",
4
4
  "description": "SDK and CLI for interacting with Veil Cash privacy pools - keypair generation, deposits, and status checking",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -48,6 +48,8 @@
48
48
  "url": "https://github.com/veildotcash/veildotcash-sdk"
49
49
  },
50
50
  "dependencies": {
51
+ "@x402/core": "2.14.0",
52
+ "@x402/evm": "2.14.0",
51
53
  "buffer": "^6.0.3",
52
54
  "circomlib": "github:tornadocash/circomlib#d20d53411d1bef61f38c99a8b36d5d0cc4836aa1",
53
55
  "commander": "^14.0.2",
@@ -330,9 +330,7 @@ Important:
330
330
  - If not yet registered, returns a normal `register` payload.
331
331
 
332
332
  Deposits treat the CLI amount as the **net** amount that lands in the pool.
333
- Each address gets a configurable number of fee-free deposits per UTC day.
334
- The CLI checks automatically — if free slots remain the fee is waived;
335
- otherwise the `0.3%` protocol fee is calculated on-chain and added.
333
+ A `0.3%` protocol fee is calculated on-chain and added on top.
336
334
  After submission, deposits go through screening / queue processing before they
337
335
  are accepted into the private pool. This typically takes around `10-15 minutes`.
338
336
 
@@ -307,10 +307,10 @@ Common codes: `VEIL_KEY_MISSING`, `WALLET_KEY_MISSING`, `DEPOSIT_KEY_MISSING`,
307
307
 
308
308
  | Asset | Minimum (net) | Notes |
309
309
  |-------|--------------|-------|
310
- | ETH | 0.01 | Fee (0.3%) added automatically, or waived if daily free deposits remain |
311
- | USDC | 10 | Fee (0.3%) added automatically, or waived if daily free deposits remain |
310
+ | ETH | 0.01 | Fee (0.3%) added automatically |
311
+ | USDC | 10 | Fee (0.3%) added automatically |
312
312
 
313
- The CLI amount is the **net** amount that lands in the pool. The CLI checks `getDailyFreeRemaining` on the queue contract — if the user has free slots left today the fee is skipped; otherwise the 0.3% fee is calculated on-chain and added to the transaction automatically.
313
+ The CLI amount is the **net** amount that lands in the pool. A 0.3% protocol fee is calculated on-chain and added to the transaction automatically.
314
314
 
315
315
  ---
316
316
 
package/src/abi.ts CHANGED
@@ -218,14 +218,6 @@ export const QUEUE_ABI = [
218
218
  stateMutability: 'view',
219
219
  type: 'function',
220
220
  },
221
- // Get remaining daily free deposits for an address (V3+)
222
- {
223
- inputs: [{ name: '_depositor', type: 'address' }],
224
- name: 'getDailyFreeRemaining',
225
- outputs: [{ name: 'remaining', type: 'uint256' }],
226
- stateMutability: 'view',
227
- type: 'function',
228
- },
229
221
  ] as const;
230
222
 
231
223
  /**
package/src/balance.ts CHANGED
@@ -127,54 +127,6 @@ export async function getQueueBalance(options: {
127
127
  };
128
128
  }
129
129
 
130
- /**
131
- * Get remaining daily free deposits for an address.
132
- * Returns 0 if the queue contract has not been upgraded to V3 yet
133
- * or if the daily free feature is disabled.
134
- *
135
- * @param options - Query options
136
- * @param options.address - Depositor address to check
137
- * @param options.pool - Pool identifier ('eth' or 'usdc', default: 'eth')
138
- * @param options.rpcUrl - Optional RPC URL
139
- * @returns Number of free deposits remaining today
140
- *
141
- * @example
142
- * ```typescript
143
- * const remaining = await getDailyFreeRemaining({
144
- * address: '0x...',
145
- * pool: 'eth',
146
- * });
147
- * console.log(`Free deposits left today: ${remaining}`);
148
- * ```
149
- */
150
- export async function getDailyFreeRemaining(options: {
151
- address: `0x${string}`;
152
- pool?: RelayPool;
153
- rpcUrl?: string;
154
- }): Promise<number> {
155
- const { address, pool = 'eth', rpcUrl } = options;
156
- const queueAddress = getQueueAddress(pool);
157
-
158
- const publicClient = createPublicClient({
159
- chain: base,
160
- transport: http(rpcUrl),
161
- });
162
-
163
- try {
164
- const remaining = await publicClient.readContract({
165
- address: queueAddress,
166
- abi: QUEUE_ABI,
167
- functionName: 'getDailyFreeRemaining',
168
- args: [address],
169
- }) as bigint;
170
-
171
- return Number(remaining);
172
- } catch {
173
- // V2 contracts don't have this function — treat as 0 remaining
174
- return 0;
175
- }
176
- }
177
-
178
130
  /**
179
131
  * Get private balance from the Pool contract
180
132
  * Decrypts all encrypted outputs, calculates nullifiers, and checks spent status
@@ -4,7 +4,6 @@
4
4
 
5
5
  import { Command } from 'commander';
6
6
  import { buildDepositETHTx, buildDepositUSDCTx, buildApproveUSDCTx } from '../../deposit.js';
7
- import { getDailyFreeRemaining } from '../../balance.js';
8
7
  import { sendTransaction, getAddress, getBalance } from '../wallet.js';
9
8
  import { getConfig, resolveAddress } from '../config.js';
10
9
  import { createPublicClient, http, parseEther, parseUnits, formatEther, formatUnits } from 'viem';
@@ -23,21 +22,12 @@ const MINIMUM_NET: Record<string, number> = {
23
22
 
24
23
  /**
25
24
  * Compute the gross amount and fee for a deposit.
26
- * Checks daily free deposit availability first if the user has
27
- * free slots remaining the fee is waived and gross === net.
25
+ * The 0.3% protocol fee is always added on top of the net amount.
28
26
  */
29
27
  async function getGrossAmount(
30
28
  netWei: bigint,
31
- depositor: `0x${string}`,
32
- pool: 'eth' | 'usdc',
33
29
  rpcUrl: string | undefined,
34
- ): Promise<{ grossWei: bigint; feeWei: bigint; dailyFreeUsed: boolean; dailyFreeRemaining: number }> {
35
- const freeRemaining = await getDailyFreeRemaining({ address: depositor, pool, rpcUrl });
36
-
37
- if (freeRemaining > 0) {
38
- return { grossWei: netWei, feeWei: 0n, dailyFreeUsed: true, dailyFreeRemaining: freeRemaining - 1 };
39
- }
40
-
30
+ ): Promise<{ grossWei: bigint; feeWei: bigint }> {
41
31
  const publicClient = createPublicClient({
42
32
  chain: base,
43
33
  transport: http(rpcUrl),
@@ -50,7 +40,7 @@ async function getGrossAmount(
50
40
  args: [netWei],
51
41
  }) as bigint;
52
42
 
53
- return { grossWei, feeWei: grossWei - netWei, dailyFreeUsed: false, dailyFreeRemaining: 0 };
43
+ return { grossWei, feeWei: grossWei - netWei };
54
44
  }
55
45
 
56
46
  const SUPPORTED_ASSETS = ['ETH', 'USDC'];
@@ -65,12 +55,11 @@ export function createDepositCommand(): Command {
65
55
  .option('--json', 'Output as JSON')
66
56
  .addHelpText('after', `
67
57
  The amount you specify is the net amount that lands in your Veil balance.
68
- A 0.3% protocol fee is normally added on top, but each address gets
69
- free daily deposits (fee waived). The CLI checks automatically.
58
+ A 0.3% protocol fee is added on top.
70
59
 
71
60
  Examples:
72
- veil deposit ETH 0.1 # deposits 0.1 ETH (free or ~0.1003 ETH)
73
- veil deposit USDC 100 # deposits 100 USDC (free or ~100.30 USDC)
61
+ veil deposit ETH 0.1 # deposits 0.1 ETH (~0.1003 ETH sent)
62
+ veil deposit USDC 100 # deposits 100 USDC (~100.30 USDC sent)
74
63
  veil deposit ETH 0.1 --unsigned --address 0x...
75
64
  SIGNER_ADDRESS=0x... veil deposit ETH 0.1 --unsigned
76
65
  veil deposit ETH 0.1 --json
@@ -123,12 +112,7 @@ Examples:
123
112
 
124
113
  progress('Checking deposit fee...');
125
114
 
126
- const { grossWei, feeWei, dailyFreeUsed, dailyFreeRemaining } = await getGrossAmount(
127
- netWei,
128
- address,
129
- pool,
130
- feeRpcUrl,
131
- );
115
+ const { grossWei, feeWei } = await getGrossAmount(netWei, feeRpcUrl);
132
116
  const grossStr = assetUpper === 'ETH'
133
117
  ? formatEther(grossWei)
134
118
  : formatUnits(grossWei, poolConfig.decimals);
@@ -244,7 +228,6 @@ Examples:
244
228
  asset: assetUpper,
245
229
  amount,
246
230
  fee: feeStr,
247
- dailyFreeUsed,
248
231
  totalSent: grossStr,
249
232
  blockNumber: result.receipt.blockNumber.toString(),
250
233
  };
@@ -254,9 +237,7 @@ Examples:
254
237
  return;
255
238
  }
256
239
 
257
- const feeLabel = dailyFreeUsed
258
- ? `0 ${assetUpper} (free — ${dailyFreeRemaining} remaining today)`
259
- : `${feeStr} ${assetUpper} (0.3%)`;
240
+ const feeLabel = `${feeStr} ${assetUpper} (0.3%)`;
260
241
 
261
242
  printHeader('Deposit Submitted');
262
243
  printFields([
package/src/compat.ts ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * CJS/ESM interop for legacy dependencies that only ship CommonJS.
3
+ *
4
+ * eth-sig-util sets __esModule: true but has no default export — only named
5
+ * exports. circomlib uses module.exports = { poseidon, ... }.
6
+ *
7
+ * Using namespace imports (import * as X) works reliably across both tsup's
8
+ * CJS and ESM outputs, and browser bundlers (webpack/vite) handle them correctly.
9
+ */
10
+
11
+ import * as _ethSigUtil from 'eth-sig-util';
12
+ import * as _circomlib from 'circomlib';
13
+
14
+ function resolveInterop<T>(mod: T): T {
15
+ if (mod && typeof mod === 'object' && 'default' in (mod as object)) {
16
+ const defaultVal = (mod as unknown as { default: T }).default;
17
+ if (defaultVal != null) return defaultVal;
18
+ }
19
+ return mod;
20
+ }
21
+
22
+ export const ethSigUtil = resolveInterop(_ethSigUtil);
23
+ export const circomlib = resolveInterop(_circomlib);
@@ -6,8 +6,9 @@ declare module 'ffjavascript' {
6
6
  }
7
7
 
8
8
  declare module 'circomlib' {
9
+ export const poseidon: (items: Array<bigint | string | number>) => { toString: () => string };
9
10
  const circomlib: {
10
- poseidon: (items: Array<bigint | string | number>) => { toString: () => string };
11
+ poseidon: typeof poseidon;
11
12
  };
12
13
  export default circomlib;
13
14
  }
@@ -15,14 +16,18 @@ declare module 'circomlib' {
15
16
  declare module 'eth-sig-util' {
16
17
  import type { EncryptedMessage } from './types.js';
17
18
 
19
+ export function getEncryptionPublicKey(privateKey: string): string;
20
+ export function encrypt(
21
+ receiverPublicKey: string,
22
+ msgParams: { data: string },
23
+ version: 'x25519-xsalsa20-poly1305'
24
+ ): EncryptedMessage;
25
+ export function decrypt(encryptedData: EncryptedMessage, receiverPrivateKey: string): string;
26
+
18
27
  const ethSigUtil: {
19
- getEncryptionPublicKey: (privateKey: string) => string;
20
- encrypt: (
21
- receiverPublicKey: string,
22
- msgParams: { data: string },
23
- version: 'x25519-xsalsa20-poly1305'
24
- ) => EncryptedMessage;
25
- decrypt: (encryptedData: EncryptedMessage, receiverPrivateKey: string) => string;
28
+ getEncryptionPublicKey: typeof getEncryptionPublicKey;
29
+ encrypt: typeof encrypt;
30
+ decrypt: typeof decrypt;
26
31
  };
27
32
  export default ethSigUtil;
28
33
  }
package/src/index.ts CHANGED
@@ -53,7 +53,6 @@ export {
53
53
  export {
54
54
  getQueueBalance,
55
55
  getPrivateBalance,
56
- getDailyFreeRemaining,
57
56
  } from './balance.js';
58
57
  export type { ProgressCallback } from './balance.js';
59
58
 
@@ -64,6 +63,27 @@ export {
64
63
  selectUtxosForWithdraw,
65
64
  } from './withdraw.js';
66
65
 
66
+ // x402 payment helpers
67
+ export {
68
+ deriveX402PayerKey,
69
+ deriveX402PayerAddress,
70
+ getX402PayerBalances,
71
+ payX402Resource,
72
+ quoteX402Resource,
73
+ selectBaseUsdcExactRequirement,
74
+ usdcAtomicToDecimalString,
75
+ usdcDecimalToAtomic,
76
+ } from './x402.js';
77
+ export type {
78
+ GetX402PayerBalancesOptions,
79
+ PayX402ResourceOptions,
80
+ PayX402ResourceResult,
81
+ QuoteX402ResourceOptions,
82
+ QuoteX402ResourceResult,
83
+ X402PayerBalance,
84
+ X402PayerFundedInfo,
85
+ } from './x402.js';
86
+
67
87
  // Transfer functions
68
88
  export {
69
89
  transfer,
package/src/keypair.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  import { ethers } from 'ethers';
7
7
  import { Buffer } from 'buffer';
8
8
  import { privateKeyToAccount } from 'viem/accounts';
9
- import ethSigUtil from 'eth-sig-util';
9
+ import { ethSigUtil } from './compat.js';
10
10
  import { poseidonHash, toFixedHex } from './utils.js';
11
11
  import type { EncryptedMessage } from './types.js';
12
12
 
package/src/types.ts CHANGED
@@ -155,9 +155,12 @@ export interface RelayExtData {
155
155
  */
156
156
  export interface RelayMetadata {
157
157
  amount?: string;
158
+ amountAtomic?: string;
158
159
  recipient?: string;
159
160
  inputUtxoCount?: number;
160
161
  outputUtxoCount?: number;
162
+ x402?: boolean;
163
+ payerIndex?: string;
161
164
  }
162
165
 
163
166
  /**
@@ -228,6 +231,8 @@ export interface BuildWithdrawProofOptions {
228
231
  pool?: RelayPool;
229
232
  /** Optional RPC URL */
230
233
  rpcUrl?: string;
234
+ /** Optional relay URL */
235
+ relayUrl?: string;
231
236
  /**
232
237
  * Optional proving key directory/base URL or resolver.
233
238
  *
package/src/utils.ts CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { ethers } from 'ethers';
7
7
  import { Buffer } from 'buffer';
8
- import circomlib from 'circomlib';
8
+ import { circomlib } from './compat.js';
9
9
 
10
10
  const poseidon = circomlib.poseidon;
11
11
 
@@ -44,7 +44,9 @@ export const randomBN = (nbytes: number = 31): bigint => {
44
44
  }).crypto;
45
45
 
46
46
  if (!cryptoApi?.getRandomValues) {
47
- throw new Error('Secure random number generation is unavailable in this runtime');
47
+ throw new Error(
48
+ 'Secure random number generation is unavailable. Provide globalThis.crypto.getRandomValues in this runtime.'
49
+ );
48
50
  }
49
51
 
50
52
  const bytes = cryptoApi.getRandomValues(new Uint8Array(nbytes));
package/src/withdraw.ts CHANGED
@@ -272,7 +272,7 @@ export async function buildWithdrawProof(
272
272
  export async function withdraw(
273
273
  options: BuildWithdrawProofOptions
274
274
  ): Promise<WithdrawResult> {
275
- const { amount, recipient, pool = 'eth', onProgress } = options;
275
+ const { amount, recipient, pool = 'eth', onProgress, relayUrl } = options;
276
276
 
277
277
  // Build the proof
278
278
  const proof = await buildWithdrawProof(options);
@@ -282,6 +282,7 @@ export async function withdraw(
282
282
  const relayResult = await submitRelay({
283
283
  type: 'withdraw',
284
284
  pool,
285
+ relayUrl,
285
286
  proofArgs: proof.proofArgs,
286
287
  extData: proof.extData,
287
288
  metadata: {