@veil-cash/sdk 0.1.0 → 0.2.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/LICENSE +21 -0
- package/README.md +81 -29
- package/dist/cli/index.cjs +94 -4
- package/package.json +1 -1
- package/src/cli/commands/deposit.ts +7 -1
- package/src/cli/commands/status.ts +129 -0
- package/src/cli/commands/transfer.ts +14 -2
- package/src/cli/commands/withdraw.ts +7 -1
- package/src/cli/index.ts +13 -10
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Veil Cash
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# @veil-cash/sdk
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@veil-cash/sdk)
|
|
4
|
+
[](https://www.npmjs.com/package/@veil-cash/sdk)
|
|
5
|
+
[](https://github.com/veildotcash/veildotcash-sdk/blob/main/LICENSE)
|
|
6
|
+
|
|
3
7
|
SDK and CLI for interacting with [Veil Cash](https://veil.cash) privacy pools on Base.
|
|
4
8
|
|
|
5
|
-
Generate keypairs, register, deposit, withdraw, and
|
|
9
|
+
Generate keypairs, register, deposit, withdraw, transfer, and merge ETH privately.
|
|
6
10
|
|
|
7
11
|
## Installation
|
|
8
12
|
|
|
@@ -31,17 +35,23 @@ export WALLET_KEY=0x...
|
|
|
31
35
|
# 3. Register your deposit key (one-time)
|
|
32
36
|
veil register
|
|
33
37
|
|
|
34
|
-
# 4.
|
|
35
|
-
veil
|
|
38
|
+
# 4. Check your setup
|
|
39
|
+
veil status
|
|
40
|
+
|
|
41
|
+
# 5. Deposit ETH
|
|
42
|
+
veil deposit ETH 0.1
|
|
36
43
|
|
|
37
|
-
#
|
|
44
|
+
# 6. Check your balance
|
|
38
45
|
veil balance
|
|
39
46
|
|
|
40
|
-
#
|
|
41
|
-
veil withdraw 0.05 0xRecipientAddress
|
|
47
|
+
# 7. Withdraw to any address
|
|
48
|
+
veil withdraw ETH 0.05 0xRecipientAddress
|
|
42
49
|
|
|
43
|
-
#
|
|
44
|
-
veil transfer 0.02 0xRecipientAddress
|
|
50
|
+
# 8. Transfer privately to another registered user
|
|
51
|
+
veil transfer ETH 0.02 0xRecipientAddress
|
|
52
|
+
|
|
53
|
+
# 9. Merge small UTXOs (consolidate balances)
|
|
54
|
+
veil merge ETH 0.1
|
|
45
55
|
```
|
|
46
56
|
|
|
47
57
|
## CLI Commands
|
|
@@ -60,13 +70,43 @@ veil init --no-save # Print keypair without saving
|
|
|
60
70
|
|
|
61
71
|
### `veil keypair`
|
|
62
72
|
|
|
63
|
-
|
|
73
|
+
Show current Veil keypair as JSON (from VEIL_KEY env).
|
|
64
74
|
|
|
65
75
|
```bash
|
|
66
76
|
veil keypair
|
|
67
77
|
# {"veilPrivateKey":"0x...","depositKey":"0x..."}
|
|
68
78
|
```
|
|
69
79
|
|
|
80
|
+
### `veil status`
|
|
81
|
+
|
|
82
|
+
Check configuration and service status.
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
veil status
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Output:
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"walletKey": { "found": true, "address": "0x..." },
|
|
92
|
+
"veilKey": { "found": true },
|
|
93
|
+
"depositKey": { "found": true, "key": "0x1234...abcd" },
|
|
94
|
+
"rpcUrl": { "found": false, "url": "https://mainnet.base.org" },
|
|
95
|
+
"registration": {
|
|
96
|
+
"checked": true,
|
|
97
|
+
"registered": true,
|
|
98
|
+
"matches": true,
|
|
99
|
+
"onChainKey": "0x..."
|
|
100
|
+
},
|
|
101
|
+
"relay": {
|
|
102
|
+
"checked": true,
|
|
103
|
+
"healthy": true,
|
|
104
|
+
"status": "ok",
|
|
105
|
+
"network": "mainnet"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
70
110
|
### `veil register`
|
|
71
111
|
|
|
72
112
|
Register your deposit key on-chain (one-time per address).
|
|
@@ -77,14 +117,14 @@ veil register --json # JSON output
|
|
|
77
117
|
veil register --unsigned --address 0x... # Unsigned payload for agents
|
|
78
118
|
```
|
|
79
119
|
|
|
80
|
-
### `veil deposit <amount>`
|
|
120
|
+
### `veil deposit ETH <amount>`
|
|
81
121
|
|
|
82
122
|
Deposit ETH into the privacy pool.
|
|
83
123
|
|
|
84
124
|
```bash
|
|
85
|
-
veil deposit 0.1 # Signs & sends (JSON output)
|
|
86
|
-
veil deposit 0.1 --unsigned # Unsigned payload for agents
|
|
87
|
-
veil deposit 0.1 --quiet # Suppress progress output
|
|
125
|
+
veil deposit ETH 0.1 # Signs & sends (JSON output)
|
|
126
|
+
veil deposit ETH 0.1 --unsigned # Unsigned payload for agents
|
|
127
|
+
veil deposit ETH 0.1 --quiet # Suppress progress output
|
|
88
128
|
```
|
|
89
129
|
|
|
90
130
|
Output:
|
|
@@ -134,13 +174,13 @@ Output:
|
|
|
134
174
|
}
|
|
135
175
|
```
|
|
136
176
|
|
|
137
|
-
### `veil withdraw <amount> <recipient>`
|
|
177
|
+
### `veil withdraw ETH <amount> <recipient>`
|
|
138
178
|
|
|
139
179
|
Withdraw from the privacy pool to any public address.
|
|
140
180
|
|
|
141
181
|
```bash
|
|
142
|
-
veil withdraw 0.05 0xRecipientAddress
|
|
143
|
-
veil withdraw 0.05 0xRecipientAddress --quiet
|
|
182
|
+
veil withdraw ETH 0.05 0xRecipientAddress
|
|
183
|
+
veil withdraw ETH 0.05 0xRecipientAddress --quiet
|
|
144
184
|
```
|
|
145
185
|
|
|
146
186
|
Output:
|
|
@@ -155,13 +195,13 @@ Output:
|
|
|
155
195
|
}
|
|
156
196
|
```
|
|
157
197
|
|
|
158
|
-
### `veil transfer <amount> <recipient>`
|
|
198
|
+
### `veil transfer ETH <amount> <recipient>`
|
|
159
199
|
|
|
160
200
|
Transfer privately to another registered Veil user.
|
|
161
201
|
|
|
162
202
|
```bash
|
|
163
|
-
veil transfer 0.02 0xRecipientAddress
|
|
164
|
-
veil transfer 0.02 0xRecipientAddress --quiet
|
|
203
|
+
veil transfer ETH 0.02 0xRecipientAddress
|
|
204
|
+
veil transfer ETH 0.02 0xRecipientAddress --quiet
|
|
165
205
|
```
|
|
166
206
|
|
|
167
207
|
Output:
|
|
@@ -176,13 +216,24 @@ Output:
|
|
|
176
216
|
}
|
|
177
217
|
```
|
|
178
218
|
|
|
179
|
-
### `veil merge <amount>`
|
|
219
|
+
### `veil merge ETH <amount>`
|
|
180
220
|
|
|
181
221
|
Consolidate multiple small UTXOs into one (self-transfer).
|
|
182
222
|
|
|
183
223
|
```bash
|
|
184
|
-
veil merge 0.1 # Merge UTXOs totaling 0.1 ETH
|
|
185
|
-
veil merge 0.1 --quiet
|
|
224
|
+
veil merge ETH 0.1 # Merge UTXOs totaling 0.1 ETH
|
|
225
|
+
veil merge ETH 0.1 --quiet
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Output:
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"success": true,
|
|
232
|
+
"transactionHash": "0x...",
|
|
233
|
+
"blockNumber": 12345678,
|
|
234
|
+
"amount": "0.1",
|
|
235
|
+
"type": "merge"
|
|
236
|
+
}
|
|
186
237
|
```
|
|
187
238
|
|
|
188
239
|
## Environment Variables
|
|
@@ -387,11 +438,11 @@ veil init --json
|
|
|
387
438
|
|
|
388
439
|
# Get unsigned transaction payloads for agent signing
|
|
389
440
|
veil register --unsigned --address 0x...
|
|
390
|
-
veil deposit 0.1 --unsigned
|
|
441
|
+
veil deposit ETH 0.1 --unsigned
|
|
391
442
|
|
|
392
443
|
# Suppress progress output for clean JSON
|
|
393
444
|
veil balance --quiet
|
|
394
|
-
veil withdraw 0.05 0xRecipient --quiet
|
|
445
|
+
veil withdraw ETH 0.05 0xRecipient --quiet
|
|
395
446
|
```
|
|
396
447
|
|
|
397
448
|
### Bankr Integration
|
|
@@ -399,7 +450,7 @@ veil withdraw 0.05 0xRecipient --quiet
|
|
|
399
450
|
Use `--unsigned` to get Bankr-compatible transaction payloads:
|
|
400
451
|
|
|
401
452
|
```bash
|
|
402
|
-
veil deposit 0.1 --unsigned
|
|
453
|
+
veil deposit ETH 0.1 --unsigned
|
|
403
454
|
# {"to":"0x...","data":"0x...","value":"100000000000000000","chainId":8453}
|
|
404
455
|
```
|
|
405
456
|
|
|
@@ -431,14 +482,15 @@ const result = await withdraw({
|
|
|
431
482
|
|
|
432
483
|
1. **Generate Keypair**: Run `veil init` to create and save your Veil keypair
|
|
433
484
|
2. **Register**: Run `veil register` to link your deposit key on-chain (one-time)
|
|
434
|
-
3. **
|
|
435
|
-
4. **
|
|
436
|
-
5. **
|
|
485
|
+
3. **Check Status**: Run `veil status` to verify your setup
|
|
486
|
+
4. **Deposit**: Run `veil deposit ETH <amount>` to send ETH
|
|
487
|
+
5. **Wait**: The Veil deposit engine processes your deposit
|
|
488
|
+
6. **Done**: Your deposit is accepted into the privacy pool
|
|
437
489
|
|
|
438
490
|
## Withdrawal Flow
|
|
439
491
|
|
|
440
492
|
1. **Check Balance**: Run `veil balance` to see your private balance
|
|
441
|
-
2. **Withdraw**: Run `veil withdraw <amount> <recipient>`
|
|
493
|
+
2. **Withdraw**: Run `veil withdraw ETH <amount> <recipient>`
|
|
442
494
|
3. **Done**: The SDK builds ZK proofs and submits via the relayer
|
|
443
495
|
|
|
444
496
|
## License
|
package/dist/cli/index.cjs
CHANGED
|
@@ -5170,8 +5170,11 @@ function progress(msg, quiet) {
|
|
|
5170
5170
|
}
|
|
5171
5171
|
}
|
|
5172
5172
|
function createDepositCommand() {
|
|
5173
|
-
const deposit = new Command("deposit").description("Deposit ETH into Veil").argument("<amount>", "Amount to deposit (e.g., 0.1)").option("--deposit-key <key>", "Your Veil deposit key (or set DEPOSIT_KEY env)").option("--wallet-key <key>", "Ethereum wallet key for signing (or set WALLET_KEY env)").option("--rpc-url <url>", "RPC URL (or set RPC_URL env)").option("--unsigned", "Output unsigned transaction payload (Bankr-compatible format)").option("--quiet", "Suppress progress output").action(async (amount, options) => {
|
|
5173
|
+
const deposit = new Command("deposit").description("Deposit ETH into Veil").argument("<asset>", "Asset to deposit (ETH)").argument("<amount>", "Amount to deposit (e.g., 0.1)").option("--deposit-key <key>", "Your Veil deposit key (or set DEPOSIT_KEY env)").option("--wallet-key <key>", "Ethereum wallet key for signing (or set WALLET_KEY env)").option("--rpc-url <url>", "RPC URL (or set RPC_URL env)").option("--unsigned", "Output unsigned transaction payload (Bankr-compatible format)").option("--quiet", "Suppress progress output").action(async (asset, amount, options) => {
|
|
5174
5174
|
try {
|
|
5175
|
+
if (asset.toUpperCase() !== "ETH") {
|
|
5176
|
+
throw new CLIError(ErrorCode.INVALID_AMOUNT, "Only ETH is supported");
|
|
5177
|
+
}
|
|
5175
5178
|
const amountNum = parseFloat(amount);
|
|
5176
5179
|
if (amountNum < MINIMUM_DEPOSIT_WITH_FEE) {
|
|
5177
5180
|
throw new CLIError(
|
|
@@ -5847,6 +5850,14 @@ async function submitRelay(options) {
|
|
|
5847
5850
|
}
|
|
5848
5851
|
return data;
|
|
5849
5852
|
}
|
|
5853
|
+
async function checkRelayHealth(relayUrl) {
|
|
5854
|
+
const url = getRelayUrl();
|
|
5855
|
+
const response = await fetch(`${url}/health`);
|
|
5856
|
+
if (!response.ok) {
|
|
5857
|
+
throw new RelayError("Relay service health check failed", response.status);
|
|
5858
|
+
}
|
|
5859
|
+
return response.json();
|
|
5860
|
+
}
|
|
5850
5861
|
|
|
5851
5862
|
// src/withdraw.ts
|
|
5852
5863
|
function selectUtxosForWithdraw(utxos, amount, decimals = 18) {
|
|
@@ -6018,8 +6029,11 @@ function progress2(msg, quiet) {
|
|
|
6018
6029
|
}
|
|
6019
6030
|
}
|
|
6020
6031
|
function createWithdrawCommand() {
|
|
6021
|
-
const withdrawCmd = new Command("withdraw").description("Withdraw from private pool to a public address").argument("<amount>", "Amount to withdraw (e.g., 0.1)").argument("<recipient>", "Recipient address (e.g., 0x...)").option("--veil-key <key>", "Veil private key (or set VEIL_KEY env)").option("--rpc-url <url>", "RPC URL (or set RPC_URL env)").option("--quiet", "Suppress progress output").action(async (amount, recipient, options) => {
|
|
6032
|
+
const withdrawCmd = new Command("withdraw").description("Withdraw from private pool to a public address").argument("<asset>", "Asset to withdraw (ETH)").argument("<amount>", "Amount to withdraw (e.g., 0.1)").argument("<recipient>", "Recipient address (e.g., 0x...)").option("--veil-key <key>", "Veil private key (or set VEIL_KEY env)").option("--rpc-url <url>", "RPC URL (or set RPC_URL env)").option("--quiet", "Suppress progress output").action(async (asset, amount, recipient, options) => {
|
|
6022
6033
|
try {
|
|
6034
|
+
if (asset.toUpperCase() !== "ETH") {
|
|
6035
|
+
throw new CLIError(ErrorCode.INVALID_AMOUNT, "Only ETH is supported");
|
|
6036
|
+
}
|
|
6023
6037
|
if (!/^0x[a-fA-F0-9]{40}$/.test(recipient)) {
|
|
6024
6038
|
throw new CLIError(ErrorCode.INVALID_ADDRESS, "Invalid recipient address format");
|
|
6025
6039
|
}
|
|
@@ -6337,8 +6351,11 @@ function progress3(msg, quiet) {
|
|
|
6337
6351
|
}
|
|
6338
6352
|
}
|
|
6339
6353
|
function createTransferCommand() {
|
|
6340
|
-
const transferCmd = new Command("transfer").description("Transfer privately within the pool to another registered address").argument("<amount>", "Amount to transfer (e.g., 0.1)").argument("<recipient>", "Recipient address (must be registered)").option("--veil-key <key>", "Veil private key (or set VEIL_KEY env)").option("--rpc-url <url>", "RPC URL (or set RPC_URL env)").option("--quiet", "Suppress progress output").action(async (amount, recipient, options) => {
|
|
6354
|
+
const transferCmd = new Command("transfer").description("Transfer privately within the pool to another registered address").argument("<asset>", "Asset to transfer (ETH)").argument("<amount>", "Amount to transfer (e.g., 0.1)").argument("<recipient>", "Recipient address (must be registered)").option("--veil-key <key>", "Veil private key (or set VEIL_KEY env)").option("--rpc-url <url>", "RPC URL (or set RPC_URL env)").option("--quiet", "Suppress progress output").action(async (asset, amount, recipient, options) => {
|
|
6341
6355
|
try {
|
|
6356
|
+
if (asset.toUpperCase() !== "ETH") {
|
|
6357
|
+
throw new CLIError(ErrorCode.INVALID_AMOUNT, "Only ETH is supported");
|
|
6358
|
+
}
|
|
6342
6359
|
if (!/^0x[a-fA-F0-9]{40}$/.test(recipient)) {
|
|
6343
6360
|
throw new CLIError(ErrorCode.INVALID_ADDRESS, "Invalid recipient address format");
|
|
6344
6361
|
}
|
|
@@ -6378,8 +6395,11 @@ function createTransferCommand() {
|
|
|
6378
6395
|
return transferCmd;
|
|
6379
6396
|
}
|
|
6380
6397
|
function createMergeCommand() {
|
|
6381
|
-
const mergeCmd = new Command("merge").description("Merge UTXOs by self-transfer (consolidate small UTXOs)").argument("<amount>", "Amount to merge (e.g., 0.5)").option("--veil-key <key>", "Veil private key (or set VEIL_KEY env)").option("--rpc-url <url>", "RPC URL (or set RPC_URL env)").option("--quiet", "Suppress progress output").action(async (amount, options) => {
|
|
6398
|
+
const mergeCmd = new Command("merge").description("Merge UTXOs by self-transfer (consolidate small UTXOs)").argument("<asset>", "Asset to merge (ETH)").argument("<amount>", "Amount to merge (e.g., 0.5)").option("--veil-key <key>", "Veil private key (or set VEIL_KEY env)").option("--rpc-url <url>", "RPC URL (or set RPC_URL env)").option("--quiet", "Suppress progress output").action(async (asset, amount, options) => {
|
|
6382
6399
|
try {
|
|
6400
|
+
if (asset.toUpperCase() !== "ETH") {
|
|
6401
|
+
throw new CLIError(ErrorCode.INVALID_AMOUNT, "Only ETH is supported");
|
|
6402
|
+
}
|
|
6383
6403
|
const veilKey = options.veilKey || process.env.VEIL_KEY;
|
|
6384
6404
|
if (!veilKey) {
|
|
6385
6405
|
throw new CLIError(ErrorCode.VEIL_KEY_MISSING, "VEIL_KEY required. Use --veil-key or set VEIL_KEY env");
|
|
@@ -6414,6 +6434,75 @@ function createMergeCommand() {
|
|
|
6414
6434
|
return mergeCmd;
|
|
6415
6435
|
}
|
|
6416
6436
|
|
|
6437
|
+
// src/cli/commands/status.ts
|
|
6438
|
+
function createStatusCommand() {
|
|
6439
|
+
const status = new Command("status").description("Check configuration and service status").option("--rpc-url <url>", "RPC URL (or set RPC_URL env)").action(async (options) => {
|
|
6440
|
+
const result = {
|
|
6441
|
+
walletKey: { found: false },
|
|
6442
|
+
veilKey: { found: false },
|
|
6443
|
+
depositKey: { found: false },
|
|
6444
|
+
rpcUrl: { found: false, url: "https://mainnet.base.org" },
|
|
6445
|
+
registration: { checked: false },
|
|
6446
|
+
relay: { checked: false }
|
|
6447
|
+
};
|
|
6448
|
+
const walletKey = process.env.WALLET_KEY;
|
|
6449
|
+
if (walletKey) {
|
|
6450
|
+
result.walletKey.found = true;
|
|
6451
|
+
try {
|
|
6452
|
+
result.walletKey.address = getAddress(walletKey);
|
|
6453
|
+
} catch {
|
|
6454
|
+
}
|
|
6455
|
+
}
|
|
6456
|
+
const veilKey = process.env.VEIL_KEY;
|
|
6457
|
+
if (veilKey) {
|
|
6458
|
+
result.veilKey.found = true;
|
|
6459
|
+
}
|
|
6460
|
+
const depositKey = process.env.DEPOSIT_KEY;
|
|
6461
|
+
if (depositKey) {
|
|
6462
|
+
result.depositKey.found = true;
|
|
6463
|
+
if (depositKey.length > 20) {
|
|
6464
|
+
result.depositKey.key = `${depositKey.slice(0, 10)}...${depositKey.slice(-8)}`;
|
|
6465
|
+
} else {
|
|
6466
|
+
result.depositKey.key = depositKey;
|
|
6467
|
+
}
|
|
6468
|
+
}
|
|
6469
|
+
const rpcUrl = options.rpcUrl || process.env.RPC_URL;
|
|
6470
|
+
if (rpcUrl) {
|
|
6471
|
+
result.rpcUrl.found = true;
|
|
6472
|
+
result.rpcUrl.url = rpcUrl;
|
|
6473
|
+
}
|
|
6474
|
+
const effectiveRpcUrl = rpcUrl || "https://mainnet.base.org";
|
|
6475
|
+
if (result.walletKey.found && result.walletKey.address) {
|
|
6476
|
+
result.registration.checked = true;
|
|
6477
|
+
try {
|
|
6478
|
+
const regStatus = await isRegistered(
|
|
6479
|
+
result.walletKey.address,
|
|
6480
|
+
effectiveRpcUrl
|
|
6481
|
+
);
|
|
6482
|
+
result.registration.registered = regStatus.registered;
|
|
6483
|
+
result.registration.onChainKey = regStatus.depositKey;
|
|
6484
|
+
if (regStatus.registered && depositKey && regStatus.depositKey) {
|
|
6485
|
+
result.registration.matches = regStatus.depositKey.toLowerCase() === depositKey.toLowerCase();
|
|
6486
|
+
}
|
|
6487
|
+
} catch (error) {
|
|
6488
|
+
result.registration.error = error instanceof Error ? error.message : "Unknown error";
|
|
6489
|
+
}
|
|
6490
|
+
}
|
|
6491
|
+
result.relay.checked = true;
|
|
6492
|
+
try {
|
|
6493
|
+
const health = await checkRelayHealth();
|
|
6494
|
+
result.relay.healthy = health.status === "ok";
|
|
6495
|
+
result.relay.status = health.status;
|
|
6496
|
+
result.relay.network = health.network;
|
|
6497
|
+
} catch (error) {
|
|
6498
|
+
result.relay.healthy = false;
|
|
6499
|
+
result.relay.error = error instanceof Error ? error.message : "Unknown error";
|
|
6500
|
+
}
|
|
6501
|
+
console.log(JSON.stringify(result, null, 2));
|
|
6502
|
+
});
|
|
6503
|
+
return status;
|
|
6504
|
+
}
|
|
6505
|
+
|
|
6417
6506
|
// src/cli/index.ts
|
|
6418
6507
|
loadEnv();
|
|
6419
6508
|
var program2 = new Command();
|
|
@@ -6428,4 +6517,5 @@ program2.addCommand(createPrivateBalanceCommand());
|
|
|
6428
6517
|
program2.addCommand(createWithdrawCommand());
|
|
6429
6518
|
program2.addCommand(createTransferCommand());
|
|
6430
6519
|
program2.addCommand(createMergeCommand());
|
|
6520
|
+
program2.addCommand(createStatusCommand());
|
|
6431
6521
|
program2.parse();
|
package/package.json
CHANGED
|
@@ -25,14 +25,20 @@ function progress(msg: string, quiet?: boolean) {
|
|
|
25
25
|
export function createDepositCommand(): Command {
|
|
26
26
|
const deposit = new Command('deposit')
|
|
27
27
|
.description('Deposit ETH into Veil')
|
|
28
|
+
.argument('<asset>', 'Asset to deposit (ETH)')
|
|
28
29
|
.argument('<amount>', 'Amount to deposit (e.g., 0.1)')
|
|
29
30
|
.option('--deposit-key <key>', 'Your Veil deposit key (or set DEPOSIT_KEY env)')
|
|
30
31
|
.option('--wallet-key <key>', 'Ethereum wallet key for signing (or set WALLET_KEY env)')
|
|
31
32
|
.option('--rpc-url <url>', 'RPC URL (or set RPC_URL env)')
|
|
32
33
|
.option('--unsigned', 'Output unsigned transaction payload (Bankr-compatible format)')
|
|
33
34
|
.option('--quiet', 'Suppress progress output')
|
|
34
|
-
.action(async (amount: string, options) => {
|
|
35
|
+
.action(async (asset: string, amount: string, options) => {
|
|
35
36
|
try {
|
|
37
|
+
// Validate asset is ETH
|
|
38
|
+
if (asset.toUpperCase() !== 'ETH') {
|
|
39
|
+
throw new CLIError(ErrorCode.INVALID_AMOUNT, 'Only ETH is supported');
|
|
40
|
+
}
|
|
41
|
+
|
|
36
42
|
const amountNum = parseFloat(amount);
|
|
37
43
|
|
|
38
44
|
// Check minimum deposit
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status CLI command - Check configuration and service status
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { isRegistered, getAddress } from '../wallet.js';
|
|
7
|
+
import { checkRelayHealth } from '../../relay.js';
|
|
8
|
+
|
|
9
|
+
interface StatusResult {
|
|
10
|
+
walletKey: {
|
|
11
|
+
found: boolean;
|
|
12
|
+
address?: string;
|
|
13
|
+
};
|
|
14
|
+
veilKey: {
|
|
15
|
+
found: boolean;
|
|
16
|
+
};
|
|
17
|
+
depositKey: {
|
|
18
|
+
found: boolean;
|
|
19
|
+
key?: string;
|
|
20
|
+
};
|
|
21
|
+
rpcUrl: {
|
|
22
|
+
found: boolean;
|
|
23
|
+
url: string;
|
|
24
|
+
};
|
|
25
|
+
registration: {
|
|
26
|
+
checked: boolean;
|
|
27
|
+
registered?: boolean;
|
|
28
|
+
matches?: boolean;
|
|
29
|
+
onChainKey?: string | null;
|
|
30
|
+
error?: string;
|
|
31
|
+
};
|
|
32
|
+
relay: {
|
|
33
|
+
checked: boolean;
|
|
34
|
+
healthy?: boolean;
|
|
35
|
+
status?: string;
|
|
36
|
+
network?: string;
|
|
37
|
+
error?: string;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function createStatusCommand(): Command {
|
|
42
|
+
const status = new Command('status')
|
|
43
|
+
.description('Check configuration and service status')
|
|
44
|
+
.option('--rpc-url <url>', 'RPC URL (or set RPC_URL env)')
|
|
45
|
+
.action(async (options) => {
|
|
46
|
+
const result: StatusResult = {
|
|
47
|
+
walletKey: { found: false },
|
|
48
|
+
veilKey: { found: false },
|
|
49
|
+
depositKey: { found: false },
|
|
50
|
+
rpcUrl: { found: false, url: 'https://mainnet.base.org' },
|
|
51
|
+
registration: { checked: false },
|
|
52
|
+
relay: { checked: false },
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Check WALLET_KEY
|
|
56
|
+
const walletKey = process.env.WALLET_KEY;
|
|
57
|
+
if (walletKey) {
|
|
58
|
+
result.walletKey.found = true;
|
|
59
|
+
try {
|
|
60
|
+
result.walletKey.address = getAddress(walletKey as `0x${string}`);
|
|
61
|
+
} catch {
|
|
62
|
+
// Invalid key format, but it was found
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check VEIL_KEY
|
|
67
|
+
const veilKey = process.env.VEIL_KEY;
|
|
68
|
+
if (veilKey) {
|
|
69
|
+
result.veilKey.found = true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check DEPOSIT_KEY
|
|
73
|
+
const depositKey = process.env.DEPOSIT_KEY;
|
|
74
|
+
if (depositKey) {
|
|
75
|
+
result.depositKey.found = true;
|
|
76
|
+
// Show truncated key
|
|
77
|
+
if (depositKey.length > 20) {
|
|
78
|
+
result.depositKey.key = `${depositKey.slice(0, 10)}...${depositKey.slice(-8)}`;
|
|
79
|
+
} else {
|
|
80
|
+
result.depositKey.key = depositKey;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check RPC_URL
|
|
85
|
+
const rpcUrl = options.rpcUrl || process.env.RPC_URL;
|
|
86
|
+
if (rpcUrl) {
|
|
87
|
+
result.rpcUrl.found = true;
|
|
88
|
+
result.rpcUrl.url = rpcUrl;
|
|
89
|
+
}
|
|
90
|
+
const effectiveRpcUrl = rpcUrl || 'https://mainnet.base.org';
|
|
91
|
+
|
|
92
|
+
// Check registration status (requires wallet address)
|
|
93
|
+
if (result.walletKey.found && result.walletKey.address) {
|
|
94
|
+
result.registration.checked = true;
|
|
95
|
+
try {
|
|
96
|
+
const regStatus = await isRegistered(
|
|
97
|
+
result.walletKey.address as `0x${string}`,
|
|
98
|
+
effectiveRpcUrl
|
|
99
|
+
);
|
|
100
|
+
result.registration.registered = regStatus.registered;
|
|
101
|
+
result.registration.onChainKey = regStatus.depositKey;
|
|
102
|
+
|
|
103
|
+
// Check if on-chain key matches env DEPOSIT_KEY
|
|
104
|
+
if (regStatus.registered && depositKey && regStatus.depositKey) {
|
|
105
|
+
result.registration.matches =
|
|
106
|
+
regStatus.depositKey.toLowerCase() === depositKey.toLowerCase();
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
result.registration.error = error instanceof Error ? error.message : 'Unknown error';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Check relay health
|
|
114
|
+
result.relay.checked = true;
|
|
115
|
+
try {
|
|
116
|
+
const health = await checkRelayHealth();
|
|
117
|
+
result.relay.healthy = health.status === 'ok';
|
|
118
|
+
result.relay.status = health.status;
|
|
119
|
+
result.relay.network = health.network;
|
|
120
|
+
} catch (error) {
|
|
121
|
+
result.relay.healthy = false;
|
|
122
|
+
result.relay.error = error instanceof Error ? error.message : 'Unknown error';
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
console.log(JSON.stringify(result, null, 2));
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return status;
|
|
129
|
+
}
|
|
@@ -17,13 +17,19 @@ function progress(msg: string, quiet?: boolean) {
|
|
|
17
17
|
export function createTransferCommand(): Command {
|
|
18
18
|
const transferCmd = new Command('transfer')
|
|
19
19
|
.description('Transfer privately within the pool to another registered address')
|
|
20
|
+
.argument('<asset>', 'Asset to transfer (ETH)')
|
|
20
21
|
.argument('<amount>', 'Amount to transfer (e.g., 0.1)')
|
|
21
22
|
.argument('<recipient>', 'Recipient address (must be registered)')
|
|
22
23
|
.option('--veil-key <key>', 'Veil private key (or set VEIL_KEY env)')
|
|
23
24
|
.option('--rpc-url <url>', 'RPC URL (or set RPC_URL env)')
|
|
24
25
|
.option('--quiet', 'Suppress progress output')
|
|
25
|
-
.action(async (amount: string, recipient: string, options) => {
|
|
26
|
+
.action(async (asset: string, amount: string, recipient: string, options) => {
|
|
26
27
|
try {
|
|
28
|
+
// Validate asset is ETH
|
|
29
|
+
if (asset.toUpperCase() !== 'ETH') {
|
|
30
|
+
throw new CLIError(ErrorCode.INVALID_AMOUNT, 'Only ETH is supported');
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
// Validate recipient
|
|
28
34
|
if (!/^0x[a-fA-F0-9]{40}$/.test(recipient)) {
|
|
29
35
|
throw new CLIError(ErrorCode.INVALID_ADDRESS, 'Invalid recipient address format');
|
|
@@ -82,12 +88,18 @@ export function createTransferCommand(): Command {
|
|
|
82
88
|
export function createMergeCommand(): Command {
|
|
83
89
|
const mergeCmd = new Command('merge')
|
|
84
90
|
.description('Merge UTXOs by self-transfer (consolidate small UTXOs)')
|
|
91
|
+
.argument('<asset>', 'Asset to merge (ETH)')
|
|
85
92
|
.argument('<amount>', 'Amount to merge (e.g., 0.5)')
|
|
86
93
|
.option('--veil-key <key>', 'Veil private key (or set VEIL_KEY env)')
|
|
87
94
|
.option('--rpc-url <url>', 'RPC URL (or set RPC_URL env)')
|
|
88
95
|
.option('--quiet', 'Suppress progress output')
|
|
89
|
-
.action(async (amount: string, options) => {
|
|
96
|
+
.action(async (asset: string, amount: string, options) => {
|
|
90
97
|
try {
|
|
98
|
+
// Validate asset is ETH
|
|
99
|
+
if (asset.toUpperCase() !== 'ETH') {
|
|
100
|
+
throw new CLIError(ErrorCode.INVALID_AMOUNT, 'Only ETH is supported');
|
|
101
|
+
}
|
|
102
|
+
|
|
91
103
|
// Get keypair
|
|
92
104
|
const veilKey = options.veilKey || process.env.VEIL_KEY;
|
|
93
105
|
if (!veilKey) {
|
|
@@ -17,13 +17,19 @@ function progress(msg: string, quiet?: boolean) {
|
|
|
17
17
|
export function createWithdrawCommand(): Command {
|
|
18
18
|
const withdrawCmd = new Command('withdraw')
|
|
19
19
|
.description('Withdraw from private pool to a public address')
|
|
20
|
+
.argument('<asset>', 'Asset to withdraw (ETH)')
|
|
20
21
|
.argument('<amount>', 'Amount to withdraw (e.g., 0.1)')
|
|
21
22
|
.argument('<recipient>', 'Recipient address (e.g., 0x...)')
|
|
22
23
|
.option('--veil-key <key>', 'Veil private key (or set VEIL_KEY env)')
|
|
23
24
|
.option('--rpc-url <url>', 'RPC URL (or set RPC_URL env)')
|
|
24
25
|
.option('--quiet', 'Suppress progress output')
|
|
25
|
-
.action(async (amount: string, recipient: string, options) => {
|
|
26
|
+
.action(async (asset: string, amount: string, recipient: string, options) => {
|
|
26
27
|
try {
|
|
28
|
+
// Validate asset is ETH
|
|
29
|
+
if (asset.toUpperCase() !== 'ETH') {
|
|
30
|
+
throw new CLIError(ErrorCode.INVALID_AMOUNT, 'Only ETH is supported');
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
// Validate recipient
|
|
28
34
|
if (!/^0x[a-fA-F0-9]{40}$/.test(recipient)) {
|
|
29
35
|
throw new CLIError(ErrorCode.INVALID_ADDRESS, 'Invalid recipient address format');
|
package/src/cli/index.ts
CHANGED
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
* Veil CLI - Command-line interface for Veil Cash
|
|
3
3
|
*
|
|
4
4
|
* Usage:
|
|
5
|
-
* veil init
|
|
6
|
-
* veil keypair
|
|
7
|
-
* veil
|
|
8
|
-
* veil
|
|
9
|
-
* veil
|
|
10
|
-
* veil
|
|
11
|
-
* veil
|
|
12
|
-
* veil
|
|
13
|
-
* veil
|
|
14
|
-
* veil
|
|
5
|
+
* veil init # Generate keypair
|
|
6
|
+
* veil keypair # Show keypair (JSON)
|
|
7
|
+
* veil status # Check config and service status
|
|
8
|
+
* veil register # Register on-chain
|
|
9
|
+
* veil deposit ETH 0.1 # Deposit ETH
|
|
10
|
+
* veil balance # Show all balances
|
|
11
|
+
* veil queue-balance # Show pending queue deposits
|
|
12
|
+
* veil private-balance # Show private balance
|
|
13
|
+
* veil withdraw ETH 0.1 0x... # Withdraw to public address
|
|
14
|
+
* veil transfer ETH 0.1 0x... # Transfer privately
|
|
15
|
+
* veil merge ETH 0.5 # Merge UTXOs (self-transfer)
|
|
15
16
|
*/
|
|
16
17
|
|
|
17
18
|
import { Command } from 'commander';
|
|
@@ -25,6 +26,7 @@ import { createQueueBalanceCommand } from './commands/queue-balance.js';
|
|
|
25
26
|
import { createPrivateBalanceCommand } from './commands/private-balance.js';
|
|
26
27
|
import { createWithdrawCommand } from './commands/withdraw.js';
|
|
27
28
|
import { createTransferCommand, createMergeCommand } from './commands/transfer.js';
|
|
29
|
+
import { createStatusCommand } from './commands/status.js';
|
|
28
30
|
|
|
29
31
|
// Load environment variables
|
|
30
32
|
loadEnv();
|
|
@@ -47,6 +49,7 @@ program.addCommand(createPrivateBalanceCommand());
|
|
|
47
49
|
program.addCommand(createWithdrawCommand());
|
|
48
50
|
program.addCommand(createTransferCommand());
|
|
49
51
|
program.addCommand(createMergeCommand());
|
|
52
|
+
program.addCommand(createStatusCommand());
|
|
50
53
|
|
|
51
54
|
// Parse and execute
|
|
52
55
|
program.parse();
|