@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
package/src/cli/config.ts
CHANGED
|
@@ -2,22 +2,50 @@
|
|
|
2
2
|
* CLI configuration handling
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { CLIError, ErrorCode } from './errors.js';
|
|
6
|
+
import { getAddress } from './wallet.js';
|
|
5
7
|
import type { WalletConfig } from './wallet.js';
|
|
6
8
|
|
|
7
9
|
export interface CLIOptions {
|
|
8
|
-
walletKey?: string;
|
|
9
10
|
rpcUrl?: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
export interface AddressOptions {
|
|
14
|
+
address?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ResolvedAddress {
|
|
18
|
+
address: `0x${string}`;
|
|
19
|
+
source: 'flag' | 'wallet-key' | 'signer-address';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function validateAddress(address: string, sourceLabel: string): `0x${string}` {
|
|
23
|
+
const normalized = address.trim();
|
|
24
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(normalized)) {
|
|
25
|
+
throw new CLIError(ErrorCode.INVALID_ADDRESS, `${sourceLabel} must be a valid 0x-prefixed Ethereum address.`);
|
|
26
|
+
}
|
|
27
|
+
return normalized as `0x${string}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function ensureAddressEnvConsistency(): void {
|
|
31
|
+
if (process.env.WALLET_KEY && process.env.SIGNER_ADDRESS) {
|
|
32
|
+
throw new CLIError(
|
|
33
|
+
ErrorCode.CONFIG_CONFLICT,
|
|
34
|
+
'WALLET_KEY and SIGNER_ADDRESS are mutually exclusive. Set only one.',
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
12
39
|
/**
|
|
13
40
|
* Get wallet configuration from CLI options and environment variables
|
|
14
41
|
*/
|
|
15
42
|
export function getConfig(options: CLIOptions): WalletConfig {
|
|
16
|
-
|
|
43
|
+
ensureAddressEnvConsistency();
|
|
44
|
+
const walletKey = process.env.WALLET_KEY;
|
|
17
45
|
const rpcUrl = options.rpcUrl || process.env.RPC_URL || 'https://mainnet.base.org';
|
|
18
46
|
|
|
19
47
|
if (!walletKey) {
|
|
20
|
-
throw new Error('
|
|
48
|
+
throw new Error('WALLET_KEY env var required. Set it before running this command.');
|
|
21
49
|
}
|
|
22
50
|
|
|
23
51
|
// Validate wallet key format
|
|
@@ -38,6 +66,58 @@ export function getVeilKey(options: { veilKey?: string }): string | undefined {
|
|
|
38
66
|
return options.veilKey || process.env.VEIL_KEY;
|
|
39
67
|
}
|
|
40
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Resolve an address for query / unsigned flows.
|
|
71
|
+
* Prefers explicit --address, then derives from WALLET_KEY, then falls back to SIGNER_ADDRESS.
|
|
72
|
+
*/
|
|
73
|
+
export function resolveAddress(
|
|
74
|
+
options: AddressOptions = {},
|
|
75
|
+
config: { required?: boolean; allowInvalidWalletKey?: boolean } = {},
|
|
76
|
+
): ResolvedAddress | null {
|
|
77
|
+
ensureAddressEnvConsistency();
|
|
78
|
+
|
|
79
|
+
if (options.address) {
|
|
80
|
+
return {
|
|
81
|
+
address: validateAddress(options.address, '--address'),
|
|
82
|
+
source: 'flag',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const walletKey = process.env.WALLET_KEY;
|
|
87
|
+
if (walletKey) {
|
|
88
|
+
try {
|
|
89
|
+
return {
|
|
90
|
+
address: getAddress(walletKey as `0x${string}`),
|
|
91
|
+
source: 'wallet-key',
|
|
92
|
+
};
|
|
93
|
+
} catch {
|
|
94
|
+
if (!config.allowInvalidWalletKey) {
|
|
95
|
+
throw new CLIError(
|
|
96
|
+
ErrorCode.WALLET_KEY_MISSING,
|
|
97
|
+
'Invalid WALLET_KEY format. Must be a 0x-prefixed 64-character hex string.',
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const signerAddress = process.env.SIGNER_ADDRESS;
|
|
104
|
+
if (signerAddress) {
|
|
105
|
+
return {
|
|
106
|
+
address: validateAddress(signerAddress, 'SIGNER_ADDRESS'),
|
|
107
|
+
source: 'signer-address',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (config.required) {
|
|
112
|
+
throw new CLIError(
|
|
113
|
+
ErrorCode.WALLET_KEY_MISSING,
|
|
114
|
+
'Must provide --address, set SIGNER_ADDRESS, or set WALLET_KEY env.',
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
41
121
|
/**
|
|
42
122
|
* Load environment variables from .env.veil and .env files
|
|
43
123
|
*/
|
|
@@ -46,10 +126,10 @@ export function loadEnv(): void {
|
|
|
46
126
|
// Dynamic import to avoid bundling issues
|
|
47
127
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
48
128
|
const dotenv = require('dotenv');
|
|
49
|
-
|
|
129
|
+
|
|
50
130
|
// Load .env.veil first (Veil-specific config)
|
|
51
131
|
dotenv.config({ path: '.env.veil', quiet: true });
|
|
52
|
-
|
|
132
|
+
|
|
53
133
|
// Then load .env (for WALLET_KEY, RPC_URL if not in .env.veil)
|
|
54
134
|
dotenv.config({ quiet: true });
|
|
55
135
|
} catch {
|
package/src/cli/errors.ts
CHANGED
|
@@ -9,6 +9,7 @@ export const ErrorCode = {
|
|
|
9
9
|
VEIL_KEY_MISSING: 'VEIL_KEY_MISSING',
|
|
10
10
|
WALLET_KEY_MISSING: 'WALLET_KEY_MISSING',
|
|
11
11
|
DEPOSIT_KEY_MISSING: 'DEPOSIT_KEY_MISSING',
|
|
12
|
+
CONFIG_CONFLICT: 'CONFIG_CONFLICT',
|
|
12
13
|
INVALID_ADDRESS: 'INVALID_ADDRESS',
|
|
13
14
|
INVALID_AMOUNT: 'INVALID_AMOUNT',
|
|
14
15
|
INSUFFICIENT_BALANCE: 'INSUFFICIENT_BALANCE',
|
|
@@ -51,6 +52,9 @@ function inferErrorCode(message: string): ErrorCodeType {
|
|
|
51
52
|
if (msg.includes('deposit_key') || msg.includes('deposit key')) {
|
|
52
53
|
return ErrorCode.DEPOSIT_KEY_MISSING;
|
|
53
54
|
}
|
|
55
|
+
if (msg.includes('mutually exclusive') || msg.includes('config conflict') || msg.includes('signer_address')) {
|
|
56
|
+
return ErrorCode.CONFIG_CONFLICT;
|
|
57
|
+
}
|
|
54
58
|
if (msg.includes('invalid') && msg.includes('address')) {
|
|
55
59
|
return ErrorCode.INVALID_ADDRESS;
|
|
56
60
|
}
|
package/src/cli/index.ts
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* veil register # Register on-chain
|
|
9
9
|
* veil deposit ETH 0.1 # Deposit ETH
|
|
10
10
|
* veil balance # Show all balances
|
|
11
|
-
* veil queue
|
|
12
|
-
* veil private
|
|
11
|
+
* veil balance queue # Show pending queue deposits
|
|
12
|
+
* veil balance private # Show private balance
|
|
13
13
|
* veil withdraw ETH 0.1 0x... # Withdraw to public address
|
|
14
14
|
* veil transfer ETH 0.1 0x... # Transfer privately
|
|
15
15
|
* veil merge ETH 0.5 # Merge UTXOs (self-transfer)
|
|
@@ -36,7 +36,14 @@ const program = new Command();
|
|
|
36
36
|
program
|
|
37
37
|
.name('veil')
|
|
38
38
|
.description('CLI for Veil Cash privacy pools on Base')
|
|
39
|
-
.version('0.
|
|
39
|
+
.version('0.5.0')
|
|
40
|
+
.addHelpText('after', `
|
|
41
|
+
Getting started:
|
|
42
|
+
veil init
|
|
43
|
+
veil register
|
|
44
|
+
veil deposit ETH 0.1
|
|
45
|
+
veil balance
|
|
46
|
+
`);
|
|
40
47
|
|
|
41
48
|
// Add commands
|
|
42
49
|
program.addCommand(createInitCommand());
|
|
@@ -44,12 +51,23 @@ program.addCommand(createKeypairCommand());
|
|
|
44
51
|
program.addCommand(createRegisterCommand());
|
|
45
52
|
program.addCommand(createDepositCommand());
|
|
46
53
|
program.addCommand(createBalanceCommand());
|
|
47
|
-
program.addCommand(createQueueBalanceCommand());
|
|
48
|
-
program.addCommand(createPrivateBalanceCommand());
|
|
54
|
+
program.addCommand(createQueueBalanceCommand(), { hidden: true });
|
|
55
|
+
program.addCommand(createPrivateBalanceCommand(), { hidden: true });
|
|
49
56
|
program.addCommand(createWithdrawCommand());
|
|
50
57
|
program.addCommand(createTransferCommand());
|
|
51
58
|
program.addCommand(createMergeCommand());
|
|
52
59
|
program.addCommand(createStatusCommand());
|
|
53
60
|
|
|
61
|
+
const knownTopLevelCommands = new Set([
|
|
62
|
+
...program.commands.map((command) => command.name()),
|
|
63
|
+
'help',
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
const firstArg = process.argv[2];
|
|
67
|
+
if (firstArg && !firstArg.startsWith('-') && !knownTopLevelCommands.has(firstArg)) {
|
|
68
|
+
console.error(`error: unknown command '${firstArg}'`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
54
72
|
// Parse and execute
|
|
55
73
|
program.parse();
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI output helpers.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const DIM = '\x1b[2m';
|
|
6
|
+
const BOLD = '\x1b[1m';
|
|
7
|
+
const RESET = '\x1b[0m';
|
|
8
|
+
|
|
9
|
+
export interface JsonOutputOption {
|
|
10
|
+
json?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function printJson(value: unknown): void {
|
|
14
|
+
console.log(JSON.stringify(value, null, 2));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function printLine(value = ''): void {
|
|
18
|
+
console.log(value);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function printHeader(title: string): void {
|
|
22
|
+
console.log();
|
|
23
|
+
console.log(`${BOLD}${title}${RESET}`);
|
|
24
|
+
console.log(`${DIM}${'─'.repeat(40)}${RESET}`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function printSection(title: string): void {
|
|
28
|
+
console.log();
|
|
29
|
+
console.log(`${BOLD}${title}${RESET}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function printDivider(): void {
|
|
33
|
+
console.log();
|
|
34
|
+
console.log(`${DIM}${'─'.repeat(40)}${RESET}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function printFields(fields: Array<{ label: string; value: unknown }>): void {
|
|
38
|
+
const visibleFields = fields.filter((field) => field.value !== undefined);
|
|
39
|
+
const width = visibleFields.reduce((max, field) => Math.max(max, field.label.length), 0);
|
|
40
|
+
|
|
41
|
+
for (const field of visibleFields) {
|
|
42
|
+
const label = `${DIM}${field.label.padEnd(width)}${RESET}`;
|
|
43
|
+
console.log(` ${label} ${formatValue(field.value)}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function printList(items: string[]): void {
|
|
48
|
+
if (items.length === 0) {
|
|
49
|
+
console.log(` ${DIM}(none)${RESET}`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for (const item of items) {
|
|
54
|
+
console.log(` ${item}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function maskValue(value: string, start = 10, end = 8): string {
|
|
59
|
+
if (value.length <= start + end + 3) {
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return `${value.slice(0, start)}...${value.slice(-end)}`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function txUrl(hash: string): string {
|
|
67
|
+
return `https://basescan.org/tx/${hash}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function clearProgress(): void {
|
|
71
|
+
process.stderr.write('\r\x1b[K');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function createProgressReporter(): (stage: string, detail?: string) => void {
|
|
75
|
+
return (stage: string, detail?: string) => {
|
|
76
|
+
const message = detail ? `${stage}: ${detail}` : stage;
|
|
77
|
+
process.stderr.write(`\r\x1b[K${message}`);
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function formatValue(value: unknown): string {
|
|
82
|
+
if (value === null) return 'null';
|
|
83
|
+
if (value === undefined) return '';
|
|
84
|
+
if (typeof value === 'boolean') return value ? 'yes' : 'no';
|
|
85
|
+
if (typeof value === 'object') return JSON.stringify(value);
|
|
86
|
+
return String(value);
|
|
87
|
+
}
|
package/src/cli/wallet.ts
CHANGED
|
@@ -9,12 +9,13 @@ import {
|
|
|
9
9
|
decodeErrorResult,
|
|
10
10
|
BaseError,
|
|
11
11
|
ContractFunctionRevertedError,
|
|
12
|
+
formatUnits,
|
|
12
13
|
} from 'viem';
|
|
13
14
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
14
15
|
import { base } from 'viem/chains';
|
|
15
16
|
import type { TransactionData } from '../types.js';
|
|
16
|
-
import { ENTRY_ABI } from '../abi.js';
|
|
17
|
-
import { getAddresses } from '../addresses.js';
|
|
17
|
+
import { ENTRY_ABI, ERC20_ABI } from '../abi.js';
|
|
18
|
+
import { getAddresses, POOL_CONFIG, ADDRESSES } from '../addresses.js';
|
|
18
19
|
|
|
19
20
|
export interface WalletConfig {
|
|
20
21
|
privateKey: `0x${string}`;
|
|
@@ -63,14 +64,25 @@ export function createWallet(config: WalletConfig): any {
|
|
|
63
64
|
* Known custom error selectors (first 4 bytes of keccak256 hash of error signature)
|
|
64
65
|
*/
|
|
65
66
|
const ERROR_SELECTORS: Record<string, string> = {
|
|
67
|
+
'0xd92e233d': 'ZeroAddress',
|
|
68
|
+
'0xe9e26e4e': 'OnlyOwnerCanRegister',
|
|
69
|
+
'0x1f2a2005': 'ZeroAmount',
|
|
66
70
|
'0x3ee5aeb5': 'DepositsDisabled',
|
|
71
|
+
'0x4cba3441': 'InvalidDepositKey',
|
|
72
|
+
'0xc64891a5': 'NotRelayer',
|
|
73
|
+
'0xfcc00b30': 'NoETHBalance',
|
|
74
|
+
'0x7b7b36da': 'NoTokenBalance',
|
|
75
|
+
'0x7ffddb78': 'TokenApproveFailed',
|
|
76
|
+
'0xb12d13eb': 'ETHTransferFailed',
|
|
77
|
+
'0x1f6d5aef': 'NonceUsed',
|
|
78
|
+
'0x82b42900': 'Unauthorized',
|
|
79
|
+
'0x1ab7da6b': 'DeadlineExpired',
|
|
67
80
|
'0x8e8f6d6f': 'MinimumDepositNotMet',
|
|
68
81
|
'0x5cd83192': 'NotAllowedToDeposit',
|
|
69
82
|
'0x6f5e8818': 'UserNotRegistered',
|
|
70
83
|
'0x8a2ef116': 'UserAlreadyRegistered',
|
|
71
84
|
'0x0dc149f0': 'InvalidDepositKey',
|
|
72
85
|
'0x584a7938': 'InvalidDepositKeyForUser',
|
|
73
|
-
'0xd92e233d': 'OnlyOwnerCanRegister',
|
|
74
86
|
};
|
|
75
87
|
|
|
76
88
|
/**
|
|
@@ -106,11 +118,17 @@ function decodeCustomError(error: unknown): string | null {
|
|
|
106
118
|
|
|
107
119
|
if (possibleData && typeof possibleData === 'string' && possibleData.startsWith('0x')) {
|
|
108
120
|
try {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
121
|
+
for (const abi of [ENTRY_ABI] as const) {
|
|
122
|
+
try {
|
|
123
|
+
const decoded = decodeErrorResult({
|
|
124
|
+
abi,
|
|
125
|
+
data: possibleData as `0x${string}`,
|
|
126
|
+
});
|
|
127
|
+
return decoded.errorName;
|
|
128
|
+
} catch {
|
|
129
|
+
// Try the next ABI
|
|
130
|
+
}
|
|
131
|
+
}
|
|
114
132
|
} catch {
|
|
115
133
|
// Try selector lookup
|
|
116
134
|
const selector = possibleData.slice(0, 10).toLowerCase();
|
|
@@ -151,16 +169,26 @@ export async function sendTransaction(
|
|
|
151
169
|
}
|
|
152
170
|
|
|
153
171
|
// Send the transaction
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
172
|
+
let hash: `0x${string}`;
|
|
173
|
+
try {
|
|
174
|
+
hash = await walletClient.sendTransaction({
|
|
175
|
+
account,
|
|
176
|
+
chain,
|
|
177
|
+
to: tx.to,
|
|
178
|
+
data: tx.data,
|
|
179
|
+
value: tx.value,
|
|
180
|
+
});
|
|
181
|
+
} catch (error) {
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
161
184
|
|
|
162
185
|
// Wait for confirmation
|
|
163
|
-
|
|
186
|
+
let receipt;
|
|
187
|
+
try {
|
|
188
|
+
receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
189
|
+
} catch (error) {
|
|
190
|
+
throw error;
|
|
191
|
+
}
|
|
164
192
|
|
|
165
193
|
return {
|
|
166
194
|
hash,
|
|
@@ -196,6 +224,37 @@ export async function getBalance(
|
|
|
196
224
|
return publicClient.getBalance({ address });
|
|
197
225
|
}
|
|
198
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Get public wallet balances (ETH + USDC) for an address
|
|
229
|
+
*/
|
|
230
|
+
export async function getWalletBalances(
|
|
231
|
+
address: `0x${string}`,
|
|
232
|
+
rpcUrl?: string
|
|
233
|
+
): Promise<{ eth: string; ethWei: string; usdc: string; usdcWei: string }> {
|
|
234
|
+
const transport = http(rpcUrl);
|
|
235
|
+
const publicClient = createPublicClient({
|
|
236
|
+
chain: base,
|
|
237
|
+
transport,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
const [ethBalance, usdcBalance] = await Promise.all([
|
|
241
|
+
publicClient.getBalance({ address }),
|
|
242
|
+
publicClient.readContract({
|
|
243
|
+
address: ADDRESSES.usdcToken as `0x${string}`,
|
|
244
|
+
abi: ERC20_ABI,
|
|
245
|
+
functionName: 'balanceOf',
|
|
246
|
+
args: [address],
|
|
247
|
+
}) as Promise<bigint>,
|
|
248
|
+
]);
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
eth: formatUnits(ethBalance, POOL_CONFIG.eth.decimals),
|
|
252
|
+
ethWei: ethBalance.toString(),
|
|
253
|
+
usdc: formatUnits(usdcBalance, POOL_CONFIG.usdc.decimals),
|
|
254
|
+
usdcWei: usdcBalance.toString(),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
199
258
|
/**
|
|
200
259
|
* Check if an address is already registered (has a deposit key on-chain)
|
|
201
260
|
*/
|
package/src/deposit.ts
CHANGED
|
@@ -181,65 +181,7 @@ export function buildDepositUSDCTx(options: {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
|
-
* Build a transaction
|
|
185
|
-
* Must be called before depositCBBTC if allowance is insufficient
|
|
186
|
-
*
|
|
187
|
-
* @param options - Approval options
|
|
188
|
-
* @param options.amount - Amount to approve (human readable, e.g., '0.5')
|
|
189
|
-
* @returns Transaction data
|
|
190
|
-
*/
|
|
191
|
-
export function buildApproveCBBTCTx(options: {
|
|
192
|
-
amount: string;
|
|
193
|
-
}): TransactionData {
|
|
194
|
-
const { amount } = options;
|
|
195
|
-
const addresses = getAddresses();
|
|
196
|
-
|
|
197
|
-
const amountWei = parseUnits(amount, POOL_CONFIG.cbbtc.decimals);
|
|
198
|
-
|
|
199
|
-
const data = encodeFunctionData({
|
|
200
|
-
abi: ERC20_ABI,
|
|
201
|
-
functionName: 'approve',
|
|
202
|
-
args: [addresses.entry, amountWei],
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
to: addresses.cbbtcToken,
|
|
207
|
-
data,
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Build a transaction to deposit cbBTC
|
|
213
|
-
* Note: You must approve cbBTC first using buildApproveCBBTCTx
|
|
214
|
-
*
|
|
215
|
-
* @param options - Deposit options
|
|
216
|
-
* @param options.depositKey - Deposit key from Keypair.depositKey()
|
|
217
|
-
* @param options.amount - Amount to deposit (human readable, e.g., '0.5')
|
|
218
|
-
* @returns Transaction data
|
|
219
|
-
*/
|
|
220
|
-
export function buildDepositCBBTCTx(options: {
|
|
221
|
-
depositKey: string;
|
|
222
|
-
amount: string;
|
|
223
|
-
}): TransactionData {
|
|
224
|
-
const { depositKey, amount } = options;
|
|
225
|
-
const addresses = getAddresses();
|
|
226
|
-
|
|
227
|
-
const amountWei = parseUnits(amount, POOL_CONFIG.cbbtc.decimals);
|
|
228
|
-
|
|
229
|
-
const data = encodeFunctionData({
|
|
230
|
-
abi: ENTRY_ABI,
|
|
231
|
-
functionName: 'queueBTC',
|
|
232
|
-
args: [amountWei, depositKey as `0x${string}`],
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
return {
|
|
236
|
-
to: addresses.entry,
|
|
237
|
-
data,
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Build a deposit transaction (ETH, USDC, or cbBTC)
|
|
184
|
+
* Build a deposit transaction (ETH or USDC)
|
|
243
185
|
* Convenience function that routes to the correct builder
|
|
244
186
|
*
|
|
245
187
|
* @param options - Deposit options
|
|
@@ -260,13 +202,6 @@ export function buildDepositCBBTCTx(options: {
|
|
|
260
202
|
* amount: '100',
|
|
261
203
|
* token: 'USDC',
|
|
262
204
|
* });
|
|
263
|
-
*
|
|
264
|
-
* // cbBTC deposit (remember to approve first!)
|
|
265
|
-
* const cbbtcTx = buildDepositTx({
|
|
266
|
-
* depositKey: keypair.depositKey(),
|
|
267
|
-
* amount: '0.5',
|
|
268
|
-
* token: 'CBBTC',
|
|
269
|
-
* });
|
|
270
205
|
* ```
|
|
271
206
|
*/
|
|
272
207
|
export function buildDepositTx(options: {
|
|
@@ -279,10 +214,6 @@ export function buildDepositTx(options: {
|
|
|
279
214
|
if (token === 'USDC') {
|
|
280
215
|
return buildDepositUSDCTx(rest);
|
|
281
216
|
}
|
|
282
|
-
|
|
283
|
-
if (token === 'CBBTC') {
|
|
284
|
-
return buildDepositCBBTCTx(rest);
|
|
285
|
-
}
|
|
286
217
|
|
|
287
218
|
return buildDepositETHTx(rest);
|
|
288
219
|
}
|
package/src/index.ts
CHANGED
|
@@ -46,8 +46,6 @@ export {
|
|
|
46
46
|
buildDepositETHTx,
|
|
47
47
|
buildDepositUSDCTx,
|
|
48
48
|
buildApproveUSDCTx,
|
|
49
|
-
buildDepositCBBTCTx,
|
|
50
|
-
buildApproveCBBTCTx,
|
|
51
49
|
buildDepositTx,
|
|
52
50
|
} from './deposit.js';
|
|
53
51
|
|
|
@@ -118,7 +116,12 @@ export {
|
|
|
118
116
|
} from './relay.js';
|
|
119
117
|
|
|
120
118
|
// ABIs
|
|
121
|
-
export {
|
|
119
|
+
export {
|
|
120
|
+
ENTRY_ABI,
|
|
121
|
+
ERC20_ABI,
|
|
122
|
+
QUEUE_ABI,
|
|
123
|
+
POOL_ABI,
|
|
124
|
+
} from './abi.js';
|
|
122
125
|
|
|
123
126
|
// Utilities
|
|
124
127
|
export {
|
package/src/prover.ts
CHANGED
|
@@ -133,6 +133,9 @@ export async function prove(input: ProofInput, circuitName: string): Promise<str
|
|
|
133
133
|
utils.stringifyBigInts(input) as any,
|
|
134
134
|
wasmPath,
|
|
135
135
|
zkeyPath,
|
|
136
|
+
undefined,
|
|
137
|
+
undefined,
|
|
138
|
+
{ singleThread: true },
|
|
136
139
|
);
|
|
137
140
|
const proof = result.proof as unknown as SnarkProof;
|
|
138
141
|
|
package/src/relay.ts
CHANGED
|
@@ -98,8 +98,8 @@ export async function submitRelay(options: SubmitRelayOptions): Promise<RelayRes
|
|
|
98
98
|
throw new RelayError('Invalid type. Must be "withdraw" or "transfer"', 400);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
if (pool !== 'eth' && pool !== 'usdc'
|
|
102
|
-
throw new RelayError('Invalid pool. Must be "eth"
|
|
101
|
+
if (pool !== 'eth' && pool !== 'usdc') {
|
|
102
|
+
throw new RelayError('Invalid pool. Must be "eth" or "usdc"', 400);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
if (!proofArgs || !extData) {
|
package/src/types.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* Supported tokens
|
|
7
7
|
*/
|
|
8
|
-
export type Token = 'ETH' | 'USDC'
|
|
8
|
+
export type Token = 'ETH' | 'USDC';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Encrypted message format (x25519-xsalsa20-poly1305)
|
|
@@ -27,9 +27,6 @@ export interface NetworkAddresses {
|
|
|
27
27
|
usdcPool: `0x${string}`;
|
|
28
28
|
usdcQueue: `0x${string}`;
|
|
29
29
|
usdcToken: `0x${string}`;
|
|
30
|
-
cbbtcPool: `0x${string}`;
|
|
31
|
-
cbbtcQueue: `0x${string}`;
|
|
32
|
-
cbbtcToken: `0x${string}`;
|
|
33
30
|
chainId: number;
|
|
34
31
|
relayUrl: string;
|
|
35
32
|
}
|
|
@@ -121,7 +118,7 @@ export interface PrivateBalanceResult {
|
|
|
121
118
|
/**
|
|
122
119
|
* Pool type for relay operations
|
|
123
120
|
*/
|
|
124
|
-
export type RelayPool = 'eth' | 'usdc'
|
|
121
|
+
export type RelayPool = 'eth' | 'usdc';
|
|
125
122
|
|
|
126
123
|
/**
|
|
127
124
|
* Type of relay transaction
|