quantumswap 0.0.2 → 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/examples/_test-wallet.js +1 -3
- package/examples/deploy-IERC20.js +3 -4
- package/examples/deploy-QuantumSwapV2ERC20.js +3 -4
- package/examples/deploy-QuantumSwapV2Factory.js +3 -4
- package/examples/deploy-QuantumSwapV2Pair.js +3 -4
- package/examples/deploy-QuantumSwapV2Router02.js +3 -4
- package/examples/deploy-WQ.js +3 -4
- package/examples/events-IERC20.js +3 -4
- package/examples/events-QuantumSwapV2ERC20.js +3 -4
- package/examples/events-QuantumSwapV2Factory.js +3 -4
- package/examples/events-QuantumSwapV2Pair.js +3 -4
- package/examples/events-QuantumSwapV2Router02.js +3 -4
- package/examples/events-WQ.js +3 -4
- package/examples/offline-signing-IERC20.js +3 -4
- package/examples/offline-signing-QuantumSwapV2ERC20.js +3 -4
- package/examples/offline-signing-QuantumSwapV2Factory.js +3 -4
- package/examples/offline-signing-QuantumSwapV2Pair.js +3 -4
- package/examples/offline-signing-QuantumSwapV2Router02.js +3 -4
- package/examples/offline-signing-WQ.js +3 -4
- package/examples/package-lock.json +11 -20
- package/examples/package.json +1 -1
- package/examples/read-operations-IERC20.js +3 -4
- package/examples/read-operations-QuantumSwapV2ERC20.js +3 -4
- package/examples/read-operations-QuantumSwapV2Factory.js +3 -4
- package/examples/read-operations-QuantumSwapV2Pair.js +3 -4
- package/examples/read-operations-QuantumSwapV2Router02.js +3 -4
- package/examples/read-operations-WQ.js +3 -4
- package/examples/run-dex-flow-custom.js +22 -13
- package/examples/run-dex-flow-custom.ts +23 -13
- package/examples/write-operations-IERC20.js +3 -4
- package/examples/write-operations-QuantumSwapV2ERC20.js +3 -4
- package/examples/write-operations-QuantumSwapV2Factory.js +3 -4
- package/examples/write-operations-QuantumSwapV2Pair.js +3 -4
- package/examples/write-operations-QuantumSwapV2Router02.js +3 -4
- package/examples/write-operations-WQ.js +3 -4
- package/package.json +3 -4
- package/test/e2e/IERC20.e2e.test.js +2 -2
- package/test/e2e/QuantumSwapV2ERC20.e2e.test.js +2 -2
- package/test/e2e/QuantumSwapV2Factory.e2e.test.js +2 -2
- package/test/e2e/QuantumSwapV2Pair.e2e.test.js +2 -2
- package/test/e2e/QuantumSwapV2Router02.e2e.test.js +2 -2
- package/test/e2e/WQ.e2e.test.js +2 -2
- package/test/e2e/all-contracts.e2e.test.js +103 -72
- package/test/e2e/dex-full-flow.e2e.test.js +59 -26
|
@@ -13,7 +13,7 @@ const { describe, it } = require("node:test");
|
|
|
13
13
|
const assert = require("node:assert/strict");
|
|
14
14
|
|
|
15
15
|
const { Initialize } = require("quantumcoin/config");
|
|
16
|
-
const {
|
|
16
|
+
const { getProvider, Wallet } = require("quantumcoin");
|
|
17
17
|
|
|
18
18
|
const { IERC20, IERC20__factory, QuantumSwapV2ERC20, QuantumSwapV2ERC20__factory, QuantumSwapV2Factory, QuantumSwapV2Factory__factory, QuantumSwapV2Pair, QuantumSwapV2Pair__factory, QuantumSwapV2Router02, QuantumSwapV2Router02__factory, WQ, WQ__factory } = require("../..");
|
|
19
19
|
|
|
@@ -22,82 +22,113 @@ const TEST_WALLET_ENCRYPTED_JSON =
|
|
|
22
22
|
"{\"address\":\"1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6\",\"crypto\":{\"cipher\":\"aes-256-ctr\",\"ciphertext\":\"ab7e620dd66cb55ac201b9c6796de92bbb06f3681b5932eabe099871f1f7d79acabe30921a39ad13bfe74f42c515734882b6723760142aa3e26e011df514a534ae47bd15d86badd9c6f17c48d4c892711d54d441ee3a0ee0e5b060f816e79c7badd13ff4c235934b1986774223ecf6e8761388969bb239c759b54c8c70e6a2e27c93a4b70129c8159f461d271ae8f3573414c78b88e4d0abfa6365ed45456636d4ed971c7a0c6b84e6f0c2621e819268b135e2bcc169a54d1847b39e6ba2ae8ec969b69f330b7db9e785ed02204d5a1185915ae5338b0f40ef2a7f4d5aaf7563d502135e57f4eb89d5ec1efa5c77e374969d6cd85be625a2ed1225d68ecdd84067bfc69adb83ecd5c6050472eca28a5a646fcdd28077165c629975bec8a79fe1457cb53389b788b25e1f8eff8b2ca326d7dfcaba3f8839225a08057c018a458891fd2caa0d2b27632cffd80f592147ccec9a10dc8a08a48fb55047bff5cf85cda39eb089096bef63842fc3686412f298a54a9e4b0bf4ad36907ba373cbd6d32e7ac494af371da5aa9d38a3463220865114c4adc5e4ac258ba9c6af9fa2ddfd1aec2e16887e4b3977c69561df8599ac9d411c9dd2a4d57f92ea4e5c02aae3f49fb3bc83e16673e6c2dbe96bb181c8dfd0f9757ade2e4ff27215a836058c5ffeab042f6f97c7c02339f76a6284680e01b4bb733690eb3347fbfcc26614b8bf755f9dfce3fea9d4e4d15b164983201732c2e87593a86bca6da6972e128490338f76ae68135888070f4e59e90db54d23834769bdbda9769213faf5357f9167a224523975a946367b68f0cec98658575609f58bfd329e420a921c06713326e4cb20a0df1d77f37e78a320a637a96c604ca3fa89e24beb42313751b8f09b14f9c14c77e4fd13fc6382505d27c771bca0d821ec7c3765acffa99d83c50140a56b0b28101c762bd682fe55cb6f23cbeb3f421d7b36021010e45ac27160dd7ead99c864a1b550c7edb1246950fe32dcc049799f9085287f0a747a6ef7a023df46a23a22f3e833bbf8d404f84344870492658256ee1dfc40fda33bb8d48fc72d4520ba9fc820c9123104a045206809037709f2a5f6723fa77d6bac5a573823d4ec3a7f1cb786a52ee2697e622e5d75962fa554d1024a6c355e21f33a63b2b72e6c4742a8b1c373aa532b40518c38c90b5373c2eb8c9d7be2a9e16047a3ee09dc9a6849deac5183ace6cfe91a9bef2ffc0a7df6ccebfd4c858c84b0e0355650d7466971e66f1e3883013e5ad1be33199b1d110b79070ac1b745ccb14cf63a08f8cca3a21c9525e626ff5f0c34746e10750fb742ad51f11f2acae3676c2111853d7250d01b77821a6ba9e04400ba2c543ca9f2d701ae6f47bfad14ffe3039ee9e71f7b2401359ade9938750ddb9c5a8b018a7929ed8d0e717ff1861446ce17535e9b17c187711190aae3388bd9490837a636c25ed4d42d7079ad1a51e13292c683d5d012abcf46965c534b83ab53f2c1f0cf5830ef7582e06863a33c19a70511df632885d63245965047ea96b56f1af5b3b94a54999f784fb9574fdfcd7c1230e07a2aaa04acd3097b2b9f8ddba05ae9734491deb5c1a513c76ed276cb78bbf4839dae3156d76af444a5805129d5df791167a9c8576a1d7f760b2d2797c4658669608706fbd0ace1be2346f74862dfc9ef518e55632e43c043186e5d070deb34d12fb9e5aba84e5cb50213dc88efd39cc35bf42455aa82d5e3b707b3140be3b8623b34fdd81d08615c188ae8438a13881fdf6bf32f2cb9ff5fa625561040c6b71d4b8eccc90bc3b99650d28dd1ee63773e49664e3d48c484996b290943635a6f2eb1ce9796d3fa144a3f00ef82faaa32d6a413668f7b521517cb68b2b017fcf56c79326fa5e4060e643631ca3f0a0dc0ed718798b6f46b130d437c33f64039e887324b6f5e604b1669d613923794edbf04b1b3caea54793b52b44b170173a4f25c7ecef3b71e2aad76e556b1cb9f1d637ec52ececfa950dd31dbb6a60828a3ad34c1beffe09eb4785786d63bad10a0b0f66ea88c57380f38ea85f018dbd7f538cf1ee7624095b9a01ec5edd528f281168af020609e651ff316aa1320a710134ddfca600cc72174dcdb846d2aa29916488aa1b537b66da92e61af526debef4eb38c984569eaf549ff2129449269b492d030cd74d885f6f5785881cc4804b4a8a09ba4ff7aefe9074ac7d0c4f05d51fe4cc0ff7388a772092b9d02d70e5433a5cf3e02f46a6bd6b818d59a07ce3b9fbbf8b5faba74563bcc5240930c2d406c9aaee3e3ce0429bf68ac2b0a57adb09414cff50817d2a48fb9fa624ab863cb0c31a8b8dc5eaf6fa68cc1d7c6c685c5a33edd5c8933b9e8ab628ee428d0743699b2ff17f25586c7ce959280bb0b8c5342251f0a30b53dbc7bf1ee426ac9619c3560f811f2268ee37f189794e2e4b3db3a2fb2e34b649e504fb467438abfd1082619cc4a0b30d66beb831077812e418d2e2148db10cf4d4a29101ca52ec445b8d83519dd7de85a98e0beae9ee537096d3f1a55a7a80cdfa93d25f07c9f98e8af18cde19ec1f99c5dd4588b717a5039ddb7f177717caf0d0fd45420a70dbd6d3146890d9e450d5224146db4c33b779e3c3a04b976c052bad042ac57dd38be45407808c0fb0d7e2a8819e6cd53c6739e6612996ddaa6f066552590aa0343bc1e62b298ff2514a0cef8be21956c2e942816f7a3a3a0935eaf9b37251409ce444c986c3817e82835555fe18239f3ae33469d7965c2bde9991fde556bd07af01df52bbde0c35bb4ef48e3b5d0db53f8ca4ed35b83f760f0a1bc4ed9f86e85d6039a17df373c85402ef956f01db00eb39c4b74bd0660d29ee746714d9780d738e05c6cca414ce3d7b40dda8036a9eea9ab1388805f913eb19bdd3f09d9e161eaa50231bd9caba61971f194332dd28c696a60458c1c6c2cc5da8b1192611c7c553e9e12fe48ce46bbb891be8bb118721c86222e671ddd1da8f0ccb2b68e02f2014b4925e904e88369aaf7466bd7033a60c265d45955944916ecbdb84bf1b522b01b0149c632e04c568a7eb627c5bb90ece052ebcf79166c28b30d23fe52da0a5ab5dea83ca479a3e3b7a9cfbbfea04dbe6137c19d067317c2ec427a8c75a6b06bec6dcd5d5c0edc9aa80b9003b8e17c088b2f3db327d3e42630d82d20120240c3ba56232280787da4aabbf5bc95a864029f00710e195f2a76460a0317d10b552fe1bea097e41d49756c680a41d6ac186e62169b6b6cd7776ea84618b5b752328a5bacaa10aa122ff9b2698b43efe73d852a899db644863c8c9bc8068ea86ea843fd6fe36272b91cdc5d5317083ef3fd1e5462a0b0d0604dc57b3bbfceb0fca4cd349625dd7b25166af30efe5ee6a0af953a74d65f4736c59918ee55a3b0d9d9d42e04c7f8a77e479109f740e20c464d5d7e3d16805f47b61f403ff7f408c9e850d9baacd8067e544536a4953480b0f9ee9cd45f41ebd67b51f78788a6470cb1e5ca72ca346ce8a50d0ca0c921d5576a4455a1afb6d0bc688004712ee122cacdb29c51e84893324c27fa4a3f1917edf5352272b4c97579a6152e4b77663d0ab532915f2eeb6a862de8b696452321b660c3f2449673d086e95a7af28845a5259b763e0fcd09f72acf7b6c811066263060e5aa5b24658e880a01fd56bda4dad5ab604e129290f7d5489728f2a40968c6168b21cebbbcd11727cc9e9160c4e92e04387d3b0d62aab06a61f26daedd9fed11816ef2180172a47f47184ac4032b88758c98a2e0fb200f70e93ba695f5ebb7a1029610ad360d3b7fa1b4640b9dc674d3625eef786da93dff19bc7991b5d6193a3896664763fde479b5dfc04812111a80782854f2cf68ca7d82765cc9eb40fba4b44640710ed6e653abf9f07b466333f4fd22784d53cf40e17120f42caa841eaa24056b237827b0f47f7257c103c35027e9f503e5acfd023e7357b600d3084d361d5ee65ba319b45c153212a54e6fed85af7e43e0a926ebcbc2edf8de7e2ec9528f00bec262ad04d5c9dafccaea06a24748d28bf1799bae0e895543084539c50b5aaa4fb50d7431d6f0c8cee2a54aaf7ee7919b55bf40adb688632e5dbe273cea09e97b19c3d8e1f4de000deb66fa1942ad03a62d3252f51992244366c156000b49c297167a6cbdedea7ebae139d295f0ad298e0864249b905b7eb812886ec70ecdb286702274b5b8574149bf3866f9e46b997ff5ed622b169a0eb071347f18d530db1663906a28f4544ee4e004ab87b65476af30ede118052ff052b8dc986ca2c93dd5d4943266a579c7698ea014f688b3e8063a107feb162d392e2177b01bff77fb5abe5feebd0607158049a5a093325b7c9ee6b4dfa7a9f65c7c2fb628920d3603a1c2dad979eaa047cd661a268af1078c9788d720e64e4ce9d12e68de1e417ef2f293323681e1071f9220e1ee43d2e29d111b870ce3439f5100ecd4551ab65ee74aa1667e564957e9bc0ae1ea193980da2a0ec2698073388c85bec25ef447f0d5e93a5203fa44dff268e5cb799ed3b66e63d5e07b487e7534f24934c73a62a243e0151843a0fd3807711a101eaa7fc71f0ba68aebb9534d57cba41b094eebfb4c31cca8eddfa426f676aa347be8a7023a4e91ddb154b35cd4d5f7dbc2e5db491de99f33fc2cff2d57029ac950e1ccd681980af6a4e8969dfe39b3c7bfcbcf8fac92f1e6ec9fe572bfa6a7d65860eab2ed10ac01a71290b52e3148e84b7376a8605cd2bb0e8681ffc54691ce087685e33921bd44d36c78291713dce17569570f62137e6904f0d68cf53aa2ec395c389a75141f08114fb293ea63950e4ffee55ec6fc83cf44876b8e7f25cdd393ff87b9eda6eb746085b61a6900de191f0ce2cb388d61ece52e78bc47368194e8e00277e0d1631e6b9d4626ef76f8522582ccd5a40be3febc699bb510acc6271d55ff0f4cf3bb7669855a72efd9ca3e1056a2fe592a5bc877cce2b1f63b58383971da87873d2d1349cf5881242cdce4e7e2c5c514755746a0e0a7c2a6d9701cde005ae3420beb17c379a3516662253554f51f0423bb1844b0b90c54ed8177ceb0e1036a6609d836e748ca06c40ca64befadc6443ec286a0ce464678e8d11eb455f7bb305acebf6cb1f50e394a9bfeb752df1687831bac9cdd811f4f112ef6658d0f8799a866374ff96c5e2b79f30e7a74f8a2bc9ed1f88f01f30e30cb78ffb2bff10108f35e910ee3be4463e9e6f0ed910e8d598326e71dfa2277ffe5579d7fe9b6018bfe295b25219eae07b3b0270665c3fa00c3e0d180812b5cd62925585de84a7c48a9a86dba96544a251654d1966e082432dc85b6149cf21e91a46020ec32b66d28ba3b6a90c0617bc6fdd55aea819af2bcf84864ad60c28fe3c9f8339d0aee68b39d97f63b6e082835d86119cf9b9fdc8b827c847ce40aa10e1577a710132316845e825345e95bdf94d0c66ec65a6c4319fce4792313663b5f7a651a6710783e6ab71608ac6cbbf3af6911adf596ccf7c172b9bd5bceb6db379967b32b143bdd11d2ee12ddf64ecef6391e0f8570e6cddd3db95204919362b89b739fa94e7c1bfde799fd5e22aa25ca6ca42e30c08e23aae2385d99ebab441072a880dcefdab74a4c9bd39d363f6d1933d59400fca161d432aa00f23b1b1c19a154be8989699d549b66d44e39896f5523443bc6ddf4a65e91f1f3fb7b52318869a05856a4fc92f3694c81ed833c972fb918f7e5\",\"cipherparams\":{\"iv\":\"8c46d6162cd4c765759aedcbce2a5874\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"82fb6cdc6917609135277badacf15baa31899d08b71a5a0fa33167167c161537\"},\"mac\":\"9187b17f7eca48e6b8c586b0cd790dbe0feb876ac8385f93faa7d5e22a3c8fc7\"},\"id\":\"92caf6ee-2d43-48c0-859e-ffa1e0e23312\",\"version\":3}";
|
|
23
23
|
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
24
24
|
|
|
25
|
+
function reportLog(entries) {
|
|
26
|
+
console.log("\n========== ALL-CONTRACTS E2E REPORT ==========");
|
|
27
|
+
console.log("Contract addresses and transaction IDs:\n");
|
|
28
|
+
for (const e of entries) {
|
|
29
|
+
if (e.address != null) console.log(` [${e.step}] ${e.name}: contract=${e.address} tx=${e.txId ?? "—"}`);
|
|
30
|
+
else console.log(` [${e.step}] ${e.name}: tx=${e.txId ?? "—"}`);
|
|
31
|
+
}
|
|
32
|
+
console.log("==============================================\n");
|
|
33
|
+
}
|
|
34
|
+
|
|
25
35
|
describe("all contracts", () => {
|
|
26
36
|
it("deploys and invokes all contracts", async (t) => {
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
const log = [];
|
|
38
|
+
const step = (name, address, txId) => {
|
|
39
|
+
log.push({ step: log.length + 1, name, address: address ?? null, txId: txId ?? null });
|
|
40
|
+
if (address != null && txId != null) console.log(`[all-contracts] ${name}: address=${address} tx=${txId}`);
|
|
41
|
+
else if (txId != null) console.log(`[all-contracts] ${name}: tx=${txId}`);
|
|
42
|
+
else if (address != null) console.log(`[all-contracts] ${name}: address=${address}`);
|
|
43
|
+
};
|
|
32
44
|
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
try {
|
|
46
|
+
const rpcUrl = process.env.QC_RPC_URL;
|
|
47
|
+
if (!rpcUrl) {
|
|
48
|
+
t.skip("QC_RPC_URL not provided");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
35
51
|
|
|
36
|
-
|
|
37
|
-
|
|
52
|
+
const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
|
|
53
|
+
await Initialize(null);
|
|
38
54
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
const provider = getProvider(rpcUrl, chainId);
|
|
56
|
+
const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
|
|
57
|
+
|
|
58
|
+
let deployGasLimit = 600000;
|
|
59
|
+
try {
|
|
60
|
+
const firstFactory = new IERC20__factory(wallet);
|
|
61
|
+
const sampleReq = firstFactory.getDeployTransaction();
|
|
62
|
+
const est = await provider.estimateGas({ from: wallet.address, data: sampleReq.data });
|
|
63
|
+
deployGasLimit = Number(est + 200_000n);
|
|
64
|
+
} catch {
|
|
65
|
+
deployGasLimit = 6_000_000;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let IERC20Inst = await (new IERC20__factory(wallet)).deploy({ gasLimit: deployGasLimit });
|
|
69
|
+
const _deployTxIERC20 = IERC20Inst.deployTransaction();
|
|
70
|
+
assert.ok(_deployTxIERC20 && _deployTxIERC20.hash);
|
|
71
|
+
step("IERC20 deploy", String(IERC20Inst.target), _deployTxIERC20.hash);
|
|
72
|
+
await _deployTxIERC20.wait(1, 600_000);
|
|
73
|
+
const approveTx1 = await IERC20Inst.approve(wallet.address, 123, { gasLimit: 200000 });
|
|
74
|
+
step("IERC20 approve", null, approveTx1.hash);
|
|
75
|
+
void (await IERC20Inst.decimals());
|
|
76
|
+
await approveTx1.wait(1, 600_000);
|
|
48
77
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
78
|
+
let QuantumSwapV2ERC20Inst = await (new QuantumSwapV2ERC20__factory(wallet)).deploy({ gasLimit: deployGasLimit });
|
|
79
|
+
const _deployTxQuantumSwapV2ERC20 = QuantumSwapV2ERC20Inst.deployTransaction();
|
|
80
|
+
assert.ok(_deployTxQuantumSwapV2ERC20 && _deployTxQuantumSwapV2ERC20.hash);
|
|
81
|
+
step("QuantumSwapV2ERC20 deploy", String(QuantumSwapV2ERC20Inst.target), _deployTxQuantumSwapV2ERC20.hash);
|
|
82
|
+
await _deployTxQuantumSwapV2ERC20.wait(1, 600_000);
|
|
83
|
+
const approveTx2 = await QuantumSwapV2ERC20Inst.approve(wallet.address, 123, { gasLimit: 200000 });
|
|
84
|
+
step("QuantumSwapV2ERC20 approve", null, approveTx2.hash);
|
|
85
|
+
void (await QuantumSwapV2ERC20Inst.decimals());
|
|
86
|
+
await approveTx2.wait(1, 600_000);
|
|
87
|
+
|
|
88
|
+
let QuantumSwapV2FactoryInst = await (new QuantumSwapV2Factory__factory(wallet)).deploy(wallet.address, { gasLimit: deployGasLimit });
|
|
89
|
+
const _deployTxQuantumSwapV2Factory = QuantumSwapV2FactoryInst.deployTransaction();
|
|
90
|
+
assert.ok(_deployTxQuantumSwapV2Factory && _deployTxQuantumSwapV2Factory.hash);
|
|
91
|
+
step("QuantumSwapV2Factory deploy", String(QuantumSwapV2FactoryInst.target), _deployTxQuantumSwapV2Factory.hash);
|
|
92
|
+
await _deployTxQuantumSwapV2Factory.wait(1, 600_000);
|
|
93
|
+
void (await QuantumSwapV2FactoryInst.INIT_CODE_HASH());
|
|
94
|
+
const createPairTx = await QuantumSwapV2FactoryInst.createPair(wallet.address, wallet.address, { gasLimit: 200000 });
|
|
95
|
+
step("QuantumSwapV2Factory createPair", null, createPairTx.hash);
|
|
96
|
+
await createPairTx.wait(1, 600_000);
|
|
97
|
+
|
|
98
|
+
let QuantumSwapV2PairInst = await (new QuantumSwapV2Pair__factory(wallet)).deploy({ gasLimit: deployGasLimit });
|
|
99
|
+
const _deployTxQuantumSwapV2Pair = QuantumSwapV2PairInst.deployTransaction();
|
|
100
|
+
assert.ok(_deployTxQuantumSwapV2Pair && _deployTxQuantumSwapV2Pair.hash);
|
|
101
|
+
step("QuantumSwapV2Pair deploy", String(QuantumSwapV2PairInst.target), _deployTxQuantumSwapV2Pair.hash);
|
|
102
|
+
await _deployTxQuantumSwapV2Pair.wait(1, 600_000);
|
|
103
|
+
void (await QuantumSwapV2PairInst.MINIMUM_LIQUIDITY());
|
|
104
|
+
const approveTx3 = await QuantumSwapV2PairInst.approve(wallet.address, 123, { gasLimit: 200000 });
|
|
105
|
+
step("QuantumSwapV2Pair approve", null, approveTx3.hash);
|
|
106
|
+
await approveTx3.wait(1, 600_000);
|
|
107
|
+
|
|
108
|
+
let QuantumSwapV2Router02Inst = await (new QuantumSwapV2Router02__factory(wallet)).deploy(wallet.address, wallet.address, { gasLimit: deployGasLimit });
|
|
109
|
+
const _deployTxQuantumSwapV2Router02 = QuantumSwapV2Router02Inst.deployTransaction();
|
|
110
|
+
assert.ok(_deployTxQuantumSwapV2Router02 && _deployTxQuantumSwapV2Router02.hash);
|
|
111
|
+
step("QuantumSwapV2Router02 deploy", String(QuantumSwapV2Router02Inst.target), _deployTxQuantumSwapV2Router02.hash);
|
|
112
|
+
await _deployTxQuantumSwapV2Router02.wait(1, 600_000);
|
|
113
|
+
void (await QuantumSwapV2Router02Inst.WETH());
|
|
114
|
+
const addLiqTx = await QuantumSwapV2Router02Inst.addLiquidity(wallet.address, wallet.address, 123, 123, 123, 123, wallet.address, 123, { gasLimit: 200000 });
|
|
115
|
+
step("QuantumSwapV2Router02 addLiquidity", null, addLiqTx.hash);
|
|
116
|
+
await addLiqTx.wait(1, 600_000);
|
|
117
|
+
|
|
118
|
+
let WQInst = await (new WQ__factory(wallet)).deploy({ gasLimit: deployGasLimit });
|
|
119
|
+
const _deployTxWQ = WQInst.deployTransaction();
|
|
120
|
+
assert.ok(_deployTxWQ && _deployTxWQ.hash);
|
|
121
|
+
step("WQ deploy", String(WQInst.target), _deployTxWQ.hash);
|
|
122
|
+
await _deployTxWQ.wait(1, 600_000);
|
|
123
|
+
void (await WQInst.decimals());
|
|
124
|
+
const approveTx4 = await WQInst.approve(wallet.address, 123, { gasLimit: 200000 });
|
|
125
|
+
step("WQ approve", null, approveTx4.hash);
|
|
126
|
+
await approveTx4.wait(1, 600_000);
|
|
127
|
+
|
|
128
|
+
reportLog(log);
|
|
129
|
+
} catch (err) {
|
|
130
|
+
if (log.length > 0) reportLog(log);
|
|
131
|
+
throw err;
|
|
132
|
+
}
|
|
102
133
|
}, { timeout: 1800000});
|
|
103
134
|
});
|
|
@@ -15,9 +15,8 @@ const path = require("node:path");
|
|
|
15
15
|
|
|
16
16
|
const { Initialize } = require("quantumcoin/config");
|
|
17
17
|
const {
|
|
18
|
-
|
|
18
|
+
getProvider,
|
|
19
19
|
Wallet,
|
|
20
|
-
Contract,
|
|
21
20
|
ContractFactory,
|
|
22
21
|
getCreateAddress,
|
|
23
22
|
isAddress,
|
|
@@ -60,10 +59,29 @@ const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
|
60
59
|
const DEPLOY_GAS_FALLBACK = 6_000_000n;
|
|
61
60
|
const TX_GAS_FALLBACK = 400_000n;
|
|
62
61
|
const GAS_BUFFER_PERCENT = 110n; // 10% buffer over estimate
|
|
63
|
-
|
|
62
|
+
// Use chain block timestamp (UTC) + offset for deadline so it matches what the router checks (no clock skew).
|
|
63
|
+
// Router requires block.timestamp <= deadline.
|
|
64
|
+
const DEADLINE_OFFSET = process.env.QC_DEADLINE_OFFSET ? Number(process.env.QC_DEADLINE_OFFSET) : 3600;
|
|
65
|
+
|
|
66
|
+
/** Returns deadline as UTC Unix timestamp: current chain block timestamp + DEADLINE_OFFSET. */
|
|
67
|
+
async function deadline(provider) {
|
|
68
|
+
const blockNumber = await provider.getBlockNumber();
|
|
69
|
+
const block = await provider.getBlock(blockNumber);
|
|
70
|
+
const blockTimestamp = block && block.timestamp != null ? Number(block.timestamp) : Math.floor(Date.now() / 1000);
|
|
71
|
+
return BigInt(blockTimestamp + DEADLINE_OFFSET);
|
|
72
|
+
}
|
|
64
73
|
|
|
65
|
-
function
|
|
66
|
-
|
|
74
|
+
function reportDexFlow(contractAddresses, txHashes) {
|
|
75
|
+
console.log("\n========== DEX-FULL-FLOW E2E REPORT ==========");
|
|
76
|
+
console.log("Contract addresses:\n");
|
|
77
|
+
for (const [name, addr] of Object.entries(contractAddresses)) {
|
|
78
|
+
console.log(` ${name}: ${addr}`);
|
|
79
|
+
}
|
|
80
|
+
console.log("\nTransaction IDs:\n");
|
|
81
|
+
(txHashes || []).forEach((hash, i) => {
|
|
82
|
+
console.log(` [${i + 1}] ${hash}`);
|
|
83
|
+
});
|
|
84
|
+
console.log("================================================\n");
|
|
67
85
|
}
|
|
68
86
|
|
|
69
87
|
/** Estimate gas via provider.estimateGas (quantumcoin.js SDK), add buffer, fallback on error. */
|
|
@@ -95,6 +113,9 @@ async function deployGasLimit(provider, from, getDeployTx, fallback, bytecodeFlo
|
|
|
95
113
|
|
|
96
114
|
describe("QuantumSwap V2 DEX full flow", () => {
|
|
97
115
|
it("deploys WQ, Factory, Router; validates addresses; deploys two ERC20s; creates pair; parses PairCreated; balance checks; sends tokens to another wallet", async (t) => {
|
|
116
|
+
const contractAddresses = {};
|
|
117
|
+
const txHashes = [];
|
|
118
|
+
try {
|
|
98
119
|
const rpcUrl = process.env.QC_RPC_URL;
|
|
99
120
|
if (!rpcUrl) {
|
|
100
121
|
t.skip("QC_RPC_URL not provided");
|
|
@@ -108,7 +129,7 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
108
129
|
const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
|
|
109
130
|
await Initialize(null);
|
|
110
131
|
|
|
111
|
-
const provider =
|
|
132
|
+
const provider = getProvider(rpcUrl, chainId);
|
|
112
133
|
const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
|
|
113
134
|
|
|
114
135
|
// --- Address validation (quantumcoin.js isAddress / getAddress) ---
|
|
@@ -119,8 +140,6 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
119
140
|
// Before-balance for step 11 (native): capture before any transactions
|
|
120
141
|
const nativeBalanceBeforeAllTxs = await provider.getBalance(walletAddr);
|
|
121
142
|
|
|
122
|
-
const contractAddresses = {};
|
|
123
|
-
const txHashes = [];
|
|
124
143
|
let totalGasUsed = 0n;
|
|
125
144
|
let pairWqTokenAAddress = null;
|
|
126
145
|
|
|
@@ -192,7 +211,7 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
192
211
|
const resp = await wallet.sendTransaction({ ...tx, nonce, gasLimit });
|
|
193
212
|
console.log("[4] ERC20 deploy tx id:", name, resp.hash);
|
|
194
213
|
addReceiptGas(await resp.wait(1, 600_000));
|
|
195
|
-
const contract =
|
|
214
|
+
const contract = IERC20.connect(getAddress(address), wallet);
|
|
196
215
|
contract._deployTx = resp;
|
|
197
216
|
return contract;
|
|
198
217
|
};
|
|
@@ -322,6 +341,7 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
322
341
|
console.log("[8b] tokenB approve tx id:", approveB.hash);
|
|
323
342
|
txHashes.push(approveB.hash);
|
|
324
343
|
addReceiptGas(await approveB.wait(1, 600_000));
|
|
344
|
+
const addLiqDeadline = await deadline(provider);
|
|
325
345
|
const addLiqTxReq = await routerContract.populateTransaction.addLiquidity(
|
|
326
346
|
tokenAAddress,
|
|
327
347
|
tokenBAddress,
|
|
@@ -330,7 +350,7 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
330
350
|
amountAMin,
|
|
331
351
|
amountBMin,
|
|
332
352
|
walletAddr,
|
|
333
|
-
|
|
353
|
+
addLiqDeadline,
|
|
334
354
|
);
|
|
335
355
|
const addLiqGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...addLiqTxReq }, TX_GAS_FALLBACK);
|
|
336
356
|
const tokenABalanceBeforeAddLiqRaw = await tokenA.balanceOf(walletAddr);
|
|
@@ -343,7 +363,7 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
343
363
|
amountAMin,
|
|
344
364
|
amountBMin,
|
|
345
365
|
walletAddr,
|
|
346
|
-
|
|
366
|
+
addLiqDeadline,
|
|
347
367
|
{ gasLimit: addLiqGasLimit },
|
|
348
368
|
);
|
|
349
369
|
console.log("[8c] addLiquidity tx id:", addLiqTx.hash);
|
|
@@ -370,12 +390,13 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
370
390
|
console.log("[9a] swap approve tx id:", approveSwap.hash);
|
|
371
391
|
txHashes.push(approveSwap.hash);
|
|
372
392
|
addReceiptGas(await approveSwap.wait(1, 600_000));
|
|
393
|
+
const swapDeadline = await deadline(provider);
|
|
373
394
|
const swapTxReq = await routerContract.populateTransaction.swapExactTokensForTokens(
|
|
374
395
|
swapAmountIn,
|
|
375
396
|
amountOutMin,
|
|
376
397
|
pathSwap,
|
|
377
398
|
walletAddr,
|
|
378
|
-
|
|
399
|
+
swapDeadline,
|
|
379
400
|
);
|
|
380
401
|
const swapGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...swapTxReq }, TX_GAS_FALLBACK);
|
|
381
402
|
const tokenBBalanceBeforeSwapRaw = await tokenB.balanceOf(walletAddr);
|
|
@@ -385,7 +406,7 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
385
406
|
amountOutMin,
|
|
386
407
|
pathSwap,
|
|
387
408
|
walletAddr,
|
|
388
|
-
|
|
409
|
+
swapDeadline,
|
|
389
410
|
{ gasLimit: swapGasLimit },
|
|
390
411
|
);
|
|
391
412
|
console.log("[9b] swapExactTokensForTokens tx id:", swapTx.hash);
|
|
@@ -438,13 +459,14 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
438
459
|
console.log("[10c] tokenA approve (ETH liq) tx id:", approveTokenAForEth.hash);
|
|
439
460
|
txHashes.push(approveTokenAForEth.hash);
|
|
440
461
|
addReceiptGas(await approveTokenAForEth.wait(1, 600_000));
|
|
462
|
+
const addLiqEthDeadline = await deadline(provider);
|
|
441
463
|
const addLiqEthTxReq = await routerContract.populateTransaction.addLiquidityETH(
|
|
442
464
|
tokenAAddress,
|
|
443
465
|
tokenForEthLiq,
|
|
444
466
|
0n,
|
|
445
467
|
0n,
|
|
446
468
|
walletAddr,
|
|
447
|
-
|
|
469
|
+
addLiqEthDeadline,
|
|
448
470
|
{ value: ethToWrap },
|
|
449
471
|
);
|
|
450
472
|
const addLiqEthGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...addLiqEthTxReq }, TX_GAS_FALLBACK);
|
|
@@ -454,7 +476,7 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
454
476
|
0n,
|
|
455
477
|
0n,
|
|
456
478
|
walletAddr,
|
|
457
|
-
|
|
479
|
+
addLiqEthDeadline,
|
|
458
480
|
{ value: ethToWrap, gasLimit: addLiqEthGasLimit },
|
|
459
481
|
);
|
|
460
482
|
console.log("[10d] addLiquidityETH tx id:", addLiqEthTx.hash);
|
|
@@ -463,11 +485,12 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
463
485
|
|
|
464
486
|
const ethSwapValue = parseUnits("0.1", 18);
|
|
465
487
|
const pathEthToToken = [wqAddressNorm, tokenAAddress];
|
|
488
|
+
const swapEthDeadline = await deadline(provider);
|
|
466
489
|
const swapEthTxReq = await routerContract.populateTransaction.swapExactETHForTokens(
|
|
467
490
|
0n,
|
|
468
491
|
pathEthToToken,
|
|
469
492
|
walletAddr,
|
|
470
|
-
|
|
493
|
+
swapEthDeadline,
|
|
471
494
|
{ value: ethSwapValue },
|
|
472
495
|
);
|
|
473
496
|
const swapEthGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...swapEthTxReq }, TX_GAS_FALLBACK);
|
|
@@ -477,7 +500,7 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
477
500
|
0n,
|
|
478
501
|
pathEthToToken,
|
|
479
502
|
walletAddr,
|
|
480
|
-
|
|
503
|
+
swapEthDeadline,
|
|
481
504
|
{ value: ethSwapValue, gasLimit: swapEthGasLimit },
|
|
482
505
|
);
|
|
483
506
|
console.log("[10e] swapExactETHForTokens tx id:", swapEthTx.hash);
|
|
@@ -529,21 +552,31 @@ describe("QuantumSwap V2 DEX full flow", () => {
|
|
|
529
552
|
assert.ok(typeof wqBalanceWallet === "bigint", "WQ balance is bigint");
|
|
530
553
|
|
|
531
554
|
// --- Summary: contract addresses and transaction hashes ---
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
console.log(` ${name}: ${addr}`);
|
|
535
|
-
}
|
|
536
|
-
console.log("\n========== TRANSACTION HASHES ==========");
|
|
537
|
-
txHashes.forEach((hash, i) => {
|
|
538
|
-
console.log(` [${i + 1}] ${hash}`);
|
|
539
|
-
});
|
|
540
|
-
console.log("\n========== TOTAL GAS USED (cumulative) ==========");
|
|
555
|
+
reportDexFlow(contractAddresses, txHashes);
|
|
556
|
+
console.log("========== TOTAL GAS USED (cumulative) ==========");
|
|
541
557
|
console.log(` ${totalGasUsed.toString()} (from ${txHashes.length} transaction receipts)`);
|
|
542
558
|
console.log("========================================\n");
|
|
543
559
|
|
|
560
|
+
// --- Test wallet token balances (after all steps) ---
|
|
561
|
+
const walletTokenABalanceRaw = await tokenA.balanceOf(walletAddr);
|
|
562
|
+
const walletTokenBBalanceRaw = await tokenB.balanceOf(walletAddr);
|
|
563
|
+
const walletTokenABalance = typeof walletTokenABalanceRaw === "bigint" ? walletTokenABalanceRaw : BigInt(String(walletTokenABalanceRaw));
|
|
564
|
+
const walletTokenBBalance = typeof walletTokenBBalanceRaw === "bigint" ? walletTokenBBalanceRaw : BigInt(String(walletTokenBBalanceRaw));
|
|
565
|
+
console.log("========== TEST WALLET TOKEN BALANCES ==========");
|
|
566
|
+
console.log(` Wallet: ${walletAddr}`);
|
|
567
|
+
console.log(` TokenA (BigCat) balance: ${walletTokenABalance.toString()} (${formatUnits(walletTokenABalance, 18)} formatted)`);
|
|
568
|
+
console.log(` TokenB (SmallDog) balance: ${walletTokenBBalance.toString()} (${formatUnits(walletTokenBBalance, 18)} formatted)`);
|
|
569
|
+
console.log("================================================\n");
|
|
570
|
+
|
|
544
571
|
// Summary assertions
|
|
545
572
|
assert.ok(isAddress(routerAddress) && isAddress(factoryAddress) && isAddress(wqAddress), "all core addresses valid");
|
|
546
573
|
assert.ok(isAddress(tokenAAddress) && isAddress(tokenBAddress), "token addresses valid");
|
|
547
574
|
assert.ok(!pairCreated || isAddress(pairAddressFromEvent), "pair address valid when pair created");
|
|
575
|
+
} catch (err) {
|
|
576
|
+
if (Object.keys(contractAddresses).length > 0 || txHashes.length > 0) {
|
|
577
|
+
reportDexFlow(contractAddresses, txHashes);
|
|
578
|
+
}
|
|
579
|
+
throw err;
|
|
580
|
+
}
|
|
548
581
|
}, { timeout: 300_000 });
|
|
549
582
|
});
|