@veil-cash/sdk 0.3.0 → 0.5.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 +105 -512
- package/SDK.md +311 -0
- package/dist/cli/index.cjs +1446 -978
- package/dist/index.cjs +9 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -58
- package/dist/index.d.ts +6 -58
- package/dist/index.js +10 -62
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/skills/veil/SKILL.md +526 -0
- package/skills/veil/reference.md +231 -0
- package/src/abi.ts +0 -12
- package/src/addresses.ts +8 -15
- package/src/balance.ts +4 -4
- package/src/cli/commands/balance.ts +128 -40
- package/src/cli/commands/deposit.ts +140 -71
- package/src/cli/commands/init.ts +98 -68
- package/src/cli/commands/keypair.ts +34 -16
- package/src/cli/commands/private-balance.ts +38 -36
- package/src/cli/commands/queue-balance.ts +49 -37
- package/src/cli/commands/register.ts +67 -53
- package/src/cli/commands/status.ts +196 -70
- package/src/cli/commands/transfer.ts +65 -56
- package/src/cli/commands/withdraw.ts +34 -32
- package/src/cli/config.ts +85 -5
- package/src/cli/errors.ts +4 -0
- package/src/cli/index.ts +23 -5
- package/src/cli/output.ts +87 -0
- package/src/cli/wallet.ts +75 -16
- package/src/deposit.ts +1 -70
- package/src/index.ts +6 -3
- package/src/prover.ts +3 -0
- package/src/relay.ts +2 -2
- package/src/types.ts +2 -5
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Veil SDK Reference
|
|
2
|
+
|
|
3
|
+
Detailed payload spec and SDK function signatures for agent integration.
|
|
4
|
+
|
|
5
|
+
## Unsigned payload spec
|
|
6
|
+
|
|
7
|
+
All `--unsigned` CLI output and programmatic builders target **Base mainnet** (chain ID 8453).
|
|
8
|
+
|
|
9
|
+
### Payload shape
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"to": "0x...",
|
|
14
|
+
"data": "0x...",
|
|
15
|
+
"value": "0",
|
|
16
|
+
"chainId": 8453
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Field reference
|
|
21
|
+
|
|
22
|
+
| Field | Type | Required | Description |
|
|
23
|
+
|-------|------|----------|-------------|
|
|
24
|
+
| `to` | `string` | yes | Target contract address (`0x` + 40 hex chars) |
|
|
25
|
+
| `data` | `string` | yes | ABI-encoded calldata (`0x` + hex) |
|
|
26
|
+
| `value` | `string` | yes | ETH amount in wei as a **string** (e.g. `"0"`, `"1000000000000000000"` for 1 ETH) |
|
|
27
|
+
| `chainId` | `number` | yes | `8453` (Base) |
|
|
28
|
+
|
|
29
|
+
`value` must always be a string. For register and USDC transactions it is `"0"`.
|
|
30
|
+
For ETH deposits it equals the deposit amount in wei.
|
|
31
|
+
|
|
32
|
+
### CLI extra fields
|
|
33
|
+
|
|
34
|
+
The CLI may include an `action` or `step` field for context:
|
|
35
|
+
|
|
36
|
+
- **Register**: `"action": "register"` or `"action": "changeDepositKey"`
|
|
37
|
+
- **Deposit**: `"step": "approve"` (USDC only) and `"step": "deposit"`
|
|
38
|
+
|
|
39
|
+
These fields are informational and can be ignored by the signer.
|
|
40
|
+
For `veil register --unsigned --force`, the CLI checks chain state first and chooses `"register"` vs `"changeDepositKey"` based on whether the address is already registered.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## SDK build functions
|
|
45
|
+
|
|
46
|
+
All functions are exported from `@veil-cash/sdk`.
|
|
47
|
+
|
|
48
|
+
### Keypair
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { Keypair, VEIL_SIGNED_MESSAGE } from '@veil-cash/sdk';
|
|
52
|
+
import type { MessageSigner } from '@veil-cash/sdk';
|
|
53
|
+
|
|
54
|
+
// Random keypair
|
|
55
|
+
const keypair = new Keypair();
|
|
56
|
+
|
|
57
|
+
// Restore from saved private key
|
|
58
|
+
const restored = new Keypair('0xSAVED_VEIL_KEY');
|
|
59
|
+
|
|
60
|
+
// Derive from Ethereum wallet key (same keypair as frontend login)
|
|
61
|
+
const derived = await Keypair.fromWalletKey('0xWALLET_KEY');
|
|
62
|
+
|
|
63
|
+
// Derive from pre-computed EIP-191 signature
|
|
64
|
+
const fromSig = Keypair.fromSignature('0xSIG');
|
|
65
|
+
|
|
66
|
+
// Derive via external signer callback
|
|
67
|
+
const fromSigner = await Keypair.fromSigner(async (msg) => {
|
|
68
|
+
return await externalSignerService.personalSign(msg);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Public deposit key (register on-chain)
|
|
72
|
+
keypair.depositKey(); // 0x-prefixed, 130 hex chars
|
|
73
|
+
|
|
74
|
+
// Private key (store securely)
|
|
75
|
+
keypair.privkey; // 0x-prefixed, 66 hex chars
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Register
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { buildRegisterTx, buildChangeDepositKeyTx } from '@veil-cash/sdk';
|
|
82
|
+
import type { TransactionData } from '@veil-cash/sdk';
|
|
83
|
+
|
|
84
|
+
// First-time registration
|
|
85
|
+
const tx: TransactionData = buildRegisterTx(depositKey, '0xSIGNER_ADDRESS');
|
|
86
|
+
// tx = { to: '0x...', data: '0x...' }
|
|
87
|
+
|
|
88
|
+
// Update existing deposit key
|
|
89
|
+
const changeTx: TransactionData = buildChangeDepositKeyTx(newDepositKey, '0xSIGNER_ADDRESS');
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`TransactionData` type:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
interface TransactionData {
|
|
96
|
+
to: `0x${string}`;
|
|
97
|
+
data: `0x${string}`;
|
|
98
|
+
value?: bigint;
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
For register transactions `value` is `undefined` (use `"0"` when forwarding to signer).
|
|
103
|
+
|
|
104
|
+
### Deposit
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import {
|
|
108
|
+
buildDepositETHTx,
|
|
109
|
+
buildDepositUSDCTx,
|
|
110
|
+
buildApproveUSDCTx,
|
|
111
|
+
buildDepositTx,
|
|
112
|
+
} from '@veil-cash/sdk';
|
|
113
|
+
|
|
114
|
+
// ETH deposit
|
|
115
|
+
const ethTx = buildDepositETHTx({ depositKey, amount: '0.1' });
|
|
116
|
+
// ethTx.value = 100000000000000000n (bigint)
|
|
117
|
+
|
|
118
|
+
// USDC deposit (two-step)
|
|
119
|
+
const approveTx = buildApproveUSDCTx({ amount: '100' });
|
|
120
|
+
const usdcTx = buildDepositUSDCTx({ depositKey, amount: '100' });
|
|
121
|
+
|
|
122
|
+
// Generic (routes to ETH or USDC builder)
|
|
123
|
+
const tx = buildDepositTx({ depositKey, amount: '0.1', token: 'ETH' });
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
When serializing for a signer: `value` must be converted to a string (`tx.value?.toString() ?? '0'`).
|
|
127
|
+
|
|
128
|
+
### Balance
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { getQueueBalance, getPrivateBalance } from '@veil-cash/sdk';
|
|
132
|
+
|
|
133
|
+
// Queue balance (pending deposits)
|
|
134
|
+
const queue = await getQueueBalance({
|
|
135
|
+
address: '0x...',
|
|
136
|
+
pool: 'eth',
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Private balance (in-pool UTXOs)
|
|
140
|
+
const priv = await getPrivateBalance({
|
|
141
|
+
keypair,
|
|
142
|
+
pool: 'eth',
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## CLI quick reference
|
|
149
|
+
|
|
150
|
+
Install globally: `npm install -g @veil-cash/sdk`
|
|
151
|
+
|
|
152
|
+
### Environment variables
|
|
153
|
+
|
|
154
|
+
| Variable | Description |
|
|
155
|
+
|----------|-------------|
|
|
156
|
+
| `VEIL_KEY` | Veil private key (for ZK proofs) |
|
|
157
|
+
| `DEPOSIT_KEY` | Veil deposit key (public) |
|
|
158
|
+
| `WALLET_KEY` | Ethereum wallet private key (for signing) |
|
|
159
|
+
| `SIGNER_ADDRESS` | Ethereum address for unsigned/query flows when signing is external |
|
|
160
|
+
| `RPC_URL` | Base RPC URL (optional, defaults to public RPC) |
|
|
161
|
+
| `RELAY_URL` | Override relay base URL for relayed CLI operations |
|
|
162
|
+
|
|
163
|
+
`WALLET_KEY` and `SIGNER_ADDRESS` are mutually exclusive. Use `SIGNER_ADDRESS` only for address-only CLI flows.
|
|
164
|
+
|
|
165
|
+
### Commands
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
veil init # Derive keypair from WALLET_KEY (saves to .env.veil)
|
|
169
|
+
veil init --generate # Generate random keypair
|
|
170
|
+
veil init --signature 0x... # Derive from pre-computed EIP-191 signature
|
|
171
|
+
veil init --force # Overwrite existing keypair without prompting
|
|
172
|
+
veil init --no-save # Print keypair without saving to disk
|
|
173
|
+
veil init --json # Output keypair as JSON (no prompts, no file save)
|
|
174
|
+
|
|
175
|
+
veil keypair # Show current keypair (from VEIL_KEY)
|
|
176
|
+
veil keypair --json # Show current keypair as JSON
|
|
177
|
+
|
|
178
|
+
veil status # Check config, signing mode, registration, and relay health
|
|
179
|
+
veil status --json # Machine-readable status
|
|
180
|
+
|
|
181
|
+
SIGNER_ADDRESS=0x... veil register --unsigned # Unsigned register payload
|
|
182
|
+
SIGNER_ADDRESS=0x... veil register --unsigned --force # Unsigned register/change-key payload (depends on chain state)
|
|
183
|
+
veil register --unsigned --address 0x... # Unsigned register payload (explicit address)
|
|
184
|
+
veil register --json # Register and output result as JSON
|
|
185
|
+
|
|
186
|
+
veil deposit ETH 0.1 --unsigned # Unsigned ETH deposit payload
|
|
187
|
+
veil deposit USDC 100 --unsigned # Unsigned USDC deposit payload(s)
|
|
188
|
+
veil deposit ETH 0.1 --json # Deposit and output result as JSON
|
|
189
|
+
|
|
190
|
+
veil balance # All pool balances
|
|
191
|
+
veil balance --pool eth # ETH pool only
|
|
192
|
+
veil balance --pool usdc # USDC pool only
|
|
193
|
+
veil balance --json # Machine-readable balances
|
|
194
|
+
veil balance queue --pool eth # Queue-only balance
|
|
195
|
+
veil balance queue --address 0x... --json # Queue balance for explicit address
|
|
196
|
+
veil balance private --pool eth # Private-only balance
|
|
197
|
+
veil balance private --json # Private balance as JSON
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Error format
|
|
201
|
+
|
|
202
|
+
All CLI errors output JSON with a standardized `errorCode`:
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"success": false,
|
|
207
|
+
"errorCode": "VEIL_KEY_MISSING",
|
|
208
|
+
"error": "VEIL_KEY required. Set VEIL_KEY env"
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Common codes: `VEIL_KEY_MISSING`, `WALLET_KEY_MISSING`, `DEPOSIT_KEY_MISSING`,
|
|
213
|
+
`CONFIG_CONFLICT`, `INVALID_AMOUNT`, `INSUFFICIENT_BALANCE`, `CONTRACT_ERROR`, `RPC_ERROR`.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Deposit minimums
|
|
218
|
+
|
|
219
|
+
| Asset | Minimum (net) | Notes |
|
|
220
|
+
|-------|--------------|-------|
|
|
221
|
+
| ETH | 0.01 | Fee (0.3%) added automatically via on-chain `getDepositAmountWithFee` |
|
|
222
|
+
| USDC | 10 | Fee (0.3%) added automatically via on-chain `getDepositAmountWithFee` |
|
|
223
|
+
|
|
224
|
+
The CLI amount is the **net** amount that lands in the pool. The fee is calculated on-chain and added to the transaction automatically — users do not need to account for it.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Links
|
|
229
|
+
|
|
230
|
+
- npm: [@veil-cash/sdk](https://www.npmjs.com/package/@veil-cash/sdk)
|
|
231
|
+
- Veil Cash: [https://veil.cash](https://veil.cash)
|
package/src/abi.ts
CHANGED
|
@@ -101,18 +101,6 @@ export const ENTRY_ABI = [
|
|
|
101
101
|
type: 'function',
|
|
102
102
|
},
|
|
103
103
|
|
|
104
|
-
// Queue cbBTC deposit
|
|
105
|
-
{
|
|
106
|
-
inputs: [
|
|
107
|
-
{ name: '_amount', type: 'uint256' },
|
|
108
|
-
{ name: '_depositKey', type: 'bytes' },
|
|
109
|
-
],
|
|
110
|
-
name: 'queueBTC',
|
|
111
|
-
outputs: [],
|
|
112
|
-
stateMutability: 'nonpayable',
|
|
113
|
-
type: 'function',
|
|
114
|
-
},
|
|
115
|
-
|
|
116
104
|
// Read deposit keys
|
|
117
105
|
{
|
|
118
106
|
inputs: [{ name: '', type: 'address' }],
|
package/src/addresses.ts
CHANGED
|
@@ -14,9 +14,6 @@ export const ADDRESSES: NetworkAddresses = {
|
|
|
14
14
|
usdcPool: '0x5c50d58E49C59d112680c187De2Bf989d2a91242',
|
|
15
15
|
usdcQueue: '0x5530241b24504bF05C9a22e95A1F5458888e6a9B',
|
|
16
16
|
usdcToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
17
|
-
cbbtcPool: '0x51A021da774b4bBB59B47f7CB4ccd631337680BA',
|
|
18
|
-
cbbtcQueue: '0x977741CaDF8D1431c4816C0993D32b02094cD35C',
|
|
19
|
-
cbbtcToken: '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf',
|
|
20
17
|
chainId: 8453,
|
|
21
18
|
relayUrl: 'https://veil-relay.up.railway.app',
|
|
22
19
|
} as const;
|
|
@@ -37,12 +34,6 @@ export const POOL_CONFIG = {
|
|
|
37
34
|
symbol: 'USDC',
|
|
38
35
|
name: 'USD Coin',
|
|
39
36
|
},
|
|
40
|
-
cbbtc: {
|
|
41
|
-
decimals: 8,
|
|
42
|
-
displayDecimals: 6,
|
|
43
|
-
symbol: 'cbBTC',
|
|
44
|
-
name: 'Coinbase Bitcoin',
|
|
45
|
-
},
|
|
46
37
|
} as const;
|
|
47
38
|
|
|
48
39
|
/**
|
|
@@ -55,30 +46,32 @@ export function getAddresses(): NetworkAddresses {
|
|
|
55
46
|
|
|
56
47
|
/**
|
|
57
48
|
* Get the pool contract address for a given pool
|
|
58
|
-
* @param pool - Pool identifier ('eth'
|
|
49
|
+
* @param pool - Pool identifier ('eth' or 'usdc')
|
|
59
50
|
* @returns Pool contract address
|
|
60
51
|
*/
|
|
61
|
-
export function getPoolAddress(
|
|
52
|
+
export function getPoolAddress(
|
|
53
|
+
pool: RelayPool
|
|
54
|
+
): `0x${string}` {
|
|
62
55
|
const addresses = getAddresses();
|
|
63
56
|
switch (pool) {
|
|
64
57
|
case 'eth': return addresses.ethPool;
|
|
65
58
|
case 'usdc': return addresses.usdcPool;
|
|
66
|
-
case 'cbbtc': return addresses.cbbtcPool;
|
|
67
59
|
default: throw new Error(`Unknown pool: ${pool}`);
|
|
68
60
|
}
|
|
69
61
|
}
|
|
70
62
|
|
|
71
63
|
/**
|
|
72
64
|
* Get the queue contract address for a given pool
|
|
73
|
-
* @param pool - Pool identifier ('eth'
|
|
65
|
+
* @param pool - Pool identifier ('eth' or 'usdc')
|
|
74
66
|
* @returns Queue contract address
|
|
75
67
|
*/
|
|
76
|
-
export function getQueueAddress(
|
|
68
|
+
export function getQueueAddress(
|
|
69
|
+
pool: RelayPool
|
|
70
|
+
): `0x${string}` {
|
|
77
71
|
const addresses = getAddresses();
|
|
78
72
|
switch (pool) {
|
|
79
73
|
case 'eth': return addresses.ethQueue;
|
|
80
74
|
case 'usdc': return addresses.usdcQueue;
|
|
81
|
-
case 'cbbtc': return addresses.cbbtcQueue;
|
|
82
75
|
default: throw new Error(`Unknown pool: ${pool}`);
|
|
83
76
|
}
|
|
84
77
|
}
|
package/src/balance.ts
CHANGED
|
@@ -101,14 +101,14 @@ export async function getQueueBalance(options: {
|
|
|
101
101
|
depositKey: `0x${string}`;
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
-
//
|
|
104
|
+
// Report the net shielded amount so queue totals match what will land in private balance.
|
|
105
105
|
if (deposit.fallbackReceiver.toLowerCase() === address.toLowerCase()) {
|
|
106
|
-
totalQueueBalance += deposit.
|
|
106
|
+
totalQueueBalance += deposit.shieldAmount;
|
|
107
107
|
pendingDeposits.push({
|
|
108
108
|
nonce: nonce.toString(),
|
|
109
109
|
status: DEPOSIT_STATUS_MAP[deposit.status as keyof typeof DEPOSIT_STATUS_MAP] || 'pending',
|
|
110
|
-
amount: formatUnits(deposit.
|
|
111
|
-
amountWei: deposit.
|
|
110
|
+
amount: formatUnits(deposit.shieldAmount, poolConfig.decimals),
|
|
111
|
+
amountWei: deposit.shieldAmount.toString(),
|
|
112
112
|
timestamp: new Date(Number(deposit.timestamp) * 1000).toISOString(),
|
|
113
113
|
});
|
|
114
114
|
}
|
|
@@ -6,12 +6,16 @@ import { Command } from 'commander';
|
|
|
6
6
|
import { getQueueBalance, getPrivateBalance } from '../../balance.js';
|
|
7
7
|
import { POOL_CONFIG } from '../../addresses.js';
|
|
8
8
|
import { Keypair } from '../../keypair.js';
|
|
9
|
-
import {
|
|
9
|
+
import { getWalletBalances } from '../wallet.js';
|
|
10
|
+
import { resolveAddress } from '../config.js';
|
|
10
11
|
import { formatUnits } from 'viem';
|
|
11
12
|
import { handleCLIError, CLIError, ErrorCode } from '../errors.js';
|
|
13
|
+
import { clearProgress, createProgressReporter, maskValue, printFields, printHeader, printJson, printLine, printList, printSection } from '../output.js';
|
|
14
|
+
import { createPrivateBalanceCommand } from './private-balance.js';
|
|
15
|
+
import { createQueueBalanceCommand } from './queue-balance.js';
|
|
12
16
|
import type { RelayPool } from '../../types.js';
|
|
13
17
|
|
|
14
|
-
const SUPPORTED_POOLS: RelayPool[] = ['eth', 'usdc'
|
|
18
|
+
const SUPPORTED_POOLS: RelayPool[] = ['eth', 'usdc'];
|
|
15
19
|
|
|
16
20
|
/**
|
|
17
21
|
* Fetch balance for a single pool and return structured output
|
|
@@ -88,12 +92,16 @@ async function fetchPoolBalance(
|
|
|
88
92
|
export function createBalanceCommand(): Command {
|
|
89
93
|
const balance = new Command('balance')
|
|
90
94
|
.description('Show queue and private balances (all pools by default)')
|
|
91
|
-
.option('--pool <pool>', 'Pool to check (eth, usdc,
|
|
92
|
-
.option('--
|
|
93
|
-
.option('--
|
|
94
|
-
.
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
.option('--pool <pool>', 'Pool to check (eth, usdc, or all)', 'all')
|
|
96
|
+
.option('--address <address>', 'Address to check (or derived from WALLET_KEY / SIGNER_ADDRESS)')
|
|
97
|
+
.option('--json', 'Output as JSON')
|
|
98
|
+
.addHelpText('after', `
|
|
99
|
+
Examples:
|
|
100
|
+
veil balance
|
|
101
|
+
veil balance --pool eth
|
|
102
|
+
veil balance queue --pool usdc
|
|
103
|
+
veil balance --json
|
|
104
|
+
`)
|
|
97
105
|
.action(async (options) => {
|
|
98
106
|
try {
|
|
99
107
|
const poolArg = (options.pool || 'all').toLowerCase();
|
|
@@ -106,73 +114,153 @@ export function createBalanceCommand(): Command {
|
|
|
106
114
|
const poolsToQuery: RelayPool[] = poolArg === 'all' ? [...SUPPORTED_POOLS] : [poolArg as RelayPool];
|
|
107
115
|
|
|
108
116
|
// Get address
|
|
109
|
-
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
throw new CLIError(ErrorCode.WALLET_KEY_MISSING, 'Must provide --address or --wallet-key (or set WALLET_KEY env)');
|
|
116
|
-
}
|
|
117
|
-
address = getAddress(walletKey as `0x${string}`);
|
|
117
|
+
const resolvedAddress = resolveAddress({ address: options.address }, { required: true });
|
|
118
|
+
if (!resolvedAddress) {
|
|
119
|
+
throw new CLIError(
|
|
120
|
+
ErrorCode.WALLET_KEY_MISSING,
|
|
121
|
+
'Must provide --address, set SIGNER_ADDRESS, or set WALLET_KEY env.',
|
|
122
|
+
);
|
|
118
123
|
}
|
|
124
|
+
const address = resolvedAddress.address;
|
|
119
125
|
|
|
120
126
|
// Get keypair for private balance
|
|
121
|
-
const veilKey =
|
|
127
|
+
const veilKey = process.env.VEIL_KEY;
|
|
122
128
|
const keypair = veilKey ? new Keypair(veilKey) : null;
|
|
123
129
|
|
|
124
|
-
const rpcUrl =
|
|
130
|
+
const rpcUrl = process.env.RPC_URL;
|
|
125
131
|
|
|
126
|
-
|
|
127
|
-
const onProgress = options.quiet
|
|
128
|
-
? undefined
|
|
129
|
-
: (stage: string, detail?: string) => {
|
|
130
|
-
const msg = detail ? `${stage}: ${detail}` : stage;
|
|
131
|
-
process.stderr.write(`\r\x1b[K${msg}`);
|
|
132
|
-
};
|
|
132
|
+
const onProgress = createProgressReporter();
|
|
133
133
|
|
|
134
134
|
// Get deposit key if available
|
|
135
135
|
const depositKey = process.env.DEPOSIT_KEY || (keypair ? keypair.depositKey() : null);
|
|
136
136
|
|
|
137
137
|
// Single pool mode -- flat output (backwards compatible)
|
|
138
138
|
if (poolsToQuery.length === 1) {
|
|
139
|
-
const poolResult = await
|
|
139
|
+
const [poolResult, walletBalances] = await Promise.all([
|
|
140
|
+
fetchPoolBalance(poolsToQuery[0], address, keypair, rpcUrl, onProgress),
|
|
141
|
+
getWalletBalances(address, rpcUrl),
|
|
142
|
+
]);
|
|
140
143
|
|
|
141
|
-
|
|
142
|
-
if (!options.quiet) process.stderr.write('\r\x1b[K');
|
|
144
|
+
clearProgress();
|
|
143
145
|
|
|
144
146
|
const output = {
|
|
145
147
|
address,
|
|
146
148
|
depositKey: depositKey || null,
|
|
149
|
+
wallet: walletBalances,
|
|
147
150
|
...poolResult,
|
|
148
151
|
};
|
|
149
152
|
|
|
150
|
-
|
|
153
|
+
if (options.json) {
|
|
154
|
+
printJson(output);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
printCombinedBalanceHuman(output);
|
|
151
159
|
return;
|
|
152
160
|
}
|
|
153
161
|
|
|
154
162
|
// All pools mode -- nested output
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
163
|
+
const poolPromises = poolsToQuery.map(pool =>
|
|
164
|
+
fetchPoolBalance(pool, address, keypair, rpcUrl, onProgress),
|
|
165
|
+
);
|
|
166
|
+
const [walletBalances, ...poolResults] = await Promise.all([
|
|
167
|
+
getWalletBalances(address, rpcUrl),
|
|
168
|
+
...poolPromises,
|
|
169
|
+
]);
|
|
160
170
|
|
|
161
|
-
|
|
162
|
-
if (!options.quiet) process.stderr.write('\r\x1b[K');
|
|
171
|
+
clearProgress();
|
|
163
172
|
|
|
164
173
|
const output = {
|
|
165
174
|
address,
|
|
166
175
|
depositKey: depositKey || null,
|
|
167
|
-
|
|
176
|
+
wallet: walletBalances,
|
|
177
|
+
pools: poolResults,
|
|
168
178
|
};
|
|
169
179
|
|
|
170
|
-
|
|
180
|
+
if (options.json) {
|
|
181
|
+
printJson(output);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
printMultiPoolBalanceHuman(output);
|
|
171
186
|
} catch (error) {
|
|
172
|
-
|
|
187
|
+
clearProgress();
|
|
173
188
|
handleCLIError(error);
|
|
174
189
|
}
|
|
175
190
|
});
|
|
176
191
|
|
|
192
|
+
balance.addCommand(createQueueBalanceCommand('queue'));
|
|
193
|
+
balance.addCommand(createPrivateBalanceCommand('private'));
|
|
194
|
+
|
|
177
195
|
return balance;
|
|
178
196
|
}
|
|
197
|
+
|
|
198
|
+
function printPoolHuman(output: Record<string, unknown>): void {
|
|
199
|
+
const symbol = output.symbol as string;
|
|
200
|
+
|
|
201
|
+
printSection(`${output.pool}`);
|
|
202
|
+
printFields([
|
|
203
|
+
{ label: 'Total', value: `${output.totalBalance} ${symbol}` },
|
|
204
|
+
]);
|
|
205
|
+
|
|
206
|
+
const privateData = output.private as { balance?: string | null; balanceWei?: string; utxoCount?: number; note?: string; utxos?: Array<{ index: number; amount: string }> };
|
|
207
|
+
if (privateData.note) {
|
|
208
|
+
printFields([
|
|
209
|
+
{ label: 'Private', value: privateData.note },
|
|
210
|
+
]);
|
|
211
|
+
} else {
|
|
212
|
+
printFields([
|
|
213
|
+
{ label: 'Private', value: `${privateData.balance} ${symbol}` },
|
|
214
|
+
]);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const queueData = output.queue as { balance: string; balanceWei: string; count: number; deposits: Array<{ nonce: string | number; amount: string; status: string }> };
|
|
218
|
+
printFields([
|
|
219
|
+
{ label: 'Queue', value: `${queueData.balance} ${symbol}` },
|
|
220
|
+
{ label: 'Pending', value: queueData.count },
|
|
221
|
+
]);
|
|
222
|
+
if (queueData.deposits.length > 0) {
|
|
223
|
+
printList(
|
|
224
|
+
queueData.deposits.map((d) => `nonce ${d.nonce}: ${d.amount} (${d.status})`)
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function printCombinedBalanceHuman(output: Record<string, unknown>): void {
|
|
230
|
+
const wallet = output.wallet as { eth: string; usdc: string };
|
|
231
|
+
|
|
232
|
+
printHeader(`${output.pool} Balance`);
|
|
233
|
+
printFields([
|
|
234
|
+
{ label: 'Address', value: output.address },
|
|
235
|
+
{ label: 'Deposit key', value: typeof output.depositKey === 'string' ? maskValue(output.depositKey) : 'not set' },
|
|
236
|
+
]);
|
|
237
|
+
|
|
238
|
+
printSection('Wallet (public)');
|
|
239
|
+
printFields([
|
|
240
|
+
{ label: 'ETH', value: `${wallet.eth} ETH` },
|
|
241
|
+
{ label: 'USDC', value: `${wallet.usdc} USDC` },
|
|
242
|
+
]);
|
|
243
|
+
|
|
244
|
+
printPoolHuman(output);
|
|
245
|
+
printLine();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function printMultiPoolBalanceHuman(output: { address: string; depositKey: string | null; wallet: { eth: string; usdc: string }; pools: Record<string, unknown>[] }): void {
|
|
249
|
+
printHeader('Balances');
|
|
250
|
+
printFields([
|
|
251
|
+
{ label: 'Address', value: output.address },
|
|
252
|
+
{ label: 'Deposit key', value: output.depositKey ? maskValue(output.depositKey) : 'not set' },
|
|
253
|
+
]);
|
|
254
|
+
|
|
255
|
+
printSection('Wallet (public)');
|
|
256
|
+
printFields([
|
|
257
|
+
{ label: 'ETH', value: `${output.wallet.eth} ETH` },
|
|
258
|
+
{ label: 'USDC', value: `${output.wallet.usdc} USDC` },
|
|
259
|
+
]);
|
|
260
|
+
|
|
261
|
+
for (const poolResult of output.pools) {
|
|
262
|
+
printPoolHuman(poolResult);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
printLine();
|
|
266
|
+
}
|