@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/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { devInspectAndGetReturnValues } from '@polymedia/suitcase-core';
|
|
2
2
|
import invariant from 'tiny-invariant';
|
|
3
3
|
import { pathOr } from 'ramda';
|
|
4
|
+
import { MerkleTree } from 'fixed-merkle-tree';
|
|
4
5
|
import require$$0 from 'fs';
|
|
5
6
|
import { BN } from 'bn.js';
|
|
6
7
|
|
|
@@ -38841,201 +38842,10 @@ _VortexKeypair_instances = new WeakSet(), _VortexKeypair_decrypt = function _Vor
|
|
|
38841
38842
|
};
|
|
38842
38843
|
|
|
38843
38844
|
// packages/vortex/src/entities/merkle-tree.ts
|
|
38844
|
-
|
|
38845
|
-
|
|
38846
|
-
|
|
38847
|
-
|
|
38848
|
-
class MerkleTree {
|
|
38849
|
-
constructor(levels) {
|
|
38850
|
-
this.levels = levels;
|
|
38851
|
-
this.capacity = 2 ** levels;
|
|
38852
|
-
this.zeroElement = ZERO_VALUE;
|
|
38853
|
-
this.zeros = [];
|
|
38854
|
-
this.subtrees = [];
|
|
38855
|
-
this._nextIndex = 0;
|
|
38856
|
-
this.leaves = [];
|
|
38857
|
-
// Initialize zero hashes (0 to levels, inclusive)
|
|
38858
|
-
// We need levels+1 elements: zeros[0] through zeros[levels]
|
|
38859
|
-
for (let i = 0; i <= levels; i++) {
|
|
38860
|
-
this.zeros[i] = EMPTY_SUBTREE_HASHES[i];
|
|
38861
|
-
}
|
|
38862
|
-
// Initialize subtrees[0..levels-1] (matching Nova's filledSubtrees)
|
|
38863
|
-
// subtrees[0] is initialized but never used (Nova quirk)
|
|
38864
|
-
for (let i = 0; i < levels; i++) {
|
|
38865
|
-
this.subtrees[i] = this.zeros[i];
|
|
38866
|
-
}
|
|
38867
|
-
// Empty root is zeros[levels]
|
|
38868
|
-
this._root = this.zeros[levels];
|
|
38869
|
-
}
|
|
38870
|
-
/**
|
|
38871
|
-
* Returns the current Merkle root
|
|
38872
|
-
*/
|
|
38873
|
-
root() {
|
|
38874
|
-
return this._root;
|
|
38875
|
-
}
|
|
38876
|
-
/**
|
|
38877
|
-
* Insert elements in bulk (must be even number for pairing)
|
|
38878
|
-
*/
|
|
38879
|
-
bulkInsert(elements) {
|
|
38880
|
-
if (elements.length % 2 !== 0) {
|
|
38881
|
-
throw new Error('Must insert even number of elements (pairs)');
|
|
38882
|
-
}
|
|
38883
|
-
for (let i = 0; i < elements.length; i += 2) {
|
|
38884
|
-
this.insertPair(elements[i], elements[i + 1]);
|
|
38885
|
-
}
|
|
38886
|
-
}
|
|
38887
|
-
/**
|
|
38888
|
-
* Insert a pair of leaves (Nova style)
|
|
38889
|
-
* This is the primary insertion method
|
|
38890
|
-
*/
|
|
38891
|
-
insertPair(leaf1, leaf2) {
|
|
38892
|
-
if (this._nextIndex >= this.capacity) {
|
|
38893
|
-
throw new Error('Merkle tree is full. No more leaves can be added');
|
|
38894
|
-
}
|
|
38895
|
-
// Store both leaves
|
|
38896
|
-
this.leaves.push(leaf1, leaf2);
|
|
38897
|
-
// Start by hashing the pair (level 0)
|
|
38898
|
-
let currentIndex = Math.floor(this._nextIndex / 2);
|
|
38899
|
-
let currentLevelHash = poseidon2(leaf1, leaf2);
|
|
38900
|
-
// Increment by 2 since we're inserting a pair
|
|
38901
|
-
this._nextIndex += 2;
|
|
38902
|
-
// Process levels 1 to levels-1 (matching Nova: for i = 1; i < levels)
|
|
38903
|
-
for (let i = 1; i < this.levels; i++) {
|
|
38904
|
-
let left;
|
|
38905
|
-
let right;
|
|
38906
|
-
if (currentIndex % 2 === 0) {
|
|
38907
|
-
// Current is left child
|
|
38908
|
-
left = currentLevelHash;
|
|
38909
|
-
right = this.zeros[i];
|
|
38910
|
-
this.subtrees[i] = currentLevelHash; // Cache left subtree
|
|
38911
|
-
}
|
|
38912
|
-
else {
|
|
38913
|
-
// Current is right child
|
|
38914
|
-
left = this.subtrees[i]; // Get cached left subtree
|
|
38915
|
-
right = currentLevelHash;
|
|
38916
|
-
}
|
|
38917
|
-
currentLevelHash = poseidon2(left, right);
|
|
38918
|
-
currentIndex = Math.floor(currentIndex / 2);
|
|
38919
|
-
}
|
|
38920
|
-
// Update root
|
|
38921
|
-
this._root = currentLevelHash;
|
|
38922
|
-
}
|
|
38923
|
-
/**
|
|
38924
|
-
* Insert a single leaf (for backward compatibility)
|
|
38925
|
-
* Pairs it with a zero leaf
|
|
38926
|
-
*/
|
|
38927
|
-
insert(leaf) {
|
|
38928
|
-
this.insertPair(leaf, this.zeros[0]);
|
|
38929
|
-
}
|
|
38930
|
-
/**
|
|
38931
|
-
* Generate Merkle path for a leaf at given index
|
|
38932
|
-
* Returns sibling hashes and indices for verification
|
|
38933
|
-
*/
|
|
38934
|
-
path(index) {
|
|
38935
|
-
if (index < 0 || index >= this._nextIndex) {
|
|
38936
|
-
throw new Error(`Index out of bounds: ${index} (tree has ${this._nextIndex} leaves)`);
|
|
38937
|
-
}
|
|
38938
|
-
const pathElements = [];
|
|
38939
|
-
const pathIndices = [];
|
|
38940
|
-
// Level 0: Get sibling leaf
|
|
38941
|
-
const isLeftAtLevel0 = index % 2 === 0;
|
|
38942
|
-
pathIndices.push(isLeftAtLevel0 ? 0 : 1);
|
|
38943
|
-
const siblingIndex = isLeftAtLevel0 ? index + 1 : index - 1;
|
|
38944
|
-
const sibling = siblingIndex < this._nextIndex
|
|
38945
|
-
? this.leaves[siblingIndex]
|
|
38946
|
-
: this.zeros[0];
|
|
38947
|
-
pathElements.push(sibling);
|
|
38948
|
-
// Levels 1 to levels-1 (matching Nova's loop structure)
|
|
38949
|
-
let currentIndex = Math.floor(index / 2);
|
|
38950
|
-
for (let i = 1; i < this.levels; i++) {
|
|
38951
|
-
const isLeft = currentIndex % 2 === 0;
|
|
38952
|
-
pathIndices.push(isLeft ? 0 : 1);
|
|
38953
|
-
if (isLeft) {
|
|
38954
|
-
// We're left child, sibling is right (zero hash)
|
|
38955
|
-
pathElements.push(this.zeros[i]);
|
|
38956
|
-
}
|
|
38957
|
-
else {
|
|
38958
|
-
// We're right child, sibling is the cached left subtree
|
|
38959
|
-
pathElements.push(this.subtrees[i]);
|
|
38960
|
-
}
|
|
38961
|
-
currentIndex = Math.floor(currentIndex / 2);
|
|
38962
|
-
}
|
|
38963
|
-
return { pathElements, pathIndices };
|
|
38964
|
-
}
|
|
38965
|
-
/**
|
|
38966
|
-
* Get all leaves in the tree
|
|
38967
|
-
*/
|
|
38968
|
-
elements() {
|
|
38969
|
-
return this.leaves;
|
|
38970
|
-
}
|
|
38971
|
-
/**
|
|
38972
|
-
* Find the index of a specific leaf
|
|
38973
|
-
*/
|
|
38974
|
-
indexOf(element, comparator = null) {
|
|
38975
|
-
if (comparator) {
|
|
38976
|
-
return this.leaves.findIndex((leaf) => comparator(element, leaf));
|
|
38977
|
-
}
|
|
38978
|
-
return this.leaves.findIndex((leaf) => leaf === element);
|
|
38979
|
-
}
|
|
38980
|
-
/**
|
|
38981
|
-
* Serialize tree state
|
|
38982
|
-
*/
|
|
38983
|
-
serialize() {
|
|
38984
|
-
return {
|
|
38985
|
-
levels: this.levels,
|
|
38986
|
-
zeros: this.zeros,
|
|
38987
|
-
subtrees: this.subtrees,
|
|
38988
|
-
nextIndex: this._nextIndex,
|
|
38989
|
-
leaves: this.leaves,
|
|
38990
|
-
root: this._root,
|
|
38991
|
-
};
|
|
38992
|
-
}
|
|
38993
|
-
/**
|
|
38994
|
-
* Verify a Merkle path is valid for a given leaf and root
|
|
38995
|
-
*/
|
|
38996
|
-
verify(leaf, pathElements, pathIndices, root) {
|
|
38997
|
-
if (pathElements.length !== this.levels ||
|
|
38998
|
-
pathIndices.length !== this.levels) {
|
|
38999
|
-
return false;
|
|
39000
|
-
}
|
|
39001
|
-
let currentHash = leaf;
|
|
39002
|
-
for (let i = 0; i < this.levels; i++) {
|
|
39003
|
-
const sibling = pathElements[i];
|
|
39004
|
-
const isLeft = pathIndices[i] === 0;
|
|
39005
|
-
if (isLeft) {
|
|
39006
|
-
currentHash = poseidon2(currentHash, sibling);
|
|
39007
|
-
}
|
|
39008
|
-
else {
|
|
39009
|
-
currentHash = poseidon2(sibling, currentHash);
|
|
39010
|
-
}
|
|
39011
|
-
}
|
|
39012
|
-
return currentHash === root;
|
|
39013
|
-
}
|
|
39014
|
-
/**
|
|
39015
|
-
* Get the current number of leaves in the tree
|
|
39016
|
-
*/
|
|
39017
|
-
get nextIndex() {
|
|
39018
|
-
return this._nextIndex;
|
|
39019
|
-
}
|
|
39020
|
-
/**
|
|
39021
|
-
* Check if the tree is full
|
|
39022
|
-
*/
|
|
39023
|
-
isFull() {
|
|
39024
|
-
return this._nextIndex >= this.capacity;
|
|
39025
|
-
}
|
|
39026
|
-
/**
|
|
39027
|
-
* Get the maximum capacity of the tree
|
|
39028
|
-
*/
|
|
39029
|
-
getCapacity() {
|
|
39030
|
-
return this.capacity;
|
|
39031
|
-
}
|
|
39032
|
-
/**
|
|
39033
|
-
* Get the current fill percentage
|
|
39034
|
-
*/
|
|
39035
|
-
getFillPercentage() {
|
|
39036
|
-
return (this._nextIndex / this.capacity) * 100;
|
|
39037
|
-
}
|
|
39038
|
-
}
|
|
38845
|
+
const buildMerkleTree = () => new MerkleTree(MERKLE_TREE_HEIGHT, [], {
|
|
38846
|
+
hashFunction: (left, right) => poseidon2(BigInt(left), BigInt(right)).toString(),
|
|
38847
|
+
zeroElement: ZERO_VALUE.toString(),
|
|
38848
|
+
});
|
|
39039
38849
|
|
|
39040
38850
|
class Utxo {
|
|
39041
38851
|
constructor({ amount, blinding, keypair, index }) {
|
|
@@ -39610,7 +39420,7 @@ function getMerklePath(merkleTree, utxo) {
|
|
|
39610
39420
|
.map(() => [ZERO_VALUE.toString(), ZERO_VALUE.toString()]);
|
|
39611
39421
|
}
|
|
39612
39422
|
const utxoIndex = Number(utxo.index);
|
|
39613
|
-
const treeSize = merkleTree.elements
|
|
39423
|
+
const treeSize = merkleTree.elements.length;
|
|
39614
39424
|
// For deposits, input UTXOs don't exist yet
|
|
39615
39425
|
if (utxoIndex < 0 || utxoIndex >= treeSize) {
|
|
39616
39426
|
return Array(MERKLE_TREE_HEIGHT)
|
|
@@ -39621,13 +39431,13 @@ function getMerklePath(merkleTree, utxo) {
|
|
|
39621
39431
|
const { pathElements, pathIndices } = merkleTree.path(utxoIndex);
|
|
39622
39432
|
const commitment = utxo.commitment();
|
|
39623
39433
|
// Verify commitment matches what's in the tree
|
|
39624
|
-
const storedCommitment = merkleTree.elements
|
|
39434
|
+
const storedCommitment = BigInt(merkleTree.elements[utxoIndex]);
|
|
39625
39435
|
invariant(storedCommitment === commitment, `Commitment mismatch at index ${utxoIndex}: expected ${commitment}, got ${storedCommitment}`);
|
|
39626
39436
|
// Build WASM-compatible path (always [left, right] format)
|
|
39627
39437
|
const wasmPath = [];
|
|
39628
39438
|
let currentHash = commitment;
|
|
39629
39439
|
for (let i = 0; i < MERKLE_TREE_HEIGHT; i++) {
|
|
39630
|
-
const sibling = pathElements[i];
|
|
39440
|
+
const sibling = BigInt(pathElements[i]);
|
|
39631
39441
|
const isLeft = pathIndices[i] === 0;
|
|
39632
39442
|
invariant(sibling !== undefined, `Sibling undefined at level ${i}`);
|
|
39633
39443
|
const leftHash = isLeft ? currentHash : sibling;
|
|
@@ -39641,13 +39451,13 @@ function getMerklePath(merkleTree, utxo) {
|
|
|
39641
39451
|
currentHash = nextHash;
|
|
39642
39452
|
}
|
|
39643
39453
|
const calculatedRoot = currentHash;
|
|
39644
|
-
const expectedRoot = merkleTree.root
|
|
39454
|
+
const expectedRoot = BigInt(merkleTree.root);
|
|
39645
39455
|
invariant(calculatedRoot === expectedRoot, `Root mismatch: calculated ${calculatedRoot}, expected ${expectedRoot}`);
|
|
39646
39456
|
return wasmPath;
|
|
39647
39457
|
}
|
|
39648
39458
|
const toProveInput = ({ merkleTree, publicAmount, extDataHash, nullifier0, nullifier1, commitment0, commitment1, vortexKeypair, inputUtxo0, inputUtxo1, outputUtxo0, outputUtxo1, }) => {
|
|
39649
39459
|
return {
|
|
39650
|
-
root: merkleTree.root
|
|
39460
|
+
root: BigInt(merkleTree.root),
|
|
39651
39461
|
publicAmount,
|
|
39652
39462
|
extDataHash,
|
|
39653
39463
|
inputNullifier0: nullifier0,
|
|
@@ -39759,7 +39569,7 @@ const deposit = async ({ tx = new Transaction(), amount, unspentUtxos = [], vort
|
|
|
39759
39569
|
const { proof: moveProof, tx: tx3 } = vortex.newProof({
|
|
39760
39570
|
tx: tx2,
|
|
39761
39571
|
proofPoints: fromHex('0x' + proof.proofSerializedHex),
|
|
39762
|
-
root: merkleTree.root
|
|
39572
|
+
root: BigInt(merkleTree.root),
|
|
39763
39573
|
publicValue: amountMinusFrontendFee,
|
|
39764
39574
|
action: Action.Deposit,
|
|
39765
39575
|
extDataHash: extDataHashBigInt,
|
|
@@ -39860,7 +39670,7 @@ const withdraw = async ({ tx = new Transaction(), amount, unspentUtxos = [], vor
|
|
|
39860
39670
|
const { proof: moveProof, tx: tx3 } = vortex.newProof({
|
|
39861
39671
|
tx: tx2,
|
|
39862
39672
|
proofPoints: fromHex('0x' + proof.proofSerializedHex),
|
|
39863
|
-
root: merkleTree.root
|
|
39673
|
+
root: BigInt(merkleTree.root),
|
|
39864
39674
|
publicValue: amount + relayerFee,
|
|
39865
39675
|
action: Action.Withdraw,
|
|
39866
39676
|
extDataHash: extDataHashBigInt,
|
|
@@ -39879,5 +39689,5 @@ const withdraw = async ({ tx = new Transaction(), amount, unspentUtxos = [], vor
|
|
|
39879
39689
|
return tx4;
|
|
39880
39690
|
};
|
|
39881
39691
|
|
|
39882
|
-
export { Action, BASIS_POINTS, BN254_FIELD_MODULUS, DEPOSIT_FEE_IN_BASIS_POINTS, EMPTY_COMMITMENT, EMPTY_SUBTREE_HASHES, ERROR_CODES, INITIAL_SHARED_VERSION, LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, MERKLE_TREE_HEIGHT,
|
|
39692
|
+
export { Action, BASIS_POINTS, BN254_FIELD_MODULUS, DEPOSIT_FEE_IN_BASIS_POINTS, EMPTY_COMMITMENT, EMPTY_SUBTREE_HASHES, ERROR_CODES, INITIAL_SHARED_VERSION, LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, MERKLE_TREE_HEIGHT, Modules, OPT, Output, REGISTRY_OBJECT_ID, ROOT_HISTORY_SIZE, TREASURY_ADDRESS, UPGRADE_CAP, Utxo, VORTEX_PACKAGE_ID, VORTEX_POOL_OBJECT_ID, VORTEX_SIGNATURE_DOMAIN, Vortex, VortexKeypair, ZERO_VALUE, buildMerkleTree, bytesToBigInt, computeExtDataHash, deposit, getMerklePath, getUnspentUtxos, parseNewCommitmentEvent, poseidon1, poseidon2, poseidon3, prove, reverseBytes, toProveInput, verify, vortexSDK, withdraw };
|
|
39883
39693
|
//# sourceMappingURL=index.mjs.map
|