@dhedge/v2-sdk 1.10.10 → 1.10.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhedge/v2-sdk",
3
- "version": "1.10.10",
3
+ "version": "1.10.11",
4
4
  "license": "MIT",
5
5
  "description": "🛠 An SDK for building applications on top of dHEDGE V2",
6
6
  "main": "dist/index.js",
@@ -34,7 +34,7 @@
34
34
  "@size-limit/preset-small-lib": "^5.0.1",
35
35
  "@types/jest": "^28.1.7",
36
36
  "@types/lodash": "^4.14.178",
37
- "hardhat": "2.22.18",
37
+ "hardhat": "2.23.0",
38
38
  "husky": "^7.0.1",
39
39
  "jest": "^28.1.3",
40
40
  "size-limit": "^5.0.1",
@@ -0,0 +1,96 @@
1
+ [
2
+ {
3
+ "type": "function",
4
+ "name": "cancelExistingOrder",
5
+ "inputs": [
6
+ {
7
+ "name": "account",
8
+ "type": "address",
9
+ "internalType": "address"
10
+ }
11
+ ],
12
+ "outputs": [],
13
+ "stateMutability": "nonpayable"
14
+ },
15
+ {
16
+ "type": "function",
17
+ "name": "cancelOrderByModule",
18
+ "inputs": [
19
+ {
20
+ "name": "account",
21
+ "type": "address",
22
+ "internalType": "address"
23
+ }
24
+ ],
25
+ "outputs": [],
26
+ "stateMutability": "nonpayable"
27
+ },
28
+ {
29
+ "type": "function",
30
+ "name": "executeLimitOrder",
31
+ "inputs": [
32
+ {
33
+ "name": "tokenId",
34
+ "type": "uint256",
35
+ "internalType": "uint256"
36
+ },
37
+ {
38
+ "name": "priceUpdateData",
39
+ "type": "bytes[]",
40
+ "internalType": "bytes[]"
41
+ }
42
+ ],
43
+ "outputs": [],
44
+ "stateMutability": "payable"
45
+ },
46
+ {
47
+ "type": "function",
48
+ "name": "executeOrder",
49
+ "inputs": [
50
+ {
51
+ "name": "account",
52
+ "type": "address",
53
+ "internalType": "address"
54
+ },
55
+ {
56
+ "name": "priceUpdateData",
57
+ "type": "bytes[]",
58
+ "internalType": "bytes[]"
59
+ }
60
+ ],
61
+ "outputs": [],
62
+ "stateMutability": "payable"
63
+ },
64
+ {
65
+ "type": "function",
66
+ "name": "hasOrderExpired",
67
+ "inputs": [
68
+ {
69
+ "name": "account",
70
+ "type": "address",
71
+ "internalType": "address"
72
+ }
73
+ ],
74
+ "outputs": [
75
+ {
76
+ "name": "expired",
77
+ "type": "bool",
78
+ "internalType": "bool"
79
+ }
80
+ ],
81
+ "stateMutability": "view"
82
+ },
83
+ {
84
+ "type": "function",
85
+ "name": "maxExecutabilityAge",
86
+ "inputs": [],
87
+ "outputs": [
88
+ {
89
+ "name": "maxExecutabilityAge",
90
+ "type": "uint64",
91
+ "internalType": "uint64"
92
+ }
93
+ ],
94
+ "stateMutability": "view"
95
+ }
96
+ ]
package/src/config.ts CHANGED
@@ -170,10 +170,11 @@ export const flatMoneyContractAddresses: Readonly<Partial<
170
170
  Record<
171
171
  Network,
172
172
  {
173
+ OrderExecution?: string;
173
174
  DelayedOrder: string;
174
175
  FlatcoinVault: string;
175
176
  StableModule: string;
176
- RETH: string;
177
+ COLLATERAL: string;
177
178
  }
178
179
  >
