@veil-cash/sdk 0.6.2 → 0.6.3
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 +7 -6
- package/SDK.md +18 -5
- package/dist/cli/index.cjs +227 -168
- package/dist/index.cjs +28 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -1
- package/dist/index.d.ts +38 -1
- package/dist/index.js +28 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/veil/SKILL.md +6 -4
- package/skills/veil/reference.md +5 -5
- package/src/abi.ts +8 -0
- package/src/balance.ts +48 -0
- package/src/cli/commands/deposit.ts +61 -15
- package/src/index.ts +1 -0
package/package.json
CHANGED
package/skills/veil/SKILL.md
CHANGED
|
@@ -165,7 +165,7 @@ What do you want to do?
|
|
|
165
165
|
|
|
|
166
166
|
+-- Register deposit key on-chain → veil register [--unsigned]
|
|
167
167
|
|
|
|
168
|
-
+-- Deposit ETH or USDC → veil deposit <asset> <amount> [--unsigned]
|
|
168
|
+
+-- Deposit ETH or USDC → veil deposit <asset> <amount> [--unsigned --address 0x...]
|
|
169
169
|
|
|
|
170
170
|
+-- Check balances → veil balance [queue|private] [--pool eth|usdc]
|
|
171
171
|
|
|
|
@@ -330,7 +330,9 @@ 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
|
-
|
|
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.
|
|
334
336
|
After submission, deposits go through screening / queue processing before they
|
|
335
337
|
are accepted into the private pool. This typically takes around `10-15 minutes`.
|
|
336
338
|
|
|
@@ -338,8 +340,8 @@ are accepted into the private pool. This typically takes around `10-15 minutes`.
|
|
|
338
340
|
veil deposit ETH 0.1
|
|
339
341
|
veil deposit USDC 100
|
|
340
342
|
veil deposit ETH 0.1 --json
|
|
341
|
-
veil deposit ETH 0.1 --unsigned
|
|
342
|
-
veil deposit USDC 100 --unsigned
|
|
343
|
+
veil deposit ETH 0.1 --unsigned --address 0x...
|
|
344
|
+
SIGNER_ADDRESS=0x... veil deposit USDC 100 --unsigned
|
|
343
345
|
```
|
|
344
346
|
|
|
345
347
|
Minimums:
|
package/skills/veil/reference.md
CHANGED
|
@@ -258,8 +258,8 @@ SIGNER_ADDRESS=0x... veil register --unsigned --force # Unsigned register/change
|
|
|
258
258
|
veil register --unsigned --address 0x... # Unsigned register payload (explicit address)
|
|
259
259
|
veil register --json # Register and output result as JSON
|
|
260
260
|
|
|
261
|
-
veil deposit ETH 0.1 --unsigned
|
|
262
|
-
veil deposit USDC 100 --unsigned
|
|
261
|
+
veil deposit ETH 0.1 --unsigned --address 0x... # Unsigned ETH deposit payload
|
|
262
|
+
SIGNER_ADDRESS=0x... veil deposit USDC 100 --unsigned # Unsigned USDC deposit payload(s)
|
|
263
263
|
veil deposit ETH 0.1 --json # Deposit and output result as JSON
|
|
264
264
|
|
|
265
265
|
veil balance # All pool balances
|
|
@@ -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, or waived if daily free deposits remain |
|
|
311
|
+
| USDC | 10 | Fee (0.3%) added automatically, or waived if daily free deposits remain |
|
|
312
312
|
|
|
313
|
-
The CLI amount is the **net** amount that lands in the pool. The fee is calculated on-chain and added to the transaction automatically
|
|
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.
|
|
314
314
|
|
|
315
315
|
---
|
|
316
316
|
|
package/src/abi.ts
CHANGED
|
@@ -218,6 +218,14 @@ 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
|
+
},
|
|
221
229
|
] as const;
|
|
222
230
|
|
|
223
231
|
/**
|
package/src/balance.ts
CHANGED
|
@@ -127,6 +127,54 @@ 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
|
+
|
|
130
178
|
/**
|
|
131
179
|
* Get private balance from the Pool contract
|
|
132
180
|
* Decrypts all encrypted outputs, calculates nullifiers, and checks spent status
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import { Command } from 'commander';
|
|
6
6
|
import { buildDepositETHTx, buildDepositUSDCTx, buildApproveUSDCTx } from '../../deposit.js';
|
|
7
|
+
import { getDailyFreeRemaining } from '../../balance.js';
|
|
7
8
|
import { sendTransaction, getAddress, getBalance } from '../wallet.js';
|
|
8
|
-
import { getConfig } from '../config.js';
|
|
9
|
+
import { getConfig, resolveAddress } from '../config.js';
|
|
9
10
|
import { createPublicClient, http, parseEther, parseUnits, formatEther, formatUnits } from 'viem';
|
|
10
11
|
import { base } from 'viem/chains';
|
|
11
12
|
import { handleCLIError, CLIError, ErrorCode } from '../errors.js';
|
|
@@ -13,6 +14,7 @@ import { clearProgress, createProgressReporter, printFields, printHeader, printJ
|
|
|
13
14
|
import { POOL_CONFIG, getAddresses } from '../../addresses.js';
|
|
14
15
|
import { ENTRY_ABI, ERC20_ABI } from '../../abi.js';
|
|
15
16
|
import type { TransactionData } from '../../types.js';
|
|
17
|
+
import type { WalletConfig } from '../wallet.js';
|
|
16
18
|
|
|
17
19
|
const MINIMUM_NET: Record<string, number> = {
|
|
18
20
|
ETH: 0.01,
|
|
@@ -20,13 +22,22 @@ const MINIMUM_NET: Record<string, number> = {
|
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
+
* 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
28
|
*/
|
|
26
29
|
async function getGrossAmount(
|
|
27
30
|
netWei: bigint,
|
|
31
|
+
depositor: `0x${string}`,
|
|
32
|
+
pool: 'eth' | 'usdc',
|
|
28
33
|
rpcUrl: string | undefined,
|
|
29
|
-
): Promise<{ grossWei: bigint; feeWei: bigint }> {
|
|
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
41
|
const publicClient = createPublicClient({
|
|
31
42
|
chain: base,
|
|
32
43
|
transport: http(rpcUrl),
|
|
@@ -39,7 +50,7 @@ async function getGrossAmount(
|
|
|
39
50
|
args: [netWei],
|
|
40
51
|
}) as bigint;
|
|
41
52
|
|
|
42
|
-
return { grossWei, feeWei: grossWei - netWei };
|
|
53
|
+
return { grossWei, feeWei: grossWei - netWei, dailyFreeUsed: false, dailyFreeRemaining: 0 };
|
|
43
54
|
}
|
|
44
55
|
|
|
45
56
|
const SUPPORTED_ASSETS = ['ETH', 'USDC'];
|
|
@@ -49,16 +60,19 @@ export function createDepositCommand(): Command {
|
|
|
49
60
|
.description('Deposit ETH or USDC into Veil')
|
|
50
61
|
.argument('<asset>', 'Asset to deposit (ETH or USDC)')
|
|
51
62
|
.argument('<amount>', 'Amount to deposit — this is what arrives in your Veil balance')
|
|
63
|
+
.option('--address <address>', 'Signer address (required in --unsigned mode unless SIGNER_ADDRESS or WALLET_KEY is set)')
|
|
52
64
|
.option('--unsigned', 'Output unsigned transaction payload instead of sending')
|
|
53
65
|
.option('--json', 'Output as JSON')
|
|
54
66
|
.addHelpText('after', `
|
|
55
67
|
The amount you specify is the net amount that lands in your Veil balance.
|
|
56
|
-
|
|
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.
|
|
57
70
|
|
|
58
71
|
Examples:
|
|
59
|
-
veil deposit ETH 0.1 # deposits 0.1 ETH (
|
|
60
|
-
veil deposit USDC 100 # deposits 100 USDC (
|
|
61
|
-
veil deposit ETH 0.1 --unsigned
|
|
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)
|
|
74
|
+
veil deposit ETH 0.1 --unsigned --address 0x...
|
|
75
|
+
SIGNER_ADDRESS=0x... veil deposit ETH 0.1 --unsigned
|
|
62
76
|
veil deposit ETH 0.1 --json
|
|
63
77
|
`)
|
|
64
78
|
.action(async (asset: string, amount: string, options) => {
|
|
@@ -80,15 +94,41 @@ Examples:
|
|
|
80
94
|
}
|
|
81
95
|
|
|
82
96
|
const rpcUrl = process.env.RPC_URL;
|
|
83
|
-
const
|
|
97
|
+
const pool = assetUpper.toLowerCase() as 'eth' | 'usdc';
|
|
98
|
+
const poolConfig = POOL_CONFIG[pool];
|
|
84
99
|
const netWei = assetUpper === 'ETH'
|
|
85
100
|
? parseEther(amount)
|
|
86
101
|
: parseUnits(amount, poolConfig.decimals);
|
|
87
102
|
|
|
88
103
|
const progress = createProgressReporter();
|
|
89
|
-
progress('Calculating fee...');
|
|
90
104
|
|
|
91
|
-
|
|
105
|
+
let config: WalletConfig | null = null;
|
|
106
|
+
let address: `0x${string}`;
|
|
107
|
+
let feeRpcUrl = rpcUrl;
|
|
108
|
+
|
|
109
|
+
if (options.unsigned) {
|
|
110
|
+
const resolved = resolveAddress({ address: options.address }, { required: true });
|
|
111
|
+
if (!resolved) {
|
|
112
|
+
throw new CLIError(
|
|
113
|
+
ErrorCode.WALLET_KEY_MISSING,
|
|
114
|
+
'Must provide --address, set SIGNER_ADDRESS, or set WALLET_KEY env.',
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
address = resolved.address;
|
|
118
|
+
} else {
|
|
119
|
+
config = getConfig(options);
|
|
120
|
+
address = getAddress(config.privateKey);
|
|
121
|
+
feeRpcUrl = config.rpcUrl;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
progress('Checking deposit fee...');
|
|
125
|
+
|
|
126
|
+
const { grossWei, feeWei, dailyFreeUsed, dailyFreeRemaining } = await getGrossAmount(
|
|
127
|
+
netWei,
|
|
128
|
+
address,
|
|
129
|
+
pool,
|
|
130
|
+
feeRpcUrl,
|
|
131
|
+
);
|
|
92
132
|
const grossStr = assetUpper === 'ETH'
|
|
93
133
|
? formatEther(grossWei)
|
|
94
134
|
: formatUnits(grossWei, poolConfig.decimals);
|
|
@@ -140,8 +180,9 @@ Examples:
|
|
|
140
180
|
return;
|
|
141
181
|
}
|
|
142
182
|
|
|
143
|
-
|
|
144
|
-
|
|
183
|
+
if (!config) {
|
|
184
|
+
throw new CLIError(ErrorCode.WALLET_KEY_MISSING, 'WALLET_KEY env var required. Set it before running this command.');
|
|
185
|
+
}
|
|
145
186
|
|
|
146
187
|
if (assetUpper === 'ETH') {
|
|
147
188
|
progress('Checking balance...');
|
|
@@ -203,6 +244,7 @@ Examples:
|
|
|
203
244
|
asset: assetUpper,
|
|
204
245
|
amount,
|
|
205
246
|
fee: feeStr,
|
|
247
|
+
dailyFreeUsed,
|
|
206
248
|
totalSent: grossStr,
|
|
207
249
|
blockNumber: result.receipt.blockNumber.toString(),
|
|
208
250
|
};
|
|
@@ -212,11 +254,15 @@ Examples:
|
|
|
212
254
|
return;
|
|
213
255
|
}
|
|
214
256
|
|
|
257
|
+
const feeLabel = dailyFreeUsed
|
|
258
|
+
? `0 ${assetUpper} (free — ${dailyFreeRemaining} remaining today)`
|
|
259
|
+
: `${feeStr} ${assetUpper} (0.3%)`;
|
|
260
|
+
|
|
215
261
|
printHeader('Deposit Submitted');
|
|
216
262
|
printFields([
|
|
217
263
|
{ label: 'Asset', value: assetUpper },
|
|
218
264
|
{ label: 'Amount', value: `${amount} ${assetUpper}` },
|
|
219
|
-
{ label: 'Fee', value:
|
|
265
|
+
{ label: 'Fee', value: feeLabel },
|
|
220
266
|
{ label: 'Total sent', value: `${grossStr} ${assetUpper}` },
|
|
221
267
|
{ label: 'From', value: address },
|
|
222
268
|
{ label: 'Transaction', value: txUrl(result.hash) },
|