@zerc20/wallet-sdk 0.0.0-stage → 0.2.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 +359 -0
  7. package/dist/chain.js +155 -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 +38 -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 +131 -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 +303 -0
  58. package/dist/wallet.js +1002 -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 +228 -0
  63. package/src/context.ts +84 -0
  64. package/src/core.ts +147 -0
  65. package/src/errors.ts +63 -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 +195 -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 +1316 -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/src/tree.ts ADDED
@@ -0,0 +1,108 @@
1
+ // Membership paths: a commitment in the latest proved root, and a deposit in the ASP's latest root. Built from
2
+ // what every wallet downloads, then checked against the roots the chain holds, so no server is trusted with them.
3
+
4
+ import type { Hex } from 'viem';
5
+ import type { Chain } from './chain.js';
6
+ import { core } from './core.js';
7
+ import { fail } from './errors.js';
8
+ import type { Asp, Indexer, RootEntry } from './servers.js';
9
+ import { PAGE } from './servers.js';
10
+
11
+ const PAGE_BITS = 24;
12
+
13
+ export interface Membership {
14
+ /** The tree size, which is also the `rootIndex` a transact names. */
15
+ size: number;
16
+ root: Hex;
17
+ siblings: Hex[];
18
+ }
19
+
20
+ /** The leaves of commitment `i`'s chunk, from page `i >> 12` of commitments. */
21
+ async function chunkOf(indexer: Indexer, i: number): Promise<Uint8Array> {
22
+ const chunk = Math.floor(i / PAGE);
23
+ const { entries } = await indexer.commitments(chunk);
24
+ if (entries.length < (i - chunk * PAGE + 1) * 128)
25
+ return fail('indexer-mismatch', `commitment ${i} is not served yet`);
26
+ return core.leaves(entries);
27
+ }
28
+
29
+ const hex = (b: Uint8Array): string => Array.from(b, (x) => x.toString(16).padStart(2, '0')).join('');
30
+
31
+ /** A path for leaf `i` (whose chunk's leaves are `leaves`) against the tree `at`, checked to fold to its root. */
32
+ async function pathAt(
33
+ i: number,
34
+ leaves: Uint8Array,
35
+ at: RootEntry,
36
+ chunkRoots: (p: number) => Promise<Uint8Array>,
37
+ pageRoots: () => Promise<Uint8Array>,
38
+ ): Promise<Membership> {
39
+ const [roots, pages] = await Promise.all([chunkRoots(Math.floor(i / 2 ** PAGE_BITS)), pageRoots()]);
40
+ const siblings = core.path(
41
+ BigInt(i),
42
+ BigInt(at.size),
43
+ leaves,
44
+ roots,
45
+ pages,
46
+ at.partialChunk,
47
+ at.partialPage,
48
+ ) as Hex[];
49
+ const leaf = `0x${hex(leaves.subarray((i % PAGE) * 32, (i % PAGE) * 32 + 32))}`;
50
+ if (core.pathRoot(leaf, BigInt(i), siblings) !== at.root) {
51
+ return fail('indexer-mismatch', `the path of ${i} does not fold to root ${at.root}`);
52
+ }
53
+ return { size: at.size, root: at.root, siblings };
54
+ }
55
+
56
+ /** Commitments `is` in the latest proved root, all under that one root, read and checked once: `null` until a proved
57
+ * root covers every one of them. */
58
+ export async function commitmentPaths(indexer: Indexer, chain: Chain, is: number[]): Promise<Membership[] | null> {
59
+ const at = (await indexer.status()).latestRoot;
60
+ if (!at || is.some((i) => at.size <= i)) return null;
61
+ const paths: Membership[] = [];
62
+ for (const i of is)
63
+ paths.push(
64
+ await pathAt(
65
+ i,
66
+ await chunkOf(indexer, i),
67
+ at,
68
+ (p) => indexer.page('chunk-roots', p),
69
+ () => indexer.pageRoots(),
70
+ ),
71
+ );
72
+ // the root a server reports is checked against the ledger: a forged one would make the proof fail on chain
73
+ if (!(await chain.provedRoot(at.size, at.root))) return fail('indexer-mismatch', `root ${at.root} is not proved`);
74
+ return paths;
75
+ }
76
+
77
+ /** Commitment `i` in the latest proved root: `null` until a proved root covers it. */
78
+ export const commitmentPath = async (indexer: Indexer, chain: Chain, i: number): Promise<Membership | null> =>
79
+ (await commitmentPaths(indexer, chain, [i]))?.[0] ?? null;
80
+
81
+ /** Deposits `is` in the ASP root the verifier currently publishes, all under that one root: `null` if that root does
82
+ * not approve every one of them. */
83
+ export async function aspPaths(asp: Asp, chain: Chain, is: number[]): Promise<Membership[] | null> {
84
+ const root = await chain.latestAspRoot();
85
+ const at = await asp.rootEntry(root);
86
+ if (!at) return fail('indexer-mismatch', `the ASP has no record of root ${root}`);
87
+ const paths: Membership[] = [];
88
+ for (const i of is) {
89
+ if (at.size <= i) return null;
90
+ const c = Math.floor(i / PAGE);
91
+ const leaves = core.aspLeaves(await asp.bitmap(c), BigInt(c * PAGE), Math.min(PAGE, at.size - c * PAGE));
92
+ if (leaves.subarray((i % PAGE) * 32, (i % PAGE) * 32 + 32).every((b) => b === 0)) return null;
93
+ paths.push(
94
+ await pathAt(
95
+ i,
96
+ leaves,
97
+ at,
98
+ (p) => asp.chunkRoots(p),
99
+ () => asp.pageRoots(),
100
+ ),
101
+ );
102
+ }
103
+ return paths;
104
+ }
105
+
106
+ /** Deposit `i` in the ASP root the verifier currently publishes: `null` if that root does not approve it. */
107
+ export const aspPath = async (asp: Asp, chain: Chain, i: number): Promise<Membership | null> =>
108
+ (await aspPaths(asp, chain, [i]))?.[0] ?? null;