179
180
  >> = {
@@ -181,6 +182,13 @@ export const flatMoneyContractAddresses: Readonly<Partial<
181
182
  DelayedOrder: "0x6D857e9D24a7566bB72a3FB0847A3E0e4E1c2879",
182
183
  FlatcoinVault: "0x95Fa1ddc9a78273f795e67AbE8f1Cd2Cd39831fF",
183
184
  StableModule: "0xb95fB324b8A2fAF8ec4f76e3dF46C718402736e2",
184
- RETH: "0xb6fe221fe9eef5aba221c348ba20a1bf5e73624c"
185
+ COLLATERAL: "0xb6fe221fe9eef5aba221c348ba20a1bf5e73624c" // RETH
186
+ },
187
+ [Network.OPTIMISM]: {
188
+ OrderExecution: "0x7805CB7fb2C2e70FDdF92949065D9Ee1Fc2F72a8",
189
+ DelayedOrder: "0xd917A0C9B21Bb71DF1209d2c211Ad83004F01554", // OrderAnnouncementModule
190
+ FlatcoinVault: "0x86C7b9640302082B0dF78023F930d8612bFcaD3f",
191
+ COLLATERAL: "0x68f180fcCe6836688e9084f035309E29Bf0A2095", // WBTC
192
+ StableModule: "0x357CB23571EF7a3d6189b7FAcFC361eA71f7CAB5"
185
193
  }
186
194
  };
@@ -23,7 +23,6 @@ export class Dhedge {
23
23
  PoolFactory.abi,
24
24
  this.signer
25
25
  );
26
-
27
26
  this.utils = new Utils(this.network, this.signer);
28
27
  }
29
28
 
