@smithii_io/mixoor 0.0.1 → 0.0.3
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/test/_constants.js +17 -0
- package/dist/test/_constants.js.map +1 -0
- package/dist/test/_create.test.js +37 -0
- package/dist/test/_create.test.js.map +1 -0
- package/dist/test/_deposit.test.js +62 -0
- package/dist/test/_deposit.test.js.map +1 -0
- package/dist/test/_helpers.js +15 -0
- package/dist/test/_helpers.js.map +1 -0
- package/dist/test/_setup.js +197 -0
- package/dist/test/_setup.js.map +1 -0
- package/dist/test/transfer.test.js +97 -0
- package/dist/test/transfer.test.js.map +1 -0
- package/package.json +4 -5
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var kit = require('@solana/kit');
|
|
4
|
+
|
|
5
|
+
const WRAPPED_SOL_MINT_TOKEN_PROGRAM = kit.address(
|
|
6
|
+
"So11111111111111111111111111111111111111112"
|
|
7
|
+
);
|
|
8
|
+
const FEE_COLLECTOR_ADDRESS = kit.address(
|
|
9
|
+
"4kg8oh3jdNtn7j2wcS7TrUua31AgbLzDVkBZgTAe44aF"
|
|
10
|
+
);
|
|
11
|
+
const LAMPORTS_PER_SOL = BigInt(1e9);
|
|
12
|
+
|
|
13
|
+
exports.FEE_COLLECTOR_ADDRESS = FEE_COLLECTOR_ADDRESS;
|
|
14
|
+
exports.LAMPORTS_PER_SOL = LAMPORTS_PER_SOL;
|
|
15
|
+
exports.WRAPPED_SOL_MINT_TOKEN_PROGRAM = WRAPPED_SOL_MINT_TOKEN_PROGRAM;
|
|
16
|
+
//# sourceMappingURL=_constants.js.map
|
|
17
|
+
//# sourceMappingURL=_constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../test/_constants.ts"],"names":["address"],"mappings":";;;;AAEO,MAAM,8BAAA,GAAiCA,WAAA;AAAA,EAC5C;AACF;AAEO,MAAM,qBAAA,GAAwBA,WAAA;AAAA,EACnC;AACF;AAEO,MAAM,gBAAA,GAAmB,OAAO,GAAa","file":"_constants.js","sourcesContent":["import { address } from '@solana/kit';\n\nexport const WRAPPED_SOL_MINT_TOKEN_PROGRAM = address(\n 'So11111111111111111111111111111111111111112'\n);\n\nexport const FEE_COLLECTOR_ADDRESS = address(\n '4kg8oh3jdNtn7j2wcS7TrUua31AgbLzDVkBZgTAe44aF'\n);\n\nexport const LAMPORTS_PER_SOL = BigInt(1_000_000_000); // one billions\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var test = require('ava');
|
|
4
|
+
var src = require('../src');
|
|
5
|
+
var _constants = require('./_constants');
|
|
6
|
+
var _setup = require('./_setup');
|
|
7
|
+
|
|
8
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
|
|
10
|
+
var test__default = /*#__PURE__*/_interopDefault(test);
|
|
11
|
+
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
14
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
15
|
+
};
|
|
16
|
+
var require_create_test = __commonJS({
|
|
17
|
+
"test/_create.test.ts"() {
|
|
18
|
+
test__default.default("it creates a new SOL pool account", async (t) => {
|
|
19
|
+
const client = _setup.createDefaultSolanaClient();
|
|
20
|
+
const { authority } = await _setup.createSolPoolForAuthority(client);
|
|
21
|
+
const [pool] = await src.findPoolAddress({
|
|
22
|
+
mint: _constants.WRAPPED_SOL_ADDRESS_TOKEN_PROGRAM
|
|
23
|
+
});
|
|
24
|
+
t.like(await src.fetchPool(client.rpc, pool), {
|
|
25
|
+
data: {
|
|
26
|
+
authority
|
|
27
|
+
// todo add missing fields later
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
var _create_test = require_create_test();
|
|
34
|
+
|
|
35
|
+
module.exports = _create_test;
|
|
36
|
+
//# sourceMappingURL=_create.test.js.map
|
|
37
|
+
//# sourceMappingURL=_create.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../test/_create.test.ts"],"names":["test","createDefaultSolanaClient","createSolPoolForAuthority","findPoolAddress","WRAPPED_SOL_ADDRESS_TOKEN_PROGRAM","fetchPool"],"mappings":";;;;;;;;;;;;;;;AAAA,IAAA,mBAAA,GAAA,UAAA,CAAA;AAAA,EAAA,sBAAA,GAAA;AAMA,IAAAA,qBAAA,CAAK,mCAAA,EAAqC,OAAO,CAAA,KAAM;AACrD,MAAA,MAAM,SAASC,gCAAA,EAA0B;AAGzC,MAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAMC,iCAA0B,MAAM,CAAA;AAG5D,MAAA,MAAM,CAAC,IAAI,CAAA,GAAI,MAAMC,mBAAA,CAAgB;AAAA,QACnC,IAAA,EAAMC;AAAA,OACP,CAAA;AAED,MAAA,CAAA,CAAE,KAAK,MAAMC,aAAA,CAAU,MAAA,CAAO,GAAA,EAAK,IAAI,CAAA,EAAkB;AAAA,QACvD,IAAA,EAAM;AAAA,UACJ;AAAA;AAAA;AAEF,OACD,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EAAA;AAAA,CAAA,CAAA","file":"_create.test.js","sourcesContent":["import { Account } from '@solana/web3.js';\nimport test from 'ava';\nimport { fetchPool, findPoolAddress, Pool } from '../src';\nimport { WRAPPED_SOL_ADDRESS_TOKEN_PROGRAM } from './_constants';\nimport { createDefaultSolanaClient, createSolPoolForAuthority } from './_setup';\n\ntest('it creates a new SOL pool account', async (t) => {\n const client = createDefaultSolanaClient();\n\n\n const { authority } = await createSolPoolForAuthority(client);\n\n // find pool address\n const [pool] = await findPoolAddress({\n mint: WRAPPED_SOL_ADDRESS_TOKEN_PROGRAM,\n });\n\n t.like(await fetchPool(client.rpc, pool), <Account<Pool>>{\n data: {\n authority,\n // todo add missing fields later\n },\n });\n});\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var test = require('ava');
|
|
4
|
+
var src = require('../src');
|
|
5
|
+
var _constants = require('./_constants');
|
|
6
|
+
var _helpers = require('./_helpers');
|
|
7
|
+
var _setup = require('./_setup');
|
|
8
|
+
|
|
9
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var test__default = /*#__PURE__*/_interopDefault(test);
|
|
12
|
+
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
15
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
16
|
+
};
|
|
17
|
+
var require_deposit_test = __commonJS({
|
|
18
|
+
"test/_deposit.test.ts"() {
|
|
19
|
+
test__default.default("it deposits into SOL pool for authority", async (t) => {
|
|
20
|
+
const client = _setup.createDefaultSolanaClient();
|
|
21
|
+
const [pool] = await src.findPoolAddress({
|
|
22
|
+
mint: _constants.WRAPPED_SOL_MINT_TOKEN_PROGRAM
|
|
23
|
+
});
|
|
24
|
+
const { merkleTree: merkleTreeAddress } = await _helpers.createAndInitEmptyMerkleTree(
|
|
25
|
+
client,
|
|
26
|
+
pool
|
|
27
|
+
);
|
|
28
|
+
const merkleTree = new src.MerkleTree(20);
|
|
29
|
+
await merkleTree.initialize();
|
|
30
|
+
const { authority } = await _setup.createSolPoolForAuthority(
|
|
31
|
+
client,
|
|
32
|
+
merkleTreeAddress
|
|
33
|
+
);
|
|
34
|
+
const [vault] = await src.findVaultAddress({ pool });
|
|
35
|
+
const amount = BigInt(10) * _constants.LAMPORTS_PER_SOL;
|
|
36
|
+
console.log(" amount", amount);
|
|
37
|
+
const { depositor, commitment } = await _setup.depositSolPoolForAuthority(
|
|
38
|
+
client,
|
|
39
|
+
amount,
|
|
40
|
+
merkleTreeAddress
|
|
41
|
+
);
|
|
42
|
+
console.log("depositor ->", depositor);
|
|
43
|
+
merkleTree.insert(commitment);
|
|
44
|
+
console.log("merkle tree", merkleTree.root());
|
|
45
|
+
const bal = await _setup.getBalance(client, vault);
|
|
46
|
+
console.log("the balance", bal);
|
|
47
|
+
//! debug
|
|
48
|
+
t.truthy(BigInt(bal) >= amount);
|
|
49
|
+
t.like(await src.fetchPool(client.rpc, pool), {
|
|
50
|
+
data: {
|
|
51
|
+
authority
|
|
52
|
+
// todo add missing fields later
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
var _deposit_test = require_deposit_test();
|
|
59
|
+
|
|
60
|
+
module.exports = _deposit_test;
|
|
61
|
+
//# sourceMappingURL=_deposit.test.js.map
|
|
62
|
+
//# sourceMappingURL=_deposit.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../test/_deposit.test.ts"],"names":["test","createDefaultSolanaClient","findPoolAddress","WRAPPED_SOL_MINT_TOKEN_PROGRAM","createAndInitEmptyMerkleTree","MerkleTree","createSolPoolForAuthority","findVaultAddress","LAMPORTS_PER_SOL","depositSolPoolForAuthority","getBalance","fetchPool"],"mappings":";;;;;;;;;;;;;;;;AAAA,IAAA,oBAAA,GAAA,UAAA,CAAA;AAAA,EAAA,uBAAA,GAAA;AAkBA,IAAAA,qBAAA,CAAK,yCAAA,EAA2C,OAAO,CAAA,KAAM;AAC3D,MAAA,MAAM,SAASC,gCAAA,EAA0B;AAGzC,MAAA,MAAM,CAAC,IAAI,CAAA,GAAI,MAAMC,mBAAA,CAAgB;AAAA,QACnC,IAAA,EAAMC;AAAA,OACP,CAAA;AAED,MAAA,MAAM,EAAE,UAAA,EAAY,iBAAA,EAAkB,GAAI,MAAMC,qCAAA;AAAA,QAC9C,MAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,MAAM,UAAA,GAAa,IAAIC,cAAA,CAAW,EAAE,CAAA;AACpC,MAAA,MAAM,WAAW,UAAA,EAAW;AAG5B,MAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAMC,gCAAA;AAAA,QAC1B,MAAA;AAAA,QACA;AAAA,OACF;AAGA,MAAA,MAAM,CAAC,KAAK,CAAA,GAAI,MAAMC,oBAAA,CAAiB,EAAE,MAAM,CAAA;AAG/C,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,EAAE,CAAA,GAAIC,2BAAA;AAC5B,MAAA,OAAA,CAAQ,GAAA,CAAI,WAAW,MAAM,CAAA;AAE7B,MAAA,MAAM,EAAE,SAAA,EAAW,UAAA,EAAW,GAAI,MAAMC,iCAAA;AAAA,QACtC,MAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,OAAA,CAAQ,GAAA,CAAI,gBAAgB,SAAS,CAAA;AAGrC,MAAA,UAAA,CAAW,OAAO,UAAU,CAAA;AAC5B,MAAA,OAAA,CAAQ,GAAA,CAAI,aAAA,EAAe,UAAA,CAAW,IAAA,EAAM,CAAA;AAG5C,MAAA,MAAM,GAAA,GAAM,MAAMC,iBAAA,CAAW,MAAA,EAAQ,KAAK,CAAA;AAC1C,MAAA,OAAA,CAAQ,GAAA,CAAI,eAAe,GAAG,CAAA;AAAA;AAC9B,MAAA,CAAA,CAAE,MAAA,CAAO,MAAA,CAAO,GAAG,CAAA,IAAK,MAAM,CAAA;AAE9B,MAAA,CAAA,CAAE,KAAK,MAAMC,aAAA,CAAU,MAAA,CAAO,GAAA,EAAK,IAAI,CAAA,EAAkB;AAAA,QACvD,IAAA,EAAM;AAAA,UACJ;AAAA;AAAA;AAEF,OACD,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EAAA;AAAA,CAAA,CAAA","file":"_deposit.test.js","sourcesContent":["import { Account } from '@solana/web3.js';\nimport test from 'ava';\nimport {\n fetchPool,\n findPoolAddress,\n findVaultAddress,\n MerkleTree,\n Pool,\n} from '../src';\nimport { LAMPORTS_PER_SOL, WRAPPED_SOL_MINT_TOKEN_PROGRAM } from './_constants';\nimport { createAndInitEmptyMerkleTree } from './_helpers';\nimport {\n createDefaultSolanaClient,\n createSolPoolForAuthority,\n depositSolPoolForAuthority,\n getBalance,\n} from './_setup';\n\ntest('it deposits into SOL pool for authority', async (t) => {\n const client = createDefaultSolanaClient();\n\n // find pool address\n const [pool] = await findPoolAddress({\n mint: WRAPPED_SOL_MINT_TOKEN_PROGRAM,\n });\n\n const { merkleTree: merkleTreeAddress } = await createAndInitEmptyMerkleTree(\n client,\n pool\n );\n\n const merkleTree = new MerkleTree(20);\n await merkleTree.initialize();\n\n // create pool\n const { authority } = await createSolPoolForAuthority(\n client,\n merkleTreeAddress\n );\n\n // find vault address\n const [vault] = await findVaultAddress({ pool });\n\n // deposit\n const amount = BigInt(10) * LAMPORTS_PER_SOL;\n console.log(' amount', amount); // ! debug\n\n const { depositor, commitment } = await depositSolPoolForAuthority(\n client,\n amount,\n merkleTreeAddress\n );\n console.log('depositor ->', depositor); // ! debug\n\n // initialize merkle tree\n merkleTree.insert(commitment);\n console.log('merkle tree', merkleTree.root()); // ! debug\n\n // check pool balance, since this is sol and not wrapped, check vault directly\n const bal = await getBalance(client, vault);\n console.log('the balance', bal); //! debug\n t.truthy(BigInt(bal) >= amount);\n\n t.like(await fetchPool(client.rpc, pool), <Account<Pool>>{\n data: {\n authority,\n // todo add missing fields later\n },\n });\n});\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _setup = require('./_setup');
|
|
4
|
+
|
|
5
|
+
const createAndInitPoseidonMerkleTree = async (_client, pool) => {
|
|
6
|
+
const authority = await _setup.loadDefaultKeypair();
|
|
7
|
+
console.log("Merkle tree is off-chain (event-based) for pool:", pool);
|
|
8
|
+
return { authority: authority.address, merkleTree: pool };
|
|
9
|
+
};
|
|
10
|
+
const createAndInitEmptyMerkleTree = createAndInitPoseidonMerkleTree;
|
|
11
|
+
|
|
12
|
+
exports.createAndInitEmptyMerkleTree = createAndInitEmptyMerkleTree;
|
|
13
|
+
exports.createAndInitPoseidonMerkleTree = createAndInitPoseidonMerkleTree;
|
|
14
|
+
//# sourceMappingURL=_helpers.js.map
|
|
15
|
+
//# sourceMappingURL=_helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../test/_helpers.ts"],"names":["loadDefaultKeypair"],"mappings":";;;;AAQO,MAAM,+BAAA,GAAkC,OAC7C,OAAA,EACA,IAAA,KACyD;AACzD,EAAA,MAAM,SAAA,GAAY,MAAMA,yBAAA,EAAmB;AAE3C,EAAA,OAAA,CAAQ,GAAA,CAAI,oDAAoD,IAAI,CAAA;AACpE,EAAA,OAAO,EAAE,SAAA,EAAW,SAAA,CAAU,OAAA,EAAS,YAAY,IAAA,EAAK;AAC1D;AAIO,MAAM,4BAAA,GAA+B","file":"_helpers.js","sourcesContent":["import { Address } from '@solana/kit';\nimport { Client, loadDefaultKeypair } from './_setup';\n\n/**\n * Merkle tree is now off-chain (events-based like Tornado Cash)\n * This function is kept for backwards compatibility but does nothing\n * Commitments are emitted as events and users build the tree locally\n */\nexport const createAndInitPoseidonMerkleTree = async (\n _client: Client,\n pool: Address\n): Promise<{ authority: Address; merkleTree: Address }> => {\n const authority = await loadDefaultKeypair();\n\n console.log('Merkle tree is off-chain (event-based) for pool:', pool);\n return { authority: authority.address, merkleTree: pool }; // Return pool as placeholder\n};\n\n// Keep old function for backwards compatibility\n/** @deprecated Merkle tree is now off-chain (event-based) */\nexport const createAndInitEmptyMerkleTree = createAndInitPoseidonMerkleTree;\n"]}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var computeBudget = require('@solana-program/compute-budget');
|
|
4
|
+
var kit = require('@solana/kit');
|
|
5
|
+
var fs = require('fs');
|
|
6
|
+
var os = require('os');
|
|
7
|
+
var path = require('path');
|
|
8
|
+
var crypto = require('crypto');
|
|
9
|
+
var src = require('../src');
|
|
10
|
+
var _constants = require('./_constants');
|
|
11
|
+
|
|
12
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
+
|
|
14
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
15
|
+
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
16
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
17
|
+
|
|
18
|
+
const createDefaultSolanaClient = () => {
|
|
19
|
+
const rpc = kit.createSolanaRpc("http://127.0.0.1:8899");
|
|
20
|
+
const rpcSubscriptions = kit.createSolanaRpcSubscriptions("ws://127.0.0.1:8900");
|
|
21
|
+
return { rpc, rpcSubscriptions };
|
|
22
|
+
};
|
|
23
|
+
const createDevnetClient = () => {
|
|
24
|
+
const rpc = kit.createSolanaRpc("https://api.devnet.solana.com");
|
|
25
|
+
const rpcSubscriptions = kit.createSolanaRpcSubscriptions(
|
|
26
|
+
"wss://api.devnet.solana.com/"
|
|
27
|
+
);
|
|
28
|
+
return { rpc, rpcSubscriptions };
|
|
29
|
+
};
|
|
30
|
+
const generateKeyPairSignerWithSol = async (client, putativeLamports = 1000000000n) => {
|
|
31
|
+
const signer = await kit.generateKeyPairSigner();
|
|
32
|
+
await kit.airdropFactory(client)({
|
|
33
|
+
recipientAddress: signer.address,
|
|
34
|
+
lamports: kit.lamports(putativeLamports),
|
|
35
|
+
commitment: "confirmed"
|
|
36
|
+
});
|
|
37
|
+
return signer;
|
|
38
|
+
};
|
|
39
|
+
const airdropSolToAddress = async (client, receiver, putativeLamports = 5000000000n) => {
|
|
40
|
+
await kit.airdropFactory(client)({
|
|
41
|
+
recipientAddress: receiver,
|
|
42
|
+
lamports: kit.lamports(putativeLamports),
|
|
43
|
+
commitment: "confirmed"
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
async function loadKeypairFromFile(filePath) {
|
|
47
|
+
const resolvedPath = path__default.default.resolve(
|
|
48
|
+
filePath.startsWith("~") ? filePath.replace("~", os__default.default.homedir()) : filePath
|
|
49
|
+
);
|
|
50
|
+
const loadedKeyBytes = Uint8Array.from(
|
|
51
|
+
JSON.parse(fs__default.default.readFileSync(resolvedPath, "utf8"))
|
|
52
|
+
);
|
|
53
|
+
const keypairSigner = await kit.createKeyPairSignerFromBytes(loadedKeyBytes);
|
|
54
|
+
return keypairSigner;
|
|
55
|
+
}
|
|
56
|
+
const createDefaultTransaction = async (client, feePayer) => {
|
|
57
|
+
const { value: latestBlockhash } = await client.rpc.getLatestBlockhash().send();
|
|
58
|
+
return kit.pipe(
|
|
59
|
+
kit.createTransactionMessage({ version: 0 }),
|
|
60
|
+
(tx) => kit.setTransactionMessageFeePayerSigner(feePayer, tx),
|
|
61
|
+
(tx) => kit.setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx)
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
const signAndSendTransaction = async (client, transactionMessage, commitment = "finalized") => {
|
|
65
|
+
const signedTransaction = await kit.signTransactionMessageWithSigners(transactionMessage);
|
|
66
|
+
kit.assertIsSendableTransaction(signedTransaction);
|
|
67
|
+
const signature = kit.getSignatureFromTransaction(signedTransaction);
|
|
68
|
+
kit.assertIsTransactionWithBlockhashLifetime(signedTransaction);
|
|
69
|
+
await kit.sendAndConfirmTransactionFactory(client)(signedTransaction, {
|
|
70
|
+
commitment,
|
|
71
|
+
skipPreflight: true
|
|
72
|
+
});
|
|
73
|
+
console.log("\n[DEBUG;] le signature ->", signature);
|
|
74
|
+
return signature;
|
|
75
|
+
};
|
|
76
|
+
const getBalance = async (client, address) => (await client.rpc.getBalance(address, { commitment: "confirmed" }).send()).value;
|
|
77
|
+
async function loadDefaultKeypair() {
|
|
78
|
+
return await loadKeypairFromFile("~/.config/solana/id.json");
|
|
79
|
+
}
|
|
80
|
+
async function loadReceiverKeypair() {
|
|
81
|
+
return await loadKeypairFromFile("~/.config/solana/id-new.json");
|
|
82
|
+
}
|
|
83
|
+
async function loadRelayerKeypair() {
|
|
84
|
+
return await loadKeypairFromFile("~/.config/solana/relayer.json");
|
|
85
|
+
}
|
|
86
|
+
const getTokenBalance = async (client, tokenAccount) => (await client.rpc.getTokenAccountBalance(tokenAccount, { commitment: "confirmed" }).send()).value;
|
|
87
|
+
const createSolPoolForAuthority = async (client) => {
|
|
88
|
+
const [authority] = await Promise.all([loadDefaultKeypair()]);
|
|
89
|
+
const createIx = await src.getInitializePoolInstructionAsync({
|
|
90
|
+
authority,
|
|
91
|
+
mint: _constants.WRAPPED_SOL_MINT_TOKEN_PROGRAM,
|
|
92
|
+
// feeCollector: FEE_COLLECTOR_ADDRESS,
|
|
93
|
+
assetType: src.AssetType.Sol
|
|
94
|
+
//! since we are using wrapped sol mint, can we get rid of this
|
|
95
|
+
});
|
|
96
|
+
await kit.pipe(
|
|
97
|
+
await createDefaultTransaction(client, authority),
|
|
98
|
+
(tx) => kit.appendTransactionMessageInstruction(createIx, tx),
|
|
99
|
+
(tx) => signAndSendTransaction(client, tx)
|
|
100
|
+
);
|
|
101
|
+
return { authority: authority.address };
|
|
102
|
+
};
|
|
103
|
+
const depositSolPoolForAuthority = async (client, amount, merkleTree) => {
|
|
104
|
+
const [authority] = await Promise.all([loadDefaultKeypair()]);
|
|
105
|
+
const [pool] = await src.findPoolAddress({
|
|
106
|
+
mint: _constants.WRAPPED_SOL_MINT_TOKEN_PROGRAM
|
|
107
|
+
});
|
|
108
|
+
const secret = crypto.randomBytes(32);
|
|
109
|
+
const nullifier = crypto.randomBytes(32);
|
|
110
|
+
const commitment = await src.generateCommitment(secret, nullifier, amount, pool);
|
|
111
|
+
console.log("commitment ", commitment);
|
|
112
|
+
merkleTree.insert(commitment);
|
|
113
|
+
const newRoot = merkleTree.root();
|
|
114
|
+
console.log("New merkle root after deposit:", newRoot);
|
|
115
|
+
const createIx = await src.getDepositInstructionAsync({
|
|
116
|
+
depositor: authority,
|
|
117
|
+
pool,
|
|
118
|
+
amount,
|
|
119
|
+
commitment,
|
|
120
|
+
newRoot,
|
|
121
|
+
mint: _constants.WRAPPED_SOL_MINT_TOKEN_PROGRAM
|
|
122
|
+
});
|
|
123
|
+
await kit.pipe(
|
|
124
|
+
await createDefaultTransaction(client, authority),
|
|
125
|
+
(tx) => kit.appendTransactionMessageInstruction(createIx, tx),
|
|
126
|
+
(tx) => signAndSendTransaction(client, tx)
|
|
127
|
+
);
|
|
128
|
+
return {
|
|
129
|
+
depositor: authority.address,
|
|
130
|
+
commitment,
|
|
131
|
+
secret,
|
|
132
|
+
nullifier
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
const transferForAuthority = async (client, ixArgs) => {
|
|
136
|
+
const [relayer, recipient] = await Promise.all([
|
|
137
|
+
loadRelayerKeypair(),
|
|
138
|
+
loadReceiverKeypair()
|
|
139
|
+
]);
|
|
140
|
+
await airdropSolToAddress(client, relayer.address);
|
|
141
|
+
const {
|
|
142
|
+
relayerFee,
|
|
143
|
+
recipientAmount,
|
|
144
|
+
nullifierHash,
|
|
145
|
+
// root,
|
|
146
|
+
mint,
|
|
147
|
+
publicInputs,
|
|
148
|
+
proofData: { proofA, proofB, proofC }
|
|
149
|
+
} = ixArgs;
|
|
150
|
+
const [pool] = await src.findPoolAddress({
|
|
151
|
+
mint
|
|
152
|
+
});
|
|
153
|
+
const transferIx = await src.getTransferInstructionAsync({
|
|
154
|
+
relayer,
|
|
155
|
+
pool,
|
|
156
|
+
recipient: recipient.address,
|
|
157
|
+
proofA,
|
|
158
|
+
proofB,
|
|
159
|
+
proofC,
|
|
160
|
+
// root,
|
|
161
|
+
nullifierHash,
|
|
162
|
+
publicInputs,
|
|
163
|
+
// recipientArg: recipient.address,
|
|
164
|
+
amount: BigInt(relayerFee),
|
|
165
|
+
// OLD 'amount' param → NEW 'relayer_fee'
|
|
166
|
+
fee: BigInt(recipientAmount),
|
|
167
|
+
mint
|
|
168
|
+
});
|
|
169
|
+
await kit.pipe(
|
|
170
|
+
await createDefaultTransaction(client, relayer),
|
|
171
|
+
(tx) => kit.appendTransactionMessageInstruction(transferIx, tx),
|
|
172
|
+
(tx) => kit.appendTransactionMessageInstructions(
|
|
173
|
+
[computeBudget.getSetComputeUnitLimitInstruction({ units: 14e5 })],
|
|
174
|
+
tx
|
|
175
|
+
),
|
|
176
|
+
(tx) => signAndSendTransaction(client, tx)
|
|
177
|
+
);
|
|
178
|
+
return { relayer: relayer.address };
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
exports.airdropSolToAddress = airdropSolToAddress;
|
|
182
|
+
exports.createDefaultSolanaClient = createDefaultSolanaClient;
|
|
183
|
+
exports.createDefaultTransaction = createDefaultTransaction;
|
|
184
|
+
exports.createDevnetClient = createDevnetClient;
|
|
185
|
+
exports.createSolPoolForAuthority = createSolPoolForAuthority;
|
|
186
|
+
exports.depositSolPoolForAuthority = depositSolPoolForAuthority;
|
|
187
|
+
exports.generateKeyPairSignerWithSol = generateKeyPairSignerWithSol;
|
|
188
|
+
exports.getBalance = getBalance;
|
|
189
|
+
exports.getTokenBalance = getTokenBalance;
|
|
190
|
+
exports.loadDefaultKeypair = loadDefaultKeypair;
|
|
191
|
+
exports.loadKeypairFromFile = loadKeypairFromFile;
|
|
192
|
+
exports.loadReceiverKeypair = loadReceiverKeypair;
|
|
193
|
+
exports.loadRelayerKeypair = loadRelayerKeypair;
|
|
194
|
+
exports.signAndSendTransaction = signAndSendTransaction;
|
|
195
|
+
exports.transferForAuthority = transferForAuthority;
|
|
196
|
+
//# sourceMappingURL=_setup.js.map
|
|
197
|
+
//# sourceMappingURL=_setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../test/_setup.ts"],"names":["createSolanaRpc","createSolanaRpcSubscriptions","generateKeyPairSigner","airdropFactory","lamports","path","os","fs","createKeyPairSignerFromBytes","pipe","createTransactionMessage","setTransactionMessageFeePayerSigner","setTransactionMessageLifetimeUsingBlockhash","signTransactionMessageWithSigners","assertIsSendableTransaction","getSignatureFromTransaction","assertIsTransactionWithBlockhashLifetime","sendAndConfirmTransactionFactory","getInitializePoolInstructionAsync","WRAPPED_SOL_MINT_TOKEN_PROGRAM","AssetType","appendTransactionMessageInstruction","findPoolAddress","randomBytes","generateCommitment","getDepositInstructionAsync","getTransferInstructionAsync","appendTransactionMessageInstructions","getSetComputeUnitLimitInstruction"],"mappings":"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","file":"_setup.js","sourcesContent":["import { getSetComputeUnitLimitInstruction } from '@solana-program/compute-budget';\nimport {\n Address,\n airdropFactory,\n appendTransactionMessageInstruction,\n appendTransactionMessageInstructions,\n assertIsSendableTransaction,\n assertIsTransactionWithBlockhashLifetime,\n Commitment,\n createKeyPairSignerFromBytes,\n createSolanaRpc,\n createSolanaRpcSubscriptions,\n createTransactionMessage,\n generateKeyPairSigner,\n getSignatureFromTransaction,\n KeyPairSigner,\n lamports,\n pipe,\n Rpc,\n RpcSubscriptions,\n sendAndConfirmTransactionFactory,\n setTransactionMessageFeePayerSigner,\n setTransactionMessageLifetimeUsingBlockhash,\n signTransactionMessageWithSigners,\n SolanaRpcApi,\n SolanaRpcSubscriptionsApi,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionSigner,\n} from '@solana/kit';\n\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport { randomBytes } from 'crypto';\nimport {\n AssetType,\n findPoolAddress,\n generateCommitment,\n getDepositInstructionAsync,\n getInitializePoolInstructionAsync,\n getTransferInstructionAsync,\n ProofData,\n} from '../src';\nimport { WRAPPED_SOL_MINT_TOKEN_PROGRAM } from './_constants';\n\nexport type Client = {\n rpc: Rpc<SolanaRpcApi>;\n rpcSubscriptions: RpcSubscriptions<SolanaRpcSubscriptionsApi>;\n};\n\nexport const createDefaultSolanaClient = (): Client => {\n const rpc = createSolanaRpc('http://127.0.0.1:8899');\n const rpcSubscriptions = createSolanaRpcSubscriptions('ws://127.0.0.1:8900');\n return { rpc, rpcSubscriptions };\n};\n\nexport const createDevnetClient = (): Client => {\n const rpc = createSolanaRpc('https://api.devnet.solana.com');\n const rpcSubscriptions = createSolanaRpcSubscriptions(\n 'wss://api.devnet.solana.com/'\n );\n\n return { rpc, rpcSubscriptions };\n};\n\nexport const generateKeyPairSignerWithSol = async (\n client: Client,\n putativeLamports: bigint = 1_000_000_000n\n) => {\n const signer = await generateKeyPairSigner();\n await airdropFactory(client)({\n recipientAddress: signer.address,\n lamports: lamports(putativeLamports),\n commitment: 'confirmed',\n });\n return signer;\n};\n\nexport const airdropSolToAddress = async (\n client: Client,\n receiver: Address, // 5 sol\n putativeLamports: bigint = 5_000_000_000n // 5 sol\n) => {\n await airdropFactory(client)({\n recipientAddress: receiver,\n lamports: lamports(putativeLamports),\n commitment: 'confirmed',\n });\n};\n\nexport async function loadKeypairFromFile(\n filePath: string\n): Promise<KeyPairSigner<string>> {\n // This is here so you can also load the default keypair from the file system.\n const resolvedPath = path.resolve(\n filePath.startsWith('~') ? filePath.replace('~', os.homedir()) : filePath\n );\n const loadedKeyBytes = Uint8Array.from(\n JSON.parse(fs.readFileSync(resolvedPath, 'utf8'))\n );\n // Here you can also set the second parameter to true in case you need to extract your private key.\n const keypairSigner = await createKeyPairSignerFromBytes(loadedKeyBytes);\n return keypairSigner;\n}\n\nexport const createDefaultTransaction = async (\n client: Client,\n feePayer: TransactionSigner\n) => {\n const { value: latestBlockhash } = await client.rpc\n .getLatestBlockhash()\n .send();\n return pipe(\n createTransactionMessage({ version: 0 }),\n (tx) => setTransactionMessageFeePayerSigner(feePayer, tx),\n (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx)\n );\n};\n\nexport const signAndSendTransaction = async (\n client: Client,\n transactionMessage: TransactionMessage & TransactionMessageWithFeePayer,\n // & TransactionMessageWithLifetime,\n commitment: Commitment = 'finalized'\n) => {\n const signedTransaction =\n await signTransactionMessageWithSigners(transactionMessage);\n assertIsSendableTransaction(signedTransaction);\n\n const signature = getSignatureFromTransaction(signedTransaction);\n\n assertIsTransactionWithBlockhashLifetime(signedTransaction);\n await sendAndConfirmTransactionFactory(client)(signedTransaction, {\n commitment,\n skipPreflight: true,\n });\n\n console.log('\\n[DEBUG;] le signature ->', signature); // ! debug\n return signature;\n};\n\nexport const getBalance = async (client: Client, address: Address) =>\n (await client.rpc.getBalance(address, { commitment: 'confirmed' }).send())\n .value;\n\nexport async function loadDefaultKeypair(): Promise<KeyPairSigner<string>> {\n return await loadKeypairFromFile('~/.config/solana/id.json');\n}\n\nexport async function loadReceiverKeypair(): Promise<KeyPairSigner<string>> {\n return await loadKeypairFromFile('~/.config/solana/id-new.json');\n}\n\nexport async function loadRelayerKeypair(): Promise<KeyPairSigner<string>> {\n return await loadKeypairFromFile('~/.config/solana/relayer.json');\n}\n\nexport const getTokenBalance = async (client: Client, tokenAccount: Address) =>\n (\n await client.rpc\n .getTokenAccountBalance(tokenAccount, { commitment: 'confirmed' })\n .send()\n ).value;\n\n// -------------------------------------------------- instructions\n\nexport const createSolPoolForAuthority = async (\n client: Client\n // merkleTree?: Address\n): Promise<{ authority: Address }> => {\n const [authority] = await Promise.all([loadDefaultKeypair()]);\n\n const createIx = await getInitializePoolInstructionAsync({\n authority,\n mint: WRAPPED_SOL_MINT_TOKEN_PROGRAM,\n // feeCollector: FEE_COLLECTOR_ADDRESS,\n assetType: AssetType.Sol, //! since we are using wrapped sol mint, can we get rid of this\n });\n\n await pipe(\n await createDefaultTransaction(client, authority),\n (tx) => appendTransactionMessageInstruction(createIx, tx),\n (tx) => signAndSendTransaction(client, tx)\n );\n\n return { authority: authority.address };\n};\n\nexport const depositSolPoolForAuthority = async (\n client: Client,\n amount: bigint,\n merkleTree: import('../src').MerkleTree\n): Promise<{\n depositor: Address;\n commitment: Uint8Array;\n secret: Uint8Array;\n nullifier: Uint8Array;\n}> => {\n const [authority] = await Promise.all([loadDefaultKeypair()]);\n\n // find pool address\n const [pool] = await findPoolAddress({\n mint: WRAPPED_SOL_MINT_TOKEN_PROGRAM,\n });\n\n // generate commitment\n const secret = randomBytes(32);\n const nullifier = randomBytes(32);\n const commitment = await generateCommitment(secret, nullifier, amount, pool);\n\n console.log('commitment ', commitment); // ! debug\n\n // Insert commitment into merkle tree and compute new root\n merkleTree.insert(commitment);\n const newRoot = merkleTree.root();\n console.log('New merkle root after deposit:', newRoot);\n\n // ! NOTE, DURING INITIALIZATION,\n const createIx = await getDepositInstructionAsync({\n depositor: authority,\n pool,\n amount,\n commitment,\n newRoot,\n mint: WRAPPED_SOL_MINT_TOKEN_PROGRAM,\n });\n\n await pipe(\n await createDefaultTransaction(client, authority),\n (tx) => appendTransactionMessageInstruction(createIx, tx),\n (tx) => signAndSendTransaction(client, tx)\n );\n\n return {\n depositor: authority.address,\n commitment,\n secret,\n nullifier,\n };\n};\n\nexport const transferForAuthority = async (\n client: Client,\n ixArgs: {\n relayerFee: number;\n recipientAmount: number;\n nullifierHash: Uint8Array;\n proofData: ProofData;\n publicInputs: Uint8Array[];\n mint: Address;\n }\n): Promise<{\n relayer: Address;\n}> => {\n const [relayer, recipient] = await Promise.all([\n loadRelayerKeypair(),\n loadReceiverKeypair(),\n ]);\n\n // airdrop relayer\n await airdropSolToAddress(client, relayer.address);\n\n const {\n relayerFee,\n recipientAmount,\n nullifierHash,\n // root,\n mint,\n publicInputs,\n proofData: { proofA, proofB, proofC },\n } = ixArgs;\n\n // find pool address\n const [pool] = await findPoolAddress({\n mint,\n });\n\n // TEMPORARY: The autogenerated client hasn't been regenerated yet\n // The Rust program expects: relayer_fee (6th), recipient_amount (7th)\n // But the old client has: amount (6th), fee (7th)\n // So we swap them here until the client is regenerated\n const transferIx = await getTransferInstructionAsync({\n relayer,\n pool,\n recipient: recipient.address,\n proofA,\n proofB,\n proofC,\n // root,\n nullifierHash,\n publicInputs,\n // recipientArg: recipient.address,\n amount: BigInt(relayerFee), // OLD 'amount' param → NEW 'relayer_fee'\n fee: BigInt(recipientAmount),\n mint,\n });\n\n await pipe(\n await createDefaultTransaction(client, relayer),\n (tx) => appendTransactionMessageInstruction(transferIx, tx),\n (tx) =>\n appendTransactionMessageInstructions(\n [getSetComputeUnitLimitInstruction({ units: 1_400_000 })],\n tx\n ),\n (tx) => signAndSendTransaction(client, tx)\n );\n\n // todo: return the address of the pool\n // todo: what to return\n return { relayer: relayer.address };\n};\n"]}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var kit = require('@solana/kit');
|
|
4
|
+
var test = require('ava');
|
|
5
|
+
var src = require('../src');
|
|
6
|
+
var _constants = require('./_constants');
|
|
7
|
+
var _setup = require('./_setup');
|
|
8
|
+
|
|
9
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var test__default = /*#__PURE__*/_interopDefault(test);
|
|
12
|
+
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
15
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
16
|
+
};
|
|
17
|
+
var require_transfer_test = __commonJS({
|
|
18
|
+
"test/transfer.test.ts"() {
|
|
19
|
+
test__default.default("it transfers authority deposited SOL", async (t) => {
|
|
20
|
+
const client = _setup.createDefaultSolanaClient();
|
|
21
|
+
const relayer = await _setup.loadRelayerKeypair();
|
|
22
|
+
const merkleTree = new src.MerkleTree(20);
|
|
23
|
+
await merkleTree.initialize();
|
|
24
|
+
const [pool] = await src.findPoolAddress({
|
|
25
|
+
mint: _constants.WRAPPED_SOL_MINT_TOKEN_PROGRAM
|
|
26
|
+
});
|
|
27
|
+
const { authority } = await _setup.createSolPoolForAuthority(client);
|
|
28
|
+
console.log("init authority", authority);
|
|
29
|
+
const [vault] = await src.findVaultAddress({ pool });
|
|
30
|
+
const depositAmount = BigInt(10) * _constants.LAMPORTS_PER_SOL;
|
|
31
|
+
const { secret, nullifier } = await _setup.depositSolPoolForAuthority(
|
|
32
|
+
client,
|
|
33
|
+
depositAmount,
|
|
34
|
+
merkleTree
|
|
35
|
+
// Pass the merkle tree to handle root computation
|
|
36
|
+
);
|
|
37
|
+
const localRoot = merkleTree.root();
|
|
38
|
+
console.log("Local merkle tree root:", localRoot);
|
|
39
|
+
const leafIndex = 0;
|
|
40
|
+
const { pathElements, pathIndices } = merkleTree.getProof(leafIndex);
|
|
41
|
+
const root = localRoot;
|
|
42
|
+
console.log("Using local root for proof:", root);
|
|
43
|
+
const nullifierHash = await src.generateNullifier(nullifier, pool);
|
|
44
|
+
const recipient = await _setup.loadReceiverKeypair();
|
|
45
|
+
const recipientBytes = kit.getAddressEncoder().encode(recipient.address);
|
|
46
|
+
const relayerBytes = kit.getAddressEncoder().encode(relayer.address);
|
|
47
|
+
const relayerFee = 0;
|
|
48
|
+
const recipientAmount = Number(depositAmount);
|
|
49
|
+
console.log("Generating ZK proof...");
|
|
50
|
+
const { proofData, publicInputs } = await src.generateProof({
|
|
51
|
+
secret,
|
|
52
|
+
nullifier,
|
|
53
|
+
amount: Number(depositAmount),
|
|
54
|
+
// Private input - what was deposited
|
|
55
|
+
pathElements,
|
|
56
|
+
pathIndices,
|
|
57
|
+
recipient: Uint8Array.from(recipientBytes),
|
|
58
|
+
relayer: Uint8Array.from(relayerBytes),
|
|
59
|
+
fee: relayerFee,
|
|
60
|
+
// Public input - must match instruction parameter
|
|
61
|
+
refund: recipientAmount,
|
|
62
|
+
// Public input - must match instruction parameter
|
|
63
|
+
root: Uint8Array.from(root),
|
|
64
|
+
poolAddress: pool
|
|
65
|
+
});
|
|
66
|
+
console.log("ZK proof generated successfully");
|
|
67
|
+
const balanceBefore = await _setup.getBalance(client, vault);
|
|
68
|
+
console.log("Vault balance before transfer:", balanceBefore);
|
|
69
|
+
await _setup.transferForAuthority(client, {
|
|
70
|
+
relayerFee,
|
|
71
|
+
recipientAmount,
|
|
72
|
+
nullifierHash,
|
|
73
|
+
publicInputs,
|
|
74
|
+
proofData,
|
|
75
|
+
mint: _constants.WRAPPED_SOL_MINT_TOKEN_PROGRAM
|
|
76
|
+
});
|
|
77
|
+
console.log("Transfer completed successfully");
|
|
78
|
+
const balanceAfter = await _setup.getBalance(client, vault);
|
|
79
|
+
console.log("Vault balance after transfer:", balanceAfter);
|
|
80
|
+
const protocolFee = BigInt(recipientAmount) * 30n / 10000n;
|
|
81
|
+
const finalRecipientAmount = BigInt(recipientAmount) - protocolFee;
|
|
82
|
+
const totalWithdrawn = BigInt(recipientAmount) + BigInt(relayerFee);
|
|
83
|
+
console.log("Protocol fee:", protocolFee);
|
|
84
|
+
console.log("Final recipient amount:", finalRecipientAmount);
|
|
85
|
+
console.log("Total withdrawn from vault:", totalWithdrawn);
|
|
86
|
+
t.truthy(BigInt(balanceBefore) - BigInt(balanceAfter) >= totalWithdrawn);
|
|
87
|
+
const recipientBalance = await _setup.getBalance(client, recipient.address);
|
|
88
|
+
console.log("Recipient balance:", recipientBalance);
|
|
89
|
+
t.truthy(BigInt(recipientBalance) >= finalRecipientAmount);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
var transfer_test = require_transfer_test();
|
|
94
|
+
|
|
95
|
+
module.exports = transfer_test;
|
|
96
|
+
//# sourceMappingURL=transfer.test.js.map
|
|
97
|
+
//# sourceMappingURL=transfer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../test/transfer.test.ts"],"names":["test","createDefaultSolanaClient","loadRelayerKeypair","MerkleTree","findPoolAddress","WRAPPED_SOL_MINT_TOKEN_PROGRAM","createSolPoolForAuthority","findVaultAddress","LAMPORTS_PER_SOL","depositSolPoolForAuthority","generateNullifier","loadReceiverKeypair","getAddressEncoder","generateProof","getBalance","transferForAuthority"],"mappings":"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","file":"transfer.test.js","sourcesContent":["import { getAddressEncoder } from '@solana/kit';\nimport test from 'ava';\nimport {\n findPoolAddress,\n findVaultAddress,\n generateNullifier,\n generateProof,\n MerkleTree,\n} from '../src';\nimport { LAMPORTS_PER_SOL, WRAPPED_SOL_MINT_TOKEN_PROGRAM } from './_constants';\nimport {\n createDefaultSolanaClient,\n createSolPoolForAuthority,\n depositSolPoolForAuthority,\n getBalance,\n loadReceiverKeypair,\n loadRelayerKeypair,\n transferForAuthority,\n} from './_setup';\n\ntest('it transfers authority deposited SOL', async (t) => {\n const client = createDefaultSolanaClient();\n const relayer = await loadRelayerKeypair();\n const merkleTree = new MerkleTree(20);\n await merkleTree.initialize();\n\n // find pool address\n const [pool] = await findPoolAddress({\n mint: WRAPPED_SOL_MINT_TOKEN_PROGRAM,\n });\n\n // create pool\n const { authority } = await createSolPoolForAuthority(client);\n console.log('init authority', authority); // ! debug\n\n // find vault address\n const [vault] = await findVaultAddress({ pool });\n\n // deposit\n const depositAmount = BigInt(10) * LAMPORTS_PER_SOL;\n const { secret, nullifier } = await depositSolPoolForAuthority(\n client,\n depositAmount,\n merkleTree // Pass the merkle tree to handle root computation\n );\n\n // Tree already updated inside depositSolPoolForAuthority\n const localRoot = merkleTree.root();\n console.log('Local merkle tree root:', localRoot);\n\n // Get merkle proof for the commitment (leaf index 0 since it's the first deposit)\n const leafIndex = 0;\n const { pathElements, pathIndices } = merkleTree.getProof(leafIndex);\n\n // Use LOCAL root (tree is off-chain now)\n const root = localRoot;\n console.log('Using local root for proof:', root);\n\n // Generate nullifier hash\n const nullifierHash = await generateNullifier(nullifier, pool);\n\n // Get recipient address\n const recipient = await loadReceiverKeypair();\n const recipientBytes = getAddressEncoder().encode(recipient.address);\n\n // For now, use authority as relayer (can be changed later)\n const relayerBytes = getAddressEncoder().encode(relayer.address);\n\n // Generate zero-knowledge proof\n // In the new design:\n // - relayer_fee: what the relayer gets (user chooses)\n // - recipient_amount: what goes to recipient BEFORE protocol fee (proven by circuit)\n // - circuit proves: depositAmount >= relayer_fee + recipient_amount\n const relayerFee = 0; // No relayer fee for this test\n const recipientAmount = Number(depositAmount); // Withdraw full deposit amount\n\n console.log('Generating ZK proof...');\n const { proofData, publicInputs } = await generateProof({\n secret,\n nullifier,\n amount: Number(depositAmount), // Private input - what was deposited\n pathElements,\n pathIndices,\n recipient: Uint8Array.from(recipientBytes),\n relayer: Uint8Array.from(relayerBytes),\n fee: relayerFee, // Public input - must match instruction parameter\n refund: recipientAmount, // Public input - must match instruction parameter\n root: Uint8Array.from(root),\n poolAddress: pool,\n });\n\n console.log('ZK proof generated successfully');\n\n // Check vault balance before transfer\n const balanceBefore = await getBalance(client, vault);\n console.log('Vault balance before transfer:', balanceBefore);\n\n // Perform the transfer (withdrawal)\n await transferForAuthority(client, {\n relayerFee,\n recipientAmount,\n nullifierHash,\n publicInputs,\n proofData,\n mint: WRAPPED_SOL_MINT_TOKEN_PROGRAM,\n });\n\n console.log('Transfer completed successfully');\n\n // Check vault balance after transfer\n const balanceAfter = await getBalance(client, vault);\n console.log('Vault balance after transfer:', balanceAfter);\n\n // Calculate expected amounts\n // Protocol fee is 30bps of recipient_amount\n const protocolFee = (BigInt(recipientAmount) * 30n) / 10000n;\n const finalRecipientAmount = BigInt(recipientAmount) - protocolFee;\n const totalWithdrawn = BigInt(recipientAmount) + BigInt(relayerFee);\n\n console.log('Protocol fee:', protocolFee);\n console.log('Final recipient amount:', finalRecipientAmount);\n console.log('Total withdrawn from vault:', totalWithdrawn);\n\n // Verify vault balance decreased by the total withdrawn amount\n t.truthy(BigInt(balanceBefore) - BigInt(balanceAfter) >= totalWithdrawn);\n\n // Verify recipient received the funds (after protocol fee)\n const recipientBalance = await getBalance(client, recipient.address);\n console.log('Recipient balance:', recipientBalance);\n t.truthy(BigInt(recipientBalance) >= finalRecipientAmount);\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smithii_io/mixoor",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "JavaScript client for the Mixoor program",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"module": "./dist/src/index.mjs",
|
|
7
7
|
"main": "./dist/src/index.js",
|
|
8
|
-
"types": "./dist/types/index.d.ts",
|
|
8
|
+
"types": "./dist/types/src/index.d.ts",
|
|
9
9
|
"type": "commonjs",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
|
-
"types": "./dist/types/index.d.ts",
|
|
12
|
+
"types": "./dist/types/src/index.d.ts",
|
|
13
13
|
"import": "./dist/src/index.mjs",
|
|
14
14
|
"require": "./dist/src/index.js"
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
|
-
"
|
|
19
|
-
"./dist/types"
|
|
18
|
+
"dist"
|
|
20
19
|
],
|
|
21
20
|
"scripts": {
|
|
22
21
|
"build": "rimraf dist && tsup && tsc -p ./tsconfig.declarations.json",
|