@unlink-xyz/core 0.1.3-canary.fd5dddf → 0.1.4
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 +9 -0
- package/dist/account/account.d.ts +31 -2
- package/dist/account/account.d.ts.map +1 -1
- package/dist/account/accounts.d.ts +42 -0
- package/dist/account/accounts.d.ts.map +1 -0
- package/dist/account/seed.d.ts +45 -0
- package/dist/account/seed.d.ts.map +1 -0
- package/dist/account/serialization.d.ts +6 -0
- package/dist/account/serialization.d.ts.map +1 -0
- package/dist/browser/index.js +34424 -86406
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/wallet/index.js +55942 -0
- package/dist/browser/wallet/index.js.map +1 -0
- package/dist/clients/broadcaster.d.ts +1 -0
- package/dist/clients/broadcaster.d.ts.map +1 -1
- package/dist/clients/indexer.d.ts +5 -0
- package/dist/clients/indexer.d.ts.map +1 -1
- package/dist/config.d.ts +6 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/crypto/adapters/index.d.ts +17 -0
- package/dist/crypto/adapters/index.d.ts.map +1 -0
- package/dist/crypto/adapters/polyfills.d.ts +5 -0
- package/dist/crypto/adapters/polyfills.d.ts.map +1 -0
- package/dist/crypto/encrypt.d.ts +33 -0
- package/dist/crypto/encrypt.d.ts.map +1 -0
- package/dist/crypto/secure-memory.d.ts.map +1 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6721 -23
- package/dist/index.js.map +1 -0
- package/dist/keys/derive.d.ts +2 -2
- package/dist/keys/derive.d.ts.map +1 -1
- package/dist/keys/hex.d.ts +1 -4
- package/dist/keys/hex.d.ts.map +1 -1
- package/dist/keys/mnemonic.d.ts +0 -2
- package/dist/keys/mnemonic.d.ts.map +1 -1
- package/dist/keys.d.ts +1 -0
- package/dist/keys.d.ts.map +1 -1
- package/dist/prover/config.d.ts +54 -9
- package/dist/prover/config.d.ts.map +1 -1
- package/dist/prover/integrity.d.ts +20 -0
- package/dist/prover/integrity.d.ts.map +1 -0
- package/dist/prover/prover.d.ts +16 -31
- package/dist/prover/prover.d.ts.map +1 -1
- package/dist/state/merkle/hydrator.d.ts +21 -19
- package/dist/state/merkle/hydrator.d.ts.map +1 -1
- package/dist/state/merkle/index.d.ts +1 -1
- package/dist/state/merkle/index.d.ts.map +1 -1
- package/dist/state/store/ciphertext-store.d.ts +7 -0
- package/dist/state/store/ciphertext-store.d.ts.map +1 -1
- package/dist/state/store/index.d.ts +1 -1
- package/dist/state/store/index.d.ts.map +1 -1
- package/dist/state/store/job-store.d.ts.map +1 -1
- package/dist/state/store/jobs.d.ts +14 -16
- package/dist/state/store/jobs.d.ts.map +1 -1
- package/dist/state/store/leaf-store.d.ts +4 -0
- package/dist/state/store/leaf-store.d.ts.map +1 -1
- package/dist/state/store/nullifier-store.d.ts.map +1 -1
- package/dist/state/store/records.d.ts +8 -0
- package/dist/state/store/records.d.ts.map +1 -1
- package/dist/state/store/store.d.ts +18 -0
- package/dist/state/store/store.d.ts.map +1 -1
- package/dist/storage/indexeddb.d.ts.map +1 -1
- package/dist/storage/memory.d.ts.map +1 -1
- package/dist/transactions/adapter.d.ts +31 -0
- package/dist/transactions/adapter.d.ts.map +1 -0
- package/dist/transactions/deposit.d.ts +1 -1
- package/dist/transactions/deposit.d.ts.map +1 -1
- package/dist/transactions/index.d.ts +4 -2
- package/dist/transactions/index.d.ts.map +1 -1
- package/dist/transactions/note-sync.d.ts +3 -3
- package/dist/transactions/note-sync.d.ts.map +1 -1
- package/dist/transactions/reconcile.d.ts +1 -1
- package/dist/transactions/reconcile.d.ts.map +1 -1
- package/dist/transactions/transact.d.ts +21 -2
- package/dist/transactions/transact.d.ts.map +1 -1
- package/dist/transactions/transaction-planner.d.ts +1 -1
- package/dist/transactions/transaction-planner.d.ts.map +1 -1
- package/dist/transactions/transfer-planner.d.ts +2 -1
- package/dist/transactions/transfer-planner.d.ts.map +1 -1
- package/dist/transactions/types/deposit.d.ts +3 -3
- package/dist/transactions/types/deposit.d.ts.map +1 -1
- package/dist/transactions/types/domain.d.ts +3 -0
- package/dist/transactions/types/domain.d.ts.map +1 -1
- package/dist/transactions/types/options.d.ts +14 -5
- package/dist/transactions/types/options.d.ts.map +1 -1
- package/dist/transactions/types/planning.d.ts +2 -0
- package/dist/transactions/types/planning.d.ts.map +1 -1
- package/dist/transactions/types/state-stores.d.ts +53 -5
- package/dist/transactions/types/state-stores.d.ts.map +1 -1
- package/dist/transactions/types/transact.d.ts +10 -3
- package/dist/transactions/types/transact.d.ts.map +1 -1
- package/dist/transactions/withdrawal-planner.d.ts +1 -1
- package/dist/transactions/withdrawal-planner.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsup.config.d.ts +8 -0
- package/dist/tsup.config.d.ts.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/amounts.d.ts +0 -13
- package/dist/utils/amounts.d.ts.map +1 -1
- package/dist/utils/async.js +37 -34
- package/dist/utils/async.js.map +1 -0
- package/dist/utils/bigint.d.ts +0 -2
- package/dist/utils/bigint.d.ts.map +1 -1
- package/dist/utils/random.d.ts +5 -0
- package/dist/utils/random.d.ts.map +1 -1
- package/dist/utils/validators.d.ts.map +1 -1
- package/dist/vitest.config.d.ts.map +1 -1
- package/dist/wallet/adapter.d.ts +21 -0
- package/dist/wallet/adapter.d.ts.map +1 -0
- package/dist/wallet/burner/service.d.ts +32 -0
- package/dist/wallet/burner/service.d.ts.map +1 -0
- package/dist/wallet/burner/types.d.ts +47 -0
- package/dist/wallet/burner/types.d.ts.map +1 -0
- package/dist/wallet/index.d.ts +20 -0
- package/dist/wallet/index.d.ts.map +1 -0
- package/dist/wallet/index.js +6462 -0
- package/dist/wallet/index.js.map +1 -0
- package/dist/wallet/sdk.d.ts +48 -0
- package/dist/wallet/sdk.d.ts.map +1 -0
- package/dist/wallet/types.d.ts +457 -0
- package/dist/wallet/types.d.ts.map +1 -0
- package/dist/wallet/unlink-wallet.d.ts +187 -0
- package/dist/wallet/unlink-wallet.d.ts.map +1 -0
- package/package.json +16 -6
- package/dist/account/account.js +0 -142
- package/dist/circuits.json +0 -74
- package/dist/clients/broadcaster.js +0 -30
- package/dist/clients/http.js +0 -72
- package/dist/clients/indexer.js +0 -94
- package/dist/config.js +0 -36
- package/dist/constants.js +0 -5
- package/dist/core.js +0 -15
- package/dist/crypto-adapters/auto-init.d.ts +0 -2
- package/dist/crypto-adapters/auto-init.d.ts.map +0 -1
- package/dist/crypto-adapters/auto-init.js +0 -7
- package/dist/crypto-adapters/index.d.ts +0 -22
- package/dist/crypto-adapters/index.d.ts.map +0 -1
- package/dist/crypto-adapters/index.js +0 -47
- package/dist/crypto-adapters/polyfills.d.ts +0 -5
- package/dist/crypto-adapters/polyfills.d.ts.map +0 -1
- package/dist/crypto-adapters/polyfills.js +0 -8
- package/dist/errors.js +0 -36
- package/dist/history/index.js +0 -2
- package/dist/history/service.js +0 -354
- package/dist/history/types.js +0 -1
- package/dist/keys/address.js +0 -55
- package/dist/keys/derive.js +0 -112
- package/dist/keys/hex.js +0 -66
- package/dist/keys/index.js +0 -4
- package/dist/keys/mnemonic.js +0 -23
- package/dist/keys.js +0 -45
- package/dist/prover/config.js +0 -70
- package/dist/prover/index.js +0 -1
- package/dist/prover/prover.js +0 -291
- package/dist/prover/registry.js +0 -18
- package/dist/schema.js +0 -14
- package/dist/state/index.js +0 -2
- package/dist/state/merkle/hydrator.js +0 -37
- package/dist/state/merkle/index.js +0 -2
- package/dist/state/merkle/merkle-tree.js +0 -113
- package/dist/state/store/ciphertext-store.js +0 -37
- package/dist/state/store/history-store.js +0 -53
- package/dist/state/store/index.js +0 -9
- package/dist/state/store/job-store.js +0 -144
- package/dist/state/store/jobs.js +0 -1
- package/dist/state/store/leaf-store.js +0 -32
- package/dist/state/store/note-store.js +0 -146
- package/dist/state/store/nullifier-store.js +0 -60
- package/dist/state/store/records.js +0 -1
- package/dist/state/store/root-store.js +0 -26
- package/dist/state/store/store.js +0 -113
- package/dist/storage/index.js +0 -2
- package/dist/storage/indexeddb.js +0 -205
- package/dist/storage/memory.js +0 -91
- package/dist/transactions/deposit.js +0 -220
- package/dist/transactions/index.js +0 -9
- package/dist/transactions/note-selection.js +0 -201
- package/dist/transactions/note-sync.js +0 -485
- package/dist/transactions/reconcile.js +0 -85
- package/dist/transactions/transact.js +0 -450
- package/dist/transactions/transaction-planner.js +0 -116
- package/dist/transactions/transfer-planner.js +0 -85
- package/dist/transactions/types/deposit.js +0 -1
- package/dist/transactions/types/domain.js +0 -4
- package/dist/transactions/types/index.js +0 -17
- package/dist/transactions/types/options.js +0 -1
- package/dist/transactions/types/planning.js +0 -1
- package/dist/transactions/types/state-stores.js +0 -1
- package/dist/transactions/types/transact.js +0 -1
- package/dist/transactions/withdrawal-planner.js +0 -128
- package/dist/tsup.browser.config.js +0 -34
- package/dist/types.js +0 -1
- package/dist/utils/amounts.js +0 -89
- package/dist/utils/bigint.js +0 -29
- package/dist/utils/crypto.d.ts +0 -18
- package/dist/utils/crypto.d.ts.map +0 -1
- package/dist/utils/crypto.js +0 -45
- package/dist/utils/format.js +0 -33
- package/dist/utils/json-codec.js +0 -25
- package/dist/utils/notes.js +0 -14
- package/dist/utils/polling.js +0 -11
- package/dist/utils/random.js +0 -27
- package/dist/utils/secure-memory.d.ts.map +0 -1
- package/dist/utils/secure-memory.js +0 -28
- package/dist/utils/signature.js +0 -14
- package/dist/utils/validators.js +0 -96
- package/dist/vitest.config.js +0 -13
- /package/dist/{utils → crypto}/secure-memory.d.ts +0 -0
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { CoreError } from "../../errors.js";
|
|
2
|
-
import { parseHexToBigInt } from "../../utils/bigint.js";
|
|
3
|
-
export async function rebuildTreeFromStore({ chainId, trees, loadLeaf, }) {
|
|
4
|
-
trees.reset(chainId);
|
|
5
|
-
let idx = 0;
|
|
6
|
-
for (;;) {
|
|
7
|
-
const leaf = await loadLeaf(chainId, idx);
|
|
8
|
-
if (!leaf)
|
|
9
|
-
break;
|
|
10
|
-
const { index } = trees.addLeaf(chainId, parseHexToBigInt(leaf.commitment));
|
|
11
|
-
if (index !== idx) {
|
|
12
|
-
throw new CoreError(`stored leaves are inconsistent with local tree, expected ${idx}, got ${index}`);
|
|
13
|
-
}
|
|
14
|
-
idx += 1;
|
|
15
|
-
}
|
|
16
|
-
return idx;
|
|
17
|
-
}
|
|
18
|
-
// TODO: Will be used for inmemory merkle tree handling for caching.
|
|
19
|
-
// Atm everytime we need to access the tree we have to rebuild it from the store.
|
|
20
|
-
// This function will help to avoid multiple rebuilds for the same chain
|
|
21
|
-
export async function hydrateChain({ chainId, trees, loadLeaf, hydrated, }) {
|
|
22
|
-
if (hydrated.has(chainId))
|
|
23
|
-
return;
|
|
24
|
-
trees.reset(chainId);
|
|
25
|
-
let idx = 0;
|
|
26
|
-
for (;;) {
|
|
27
|
-
const leaf = await loadLeaf(chainId, idx);
|
|
28
|
-
if (!leaf)
|
|
29
|
-
break;
|
|
30
|
-
const { index } = trees.addLeaf(chainId, parseHexToBigInt(leaf.commitment));
|
|
31
|
-
if (index !== idx) {
|
|
32
|
-
throw new CoreError("stored leaves are inconsistent with local tree");
|
|
33
|
-
}
|
|
34
|
-
idx += 1;
|
|
35
|
-
}
|
|
36
|
-
hydrated.add(chainId);
|
|
37
|
-
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { IMT, } from "@zk-kit/imt";
|
|
2
|
-
import { poseidon } from "../../crypto-adapters/index.js";
|
|
3
|
-
import { CoreError } from "../../errors.js";
|
|
4
|
-
import { FieldSize, Hex } from "../../keys/hex.js";
|
|
5
|
-
import { ensureChainId } from "../../utils/validators.js";
|
|
6
|
-
const DEFAULT_DEPTH = 16;
|
|
7
|
-
const DEFAULT_ARITY = 2;
|
|
8
|
-
const ZERO_BYTE_LENGTH = FieldSize.SCALAR;
|
|
9
|
-
// Simple adapter: IMTNode[] -> poseidon(bigint[])
|
|
10
|
-
const hash = (values) => poseidon(values.map((v) => BigInt(v)));
|
|
11
|
-
const formatNode = (value) => Hex.fromBigInt(value, ZERO_BYTE_LENGTH, true);
|
|
12
|
-
export function createLocalMerkleTree() {
|
|
13
|
-
const zeroLeaf = 0n;
|
|
14
|
-
const capacity = 2 ** DEFAULT_DEPTH;
|
|
15
|
-
const tree = new IMT(hash, DEFAULT_DEPTH, zeroLeaf, DEFAULT_ARITY);
|
|
16
|
-
function addLeaf(value) {
|
|
17
|
-
if (tree.leaves.length >= capacity) {
|
|
18
|
-
throw new CoreError("merkle tree is full");
|
|
19
|
-
}
|
|
20
|
-
const insertedIndex = tree.leaves.length;
|
|
21
|
-
tree.insert(value);
|
|
22
|
-
return {
|
|
23
|
-
index: insertedIndex,
|
|
24
|
-
root: formatNode(tree.root),
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
function getRoot() {
|
|
28
|
-
return formatNode(tree.root);
|
|
29
|
-
}
|
|
30
|
-
function getLeafCount() {
|
|
31
|
-
return tree.leaves.length;
|
|
32
|
-
}
|
|
33
|
-
function getLeaf(index) {
|
|
34
|
-
const leaf = tree.leaves[index];
|
|
35
|
-
if (leaf === undefined) {
|
|
36
|
-
throw new CoreError("leaf does not exist in this tree");
|
|
37
|
-
}
|
|
38
|
-
return formatNode(BigInt(leaf));
|
|
39
|
-
}
|
|
40
|
-
function createMerkleProof(index) {
|
|
41
|
-
return tree.createProof(index);
|
|
42
|
-
}
|
|
43
|
-
return {
|
|
44
|
-
addLeaf,
|
|
45
|
-
getRoot,
|
|
46
|
-
getLeafCount,
|
|
47
|
-
getLeaf,
|
|
48
|
-
createMerkleProof,
|
|
49
|
-
getZero(level) {
|
|
50
|
-
if (level === tree.depth) {
|
|
51
|
-
return getRoot();
|
|
52
|
-
}
|
|
53
|
-
const zero = tree.zeroes[level];
|
|
54
|
-
if (zero === undefined) {
|
|
55
|
-
throw new CoreError("invalid level");
|
|
56
|
-
}
|
|
57
|
-
return formatNode(zero);
|
|
58
|
-
},
|
|
59
|
-
get depth() {
|
|
60
|
-
return tree.depth;
|
|
61
|
-
},
|
|
62
|
-
get capacity() {
|
|
63
|
-
return capacity;
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
export function createMerkleTrees() {
|
|
68
|
-
const trees = new Map();
|
|
69
|
-
const resetTree = (chainId) => {
|
|
70
|
-
ensureChainId(chainId);
|
|
71
|
-
const tree = createLocalMerkleTree();
|
|
72
|
-
trees.set(chainId, tree);
|
|
73
|
-
return tree;
|
|
74
|
-
};
|
|
75
|
-
const getOrCreate = (chainId) => {
|
|
76
|
-
ensureChainId(chainId);
|
|
77
|
-
let tree = trees.get(chainId);
|
|
78
|
-
if (!tree) {
|
|
79
|
-
tree = resetTree(chainId);
|
|
80
|
-
}
|
|
81
|
-
return tree;
|
|
82
|
-
};
|
|
83
|
-
return {
|
|
84
|
-
get(chainId) {
|
|
85
|
-
ensureChainId(chainId);
|
|
86
|
-
return trees.get(chainId);
|
|
87
|
-
},
|
|
88
|
-
getOrCreate,
|
|
89
|
-
addLeaf(chainId, value) {
|
|
90
|
-
return getOrCreate(chainId).addLeaf(value);
|
|
91
|
-
},
|
|
92
|
-
createMerkleProof(chainId, index) {
|
|
93
|
-
return getOrCreate(chainId).createMerkleProof(index);
|
|
94
|
-
},
|
|
95
|
-
getRoot(chainId) {
|
|
96
|
-
return getOrCreate(chainId).getRoot();
|
|
97
|
-
},
|
|
98
|
-
getLeafCount(chainId) {
|
|
99
|
-
return getOrCreate(chainId).getLeafCount();
|
|
100
|
-
},
|
|
101
|
-
reset(chainId) {
|
|
102
|
-
resetTree(chainId);
|
|
103
|
-
},
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Resolve merkle trees from options or create new instance.
|
|
108
|
-
* @param opts - Options object that may contain merkle trees
|
|
109
|
-
* @returns Merkle trees instance
|
|
110
|
-
*/
|
|
111
|
-
export function resolveMerkleTrees(opts) {
|
|
112
|
-
return opts?.merkleTrees ?? createMerkleTrees();
|
|
113
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { keys, validateKey } from "../../keys.js";
|
|
2
|
-
import { ensureChainId, ensurePositiveInt } from "../../utils/validators.js";
|
|
3
|
-
export function createCiphertextStore(storage) {
|
|
4
|
-
return {
|
|
5
|
-
/**
|
|
6
|
-
* Store encrypted note payloads alongside their on-chain commitments.
|
|
7
|
-
*/
|
|
8
|
-
async putCiphertext(chainId, index, payload) {
|
|
9
|
-
ensureChainId(chainId);
|
|
10
|
-
ensurePositiveInt("ciphertext index", index);
|
|
11
|
-
const key = keys.ciphertext(chainId, index);
|
|
12
|
-
validateKey(key);
|
|
13
|
-
await storage.put(key, new Uint8Array(payload));
|
|
14
|
-
},
|
|
15
|
-
/**
|
|
16
|
-
* Retrieve encrypted note payloads; returns null when the ciphertext is missing.
|
|
17
|
-
*/
|
|
18
|
-
async getCiphertext(chainId, index) {
|
|
19
|
-
ensureChainId(chainId);
|
|
20
|
-
ensurePositiveInt("ciphertext index", index);
|
|
21
|
-
const data = await storage.get(keys.ciphertext(chainId, index));
|
|
22
|
-
return data ? new Uint8Array(data) : null;
|
|
23
|
-
},
|
|
24
|
-
/**
|
|
25
|
-
* Remove all cached ciphertexts for a chain.
|
|
26
|
-
*/
|
|
27
|
-
async clearCiphertexts(chainId) {
|
|
28
|
-
ensureChainId(chainId);
|
|
29
|
-
const prefix = `ciphertexts:${chainId}:`;
|
|
30
|
-
const entries = await storage.iter({ prefix });
|
|
31
|
-
if (entries.length === 0)
|
|
32
|
-
return;
|
|
33
|
-
const deletions = entries.map(({ key }) => ({ del: key }));
|
|
34
|
-
await storage.batch(deletions);
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { keys } from "../../keys.js";
|
|
2
|
-
import { decodeJson, encodeJson, } from "../../utils/json-codec.js";
|
|
3
|
-
import { ensureChainId, ensureMpk } from "../../utils/validators.js";
|
|
4
|
-
export function createHistoryStore(storage) {
|
|
5
|
-
async function putMeta(options) {
|
|
6
|
-
await storage.put(keys.historyMeta(options.chainId, options.mpk), encodeJson({ v: 1, updatedAtMs: Date.now() }));
|
|
7
|
-
}
|
|
8
|
-
return {
|
|
9
|
-
async putHistoryEntry(entry) {
|
|
10
|
-
ensureChainId(entry.chainId);
|
|
11
|
-
ensureMpk(entry.mpk);
|
|
12
|
-
const key = keys.historyEntry(entry.id);
|
|
13
|
-
await storage.put(key, encodeJson(entry));
|
|
14
|
-
},
|
|
15
|
-
async hasHistorySnapshot(options) {
|
|
16
|
-
ensureChainId(options.chainId);
|
|
17
|
-
ensureMpk(options.mpk);
|
|
18
|
-
const meta = await storage.get(keys.historyMeta(options.chainId, options.mpk));
|
|
19
|
-
return meta !== null;
|
|
20
|
-
},
|
|
21
|
-
async listHistoryEntries(options) {
|
|
22
|
-
ensureChainId(options.chainId);
|
|
23
|
-
ensureMpk(options.mpk);
|
|
24
|
-
const prefix = keys.historyPrefix(options.chainId, options.mpk);
|
|
25
|
-
const entries = await storage.iter({ prefix });
|
|
26
|
-
const decoded = entries
|
|
27
|
-
.filter(({ key }) => !key.endsWith(":__meta__"))
|
|
28
|
-
.map(({ value }) => decodeJson(value));
|
|
29
|
-
decoded.sort((a, b) => {
|
|
30
|
-
const at = a.timestamp ?? 0;
|
|
31
|
-
const bt = b.timestamp ?? 0;
|
|
32
|
-
if (at !== bt)
|
|
33
|
-
return bt - at;
|
|
34
|
-
return b.txHash.localeCompare(a.txHash);
|
|
35
|
-
});
|
|
36
|
-
return decoded;
|
|
37
|
-
},
|
|
38
|
-
async clearHistoryEntries(options) {
|
|
39
|
-
ensureChainId(options.chainId);
|
|
40
|
-
ensureMpk(options.mpk);
|
|
41
|
-
const prefix = keys.historyPrefix(options.chainId, options.mpk);
|
|
42
|
-
const existing = await storage.iter({ prefix });
|
|
43
|
-
if (existing.length === 0)
|
|
44
|
-
return;
|
|
45
|
-
await storage.batch(existing.map(({ key }) => ({ del: key })));
|
|
46
|
-
},
|
|
47
|
-
async commitHistorySnapshot(options) {
|
|
48
|
-
ensureChainId(options.chainId);
|
|
49
|
-
ensureMpk(options.mpk);
|
|
50
|
-
await putMeta(options);
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { createStateStore } from "./store.js";
|
|
2
|
-
export { createLeafStore } from "./leaf-store.js";
|
|
3
|
-
export { createNoteStore } from "./note-store.js";
|
|
4
|
-
export { createNullifierStore } from "./nullifier-store.js";
|
|
5
|
-
export { createRootStore } from "./root-store.js";
|
|
6
|
-
export { createCiphertextStore } from "./ciphertext-store.js";
|
|
7
|
-
export { createHistoryStore } from "./history-store.js";
|
|
8
|
-
export { createJobStore } from "./job-store.js";
|
|
9
|
-
export { DEFAULT_JOB_TIMEOUT_MS, } from "./jobs.js";
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { CoreError } from "../../errors.js";
|
|
2
|
-
import { keys } from "../../keys.js";
|
|
3
|
-
import { decodeJson, encodeJson, getJson } from "../../utils/json-codec.js";
|
|
4
|
-
import { ensureAddress, ensureChainId, ensureMpk, ensurePositiveInt, } from "../../utils/validators.js";
|
|
5
|
-
import { DEFAULT_JOB_TIMEOUT_MS } from "../store/jobs.js";
|
|
6
|
-
const VALID_STATUSES = [
|
|
7
|
-
"pending",
|
|
8
|
-
"submitted",
|
|
9
|
-
"broadcasting",
|
|
10
|
-
"succeeded",
|
|
11
|
-
"failed",
|
|
12
|
-
"dead",
|
|
13
|
-
];
|
|
14
|
-
const VALID_KINDS = ["deposit", "transfer", "withdraw"];
|
|
15
|
-
function assertStatus(status) {
|
|
16
|
-
if (!VALID_STATUSES.includes(status)) {
|
|
17
|
-
throw new CoreError(`invalid job status: ${status}`);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
function assertKind(kind) {
|
|
21
|
-
if (!VALID_KINDS.includes(kind)) {
|
|
22
|
-
throw new CoreError(`invalid job kind: ${kind}`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
function normalizeTimestamps(job) {
|
|
26
|
-
const createdAt = typeof job.createdAt === "number" && Number.isFinite(job.createdAt)
|
|
27
|
-
? job.createdAt
|
|
28
|
-
: Date.now();
|
|
29
|
-
const timeoutMs = typeof job.timeoutMs === "number" && job.timeoutMs > 0
|
|
30
|
-
? job.timeoutMs
|
|
31
|
-
: DEFAULT_JOB_TIMEOUT_MS;
|
|
32
|
-
return {
|
|
33
|
-
...job,
|
|
34
|
-
createdAt,
|
|
35
|
-
timeoutMs,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function validatePoolTransactionRecord(job) {
|
|
39
|
-
ensureAddress("pool address", job.poolAddress);
|
|
40
|
-
if (!job.calldata) {
|
|
41
|
-
throw new CoreError("calldata is required for pool transaction record");
|
|
42
|
-
}
|
|
43
|
-
if (!Array.isArray(job.transactions) || !job.transactions.length) {
|
|
44
|
-
throw new CoreError("transactions array is required");
|
|
45
|
-
}
|
|
46
|
-
for (let i = 0; i < job.transactions.length; i++) {
|
|
47
|
-
const tx = job.transactions[i];
|
|
48
|
-
ensureAddress(`transaction token at ${i}`, tx.token);
|
|
49
|
-
if (!Array.isArray(tx.nullifiers) || !tx.nullifiers.length) {
|
|
50
|
-
throw new CoreError(`nullifiers array is required at index ${i}`);
|
|
51
|
-
}
|
|
52
|
-
// predictedCommitments can be empty for withdrawals with no change
|
|
53
|
-
if (!Array.isArray(tx.predictedCommitments)) {
|
|
54
|
-
throw new CoreError(`predicted commitments array is required at index ${i}`);
|
|
55
|
-
}
|
|
56
|
-
// Only require non-empty commitments if there's no withdrawal
|
|
57
|
-
if (!tx.predictedCommitments.length && !tx.withdrawal) {
|
|
58
|
-
throw new CoreError(`predicted commitments are required at index ${i}`);
|
|
59
|
-
}
|
|
60
|
-
for (let j = 0; j < tx.predictedCommitments.length; j++) {
|
|
61
|
-
const c = tx.predictedCommitments[j];
|
|
62
|
-
if (!c.hex) {
|
|
63
|
-
throw new CoreError(`predicted commitment hex is required at index ${i}.${j}`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (tx.withdrawal) {
|
|
67
|
-
if (!tx.withdrawal.amount) {
|
|
68
|
-
throw new CoreError(`withdrawal amount is required at index ${i}`);
|
|
69
|
-
}
|
|
70
|
-
if (!tx.withdrawal.recipient) {
|
|
71
|
-
throw new CoreError(`withdrawal recipient is required at index ${i}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
function validateDepositRecord(job) {
|
|
77
|
-
if (!Array.isArray(job.predictedCommitments) ||
|
|
78
|
-
!job.predictedCommitments.length) {
|
|
79
|
-
throw new CoreError("predicted commitments array is required for deposit");
|
|
80
|
-
}
|
|
81
|
-
for (let i = 0; i < job.predictedCommitments.length; i++) {
|
|
82
|
-
const c = job.predictedCommitments[i];
|
|
83
|
-
if (!c.hex) {
|
|
84
|
-
throw new CoreError(`predicted commitment hex is required at index ${i}`);
|
|
85
|
-
}
|
|
86
|
-
ensureAddress(`predicted commitment token at ${i}`, c.token);
|
|
87
|
-
if (!c.amount) {
|
|
88
|
-
throw new CoreError(`predicted commitment amount is required at index ${i}`);
|
|
89
|
-
}
|
|
90
|
-
if (c.index !== undefined) {
|
|
91
|
-
ensurePositiveInt(`predicted commitment index at ${i}`, c.index);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
function validateJob(job) {
|
|
96
|
-
if (!job.relayId) {
|
|
97
|
-
throw new CoreError("relayId is required");
|
|
98
|
-
}
|
|
99
|
-
ensureChainId(job.chainId);
|
|
100
|
-
if (job.mpk !== undefined) {
|
|
101
|
-
ensureMpk(job.mpk);
|
|
102
|
-
}
|
|
103
|
-
assertStatus(job.status);
|
|
104
|
-
assertKind(job.kind);
|
|
105
|
-
ensurePositiveInt("job createdAt", job.createdAt);
|
|
106
|
-
ensurePositiveInt("job timeoutMs", job.timeoutMs);
|
|
107
|
-
if (job.lastCheckedAt !== undefined) {
|
|
108
|
-
ensurePositiveInt("job lastCheckedAt", job.lastCheckedAt);
|
|
109
|
-
}
|
|
110
|
-
if (job.kind === "deposit") {
|
|
111
|
-
validateDepositRecord(job);
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
validatePoolTransactionRecord(job);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function buildJobKey(relayId) {
|
|
118
|
-
return keys.job(relayId);
|
|
119
|
-
}
|
|
120
|
-
export function createJobStore(storage) {
|
|
121
|
-
return {
|
|
122
|
-
async putJob(job) {
|
|
123
|
-
const normalized = normalizeTimestamps(job);
|
|
124
|
-
validateJob(normalized);
|
|
125
|
-
await storage.put(buildJobKey(normalized.relayId), encodeJson(normalized));
|
|
126
|
-
},
|
|
127
|
-
async getJob(relayId) {
|
|
128
|
-
return getJson(storage, buildJobKey(relayId));
|
|
129
|
-
},
|
|
130
|
-
async listJobs(filter = {}) {
|
|
131
|
-
const entries = await storage.iter({ prefix: "jobs:" });
|
|
132
|
-
const statuses = filter.statuses ?? VALID_STATUSES;
|
|
133
|
-
const filtered = entries
|
|
134
|
-
.map(({ value }) => decodeJson(value))
|
|
135
|
-
.filter((job) => (filter.kind === undefined || job.kind === filter.kind) &&
|
|
136
|
-
statuses.includes(job.status));
|
|
137
|
-
filtered.sort((a, b) => a.createdAt - b.createdAt);
|
|
138
|
-
return filtered;
|
|
139
|
-
},
|
|
140
|
-
async deleteJob(relayId) {
|
|
141
|
-
await storage.delete(buildJobKey(relayId));
|
|
142
|
-
},
|
|
143
|
-
};
|
|
144
|
-
}
|
package/dist/state/store/jobs.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_JOB_TIMEOUT_MS = 5 * 60 * 1000;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { keys } from "../../keys.js";
|
|
2
|
-
import { getJson, putJson } from "../../utils/json-codec.js";
|
|
3
|
-
import { ensureChainId, ensurePositiveInt } from "../../utils/validators.js";
|
|
4
|
-
export function createLeafStore(storage) {
|
|
5
|
-
return {
|
|
6
|
-
/**
|
|
7
|
-
* Cache public leaf data pulled from the on-chain Merkle tree.
|
|
8
|
-
*/
|
|
9
|
-
async putLeaf(leaf) {
|
|
10
|
-
ensureChainId(leaf.chainId);
|
|
11
|
-
ensurePositiveInt("leaf index", leaf.index);
|
|
12
|
-
await putJson(storage, keys.leaf(leaf.chainId, leaf.index), leaf);
|
|
13
|
-
},
|
|
14
|
-
/**
|
|
15
|
-
* Load a leaf commitment by tree index.
|
|
16
|
-
*/
|
|
17
|
-
async getLeaf(chainId, index) {
|
|
18
|
-
return getJson(storage, keys.leaf(chainId, index));
|
|
19
|
-
},
|
|
20
|
-
/**
|
|
21
|
-
* Remove all cached leaves for a chain.
|
|
22
|
-
*/
|
|
23
|
-
async clearLeaves(chainId) {
|
|
24
|
-
const prefix = `leaves:${chainId}:`;
|
|
25
|
-
const entries = await storage.iter({ prefix });
|
|
26
|
-
if (entries.length === 0)
|
|
27
|
-
return;
|
|
28
|
-
const deletions = entries.map(({ key }) => ({ del: key }));
|
|
29
|
-
await storage.batch(deletions);
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { CoreError } from "../../errors.js";
|
|
2
|
-
import { keys } from "../../keys.js";
|
|
3
|
-
import { decodeJson, encodeJson, getJson, } from "../../utils/json-codec.js";
|
|
4
|
-
import { ensureBigIntString, ensureChainId, ensureMpk, ensurePositiveInt, } from "../../utils/validators.js";
|
|
5
|
-
export const emptyBytes = () => new Uint8Array(0);
|
|
6
|
-
export function createNoteStore(storage) {
|
|
7
|
-
const persistNote = async (record) => {
|
|
8
|
-
ensureChainId(record.chainId);
|
|
9
|
-
ensurePositiveInt("note index", record.index);
|
|
10
|
-
ensureMpk(record.mpk);
|
|
11
|
-
ensureBigIntString("note value", record.value);
|
|
12
|
-
if (record.createdAt !== undefined) {
|
|
13
|
-
ensurePositiveInt("note createdAt", record.createdAt);
|
|
14
|
-
}
|
|
15
|
-
if (record.spentAt !== undefined) {
|
|
16
|
-
ensurePositiveInt("note spentAt", record.spentAt);
|
|
17
|
-
}
|
|
18
|
-
if (record.createdTxHash !== undefined &&
|
|
19
|
-
record.createdTxHash.length === 0) {
|
|
20
|
-
throw new CoreError("note createdTxHash must be a non-empty string");
|
|
21
|
-
}
|
|
22
|
-
if (record.createdEventType !== undefined &&
|
|
23
|
-
record.createdEventType.length === 0) {
|
|
24
|
-
throw new CoreError("note createdEventType must be a non-empty string");
|
|
25
|
-
}
|
|
26
|
-
if (record.spentTxHash !== undefined && record.spentTxHash.length === 0) {
|
|
27
|
-
throw new CoreError("note spentTxHash must be a non-empty string");
|
|
28
|
-
}
|
|
29
|
-
const noteKey = keys.note(record.chainId, record.index);
|
|
30
|
-
const previous = await getJson(storage, noteKey);
|
|
31
|
-
const ops = [
|
|
32
|
-
{ put: [noteKey, encodeJson(record)] },
|
|
33
|
-
];
|
|
34
|
-
if (previous && previous.spentAt === undefined) {
|
|
35
|
-
ops.push({
|
|
36
|
-
del: keys.unspent(previous.chainId, previous.mpk, previous.index),
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
if (record.spentAt === undefined) {
|
|
40
|
-
// idx:notes:unspent functions as a set, so we only persist the sentinel bytes.
|
|
41
|
-
ops.push({
|
|
42
|
-
put: [
|
|
43
|
-
keys.unspent(record.chainId, record.mpk, record.index),
|
|
44
|
-
emptyBytes(),
|
|
45
|
-
],
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
ops.push({
|
|
50
|
-
del: keys.unspent(record.chainId, record.mpk, record.index),
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
await storage.batch(ops);
|
|
54
|
-
};
|
|
55
|
-
const store = {
|
|
56
|
-
/**
|
|
57
|
-
* Upsert a note record and maintain the unspent-note index for fast balance queries.
|
|
58
|
-
* If the note already exists and is marked as spent, preserve spentAt unless the caller
|
|
59
|
-
* provides an explicit spentAt value (eg. upgrading from a local observation time to an
|
|
60
|
-
* on-chain timestamp from the indexer).
|
|
61
|
-
*/
|
|
62
|
-
async putNote(note) {
|
|
63
|
-
const noteKey = keys.note(note.chainId, note.index);
|
|
64
|
-
const existing = await getJson(storage, noteKey);
|
|
65
|
-
if (existing?.spentAt !== undefined && note.spentAt === undefined) {
|
|
66
|
-
// Preserve spentAt if caller doesn't provide a value.
|
|
67
|
-
await persistNote({ ...note, spentAt: existing.spentAt });
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
await persistNote({ ...note });
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
/**
|
|
74
|
-
* Fetch a note by (chainId, index) if it exists in local storage.
|
|
75
|
-
*/
|
|
76
|
-
async getNote(chainId, index) {
|
|
77
|
-
return getJson(storage, keys.note(chainId, index));
|
|
78
|
-
},
|
|
79
|
-
/**
|
|
80
|
-
* List notes matching optional filters (by chainId, mpk) and spent state.
|
|
81
|
-
*/
|
|
82
|
-
async listNotes(options = {}) {
|
|
83
|
-
const { chainId, mpk, token, includeSpent = true } = options;
|
|
84
|
-
const prefix = chainId !== undefined ? `notes:${chainId}:` : "notes:";
|
|
85
|
-
const entries = await storage.iter({ prefix });
|
|
86
|
-
const filtered = entries
|
|
87
|
-
.map(({ value }) => decodeJson(value))
|
|
88
|
-
.filter((note) => (chainId === undefined || note.chainId === chainId) &&
|
|
89
|
-
(mpk === undefined || note.mpk === mpk) &&
|
|
90
|
-
(token === undefined || note.token === token) &&
|
|
91
|
-
(includeSpent || note.spentAt === undefined));
|
|
92
|
-
filtered.sort((a, b) => a.index - b.index);
|
|
93
|
-
return filtered;
|
|
94
|
-
},
|
|
95
|
-
/**
|
|
96
|
-
* Mark a cached note as spent by setting its timestamp and transaction hash.
|
|
97
|
-
*/
|
|
98
|
-
async markNoteSpent(chainId, index, spentAt = Date.now(), spentTxHash) {
|
|
99
|
-
const existing = await store.getNote(chainId, index);
|
|
100
|
-
if (!existing) {
|
|
101
|
-
throw new CoreError("note not found");
|
|
102
|
-
}
|
|
103
|
-
if (existing.spentAt === spentAt &&
|
|
104
|
-
existing.spentTxHash === spentTxHash) {
|
|
105
|
-
return existing;
|
|
106
|
-
}
|
|
107
|
-
const updated = { ...existing, spentAt, spentTxHash };
|
|
108
|
-
await persistNote(updated);
|
|
109
|
-
return updated;
|
|
110
|
-
},
|
|
111
|
-
/**
|
|
112
|
-
* Drop the spent marker from a cached note, returning it to the unspent index.
|
|
113
|
-
*/
|
|
114
|
-
async markNoteUnspent(chainId, index) {
|
|
115
|
-
const existing = await store.getNote(chainId, index);
|
|
116
|
-
if (!existing) {
|
|
117
|
-
throw new CoreError("note not found");
|
|
118
|
-
}
|
|
119
|
-
if (existing.spentAt === undefined) {
|
|
120
|
-
return existing;
|
|
121
|
-
}
|
|
122
|
-
const updated = { ...existing };
|
|
123
|
-
delete updated.spentAt;
|
|
124
|
-
await persistNote(updated);
|
|
125
|
-
return updated;
|
|
126
|
-
},
|
|
127
|
-
/**
|
|
128
|
-
* Remove all cached notes and their unspent indices for a chain.
|
|
129
|
-
*/
|
|
130
|
-
async clearNotes(chainId) {
|
|
131
|
-
const notePrefix = `notes:${chainId}:`;
|
|
132
|
-
const noteEntries = await storage.iter({ prefix: notePrefix });
|
|
133
|
-
// Also clear unspent indices for this chain (all mpks)
|
|
134
|
-
const unspentPrefix = `idx:notes:unspent:${chainId}:`;
|
|
135
|
-
const unspentEntries = await storage.iter({ prefix: unspentPrefix });
|
|
136
|
-
if (noteEntries.length === 0 && unspentEntries.length === 0)
|
|
137
|
-
return;
|
|
138
|
-
const deletions = [
|
|
139
|
-
...noteEntries.map(({ key }) => ({ del: key })),
|
|
140
|
-
...unspentEntries.map(({ key }) => ({ del: key })),
|
|
141
|
-
];
|
|
142
|
-
await storage.batch(deletions);
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
return store;
|
|
146
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { keys } from "../../keys.js";
|
|
2
|
-
import { getJson, putJson } from "../../utils/json-codec.js";
|
|
3
|
-
import { ensureChainId } from "../../utils/validators.js";
|
|
4
|
-
export function createNullifierStore(storage) {
|
|
5
|
-
return {
|
|
6
|
-
/**
|
|
7
|
-
* Record a nullifier observation so later syncs can de-duplicate work.
|
|
8
|
-
*/
|
|
9
|
-
async putNullifier(nullifier) {
|
|
10
|
-
ensureChainId(nullifier.chainId);
|
|
11
|
-
await putJson(storage, keys.nullifier(nullifier.chainId, nullifier.nullifier), nullifier);
|
|
12
|
-
},
|
|
13
|
-
/**
|
|
14
|
-
* Lookup a previously observed nullifier by value.
|
|
15
|
-
*/
|
|
16
|
-
async getNullifier(chainId, value) {
|
|
17
|
-
return getJson(storage, keys.nullifier(chainId, value));
|
|
18
|
-
},
|
|
19
|
-
/**
|
|
20
|
-
* Count all nullifiers stored locally for a given chain.
|
|
21
|
-
*/
|
|
22
|
-
async countNullifiers(chainId) {
|
|
23
|
-
const prefix = `nullifiers:${chainId}:`;
|
|
24
|
-
const entries = await storage.iter({ prefix });
|
|
25
|
-
return entries.length;
|
|
26
|
-
},
|
|
27
|
-
/**
|
|
28
|
-
* Remove all cached nullifiers for a chain.
|
|
29
|
-
*/
|
|
30
|
-
async clearNullifiers(chainId) {
|
|
31
|
-
const prefix = `nullifiers:${chainId}:`;
|
|
32
|
-
const entries = await storage.iter({ prefix });
|
|
33
|
-
if (entries.length === 0)
|
|
34
|
-
return;
|
|
35
|
-
await storage.batch(entries.map(({ key }) => ({ del: key })));
|
|
36
|
-
},
|
|
37
|
-
/**
|
|
38
|
-
* Remove cached nullifiers whose noteIndex >= fromIndex.
|
|
39
|
-
* Used by partial resync to keep the count-based optimization accurate.
|
|
40
|
-
*/
|
|
41
|
-
async clearNullifiersFromIndex(chainId, fromIndex) {
|
|
42
|
-
const prefix = `nullifiers:${chainId}:`;
|
|
43
|
-
const entries = await storage.iter({ prefix });
|
|
44
|
-
const ops = [];
|
|
45
|
-
for (const { key, value } of entries) {
|
|
46
|
-
try {
|
|
47
|
-
const record = JSON.parse(new TextDecoder().decode(value));
|
|
48
|
-
if (record.noteIndex === undefined || record.noteIndex >= fromIndex) {
|
|
49
|
-
ops.push({ del: key });
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
// Malformed entry — skip
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
if (ops.length > 0)
|
|
57
|
-
await storage.batch(ops);
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { CoreError } from "../../errors.js";
|
|
2
|
-
import { keys, validateKey } from "../../keys.js";
|
|
3
|
-
import { getJson, putJson } from "../../utils/json-codec.js";
|
|
4
|
-
import { ensureChainId } from "../../utils/validators.js";
|
|
5
|
-
export function createRootStore(storage) {
|
|
6
|
-
return {
|
|
7
|
-
/**
|
|
8
|
-
* Persist a historical root snapshot for proof generation.
|
|
9
|
-
*/
|
|
10
|
-
async putRoot(root) {
|
|
11
|
-
ensureChainId(root.chainId);
|
|
12
|
-
if (typeof root.root !== "string" || root.root.length === 0) {
|
|
13
|
-
throw new CoreError("root value must be a non-empty string");
|
|
14
|
-
}
|
|
15
|
-
const key = keys.root(root.chainId, root.root);
|
|
16
|
-
validateKey(key);
|
|
17
|
-
await putJson(storage, key, root);
|
|
18
|
-
},
|
|
19
|
-
/**
|
|
20
|
-
* Retrieve a root snapshot by Merkle root value.
|
|
21
|
-
*/
|
|
22
|
-
async getRoot(chainId, value) {
|
|
23
|
-
return getJson(storage, keys.root(chainId, value));
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
}
|