@@ -87,9 +86,10 @@ export class Dhedge {
87
86
  * @param {string} address Pool address
88
87
  * @returns {Pool} Loaded Pool
89
88
  */
90
- public async loadPool(address: string): Promise<Pool> {
89
+ public async loadPool(address: string, isDhedge = true): Promise<Pool> {
91
90
  const poolLogic = new Contract(address, PoolLogic.abi, this.signer);
92
- const managerLogicAddress = await poolLogic.poolManagerLogic();
91
+ let managerLogicAddress = address;
92
+ if (isDhedge) managerLogicAddress = await poolLogic.poolManagerLogic();
93
93
  const managerLogic = new Contract(
94
94
  managerLogicAddress,
95
95
  ManagerLogic.abi,
@@ -102,7 +102,8 @@ export class Dhedge {
102
102
  poolLogic,
103
103
  managerLogic,
104
104
  this.utils,
105
- this.factory
105
+ this.factory,
106
+ isDhedge
106
107
  );
107
108
  }
108
109
 
@@ -96,6 +96,7 @@ export class Pool {
96
96
  public readonly address: string;
97
97
  public readonly utils: Utils;
98
98
  public readonly network: Network;
99
+ public readonly isDhedge: boolean;
99
100
 
100
101
  public constructor(
101
102
  network: Network,
@@ -103,7 +104,8 @@ export class Pool {
103
104
  poolLogic: Contract,
104
105
  mangerLogic: Contract,
105
106
  utils: Utils,
106
- factory: Contract
107
+ factory: Contract,
108
+ isDhedge = true
107
109
  ) {
108
110
  this.network = network;
109
111
  this.poolLogic = poolLogic;
@@ -112,6 +114,7 @@ export class Pool {
112
114
  this.signer = signer;
113
115
  this.utils = utils;
114
116
  this.factory = factory;
117
+ this.isDhedge = isDhedge;
115
118
  }
116
119
 
117
120
  /**
@@ -4,6 +4,7 @@ import IFlatcoinVaultAbi from "../../abi/flatmoney/IFlatcoinVault.json";
4
4
  import KeeperFeeAbi from "../../abi/flatmoney/KeeperFee.json";
5
5
  import { flatMoneyContractAddresses } from "../../config";
6
6
  import BigNumber from "bignumber.js";
7
+ import { JsonRpcProvider } from "@ethersproject/providers";
7
8
 
8
9
  export const getKeeperFeeContract = async (pool: Pool): Promise<Contract> => {
9
10
  const flatMoneyContracts = flatMoneyContractAddresses[pool.network];
@@ -35,12 +36,16 @@ export const getKeeperFee = async (
35
36
  maxKeeperFeeInUsd: number | null
36
37
  ): Promise<ethers.BigNumber> => {
37
38
  const keeperFeeContract = await getKeeperFeeContract(pool);
38
- const gasPrice = await pool.signer.provider.getGasPrice();
39
+
40
+ const feeHistory = await (pool.signer
41
+ .provider as JsonRpcProvider).send("eth_feeHistory", [1, "latest"]);
42
+
43
+ const gasPrice = Number(feeHistory.baseFeePerGas[0]);
39
44
 
40
45
  let keeperfee: ethers.BigNumber;
41
46
  if (gasPrice) {
42
47
  keeperfee = await keeperFeeContract["getKeeperFee(uint256)"](
43
- new BigNumber(gasPrice.toString()).times(1.2).toFixed(0)
48
+ new BigNumber(gasPrice.toString()).times(1.5).toFixed(0)
44
49
  );
45
50
  } else {
46
51
  keeperfee = await keeperFeeContract["getKeeperFee()"]();
@@ -72,7 +77,7 @@ export const getKeeperFeeInUsd = async (
72
77
  const filteredFc = fundComposition.filter(
73
78
  fc =>
74
79
  fc.asset.toLocaleLowerCase() ===
75
- flatMoneyContracts.RETH.toLocaleLowerCase()
80
+ flatMoneyContracts.COLLATERAL.toLocaleLowerCase()
76
81
  );
77
82
 
78
83
  if (!filteredFc[0])
@@ -80,5 +85,8 @@ export const getKeeperFeeInUsd = async (
80
85
 
81
86
  const rateD1 = new BigNumber(filteredFc[0].rate.toString()).div(1e18);
82
87
 
83
- return rateD1.times(keeperFee.toString()).div(1e18);
88
+ const assetDecimal = await pool.utils.getDecimals(
89
+ flatMoneyContracts.COLLATERAL
90
+ );
91
+ return rateD1.times(keeperFee.toString()).div(10 ** assetDecimal);
84
92
  };
@@ -3,6 +3,7 @@
3
3
  import BigNumber from "bignumber.js";
4
4
  import { Pool, ethers } from "../..";
5
5
  import DelayedOrderAbi from "../../abi/flatmoney/DelayedOrder.json";
6
+ import IOrderExecutionModuleAbi from "../../abi/flatmoney/v2/IOrderExecutionModule.json";
6
7
  import { flatMoneyContractAddresses } from "../../config";
7
8
  import { getPoolTxOrGasEstimate } from "../../utils/contract";
8
9
  import { getStableDepositQuote, getStableWithdrawQuote } from "./stableModule";
@@ -42,6 +43,12 @@ export function getCancelExistingOrderTxData(account: string): string {
42
43
  ).encodeFunctionData("cancelExistingOrder", [account]);
43
44
  }
44
45
 
46
+ export function getCancelExistingOrderTxDataForV2(account: string): string {
47
+ return new ethers.utils.Interface(
48
+ IOrderExecutionModuleAbi
49
+ ).encodeFunctionData("cancelExistingOrder", [account]);
50
+ }
51
+
45
52
  export async function mintUnitViaFlatMoney(
46
53
  pool: Pool,
47
54
  depositAmount: ethers.BigNumber | string,
@@ -55,7 +62,7 @@ export async function mintUnitViaFlatMoney(
55
62
  throw new Error("mintUnitViaFlatMoney: network not supported");
56
63
  }
57
64
 
58
- const keeperfee = await getKeeperFee(pool, maxKeeperFeeInUsd); // in RETH
65
+ const keeperfee = await getKeeperFee(pool, maxKeeperFeeInUsd); // in COLLATERAL
59
66
 
60
67
  const adjustedDepositAmount = new BigNumber(depositAmount.toString()).minus(
61
68
  keeperfee.toString() // keeper fee deducted from amountIn
@@ -125,11 +132,26 @@ export async function cancelOrderViaFlatMoney(
125
132
  if (!flatMoneyContracts) {
126
133
  throw new Error("cancelOrderViaFlatMoney: network not supported");
127
134
  }
128
- const cancelOrderTxData = await getCancelExistingOrderTxData(pool.address);
129
- const tx = await getPoolTxOrGasEstimate(
130
- pool,
131
- [flatMoneyContracts.DelayedOrder, cancelOrderTxData, options],
132
- estimateGas
133
- );
134
- return tx;
135
+ // flat money v2
136
+ // use OrderExecution module to cancel order
137
+ let toAddress = flatMoneyContracts.DelayedOrder;
138
+ let cancelOrderTxData = getCancelExistingOrderTxData(pool.address);
139
+ if (flatMoneyContracts.OrderExecution) {
140
+ toAddress = flatMoneyContracts.OrderExecution;
141
+ cancelOrderTxData = await getCancelExistingOrderTxDataForV2(pool.address);
142
+ }
143
+ // use trader address to cancel order
144
+ if (estimateGas) {
145
+ return pool.signer.estimateGas({
146
+ to: toAddress,
147
+ data: cancelOrderTxData
148
+ });
149
+ } else {
150
+ const tx = await pool.signer.sendTransaction({
151
+ to: toAddress,
152
+ data: cancelOrderTxData,
153
+ ...options
154
+ });
155
+ return tx;
156
+ }
135
157
  }
@@ -62,7 +62,8 @@ export const CONTRACT_ADDRESS = {
62
62
  VELODROME_CL_USDC_WETH_GAUGE: "",
63
63
  VELO: "",
64
64
  COMPOUNDV3_WETH: "",
65
- TOROS: ""
65
+ TOROS: "",
66
+ UNIT: ""
66
67
  },
67
68
 
68
69
  [Network.OPTIMISM]: {
@@ -77,6 +78,7 @@ export const CONTRACT_ADDRESS = {
77
78
  nonfungiblePositionManager: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88"
78
79
  },
79
80
 
81
+ UNIT: "0x357CB23571EF7a3d6189b7FAcFC361eA71f7CAB5",
80
82
  WMATIC: "",
81
83
  //
82
84
  ARRAKIS_USDC_WETH_GAUGE: "",
@@ -101,6 +103,8 @@ export const CONTRACT_ADDRESS = {
101
103
  nonfungiblePositionManager: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88"
102
104
  },
103
105
 
106
+ UNIT: "",
107
+
104
108
  //
105
109
  ARRAKIS_USDC_WETH_GAUGE: "",
106
110
  ARRAKIS_USDC_WETH_LP: "",
@@ -117,6 +121,7 @@ export const CONTRACT_ADDRESS = {
117
121
  WETH: "0x4200000000000000000000000000000000000006",
118
122
  WBTC: "",
119
123
  SWETH: "",
124
+ UNIT: "0xb95fB324b8A2fAF8ec4f76e3dF46C718402736e2",
120
125
  uniswapV3: {
121
126
  nonfungiblePositionManager: ""
122
127
  },
@@ -4,6 +4,7 @@ import { Dhedge, Pool } from "../entities";
4
4
  import { AssetEnabled, Network } from "../types";
5
5
  import {
6
6
  TestingRunParams,
7
+ runWithImpersonateAccount,
7
8
  setTokenAmount,
8
9
  testingHelper
9
10
  } from "./utils/testingHelper";
@@ -14,9 +15,7 @@ import DelayedOrderAbi from "../abi/flatmoney/DelayedOrder.json";
14
15
  import { allowanceDelta } from "./utils/token";
15
16
  import { getKeeperFee } from "../services/flatmoney/keeperFee";
16
17
 
17
- const RETH = "0xb6fe221fe9eef5aba221c348ba20a1bf5e73624c";
18
- const RETH_SLOT = 0;
19
- const UNIT = "0xb95fB324b8A2fAF8ec4f76e3dF46C718402736e2";
18
+ const COLLATERAL_SLOT = 0; // same for RETH(base) and WBTC(optimism)
20
19
  // https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/token/ERC20/ERC20Upgradeable.sol#L31
21
20
  // https://eips.ethereum.org/EIPS/eip-7201
22
21
  const UNIT_SLOT =
@@ -31,16 +30,26 @@ const testFlatMoney = ({
31
30
  let dhedge: Dhedge;
32
31
  let pool: Pool;
33
32
  let delayOrderContract: Contract;
33
+ let COLLATERAL: string;
34
34
  jest.setTimeout(200000);
35
35
  describe(`flatmoney on ${network}`, () => {
36
36
  beforeAll(async () => {
37
+ await provider.send("evm_mine", []);
37
38
  dhedge = new Dhedge(wallet, network);
38
39
  pool = await dhedge.loadPool(TEST_POOL[network]);
39
40
 
41
+ await runWithImpersonateAccount(
42
+ { provider, account: await pool.managerLogic.manager() },
43
+ async ({ signer }) => {
44
+ await pool.managerLogic.connect(signer).setTrader(wallet.address);
45
+ }
46
+ );
47
+
40
48
  const flatMoneyContracts = flatMoneyContractAddresses[pool.network];
41
49
  if (!flatMoneyContracts) {
42
50
  throw new Error("testFlatMoney: network not supported");
43
51
  }
52
+ COLLATERAL = flatMoneyContracts.COLLATERAL;
44
53
  delayOrderContract = new Contract(
45
54
  flatMoneyContracts.DelayedOrder,
46
55
  DelayedOrderAbi,
@@ -57,14 +66,14 @@ const testFlatMoney = ({
57
66
  await setTokenAmount({
58
67
  amount: new BigNumber(100).times(1e18).toString(),
59
68
  provider,
60
- tokenAddress: RETH,
61
- slot: RETH_SLOT,
69
+ tokenAddress: COLLATERAL,
70
+ slot: COLLATERAL_SLOT,
62
71
  userAddress: pool.address
63
72
  });
64
73
  await setTokenAmount({
65
74
  amount: new BigNumber(100).times(1e18).toString(),
66
75
  provider,
67
- tokenAddress: UNIT,
76
+ tokenAddress: CONTRACT_ADDRESS[network].UNIT,
68
77
  slot: UNIT_SLOT,
69
78
  userAddress: pool.address
70
79
  });
@@ -82,11 +91,11 @@ const testFlatMoney = ({
82
91
  { asset: CONTRACT_ADDRESS[network].USDC, isDeposit: true },
83
92
  { asset: CONTRACT_ADDRESS[network].WETH, isDeposit: true },
84
93
  {
85
- asset: UNIT,
94
+ asset: CONTRACT_ADDRESS[network].UNIT,
86
95
  isDeposit: false
87
96
  },
88
97
  {
89
- asset: RETH,
98
+ asset: COLLATERAL,
90
99
  isDeposit: false
91
100
  }
92
101
  ];
@@ -95,10 +104,14 @@ const testFlatMoney = ({
95
104
 
96
105
  it("mint UNIT", async () => {
97
106
  //approve
98
- await pool.approveSpender(delayOrderContract.address, RETH, MAX_AMOUNT);
107
+ await pool.approveSpender(
108
+ delayOrderContract.address,
109
+ COLLATERAL,
110
+ MAX_AMOUNT
111
+ );
99
112
  const collateralAllowanceDelta = await allowanceDelta(
100
113
  pool.address,
101
- RETH,
114
+ COLLATERAL,
102
115
  delayOrderContract.address,
103
116
  pool.signer
104
117
  );
@@ -129,7 +142,13 @@ const testFlatMoney = ({
129
142
  });
130
143
 
131
144
  it("redeem UNIT", async () => {
132
- const withdrawAmountStr = new BigNumber(2).times(1e18).toString();
145
+ let withdrawAmountStr;
146
+ if (Network.OPTIMISM === network) {
147
+ withdrawAmountStr = new BigNumber(2).times(1e8).toString(); // smaller amount
148
+ } else {
149
+ withdrawAmountStr = new BigNumber(2).times(1e18).toString();
150
+ }
151
+
133
152
  const tx = await pool.redeemUnitViaFlatMoney(
134
153
  withdrawAmountStr,
135
154
  0.5,
@@ -99,13 +99,25 @@ export const getPoolTxOrGasEstimate = async (
99
99
  args: any[],
100
100
  estimateGas: boolean
101
101
  ): Promise<any> => {
102
- if (estimateGas) {
103
- return await pool.poolLogic.estimateGas.execTransaction(
104
- args[0],
105
- args[1],
106
- args[2]
107
- );
102
+ if (pool.isDhedge) {
103
+ if (estimateGas) {
104
+ return await pool.poolLogic.estimateGas.execTransaction(
105
+ args[0],
106
+ args[1],
107
+ args[2]
108
+ );
109
+ } else {
110
+ return await pool.poolLogic.execTransaction(args[0], args[1], args[2]);
111
+ }
108
112
  } else {
109
- return await pool.poolLogic.execTransaction(args[0], args[1], args[2]);
113
+ if (estimateGas) {
114
+ return await pool.signer.estimateGas({ to: args[0], data: args[1] });
115
+ } else {
116
+ return await pool.signer.sendTransaction({
117
+ to: args[0],
118
+ data: args[1],
119
+ ...args[2]
120
+ });
121
+ }
110
122
  }
111
123
  };