@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.
@@ -3,95 +3,121 @@
3
3
  */
4
4
 
5
5
  import { Command } from 'commander';
6
- import { buildDepositETHTx, buildDepositUSDCTx, buildApproveUSDCTx, buildDepositCBBTCTx, buildApproveCBBTCTx } from '../../deposit.js';
6
+ import { buildDepositETHTx, buildDepositUSDCTx, buildApproveUSDCTx } from '../../deposit.js';
7
7
  import { sendTransaction, getAddress, getBalance } from '../wallet.js';
8
8
  import { getConfig } from '../config.js';
9
- import { parseEther, formatEther } from 'viem';
9
+ import { createPublicClient, http, parseEther, parseUnits, formatEther, formatUnits } from 'viem';
10
+ import { base } from 'viem/chains';
10
11
  import { handleCLIError, CLIError, ErrorCode } from '../errors.js';
12
+ import { clearProgress, createProgressReporter, printFields, printHeader, printJson, printLine, txUrl } from '../output.js';
13
+ import { POOL_CONFIG, getAddresses } from '../../addresses.js';
14
+ import { ENTRY_ABI, ERC20_ABI } from '../../abi.js';
11
15
  import type { TransactionData } from '../../types.js';
12
16
 
13
- // Minimum deposits per asset (net after 0.3% fee)
14
- const DEPOSIT_FEE_PERCENT = 0.3;
15
- const MINIMUM_DEPOSITS: Record<string, number> = {
17
+ const MINIMUM_NET: Record<string, number> = {
16
18
  ETH: 0.01,
17
19
  USDC: 10,
18
- CBBTC: 0.0001,
19
20
  };
20
21
 
21
- function getMinimumWithFee(asset: string): number {
22
- const min = MINIMUM_DEPOSITS[asset] || 0;
23
- return min / (1 - DEPOSIT_FEE_PERCENT / 100);
22
+ /**
23
+ * Query the Entry contract for the exact gross amount (net + fee).
24
+ * This matches the contract's own fee math and avoids rounding mismatches.
25
+ */
26
+ async function getGrossAmount(
27
+ netWei: bigint,
28
+ rpcUrl: string | undefined,
29
+ ): Promise<{ grossWei: bigint; feeWei: bigint }> {
30
+ const publicClient = createPublicClient({
31
+ chain: base,
32
+ transport: http(rpcUrl),
33
+ });
34
+
35
+ const grossWei = await publicClient.readContract({
36
+ address: getAddresses().entry,
37
+ abi: ENTRY_ABI,
38
+ functionName: 'getDepositAmountWithFee',
39
+ args: [netWei],
40
+ }) as bigint;
41
+
42
+ return { grossWei, feeWei: grossWei - netWei };
24
43
  }
25
44
 
26
- const SUPPORTED_ASSETS = ['ETH', 'USDC', 'CBBTC'];
27
-
28
- // Progress helper - writes to stderr so JSON output stays clean
29
- function progress(msg: string, quiet?: boolean) {
30
- if (!quiet) {
31
- process.stderr.write(`\r\x1b[K${msg}`);
32
- }
33
- }
45
+ const SUPPORTED_ASSETS = ['ETH', 'USDC'];
34
46
 
35
47
  export function createDepositCommand(): Command {
36
48
  const deposit = new Command('deposit')
37
- .description('Deposit ETH, USDC, or cbBTC into Veil')
38
- .argument('<asset>', 'Asset to deposit (ETH, USDC, or CBBTC)')
39
- .argument('<amount>', 'Amount to deposit (e.g., 0.1)')
40
- .option('--deposit-key <key>', 'Your Veil deposit key (or set DEPOSIT_KEY env)')
41
- .option('--wallet-key <key>', 'Ethereum wallet key for signing (or set WALLET_KEY env)')
42
- .option('--rpc-url <url>', 'RPC URL (or set RPC_URL env)')
43
- .option('--unsigned', 'Output unsigned transaction payload (Bankr-compatible format)')
44
- .option('--quiet', 'Suppress progress output')
49
+ .description('Deposit ETH or USDC into Veil')
50
+ .argument('<asset>', 'Asset to deposit (ETH or USDC)')
51
+ .argument('<amount>', 'Amount to deposit this is what arrives in your Veil balance')
52
+ .option('--unsigned', 'Output unsigned transaction payload instead of sending')
53
+ .option('--json', 'Output as JSON')
54
+ .addHelpText('after', `
55
+ The amount you specify is the net amount that lands in your Veil balance.
56
+ The 0.3% protocol fee is automatically added on top.
57
+
58
+ Examples:
59
+ veil deposit ETH 0.1 # deposits 0.1 ETH (sends ~0.1003 ETH)
60
+ veil deposit USDC 100 # deposits 100 USDC (sends ~100.30 USDC)
61
+ veil deposit ETH 0.1 --unsigned
62
+ veil deposit ETH 0.1 --json
63
+ `)
45
64
  .action(async (asset: string, amount: string, options) => {
46
65
  try {
47
66
  const assetUpper = asset.toUpperCase();
48
67
 
49
- // Validate asset
50
68
  if (!SUPPORTED_ASSETS.includes(assetUpper)) {
51
69
  throw new CLIError(ErrorCode.INVALID_AMOUNT, `Unsupported asset: ${asset}. Supported: ${SUPPORTED_ASSETS.join(', ')}`);
52
70
  }
53
71
 
54
72
  const amountNum = parseFloat(amount);
55
- const minimumWithFee = getMinimumWithFee(assetUpper);
56
- const minimumNet = MINIMUM_DEPOSITS[assetUpper];
57
-
58
- // Check minimum deposit
59
- if (amountNum < minimumWithFee) {
73
+ const minimumNet = MINIMUM_NET[assetUpper];
74
+
75
+ if (amountNum < minimumNet) {
60
76
  throw new CLIError(
61
77
  ErrorCode.INVALID_AMOUNT,
62
- `Minimum deposit is ${minimumNet} ${assetUpper} (net). ` +
63
- `With ${DEPOSIT_FEE_PERCENT}% fee, send at least ${minimumWithFee.toFixed(assetUpper === 'ETH' ? 5 : 8)} ${assetUpper}.`
78
+ `Minimum deposit is ${minimumNet} ${assetUpper}.`
64
79
  );
65
80
  }
66
81
 
67
- // Get deposit key from option or env
68
- const depositKey = options.depositKey || process.env.DEPOSIT_KEY;
82
+ const rpcUrl = process.env.RPC_URL;
83
+ const poolConfig = POOL_CONFIG[assetUpper.toLowerCase() as 'eth' | 'usdc'];
84
+ const netWei = assetUpper === 'ETH'
85
+ ? parseEther(amount)
86
+ : parseUnits(amount, poolConfig.decimals);
87
+
88
+ const progress = createProgressReporter();
89
+ progress('Calculating fee...');
90
+
91
+ const { grossWei, feeWei } = await getGrossAmount(netWei, rpcUrl);
92
+ const grossStr = assetUpper === 'ETH'
93
+ ? formatEther(grossWei)
94
+ : formatUnits(grossWei, poolConfig.decimals);
95
+ const feeStr = assetUpper === 'ETH'
96
+ ? formatEther(feeWei)
97
+ : formatUnits(feeWei, poolConfig.decimals);
98
+
99
+ const depositKey = process.env.DEPOSIT_KEY;
69
100
  if (!depositKey) {
70
- throw new CLIError(ErrorCode.DEPOSIT_KEY_MISSING, 'Deposit key required. Use --deposit-key or set DEPOSIT_KEY in .env (run: veil init)');
101
+ throw new CLIError(ErrorCode.DEPOSIT_KEY_MISSING, 'DEPOSIT_KEY not set. Run "veil init" first.');
71
102
  }
72
103
 
73
- progress('Building transaction...', options.quiet);
104
+ progress('Building transaction...');
74
105
 
75
- // Build the deposit transaction
76
106
  let tx: TransactionData;
77
107
  let approveTx: TransactionData | null = null;
78
108
 
79
109
  if (assetUpper === 'USDC') {
80
- approveTx = buildApproveUSDCTx({ amount });
81
- tx = buildDepositUSDCTx({ depositKey, amount });
82
- } else if (assetUpper === 'CBBTC') {
83
- approveTx = buildApproveCBBTCTx({ amount });
84
- tx = buildDepositCBBTCTx({ depositKey, amount });
110
+ approveTx = buildApproveUSDCTx({ amount: grossStr });
111
+ tx = buildDepositUSDCTx({ depositKey, amount: grossStr });
85
112
  } else {
86
- tx = buildDepositETHTx({ depositKey, amount });
113
+ tx = buildDepositETHTx({ depositKey, amount: grossStr });
87
114
  }
88
115
 
89
- // Handle --unsigned mode (no wallet required, just build payload)
116
+ // --unsigned mode
90
117
  if (options.unsigned) {
91
- progress('', options.quiet); // Clear line
118
+ clearProgress();
92
119
  const payloads: Record<string, unknown>[] = [];
93
120
 
94
- // Include approval tx for ERC20 tokens
95
121
  if (approveTx) {
96
122
  payloads.push({
97
123
  step: 'approve',
@@ -110,52 +136,95 @@ export function createDepositCommand(): Command {
110
136
  chainId: 8453,
111
137
  });
112
138
 
113
- console.log(JSON.stringify(payloads.length === 1 ? payloads[0] : payloads, null, 2));
139
+ printJson(payloads.length === 1 ? payloads[0] : payloads);
114
140
  return;
115
141
  }
116
142
 
117
- // Regular mode: sign and send
118
143
  const config = getConfig(options);
119
144
  const address = getAddress(config.privateKey);
120
145
 
121
- // For ETH deposits, check ETH balance
122
146
  if (assetUpper === 'ETH') {
123
- progress('Checking balance...', options.quiet);
147
+ progress('Checking balance...');
124
148
  const balance = await getBalance(address, config.rpcUrl);
125
- const amountWei = parseEther(amount);
126
-
127
- if (balance < amountWei) {
128
- progress('', options.quiet);
129
- throw new CLIError(ErrorCode.INSUFFICIENT_BALANCE, `Insufficient ETH balance. Have: ${formatEther(balance)} ETH, Need: ${amount} ETH`);
149
+
150
+ if (balance < grossWei) {
151
+ clearProgress();
152
+ throw new CLIError(
153
+ ErrorCode.INSUFFICIENT_BALANCE,
154
+ `Insufficient ETH balance. Have: ${formatEther(balance)} ETH, Need: ${grossStr} ETH (${amount} + fee)`
155
+ );
130
156
  }
131
157
  }
132
158
 
133
- // Send approval transaction for ERC20 tokens
134
159
  if (approveTx) {
135
- progress(`Approving ${assetUpper}...`, options.quiet);
136
- await sendTransaction(config, approveTx);
160
+ progress(`Approving ${assetUpper}...`);
161
+ const approvalResult = await sendTransaction(config, approveTx);
162
+ if (assetUpper === 'USDC') {
163
+ const publicClient = createPublicClient({
164
+ chain: base,
165
+ transport: http(config.rpcUrl),
166
+ });
167
+ const addresses = getAddresses();
168
+ let allowance = await publicClient.readContract({
169
+ address: getAddresses().usdcToken,
170
+ abi: ERC20_ABI,
171
+ functionName: 'allowance',
172
+ args: [address, addresses.entry],
173
+ }) as bigint;
174
+ for (let confirmations = 2; allowance < grossWei && confirmations <= 3; confirmations++) {
175
+ await publicClient.waitForTransactionReceipt({
176
+ hash: approvalResult.hash,
177
+ confirmations,
178
+ });
179
+ allowance = await publicClient.readContract({
180
+ address: addresses.usdcToken,
181
+ abi: ERC20_ABI,
182
+ functionName: 'allowance',
183
+ args: [address, addresses.entry],
184
+ }) as bigint;
185
+ }
186
+ if (allowance < grossWei) {
187
+ throw new CLIError(
188
+ ErrorCode.CONTRACT_ERROR,
189
+ `USDC approval is not yet visible on RPC after confirmation. Allowance ${allowance.toString()} < required ${grossWei.toString()}.`
190
+ );
191
+ }
192
+ }
137
193
  }
138
194
 
139
- progress('Sending deposit transaction...', options.quiet);
140
-
141
- // Send the deposit transaction
195
+ progress('Sending deposit transaction...');
142
196
  const result = await sendTransaction(config, tx);
197
+ progress('Confirming...');
198
+ clearProgress();
143
199
 
144
- progress('Confirming...', options.quiet);
145
-
146
- // Clear progress line
147
- progress('', options.quiet);
148
-
149
- console.log(JSON.stringify({
200
+ const output = {
150
201
  success: result.receipt.status === 'success',
151
202
  hash: result.hash,
152
203
  asset: assetUpper,
153
204
  amount,
205
+ fee: feeStr,
206
+ totalSent: grossStr,
154
207
  blockNumber: result.receipt.blockNumber.toString(),
155
- gasUsed: result.receipt.gasUsed.toString(),
156
- }, null, 2));
208
+ };
209
+
210
+ if (options.json) {
211
+ printJson(output);
212
+ return;
213
+ }
214
+
215
+ printHeader('Deposit Submitted');
216
+ printFields([
217
+ { label: 'Asset', value: assetUpper },
218
+ { label: 'Amount', value: `${amount} ${assetUpper}` },
219
+ { label: 'Fee', value: `${feeStr} ${assetUpper} (0.3%)` },
220
+ { label: 'Total sent', value: `${grossStr} ${assetUpper}` },
221
+ { label: 'From', value: address },
222
+ { label: 'Transaction', value: txUrl(result.hash) },
223
+ { label: 'Block', value: result.receipt.blockNumber },
224
+ ]);
225
+ printLine();
157
226
  } catch (error) {
158
- progress('', options.quiet); // Clear progress line
227
+ clearProgress();
159
228
  handleCLIError(error);
160
229
  }
161
230
  });
@@ -8,6 +8,8 @@ import { existsSync, readFileSync, writeFileSync } from 'fs';
8
8
  import { dirname } from 'path';
9
9
  import { mkdirSync } from 'fs';
10
10
  import { Keypair } from '../../keypair.js';
11
+ import { handleCLIError, CLIError, ErrorCode } from '../errors.js';
12
+ import { printFields, printHeader, printJson, printLine } from '../output.js';
11
13
 
12
14
  /**
13
15
  * Prompt user for yes/no confirmation
@@ -33,6 +35,18 @@ function getDefaultEnvPath(): string {
33
35
  return '.env.veil';
34
36
  }
35
37
 
38
+ /**
39
+ * Enforce mutually exclusive wallet env modes.
40
+ */
41
+ function ensureAddressEnvConsistency(): void {
42
+ if (process.env.WALLET_KEY && process.env.SIGNER_ADDRESS) {
43
+ throw new CLIError(
44
+ ErrorCode.CONFIG_CONFLICT,
45
+ 'WALLET_KEY and SIGNER_ADDRESS are mutually exclusive. Set only one.',
46
+ );
47
+ }
48
+ }
49
+
36
50
  /**
37
51
  * Check if VEIL_KEY exists in an env file
38
52
  */
@@ -62,7 +76,6 @@ function updateEnvVar(content: string, key: string, value: string): string {
62
76
  * Save Veil keypair to a file
63
77
  */
64
78
  function saveVeilKeypair(veilKey: string, depositKey: string, envPath: string): void {
65
- // Ensure directory exists
66
79
  const dir = dirname(envPath);
67
80
  if (dir && dir !== '.' && !existsSync(dir)) {
68
81
  mkdirSync(dir, { recursive: true });
@@ -85,99 +98,116 @@ function saveVeilKeypair(veilKey: string, depositKey: string, envPath: string):
85
98
  /**
86
99
  * Resolve wallet key from CLI flag or WALLET_KEY env var
87
100
  */
88
- function resolveWalletKey(options: { walletKey?: string }): `0x${string}` {
89
- const raw = options.walletKey || process.env.WALLET_KEY;
101
+ function resolveWalletKey(): `0x${string}` {
102
+ const raw = process.env.WALLET_KEY;
90
103
  if (!raw) {
91
- throw new Error('Wallet key required for --sign-message. Use --wallet-key <key> or set WALLET_KEY env var.');
104
+ const hasExternalSigner = Boolean(process.env.SIGNER_ADDRESS);
105
+ throw new CLIError(
106
+ ErrorCode.WALLET_KEY_MISSING,
107
+ hasExternalSigner
108
+ ? 'WALLET_KEY env var required for wallet-derived init. If you are using an external signer, use "veil init --signature 0x..." or use --generate for a random keypair.'
109
+ : 'WALLET_KEY env var required. Set it or use --generate for a random keypair.',
110
+ );
92
111
  }
93
112
  const key = raw.startsWith('0x') ? raw : `0x${raw}`;
94
113
  if (key.length !== 66) {
95
- throw new Error('Invalid wallet key format. Must be a 0x-prefixed 64-character hex string.');
114
+ throw new CLIError(ErrorCode.WALLET_KEY_MISSING, 'Invalid WALLET_KEY format. Must be a 0x-prefixed 64-character hex string.');
96
115
  }
97
116
  return key as `0x${string}`;
98
117
  }
99
118
 
100
119
  export function createInitCommand(): Command {
101
120
  const init = new Command('init')
102
- .description('Generate a new Veil keypair')
121
+ .description('Derive a Veil keypair from your wallet (or generate a random one)')
122
+ .option('--generate', 'Generate a random keypair instead of deriving from wallet')
123
+ .option('--signature <sig>', 'Derive keypair from a pre-computed EIP-191 personal_sign signature')
103
124
  .option('--force', 'Overwrite existing keypair without prompting')
104
125
  .option('--json', 'Output as JSON (no prompts, no file save)')
105
126
  .option('--no-save', 'Print keypair without saving to file')
106
- .option('--sign-message', 'Derive keypair from wallet signature (same as frontend login)')
107
- .option('--wallet-key <key>', 'Ethereum wallet private key (or set WALLET_KEY env var)')
108
- .option('--signature <sig>', 'Derive keypair from a pre-computed EIP-191 personal_sign signature')
127
+ .addHelpText('after', `
128
+ Examples:
129
+ veil init Derive from WALLET_KEY (default)
130
+ veil init --generate Generate a random keypair
131
+ veil init --signature 0x... Derive from a pre-computed signature
132
+ veil init --json Output keypair as JSON
133
+ `)
109
134
  .action(async (options) => {
110
- const envPath = getDefaultEnvPath();
111
-
112
- /**
113
- * Create keypair: derived from wallet, from signature, or random
114
- */
115
- async function createKp(): Promise<Keypair> {
116
- if (options.signMessage) {
117
- const walletKey = resolveWalletKey(options);
135
+ try {
136
+ ensureAddressEnvConsistency();
137
+ const envPath = getDefaultEnvPath();
138
+ const useRandom = options.generate;
139
+ const useSignature = options.signature;
140
+
141
+ async function createKp(): Promise<Keypair> {
142
+ if (useSignature) {
143
+ return Keypair.fromSignature(options.signature);
144
+ }
145
+ if (useRandom) {
146
+ return new Keypair();
147
+ }
148
+ const walletKey = resolveWalletKey();
118
149
  return Keypair.fromWalletKey(walletKey);
119
150
  }
120
- if (options.signature) {
121
- return Keypair.fromSignature(options.signature);
122
- }
123
- return new Keypair();
124
- }
125
151
 
126
- const derivationLabel = options.signMessage
127
- ? 'Derived Veil keypair from wallet signature'
128
- : options.signature
129
- ? 'Derived Veil keypair from provided signature'
130
- : 'Generated new Veil keypair';
152
+ const derivation: 'wallet-signature' | 'provided-signature' | 'random' =
153
+ useSignature ? 'provided-signature'
154
+ : useRandom ? 'random'
155
+ : 'wallet-signature';
156
+
157
+ const derivationLabel =
158
+ useSignature ? 'Derived keypair from provided signature'
159
+ : useRandom ? 'Generated random keypair'
160
+ : 'Derived keypair from wallet signature';
131
161
 
132
- // JSON mode: no prompts, no save, just output JSON
133
- if (options.json) {
134
162
  const kp = await createKp();
135
- console.log(JSON.stringify({
163
+ const result = {
136
164
  veilKey: kp.privkey,
165
+ veilPrivateKey: kp.privkey,
137
166
  depositKey: kp.depositKey(),
138
- }, null, 2));
139
- process.exit(0);
140
- return;
141
- }
167
+ derivation,
168
+ };
142
169
 
143
- // No-save mode: print but don't save
144
- if (!options.save) {
145
- const kp = await createKp();
146
- console.log(`\n${derivationLabel}:\n`);
147
- console.log('Veil Private Key:');
148
- console.log(` ${kp.privkey}\n`);
149
- console.log('Deposit Key (register this on-chain):');
150
- console.log(` ${kp.depositKey()}\n`);
151
- console.log('(Not saved - run without --no-save to save to .env.veil)');
152
- process.exit(0);
153
- return;
154
- }
170
+ if (options.json) {
171
+ printJson(result);
172
+ return;
173
+ }
155
174
 
156
- // Check if VEIL_KEY already exists (unless --force)
157
- const keyExists = veilKeyExistsAt(envPath);
158
-
159
- if (keyExists && !options.force) {
160
- console.log(`\nWARNING: A Veil key already exists in ${envPath}`);
161
- const proceed = await confirm('Create a new key? This will overwrite the existing one');
162
- if (!proceed) {
163
- console.log('Aborted. Existing key preserved.');
164
- process.exit(0);
175
+ if (!options.save) {
176
+ printHeader(derivationLabel);
177
+ printFields([
178
+ { label: 'Veil private key', value: kp.privkey },
179
+ { label: 'Deposit key', value: kp.depositKey() },
180
+ { label: 'Saved', value: 'no' },
181
+ ]);
182
+ printLine();
183
+ printLine('Run `veil init` without `--no-save` to persist these keys to .env.veil.');
184
+ printLine();
165
185
  return;
166
186
  }
187
+
188
+ const keyExists = veilKeyExistsAt(envPath);
189
+ if (keyExists && !options.force) {
190
+ printLine(`WARNING: A Veil key already exists in ${envPath}`);
191
+ const proceed = await confirm('Create a new key? This will overwrite the existing one');
192
+ if (!proceed) {
193
+ printLine('Aborted. Existing key preserved.');
194
+ return;
195
+ }
196
+ }
197
+
198
+ saveVeilKeypair(kp.privkey!, kp.depositKey(), envPath);
199
+ printHeader(derivationLabel);
200
+ printFields([
201
+ { label: 'Veil private key', value: kp.privkey },
202
+ { label: 'Deposit key', value: kp.depositKey() },
203
+ { label: 'Saved to', value: envPath },
204
+ ]);
205
+ printLine();
206
+ printLine('Next step: veil register');
207
+ printLine();
208
+ } catch (error) {
209
+ handleCLIError(error);
167
210
  }
168
-
169
- const kp = await createKp();
170
-
171
- console.log(`\n${derivationLabel}:\n`);
172
- console.log('Veil Private Key:');
173
- console.log(` ${kp.privkey}\n`);
174
- console.log('Deposit Key (register this on-chain):');
175
- console.log(` ${kp.depositKey()}\n`);
176
-
177
- saveVeilKeypair(kp.privkey!, kp.depositKey(), envPath);
178
- console.log(`Saved to ${envPath}`);
179
- console.log('\nNext step: veil register');
180
- process.exit(0);
181
211
  });
182
212
 
183
213
  return init;
@@ -4,27 +4,45 @@
4
4
 
5
5
  import { Command } from 'commander';
6
6
  import { Keypair } from '../../keypair.js';
7
+ import { handleCLIError, CLIError, ErrorCode } from '../errors.js';
8
+ import { printFields, printJson, printLine } from '../output.js';
7
9
 
8
10
  export function createKeypairCommand(): Command {
9
11
  const keypair = new Command('keypair')
10
- .description('Show current Veil keypair as JSON')
12
+ .description('Show your current Veil keypair')
13
+ .option('--json', 'Output as JSON')
14
+ .addHelpText('after', `
15
+ Examples:
16
+ veil keypair
17
+ veil keypair --json
18
+ `)
11
19
  .action(() => {
12
- const veilKey = process.env.VEIL_KEY;
13
-
14
- if (!veilKey) {
15
- console.log(JSON.stringify({
16
- success: false,
17
- error: 'No keypair found. Run "veil init" first.'
18
- }, null, 2));
19
- process.exit(1);
20
+ try {
21
+ const veilKey = process.env.VEIL_KEY;
22
+
23
+ if (!veilKey) {
24
+ throw new CLIError(ErrorCode.VEIL_KEY_MISSING, 'No keypair found. Run "veil init" first.');
25
+ }
26
+
27
+ const kp = new Keypair(veilKey);
28
+ const result = {
29
+ veilPrivateKey: kp.privkey,
30
+ depositKey: kp.depositKey(),
31
+ };
32
+
33
+ if ((keypair.opts() as { json?: boolean }).json) {
34
+ printJson(result);
35
+ return;
36
+ }
37
+
38
+ printLine('Veil keypair');
39
+ printFields([
40
+ { label: 'Veil private key', value: result.veilPrivateKey },
41
+ { label: 'Deposit key', value: result.depositKey },
42
+ ]);
43
+ } catch (error) {
44
+ handleCLIError(error);
20
45
  }
21
-
22
- const kp = new Keypair(veilKey);
23
-
24
- console.log(JSON.stringify({
25
- veilPrivateKey: kp.privkey,
26
- depositKey: kp.depositKey(),
27
- }, null, 2));
28
46
  });
29
47
 
30
48
  return keypair;