@interest-protocol/vortex-sdk 0.0.1-alpha.0 → 1.0.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.
- package/.eslingignore +1 -0
- package/dist/__tests__/entities/keypair.spec.d.ts +2 -0
- package/dist/__tests__/entities/keypair.spec.d.ts.map +1 -0
- package/dist/__tests__/test-utils.d.ts +25 -0
- package/dist/__tests__/test-utils.d.ts.map +1 -0
- package/dist/__tests__/types.d.ts +3 -0
- package/dist/__tests__/types.d.ts.map +1 -0
- package/dist/__tests__/vortex.test.d.ts +2 -0
- package/dist/__tests__/vortex.test.d.ts.map +1 -0
- package/dist/constants.d.ts +44 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/crypto/ff/f1field.d.ts +76 -0
- package/dist/crypto/ff/f1field.d.ts.map +1 -0
- package/dist/crypto/ff/index.d.ts +6 -0
- package/dist/crypto/ff/index.d.ts.map +1 -0
- package/dist/crypto/ff/random.d.ts +2 -0
- package/dist/crypto/ff/random.d.ts.map +1 -0
- package/dist/crypto/ff/scalar.d.ts +45 -0
- package/dist/crypto/ff/scalar.d.ts.map +1 -0
- package/dist/crypto/ff/utils.d.ts +6 -0
- package/dist/crypto/ff/utils.d.ts.map +1 -0
- package/dist/crypto/index.d.ts +6 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/poseidon/index.d.ts +2 -0
- package/dist/crypto/poseidon/index.d.ts.map +1 -0
- package/dist/crypto/poseidon/poseidon-constants-opt.d.ts +7 -0
- package/dist/crypto/poseidon/poseidon-constants-opt.d.ts.map +1 -0
- package/dist/crypto/poseidon/poseidon-opt.d.ts +16 -0
- package/dist/crypto/poseidon/poseidon-opt.d.ts.map +1 -0
- package/dist/deposit.d.ts +4 -0
- package/dist/deposit.d.ts.map +1 -0
- package/dist/entities/index.d.ts +4 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/keypair.d.ts +29 -0
- package/dist/entities/keypair.d.ts.map +1 -0
- package/dist/entities/merkle-tree.d.ts +81 -0
- package/dist/entities/merkle-tree.d.ts.map +1 -0
- package/dist/entities/utxo.d.ts +24 -0
- package/dist/entities/utxo.d.ts.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38280 -4459
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +38244 -4453
- package/dist/index.mjs.map +1 -1
- package/dist/jest-setup.d.ts +2 -0
- package/dist/jest-setup.d.ts.map +1 -0
- package/dist/keys/index.d.ts +3 -0
- package/dist/keys/index.d.ts.map +1 -0
- package/dist/pkg/nodejs/vortex.d.ts +11 -0
- package/dist/pkg/nodejs/vortex.d.ts.map +1 -0
- package/dist/pkg/web/vortex.d.ts +44 -0
- package/dist/pkg/web/vortex.d.ts.map +1 -0
- package/dist/utils/decrypt.d.ts +12 -0
- package/dist/utils/decrypt.d.ts.map +1 -0
- package/dist/utils/env.d.ts +2 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/events.d.ts +7 -0
- package/dist/utils/events.d.ts.map +1 -0
- package/dist/utils/ext-data.d.ts +3 -0
- package/dist/utils/ext-data.d.ts.map +1 -0
- package/dist/utils/index.d.ts +50 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/prove.d.ts +3 -0
- package/dist/utils/prove.d.ts.map +1 -0
- package/dist/vortex.d.ts +51 -21
- package/dist/vortex.d.ts.map +1 -1
- package/dist/vortex.types.d.ts +74 -50
- package/dist/vortex.types.d.ts.map +1 -1
- package/dist/vortex_bg.wasm +0 -0
- package/dist/withdraw.d.ts +4 -0
- package/dist/withdraw.d.ts.map +1 -0
- package/jest.config.js +31 -0
- package/package.json +20 -5
- package/src/__tests__/entities/keypair.spec.ts +191 -0
- package/src/__tests__/test-utils.ts +76 -0
- package/src/__tests__/types.ts +3 -0
- package/src/__tests__/vortex.test.ts +25 -0
- package/src/constants.ts +104 -0
- package/src/crypto/ff/f1field.ts +464 -0
- package/src/crypto/ff/index.ts +6 -0
- package/src/crypto/ff/random.ts +32 -0
- package/src/crypto/ff/readme.md +8 -0
- package/src/crypto/ff/scalar.ts +264 -0
- package/src/crypto/ff/utils.ts +121 -0
- package/src/crypto/index.ts +8 -0
- package/src/crypto/poseidon/index.ts +1 -0
- package/src/crypto/poseidon/poseidon-constants-opt.ts +24806 -0
- package/src/crypto/poseidon/poseidon-opt.ts +184 -0
- package/src/deposit.ts +168 -0
- package/src/entities/index.ts +3 -0
- package/src/entities/keypair.ts +262 -0
- package/src/entities/merkle-tree.ts +256 -0
- package/src/entities/utxo.ts +52 -0
- package/src/index.ts +6 -2
- package/src/jest-setup.ts +2 -0
- package/src/keys/index.ts +5 -0
- package/src/pkg/nodejs/vortex.d.ts +36 -0
- package/src/pkg/nodejs/vortex.js +332 -0
- package/src/pkg/nodejs/vortex_bg.wasm +0 -0
- package/src/pkg/nodejs/vortex_bg.wasm.d.ts +12 -0
- package/src/pkg/web/vortex.d.ts +72 -0
- package/src/pkg/web/vortex.js +442 -0
- package/src/pkg/web/vortex_bg.wasm +0 -0
- package/src/pkg/web/vortex_bg.wasm.d.ts +12 -0
- package/src/utils/decrypt.ts +46 -0
- package/src/utils/env.ts +18 -0
- package/src/utils/events.ts +16 -0
- package/src/utils/ext-data.ts +43 -0
- package/src/utils/index.ts +152 -0
- package/src/utils/prove.ts +18 -0
- package/src/vortex.ts +235 -111
- package/src/vortex.types.ts +74 -54
- package/src/withdraw.ts +159 -0
- package/tsconfig.json +4 -2
- package/dist/admin.d.ts +0 -17
- package/dist/admin.d.ts.map +0 -1
- package/dist/utils.d.ts +0 -11
- package/dist/utils.d.ts.map +0 -1
- package/src/admin.ts +0 -124
- package/src/utils.ts +0 -66
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { toHex } from '@mysten/sui/utils';
|
|
2
|
+
import invariant from 'tiny-invariant';
|
|
3
|
+
import { MerkleTree } from '../entities/merkle-tree';
|
|
4
|
+
import { Utxo } from '../entities/utxo';
|
|
5
|
+
import { VortexKeypair } from '../entities/keypair';
|
|
6
|
+
import { ZERO_VALUE, MERKLE_TREE_HEIGHT } from '../constants';
|
|
7
|
+
import { poseidon2 } from '../crypto';
|
|
8
|
+
|
|
9
|
+
export const reverseBytes = (bytes: Uint8Array): Uint8Array => {
|
|
10
|
+
const reversed = new Uint8Array(bytes.length);
|
|
11
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
12
|
+
reversed[i] = bytes[bytes.length - 1 - i]!;
|
|
13
|
+
}
|
|
14
|
+
return reversed;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const bytesToBigInt = (bytes: Uint8Array): bigint => {
|
|
18
|
+
return BigInt('0x' + toHex(bytes));
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export function getMerklePath(
|
|
22
|
+
merkleTree: MerkleTree,
|
|
23
|
+
utxo: Utxo | null
|
|
24
|
+
): [string, string][] {
|
|
25
|
+
// Handle zero-amount UTXOs
|
|
26
|
+
if (!utxo || utxo.amount === 0n) {
|
|
27
|
+
return Array(MERKLE_TREE_HEIGHT)
|
|
28
|
+
.fill(null)
|
|
29
|
+
.map(() => [ZERO_VALUE.toString(), ZERO_VALUE.toString()]);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const utxoIndex = Number(utxo.index);
|
|
33
|
+
const treeSize = merkleTree.elements().length;
|
|
34
|
+
|
|
35
|
+
// For deposits, input UTXOs don't exist yet
|
|
36
|
+
if (utxoIndex < 0 || utxoIndex >= treeSize) {
|
|
37
|
+
return Array(MERKLE_TREE_HEIGHT)
|
|
38
|
+
.fill(null)
|
|
39
|
+
.map(() => [ZERO_VALUE.toString(), ZERO_VALUE.toString()]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Get Merkle path
|
|
43
|
+
const { pathElements, pathIndices } = merkleTree.path(utxoIndex);
|
|
44
|
+
const commitment = utxo.commitment();
|
|
45
|
+
|
|
46
|
+
// Verify commitment matches what's in the tree
|
|
47
|
+
const storedCommitment = merkleTree.elements()[utxoIndex]!;
|
|
48
|
+
|
|
49
|
+
invariant(
|
|
50
|
+
storedCommitment === commitment,
|
|
51
|
+
`Commitment mismatch at index ${utxoIndex}: expected ${commitment}, got ${storedCommitment}`
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
// Build WASM-compatible path (always [left, right] format)
|
|
55
|
+
const wasmPath: [string, string][] = [];
|
|
56
|
+
let currentHash = commitment;
|
|
57
|
+
|
|
58
|
+
for (let i = 0; i < MERKLE_TREE_HEIGHT; i++) {
|
|
59
|
+
const sibling = pathElements[i];
|
|
60
|
+
const isLeft = pathIndices[i] === 0;
|
|
61
|
+
|
|
62
|
+
invariant(sibling !== undefined, `Sibling undefined at level ${i}`);
|
|
63
|
+
|
|
64
|
+
const leftHash = isLeft ? currentHash : sibling;
|
|
65
|
+
const rightHash = isLeft ? sibling : currentHash;
|
|
66
|
+
|
|
67
|
+
// Verify current hash appears in the pair (critical Rust check)
|
|
68
|
+
if (currentHash !== leftHash && currentHash !== rightHash) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Invalid path at level ${i}: current hash must be either left or right`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
wasmPath.push([leftHash.toString(), rightHash.toString()]);
|
|
75
|
+
|
|
76
|
+
const nextHash = poseidon2(leftHash, rightHash);
|
|
77
|
+
|
|
78
|
+
currentHash = nextHash;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const calculatedRoot = currentHash;
|
|
82
|
+
const expectedRoot = merkleTree.root();
|
|
83
|
+
|
|
84
|
+
invariant(
|
|
85
|
+
calculatedRoot === expectedRoot,
|
|
86
|
+
`Root mismatch: calculated ${calculatedRoot}, expected ${expectedRoot}`
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
return wasmPath;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface ToProveInputArgs {
|
|
93
|
+
merkleTree: MerkleTree;
|
|
94
|
+
publicAmount: bigint;
|
|
95
|
+
extDataHash: bigint;
|
|
96
|
+
nullifier0: bigint;
|
|
97
|
+
nullifier1: bigint;
|
|
98
|
+
commitment0: bigint;
|
|
99
|
+
commitment1: bigint;
|
|
100
|
+
vortexKeypair: VortexKeypair;
|
|
101
|
+
inputUtxo0: Utxo;
|
|
102
|
+
inputUtxo1: Utxo;
|
|
103
|
+
outputUtxo0: Utxo;
|
|
104
|
+
outputUtxo1: Utxo;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const toProveInput = ({
|
|
108
|
+
merkleTree,
|
|
109
|
+
publicAmount,
|
|
110
|
+
extDataHash,
|
|
111
|
+
nullifier0,
|
|
112
|
+
nullifier1,
|
|
113
|
+
commitment0,
|
|
114
|
+
commitment1,
|
|
115
|
+
vortexKeypair,
|
|
116
|
+
inputUtxo0,
|
|
117
|
+
inputUtxo1,
|
|
118
|
+
outputUtxo0,
|
|
119
|
+
outputUtxo1,
|
|
120
|
+
}: ToProveInputArgs) => {
|
|
121
|
+
return {
|
|
122
|
+
root: merkleTree.root(),
|
|
123
|
+
publicAmount,
|
|
124
|
+
extDataHash,
|
|
125
|
+
inputNullifier0: nullifier0,
|
|
126
|
+
inputNullifier1: nullifier1,
|
|
127
|
+
outputCommitment0: commitment0,
|
|
128
|
+
outputCommitment1: commitment1,
|
|
129
|
+
inPrivateKey0: vortexKeypair.privateKey,
|
|
130
|
+
inPrivateKey1: vortexKeypair.privateKey,
|
|
131
|
+
inAmount0: inputUtxo0.amount,
|
|
132
|
+
inAmount1: inputUtxo1.amount,
|
|
133
|
+
inBlinding0: inputUtxo0.blinding,
|
|
134
|
+
inBlinding1: inputUtxo1.blinding,
|
|
135
|
+
inPathIndex0: inputUtxo0.index,
|
|
136
|
+
inPathIndex1: inputUtxo1.index,
|
|
137
|
+
merklePath0: getMerklePath(merkleTree, inputUtxo0),
|
|
138
|
+
merklePath1: getMerklePath(merkleTree, inputUtxo1),
|
|
139
|
+
|
|
140
|
+
outPublicKey0: vortexKeypair.publicKey,
|
|
141
|
+
outPublicKey1: vortexKeypair.publicKey,
|
|
142
|
+
outAmount0: outputUtxo0.amount,
|
|
143
|
+
outAmount1: outputUtxo1.amount,
|
|
144
|
+
outBlinding0: outputUtxo0.blinding,
|
|
145
|
+
outBlinding1: outputUtxo1.blinding,
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export * from './ext-data';
|
|
150
|
+
export * from './events';
|
|
151
|
+
export * from './prove';
|
|
152
|
+
export * from './decrypt';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { prove as proveNode, verify as verifyNode } from '../pkg/nodejs/vortex';
|
|
2
|
+
import { prove as proveWeb, verify as verifyWeb } from '../pkg/web/vortex';
|
|
3
|
+
import { getEnv } from './env';
|
|
4
|
+
import { VERIFYING_KEY, PROVING_KEY } from '../keys';
|
|
5
|
+
|
|
6
|
+
export const prove = (input: string) => {
|
|
7
|
+
const env = getEnv();
|
|
8
|
+
if (env === 'node') return proveNode(input, PROVING_KEY);
|
|
9
|
+
if (env === 'web') return proveWeb(input, PROVING_KEY);
|
|
10
|
+
throw new Error('Unsupported environment');
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const verify = (proof: string) => {
|
|
14
|
+
const env = getEnv();
|
|
15
|
+
if (env === 'node') return verifyNode(proof, VERIFYING_KEY);
|
|
16
|
+
if (env === 'web') return verifyWeb(proof, VERIFYING_KEY);
|
|
17
|
+
throw new Error('Unsupported environment');
|
|
18
|
+
};
|
package/src/vortex.ts
CHANGED
|
@@ -1,162 +1,286 @@
|
|
|
1
|
+
import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
|
|
2
|
+
import { Transaction } from '@mysten/sui/transactions';
|
|
1
3
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
ConstructorArgs,
|
|
5
|
+
RegisterArgs,
|
|
6
|
+
SharedObjectData,
|
|
7
|
+
NewExtDataArgs,
|
|
8
|
+
Action,
|
|
9
|
+
NewProofArgs,
|
|
10
|
+
TransactArgs,
|
|
8
11
|
} from './vortex.types';
|
|
9
|
-
import { SuiClient } from '@mysten/sui/client';
|
|
10
|
-
import {
|
|
11
|
-
generateRandomNote,
|
|
12
|
-
zeros,
|
|
13
|
-
BN254_FIELD_MODULUS,
|
|
14
|
-
addressToFieldElement,
|
|
15
|
-
bigIntToFieldElement,
|
|
16
|
-
} from './utils';
|
|
17
|
-
import { poseidon2, poseidon1 } from 'poseidon-lite';
|
|
18
12
|
import { devInspectAndGetReturnValues } from '@polymedia/suitcase-core';
|
|
19
|
-
import { Transaction, coinWithBalance } from '@mysten/sui/transactions';
|
|
20
|
-
import { fromHex, SUI_TYPE_ARG } from '@mysten/sui/utils';
|
|
21
13
|
import { bcs } from '@mysten/sui/bcs';
|
|
22
14
|
import invariant from 'tiny-invariant';
|
|
15
|
+
import { pathOr } from 'ramda';
|
|
16
|
+
import {
|
|
17
|
+
BN254_FIELD_MODULUS,
|
|
18
|
+
VORTEX_PACKAGE_ID,
|
|
19
|
+
REGISTRY_OBJECT_ID,
|
|
20
|
+
INITIAL_SHARED_VERSION,
|
|
21
|
+
VORTEX_POOL_OBJECT_ID,
|
|
22
|
+
} from './constants';
|
|
23
23
|
|
|
24
|
-
export class
|
|
25
|
-
|
|
26
|
-
private packageId: string;
|
|
27
|
-
private pools: VortexPools;
|
|
24
|
+
export class Vortex {
|
|
25
|
+
#suiClient: SuiClient;
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
packageId: string;
|
|
28
|
+
registry: SharedObjectData;
|
|
29
|
+
vortex: SharedObjectData;
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.pools = args.pools;
|
|
36
|
-
}
|
|
31
|
+
newCommitmentEventType: string;
|
|
32
|
+
nullifierSpentEventType: string;
|
|
33
|
+
newEncryptionKeyEventType: string;
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
constructor({
|
|
36
|
+
registry,
|
|
37
|
+
packageId,
|
|
38
|
+
vortex,
|
|
39
|
+
fullNodeUrl = getFullnodeUrl('devnet'),
|
|
40
|
+
}: ConstructorArgs) {
|
|
41
|
+
this.#suiClient = new SuiClient({
|
|
42
|
+
url: fullNodeUrl,
|
|
43
|
+
});
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
this.newCommitmentEventType = `${packageId}::vortex::NewCommitment`;
|
|
46
|
+
this.nullifierSpentEventType = `${packageId}::vortex::NullifierSpent`;
|
|
47
|
+
this.newEncryptionKeyEventType = `${packageId}::vortex::NewEncryptionKey`;
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
this.packageId = packageId;
|
|
50
|
+
this.registry = registry;
|
|
51
|
+
this.vortex = vortex;
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return bigIntToFieldElement(value);
|
|
56
|
-
}
|
|
54
|
+
register({ tx = new Transaction(), encryptionKey }: RegisterArgs) {
|
|
55
|
+
tx.moveCall({
|
|
56
|
+
target: `${this.packageId}::vortex::register`,
|
|
57
|
+
arguments: [this.mutableRegistryRef(tx), tx.pure.string(encryptionKey)],
|
|
58
|
+
});
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
return zeros(this.TREE_HEIGHT);
|
|
60
|
+
return { tx };
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
const suiCoin = coinWithBalance({
|
|
66
|
-
type: SUI_TYPE_ARG,
|
|
67
|
-
balance: pool,
|
|
68
|
-
})(tx);
|
|
63
|
+
async encryptionKey(user: string) {
|
|
64
|
+
const tx = new Transaction();
|
|
69
65
|
|
|
70
66
|
tx.moveCall({
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
function: 'deposit',
|
|
74
|
-
arguments: [
|
|
75
|
-
tx.sharedObjectRef({
|
|
76
|
-
objectId: poolObject.objectId,
|
|
77
|
-
mutable: true,
|
|
78
|
-
initialSharedVersion: poolObject.initialSharedVersion,
|
|
79
|
-
}),
|
|
80
|
-
suiCoin,
|
|
81
|
-
tx.pure.u256(commitment),
|
|
82
|
-
],
|
|
67
|
+
target: `${this.packageId}::vortex::encryption_key`,
|
|
68
|
+
arguments: [this.immutableRegistryRef(tx), tx.pure.address(user)],
|
|
83
69
|
});
|
|
84
70
|
|
|
85
|
-
|
|
71
|
+
const result = await devInspectAndGetReturnValues(this.#suiClient, tx, [
|
|
72
|
+
[bcs.String],
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
invariant(result[0], 'Encryption key devInspectAndGetReturnValues failed');
|
|
76
|
+
|
|
77
|
+
return result[0][0] as string;
|
|
86
78
|
}
|
|
87
79
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
root,
|
|
91
|
-
nullifier,
|
|
80
|
+
newExtData({
|
|
81
|
+
tx = new Transaction(),
|
|
92
82
|
recipient,
|
|
83
|
+
value,
|
|
84
|
+
action,
|
|
93
85
|
relayer,
|
|
94
86
|
relayerFee,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}:
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
const proof = tx.moveCall({
|
|
101
|
-
package: this.packageId,
|
|
102
|
-
module: Modules.proof,
|
|
103
|
-
function: 'new',
|
|
87
|
+
encryptedOutput1,
|
|
88
|
+
encryptedOutput0,
|
|
89
|
+
}: NewExtDataArgs) {
|
|
90
|
+
const extData = tx.moveCall({
|
|
91
|
+
target: `${this.packageId}::vortex_ext_data::new`,
|
|
104
92
|
arguments: [
|
|
105
|
-
tx.pure.vector('u8', fromHex(proofPointsHex)),
|
|
106
|
-
tx.pure.vector('u8', []),
|
|
107
|
-
tx.pure.vector('u8', []),
|
|
108
|
-
tx.pure.u256(root),
|
|
109
|
-
tx.pure.u256(nullifier),
|
|
110
93
|
tx.pure.address(recipient),
|
|
111
|
-
tx.pure.u64(
|
|
94
|
+
tx.pure.u64(value),
|
|
95
|
+
tx.pure.bool(action === Action.Deposit), // true for deposit, false for withdraw
|
|
112
96
|
tx.pure.address(relayer),
|
|
113
97
|
tx.pure.u64(relayerFee),
|
|
98
|
+
tx.pure.vector('u8', encryptedOutput0),
|
|
99
|
+
tx.pure.vector('u8', encryptedOutput1),
|
|
114
100
|
],
|
|
115
101
|
});
|
|
116
102
|
|
|
117
|
-
tx
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
103
|
+
return { tx, extData };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
newProof({
|
|
107
|
+
tx = new Transaction(),
|
|
108
|
+
proofPoints,
|
|
109
|
+
root,
|
|
110
|
+
publicValue,
|
|
111
|
+
action,
|
|
112
|
+
extDataHash,
|
|
113
|
+
inputNullifier0,
|
|
114
|
+
inputNullifier1,
|
|
115
|
+
outputCommitment0,
|
|
116
|
+
outputCommitment1,
|
|
117
|
+
}: NewProofArgs) {
|
|
118
|
+
const value =
|
|
119
|
+
action === Action.Deposit
|
|
120
|
+
? publicValue
|
|
121
|
+
: BN254_FIELD_MODULUS - publicValue;
|
|
122
|
+
|
|
123
|
+
const proof = tx.moveCall({
|
|
124
|
+
target: `${this.packageId}::vortex_proof::new`,
|
|
121
125
|
arguments: [
|
|
122
|
-
tx.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
tx.pure.vector('u8', proofPoints),
|
|
127
|
+
tx.pure.u256(root),
|
|
128
|
+
tx.pure.u256(value),
|
|
129
|
+
tx.pure.u256(extDataHash),
|
|
130
|
+
tx.pure.u256(inputNullifier0),
|
|
131
|
+
tx.pure.u256(inputNullifier1),
|
|
132
|
+
tx.pure.u256(outputCommitment0),
|
|
133
|
+
tx.pure.u256(outputCommitment1),
|
|
128
134
|
],
|
|
129
135
|
});
|
|
130
136
|
|
|
131
|
-
return tx;
|
|
137
|
+
return { tx, proof };
|
|
132
138
|
}
|
|
133
139
|
|
|
134
|
-
|
|
135
|
-
|
|
140
|
+
transact({ tx = new Transaction(), proof, extData, deposit }: TransactArgs) {
|
|
141
|
+
tx.moveCall({
|
|
142
|
+
target: `${this.packageId}::vortex::transact`,
|
|
143
|
+
arguments: [this.mutableVortexRef(tx), proof, extData, deposit],
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
return { tx };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async tvl() {
|
|
150
|
+
const object = await this.#suiClient.getObject({
|
|
151
|
+
id: this.vortex.objectId,
|
|
152
|
+
options: {
|
|
153
|
+
showContent: true,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
invariant(object.data, 'Vortex object data not found');
|
|
158
|
+
|
|
159
|
+
const content = object.data.content;
|
|
160
|
+
|
|
161
|
+
return BigInt(pathOr(0, ['fields', 'balance'], content));
|
|
162
|
+
}
|
|
136
163
|
|
|
137
|
-
|
|
164
|
+
async root() {
|
|
165
|
+
const tx = new Transaction();
|
|
138
166
|
|
|
139
167
|
tx.moveCall({
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
function: 'root',
|
|
143
|
-
arguments: [
|
|
144
|
-
tx.sharedObjectRef({
|
|
145
|
-
objectId: poolObject.objectId,
|
|
146
|
-
mutable: false,
|
|
147
|
-
initialSharedVersion: poolObject.initialSharedVersion,
|
|
148
|
-
}),
|
|
149
|
-
],
|
|
168
|
+
target: `${this.packageId}::vortex::root`,
|
|
169
|
+
arguments: [this.immutableVortexRef(tx)],
|
|
150
170
|
});
|
|
151
171
|
|
|
152
|
-
const result = await devInspectAndGetReturnValues(this
|
|
172
|
+
const result = await devInspectAndGetReturnValues(this.#suiClient, tx, [
|
|
153
173
|
[bcs.u256()],
|
|
154
174
|
]);
|
|
155
175
|
|
|
156
176
|
invariant(result[0], 'Root devInspectAndGetReturnValues failed');
|
|
157
177
|
|
|
158
|
-
|
|
178
|
+
return BigInt(result[0][0] as string);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async nextIndex() {
|
|
182
|
+
const tx = new Transaction();
|
|
183
|
+
|
|
184
|
+
tx.moveCall({
|
|
185
|
+
target: `${this.packageId}::vortex::next_index`,
|
|
186
|
+
arguments: [this.immutableVortexRef(tx)],
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const result = await devInspectAndGetReturnValues(this.#suiClient, tx, [
|
|
190
|
+
[bcs.u64()],
|
|
191
|
+
]);
|
|
192
|
+
|
|
193
|
+
invariant(result[0], 'Next index devInspectAndGetReturnValues failed');
|
|
194
|
+
|
|
195
|
+
return BigInt(result[0][0] as string);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async isNullifierSpent(nullifier: bigint) {
|
|
199
|
+
const tx = new Transaction();
|
|
200
|
+
|
|
201
|
+
tx.moveCall({
|
|
202
|
+
target: `${this.packageId}::vortex::is_nullifier_spent`,
|
|
203
|
+
arguments: [this.immutableVortexRef(tx), tx.pure.u256(nullifier)],
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const result = await devInspectAndGetReturnValues(this.#suiClient, tx, [
|
|
207
|
+
[bcs.Bool],
|
|
208
|
+
]);
|
|
209
|
+
|
|
210
|
+
invariant(
|
|
211
|
+
result[0],
|
|
212
|
+
'Is nullifier spent devInspectAndGetReturnValues failed'
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
return result[0][0] as boolean;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async areNullifiersSpent(nullifiers: bigint[]) {
|
|
219
|
+
const tx = new Transaction();
|
|
220
|
+
|
|
221
|
+
nullifiers.forEach((nullifier) => {
|
|
222
|
+
tx.moveCall({
|
|
223
|
+
target: `${this.packageId}::vortex::is_nullifier_spent`,
|
|
224
|
+
arguments: [this.immutableVortexRef(tx), tx.pure.u256(nullifier)],
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const result = await devInspectAndGetReturnValues(
|
|
229
|
+
this.#suiClient,
|
|
230
|
+
tx,
|
|
231
|
+
nullifiers.map(() => [bcs.Bool])
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
invariant(
|
|
235
|
+
result[0],
|
|
236
|
+
'Is nullifier spent devInspectAndGetReturnValues failed'
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
return result.flat() as boolean[];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
immutableVortexRef(tx: Transaction) {
|
|
243
|
+
return tx.sharedObjectRef({
|
|
244
|
+
objectId: this.vortex.objectId,
|
|
245
|
+
initialSharedVersion: this.vortex.initialSharedVersion,
|
|
246
|
+
mutable: false,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
159
249
|
|
|
160
|
-
|
|
250
|
+
immutableRegistryRef(tx: Transaction) {
|
|
251
|
+
return tx.sharedObjectRef({
|
|
252
|
+
objectId: this.registry.objectId,
|
|
253
|
+
initialSharedVersion: this.registry.initialSharedVersion,
|
|
254
|
+
mutable: false,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
mutableVortexRef(tx: Transaction) {
|
|
259
|
+
return tx.sharedObjectRef({
|
|
260
|
+
objectId: this.vortex.objectId,
|
|
261
|
+
initialSharedVersion: this.vortex.initialSharedVersion,
|
|
262
|
+
mutable: true,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
mutableRegistryRef(tx: Transaction) {
|
|
267
|
+
return tx.sharedObjectRef({
|
|
268
|
+
objectId: this.registry.objectId,
|
|
269
|
+
initialSharedVersion: this.registry.initialSharedVersion,
|
|
270
|
+
mutable: true,
|
|
271
|
+
});
|
|
161
272
|
}
|
|
162
273
|
}
|
|
274
|
+
|
|
275
|
+
export const vortexSDK = new Vortex({
|
|
276
|
+
packageId: VORTEX_PACKAGE_ID,
|
|
277
|
+
registry: {
|
|
278
|
+
objectId: REGISTRY_OBJECT_ID,
|
|
279
|
+
initialSharedVersion: INITIAL_SHARED_VERSION,
|
|
280
|
+
},
|
|
281
|
+
vortex: {
|
|
282
|
+
objectId: VORTEX_POOL_OBJECT_ID,
|
|
283
|
+
initialSharedVersion: INITIAL_SHARED_VERSION,
|
|
284
|
+
},
|
|
285
|
+
fullNodeUrl: getFullnodeUrl('devnet'),
|
|
286
|
+
});
|