punkkit-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +47 -0
- package/.gitmodules +3 -0
- package/README.md +158 -0
- package/config/auction.config.ts +40 -0
- package/config/env.config.ts +204 -0
- package/config/uniswap.config.ts +107 -0
- package/config/voucher.config.ts +10 -0
- package/contracts/MutiVoucher.sol +78 -0
- package/contracts/auction/ChainXAuction.sol +177 -0
- package/contracts/auction/ChainXAuctionV2.sol +672 -0
- package/contracts/auction/ChainXWrappedETH.sol +80 -0
- package/contracts/auction/ChainYLiquidityManager.sol +57 -0
- package/contracts/auction/ChainYShadowETH.sol +148 -0
- package/contracts/auction/ChainYVault.sol +195 -0
- package/contracts/auction/ChainYVaultCoinbase.sol +276 -0
- package/contracts/auction/ChainYVaultV2.sol +318 -0
- package/contracts/auction/coinbase-and-stake/README.md +55 -0
- package/contracts/auction/coinbase-and-stake/coinbase.sol +142 -0
- package/contracts/auction/coinbase-and-stake/invokeCoinbase.sol +159 -0
- package/contracts/auction/coinbase-and-stake/invokeStake.sol +82 -0
- package/contracts/auction/coinbase-and-stake/stake.sol +92 -0
- package/contracts/auction/interfaces/IUniswapV2Factory.sol +15 -0
- package/contracts/auction/interfaces/IUniswapV2Pair.sol +53 -0
- package/contracts/auction/interfaces/IUniswapV2Router02.sol +25 -0
- package/contracts/auction/interfaces/IUnlockStrategy.sol +18 -0
- package/contracts/auction/libraries/EventParser.sol +32 -0
- package/contracts/auction/libraries/TransactionParser.sol +70 -0
- package/contracts/auction/strategies/MatchResultWithdrawnStrategy.sol +33 -0
- package/contracts/auction/utils/BytesLib.sol +180 -0
- package/contracts/auction/utils/RLPReader.sol +355 -0
- package/contracts/uniswap/Create2.sol +80 -0
- package/contracts/uniswap/DynamicFee.sol +100 -0
- package/contracts/uniswap/Example.sol +35 -0
- package/contracts/uniswap/HookMiner.sol +52 -0
- package/contracts/uniswap/LimitOrder.sol +486 -0
- package/contracts/uniswap/LiquidPool.sol +179 -0
- package/contracts/uniswap/MockERC20.sol +20 -0
- package/hardhat.config.ts +35 -0
- package/ignition/modules/LimitOrder.ts +33 -0
- package/package.json +32 -0
- package/scripts/auction/deploy.ts +23 -0
- package/scripts/auction/deployCoinbase.ts +21 -0
- package/scripts/auction/deployXAuction.ts +23 -0
- package/scripts/auction/deployYVault.ts +22 -0
- package/scripts/deploy_voucher.ts +20 -0
- package/scripts/uniswap/deploy/deploy.ts +65 -0
- package/scripts/uniswap/deploy/deploy_create2.ts +11 -0
- package/scripts/uniswap/deploy/deploy_example.ts +35 -0
- package/scripts/uniswap/deploy/deploy_hooks.ts +74 -0
- package/scripts/uniswap/deploy/deploy_mockERC20.ts +42 -0
- package/scripts/uniswap/deploy/help.ts +96 -0
- package/scripts/uniswap/deploy/init.ts +70 -0
- package/src/auction/chainXAuction.ts +209 -0
- package/src/auction/chainYVault.ts +153 -0
- package/src/auction/event.ts +19 -0
- package/src/auction/serialize.ts +162 -0
- package/src/auction/type.ts +71 -0
- package/src/lib/signer.ts +20 -0
- package/src/lib/unlock.ts +14 -0
- package/src/uniswap/1-marketprice/addLiquidity.ts +80 -0
- package/src/uniswap/1-marketprice/removeLiquidity.ts +63 -0
- package/src/uniswap/1-marketprice/swap.ts +100 -0
- package/src/uniswap/2-limitorder/kill.ts +70 -0
- package/src/uniswap/2-limitorder/place.ts +93 -0
- package/src/uniswap/2-limitorder/withdraw.ts +78 -0
- package/src/uniswap/3-dynamicfee/dynamicfee.ts +321 -0
- package/src/uniswap/lib/ERC20.ts +49 -0
- package/src/uniswap/lib/contract.ts +18 -0
- package/src/uniswap/lib/limitOrder.ts +40 -0
- package/src/uniswap/lib/liqCalculation.ts +152 -0
- package/src/uniswap/lib/listen.ts +57 -0
- package/src/uniswap/lib/pool.ts +62 -0
- package/src/uniswap/lib/swap.ts +8 -0
- package/src/uniswap/lib/types.ts +21 -0
- package/src/uniswap/lib/utils.ts +26 -0
- package/src/uniswap/playgroud/abiencode.ts +21 -0
- package/src/uniswap/playgroud/amount0.ts +47 -0
- package/src/uniswap/playgroud/errordecode.ts +54 -0
- package/src/uniswap/playgroud/errorsigs.ts +86 -0
- package/src/voucher.ts +122 -0
- package/test/auction/ChainXAuctionV2.test.ts +265 -0
- package/test/auction/ChainYVaultV2.test.js +163 -0
- package/test/auction/ChainYVaultV2.test.ts +183 -0
- package/test/auction/auction.test.ts +106 -0
- package/test/connect_punk.test.ts +26 -0
- package/test/create2.test.ts +44 -0
- package/test/normal.ts +43 -0
- package/test/test-config.ts +18 -0
- package/test/uniswap/example.test.ts +62 -0
- package/test/uniswap/limitOrder.test.ts +184 -0
- package/test/uniswap/mockERC20.test.ts +142 -0
- package/test/voucher_hardhat.test.ts +120 -0
- package/test/voucher_punk.test.ts +83 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { MatchResultWithdrawnEvent } from "./event";
|
|
2
|
+
|
|
3
|
+
// * chainXAuction 相关参数
|
|
4
|
+
export interface CreateAuctionParams {
|
|
5
|
+
seller: string;
|
|
6
|
+
sourceChainId: number;
|
|
7
|
+
activeAuctionCount: bigint;
|
|
8
|
+
auctionType: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface PlaceBidParams {
|
|
12
|
+
auctionId: string;
|
|
13
|
+
seller: string;
|
|
14
|
+
valueEth: string;
|
|
15
|
+
secretText?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RevealBidParams {
|
|
19
|
+
auctionId: string;
|
|
20
|
+
valueEth: string;
|
|
21
|
+
saltHex?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface RevealLockParams {
|
|
25
|
+
auctionId: string;
|
|
26
|
+
lockId: string;
|
|
27
|
+
valueEth: string;
|
|
28
|
+
saltHex?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SubmitMatchResultsParams {
|
|
32
|
+
auctionId: string;
|
|
33
|
+
lockIds: string[];
|
|
34
|
+
bidders: string[];
|
|
35
|
+
finalValuesEth: string[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ChallengeMatchResultParams {
|
|
39
|
+
auctionId: string;
|
|
40
|
+
bidder: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface WithdrawMatchResultParams {
|
|
44
|
+
auctionId: string;
|
|
45
|
+
lockId: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// * chainYVaultClient 相关参数
|
|
49
|
+
|
|
50
|
+
export interface CreateAuctionConfigParams {
|
|
51
|
+
auctionType: number;
|
|
52
|
+
baseAmountEth: string;
|
|
53
|
+
extendSeconds: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface SetUnlockStrategyParams {
|
|
57
|
+
auctionType: number;
|
|
58
|
+
strategyAddress: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface CreateAuctionParams {
|
|
62
|
+
configId: number;
|
|
63
|
+
secretText: string;
|
|
64
|
+
expirationTs: number;
|
|
65
|
+
amountEth: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface UnlockTokensParams {
|
|
69
|
+
lockId: string;
|
|
70
|
+
rawReceipt: string;
|
|
71
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Wallet, providers } from "ethers";
|
|
2
|
+
|
|
3
|
+
export function addressFromPrivateKey(pk: string): string {
|
|
4
|
+
return new Wallet(pk).address;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function getSigner(
|
|
8
|
+
rpcUrl: string,
|
|
9
|
+
privateKey: string
|
|
10
|
+
): Wallet {
|
|
11
|
+
if (!privateKey) {
|
|
12
|
+
throw new Error("PRIVATE_KEY not set");
|
|
13
|
+
}
|
|
14
|
+
const provider = new providers.JsonRpcProvider(rpcUrl);
|
|
15
|
+
return new Wallet(privateKey, provider);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getProvider(rpcUrl:string): providers.JsonRpcProvider {
|
|
19
|
+
return new providers.JsonRpcProvider(rpcUrl);
|
|
20
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ethers } from "ethers";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
|
|
4
|
+
const keystore = fs.readFileSync("keystore.json", "utf-8");
|
|
5
|
+
const password = "mypassword";
|
|
6
|
+
|
|
7
|
+
async function loadWallet() {
|
|
8
|
+
const wallet = await ethers.Wallet.fromEncryptedJson(keystore, password);
|
|
9
|
+
console.log("Private Key:", wallet.privateKey);
|
|
10
|
+
console.log("Public Key:", wallet.publicKey);
|
|
11
|
+
console.log("Address:", wallet.address);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
loadWallet();
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { ethers } from "hardhat";
|
|
2
|
+
import { Wallet, Contract } from "ethers";
|
|
3
|
+
|
|
4
|
+
import { CONTRACT_ADDRESSES, POOL_KEYS, RPC_URL, PRIVATE_KEY, INITIAL_LIQUIDITY } from "../../../config/uniswap.config";
|
|
5
|
+
import { ModifyPositionParams, PoolKey } from "../lib/types";
|
|
6
|
+
import { getPoolPrice, getPoolSqrtPrice, modifyPosition } from "../lib/pool";
|
|
7
|
+
import { getERC20Balance, isApproved, approveERC20 } from "../lib/ERC20";
|
|
8
|
+
import { calculateLiqDelta, calculateTickFromPriceWithSpacing } from "../lib/liqCalculation";
|
|
9
|
+
import { getContract } from "../lib/contract";
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async function addLiq(wallet: Wallet, priceLower: number, priceUpper: number, amount0: bigint, amount1: bigint, poolKey: PoolKey): Promise<void> {
|
|
17
|
+
// 合约对象实例化
|
|
18
|
+
const token0 = await getContract(wallet, "Token0");
|
|
19
|
+
const token1 = await getContract(wallet, "Token1");
|
|
20
|
+
const liqPool = await getContract(wallet, "LiquidPool");
|
|
21
|
+
|
|
22
|
+
const ticklow = calculateTickFromPriceWithSpacing(priceLower, poolKey.tickSpacing);
|
|
23
|
+
const tickhigh = calculateTickFromPriceWithSpacing(priceUpper, poolKey.tickSpacing);
|
|
24
|
+
const sqrtCurrent = await getPoolSqrtPrice(liqPool);
|
|
25
|
+
|
|
26
|
+
const [liqDelta, amount0Add, amount1Add] = calculateLiqDelta(ticklow, sqrtCurrent, tickhigh, amount0, amount1);
|
|
27
|
+
|
|
28
|
+
let modifyPositionParams: ModifyPositionParams = {
|
|
29
|
+
tickLower: ticklow,
|
|
30
|
+
tickUpper: tickhigh,
|
|
31
|
+
liquidityDelta: liqDelta,
|
|
32
|
+
};
|
|
33
|
+
console.log("Modify position params:", modifyPositionParams);
|
|
34
|
+
|
|
35
|
+
// Check ERC20 token balances and approve if necessary
|
|
36
|
+
const liqPoolAddr = liqPool.address;
|
|
37
|
+
if (!(await isApproved(token0, wallet.address, liqPoolAddr, amount0Add))) {
|
|
38
|
+
await approveERC20(token0, liqPoolAddr, amount0Add);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!(await isApproved(token1, wallet.address, liqPoolAddr, amount1Add))) {
|
|
42
|
+
await approveERC20(token1, liqPoolAddr, amount1Add);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await modifyPosition(liqPool, modifyPositionParams, "0x00");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function main(): Promise<void> {
|
|
49
|
+
const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
|
|
50
|
+
const wallet = new Wallet(PRIVATE_KEY, provider);
|
|
51
|
+
const tokenContractName = "MockERC20";
|
|
52
|
+
const liqPoolAddress = CONTRACT_ADDRESSES.LiquidPool;
|
|
53
|
+
|
|
54
|
+
const token0 = await getContract(wallet, "Token0");
|
|
55
|
+
const token1 = await getContract(wallet, "Token1");
|
|
56
|
+
const liqPool = await getContract(wallet, "LiquidPool");
|
|
57
|
+
|
|
58
|
+
const token0Before = (await getERC20Balance(token0, wallet.address)).valueOf();
|
|
59
|
+
const token1Before = (await getERC20Balance(token1, wallet.address)).valueOf();
|
|
60
|
+
let poolPrice = await getPoolPrice(liqPool);
|
|
61
|
+
console.log(`Current price of pool before adding liquidity is ${poolPrice}`);
|
|
62
|
+
|
|
63
|
+
// 如果价格比当前区间最大值还要大,则只会添加token1。比当前价格区间还要小,则只会添加token0
|
|
64
|
+
const priceLower = 0.5;
|
|
65
|
+
const priceUpper = 1.5;
|
|
66
|
+
const amount0 = INITIAL_LIQUIDITY;
|
|
67
|
+
const amount1 = INITIAL_LIQUIDITY;
|
|
68
|
+
await addLiq(wallet, priceLower, priceUpper, amount0, amount1, POOL_KEYS.limitOrderPoolKey);
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
const token0After = (await getERC20Balance(token0, wallet.address)).valueOf();
|
|
72
|
+
const token1After = (await getERC20Balance(token1, wallet.address)).valueOf();
|
|
73
|
+
console.log("Token0 change:", token0After - token0Before);
|
|
74
|
+
console.log("Token1 change:", token1After - token1Before);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
main().catch((error) => {
|
|
78
|
+
console.error(error);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Contract, Wallet,providers } from "ethers";
|
|
2
|
+
import { CONTRACT_ADDRESSES, POOL_KEYS, RPC_URL, PRIVATE_KEY, SALT } from "../../../config/uniswap.config";
|
|
3
|
+
import { getPoolPrice, getPoolSqrtPrice, modifyPosition } from "../lib/pool";
|
|
4
|
+
import { getERC20Balance, isApproved, approveERC20 } from "../lib/ERC20";
|
|
5
|
+
import { calculateLiqDelta, calculateTickFromPriceWithSpacing } from "../lib/liqCalculation";
|
|
6
|
+
import { ModifyPositionParams } from "../lib/types";
|
|
7
|
+
import { getContract } from "../lib/contract";
|
|
8
|
+
|
|
9
|
+
async function removeLiq(wallet: Wallet, priceLower: number, priceUpper: number, amount0: bigint, amount1: bigint, poolKey: any): Promise<void> {
|
|
10
|
+
const ticklow = calculateTickFromPriceWithSpacing(priceLower, poolKey.tickSpacing);
|
|
11
|
+
const tickhigh = calculateTickFromPriceWithSpacing(priceUpper, poolKey.tickSpacing);
|
|
12
|
+
const liqPool = await getContract(wallet, "LiquidPool");
|
|
13
|
+
|
|
14
|
+
const sqrtCurrent = await getPoolSqrtPrice(liqPool);
|
|
15
|
+
const [liqDelta, amount0Rmv, amount1Rmv] = calculateLiqDelta(ticklow, sqrtCurrent, tickhigh, amount0, amount1);
|
|
16
|
+
console.log(`Attempting to remove liquidity ${liqDelta} to price range [${priceLower}, ${priceUpper}] with amount0[${amount0Rmv.toString()}], amount1[${amount1Rmv.toString()}]`);
|
|
17
|
+
const modifyPositionParams: ModifyPositionParams = {
|
|
18
|
+
tickLower: ticklow,
|
|
19
|
+
tickUpper: tickhigh,
|
|
20
|
+
liquidityDelta: liqDelta * BigInt(-1),
|
|
21
|
+
};
|
|
22
|
+
await modifyPosition(liqPool, modifyPositionParams, "0x00");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function main(): Promise<void> {
|
|
26
|
+
const provider = new providers.JsonRpcProvider(RPC_URL);
|
|
27
|
+
const wallet = new Wallet(PRIVATE_KEY, provider);
|
|
28
|
+
|
|
29
|
+
const liqPoolAddress = CONTRACT_ADDRESSES.LiquidPool;
|
|
30
|
+
|
|
31
|
+
const token0 = await getContract(wallet, "Token0");
|
|
32
|
+
const token1 = await getContract(wallet, "Token1");
|
|
33
|
+
const liqPool = await getContract(wallet, "LiquidPool");
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
let poolPrice = await getPoolPrice(liqPool);
|
|
37
|
+
console.log(`Current price of pool ${liqPool.address} before removing liquidity is ${poolPrice}`);
|
|
38
|
+
|
|
39
|
+
const token0Before = await getERC20Balance(token0, wallet.address);
|
|
40
|
+
const token1Before = await getERC20Balance(token1, wallet.address);
|
|
41
|
+
console.log("Token0 balance before removing liquidity:", token0Before.toString());
|
|
42
|
+
console.log("Token1 balance before removing liquidity:", token1Before.toString());
|
|
43
|
+
|
|
44
|
+
const priceLower = 0.5;
|
|
45
|
+
const priceUpper = 1.5;
|
|
46
|
+
const amount0 = 100n;
|
|
47
|
+
const amount1 = 100n;
|
|
48
|
+
|
|
49
|
+
await removeLiq(wallet, priceLower, priceUpper, amount0, amount1, POOL_KEYS.limitOrderPoolKey);
|
|
50
|
+
|
|
51
|
+
poolPrice = await getPoolPrice(liqPool);
|
|
52
|
+
console.log(`Current price of pool ${liqPool.address} after removing liquidity is ${poolPrice}`);
|
|
53
|
+
|
|
54
|
+
const token0After = await getERC20Balance(token0, wallet.address);
|
|
55
|
+
const token1After = await getERC20Balance(token1, wallet.address);
|
|
56
|
+
console.log("Token0 change:", token0After - token0Before);
|
|
57
|
+
console.log("Token1 change:", token1After - token1Before);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
main().catch((error) => {
|
|
61
|
+
console.error(error);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Wallet,providers,constants, utils } from "ethers";
|
|
2
|
+
import { CONTRACT_ADDRESSES, RPC_URL, PRIVATE_KEY, SALT, SALT_LIMITORDER } from "../../../config/uniswap.config";
|
|
3
|
+
import { SwapParams } from "../lib/types";
|
|
4
|
+
import { getPoolPrice, getCurrentTick } from "../lib/pool";
|
|
5
|
+
import { getERC20Balance, isApproved, approveERC20 } from "../lib/ERC20";
|
|
6
|
+
import { executeSwap } from "../lib/swap";
|
|
7
|
+
import { priceToSqrtPrice, calculateTickFromPriceWithSpacing } from "../lib/liqCalculation";
|
|
8
|
+
import { getContract } from "../lib/contract";
|
|
9
|
+
|
|
10
|
+
// Swap function that handles token approval and execution
|
|
11
|
+
// amountIn代表投入的代币数量,获取到的数量不定
|
|
12
|
+
export async function swap(wallet: Wallet, amountIn: bigint, zeroForOne: boolean, hookData: string): Promise<void> {
|
|
13
|
+
const token0 = await getContract(wallet,"MockERC20");
|
|
14
|
+
const token1 = await getContract(wallet,"MockERC20");
|
|
15
|
+
const liqPool = await getContract(wallet,"LiquidPool");
|
|
16
|
+
|
|
17
|
+
const priceCurrent = await getPoolPrice(liqPool);
|
|
18
|
+
// slippage at 5%
|
|
19
|
+
const slippageMultiplier = 105;
|
|
20
|
+
const base = 100;
|
|
21
|
+
|
|
22
|
+
// after zero for one, the price is decreased, the price0 is the maximum slippage
|
|
23
|
+
const price0 = priceCurrent * base / slippageMultiplier;
|
|
24
|
+
const price1 = priceCurrent * slippageMultiplier / base;
|
|
25
|
+
const sqrtPricecur = priceToSqrtPrice(priceCurrent)
|
|
26
|
+
const sqrtPrice0 = priceToSqrtPrice(price0)
|
|
27
|
+
const sqrtPrice1 = priceToSqrtPrice(price1)
|
|
28
|
+
// console.log(`sqrtPricecur: ${sqrtPricecur.toString()}, sqrtPrice0: ${sqrtPrice0.toString()}, sqrtPrice1: ${sqrtPrice1.toString()}`);
|
|
29
|
+
|
|
30
|
+
const tick = await getCurrentTick(liqPool);
|
|
31
|
+
console.log("Current tick at liquild pool:", tick);
|
|
32
|
+
|
|
33
|
+
// If zero for one, the price cannot be less than this value after the swap.
|
|
34
|
+
// If one for zero, the price cannot be greater than this value after the swap
|
|
35
|
+
const sqrtPriceLimitX96 = zeroForOne
|
|
36
|
+
? sqrtPrice0
|
|
37
|
+
: sqrtPrice1;
|
|
38
|
+
|
|
39
|
+
const swapParams: SwapParams = {
|
|
40
|
+
zeroForOne: zeroForOne, // Swap direction, if true, swap token0 for token1
|
|
41
|
+
amountSpecified: amountIn,
|
|
42
|
+
sqrtPriceLimitX96: sqrtPriceLimitX96 // Price limit after swap to protect against slippage
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Check and approve ERC20 tokens if necessary
|
|
46
|
+
const token = zeroForOne ? token0 : token1;
|
|
47
|
+
// Calculate an approval amount with a 1% buffer to account for fees
|
|
48
|
+
if (!(await isApproved(token, wallet.address, liqPool.address, constants.MaxUint256.toBigInt()))) {
|
|
49
|
+
await approveERC20(token, liqPool.address, constants.MaxUint256.toBigInt());
|
|
50
|
+
}
|
|
51
|
+
// Execute the swap
|
|
52
|
+
await executeSwap(liqPool, swapParams, hookData);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Main function to execute the swap and display results
|
|
56
|
+
export async function main(): Promise<void> {
|
|
57
|
+
const provider = new providers.JsonRpcProvider(RPC_URL);
|
|
58
|
+
const wallet = new Wallet(PRIVATE_KEY, provider);
|
|
59
|
+
|
|
60
|
+
const token0 = await getContract(wallet, "Token0");
|
|
61
|
+
const token1 = await getContract(wallet, "Token1");
|
|
62
|
+
const liqPool = await getContract(wallet, 'LiquidPool');
|
|
63
|
+
|
|
64
|
+
const token0Before = await getERC20Balance(token0, wallet.address);
|
|
65
|
+
const token1Before = await getERC20Balance(token1, wallet.address);
|
|
66
|
+
console.log("Token0 balance before swapping:", token0Before.toString());
|
|
67
|
+
console.log("Token1 balance before swapping:", token1Before.toString());
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
const swapAmount = utils.parseEther("1000").toBigInt();
|
|
71
|
+
// False will make price higher, True will make price lower
|
|
72
|
+
const zeroForOne = false;
|
|
73
|
+
const x = zeroForOne ? 0 : 1;
|
|
74
|
+
console.log(`swap ${utils.formatEther(swapAmount)} amount of token${1 - x} from token${x}`);
|
|
75
|
+
|
|
76
|
+
// used for LimitOrder.sol afterSwap
|
|
77
|
+
const hookData = utils.defaultAbiCoder.encode(["bytes32"], [SALT_LIMITORDER]);
|
|
78
|
+
await swap(wallet, swapAmount, zeroForOne, hookData);
|
|
79
|
+
|
|
80
|
+
const token0After: bigint = await getERC20Balance(token0, wallet.address);
|
|
81
|
+
const token1After: bigint = await getERC20Balance(token1, wallet.address);
|
|
82
|
+
const token0Diff = token0After - token0Before;
|
|
83
|
+
const token1Diff = token1After - token1Before;
|
|
84
|
+
console.log("Token0 change:", utils.formatEther(token0Diff));
|
|
85
|
+
console.log("Token1 change:", utils.formatEther(token1Diff));
|
|
86
|
+
|
|
87
|
+
if (token0Diff === BigInt(0) || token1Diff === BigInt(0)) {
|
|
88
|
+
console.log("No tokens were swapped. Maybe liquidity is insufficient.");
|
|
89
|
+
return;
|
|
90
|
+
} else {
|
|
91
|
+
const currentTick = await getCurrentTick(liqPool);
|
|
92
|
+
console.log(`Current Tick After Swap: ${currentTick}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Run the main function
|
|
97
|
+
main().catch((error) => {
|
|
98
|
+
console.error(error);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Contract, providers, Wallet } from "ethers";
|
|
2
|
+
import { CONTRACT_ADDRESSES, POOL_KEYS, PRIVATE_KEY, RPC_URL, PRICE_LIMIT } from "../../../config/uniswap.config";
|
|
3
|
+
import { calculateTickFromPriceWithSpacing } from "../lib/liqCalculation";
|
|
4
|
+
import { PoolKey } from "../lib/types";
|
|
5
|
+
import { getERC20Balance } from "../lib/ERC20";
|
|
6
|
+
import { getPoolPrice } from "../lib/pool";
|
|
7
|
+
import { getContract } from "../lib/contract";
|
|
8
|
+
|
|
9
|
+
async function killLimitOrderFrontend(sender: string, priceLimit: number, poolkey: PoolKey, wallet: Wallet) {
|
|
10
|
+
const liqPool = await getContract(wallet, "LiquidPool");
|
|
11
|
+
const limitHook = await getContract(wallet, "LimitOrder");
|
|
12
|
+
|
|
13
|
+
const priceCurrent = await getPoolPrice(liqPool);
|
|
14
|
+
const tickcurr = calculateTickFromPriceWithSpacing(priceCurrent, poolkey.tickSpacing)
|
|
15
|
+
const ticklow = calculateTickFromPriceWithSpacing(priceLimit, poolkey.tickSpacing)
|
|
16
|
+
const tickhigh = ticklow + poolkey.tickSpacing;
|
|
17
|
+
console.log(`tickcurr: ${tickcurr}, ticklower: ${ticklow}, tickhigh: ${tickhigh}`);
|
|
18
|
+
|
|
19
|
+
let zeroForOne: boolean;
|
|
20
|
+
if (tickcurr < ticklow) {
|
|
21
|
+
zeroForOne = true;
|
|
22
|
+
} else if (tickcurr > tickhigh) {
|
|
23
|
+
zeroForOne = false;
|
|
24
|
+
} else {
|
|
25
|
+
throw new Error("Price mismatch for limit order");
|
|
26
|
+
}
|
|
27
|
+
console.log("Killing limit order, zeroForOne:", zeroForOne);
|
|
28
|
+
|
|
29
|
+
let tx = await limitHook.kill(poolkey, ticklow, zeroForOne, wallet.address);
|
|
30
|
+
await tx.wait();
|
|
31
|
+
|
|
32
|
+
await limitHook.once("Kill", (owner, epoch, key, tickLower, zeroForOne, liquidity, event) => {
|
|
33
|
+
console.log("Kill event emitted:");
|
|
34
|
+
console.log(`Owner: ${owner}`);
|
|
35
|
+
console.log(`Epoch: ${epoch.toString()}`);
|
|
36
|
+
console.log(`Key: ${key}`);
|
|
37
|
+
console.log(`TickLower: ${tickLower.toString()}`);
|
|
38
|
+
console.log(`ZeroForOne: ${zeroForOne}`);
|
|
39
|
+
console.log(`Liquidity: ${liquidity.toString()}`);
|
|
40
|
+
|
|
41
|
+
// Handle event here
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function main(): Promise<void> {
|
|
46
|
+
const provider = new providers.JsonRpcProvider(RPC_URL);
|
|
47
|
+
const wallet = new Wallet(PRIVATE_KEY, provider);
|
|
48
|
+
|
|
49
|
+
const token0 = await getContract(wallet, "Token0");
|
|
50
|
+
const token1 = await getContract(wallet, "Token1");
|
|
51
|
+
|
|
52
|
+
const token0Before = (await getERC20Balance(token0, wallet.address)).valueOf();
|
|
53
|
+
const token1Before = (await getERC20Balance(token1, wallet.address)).valueOf();
|
|
54
|
+
console.log("Token0 balance before adding Limit order:", token0Before.toString());
|
|
55
|
+
console.log("Token1 balance before adding limit order:", token1Before.toString());
|
|
56
|
+
|
|
57
|
+
const price = PRICE_LIMIT;
|
|
58
|
+
const epo = await killLimitOrderFrontend(wallet.address, price, POOL_KEYS.limitOrderPoolKey, wallet)
|
|
59
|
+
console.log("epoch:", epo);
|
|
60
|
+
|
|
61
|
+
const token0After = (await getERC20Balance(token0, wallet.address)).valueOf();
|
|
62
|
+
const token1After = (await getERC20Balance(token1, wallet.address)).valueOf();
|
|
63
|
+
console.log("Token0 change:", token0After - token0Before);
|
|
64
|
+
console.log("Token1 change:", token1After - token1Before);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
main().catch(error => {
|
|
68
|
+
console.error(error);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { Contract, Wallet } from "ethers";
|
|
2
|
+
import { CONTRACT_ADDRESSES, PRIVATE_KEY, RPC_URL, POOL_KEYS, SALT_LIMITORDER, PRICE_LIMIT } from "../../../config/uniswap.config";
|
|
3
|
+
import { getCurrentTick, getPoolPrice } from "../lib/pool";
|
|
4
|
+
import { getERC20Balance, isApproved, approveERC20 } from "../lib/ERC20";
|
|
5
|
+
import { calculateTickFromPriceWithSpacing, calculatePriceFromTick, getSqrtPriceAtTick, liquidity0, liquidity1, amount0 } from "../lib/liqCalculation";
|
|
6
|
+
import { PoolKey } from "../lib/types";
|
|
7
|
+
import { ethers } from "hardhat";
|
|
8
|
+
import { getContract } from "../lib/contract";
|
|
9
|
+
|
|
10
|
+
async function placeLimitOrder(contract: Contract, poolKey: any, tickLower: number, zeroForOne: boolean, liquidity: BigInt): Promise<any> {
|
|
11
|
+
const tx = await contract.place(poolKey, tickLower, zeroForOne, liquidity);
|
|
12
|
+
await tx.wait();
|
|
13
|
+
console.log("Limit order set successfully:");
|
|
14
|
+
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
contract.once("Place", (owner, epoch, key, tickLower, zeroForOne, liquidity) => {
|
|
17
|
+
resolve({
|
|
18
|
+
owner,
|
|
19
|
+
epoch: epoch.toString(),
|
|
20
|
+
key,
|
|
21
|
+
tickLower: tickLower.toString(),
|
|
22
|
+
zeroForOne,
|
|
23
|
+
liquidity: liquidity.toString()
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function placeLimitOrderFrontend(token0: Contract, token1: Contract, amountIn: bigint, priceLimit: number, poolKey: PoolKey, wallet: Wallet): Promise<any> {
|
|
30
|
+
const ticklow = calculateTickFromPriceWithSpacing(priceLimit, poolKey.tickSpacing);
|
|
31
|
+
const tickhigh = ticklow + poolKey.tickSpacing;
|
|
32
|
+
|
|
33
|
+
const pricelow = calculatePriceFromTick(ticklow);
|
|
34
|
+
const priceupp = calculatePriceFromTick(tickhigh);
|
|
35
|
+
|
|
36
|
+
const sqrt_low = getSqrtPriceAtTick(ticklow);
|
|
37
|
+
const sqrt_upp = getSqrtPriceAtTick(tickhigh);
|
|
38
|
+
|
|
39
|
+
const liqPool = await getContract(wallet, "LiquidPool");
|
|
40
|
+
const currentTick = await getCurrentTick(liqPool);
|
|
41
|
+
const priceCurrent = await getPoolPrice(liqPool);
|
|
42
|
+
|
|
43
|
+
console.log(`Current pool price: ${priceCurrent}, price low: ${pricelow}, price upp: ${priceupp}`);
|
|
44
|
+
console.log(`Tick low: ${ticklow}, Tick high: ${tickhigh}, Current Tick: ${currentTick}`);
|
|
45
|
+
|
|
46
|
+
let liquidity: bigint;
|
|
47
|
+
let zeroForOne: boolean;
|
|
48
|
+
if (ticklow > currentTick) {
|
|
49
|
+
zeroForOne = true;
|
|
50
|
+
liquidity = liquidity0(amountIn, sqrt_low, sqrt_upp);
|
|
51
|
+
if (!(await isApproved(token0, wallet.address, CONTRACT_ADDRESSES.LimitOrder, amountIn))) {
|
|
52
|
+
await approveERC20(token0, CONTRACT_ADDRESSES.LimitOrder, amountIn);
|
|
53
|
+
}
|
|
54
|
+
} else if (tickhigh <= currentTick) {
|
|
55
|
+
zeroForOne = false;
|
|
56
|
+
liquidity = liquidity1(amountIn, sqrt_upp, sqrt_low);
|
|
57
|
+
if (!(await isApproved(token1, wallet.address, CONTRACT_ADDRESSES.LimitOrder, amountIn))) {
|
|
58
|
+
await approveERC20(token1, CONTRACT_ADDRESSES.LimitOrder, amountIn);
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
throw new Error("Price mismatch for limit order");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const hook = await getContract(wallet, "LimitOrder");
|
|
65
|
+
const epoch = await placeLimitOrder(hook, poolKey, ticklow, zeroForOne, liquidity);
|
|
66
|
+
return epoch;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function main() {
|
|
70
|
+
const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
|
|
71
|
+
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
|
|
72
|
+
|
|
73
|
+
const token0 = await getContract(wallet, "Token0");
|
|
74
|
+
const token1 = await getContract(wallet, "Token1");
|
|
75
|
+
|
|
76
|
+
const token0Before = (await getERC20Balance(token0, wallet.address)).valueOf();
|
|
77
|
+
const token1Before = (await getERC20Balance(token1, wallet.address)).valueOf();
|
|
78
|
+
|
|
79
|
+
const limitPrice = PRICE_LIMIT;
|
|
80
|
+
const amountIn = ethers.utils.parseEther("1000").toBigInt();
|
|
81
|
+
const epo = await placeLimitOrderFrontend(token0, token1, amountIn, limitPrice, POOL_KEYS.limitOrderPoolKey, wallet)
|
|
82
|
+
console.log("epoch:", epo);
|
|
83
|
+
|
|
84
|
+
const token0After = (await getERC20Balance(token0, wallet.address)).valueOf();
|
|
85
|
+
const token1After = (await getERC20Balance(token1, wallet.address)).valueOf();
|
|
86
|
+
console.log("Token0 change:", token0After - token0Before);
|
|
87
|
+
console.log("Token1 change:", token1After - token1Before);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
main().catch((error) => {
|
|
91
|
+
console.error(error);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Contract, providers, Wallet } from "ethers";
|
|
2
|
+
import { CONTRACT_ADDRESSES, PRIVATE_KEY, RPC_URL } from "../../../config/uniswap.config";
|
|
3
|
+
import { getERC20Balance } from "../lib/ERC20";
|
|
4
|
+
import { getContract } from "../lib/contract";
|
|
5
|
+
|
|
6
|
+
async function withdrawLimitOrder(contract: Contract, epoch: number, to: string): Promise<{ owner: string; epoch: string; liquidity: string; }> {
|
|
7
|
+
try {
|
|
8
|
+
// Initiate the withdraw transaction
|
|
9
|
+
const tx = await contract.withdraw(epoch, to);
|
|
10
|
+
await tx.wait();
|
|
11
|
+
console.log("Withdraw executed successfully.");
|
|
12
|
+
|
|
13
|
+
// Return a promise that resolves when the "Kill" event is emitted
|
|
14
|
+
// 监听链上事件,如果事件成功则返回结果。
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
contract.once("Withdraw", (owner, eventEpoch, liquidity) => {
|
|
17
|
+
resolve({
|
|
18
|
+
owner,
|
|
19
|
+
epoch: eventEpoch.toString(),
|
|
20
|
+
liquidity: liquidity.toString(),
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
} catch (error: any) {
|
|
26
|
+
handleContractError(error);
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function handleContractError(error: any): void {
|
|
32
|
+
if (error.code === 'CALL_EXCEPTION') {
|
|
33
|
+
console.error('Transaction failed with CALL_EXCEPTION');
|
|
34
|
+
switch (error.data) {
|
|
35
|
+
case '0x10074548':
|
|
36
|
+
console.error('Encountered custom error ZeroLiquidity()');
|
|
37
|
+
break;
|
|
38
|
+
case '0x6cb6fbf0':
|
|
39
|
+
console.error('Encountered custom error NotFilled()');
|
|
40
|
+
break;
|
|
41
|
+
default:
|
|
42
|
+
console.error('Unknown error data:', error.data);
|
|
43
|
+
}
|
|
44
|
+
console.log('Transaction Details:', error.transaction);
|
|
45
|
+
} else {
|
|
46
|
+
console.error('An unexpected error occurred:', error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
async function main() {
|
|
52
|
+
const provider = new providers.JsonRpcProvider(RPC_URL);
|
|
53
|
+
const wallet = new Wallet(PRIVATE_KEY, provider);
|
|
54
|
+
|
|
55
|
+
const token0 = await getContract(wallet, "Token0");
|
|
56
|
+
const token1 = await getContract(wallet, "Token1");
|
|
57
|
+
const LimitOrder = await getContract(wallet, "LimitOrder");
|
|
58
|
+
|
|
59
|
+
const token0Before = await getERC20Balance(token0, wallet.address);
|
|
60
|
+
const token1Before = await getERC20Balance(token1, wallet.address);
|
|
61
|
+
console.log("Token0 balance before adding Limit order:", token0Before.toString());
|
|
62
|
+
console.log("Token1 balance before adding limit order:", token1Before.toString());
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
const epoch = 1;
|
|
66
|
+
const epo = await withdrawLimitOrder(LimitOrder, epoch, wallet.address);
|
|
67
|
+
console.log("epoch:", epo);
|
|
68
|
+
|
|
69
|
+
const token0After = await getERC20Balance(token0, wallet.address);
|
|
70
|
+
const token1After = await getERC20Balance(token1, wallet.address);
|
|
71
|
+
console.log("Token0 change:", token0After - token0Before);
|
|
72
|
+
console.log("Token1 change:", token1After - token1Before);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
main().catch(error => {
|
|
76
|
+
console.error(error);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
});
|