@veil-cash/sdk 0.2.0 → 0.3.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 +218 -41
- package/dist/cli/index.cjs +507 -130
- package/dist/index.cjs +214 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +172 -4
- package/dist/index.d.ts +172 -4
- package/dist/index.js +210 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/abi.ts +30 -0
- package/src/addresses.ts +40 -1
- package/src/balance.ts +22 -15
- package/src/cli/commands/balance.ts +114 -54
- package/src/cli/commands/deposit.ts +76 -33
- package/src/cli/commands/init.ts +45 -8
- package/src/cli/commands/private-balance.ts +6 -1
- package/src/cli/commands/queue-balance.ts +5 -1
- package/src/cli/commands/register.ts +47 -12
- package/src/cli/commands/transfer.ts +23 -10
- package/src/cli/commands/withdraw.ts +13 -5
- package/src/cli/index.ts +1 -1
- package/src/deposit.ts +106 -1
- package/src/index.ts +8 -2
- package/src/keypair.ts +79 -0
- package/src/relay.ts +2 -2
- package/src/transfer.ts +14 -11
- package/src/types.ts +9 -2
- package/src/withdraw.ts +7 -6
package/src/keypair.ts
CHANGED
|
@@ -4,9 +4,22 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ethers } from 'ethers';
|
|
7
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
7
8
|
import { poseidonHash, toFixedHex } from './utils.js';
|
|
8
9
|
import type { EncryptedMessage } from './types.js';
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Canonical message signed by a wallet to derive a Veil keypair.
|
|
13
|
+
* Must match the frontend's SIGNED_MESSAGE in data/wallet/config.ts.
|
|
14
|
+
*/
|
|
15
|
+
export const VEIL_SIGNED_MESSAGE = "Sign this message to create your Veil Wallet private key. This will be used to decrypt your balances. Ensure you are signing this message on the Veil Cash website.";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Any async function that performs EIP-191 personal_sign and returns a 0x-prefixed signature.
|
|
19
|
+
* Used with Keypair.fromSigner() to support external signing services.
|
|
20
|
+
*/
|
|
21
|
+
export type MessageSigner = (message: string) => Promise<string>;
|
|
22
|
+
|
|
10
23
|
// eth-sig-util for x25519 encryption
|
|
11
24
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
12
25
|
const ethSigUtil = require('eth-sig-util');
|
|
@@ -125,6 +138,72 @@ export class Keypair {
|
|
|
125
138
|
});
|
|
126
139
|
}
|
|
127
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Derive a Keypair from an EIP-191 personal_sign signature.
|
|
143
|
+
* The private key is keccak256(signature) -- matching the frontend derivation.
|
|
144
|
+
*
|
|
145
|
+
* @param signature - Raw ECDSA signature (0x-prefixed, 132 hex chars)
|
|
146
|
+
* @returns Keypair derived from the signature
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* const keypair = Keypair.fromSignature(signature);
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
static fromSignature(signature: string): Keypair {
|
|
154
|
+
const privkey = ethers.keccak256(signature);
|
|
155
|
+
return new Keypair(privkey);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Derive a Keypair from an Ethereum wallet private key.
|
|
160
|
+
* Signs VEIL_SIGNED_MESSAGE with the wallet, then derives via keccak256(signature).
|
|
161
|
+
* Produces the same keypair as the frontend for the same wallet.
|
|
162
|
+
*
|
|
163
|
+
* @param walletPrivateKey - Ethereum EOA private key (0x-prefixed)
|
|
164
|
+
* @returns Promise resolving to the derived Keypair
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* const keypair = await Keypair.fromWalletKey('0xYOUR_WALLET_PRIVATE_KEY');
|
|
169
|
+
* console.log(keypair.depositKey()); // Same as frontend login with this wallet
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
static async fromWalletKey(walletPrivateKey: `0x${string}`): Promise<Keypair> {
|
|
173
|
+
const account = privateKeyToAccount(walletPrivateKey);
|
|
174
|
+
const signature = await account.signMessage({ message: VEIL_SIGNED_MESSAGE });
|
|
175
|
+
return Keypair.fromSignature(signature);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Derive a Keypair using any external signer that supports personal_sign (EIP-191).
|
|
180
|
+
* The signer function receives VEIL_SIGNED_MESSAGE and must return a 0x-prefixed signature.
|
|
181
|
+
* Works with any signing backend: Bankr, MPC wallets, custodial services, hardware wallets, etc.
|
|
182
|
+
*
|
|
183
|
+
* @param signer - Async function that signs a message and returns a 0x-prefixed signature
|
|
184
|
+
* @returns Promise resolving to the derived Keypair
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```typescript
|
|
188
|
+
* // With Bankr
|
|
189
|
+
* const keypair = await Keypair.fromSigner(async (message) => {
|
|
190
|
+
* const res = await fetch('https://api.bankr.bot/agent/sign', {
|
|
191
|
+
* method: 'POST',
|
|
192
|
+
* headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' },
|
|
193
|
+
* body: JSON.stringify({ signatureType: 'personal_sign', message }),
|
|
194
|
+
* });
|
|
195
|
+
* return (await res.json()).signature;
|
|
196
|
+
* });
|
|
197
|
+
*
|
|
198
|
+
* // With any custom signer
|
|
199
|
+
* const keypair = await Keypair.fromSigner(async (msg) => myService.personalSign(msg));
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
static async fromSigner(signer: MessageSigner): Promise<Keypair> {
|
|
203
|
+
const signature = await signer(VEIL_SIGNED_MESSAGE);
|
|
204
|
+
return Keypair.fromSignature(signature);
|
|
205
|
+
}
|
|
206
|
+
|
|
128
207
|
/**
|
|
129
208
|
* Sign a message using the private key
|
|
130
209
|
* @param commitment - Commitment hash
|
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" or "
|
|
101
|
+
if (pool !== 'eth' && pool !== 'usdc' && pool !== 'cbbtc') {
|
|
102
|
+
throw new RelayError('Invalid pool. Must be "eth", "usdc", or "cbbtc"', 400);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
if (!proofArgs || !extData) {
|
package/src/transfer.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { createPublicClient, http, parseUnits } from 'viem';
|
|
7
7
|
import { base } from 'viem/chains';
|
|
8
|
-
import { getAddresses, POOL_CONFIG } from './addresses.js';
|
|
8
|
+
import { getAddresses, getPoolAddress, POOL_CONFIG } from './addresses.js';
|
|
9
9
|
import { POOL_ABI, ENTRY_ABI } from './abi.js';
|
|
10
10
|
import { Keypair } from './keypair.js';
|
|
11
11
|
import { Utxo } from './utxo.js';
|
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
BuildTransferProofOptions,
|
|
18
18
|
ProofBuildResult,
|
|
19
19
|
TransferResult,
|
|
20
|
+
RelayPool,
|
|
20
21
|
} from './types.js';
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -137,13 +138,13 @@ export async function buildTransferProof(
|
|
|
137
138
|
amount,
|
|
138
139
|
recipientAddress,
|
|
139
140
|
senderKeypair,
|
|
141
|
+
pool = 'eth',
|
|
140
142
|
rpcUrl,
|
|
141
143
|
onProgress,
|
|
142
144
|
} = options;
|
|
143
145
|
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
const poolAddress = addresses.ethPool;
|
|
146
|
+
const poolConfig = POOL_CONFIG[pool];
|
|
147
|
+
const poolAddress = getPoolAddress(pool);
|
|
147
148
|
|
|
148
149
|
// 1. Check recipient is registered and get their deposit key
|
|
149
150
|
onProgress?.('Checking recipient registration...');
|
|
@@ -160,6 +161,7 @@ export async function buildTransferProof(
|
|
|
160
161
|
onProgress?.('Fetching your UTXOs...');
|
|
161
162
|
const balanceResult = await getPrivateBalance({
|
|
162
163
|
keypair: senderKeypair,
|
|
164
|
+
pool,
|
|
163
165
|
rpcUrl,
|
|
164
166
|
onProgress,
|
|
165
167
|
});
|
|
@@ -283,7 +285,7 @@ export async function buildTransferProof(
|
|
|
283
285
|
export async function transfer(
|
|
284
286
|
options: BuildTransferProofOptions
|
|
285
287
|
): Promise<TransferResult> {
|
|
286
|
-
const { amount, recipientAddress, onProgress } = options;
|
|
288
|
+
const { amount, recipientAddress, pool = 'eth', onProgress } = options;
|
|
287
289
|
|
|
288
290
|
// Build the proof
|
|
289
291
|
const proof = await buildTransferProof(options);
|
|
@@ -292,7 +294,7 @@ export async function transfer(
|
|
|
292
294
|
onProgress?.('Submitting to relay...');
|
|
293
295
|
const relayResult = await submitRelay({
|
|
294
296
|
type: 'transfer',
|
|
295
|
-
pool
|
|
297
|
+
pool,
|
|
296
298
|
proofArgs: proof.proofArgs,
|
|
297
299
|
extData: proof.extData,
|
|
298
300
|
metadata: {
|
|
@@ -334,19 +336,20 @@ export async function transfer(
|
|
|
334
336
|
export async function mergeUtxos(options: {
|
|
335
337
|
amount: string;
|
|
336
338
|
keypair: Keypair;
|
|
339
|
+
pool?: RelayPool;
|
|
337
340
|
rpcUrl?: string;
|
|
338
341
|
onProgress?: (stage: string, detail?: string) => void;
|
|
339
342
|
}): Promise<TransferResult> {
|
|
340
|
-
const { amount, keypair, rpcUrl, onProgress } = options;
|
|
343
|
+
const { amount, keypair, pool = 'eth', rpcUrl, onProgress } = options;
|
|
341
344
|
|
|
342
|
-
const
|
|
343
|
-
const
|
|
344
|
-
const poolAddress = addresses.ethPool;
|
|
345
|
+
const poolConfig = POOL_CONFIG[pool];
|
|
346
|
+
const poolAddress = getPoolAddress(pool);
|
|
345
347
|
|
|
346
348
|
// 1. Get sender's unspent UTXOs
|
|
347
349
|
onProgress?.('Fetching your UTXOs...');
|
|
348
350
|
const balanceResult = await getPrivateBalance({
|
|
349
351
|
keypair,
|
|
352
|
+
pool,
|
|
350
353
|
rpcUrl,
|
|
351
354
|
onProgress,
|
|
352
355
|
});
|
|
@@ -435,7 +438,7 @@ export async function mergeUtxos(options: {
|
|
|
435
438
|
onProgress?.('Submitting to relay...');
|
|
436
439
|
const relayResult = await submitRelay({
|
|
437
440
|
type: 'transfer',
|
|
438
|
-
pool
|
|
441
|
+
pool,
|
|
439
442
|
proofArgs: {
|
|
440
443
|
proof: result.args.proof,
|
|
441
444
|
root: result.args.root,
|
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' | 'CBBTC';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Encrypted message format (x25519-xsalsa20-poly1305)
|
|
@@ -27,6 +27,9 @@ 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}`;
|
|
30
33
|
chainId: number;
|
|
31
34
|
relayUrl: string;
|
|
32
35
|
}
|
|
@@ -118,7 +121,7 @@ export interface PrivateBalanceResult {
|
|
|
118
121
|
/**
|
|
119
122
|
* Pool type for relay operations
|
|
120
123
|
*/
|
|
121
|
-
export type RelayPool = 'eth' | 'usdc';
|
|
124
|
+
export type RelayPool = 'eth' | 'usdc' | 'cbbtc';
|
|
122
125
|
|
|
123
126
|
/**
|
|
124
127
|
* Type of relay transaction
|
|
@@ -223,6 +226,8 @@ export interface BuildWithdrawProofOptions {
|
|
|
223
226
|
recipient: `0x${string}`;
|
|
224
227
|
/** User's keypair for signing */
|
|
225
228
|
keypair: import('./keypair.js').Keypair;
|
|
229
|
+
/** Pool to withdraw from (default: 'eth') */
|
|
230
|
+
pool?: RelayPool;
|
|
226
231
|
/** Optional RPC URL */
|
|
227
232
|
rpcUrl?: string;
|
|
228
233
|
/** Progress callback */
|
|
@@ -239,6 +244,8 @@ export interface BuildTransferProofOptions {
|
|
|
239
244
|
recipientAddress: `0x${string}`;
|
|
240
245
|
/** Sender's keypair */
|
|
241
246
|
senderKeypair: import('./keypair.js').Keypair;
|
|
247
|
+
/** Pool to transfer in (default: 'eth') */
|
|
248
|
+
pool?: RelayPool;
|
|
242
249
|
/** Optional RPC URL */
|
|
243
250
|
rpcUrl?: string;
|
|
244
251
|
/** Progress callback */
|
package/src/withdraw.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { createPublicClient, http, parseUnits, formatUnits } from 'viem';
|
|
7
7
|
import { base } from 'viem/chains';
|
|
8
|
-
import {
|
|
8
|
+
import { getPoolAddress, POOL_CONFIG } from './addresses.js';
|
|
9
9
|
import { POOL_ABI } from './abi.js';
|
|
10
10
|
import { Keypair } from './keypair.js';
|
|
11
11
|
import { Utxo } from './utxo.js';
|
|
@@ -143,18 +143,19 @@ export async function buildWithdrawProof(
|
|
|
143
143
|
amount,
|
|
144
144
|
recipient,
|
|
145
145
|
keypair,
|
|
146
|
+
pool = 'eth',
|
|
146
147
|
rpcUrl,
|
|
147
148
|
onProgress,
|
|
148
149
|
} = options;
|
|
149
150
|
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
const poolAddress = addresses.ethPool;
|
|
151
|
+
const poolConfig = POOL_CONFIG[pool];
|
|
152
|
+
const poolAddress = getPoolAddress(pool);
|
|
153
153
|
|
|
154
154
|
// 1. Get user's unspent UTXOs
|
|
155
155
|
onProgress?.('Fetching your UTXOs...');
|
|
156
156
|
const balanceResult = await getPrivateBalance({
|
|
157
157
|
keypair,
|
|
158
|
+
pool,
|
|
158
159
|
rpcUrl,
|
|
159
160
|
onProgress,
|
|
160
161
|
});
|
|
@@ -269,7 +270,7 @@ export async function buildWithdrawProof(
|
|
|
269
270
|
export async function withdraw(
|
|
270
271
|
options: BuildWithdrawProofOptions
|
|
271
272
|
): Promise<WithdrawResult> {
|
|
272
|
-
const { amount, recipient, onProgress } = options;
|
|
273
|
+
const { amount, recipient, pool = 'eth', onProgress } = options;
|
|
273
274
|
|
|
274
275
|
// Build the proof
|
|
275
276
|
const proof = await buildWithdrawProof(options);
|
|
@@ -278,7 +279,7 @@ export async function withdraw(
|
|
|
278
279
|
onProgress?.('Submitting to relay...');
|
|
279
280
|
const relayResult = await submitRelay({
|
|
280
281
|
type: 'withdraw',
|
|
281
|
-
pool
|
|
282
|
+
pool,
|
|
282
283
|
proofArgs: proof.proofArgs,
|
|
283
284
|
extData: proof.extData,
|
|
284
285
|
metadata: {
|