@interest-protocol/vortex-sdk 2.0.0 → 3.0.1
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/dist/entities/merkle-tree.d.ts +3 -80
- package/dist/entities/merkle-tree.d.ts.map +1 -1
- package/dist/index.js +13 -203
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13 -203
- package/dist/index.mjs.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/vortex.types.d.ts +1 -1
- package/dist/vortex.types.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/deposit.ts +1 -1
- package/src/entities/merkle-tree.ts +9 -251
- package/src/utils/index.ts +6 -6
- package/src/vortex.types.ts +1 -1
- package/src/withdraw.ts +1 -1
- package/dist/__tests__/vortex.test.d.ts +0 -2
- package/dist/__tests__/vortex.test.d.ts.map +0 -1
- package/src/__tests__/vortex.test.ts +0 -25
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MerkleTree } from '
|
|
1
|
+
import { MerkleTree } from 'fixed-merkle-tree';
|
|
2
2
|
import { Utxo } from '../entities/utxo';
|
|
3
3
|
import { VortexKeypair } from '../entities/keypair';
|
|
4
4
|
export declare const reverseBytes: (bytes: Uint8Array) => Uint8Array;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIpD,eAAO,MAAM,YAAY,GAAI,OAAO,UAAU,KAAG,UAMhD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,UAAU,KAAG,MAEjD,CAAC;AAEF,wBAAgB,aAAa,CAC3B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,IAAI,GAAG,IAAI,GAChB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAkEpB;AAED,UAAU,gBAAgB;IACxB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,EAAE,IAAI,CAAC;IACjB,WAAW,EAAE,IAAI,CAAC;IAClB,WAAW,EAAE,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,YAAY,GAAI,+JAa1B,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;CA2BlB,CAAC;AAEF,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC"}
|
package/dist/vortex.types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { MaybeTx } from '@interest-protocol/sui-core-sdk';
|
|
|
2
2
|
import { TransactionResult } from '@mysten/sui/transactions';
|
|
3
3
|
import { Vortex } from './vortex';
|
|
4
4
|
import { VortexKeypair } from './entities/keypair';
|
|
5
|
-
import { MerkleTree } from '
|
|
5
|
+
import { MerkleTree } from 'fixed-merkle-tree';
|
|
6
6
|
import { Utxo } from './entities/utxo';
|
|
7
7
|
export declare enum Action {
|
|
8
8
|
Deposit = 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vortex.types.d.ts","sourceRoot":"","sources":["../src/vortex.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"vortex.types.d.ts","sourceRoot":"","sources":["../src/vortex.types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interest-protocol/vortex-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"@noble/hashes": "^2.0.1",
|
|
24
24
|
"@polymedia/suitcase-core": "^0.0.67",
|
|
25
25
|
"bn.js": "^5.2.2",
|
|
26
|
+
"fixed-merkle-tree": "^0.7.3",
|
|
26
27
|
"ramda": "^0.30.1",
|
|
27
28
|
"tiny-invariant": "^1.3.3",
|
|
28
29
|
"@interest-protocol/sui-core-sdk": "1.0.0"
|
package/src/deposit.ts
CHANGED
|
@@ -140,7 +140,7 @@ export const deposit = async ({
|
|
|
140
140
|
const { proof: moveProof, tx: tx3 } = vortex.newProof({
|
|
141
141
|
tx: tx2,
|
|
142
142
|
proofPoints: fromHex('0x' + proof.proofSerializedHex),
|
|
143
|
-
root: merkleTree.root
|
|
143
|
+
root: BigInt(merkleTree.root),
|
|
144
144
|
publicValue: amountMinusFrontendFee,
|
|
145
145
|
action: Action.Deposit,
|
|
146
146
|
extDataHash: extDataHashBigInt,
|
|
@@ -1,256 +1,14 @@
|
|
|
1
1
|
// packages/vortex/src/entities/merkle-tree.ts
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
ZERO_VALUE,
|
|
5
|
-
EMPTY_SUBTREE_HASHES,
|
|
6
|
-
MERKLE_TREE_HEIGHT,
|
|
7
|
-
} from '../constants';
|
|
3
|
+
import { ZERO_VALUE, MERKLE_TREE_HEIGHT } from '../constants';
|
|
8
4
|
import { poseidon2 } from '../crypto';
|
|
5
|
+
import { Element, MerkleTree as FixedMerkleTree } from 'fixed-merkle-tree';
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
capacity: number;
|
|
17
|
-
zeroElement: bigint;
|
|
7
|
+
export const buildMerkleTree = () =>
|
|
8
|
+
new FixedMerkleTree(MERKLE_TREE_HEIGHT, [], {
|
|
9
|
+
hashFunction: (left: Element, right: Element) =>
|
|
10
|
+
poseidon2(BigInt(left), BigInt(right)).toString(),
|
|
11
|
+
zeroElement: ZERO_VALUE.toString(),
|
|
12
|
+
});
|
|
18
13
|
|
|
19
|
-
|
|
20
|
-
private subtrees: bigint[]; // filledSubtrees in Tornado Nova (indices 0..levels-1)
|
|
21
|
-
private _nextIndex: number;
|
|
22
|
-
private leaves: bigint[];
|
|
23
|
-
private _root: bigint;
|
|
24
|
-
|
|
25
|
-
constructor(levels: number) {
|
|
26
|
-
this.levels = levels;
|
|
27
|
-
this.capacity = 2 ** levels;
|
|
28
|
-
this.zeroElement = ZERO_VALUE;
|
|
29
|
-
this.zeros = [];
|
|
30
|
-
this.subtrees = [];
|
|
31
|
-
this._nextIndex = 0;
|
|
32
|
-
this.leaves = [];
|
|
33
|
-
|
|
34
|
-
// Initialize zero hashes (0 to levels, inclusive)
|
|
35
|
-
// We need levels+1 elements: zeros[0] through zeros[levels]
|
|
36
|
-
for (let i = 0; i <= levels; i++) {
|
|
37
|
-
this.zeros[i] = EMPTY_SUBTREE_HASHES[i];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Initialize subtrees[0..levels-1] (matching Nova's filledSubtrees)
|
|
41
|
-
// subtrees[0] is initialized but never used (Nova quirk)
|
|
42
|
-
for (let i = 0; i < levels; i++) {
|
|
43
|
-
this.subtrees[i] = this.zeros[i];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Empty root is zeros[levels]
|
|
47
|
-
this._root = this.zeros[levels];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Returns the current Merkle root
|
|
52
|
-
*/
|
|
53
|
-
root(): bigint {
|
|
54
|
-
return this._root;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Insert elements in bulk (must be even number for pairing)
|
|
59
|
-
*/
|
|
60
|
-
bulkInsert(elements: bigint[]) {
|
|
61
|
-
if (elements.length % 2 !== 0) {
|
|
62
|
-
throw new Error('Must insert even number of elements (pairs)');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
for (let i = 0; i < elements.length; i += 2) {
|
|
66
|
-
this.insertPair(elements[i], elements[i + 1]);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Insert a pair of leaves (Nova style)
|
|
72
|
-
* This is the primary insertion method
|
|
73
|
-
*/
|
|
74
|
-
insertPair(leaf1: bigint, leaf2: bigint) {
|
|
75
|
-
if (this._nextIndex >= this.capacity) {
|
|
76
|
-
throw new Error('Merkle tree is full. No more leaves can be added');
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Store both leaves
|
|
80
|
-
this.leaves.push(leaf1, leaf2);
|
|
81
|
-
|
|
82
|
-
// Start by hashing the pair (level 0)
|
|
83
|
-
let currentIndex = Math.floor(this._nextIndex / 2);
|
|
84
|
-
let currentLevelHash = poseidon2(leaf1, leaf2);
|
|
85
|
-
|
|
86
|
-
// Increment by 2 since we're inserting a pair
|
|
87
|
-
this._nextIndex += 2;
|
|
88
|
-
|
|
89
|
-
// Process levels 1 to levels-1 (matching Nova: for i = 1; i < levels)
|
|
90
|
-
for (let i = 1; i < this.levels; i++) {
|
|
91
|
-
let left: bigint;
|
|
92
|
-
let right: bigint;
|
|
93
|
-
|
|
94
|
-
if (currentIndex % 2 === 0) {
|
|
95
|
-
// Current is left child
|
|
96
|
-
left = currentLevelHash;
|
|
97
|
-
right = this.zeros[i];
|
|
98
|
-
this.subtrees[i] = currentLevelHash; // Cache left subtree
|
|
99
|
-
} else {
|
|
100
|
-
// Current is right child
|
|
101
|
-
left = this.subtrees[i]; // Get cached left subtree
|
|
102
|
-
right = currentLevelHash;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
currentLevelHash = poseidon2(left, right);
|
|
106
|
-
currentIndex = Math.floor(currentIndex / 2);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Update root
|
|
110
|
-
this._root = currentLevelHash;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Insert a single leaf (for backward compatibility)
|
|
115
|
-
* Pairs it with a zero leaf
|
|
116
|
-
*/
|
|
117
|
-
insert(leaf: bigint) {
|
|
118
|
-
this.insertPair(leaf, this.zeros[0]);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Generate Merkle path for a leaf at given index
|
|
123
|
-
* Returns sibling hashes and indices for verification
|
|
124
|
-
*/
|
|
125
|
-
path(index: number): { pathElements: bigint[]; pathIndices: number[] } {
|
|
126
|
-
if (index < 0 || index >= this._nextIndex) {
|
|
127
|
-
throw new Error(
|
|
128
|
-
`Index out of bounds: ${index} (tree has ${this._nextIndex} leaves)`
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const pathElements: bigint[] = [];
|
|
133
|
-
const pathIndices: number[] = [];
|
|
134
|
-
|
|
135
|
-
// Level 0: Get sibling leaf
|
|
136
|
-
const isLeftAtLevel0 = index % 2 === 0;
|
|
137
|
-
pathIndices.push(isLeftAtLevel0 ? 0 : 1);
|
|
138
|
-
|
|
139
|
-
const siblingIndex = isLeftAtLevel0 ? index + 1 : index - 1;
|
|
140
|
-
const sibling =
|
|
141
|
-
siblingIndex < this._nextIndex
|
|
142
|
-
? this.leaves[siblingIndex]
|
|
143
|
-
: this.zeros[0];
|
|
144
|
-
pathElements.push(sibling);
|
|
145
|
-
|
|
146
|
-
// Levels 1 to levels-1 (matching Nova's loop structure)
|
|
147
|
-
let currentIndex = Math.floor(index / 2);
|
|
148
|
-
for (let i = 1; i < this.levels; i++) {
|
|
149
|
-
const isLeft = currentIndex % 2 === 0;
|
|
150
|
-
pathIndices.push(isLeft ? 0 : 1);
|
|
151
|
-
|
|
152
|
-
if (isLeft) {
|
|
153
|
-
// We're left child, sibling is right (zero hash)
|
|
154
|
-
pathElements.push(this.zeros[i]);
|
|
155
|
-
} else {
|
|
156
|
-
// We're right child, sibling is the cached left subtree
|
|
157
|
-
pathElements.push(this.subtrees[i]);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
currentIndex = Math.floor(currentIndex / 2);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return { pathElements, pathIndices };
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Get all leaves in the tree
|
|
168
|
-
*/
|
|
169
|
-
elements(): bigint[] {
|
|
170
|
-
return this.leaves;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Find the index of a specific leaf
|
|
175
|
-
*/
|
|
176
|
-
indexOf(element: bigint, comparator: Function | null = null): number {
|
|
177
|
-
if (comparator) {
|
|
178
|
-
return this.leaves.findIndex((leaf) => comparator(element, leaf));
|
|
179
|
-
}
|
|
180
|
-
return this.leaves.findIndex((leaf) => leaf === element);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Serialize tree state
|
|
185
|
-
*/
|
|
186
|
-
serialize() {
|
|
187
|
-
return {
|
|
188
|
-
levels: this.levels,
|
|
189
|
-
zeros: this.zeros,
|
|
190
|
-
subtrees: this.subtrees,
|
|
191
|
-
nextIndex: this._nextIndex,
|
|
192
|
-
leaves: this.leaves,
|
|
193
|
-
root: this._root,
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Verify a Merkle path is valid for a given leaf and root
|
|
199
|
-
*/
|
|
200
|
-
verify(
|
|
201
|
-
leaf: bigint,
|
|
202
|
-
pathElements: bigint[],
|
|
203
|
-
pathIndices: number[],
|
|
204
|
-
root: bigint
|
|
205
|
-
): boolean {
|
|
206
|
-
if (
|
|
207
|
-
pathElements.length !== this.levels ||
|
|
208
|
-
pathIndices.length !== this.levels
|
|
209
|
-
) {
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
let currentHash = leaf;
|
|
214
|
-
|
|
215
|
-
for (let i = 0; i < this.levels; i++) {
|
|
216
|
-
const sibling = pathElements[i];
|
|
217
|
-
const isLeft = pathIndices[i] === 0;
|
|
218
|
-
|
|
219
|
-
if (isLeft) {
|
|
220
|
-
currentHash = poseidon2(currentHash, sibling);
|
|
221
|
-
} else {
|
|
222
|
-
currentHash = poseidon2(sibling, currentHash);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
return currentHash === root;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Get the current number of leaves in the tree
|
|
231
|
-
*/
|
|
232
|
-
get nextIndex(): number {
|
|
233
|
-
return this._nextIndex;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Check if the tree is full
|
|
238
|
-
*/
|
|
239
|
-
isFull(): boolean {
|
|
240
|
-
return this._nextIndex >= this.capacity;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Get the maximum capacity of the tree
|
|
245
|
-
*/
|
|
246
|
-
getCapacity(): number {
|
|
247
|
-
return this.capacity;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Get the current fill percentage
|
|
252
|
-
*/
|
|
253
|
-
getFillPercentage(): number {
|
|
254
|
-
return (this._nextIndex / this.capacity) * 100;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
14
|
+
export type MerkleTree = FixedMerkleTree;
|
package/src/utils/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { toHex } from '@mysten/sui/utils';
|
|
2
2
|
import invariant from 'tiny-invariant';
|
|
3
|
-
import { MerkleTree } from '
|
|
3
|
+
import { MerkleTree } from 'fixed-merkle-tree';
|
|
4
4
|
import { Utxo } from '../entities/utxo';
|
|
5
5
|
import { VortexKeypair } from '../entities/keypair';
|
|
6
6
|
import { ZERO_VALUE, MERKLE_TREE_HEIGHT } from '../constants';
|
|
@@ -30,7 +30,7 @@ export function getMerklePath(
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const utxoIndex = Number(utxo.index);
|
|
33
|
-
const treeSize = merkleTree.elements
|
|
33
|
+
const treeSize = merkleTree.elements.length;
|
|
34
34
|
|
|
35
35
|
// For deposits, input UTXOs don't exist yet
|
|
36
36
|
if (utxoIndex < 0 || utxoIndex >= treeSize) {
|
|
@@ -44,7 +44,7 @@ export function getMerklePath(
|
|
|
44
44
|
const commitment = utxo.commitment();
|
|
45
45
|
|
|
46
46
|
// Verify commitment matches what's in the tree
|
|
47
|
-
const storedCommitment = merkleTree.elements
|
|
47
|
+
const storedCommitment = BigInt(merkleTree.elements[utxoIndex]!);
|
|
48
48
|
|
|
49
49
|
invariant(
|
|
50
50
|
storedCommitment === commitment,
|
|
@@ -56,7 +56,7 @@ export function getMerklePath(
|
|
|
56
56
|
let currentHash = commitment;
|
|
57
57
|
|
|
58
58
|
for (let i = 0; i < MERKLE_TREE_HEIGHT; i++) {
|
|
59
|
-
const sibling = pathElements[i];
|
|
59
|
+
const sibling = BigInt(pathElements[i]!);
|
|
60
60
|
const isLeft = pathIndices[i] === 0;
|
|
61
61
|
|
|
62
62
|
invariant(sibling !== undefined, `Sibling undefined at level ${i}`);
|
|
@@ -79,7 +79,7 @@ export function getMerklePath(
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
const calculatedRoot = currentHash;
|
|
82
|
-
const expectedRoot = merkleTree.root
|
|
82
|
+
const expectedRoot = BigInt(merkleTree.root);
|
|
83
83
|
|
|
84
84
|
invariant(
|
|
85
85
|
calculatedRoot === expectedRoot,
|
|
@@ -119,7 +119,7 @@ export const toProveInput = ({
|
|
|
119
119
|
outputUtxo1,
|
|
120
120
|
}: ToProveInputArgs) => {
|
|
121
121
|
return {
|
|
122
|
-
root: merkleTree.root
|
|
122
|
+
root: BigInt(merkleTree.root),
|
|
123
123
|
publicAmount,
|
|
124
124
|
extDataHash,
|
|
125
125
|
inputNullifier0: nullifier0,
|
package/src/vortex.types.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { MaybeTx } from '@interest-protocol/sui-core-sdk';
|
|
|
2
2
|
import { TransactionResult } from '@mysten/sui/transactions';
|
|
3
3
|
import { Vortex } from './vortex';
|
|
4
4
|
import { VortexKeypair } from './entities/keypair';
|
|
5
|
-
import { MerkleTree } from '
|
|
5
|
+
import { MerkleTree } from 'fixed-merkle-tree';
|
|
6
6
|
import { Utxo } from './entities/utxo';
|
|
7
7
|
|
|
8
8
|
export enum Action {
|
package/src/withdraw.ts
CHANGED
|
@@ -136,7 +136,7 @@ export const withdraw = async ({
|
|
|
136
136
|
const { proof: moveProof, tx: tx3 } = vortex.newProof({
|
|
137
137
|
tx: tx2,
|
|
138
138
|
proofPoints: fromHex('0x' + proof.proofSerializedHex),
|
|
139
|
-
root: merkleTree.root
|
|
139
|
+
root: BigInt(merkleTree.root),
|
|
140
140
|
publicValue: amount + relayerFee,
|
|
141
141
|
action: Action.Withdraw,
|
|
142
142
|
extDataHash: extDataHashBigInt,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vortex.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/vortex.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { testVortex } from './test-utils';
|
|
2
|
-
import { MERKLE_TREE_HEIGHT, EMPTY_SUBTREE_HASHES } from '../constants';
|
|
3
|
-
|
|
4
|
-
describe('Vortex', () => {
|
|
5
|
-
it('should get the TVL', async () => {
|
|
6
|
-
const tvl = await testVortex.tvl();
|
|
7
|
-
expect(tvl).toBe(0n);
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('should get the root', async () => {
|
|
11
|
-
const root = await testVortex.root();
|
|
12
|
-
expect(root).toBe(String(EMPTY_SUBTREE_HASHES[MERKLE_TREE_HEIGHT]));
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('should get the next index', async () => {
|
|
16
|
-
const nextIndex = await testVortex.nextIndex();
|
|
17
|
-
expect(nextIndex).toBe('0');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should check if a nullifier is spent', async () => {
|
|
21
|
-
const nullifier = 12345n;
|
|
22
|
-
const isNullifierSpent = await testVortex.isNullifierSpent(nullifier);
|
|
23
|
-
expect(isNullifierSpent).toBe(false);
|
|
24
|
-
});
|
|
25
|
-
});
|