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.
Files changed (44) hide show
  1. package/examples/_test-wallet.js +1 -3
  2. package/examples/deploy-IERC20.js +3 -4
  3. package/examples/deploy-QuantumSwapV2ERC20.js +3 -4
  4. package/examples/deploy-QuantumSwapV2Factory.js +3 -4
  5. package/examples/deploy-QuantumSwapV2Pair.js +3 -4
  6. package/examples/deploy-QuantumSwapV2Router02.js +3 -4
  7. package/examples/deploy-WQ.js +3 -4
  8. package/examples/events-IERC20.js +3 -4
  9. package/examples/events-QuantumSwapV2ERC20.js +3 -4
  10. package/examples/events-QuantumSwapV2Factory.js +3 -4
  11. package/examples/events-QuantumSwapV2Pair.js +3 -4
  12. package/examples/events-QuantumSwapV2Router02.js +3 -4
  13. package/examples/events-WQ.js +3 -4
  14. package/examples/offline-signing-IERC20.js +3 -4
  15. package/examples/offline-signing-QuantumSwapV2ERC20.js +3 -4
  16. package/examples/offline-signing-QuantumSwapV2Factory.js +3 -4
  17. package/examples/offline-signing-QuantumSwapV2Pair.js +3 -4
  18. package/examples/offline-signing-QuantumSwapV2Router02.js +3 -4
  19. package/examples/offline-signing-WQ.js +3 -4
  20. package/examples/package-lock.json +11 -20
  21. package/examples/package.json +1 -1
  22. package/examples/read-operations-IERC20.js +3 -4
  23. package/examples/read-operations-QuantumSwapV2ERC20.js +3 -4
  24. package/examples/read-operations-QuantumSwapV2Factory.js +3 -4
  25. package/examples/read-operations-QuantumSwapV2Pair.js +3 -4
  26. package/examples/read-operations-QuantumSwapV2Router02.js +3 -4
  27. package/examples/read-operations-WQ.js +3 -4
  28. package/examples/run-dex-flow-custom.js +22 -13
  29. package/examples/run-dex-flow-custom.ts +23 -13
  30. package/examples/write-operations-IERC20.js +3 -4
  31. package/examples/write-operations-QuantumSwapV2ERC20.js +3 -4
  32. package/examples/write-operations-QuantumSwapV2Factory.js +3 -4
  33. package/examples/write-operations-QuantumSwapV2Pair.js +3 -4
  34. package/examples/write-operations-QuantumSwapV2Router02.js +3 -4
  35. package/examples/write-operations-WQ.js +3 -4
  36. package/package.json +3 -4
  37. package/test/e2e/IERC20.e2e.test.js +2 -2
  38. package/test/e2e/QuantumSwapV2ERC20.e2e.test.js +2 -2
  39. package/test/e2e/QuantumSwapV2Factory.e2e.test.js +2 -2
  40. package/test/e2e/QuantumSwapV2Pair.e2e.test.js +2 -2
  41. package/test/e2e/QuantumSwapV2Router02.e2e.test.js +2 -2
  42. package/test/e2e/WQ.e2e.test.js +2 -2
  43. package/test/e2e/all-contracts.e2e.test.js +103 -72
  44. 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 { JsonRpcProvider, Wallet } = require("quantumcoin");
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 rpcUrl = process.env.QC_RPC_URL;
28
- if (!rpcUrl) {
29
- t.skip("QC_RPC_URL not provided");
30
- return;
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
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
34
- await Initialize(null);
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
- const provider = new JsonRpcProvider(rpcUrl, chainId);
37
- const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
52
+ const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
53
+ await Initialize(null);
38
54
 
39
- let deployGasLimit = 600000;
40
- try {
41
- const firstFactory = new IERC20__factory(wallet);
42
- const sampleReq = firstFactory.getDeployTransaction();
43
- const est = await provider.estimateGas({ from: wallet.address, data: sampleReq.data });
44
- deployGasLimit = Number(est + 200_000n);
45
- } catch {
46
- deployGasLimit = 6_000_000;
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
- let IERC20Inst = await (new IERC20__factory(wallet)).deploy({ gasLimit: deployGasLimit });
50
- const _deployTxIERC20 = IERC20Inst.deployTransaction();
51
- assert.ok(_deployTxIERC20 && _deployTxIERC20.hash);
52
- await _deployTxIERC20.wait(1, 600_000);
53
- const _v = await IERC20Inst.decimals();
54
- void _v;
55
- const _tx = await IERC20Inst.approve(wallet.address, 123, { gasLimit: 200000 });
56
- await _tx.wait(1, 600_000);
57
-
58
- let QuantumSwapV2ERC20Inst = await (new QuantumSwapV2ERC20__factory(wallet)).deploy({ gasLimit: deployGasLimit });
59
- const _deployTxQuantumSwapV2ERC20 = QuantumSwapV2ERC20Inst.deployTransaction();
60
- assert.ok(_deployTxQuantumSwapV2ERC20 && _deployTxQuantumSwapV2ERC20.hash);
61
- await _deployTxQuantumSwapV2ERC20.wait(1, 600_000);
62
- const _v = await QuantumSwapV2ERC20Inst.decimals();
63
- void _v;
64
- const _tx = await QuantumSwapV2ERC20Inst.approve(wallet.address, 123, { gasLimit: 200000 });
65
- await _tx.wait(1, 600_000);
66
-
67
- let QuantumSwapV2FactoryInst = await (new QuantumSwapV2Factory__factory(wallet)).deploy(wallet.address, { gasLimit: deployGasLimit });
68
- const _deployTxQuantumSwapV2Factory = QuantumSwapV2FactoryInst.deployTransaction();
69
- assert.ok(_deployTxQuantumSwapV2Factory && _deployTxQuantumSwapV2Factory.hash);
70
- await _deployTxQuantumSwapV2Factory.wait(1, 600_000);
71
- const _v = await QuantumSwapV2FactoryInst.INIT_CODE_HASH();
72
- void _v;
73
- const _tx = await QuantumSwapV2FactoryInst.createPair(wallet.address, wallet.address, { gasLimit: 200000 });
74
- await _tx.wait(1, 600_000);
75
-
76
- let QuantumSwapV2PairInst = await (new QuantumSwapV2Pair__factory(wallet)).deploy({ gasLimit: deployGasLimit });
77
- const _deployTxQuantumSwapV2Pair = QuantumSwapV2PairInst.deployTransaction();
78
- assert.ok(_deployTxQuantumSwapV2Pair && _deployTxQuantumSwapV2Pair.hash);
79
- await _deployTxQuantumSwapV2Pair.wait(1, 600_000);
80
- const _v = await QuantumSwapV2PairInst.MINIMUM_LIQUIDITY();
81
- void _v;
82
- const _tx = await QuantumSwapV2PairInst.approve(wallet.address, 123, { gasLimit: 200000 });
83
- await _tx.wait(1, 600_000);
84
-
85
- let QuantumSwapV2Router02Inst = await (new QuantumSwapV2Router02__factory(wallet)).deploy(wallet.address, wallet.address, { gasLimit: deployGasLimit });
86
- const _deployTxQuantumSwapV2Router02 = QuantumSwapV2Router02Inst.deployTransaction();
87
- assert.ok(_deployTxQuantumSwapV2Router02 && _deployTxQuantumSwapV2Router02.hash);
88
- await _deployTxQuantumSwapV2Router02.wait(1, 600_000);
89
- const _v = await QuantumSwapV2Router02Inst.WETH();
90
- void _v;
91
- const _tx = await QuantumSwapV2Router02Inst.addLiquidity(wallet.address, wallet.address, 123, 123, 123, 123, wallet.address, 123, { gasLimit: 200000 });
92
- await _tx.wait(1, 600_000);
93
-
94
- let WQInst = await (new WQ__factory(wallet)).deploy({ gasLimit: deployGasLimit });
95
- const _deployTxWQ = WQInst.deployTransaction();
96
- assert.ok(_deployTxWQ && _deployTxWQ.hash);
97
- await _deployTxWQ.wait(1, 600_000);
98
- const _v = await WQInst.decimals();
99
- void _v;
100
- const _tx = await WQInst.approve(wallet.address, 123, { gasLimit: 200000 });
101
- await _tx.wait(1, 600_000);
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
- JsonRpcProvider,
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
- const DEADLINE_OFFSET = 1200;
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 deadline() {
66
- return BigInt(Math.floor(Date.now() / 1000) + DEADLINE_OFFSET);
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 = new JsonRpcProvider(rpcUrl, chainId);
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 = new Contract(address, SIMPLE_ERC20_ABI, wallet);
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
- deadline(),
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
- deadline(),
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
- deadline(),
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
- deadline(),
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
- deadline(),
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
- deadline(),
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
- deadline(),
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
- deadline(),
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
- console.log("\n========== CONTRACT ADDRESSES ==========");
533
- for (const [name, addr] of Object.entries(contractAddresses)) {
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
  });