@zerc20/wallet-sdk 0.0.0-stage → 0.1.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.
Files changed (84) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +26 -2
  3. package/dist/burnWorker.d.ts +1 -0
  4. package/dist/burnWorker.js +21 -0
  5. package/dist/burnWorker.js.map +1 -0
  6. package/dist/chain.d.ts +345 -0
  7. package/dist/chain.js +149 -0
  8. package/dist/chain.js.map +1 -0
  9. package/dist/context.d.ts +48 -0
  10. package/dist/context.js +40 -0
  11. package/dist/context.js.map +1 -0
  12. package/dist/core.d.ts +43 -0
  13. package/dist/core.js +106 -0
  14. package/dist/core.js.map +1 -0
  15. package/dist/errors.d.ts +36 -0
  16. package/dist/errors.js +26 -0
  17. package/dist/errors.js.map +1 -0
  18. package/dist/index.d.ts +6 -0
  19. package/dist/index.js +19 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/network.d.ts +66 -0
  22. package/dist/network.js +55 -0
  23. package/dist/network.js.map +1 -0
  24. package/dist/pos.d.ts +93 -0
  25. package/dist/pos.js +302 -0
  26. package/dist/pos.js.map +1 -0
  27. package/dist/prove.d.ts +13 -0
  28. package/dist/prove.js +53 -0
  29. package/dist/prove.js.map +1 -0
  30. package/dist/rageExit.d.ts +5 -0
  31. package/dist/rageExit.js +146 -0
  32. package/dist/rageExit.js.map +1 -0
  33. package/dist/scan.d.ts +17 -0
  34. package/dist/scan.js +47 -0
  35. package/dist/scan.js.map +1 -0
  36. package/dist/seed.d.ts +8 -0
  37. package/dist/seed.js +35 -0
  38. package/dist/seed.js.map +1 -0
  39. package/dist/servers.d.ts +60 -0
  40. package/dist/servers.js +117 -0
  41. package/dist/servers.js.map +1 -0
  42. package/dist/services.d.ts +62 -0
  43. package/dist/services.js +128 -0
  44. package/dist/services.js.map +1 -0
  45. package/dist/spend.d.ts +151 -0
  46. package/dist/spend.js +745 -0
  47. package/dist/spend.js.map +1 -0
  48. package/dist/state.d.ts +174 -0
  49. package/dist/state.js +45 -0
  50. package/dist/state.js.map +1 -0
  51. package/dist/sync.d.ts +84 -0
  52. package/dist/sync.js +615 -0
  53. package/dist/sync.js.map +1 -0
  54. package/dist/tree.d.ts +19 -0
  55. package/dist/tree.js +63 -0
  56. package/dist/tree.js.map +1 -0
  57. package/dist/wallet.d.ts +301 -0
  58. package/dist/wallet.js +992 -0
  59. package/dist/wallet.js.map +1 -0
  60. package/package.json +60 -4
  61. package/src/burnWorker.ts +25 -0
  62. package/src/chain.ts +205 -0
  63. package/src/context.ts +84 -0
  64. package/src/core.ts +147 -0
  65. package/src/errors.ts +61 -0
  66. package/src/index.ts +41 -0
  67. package/src/network.ts +94 -0
  68. package/src/pos.ts +415 -0
  69. package/src/prove.ts +67 -0
  70. package/src/rageExit.ts +168 -0
  71. package/src/scan.ts +62 -0
  72. package/src/seed.ts +46 -0
  73. package/src/servers.ts +172 -0
  74. package/src/services.ts +184 -0
  75. package/src/snarkjs.d.ts +11 -0
  76. package/src/spend.ts +912 -0
  77. package/src/state.ts +211 -0
  78. package/src/sync.ts +698 -0
  79. package/src/tree.ts +108 -0
  80. package/src/wallet.ts +1297 -0
  81. package/wasm/zerc20_wallet_core.d.ts +176 -0
  82. package/wasm/zerc20_wallet_core.js +783 -0
  83. package/wasm/zerc20_wallet_core_bg.wasm +0 -0
  84. package/wasm/zerc20_wallet_core_bg.wasm.d.ts +32 -0
