@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veil-cash/sdk",
|
|
3
|
-
"version": "0.
|
|
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",
|
package/skills/veil/SKILL.md
CHANGED
|
@@ -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
|
-
|
|
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
|
|
package/skills/veil/reference.md
CHANGED
|
@@ -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
|
|
311
|
-
| USDC | 10 | Fee (0.3%) added automatically
|
|
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.
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
73
|
-
veil deposit USDC 100 # deposits 100 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
|
|
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 =
|
|
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);
|
package/src/ffjavascript.d.ts
CHANGED
|
@@ -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:
|
|
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:
|
|
20
|
-
encrypt:
|
|
21
|
-
|
|
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 '
|
|
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 '
|
|
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(
|
|
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: {
|