quantumswap 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/README.md +73 -53
- package/examples/README.md +46 -0
- package/examples/deploy-IERC20.js +5 -3
- package/examples/deploy-QuantumSwapV2ERC20.js +5 -3
- package/examples/deploy-QuantumSwapV2Factory.js +5 -3
- package/examples/deploy-QuantumSwapV2Pair.js +5 -3
- package/examples/deploy-QuantumSwapV2Router02.js +5 -3
- package/examples/deploy-WQ.js +5 -3
- package/examples/events-IERC20.js +5 -3
- package/examples/events-QuantumSwapV2ERC20.js +5 -3
- package/examples/events-QuantumSwapV2Factory.js +5 -3
- package/examples/events-QuantumSwapV2Pair.js +5 -3
- package/examples/events-QuantumSwapV2Router02.js +5 -3
- package/examples/events-WQ.js +5 -3
- package/examples/offline-signing-IERC20.js +5 -3
- package/examples/offline-signing-QuantumSwapV2ERC20.js +5 -3
- package/examples/offline-signing-QuantumSwapV2Factory.js +5 -3
- package/examples/offline-signing-QuantumSwapV2Pair.js +5 -3
- package/examples/offline-signing-QuantumSwapV2Router02.js +5 -3
- package/examples/offline-signing-WQ.js +5 -3
- package/examples/package-lock.json +62 -0
- package/examples/package.json +14 -0
- package/examples/read-operations-IERC20.js +5 -3
- package/examples/read-operations-QuantumSwapV2ERC20.js +5 -3
- package/examples/read-operations-QuantumSwapV2Factory.js +5 -3
- package/examples/read-operations-QuantumSwapV2Pair.js +5 -3
- package/examples/read-operations-QuantumSwapV2Router02.js +5 -3
- package/examples/read-operations-WQ.js +5 -3
- package/examples/run-dex-flow-custom.js +493 -0
- package/examples/run-dex-flow-custom.ts +556 -0
- package/examples/write-operations-IERC20.js +5 -3
- package/examples/write-operations-QuantumSwapV2ERC20.js +5 -3
- package/examples/write-operations-QuantumSwapV2Factory.js +5 -3
- package/examples/write-operations-QuantumSwapV2Pair.js +5 -3
- package/examples/write-operations-QuantumSwapV2Router02.js +5 -3
- package/examples/write-operations-WQ.js +5 -3
- package/package.json +8 -9
- 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 +276 -47
- package/examples/walkthrough-dex-full-flow.js +0 -226
- package/examples/walkthrough-dex-full-flow.ts +0 -231
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DEX full flow (same steps as test/e2e/dex-full-flow.e2e.test.js):
|
|
3
|
+
* 1–3) WQ, Factory, Router — COMMENTED OUT; uses pre-deployed addresses below.
|
|
4
|
+
* Uncomment the "Deploy WQ, Factory, Router" block to deploy these contracts instead.
|
|
5
|
+
* 4) Deploy BigCat and SmallDog tokens (SimpleERC20)
|
|
6
|
+
* 5) Create pair (BigCat, SmallDog); parse PairCreated
|
|
7
|
+
* 6) Reserves check (pair)
|
|
8
|
+
* 7) Add liquidity (1000 BigCat, 1000 SmallDog)
|
|
9
|
+
* 8) Quote (getAmountsOut / getAmountsIn)
|
|
10
|
+
* 9) Swap: swapExactTokensForTokens (10 BigCat → SmallDog)
|
|
11
|
+
* 10) Swap ETH: WQ deposit, create WQ/BigCat pair if needed, addLiquidityETH, swapExactETHForTokens
|
|
12
|
+
* 11) Send 100 BigCat and 100 SmallDog to another wallet
|
|
13
|
+
* Uses same gas estimate pattern as the test (estimateGasLimit / deployGasLimit with 10% buffer).
|
|
14
|
+
*
|
|
15
|
+
* Usage: node examples/run-dex-flow-custom.js
|
|
16
|
+
* Optional: QC_RPC_URL=https://public.rpc.quantumcoinapi.com QC_CHAIN_ID=123123 (for mainnet)
|
|
17
|
+
* Requires: quantumcoin package (and SimpleERC20 artifact) and RPC node.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const path = require("node:path");
|
|
21
|
+
const { Initialize } = require("quantumcoin/config");
|
|
22
|
+
const {
|
|
23
|
+
getProvider,
|
|
24
|
+
Wallet,
|
|
25
|
+
Contract,
|
|
26
|
+
ContractFactory,
|
|
27
|
+
getCreateAddress,
|
|
28
|
+
getAddress,
|
|
29
|
+
parseUnits,
|
|
30
|
+
isAddress,
|
|
31
|
+
Interface,
|
|
32
|
+
} = require("quantumcoin");
|
|
33
|
+
|
|
34
|
+
// Use https://public.rpc.quantumcoinapi.com for mainnet
|
|
35
|
+
const RPC_URL = process.env.QC_RPC_URL || "http://127.0.0.1:8545";
|
|
36
|
+
const CHAIN_ID = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
|
|
37
|
+
// Use chain block timestamp (UTC) + offset for deadline (same as dex-full-flow e2e test).
|
|
38
|
+
const DEADLINE_OFFSET = process.env.QC_DEADLINE_OFFSET ? Number(process.env.QC_DEADLINE_OFFSET) : 3600;
|
|
39
|
+
const DEPLOY_GAS_FALLBACK = 6_000_000n;
|
|
40
|
+
const TX_GAS_FALLBACK = 400_000n;
|
|
41
|
+
const GAS_BUFFER_PERCENT = 110n; // 10% buffer over estimate (same as test)
|
|
42
|
+
|
|
43
|
+
// Pre-deployed contract addresses for test release Dec 2025 (experimental). Replace with your own if needed.
|
|
44
|
+
// Uncomment the deploy block below to deploy WQ, Factory, and Router instead.
|
|
45
|
+
const WQ_ADDRESS = "0x0E49c26cd1ca19bF8ddA2C8985B96783288458754757F4C9E00a5439A7291628";
|
|
46
|
+
const FACTORY_ADDRESS = "0xbbF45a1B60044669793B444eD01Eb33e03Bb8cf3c5b6ae7887B218D05C5Cbf1d";
|
|
47
|
+
const ROUTER_ADDRESS = "0x41323EF72662185f44a03ea0ad8094a0C9e925aB1102679D8e957e838054aac5";
|
|
48
|
+
|
|
49
|
+
let SIMPLE_ERC20_ABI;
|
|
50
|
+
let SIMPLE_ERC20_BYTECODE;
|
|
51
|
+
try {
|
|
52
|
+
let artifact;
|
|
53
|
+
try {
|
|
54
|
+
artifact = require("quantumcoin/examples/sdk-generator-erc20.inline.json");
|
|
55
|
+
} catch {
|
|
56
|
+
const qcDir = path.dirname(require.resolve("quantumcoin"));
|
|
57
|
+
artifact = require(path.join(qcDir, "examples", "sdk-generator-erc20.inline.json"));
|
|
58
|
+
}
|
|
59
|
+
const simple = Array.isArray(artifact) ? artifact[0] : artifact;
|
|
60
|
+
SIMPLE_ERC20_ABI = simple.abi;
|
|
61
|
+
SIMPLE_ERC20_BYTECODE = simple.bin;
|
|
62
|
+
} catch (e) {
|
|
63
|
+
SIMPLE_ERC20_ABI = null;
|
|
64
|
+
SIMPLE_ERC20_BYTECODE = null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Returns deadline as UTC Unix timestamp: current chain block timestamp + DEADLINE_OFFSET. */
|
|
68
|
+
async function deadline(provider) {
|
|
69
|
+
const blockNumber = await provider.getBlockNumber();
|
|
70
|
+
const block = await provider.getBlock(blockNumber);
|
|
71
|
+
const blockTimestamp = block && block.timestamp != null ? Number(block.timestamp) : Math.floor(Date.now() / 1000);
|
|
72
|
+
return BigInt(blockTimestamp + DEADLINE_OFFSET);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Estimate gas via provider.estimateGas, add buffer, fallback on error (same as test). */
|
|
76
|
+
async function estimateGasLimit(provider, txRequest, fallback) {
|
|
77
|
+
try {
|
|
78
|
+
const est = await provider.estimateGas(txRequest);
|
|
79
|
+
const estBn = typeof est === "bigint" ? est : BigInt(est);
|
|
80
|
+
const withBuffer = (estBn * GAS_BUFFER_PERCENT) / 100n;
|
|
81
|
+
return withBuffer > 0n ? withBuffer : fallback;
|
|
82
|
+
} catch {
|
|
83
|
+
return fallback;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Deploy gas: estimate from getDeployTransaction().data, apply floor for large bytecode (same as test). */
|
|
88
|
+
async function deployGasLimit(provider, from, getDeployTx, fallback, bytecodeFloor) {
|
|
89
|
+
const txReq = getDeployTx();
|
|
90
|
+
if (!txReq || !txReq.data) return fallback;
|
|
91
|
+
let gas = await estimateGasLimit(provider, { from, data: txReq.data }, fallback);
|
|
92
|
+
if (bytecodeFloor && txReq.data && txReq.data.length > 40000 && gas < bytecodeFloor) {
|
|
93
|
+
gas = bytecodeFloor;
|
|
94
|
+
}
|
|
95
|
+
return gas;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function main() {
|
|
99
|
+
if (!SIMPLE_ERC20_ABI || !SIMPLE_ERC20_BYTECODE) {
|
|
100
|
+
console.error("SimpleERC20 artifact not found (quantumcoin examples/sdk-generator-erc20.inline.json).");
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
await Initialize(null);
|
|
105
|
+
// quantumswap (file:..) uses repo root's quantumcoin; initialize that instance too
|
|
106
|
+
try {
|
|
107
|
+
const qswapMain = require.resolve("quantumswap");
|
|
108
|
+
const repoRoot = path.join(path.dirname(qswapMain), "..");
|
|
109
|
+
const rootQcConfig = require(path.join(repoRoot, "node_modules", "quantumcoin", "config"));
|
|
110
|
+
if (rootQcConfig && typeof rootQcConfig.Initialize === "function") {
|
|
111
|
+
await rootQcConfig.Initialize(null);
|
|
112
|
+
}
|
|
113
|
+
} catch {
|
|
114
|
+
// ignore
|
|
115
|
+
}
|
|
116
|
+
const {
|
|
117
|
+
WQ,
|
|
118
|
+
WQ__factory,
|
|
119
|
+
QuantumSwapV2Factory,
|
|
120
|
+
QuantumSwapV2Factory__factory,
|
|
121
|
+
QuantumSwapV2Router02,
|
|
122
|
+
QuantumSwapV2Router02__factory,
|
|
123
|
+
QuantumSwapV2Pair,
|
|
124
|
+
} = require("quantumswap");
|
|
125
|
+
const provider = getProvider(RPC_URL, CHAIN_ID);
|
|
126
|
+
const TEST_WALLET_ENCRYPTED_JSON =
|
|
127
|
+
"{\"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}";
|
|
128
|
+
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
129
|
+
const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
|
|
130
|
+
const walletAddr = getAddress(wallet.address);
|
|
131
|
+
console.log("RPC:", RPC_URL, "| ChainId:", CHAIN_ID, "| Owner:", walletAddr);
|
|
132
|
+
console.log("");
|
|
133
|
+
|
|
134
|
+
let wqAddressNorm = getAddress(WQ_ADDRESS);
|
|
135
|
+
let factoryAddressNorm = getAddress(FACTORY_ADDRESS);
|
|
136
|
+
let routerAddress = getAddress(ROUTER_ADDRESS);
|
|
137
|
+
let wq;
|
|
138
|
+
let factoryContract;
|
|
139
|
+
let routerContract;
|
|
140
|
+
|
|
141
|
+
// --- 1–3) WQ, Factory, Router: use pre-deployed addresses. Uncomment block below to deploy instead. ---
|
|
142
|
+
/*
|
|
143
|
+
// Uncomment from here to deploy WQ, Factory, and Router (steps 1–3):
|
|
144
|
+
const wqFactory = new WQ__factory(wallet);
|
|
145
|
+
const wqGasLimit = await deployGasLimit(provider, walletAddr, () => wqFactory.getDeployTransaction(), DEPLOY_GAS_FALLBACK, 6_000_000n);
|
|
146
|
+
const wqDeploy = await wqFactory.deploy({ gasLimit: wqGasLimit });
|
|
147
|
+
await wqDeploy.deployTransaction().wait(1, 600_000);
|
|
148
|
+
wqAddressNorm = getAddress(wqDeploy.target);
|
|
149
|
+
console.log("1) WQ deployed:", wqAddressNorm);
|
|
150
|
+
|
|
151
|
+
const factoryFactory = new QuantumSwapV2Factory__factory(wallet);
|
|
152
|
+
const factoryGasLimit = await deployGasLimit(provider, walletAddr, () => factoryFactory.getDeployTransaction(walletAddr), DEPLOY_GAS_FALLBACK, 6_000_000n);
|
|
153
|
+
factoryContract = await factoryFactory.deploy(walletAddr, { gasLimit: factoryGasLimit });
|
|
154
|
+
await factoryContract.deployTransaction().wait(1, 600_000);
|
|
155
|
+
factoryAddressNorm = getAddress(factoryContract.target);
|
|
156
|
+
console.log("2) Factory deployed:", factoryAddressNorm);
|
|
157
|
+
|
|
158
|
+
const routerFactory = new QuantumSwapV2Router02__factory(wallet);
|
|
159
|
+
const routerGasLimit = await deployGasLimit(provider, walletAddr, () => routerFactory.getDeployTransaction(factoryAddressNorm, wqAddressNorm), DEPLOY_GAS_FALLBACK, 6_000_000n);
|
|
160
|
+
routerContract = await routerFactory.deploy(factoryAddressNorm, wqAddressNorm, { gasLimit: routerGasLimit });
|
|
161
|
+
await routerContract.deployTransaction().wait(1, 600_000);
|
|
162
|
+
routerAddress = getAddress(routerContract.target);
|
|
163
|
+
console.log("3) Router deployed:", routerAddress);
|
|
164
|
+
*/
|
|
165
|
+
// Attach to pre-deployed contracts (comment out the three lines below if you uncommented the deploy block above)
|
|
166
|
+
wq = WQ.connect(wqAddressNorm, wallet);
|
|
167
|
+
factoryContract = QuantumSwapV2Factory.connect(factoryAddressNorm, wallet);
|
|
168
|
+
routerContract = QuantumSwapV2Router02.connect(routerAddress, wallet);
|
|
169
|
+
console.log("1–3) Using pre-deployed WQ, Factory, Router");
|
|
170
|
+
console.log(" WQ:", wqAddressNorm);
|
|
171
|
+
console.log(" Factory:", factoryAddressNorm);
|
|
172
|
+
console.log(" Router:", routerAddress);
|
|
173
|
+
console.log("");
|
|
174
|
+
|
|
175
|
+
const txHashes = [];
|
|
176
|
+
|
|
177
|
+
// --- 4) Deploy BigCat and SmallDog tokens ---
|
|
178
|
+
console.log("4) Deploying BigCat and SmallDog tokens...");
|
|
179
|
+
const initialSupply = parseUnits("1000000", 18);
|
|
180
|
+
const simpleErc20Factory = new ContractFactory(SIMPLE_ERC20_ABI, SIMPLE_ERC20_BYTECODE, wallet);
|
|
181
|
+
const deploySimpleErc20 = async (name, symbol) => {
|
|
182
|
+
const tx = simpleErc20Factory.getDeployTransaction(name, symbol, initialSupply);
|
|
183
|
+
const nonce = await provider.getTransactionCount(walletAddr, "pending");
|
|
184
|
+
const address = getCreateAddress({ from: walletAddr, nonce });
|
|
185
|
+
const gasLimit = await estimateGasLimit(provider, { from: walletAddr, data: tx.data }, DEPLOY_GAS_FALLBACK);
|
|
186
|
+
const resp = await wallet.sendTransaction({ ...tx, nonce, gasLimit });
|
|
187
|
+
await resp.wait(1, 600_000);
|
|
188
|
+
const contract = new Contract(address, SIMPLE_ERC20_ABI, wallet);
|
|
189
|
+
contract._deployTx = resp;
|
|
190
|
+
return contract;
|
|
191
|
+
};
|
|
192
|
+
const bigCat = await deploySimpleErc20("BigCat", "BCAT");
|
|
193
|
+
const smallDog = await deploySimpleErc20("SmallDog", "SDOG");
|
|
194
|
+
txHashes.push(bigCat._deployTx.hash);
|
|
195
|
+
txHashes.push(smallDog._deployTx.hash);
|
|
196
|
+
const bigCatAddress = getAddress(bigCat.target);
|
|
197
|
+
const smallDogAddress = getAddress(smallDog.target);
|
|
198
|
+
console.log(" BigCat:", bigCatAddress);
|
|
199
|
+
console.log(" SmallDog:", smallDogAddress);
|
|
200
|
+
console.log("");
|
|
201
|
+
|
|
202
|
+
// --- 5) Create pair (BigCat, SmallDog) ---
|
|
203
|
+
console.log("5) Creating pair (BigCat, SmallDog)...");
|
|
204
|
+
const createPairTxReq = await factoryContract.populateTransaction.createPair(bigCatAddress, smallDogAddress);
|
|
205
|
+
const createPairGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...createPairTxReq }, TX_GAS_FALLBACK);
|
|
206
|
+
const createPairTx = await factoryContract.createPair(bigCatAddress, smallDogAddress, { gasLimit: createPairGasLimit });
|
|
207
|
+
txHashes.push(createPairTx.hash);
|
|
208
|
+
const createPairReceipt = await createPairTx.wait(1, 600_000);
|
|
209
|
+
let pairAddressFromEvent = null;
|
|
210
|
+
try {
|
|
211
|
+
pairAddressFromEvent = getAddress(await factoryContract.getPair(bigCatAddress, smallDogAddress));
|
|
212
|
+
} catch {
|
|
213
|
+
pairAddressFromEvent = null;
|
|
214
|
+
}
|
|
215
|
+
const zeroAddress32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
216
|
+
const pairCreated =
|
|
217
|
+
pairAddressFromEvent &&
|
|
218
|
+
isAddress(pairAddressFromEvent) &&
|
|
219
|
+
pairAddressFromEvent !== zeroAddress32 &&
|
|
220
|
+
pairAddressFromEvent !== "0x" + "0".repeat(64);
|
|
221
|
+
if (pairCreated) {
|
|
222
|
+
console.log(" Pair:", pairAddressFromEvent);
|
|
223
|
+
if (Array.isArray(createPairReceipt.logs) && createPairReceipt.logs.length >= 1) {
|
|
224
|
+
const factoryIface = new Interface(QuantumSwapV2Factory.abi);
|
|
225
|
+
for (const log of createPairReceipt.logs) {
|
|
226
|
+
if (!log.topics || !log.data) continue;
|
|
227
|
+
try {
|
|
228
|
+
const parsed = factoryIface.parseLog({ topics: log.topics, data: log.data });
|
|
229
|
+
if (parsed && parsed.name === "PairCreated") break;
|
|
230
|
+
} catch {
|
|
231
|
+
// not this contract's event
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} else {
|
|
236
|
+
console.log(" Pair not created (getPair returned zero or invalid).");
|
|
237
|
+
}
|
|
238
|
+
console.log("");
|
|
239
|
+
|
|
240
|
+
// --- 6) Reserves (pair) ---
|
|
241
|
+
if (pairCreated) {
|
|
242
|
+
const pairContract = QuantumSwapV2Pair.connect(pairAddressFromEvent, provider);
|
|
243
|
+
const reservesResult = await pairContract.getReserves();
|
|
244
|
+
const reserve0 = Array.isArray(reservesResult) ? reservesResult[0] : reservesResult;
|
|
245
|
+
const reserve1 = Array.isArray(reservesResult) ? reservesResult[1] : 0n;
|
|
246
|
+
console.log("6) Pair reserves (before liquidity): reserve0=" + reserve0.toString() + ", reserve1=" + reserve1.toString());
|
|
247
|
+
console.log("");
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// --- 7) Add liquidity (1000 BigCat, 1000 SmallDog) ---
|
|
251
|
+
if (pairCreated) {
|
|
252
|
+
console.log("7) Adding liquidity (1000 BigCat, 1000 SmallDog)...");
|
|
253
|
+
const amountADesired = parseUnits("1000", 18);
|
|
254
|
+
const amountBDesired = parseUnits("1000", 18);
|
|
255
|
+
const approveAmount = amountADesired > amountBDesired ? amountADesired : amountBDesired;
|
|
256
|
+
const approveTxReqA = await bigCat.populateTransaction.approve(routerAddress, approveAmount);
|
|
257
|
+
const approveGasA = await estimateGasLimit(provider, { from: walletAddr, ...approveTxReqA }, TX_GAS_FALLBACK);
|
|
258
|
+
const approveA = await bigCat.approve(routerAddress, approveAmount, { gasLimit: approveGasA });
|
|
259
|
+
txHashes.push(approveA.hash);
|
|
260
|
+
await approveA.wait(1, 600_000);
|
|
261
|
+
const approveTxReqB = await smallDog.populateTransaction.approve(routerAddress, approveAmount);
|
|
262
|
+
const approveGasB = await estimateGasLimit(provider, { from: walletAddr, ...approveTxReqB }, TX_GAS_FALLBACK);
|
|
263
|
+
const approveB = await smallDog.approve(routerAddress, approveAmount, { gasLimit: approveGasB });
|
|
264
|
+
txHashes.push(approveB.hash);
|
|
265
|
+
await approveB.wait(1, 600_000);
|
|
266
|
+
const addLiqDeadline = await deadline(provider);
|
|
267
|
+
const addLiqTxReq = await routerContract.populateTransaction.addLiquidity(
|
|
268
|
+
bigCatAddress,
|
|
269
|
+
smallDogAddress,
|
|
270
|
+
amountADesired,
|
|
271
|
+
amountBDesired,
|
|
272
|
+
0n,
|
|
273
|
+
0n,
|
|
274
|
+
walletAddr,
|
|
275
|
+
addLiqDeadline,
|
|
276
|
+
);
|
|
277
|
+
const addLiqGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...addLiqTxReq }, TX_GAS_FALLBACK);
|
|
278
|
+
const addLiqTx = await routerContract.addLiquidity(
|
|
279
|
+
bigCatAddress,
|
|
280
|
+
smallDogAddress,
|
|
281
|
+
amountADesired,
|
|
282
|
+
amountBDesired,
|
|
283
|
+
0n,
|
|
284
|
+
0n,
|
|
285
|
+
walletAddr,
|
|
286
|
+
addLiqDeadline,
|
|
287
|
+
{ gasLimit: addLiqGasLimit },
|
|
288
|
+
);
|
|
289
|
+
txHashes.push(addLiqTx.hash);
|
|
290
|
+
await addLiqTx.wait(1, 600_000);
|
|
291
|
+
const pairContract = QuantumSwapV2Pair.connect(pairAddressFromEvent, provider);
|
|
292
|
+
const reservesAfter = await pairContract.getReserves();
|
|
293
|
+
const res0 = Array.isArray(reservesAfter) ? reservesAfter[0] : reservesAfter;
|
|
294
|
+
const res1 = Array.isArray(reservesAfter) ? reservesAfter[1] : 0n;
|
|
295
|
+
console.log(" Reserves after addLiquidity:", res0.toString(), res1.toString());
|
|
296
|
+
console.log("");
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// --- 8) Quote (getAmountsOut / getAmountsIn) ---
|
|
300
|
+
const pathBigCatToSmallDog = [bigCatAddress, smallDogAddress];
|
|
301
|
+
const amountIn = parseUnits("1", 18);
|
|
302
|
+
let amountsOut = [];
|
|
303
|
+
try {
|
|
304
|
+
amountsOut = await routerContract.getAmountsOut(amountIn, pathBigCatToSmallDog);
|
|
305
|
+
} catch {
|
|
306
|
+
// may revert with no liquidity
|
|
307
|
+
}
|
|
308
|
+
if (Array.isArray(amountsOut) && amountsOut.length >= 2) {
|
|
309
|
+
console.log("8) Quote getAmountsOut(1 BigCat):", amountsOut[1].toString(), "SmallDog");
|
|
310
|
+
}
|
|
311
|
+
let amountsIn = [];
|
|
312
|
+
try {
|
|
313
|
+
amountsIn = await routerContract.getAmountsIn(parseUnits("1", 18), pathBigCatToSmallDog);
|
|
314
|
+
} catch {
|
|
315
|
+
// may revert with no liquidity
|
|
316
|
+
}
|
|
317
|
+
if (Array.isArray(amountsIn) && amountsIn.length >= 1) {
|
|
318
|
+
console.log(" getAmountsIn(1 SmallDog):", amountsIn[0].toString(), "BigCat");
|
|
319
|
+
}
|
|
320
|
+
console.log("");
|
|
321
|
+
|
|
322
|
+
// --- 9) Swap: 10 BigCat → SmallDog ---
|
|
323
|
+
if (pairCreated) {
|
|
324
|
+
console.log("9) Swapping 10 BigCat for SmallDog...");
|
|
325
|
+
const swapAmountIn = parseUnits("10", 18);
|
|
326
|
+
const pathSwap = [bigCatAddress, smallDogAddress];
|
|
327
|
+
const approveSwapTxReq = await bigCat.populateTransaction.approve(routerAddress, swapAmountIn);
|
|
328
|
+
const approveSwapGas = await estimateGasLimit(provider, { from: walletAddr, ...approveSwapTxReq }, TX_GAS_FALLBACK);
|
|
329
|
+
const approveSwap = await bigCat.approve(routerAddress, swapAmountIn, { gasLimit: approveSwapGas });
|
|
330
|
+
txHashes.push(approveSwap.hash);
|
|
331
|
+
await approveSwap.wait(1, 600_000);
|
|
332
|
+
const swapDeadline = await deadline(provider);
|
|
333
|
+
const swapTxReq = await routerContract.populateTransaction.swapExactTokensForTokens(
|
|
334
|
+
swapAmountIn,
|
|
335
|
+
0n,
|
|
336
|
+
pathSwap,
|
|
337
|
+
walletAddr,
|
|
338
|
+
swapDeadline,
|
|
339
|
+
);
|
|
340
|
+
const swapGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...swapTxReq }, TX_GAS_FALLBACK);
|
|
341
|
+
const swapTx = await routerContract.swapExactTokensForTokens(
|
|
342
|
+
swapAmountIn,
|
|
343
|
+
0n,
|
|
344
|
+
pathSwap,
|
|
345
|
+
walletAddr,
|
|
346
|
+
swapDeadline,
|
|
347
|
+
{ gasLimit: swapGasLimit },
|
|
348
|
+
);
|
|
349
|
+
txHashes.push(swapTx.hash);
|
|
350
|
+
await swapTx.wait(1, 600_000);
|
|
351
|
+
const smallDogBalanceRaw = await smallDog.balanceOf(walletAddr);
|
|
352
|
+
const smallDogBalance = typeof smallDogBalanceRaw === "bigint" ? smallDogBalanceRaw : BigInt(String(smallDogBalanceRaw));
|
|
353
|
+
console.log(" SmallDog balance after swap:", smallDogBalance.toString());
|
|
354
|
+
console.log("");
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// --- 10) Swap ETH: WQ deposit, WQ/BigCat pair, addLiquidityETH, swapExactETHForTokens ---
|
|
358
|
+
if (pairCreated) {
|
|
359
|
+
console.log("10) Swap ETH: wrap, add WQ/BigCat liquidity, swapExactETHForTokens...");
|
|
360
|
+
const ethToWrap = parseUnits("1", 18);
|
|
361
|
+
const depositTxReq = await wq.populateTransaction.deposit({ value: ethToWrap });
|
|
362
|
+
const depositGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...depositTxReq }, TX_GAS_FALLBACK);
|
|
363
|
+
const depositTx = await wq.deposit({ value: ethToWrap, gasLimit: depositGasLimit });
|
|
364
|
+
txHashes.push(depositTx.hash);
|
|
365
|
+
await depositTx.wait(1, 600_000);
|
|
366
|
+
|
|
367
|
+
let pairWqBigCatAddr = null;
|
|
368
|
+
try {
|
|
369
|
+
const raw = await factoryContract.getPair(wqAddressNorm, bigCatAddress);
|
|
370
|
+
pairWqBigCatAddr = getAddress(raw);
|
|
371
|
+
} catch {
|
|
372
|
+
pairWqBigCatAddr = null;
|
|
373
|
+
}
|
|
374
|
+
const zeroAddr = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
375
|
+
const hasWqPair =
|
|
376
|
+
pairWqBigCatAddr && isAddress(pairWqBigCatAddr) && pairWqBigCatAddr !== zeroAddr && pairWqBigCatAddr !== "0x" + "0".repeat(64);
|
|
377
|
+
if (!hasWqPair) {
|
|
378
|
+
const createWqPairTxReq = await factoryContract.populateTransaction.createPair(wqAddressNorm, bigCatAddress);
|
|
379
|
+
const createWqPairGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...createWqPairTxReq }, TX_GAS_FALLBACK);
|
|
380
|
+
const createWqPairTx = await factoryContract.createPair(wqAddressNorm, bigCatAddress, { gasLimit: createWqPairGasLimit });
|
|
381
|
+
txHashes.push(createWqPairTx.hash);
|
|
382
|
+
await createWqPairTx.wait(1, 600_000);
|
|
383
|
+
pairWqBigCatAddr = getAddress(await factoryContract.getPair(wqAddressNorm, bigCatAddress));
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const tokenForEthLiq = parseUnits("500", 18);
|
|
387
|
+
const approveBigCatTxReq = await bigCat.populateTransaction.approve(routerAddress, tokenForEthLiq);
|
|
388
|
+
const approveBigCatGas = await estimateGasLimit(provider, { from: walletAddr, ...approveBigCatTxReq }, TX_GAS_FALLBACK);
|
|
389
|
+
const approveBigCat = await bigCat.approve(routerAddress, tokenForEthLiq, { gasLimit: approveBigCatGas });
|
|
390
|
+
txHashes.push(approveBigCat.hash);
|
|
391
|
+
await approveBigCat.wait(1, 600_000);
|
|
392
|
+
const addLiqEthDeadline = await deadline(provider);
|
|
393
|
+
const addLiqEthTxReq = await routerContract.populateTransaction.addLiquidityETH(
|
|
394
|
+
bigCatAddress,
|
|
395
|
+
tokenForEthLiq,
|
|
396
|
+
0n,
|
|
397
|
+
0n,
|
|
398
|
+
walletAddr,
|
|
399
|
+
addLiqEthDeadline,
|
|
400
|
+
{ value: ethToWrap },
|
|
401
|
+
);
|
|
402
|
+
const addLiqEthGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...addLiqEthTxReq }, TX_GAS_FALLBACK);
|
|
403
|
+
const addLiqEthTx = await routerContract.addLiquidityETH(
|
|
404
|
+
bigCatAddress,
|
|
405
|
+
tokenForEthLiq,
|
|
406
|
+
0n,
|
|
407
|
+
0n,
|
|
408
|
+
walletAddr,
|
|
409
|
+
addLiqEthDeadline,
|
|
410
|
+
{ value: ethToWrap, gasLimit: addLiqEthGasLimit },
|
|
411
|
+
);
|
|
412
|
+
txHashes.push(addLiqEthTx.hash);
|
|
413
|
+
await addLiqEthTx.wait(1, 600_000);
|
|
414
|
+
|
|
415
|
+
const ethSwapValue = parseUnits("0.1", 18);
|
|
416
|
+
const pathEthToToken = [wqAddressNorm, bigCatAddress];
|
|
417
|
+
const swapEthDeadline = await deadline(provider);
|
|
418
|
+
const swapEthTxReq = await routerContract.populateTransaction.swapExactETHForTokens(
|
|
419
|
+
0n,
|
|
420
|
+
pathEthToToken,
|
|
421
|
+
walletAddr,
|
|
422
|
+
swapEthDeadline,
|
|
423
|
+
{ value: ethSwapValue },
|
|
424
|
+
);
|
|
425
|
+
const swapEthGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...swapEthTxReq }, TX_GAS_FALLBACK);
|
|
426
|
+
const swapEthTx = await routerContract.swapExactETHForTokens(
|
|
427
|
+
0n,
|
|
428
|
+
pathEthToToken,
|
|
429
|
+
walletAddr,
|
|
430
|
+
swapEthDeadline,
|
|
431
|
+
{ value: ethSwapValue, gasLimit: swapEthGasLimit },
|
|
432
|
+
);
|
|
433
|
+
txHashes.push(swapEthTx.hash);
|
|
434
|
+
await swapEthTx.wait(1, 600_000);
|
|
435
|
+
const bigCatBalanceRaw = await bigCat.balanceOf(walletAddr);
|
|
436
|
+
console.log(" BigCat balance after ETH swap:", (typeof bigCatBalanceRaw === "bigint" ? bigCatBalanceRaw : BigInt(String(bigCatBalanceRaw))).toString());
|
|
437
|
+
console.log("");
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// --- 11) Send 100 BigCat and 100 SmallDog to another wallet ---
|
|
441
|
+
console.log("11) Sending 100 BigCat and 100 SmallDog to another wallet...");
|
|
442
|
+
const otherWallet = Wallet.createRandom().connect(provider);
|
|
443
|
+
const otherAddr = getAddress(otherWallet.address);
|
|
444
|
+
const transferAmount = parseUnits("100", 18);
|
|
445
|
+
const transferATxReq = await bigCat.populateTransaction.transfer(otherAddr, transferAmount);
|
|
446
|
+
const transferAGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...transferATxReq }, TX_GAS_FALLBACK);
|
|
447
|
+
const transferATx = await bigCat.transfer(otherAddr, transferAmount, { gasLimit: transferAGasLimit });
|
|
448
|
+
txHashes.push(transferATx.hash);
|
|
449
|
+
await transferATx.wait(1, 600_000);
|
|
450
|
+
const transferBTxReq = await smallDog.populateTransaction.transfer(otherAddr, transferAmount);
|
|
451
|
+
const transferBGasLimit = await estimateGasLimit(provider, { from: walletAddr, ...transferBTxReq }, TX_GAS_FALLBACK);
|
|
452
|
+
const transferBTx = await smallDog.transfer(otherAddr, transferAmount, { gasLimit: transferBGasLimit });
|
|
453
|
+
txHashes.push(transferBTx.hash);
|
|
454
|
+
await transferBTx.wait(1, 600_000);
|
|
455
|
+
const otherBigCatRaw = await bigCat.balanceOf(otherAddr);
|
|
456
|
+
const otherSmallDogRaw = await smallDog.balanceOf(otherAddr);
|
|
457
|
+
console.log(" Other wallet BigCat balance:", (typeof otherBigCatRaw === "bigint" ? otherBigCatRaw : BigInt(String(otherBigCatRaw))).toString());
|
|
458
|
+
console.log(" Other wallet SmallDog balance:", (typeof otherSmallDogRaw === "bigint" ? otherSmallDogRaw : BigInt(String(otherSmallDogRaw))).toString());
|
|
459
|
+
console.log("");
|
|
460
|
+
|
|
461
|
+
// --- Summary: contract addresses ---
|
|
462
|
+
console.log("========== CONTRACT ADDRESSES ==========");
|
|
463
|
+
console.log(" wallet:", walletAddr);
|
|
464
|
+
console.log(" WQ:", wqAddressNorm);
|
|
465
|
+
console.log(" Factory:", factoryAddressNorm);
|
|
466
|
+
console.log(" Router:", routerAddress);
|
|
467
|
+
console.log(" BigCat:", bigCatAddress);
|
|
468
|
+
console.log(" SmallDog:", smallDogAddress);
|
|
469
|
+
console.log(" PairBigCatSmallDog:", pairCreated ? pairAddressFromEvent : "(not created)");
|
|
470
|
+
if (pairCreated) {
|
|
471
|
+
try {
|
|
472
|
+
const pairWq = await factoryContract.getPair(wqAddressNorm, bigCatAddress);
|
|
473
|
+
const pairWqAddr = getAddress(pairWq);
|
|
474
|
+
if (pairWqAddr && pairWqAddr !== zeroAddress32) console.log(" PairWqBigCat:", pairWqAddr);
|
|
475
|
+
} catch {
|
|
476
|
+
// ignore
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
console.log(" OtherWallet:", otherAddr);
|
|
480
|
+
console.log("========================================");
|
|
481
|
+
console.log("");
|
|
482
|
+
console.log("========== TRANSACTION HASHES ==========");
|
|
483
|
+
txHashes.forEach((hash, i) => {
|
|
484
|
+
console.log(" [" + (i + 1) + "] " + hash);
|
|
485
|
+
});
|
|
486
|
+
console.log("========================================");
|
|
487
|
+
console.log("Done.");
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
main().catch((err) => {
|
|
491
|
+
console.error(err);
|
|
492
|
+
process.exit(1);
|
|
493
|
+
});
|