package/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <https://unlicense.org/>
package/README.md CHANGED
@@ -1,3 +1,27 @@
1
- # Temporary Holding Version
1
+ # @zerc20/wallet-sdk
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A zERC20 wallet for browsers and Node: deposits, private payments, merges, withdrawals and rage exits. Proofs are made
4
+ on the device, and what the attester and the merge prover need reaches them sealed to an enclave the SDK has checked.
5
+
6
+ ```sh
7
+ npm install @zerc20/wallet-sdk viem
8
+ ```
9
+
10
+ Node 22.12 or later. viem is a peer dependency: the SDK tells a declined wallet prompt by viem's error classes, so it
11
+ must be the app's own copy.
12
+
13
+ ```ts
14
+ import { Wallet, networkFromJson, seedFromSignature } from '@zerc20/wallet-sdk';
15
+
16
+ const network = networkFromJson(networkJson);
17
+ const { seed } = await seedFromSignature(walletClient); // a viem WalletClient with its account
18
+ const wallet = await Wallet.open({ network, walletClient, seed, persist: { load, save } });
19
+ await wallet.sync();
20
+ wallet.balances();
21
+ const q = await wallet.fees({ kind: 'send', token, amount });
22
+ await (await wallet.send({ to: '0x…', token, amount, maxFee: q.fee })).wait();
23
+ ```
24
+
25
+ ## License
26
+
27
+ [Unlicense](LICENSE)
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ // Searches a burn address off the main thread: core.ts starts one per search, a Web Worker in a browser and a worker
2
+ // thread in Node.
3
+ import { initCore, searchHere } from './core.js';
4
+ async function answer(s) {
5
+ try {
6
+ await initCore();
7
+ return { burn: searchHere(s) };
8
+ }
9
+ catch (e) {
10
+ return { error: e instanceof Error ? e.message : String(e) };
11
+ }
12
+ }
13
+ if (typeof self !== 'undefined') {
14
+ self.onmessage = async ({ data }) => postMessage(await answer(data));
15
+ }
16
+ else {
17
+ // a variable, so that bundlers for the browser leave Node's module alone
18
+ const threads = 'node:worker_threads';
19
+ void import(/* @vite-ignore */ threads).then(async ({ parentPort, workerData }) => parentPort.postMessage(await answer(workerData)));
20
+ }
21
+ //# sourceMappingURL=burnWorker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"burnWorker.js","sourceRoot":"","sources":["../src/burnWorker.ts"],"names":[],"mappings":"AAAA,qHAAqH;AACrH,kBAAkB;AAElB,OAAO,EAAoC,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEnF,KAAK,UAAU,MAAM,CAAC,CAAa;IACjC,IAAI,CAAC;QACH,MAAM,QAAQ,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/D,CAAC;AACH,CAAC;AAED,IAAI,OAAO,IAAI,KAAK,WAAW,EAAE,CAAC;IAChC,IAAI,CAAC,SAAS,GAAG,KAAK,EAAE,EAAE,IAAI,EAA4B,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACjG,CAAC;KAAM,CAAC;IACN,yEAAyE;IACzE,MAAM,OAAO,GAAG,qBAAqB,CAAC;IAEtC,KAAK,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,IAAI,CAC1C,KAAK,EAAE,EAAE,UAAU,EAAE,UAAU,EAAgD,EAAE,EAAE,CACjF,UAAU,CAAC,WAAW,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,CACnD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,345 @@
1
+ import { type Address, type Hex, type PublicClient } from 'viem';
2
+ import type { ChainConfig } from './network.js';
3
+ export declare const verifierAbi: readonly [{
4
+ readonly name: "ledger";
5
+ readonly type: "function";
6
+ readonly stateMutability: "view";
7
+ readonly inputs: readonly [];
8
+ readonly outputs: readonly [{
9
+ readonly type: "address";
10
+ }];
11
+ }, {
12
+ readonly name: "factory";
13
+ readonly type: "function";
14
+ readonly stateMutability: "view";
15
+ readonly inputs: readonly [];
16
+ readonly outputs: readonly [{
17
+ readonly type: "address";
18
+ }];
19
+ }, {
20
+ readonly name: "latestAspRoot";
21
+ readonly type: "function";
22
+ readonly stateMutability: "view";
23
+ readonly inputs: readonly [];
24
+ readonly outputs: readonly [{
25
+ readonly type: "uint256";
26
+ }];
27
+ }, {
28
+ readonly name: "withdrawFee";
29
+ readonly type: "function";
30
+ readonly stateMutability: "view";
31
+ readonly inputs: readonly [{
32
+ readonly type: "uint32";
33
+ readonly name: "tokenId";
34
+ }, {
35
+ readonly type: "uint256";
36
+ readonly name: "amount";
37
+ }];
38
+ readonly outputs: readonly [{
39
+ readonly type: "uint256";
40
+ }];
41
+ }, {
42
+ readonly name: "rageExit";
43
+ readonly type: "function";
44
+ readonly stateMutability: "nonpayable";
45
+ readonly inputs: readonly [{
46
+ readonly type: "tuple";
47
+ readonly components: readonly [{
48
+ readonly type: "uint64";
49
+ readonly name: "checkpointIndex";
50
+ }, {
51
+ readonly type: "uint256";
52
+ readonly name: "prevHashChain";
53
+ }, {
54
+ readonly type: "uint256[4][]";
55
+ readonly name: "commitments";
56
+ }, {
57
+ readonly type: "uint256";
58
+ readonly name: "nullifier";
59
+ }, {
60
+ readonly name: "proof";
61
+ readonly type: "tuple";
62
+ readonly components: readonly [{
63
+ readonly type: "uint256[2]";
64
+ readonly name: "pA";
65
+ }, {
66
+ readonly type: "uint256[2][2]";
67
+ readonly name: "pB";
68
+ }, {
69
+ readonly type: "uint256[2]";
70
+ readonly name: "pC";
71
+ }];
72
+ }];
73
+ readonly name: "request";
74
+ }];
75
+ readonly outputs: readonly [];
76
+ }];
77
+ export declare const ledgerAbi: readonly [{
78
+ readonly name: "provedRoots";
79
+ readonly type: "function";
80
+ readonly stateMutability: "view";
81
+ readonly inputs: readonly [{
82
+ readonly type: "uint64";
83
+ readonly name: "index";
84
+ }, {
85
+ readonly type: "uint256";
86
+ readonly name: "root";
87
+ }];
88
+ readonly outputs: readonly [{
89
+ readonly type: "bool";
90
+ }];
91
+ }, {
92
+ readonly name: "bound";
93
+ readonly type: "function";
94
+ readonly stateMutability: "view";
95
+ readonly inputs: readonly [];
96
+ readonly outputs: readonly [{
97
+ readonly type: "uint64";
98
+ }];
99
+ }, {
100
+ readonly name: "hashChainAt";
101
+ readonly type: "function";
102
+ readonly stateMutability: "view";
103
+ readonly inputs: readonly [{
104
+ readonly type: "uint64";
105
+ readonly name: "index";
106
+ }];
107
+ readonly outputs: readonly [{
108
+ readonly type: "uint256";
109
+ }, {
110
+ readonly type: "bool";
111
+ }];
112
+ }, {
113
+ readonly name: "reserveHashChain";
114
+ readonly type: "function";
115
+ readonly stateMutability: "nonpayable";
116
+ readonly inputs: readonly [];
117
+ readonly outputs: readonly [{
118
+ readonly type: "uint64";
119
+ readonly name: "index";
120
+ }, {
121
+ readonly type: "uint256";
122
+ readonly name: "checkpoint";
123
+ }];
124
+ }, {
125
+ readonly name: "verifySegment";
126
+ readonly type: "function";
127
+ readonly stateMutability: "view";
128
+ readonly inputs: readonly [{
129
+ readonly type: "uint64";
130
+ readonly name: "end";
131
+ }, {
132
+ readonly type: "uint256";
133
+ readonly name: "prev";
134
+ }, {
135
+ readonly type: "uint256[4][]";
136
+ readonly name: "commits";
137
+ }];
138
+ readonly outputs: readonly [{
139
+ readonly type: "uint64";
140
+ readonly name: "start";
141
+ }];
142
+ }, {
143
+ readonly name: "checkpointBefore";
144
+ readonly type: "function";
145
+ readonly stateMutability: "nonpayable";
146
+ readonly inputs: readonly [{
147
+ readonly type: "uint64";
148
+ readonly name: "end";
149
+ }, {
150
+ readonly type: "uint256";
151
+ readonly name: "prev";
152
+ }, {
153
+ readonly type: "uint256[4][]";
154
+ readonly name: "commits";
155
+ }];
156
+ readonly outputs: readonly [{
157
+ readonly type: "uint64";
158
+ readonly name: "start";
159
+ }];
160
+ }];
161
+ export declare const factoryAbi: readonly [{
162
+ readonly name: "tokenCount";
163
+ readonly type: "function";
164
+ readonly stateMutability: "view";
165
+ readonly inputs: readonly [];
166
+ readonly outputs: readonly [{
167
+ readonly type: "uint32";
168
+ }];
169
+ }, {
170
+ readonly name: "tokenById";
171
+ readonly type: "function";
172
+ readonly stateMutability: "view";
173
+ readonly inputs: readonly [{
174
+ readonly type: "uint32";
175
+ readonly name: "tokenId";
176
+ }];
177
+ readonly outputs: readonly [{
178
+ readonly type: "address";
179
+ }];
180
+ }];
181
+ export declare const tokenAbi: readonly [{
182
+ readonly name: "symbol";
183
+ readonly type: "function";
184
+ readonly stateMutability: "view";
185
+ readonly inputs: readonly [];
186
+ readonly outputs: readonly [{
187
+ readonly type: "string";
188
+ }];
189
+ }, {
190
+ readonly name: "decimals";
191
+ readonly type: "function";
192
+ readonly stateMutability: "view";
193
+ readonly inputs: readonly [];
194
+ readonly outputs: readonly [{
195
+ readonly type: "uint8";
196
+ }];
197
+ }, {
198
+ readonly name: "underlyingAsset";
199
+ readonly type: "function";
200
+ readonly stateMutability: "view";
201
+ readonly inputs: readonly [];
202
+ readonly outputs: readonly [{
203
+ readonly type: "address";
204
+ }];
205
+ }, {
206
+ readonly name: "wrap";
207
+ readonly type: "function";
208
+ readonly stateMutability: "payable";
209
+ readonly inputs: readonly [{
210
+ readonly type: "uint256";
211
+ readonly name: "amount";
212
+ }, {
213
+ readonly type: "address";
214
+ readonly name: "receiver";
215
+ }];
216
+ readonly outputs: readonly [];
217
+ }];
218
+ export declare const erc20Abi: readonly [{
219
+ readonly name: "balanceOf";
220
+ readonly type: "function";
221
+ readonly stateMutability: "view";
222
+ readonly inputs: readonly [{
223
+ readonly type: "address";
224
+ readonly name: "owner";
225
+ }];
226
+ readonly outputs: readonly [{
227
+ readonly type: "uint256";
228
+ }];
229
+ }, {
230
+ readonly name: "allowance";
231
+ readonly type: "function";
232
+ readonly stateMutability: "view";
233
+ readonly inputs: readonly [{
234
+ readonly type: "address";
235
+ readonly name: "owner";
236
+ }, {
237
+ readonly type: "address";
238
+ readonly name: "spender";
239
+ }];
240
+ readonly outputs: readonly [{
241
+ readonly type: "uint256";
242
+ }];
243
+ }, {
244
+ readonly name: "approve";
245
+ readonly type: "function";
246
+ readonly stateMutability: "nonpayable";
247
+ readonly inputs: readonly [{
248
+ readonly type: "address";
249
+ readonly name: "spender";
250
+ }, {
251
+ readonly type: "uint256";
252
+ readonly name: "amount";
253
+ }];
254
+ readonly outputs: readonly [{
255
+ readonly type: "bool";
256
+ }];
257
+ }, {
258
+ readonly name: "transfer";
259
+ readonly type: "function";
260
+ readonly stateMutability: "nonpayable";
261
+ readonly inputs: readonly [{
262
+ readonly type: "address";
263
+ readonly name: "to";
264
+ }, {
265
+ readonly type: "uint256";
266
+ readonly name: "amount";
267
+ }];
268
+ readonly outputs: readonly [{
269
+ readonly type: "bool";
270
+ }];
271
+ }];
272
+ export declare const depositFactoryAbi: readonly [{
273
+ readonly name: "predict";
274
+ readonly type: "function";
275
+ readonly stateMutability: "view";
276
+ readonly inputs: readonly [{
277
+ readonly type: "address";
278
+ readonly name: "token";
279
+ }, {
280
+ readonly type: "address";
281
+ readonly name: "burnAddress";
282
+ }, {
283
+ readonly type: "address";
284
+ readonly name: "refundAddress";
285
+ }, {
286
+ readonly type: "address";
287
+ readonly name: "feeRecipient";
288
+ }, {
289
+ readonly type: "uint256";
290
+ readonly name: "fee";
291
+ }];
292
+ readonly outputs: readonly [{
293
+ readonly type: "address";
294
+ }];
295
+ }];
296
+ export declare const depositAddressAbi: readonly [{
297
+ readonly name: "refund";
298
+ readonly type: "function";
299
+ readonly stateMutability: "nonpayable";
300
+ readonly inputs: readonly [{
301
+ readonly type: "address";
302
+ readonly name: "asset";
303
+ }];
304
+ readonly outputs: readonly [];
305
+ }];
306
+ /** The native asset's stand-in for `underlyingAsset`. */
307
+ export declare const NATIVE: Address;
308
+ /** `Protocol.UNWRAP_INTENT`: the `withdrawIntent` that pays a withdrawal out as the underlying asset. The EIP-712 struct
309
+ * hash of `Unwrap()`, reduced into the BN254 field. */
310
+ export declare const UNWRAP_INTENT: bigint;
311
+ /** A zERC20 token on one chain. Amounts are in its base units, the same as its underlying asset's. */
312
+ export interface Token {
313
+ chainId: bigint;
314
+ tokenId: number;
315
+ /** The zERC20 token: what a public withdrawal pays out (unless it unwraps), and what `unwrap` turns back into
316
+ * `underlying`. */
317
+ address: Address;
318
+ underlying: Address;
319
+ symbol: string;
320
+ decimals: number;
321
+ }
322
+ export declare class Chain {
323
+ #private;
324
+ readonly config: ChainConfig;
325
+ readonly client: PublicClient;
326
+ constructor(config: ChainConfig);
327
+ get chainId(): bigint;
328
+ ledger(): Promise<Address>;
329
+ /** The deposit address the factory deploys for `token`, `burnAddress` and `refundAddress`, whose flush pays `fee`
330
+ * to `feeRecipient`. */
331
+ predictDepositAddress(token: Address, burnAddress: Hex, refundAddress: Address, feeRecipient: Address, fee: bigint): Promise<Address>;
332
+ /** The refund address of `address` if it is a deployed deposit address for `token` and `burnAddress`, whatever its
333
+ * refund address and fee; null if it is not one. A clone's code ends with its immutable args, `abi.encode(token,
334
+ * burnAddress, refundAddress, feeRecipient, fee)`; the factory's address for them confirms it, so code made to look
335
+ * like one does not pass. */
336
+ depositAddressRefund(address: Address, token: Address, burnAddress: Hex): Promise<Address | null>;
337
+ /** Whether the ledger accepts `root` as the tree at `size` leaves. */
338
+ provedRoot(size: number, root: Hex): Promise<boolean>;
339
+ /** `2^64 - 1`, unless the ledger is in an emergency: then it accepts no root above it, and proves none. */
340
+ bound(): Promise<bigint>;
341
+ latestAspRoot(): Promise<Hex>;
342
+ withdrawFee(tokenId: number, amount: bigint): Promise<bigint>;
343
+ /** Every token the factory has registered, read once and then only the new ones. */
344
+ tokens(): Promise<Token[]>;
345
+ }
package/dist/chain.js ADDED
@@ -0,0 +1,149 @@
1
+ // What a wallet reads from the chain itself, through its own RPC: roots are taken from here, never from a server.
2
+ import { createPublicClient, decodeAbiParameters, http, keccak256, numberToHex, parseAbi, size, slice, toHex, zeroAddress, } from 'viem';
3
+ export const verifierAbi = parseAbi([
4
+ 'function ledger() view returns (address)',
5
+ 'function factory() view returns (address)',
6
+ 'function latestAspRoot() view returns (uint256)',
7
+ 'function withdrawFee(uint32 tokenId, uint256 amount) view returns (uint256)',
8
+ 'struct Groth16Proof { uint256[2] pA; uint256[2][2] pB; uint256[2] pC; }',
9
+ 'struct TransactSignals { uint256 tokenId; uint256 chainId; uint256 commitmentRoot; uint256 aspRoot; uint256 nullifier0; uint256 nullifier1; uint256 withdrawRecipient; uint256 withdrawAmount; uint256 withdrawIntent; uint256 noteHash1; uint256 noteHash2; }',
10
+ 'struct RageExitRequest { uint64 checkpointIndex; uint256 prevHashChain; uint256[4][] commitments; uint256 nullifier; Groth16Proof proof; }',
11
+ 'function rageExit(RageExitRequest request)',
12
+ ]);
13
+ export const ledgerAbi = parseAbi([
14
+ 'function provedRoots(uint64 index, uint256 root) view returns (bool)',
15
+ 'function bound() view returns (uint64)',
16
+ 'function hashChainAt(uint64 index) view returns (uint256, bool)',
17
+ 'function reserveHashChain() returns (uint64 index, uint256 checkpoint)',
18
+ 'function verifySegment(uint64 end, uint256 prev, uint256[4][] commits) view returns (uint64 start)',
19
+ 'function checkpointBefore(uint64 end, uint256 prev, uint256[4][] commits) returns (uint64 start)',
20
+ ]);
21
+ export const factoryAbi = parseAbi([
22
+ 'function tokenCount() view returns (uint32)',
23
+ 'function tokenById(uint32 tokenId) view returns (address)',
24
+ ]);
25
+ export const tokenAbi = parseAbi([
26
+ 'function symbol() view returns (string)',
27
+ 'function decimals() view returns (uint8)',
28
+ 'function underlyingAsset() view returns (address)',
29
+ 'function wrap(uint256 amount, address receiver) payable',
30
+ ]);
31
+ export const erc20Abi = parseAbi([
32
+ 'function balanceOf(address owner) view returns (uint256)',
33
+ 'function allowance(address owner, address spender) view returns (uint256)',
34
+ 'function approve(address spender, uint256 amount) returns (bool)',
35
+ 'function transfer(address to, uint256 amount) returns (bool)',
36
+ ]);
37
+ export const depositFactoryAbi = parseAbi([
38
+ 'function predict(address token, address burnAddress, address refundAddress, address feeRecipient, uint256 fee) view returns (address)',
39
+ ]);
40
+ export const depositAddressAbi = parseAbi(['function refund(address asset)']);
41
+ /** The native asset's stand-in for `underlyingAsset`. */
42
+ export const NATIVE = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
43
+ /** `Protocol.UNWRAP_INTENT`: the `withdrawIntent` that pays a withdrawal out as the underlying asset. The EIP-712 struct
44
+ * hash of `Unwrap()`, reduced into the BN254 field. */
45
+ export const UNWRAP_INTENT = BigInt(keccak256(keccak256(toHex('Unwrap()')))) %
46
+ 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
47
+ export class Chain {
48
+ config;
49
+ client;
50
+ #ledger;
51
+ #tokens;
52
+ constructor(config) {
53
+ this.config = config;
54
+ this.client = createPublicClient({ transport: http(config.rpcUrl) });
55
+ }
56
+ get chainId() {
57
+ return this.config.chainId;
58
+ }
59
+ ledger() {
60
+ this.#ledger ??= this.client.readContract({
61
+ address: this.config.verifier,
62
+ abi: verifierAbi,
63
+ functionName: 'ledger',
64
+ });
65
+ return this.#ledger;
66
+ }
67
+ /** The deposit address the factory deploys for `token`, `burnAddress` and `refundAddress`, whose flush pays `fee`
68
+ * to `feeRecipient`. */
69
+ predictDepositAddress(token, burnAddress, refundAddress, feeRecipient, fee) {
70
+ return this.client.readContract({
71
+ address: this.config.depositAddressFactory,
72
+ abi: depositFactoryAbi,
73
+ functionName: 'predict',
74
+ args: [token, burnAddress, refundAddress, feeRecipient, fee],
75
+ });
76
+ }
77
+ /** The refund address of `address` if it is a deployed deposit address for `token` and `burnAddress`, whatever its
78
+ * refund address and fee; null if it is not one. A clone's code ends with its immutable args, `abi.encode(token,
79
+ * burnAddress, refundAddress, feeRecipient, fee)`; the factory's address for them confirms it, so code made to look
80
+ * like one does not pass. */
81
+ async depositAddressRefund(address, token, burnAddress) {
82
+ const code = await this.client.getCode({ address });
83
+ if (!code || size(code) < 160)
84
+ return null;
85
+ const [refundAddress, feeRecipient, fee] = decodeAbiParameters([{ type: 'address' }, { type: 'address' }, { type: 'uint256' }], slice(code, size(code) - 96));
86
+ if (refundAddress === zeroAddress || feeRecipient === zeroAddress)
87
+ return null; // predict would revert
88
+ const expected = await this.predictDepositAddress(token, burnAddress, refundAddress, feeRecipient, fee);
89
+ return expected.toLowerCase() === address.toLowerCase() ? refundAddress : null;
90
+ }
91
+ /** Whether the ledger accepts `root` as the tree at `size` leaves. */
92
+ async provedRoot(size, root) {
93
+ return this.client.readContract({
94
+ address: await this.ledger(),
95
+ abi: ledgerAbi,
96
+ functionName: 'provedRoots',
97
+ args: [BigInt(size), BigInt(root)],
98
+ });
99
+ }
100
+ /** `2^64 - 1`, unless the ledger is in an emergency: then it accepts no root above it, and proves none. */
101
+ async bound() {
102
+ return this.client.readContract({ address: await this.ledger(), abi: ledgerAbi, functionName: 'bound' });
103
+ }
104
+ async latestAspRoot() {
105
+ const root = await this.client.readContract({
106
+ address: this.config.verifier,
107
+ abi: verifierAbi,
108
+ functionName: 'latestAspRoot',
109
+ });
110
+ return numberToHex(root, { size: 32 });
111
+ }
112
+ withdrawFee(tokenId, amount) {
113
+ return this.client.readContract({
114
+ address: this.config.verifier,
115
+ abi: verifierAbi,
116
+ functionName: 'withdrawFee',
117
+ args: [tokenId, amount],
118
+ });
119
+ }
120
+ /** Every token the factory has registered, read once and then only the new ones. */
121
+ async tokens() {
122
+ const factory = await this.client.readContract({
123
+ address: this.config.verifier,
124
+ abi: verifierAbi,
125
+ functionName: 'factory',
126
+ });
127
+ const count = await this.client.readContract({ address: factory, abi: factoryAbi, functionName: 'tokenCount' });
128
+ const known = this.#tokens ?? [];
129
+ const fresh = await Promise.all(Array.from({ length: count - known.length }, async (_, i) => {
130
+ const tokenId = known.length + i + 1;
131
+ const address = await this.client.readContract({
132
+ address: factory,
133
+ abi: factoryAbi,
134
+ functionName: 'tokenById',
135
+ args: [tokenId],
136
+ });
137
+ const read = (functionName) => this.client.readContract({ address, abi: tokenAbi, functionName });
138
+ const [symbol, decimals, underlying] = await Promise.all([
139
+ read('symbol'),
140
+ read('decimals'),
141
+ read('underlyingAsset'),
142
+ ]);
143
+ return { chainId: this.chainId, tokenId, address, underlying, symbol, decimals };
144
+ }));
145
+ this.#tokens = [...known, ...fresh];
146
+ return this.#tokens;
147
+ }
148
+ }
149
+ //# sourceMappingURL=chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.js","sourceRoot":"","sources":["../src/chain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { CanisterClient, ViewKey } from '@zerc20/storage-sdk';
2
+ import { type Hex, type WalletClient } from 'viem';
3
+ import type { Chain } from './chain.js';
4
+ import type { ChainConfig, Network } from './network.js';
5
+ import type { Asp, Indexer } from './servers.js';
6
+ import type { ChainState, WalletState } from './state.js';
7
+ export interface ChainCtx {
8
+ config: ChainConfig;
9
+ chain: Chain;
10
+ indexer: Indexer;
11
+ asp: Asp;
12
+ }
13
+ export interface SpendKey {
14
+ /** The circuits' `private_key`: only this wallet's own proofs take it. */
15
+ secret: Hex;
16
+ /** The hash of the key that signs this key's spends, which the circuits take with `secret`. */
17
+ authKeyHash: Hex;
18
+ publicKey: Hex;
19
+ nullifyingKey: Hex;
20
+ }
21
+ export interface Ctx {
22
+ network: Network;
23
+ seed: Uint8Array;
24
+ address: Hex;
25
+ walletClient: WalletClient;
26
+ storage: CanisterClient;
27
+ view: ViewKey;
28
+ chains: ChainCtx[];
29
+ state: WalletState;
30
+ save(): Promise<void>;
31
+ /** When storage was last read in full rather than through its log (in memory: the first sync does it). */
32
+ lastFullRefreshMs: number;
33
+ }
34
+ /** A receive code of this seed's: its chain, token and index (the burn index the code shares). */
35
+ export interface CodeId {
36
+ chainId: bigint;
37
+ tokenId: number;
38
+ index: number;
39
+ }
40
+ /** The key that owns this seed's notes and deposits on every chain and token, or with `code`, the notes paid to that
41
+ * receive code. */
42
+ export declare function spendKey(ctx: Ctx, code?: CodeId): SpendKey;
43
+ export declare function chainCtx(ctx: Ctx, chainId: bigint): ChainCtx;
44
+ export declare function chainState(ctx: Ctx, chainId: bigint): ChainState;
45
+ /** Waits until the wallet's own node has a transaction mined on ours too: the wallet simulates the next one there, and
46
+ * where blocks are fast that node lags ours now and then, so the next one would show as reverting. A wallet that does
47
+ * not answer is not waited on. */
48
+ export declare function walletSees(wc: WalletClient, hash: Hex): Promise<void>;
@@ -0,0 +1,40 @@
1
+ // Everything an open wallet works with, shared by sync and the operations.
2
+ import { publicActions } from 'viem';
3
+ import { core } from './core.js';
4
+ const keys = new WeakMap();
5
+ /** The key that owns this seed's notes and deposits on every chain and token, or with `code`, the notes paid to that
6
+ * receive code. */
7
+ export function spendKey(ctx, code) {
8
+ let bySeed = keys.get(ctx.seed);
9
+ if (!bySeed)
10
+ keys.set(ctx.seed, (bySeed = new Map()));
11
+ const id = code ? `${code.chainId}:${code.tokenId}:${code.index}` : '';
12
+ let key = bySeed.get(id);
13
+ if (!key) {
14
+ key = (code ? core.codeKey(ctx.seed, code.chainId, code.tokenId, code.index) : core.spendKey(ctx.seed));
15
+ bySeed.set(id, key);
16
+ }
17
+ return key;
18
+ }
19
+ export function chainCtx(ctx, chainId) {
20
+ const c = ctx.chains.find((c) => c.config.chainId === chainId);
21
+ if (!c)
22
+ throw new Error(`chain ${chainId} is not in this network`);
23
+ return c;
24
+ }
25
+ export function chainState(ctx, chainId) {
26
+ let s = ctx.state.chains.find((c) => c.chainId === chainId);
27
+ if (!s)
28
+ ctx.state.chains.push((s = { chainId, samples: [], burnNext: {} }));
29
+ return s;
30
+ }
31
+ /** Waits until the wallet's own node has a transaction mined on ours too: the wallet simulates the next one there, and
32
+ * where blocks are fast that node lags ours now and then, so the next one would show as reverting. A wallet that does
33
+ * not answer is not waited on. */
34
+ export async function walletSees(wc, hash) {
35
+ await wc
36
+ .extend(publicActions)
37
+ .waitForTransactionReceipt({ hash, pollingInterval: 1_000, timeout: 30_000 })
38
+ .catch(() => { });
39
+ }
40
+ //# sourceMappingURL=context.js.map