@dhedge/v2-sdk 1.1.0 → 1.2.1
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 +60 -3
- package/dist/config.d.ts +2 -0
- package/dist/entities/pool.d.ts +37 -3
- package/dist/entities/utils.d.ts +4 -0
- package/dist/services/claim-balancer/claim.service.d.ts +17 -0
- package/dist/services/claim-balancer/claim.worker.d.ts +4 -0
- package/dist/services/claim-balancer/ipfs.service.d.ts +4 -0
- package/dist/services/claim-balancer/types.d.ts +54 -0
- package/dist/test/constants.d.ts +12 -0
- package/dist/types.d.ts +5 -2
- package/dist/utils/contract.d.ts +14 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/merkle.d.ts +22 -0
- package/dist/v2-sdk.cjs.development.js +3497 -690
- package/dist/v2-sdk.cjs.development.js.map +1 -1
- package/dist/v2-sdk.cjs.production.min.js +1 -1
- package/dist/v2-sdk.cjs.production.min.js.map +1 -1
- package/dist/v2-sdk.esm.js +3497 -690
- package/dist/v2-sdk.esm.js.map +1 -1
- package/package.json +9 -2
- package/src/abi/IAaveIncentivesController.json +50 -0
- package/src/abi/IBalancerMerkleOrchard.json +353 -0
- package/src/abi/IBalancertV2Vault.json +938 -0
- package/src/config.ts +21 -4
- package/src/entities/pool.ts +148 -5
- package/src/entities/utils.ts +135 -0
- package/src/services/claim-balancer/MultiTokenClaim.json +115 -0
- package/src/services/claim-balancer/claim.service.ts +262 -0
- package/src/services/claim-balancer/claim.worker.ts +32 -0
- package/src/services/claim-balancer/ipfs.service.ts +12 -0
- package/src/services/claim-balancer/types.ts +66 -0
- package/src/test/aave.test.ts +73 -0
- package/src/test/balancer.test.ts +109 -0
- package/src/test/constants.ts +13 -0
- package/src/test/oneInch.test.ts +56 -0
- package/src/test/pool.test.ts +5 -244
- package/src/test/sushi.test.ts +173 -0
- package/src/test/utils.test.ts +41 -26
- package/src/types.ts +6 -3
- package/src/utils/contract.ts +95 -0
- package/src/utils/index.ts +38 -0
- package/src/utils/merkle.ts +172 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
import { chunk, flatten } from "lodash";
|
|
4
|
+
import merkleOrchardAbi from "../../abi/IBalancerMerkleOrchard.json";
|
|
5
|
+
import { ethers, Wallet } from "ethers";
|
|
6
|
+
|
|
7
|
+
import { getAddress } from "@ethersproject/address";
|
|
8
|
+
|
|
9
|
+
import { multicall } from "../../utils/contract";
|
|
10
|
+
import { bnum, loadTree, scale } from "../../utils";
|
|
11
|
+
|
|
12
|
+
import { ipfsService } from "./ipfs.service";
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
ClaimProofTuple,
|
|
16
|
+
ClaimStatus,
|
|
17
|
+
ComputeClaimProofPayload,
|
|
18
|
+
MultiTokenPendingClaims,
|
|
19
|
+
Report,
|
|
20
|
+
Snapshot,
|
|
21
|
+
TokenClaimInfo
|
|
22
|
+
} from "./types";
|
|
23
|
+
|
|
24
|
+
import { Network } from "../../types";
|
|
25
|
+
import { networkChainIdMap, stakingAddress } from "../../config";
|
|
26
|
+
import { soliditySha3 } from "web3-utils";
|
|
27
|
+
import { Dapp } from "../..";
|
|
28
|
+
|
|
29
|
+
export class ClaimService {
|
|
30
|
+
network: Network;
|
|
31
|
+
signer: ethers.Wallet;
|
|
32
|
+
public constructor(network: Network, signer: Wallet) {
|
|
33
|
+
this.network = network;
|
|
34
|
+
this.signer = signer;
|
|
35
|
+
}
|
|
36
|
+
public async getMultiTokensPendingClaims(
|
|
37
|
+
account: string
|
|
38
|
+
): Promise<MultiTokenPendingClaims[]> {
|
|
39
|
+
const tokenClaimsInfo = await this.getTokenClaimsInfo();
|
|
40
|
+
if (tokenClaimsInfo != null) {
|
|
41
|
+
const multiTokenPendingClaims = await Promise.all(
|
|
42
|
+
tokenClaimsInfo.map(tokenClaimInfo =>
|
|
43
|
+
this.getTokenPendingClaims(tokenClaimInfo, getAddress(account))
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const multiTokenPendingClaimsWithRewards = multiTokenPendingClaims.filter(
|
|
48
|
+
pendingClaim => Number(pendingClaim.availableToClaim) > 0
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
return multiTokenPendingClaimsWithRewards;
|
|
52
|
+
}
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public async getTokenPendingClaims(
|
|
57
|
+
tokenClaimInfo: TokenClaimInfo,
|
|
58
|
+
account: string
|
|
59
|
+
): Promise<MultiTokenPendingClaims> {
|
|
60
|
+
const snapshot = await this.getSnapshot(tokenClaimInfo.manifest);
|
|
61
|
+
const weekStart = tokenClaimInfo.weekStart;
|
|
62
|
+
const claimStatus = await this.getClaimStatus(
|
|
63
|
+
Object.keys(snapshot).length,
|
|
64
|
+
account,
|
|
65
|
+
tokenClaimInfo
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const pendingWeeks = claimStatus
|
|
69
|
+
.map((status, i) => [i + weekStart, status])
|
|
70
|
+
.filter(([, status]) => !status)
|
|
71
|
+
.map(([i]) => i) as number[];
|
|
72
|
+
|
|
73
|
+
const reports = await this.getReports(snapshot, pendingWeeks);
|
|
74
|
+
|
|
75
|
+
const claims = Object.entries(reports)
|
|
76
|
+
.filter((report: Report) => report[1][account])
|
|
77
|
+
.map((report: Report) => {
|
|
78
|
+
return {
|
|
79
|
+
id: report[0],
|
|
80
|
+
amount: report[1][account]
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
//console.log("claims", claims);
|
|
85
|
+
|
|
86
|
+
const availableToClaim = claims
|
|
87
|
+
.map(claim => parseFloat(claim.amount))
|
|
88
|
+
.reduce((total, amount) => total.plus(amount), bnum(0))
|
|
89
|
+
.toString();
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
claims,
|
|
93
|
+
reports,
|
|
94
|
+
tokenClaimInfo,
|
|
95
|
+
availableToClaim
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public async multiTokenClaimRewards(
|
|
100
|
+
account: string,
|
|
101
|
+
multiTokenPendingClaims: MultiTokenPendingClaims[]
|
|
102
|
+
): Promise<any> {
|
|
103
|
+
try {
|
|
104
|
+
const multiTokenClaims = await Promise.all(
|
|
105
|
+
multiTokenPendingClaims.map((tokenPendingClaims, tokenIndex) =>
|
|
106
|
+
this.computeClaimProofs(
|
|
107
|
+
tokenPendingClaims,
|
|
108
|
+
getAddress(account),
|
|
109
|
+
tokenIndex
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return flatten(multiTokenClaims);
|
|
115
|
+
} catch (e) {
|
|
116
|
+
console.log("[Claim] Claim Rewards Error:", e);
|
|
117
|
+
return Promise.reject(e);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private async computeClaimProofs(
|
|
122
|
+
tokenPendingClaims: MultiTokenPendingClaims,
|
|
123
|
+
account: string,
|
|
124
|
+
tokenIndex: number
|
|
125
|
+
): Promise<Promise<ClaimProofTuple[]>> {
|
|
126
|
+
return Promise.all(
|
|
127
|
+
tokenPendingClaims.claims.map(claim => {
|
|
128
|
+
const payload: ComputeClaimProofPayload = {
|
|
129
|
+
account,
|
|
130
|
+
distributor: tokenPendingClaims.tokenClaimInfo.distributor,
|
|
131
|
+
tokenIndex,
|
|
132
|
+
decimals: tokenPendingClaims.tokenClaimInfo.decimals,
|
|
133
|
+
// objects must be cloned
|
|
134
|
+
report: { ...tokenPendingClaims.reports[claim.id] },
|
|
135
|
+
claim: { ...claim }
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
return this.computeClaimProof(payload);
|
|
139
|
+
})
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private computeClaimProof(
|
|
144
|
+
payload: ComputeClaimProofPayload
|
|
145
|
+
): ClaimProofTuple {
|
|
146
|
+
const {
|
|
147
|
+
report,
|
|
148
|
+
account,
|
|
149
|
+
claim,
|
|
150
|
+
distributor,
|
|
151
|
+
tokenIndex,
|
|
152
|
+
decimals
|
|
153
|
+
} = payload;
|
|
154
|
+
|
|
155
|
+
const claimAmount = claim.amount;
|
|
156
|
+
const merkleTree = loadTree(report, decimals);
|
|
157
|
+
|
|
158
|
+
const scaledBalance = scale(claimAmount, decimals).toString(10);
|
|
159
|
+
|
|
160
|
+
const proof = merkleTree.getHexProof(
|
|
161
|
+
soliditySha3(
|
|
162
|
+
{ t: "address", v: account },
|
|
163
|
+
{ t: "uint", v: scaledBalance }
|
|
164
|
+
)
|
|
165
|
+
);
|
|
166
|
+
return [
|
|
167
|
+
parseInt(claim.id),
|
|
168
|
+
scaledBalance,
|
|
169
|
+
distributor,
|
|
170
|
+
tokenIndex,
|
|
171
|
+
proof
|
|
172
|
+
] as ClaimProofTuple;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private async getTokenClaimsInfo() {
|
|
176
|
+
let tokenClaims;
|
|
177
|
+
try {
|
|
178
|
+
const multiTokenClaim = await axios.get(
|
|
179
|
+
"https://raw.githubusercontent.com/balancer-labs/frontend-v2/develop/src/services/claim/MultiTokenClaim.json"
|
|
180
|
+
);
|
|
181
|
+
const chainId = networkChainIdMap[this.network];
|
|
182
|
+
tokenClaims = multiTokenClaim.data[chainId];
|
|
183
|
+
} catch (e) {
|
|
184
|
+
console.log("balancer multi token info error", e);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (tokenClaims != null) {
|
|
188
|
+
return (tokenClaims as TokenClaimInfo[]).map(tokenClaim => ({
|
|
189
|
+
...tokenClaim,
|
|
190
|
+
token: getAddress(tokenClaim.token),
|
|
191
|
+
decimals: 18
|
|
192
|
+
}));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private async getSnapshot(manifest: string) {
|
|
199
|
+
try {
|
|
200
|
+
const response = await axios.get<Snapshot>(manifest);
|
|
201
|
+
return response.data || {};
|
|
202
|
+
} catch (error) {
|
|
203
|
+
return {};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private async getClaimStatus(
|
|
208
|
+
totalWeeks: number,
|
|
209
|
+
account: string,
|
|
210
|
+
tokenClaimInfo: TokenClaimInfo
|
|
211
|
+
): Promise<ClaimStatus[]> {
|
|
212
|
+
const { token, distributor, weekStart } = tokenClaimInfo;
|
|
213
|
+
|
|
214
|
+
const claimStatusCalls = Array.from({ length: totalWeeks }).map((_, i) => [
|
|
215
|
+
stakingAddress[this.network][Dapp.BALANCER],
|
|
216
|
+
"isClaimed",
|
|
217
|
+
[token, distributor, weekStart + i, account]
|
|
218
|
+
]);
|
|
219
|
+
|
|
220
|
+
const rootCalls = Array.from({ length: totalWeeks }).map((_, i) => [
|
|
221
|
+
stakingAddress[this.network][Dapp.BALANCER],
|
|
222
|
+
"getDistributionRoot",
|
|
223
|
+
[token, distributor, weekStart + i]
|
|
224
|
+
]);
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
const result = (await multicall<boolean | string>(
|
|
228
|
+
this.network,
|
|
229
|
+
this.signer,
|
|
230
|
+
merkleOrchardAbi.abi,
|
|
231
|
+
[...claimStatusCalls, ...rootCalls],
|
|
232
|
+
{},
|
|
233
|
+
true
|
|
234
|
+
)) as (boolean | string)[];
|
|
235
|
+
|
|
236
|
+
if (result.length > 0) {
|
|
237
|
+
const chunks = chunk(flatten(result), totalWeeks);
|
|
238
|
+
|
|
239
|
+
const claimedResult = chunks[0] as boolean[];
|
|
240
|
+
const distributionRootResult = chunks[1] as string[];
|
|
241
|
+
|
|
242
|
+
return claimedResult.filter(
|
|
243
|
+
(_, index) =>
|
|
244
|
+
distributionRootResult[index] !== ethers.constants.HashZero
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
} catch (e) {
|
|
248
|
+
console.log("[Claim] Claim Status Error:", e);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return [];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private async getReports(snapshot: Snapshot, weeks: number[]) {
|
|
255
|
+
const reports = await Promise.all<Report>(
|
|
256
|
+
weeks
|
|
257
|
+
.filter(week => snapshot[week] != null)
|
|
258
|
+
.map(week => ipfsService.get(snapshot[week]))
|
|
259
|
+
);
|
|
260
|
+
return Object.fromEntries(reports.map((report, i) => [weeks[i], report]));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Shamelessly adapted from OpenZeppelin-contracts test utils
|
|
2
|
+
import { soliditySha3 } from "web3-utils";
|
|
3
|
+
import { loadTree, scale } from "../../utils";
|
|
4
|
+
|
|
5
|
+
import { ComputeClaimProofPayload } from "./types";
|
|
6
|
+
|
|
7
|
+
export class ClaimWorker {
|
|
8
|
+
public calcClaimProof(payload: ComputeClaimProofPayload): any {
|
|
9
|
+
const {
|
|
10
|
+
report,
|
|
11
|
+
account,
|
|
12
|
+
claim,
|
|
13
|
+
distributor,
|
|
14
|
+
tokenIndex,
|
|
15
|
+
decimals
|
|
16
|
+
} = payload;
|
|
17
|
+
|
|
18
|
+
const claimAmount = claim.amount;
|
|
19
|
+
const merkleTree = loadTree(report, decimals);
|
|
20
|
+
|
|
21
|
+
const scaledBalance = scale(claimAmount, decimals).toString(10);
|
|
22
|
+
|
|
23
|
+
const proof = merkleTree.getHexProof(
|
|
24
|
+
soliditySha3(
|
|
25
|
+
{ t: "address", v: account },
|
|
26
|
+
{ t: "uint", v: scaledBalance }
|
|
27
|
+
)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return [parseInt(claim.id), scaledBalance, distributor, tokenIndex, proof];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
|
|
3
|
+
export default class IpfsService {
|
|
4
|
+
async get<T>(hash: string, protocol = "ipfs"): Promise<T> {
|
|
5
|
+
const { data } = await axios.get(
|
|
6
|
+
`https://cloudflare-ipfs.com/${protocol}/${hash}`
|
|
7
|
+
);
|
|
8
|
+
return data;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const ipfsService = new IpfsService();
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export interface Claim {
|
|
2
|
+
id: string;
|
|
3
|
+
amount: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type Snapshot = Record<number, string>;
|
|
7
|
+
|
|
8
|
+
export type TokenClaimInfo = {
|
|
9
|
+
label: string;
|
|
10
|
+
distributor: string;
|
|
11
|
+
token: string;
|
|
12
|
+
decimals: number;
|
|
13
|
+
manifest: string;
|
|
14
|
+
weekStart: number;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type MultiTokenPendingClaims = {
|
|
18
|
+
claims: Claim[];
|
|
19
|
+
reports: Report;
|
|
20
|
+
tokenClaimInfo: TokenClaimInfo;
|
|
21
|
+
availableToClaim: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type ClaimStatus = boolean;
|
|
25
|
+
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
export type Report = Record<string, any>;
|
|
28
|
+
|
|
29
|
+
export type MultiTokenCurrentRewardsEstimateResponse = {
|
|
30
|
+
success: boolean;
|
|
31
|
+
result: {
|
|
32
|
+
current_timestamp: string;
|
|
33
|
+
"liquidity-providers": Array<{
|
|
34
|
+
snapshot_timestamp: string;
|
|
35
|
+
address: string;
|
|
36
|
+
token_address: string;
|
|
37
|
+
chain_id: number;
|
|
38
|
+
current_estimate: string;
|
|
39
|
+
velocity: string;
|
|
40
|
+
week: number;
|
|
41
|
+
}>;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type MultiTokenCurrentRewardsEstimate = {
|
|
46
|
+
rewards: string;
|
|
47
|
+
velocity: string;
|
|
48
|
+
token: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type ClaimProofTuple = [number, string, string, number, string[]]; // claimId, claimAmount, distributor, tokenIndex, proof
|
|
52
|
+
|
|
53
|
+
export type ComputeClaimProofPayload = {
|
|
54
|
+
report: Report;
|
|
55
|
+
account: string;
|
|
56
|
+
claim: Claim;
|
|
57
|
+
distributor: string;
|
|
58
|
+
tokenIndex: number;
|
|
59
|
+
decimals: number;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
63
|
+
export type ClaimWorkerMessage<P = any> = {
|
|
64
|
+
type: "computeClaimProof";
|
|
65
|
+
payload: P;
|
|
66
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Dhedge, ethers } from "..";
|
|
2
|
+
import { Network } from "../types";
|
|
3
|
+
import { AMUSDC, TEST_POOL, VDEBTWETH } from "./constants";
|
|
4
|
+
|
|
5
|
+
import { wallet } from "./wallet";
|
|
6
|
+
|
|
7
|
+
let dhedge: Dhedge;
|
|
8
|
+
|
|
9
|
+
jest.setTimeout(100000);
|
|
10
|
+
|
|
11
|
+
const options = {
|
|
12
|
+
gasLimit: 5000000,
|
|
13
|
+
gasPrice: ethers.utils.parseUnits("100", "gwei")
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe("pool", () => {
|
|
17
|
+
beforeAll(() => {
|
|
18
|
+
dhedge = new Dhedge(wallet, Network.POLYGON);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// it("withdraws 1 USDC from Aave lending pool", async () => {
|
|
22
|
+
// let result;
|
|
23
|
+
// const pool = await dhedge.loadPool(myPool);
|
|
24
|
+
// try {
|
|
25
|
+
// result = await pool.withdrawDeposit(
|
|
26
|
+
// Dapp.AAVE,
|
|
27
|
+
// weth,
|
|
28
|
+
// "86567951006165",
|
|
29
|
+
// options
|
|
30
|
+
// );
|
|
31
|
+
// console.log(result);
|
|
32
|
+
// } catch (e) {
|
|
33
|
+
// console.log(e);
|
|
34
|
+
// }
|
|
35
|
+
// expect(result).not.toBe(null);
|
|
36
|
+
// });
|
|
37
|
+
|
|
38
|
+
// it("borrows 0.0001 WETH from Aave lending pool", async () => {
|
|
39
|
+
// let result;
|
|
40
|
+
// const pool = await dhedge.loadPool(myPool);
|
|
41
|
+
// try {
|
|
42
|
+
// result = await pool.borrow(Dapp.AAVE, weth, "100000000000000");
|
|
43
|
+
// console.log(result);
|
|
44
|
+
// } catch (e) {
|
|
45
|
+
// console.log(e);
|
|
46
|
+
// }
|
|
47
|
+
// expect(result).not.toBe(null);
|
|
48
|
+
// });
|
|
49
|
+
|
|
50
|
+
// it("reapys 0.0001 WETH to Aave lending pool", async () => {
|
|
51
|
+
// let result;
|
|
52
|
+
// const pool = await dhedge.loadPool(myPool);
|
|
53
|
+
// try {
|
|
54
|
+
// result = await pool.repay(Dapp.AAVE, weth, "100000000000000", options);
|
|
55
|
+
// console.log(result);
|
|
56
|
+
// } catch (e) {
|
|
57
|
+
// console.log(e);
|
|
58
|
+
// }
|
|
59
|
+
// expect(result).not.toBe(null);
|
|
60
|
+
// });
|
|
61
|
+
|
|
62
|
+
it("claims rewards from Aave", async () => {
|
|
63
|
+
let result;
|
|
64
|
+
const pool = await dhedge.loadPool(TEST_POOL);
|
|
65
|
+
try {
|
|
66
|
+
result = await pool.harvestAaveRewards([AMUSDC, VDEBTWETH], options);
|
|
67
|
+
console.log(result);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.log(e);
|
|
70
|
+
}
|
|
71
|
+
expect(result).not.toBe(null);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Dhedge, ethers } from "..";
|
|
2
|
+
import { Network } from "../types";
|
|
3
|
+
import { TEST_POOL } from "./constants";
|
|
4
|
+
|
|
5
|
+
import { wallet } from "./wallet";
|
|
6
|
+
|
|
7
|
+
let dhedge: Dhedge;
|
|
8
|
+
|
|
9
|
+
jest.setTimeout(100000);
|
|
10
|
+
|
|
11
|
+
const options = {
|
|
12
|
+
gasLimit: 2000000,
|
|
13
|
+
gasPrice: ethers.utils.parseUnits("1000", "gwei")
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe("pool", () => {
|
|
17
|
+
beforeAll(() => {
|
|
18
|
+
dhedge = new Dhedge(wallet, Network.POLYGON);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// it("approves unlimited USDC on Balancer", async () => {
|
|
22
|
+
// let result;
|
|
23
|
+
// const pool = await dhedge.loadPool(TEST_POOL);
|
|
24
|
+
// try {
|
|
25
|
+
// result = await pool.approve(
|
|
26
|
+
// Dapp.BALANCER,
|
|
27
|
+
// USDC,
|
|
28
|
+
// ethers.constants.MaxInt256,
|
|
29
|
+
// options
|
|
30
|
+
// );
|
|
31
|
+
// console.log(result);
|
|
32
|
+
// } catch (e) {
|
|
33
|
+
// console.log(e);
|
|
34
|
+
// }
|
|
35
|
+
// expect(result).not.toBe(null);
|
|
36
|
+
// });
|
|
37
|
+
|
|
38
|
+
// it("trades 2 USDC into SUSHI on Balancer", async () => {
|
|
39
|
+
// let result;
|
|
40
|
+
// const pool = await dhedge.loadPool(myPool);
|
|
41
|
+
// try {
|
|
42
|
+
// result = await pool.trade(
|
|
43
|
+
// Dapp.BALANCER,
|
|
44
|
+
// usdc,
|
|
45
|
+
// sushi,
|
|
46
|
+
// "2000000",
|
|
47
|
+
// 0.5,
|
|
48
|
+
// options
|
|
49
|
+
// );
|
|
50
|
+
// console.log(result);
|
|
51
|
+
// } catch (e) {
|
|
52
|
+
// console.log(e);
|
|
53
|
+
// }
|
|
54
|
+
// expect(result).not.toBe(null);
|
|
55
|
+
// });
|
|
56
|
+
|
|
57
|
+
// it("adds 1 USDC to a USDC/TUSD/DAI/USDT balancer pool", async () => {
|
|
58
|
+
// let result;
|
|
59
|
+
// const pool = await dhedge.loadPool(TEST_POOL);
|
|
60
|
+
// const assets = [USDC, TUSD, DAI, USDT];
|
|
61
|
+
// const amounts = ["1000000", "0", "0", "0"];
|
|
62
|
+
// try {
|
|
63
|
+
// result = await pool.joinBalancerPool(
|
|
64
|
+
// "0x0d34e5dd4d8f043557145598e4e2dc286b35fd4f000000000000000000000068",
|
|
65
|
+
// assets,
|
|
66
|
+
// amounts,
|
|
67
|
+
// options
|
|
68
|
+
// );
|
|
69
|
+
// console.log("result", result);
|
|
70
|
+
// } catch (e) {
|
|
71
|
+
// console.log(e);
|
|
72
|
+
// }
|
|
73
|
+
// expect(result).not.toBe(null);
|
|
74
|
+
// });
|
|
75
|
+
|
|
76
|
+
// it("exits entire balance of WBTC/USDC/WETH balancer pool", async () => {
|
|
77
|
+
// let result;
|
|
78
|
+
// const pool = await dhedge.loadPool(myPool);
|
|
79
|
+
// const assets = [wbtc, usdc, weth];
|
|
80
|
+
// const amount = await dhedge.utils.getBalance(
|
|
81
|
+
// "0x03cd191f589d12b0582a99808cf19851e468e6b5",
|
|
82
|
+
// pool.address
|
|
83
|
+
// );
|
|
84
|
+
// try {
|
|
85
|
+
// result = await pool.exitBalancerPool(
|
|
86
|
+
// "0x03cd191f589d12b0582a99808cf19851e468e6b500010000000000000000000a",
|
|
87
|
+
// assets,
|
|
88
|
+
// amount,
|
|
89
|
+
// options
|
|
90
|
+
// );
|
|
91
|
+
// console.log("result", result);
|
|
92
|
+
// } catch (e) {
|
|
93
|
+
// console.log(e);
|
|
94
|
+
// }
|
|
95
|
+
// expect(result).not.toBe(null);
|
|
96
|
+
// });
|
|
97
|
+
|
|
98
|
+
it("claims balancer rewards", async () => {
|
|
99
|
+
let result;
|
|
100
|
+
const pool = await dhedge.loadPool(TEST_POOL);
|
|
101
|
+
try {
|
|
102
|
+
result = await pool.harvestBalancerRewards(options);
|
|
103
|
+
console.log("result", result);
|
|
104
|
+
} catch (e) {
|
|
105
|
+
console.log(e);
|
|
106
|
+
}
|
|
107
|
+
expect(result).not.toBe(null);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
|
|
2
|
+
export const USDT = "0xc2132D05D31c914a87C6611C10748AEb04B58e8F";
|
|
3
|
+
export const DAI = "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063";
|
|
4
|
+
export const TUSD = "0x2e1ad108ff1d8c782fcbbb89aad783ac49586756";
|
|
5
|
+
export const WETH = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619";
|
|
6
|
+
export const WBTC = "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6";
|
|
7
|
+
export const SUSHI = "0x0b3f868e0be5597d5db7feb59e1cadbb0fdda50a";
|
|
8
|
+
export const WMATIC = "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270";
|
|
9
|
+
export const BAL = "0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3";
|
|
10
|
+
export const AMUSDC = "0x1a13f4ca1d028320a707d99520abfefca3998b7f";
|
|
11
|
+
export const VDEBTWETH = "0xede17e9d79fc6f9ff9250d9eefbdb88cc18038b5";
|
|
12
|
+
|
|
13
|
+
export const TEST_POOL = "0x3deeba9ca29e2dd98d32eed8dd559dac55014615";
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Dhedge, ethers } from "..";
|
|
2
|
+
import { Dapp, Network } from "../types";
|
|
3
|
+
import { TEST_POOL, USDC, WETH } from "./constants";
|
|
4
|
+
|
|
5
|
+
import { wallet } from "./wallet";
|
|
6
|
+
|
|
7
|
+
let dhedge: Dhedge;
|
|
8
|
+
|
|
9
|
+
jest.setTimeout(100000);
|
|
10
|
+
|
|
11
|
+
const options = {
|
|
12
|
+
gasLimit: 5000000,
|
|
13
|
+
gasPrice: ethers.utils.parseUnits("35", "gwei")
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe("pool", () => {
|
|
17
|
+
beforeAll(() => {
|
|
18
|
+
dhedge = new Dhedge(wallet, Network.POLYGON);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// it("approves unlimited USDC on 1Inch", async () => {
|
|
22
|
+
// let result;
|
|
23
|
+
// const pool = await dhedge.loadPool(TEST_POOL);
|
|
24
|
+
// try {
|
|
25
|
+
// result = await pool.approve(
|
|
26
|
+
// Dapp.ONEINCH,
|
|
27
|
+
// USDC,
|
|
28
|
+
// ethers.constants.MaxInt256,
|
|
29
|
+
// options
|
|
30
|
+
// );
|
|
31
|
+
// console.log(result);
|
|
32
|
+
// } catch (e) {
|
|
33
|
+
// console.log(e);
|
|
34
|
+
// }
|
|
35
|
+
// expect(result).not.toBe(null);
|
|
36
|
+
// });
|
|
37
|
+
|
|
38
|
+
it("trades 1 USDC into WETH on 1Inch", async () => {
|
|
39
|
+
let result;
|
|
40
|
+
const pool = await dhedge.loadPool(TEST_POOL);
|
|
41
|
+
try {
|
|
42
|
+
result = await pool.trade(
|
|
43
|
+
Dapp.ONEINCH,
|
|
44
|
+
USDC,
|
|
45
|
+
WETH,
|
|
46
|
+
"1000000",
|
|
47
|
+
0.5,
|
|
48
|
+
options
|
|
49
|
+
);
|
|
50
|
+
console.log("1inch trade", result);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
console.log(e);
|
|
53
|
+
}
|
|
54
|
+
expect(result).not.toBe(null);
|
|
55
|
+
});
|
|
56
|
+
});
|