@dhedge/v2-sdk 1.5.3 → 1.7.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/dist/config.d.ts +2 -1
- package/dist/entities/pool.d.ts +44 -2
- package/dist/entities/utils.d.ts +7 -2
- package/dist/services/lyra/markets.d.ts +6 -0
- package/dist/services/lyra/positions.d.ts +2 -0
- package/dist/services/lyra/quote.d.ts +4 -0
- package/dist/services/lyra/trade.d.ts +4 -0
- package/dist/services/lyra/tradeOptionType.d.ts +3 -0
- package/dist/services/velodrome/liquidity.d.ts +4 -0
- package/dist/services/velodrome/staking.d.ts +4 -0
- package/dist/test/constants.d.ts +3 -0
- package/dist/types.d.ts +21 -1
- package/dist/v2-sdk.cjs.development.js +6701 -291
- 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 +6699 -290
- package/dist/v2-sdk.esm.js.map +1 -1
- package/package.json +6 -2
- package/src/abi/IOptionMArketWrapper.json +1038 -0
- package/src/abi/IOptionMarket.json +1473 -0
- package/src/abi/IOptionToken.json +1671 -0
- package/src/abi/IVeldodromeRouter.json +438 -0
- package/src/abi/IVelodromeGauge.json +559 -0
- package/src/config.ts +11 -5
- package/src/entities/pool.ts +167 -20
- package/src/entities/utils.ts +45 -2
- package/src/services/lyra/markets.ts +52 -0
- package/src/services/lyra/positions.ts +19 -0
- package/src/services/lyra/quote.ts +12 -0
- package/src/services/lyra/trade.ts +101 -0
- package/src/services/lyra/tradeOptionType.ts +19 -0
- package/src/services/velodrome/liquidity.ts +48 -0
- package/src/services/velodrome/staking.ts +31 -0
- package/src/test/constants.ts +3 -0
- package/src/test/lyra.test.ts +163 -0
- package/src/test/pool.test.ts +1 -1
- package/src/test/toros.test.ts +1 -1
- package/src/test/txOptions.ts +1 -1
- package/src/test/uniswap.test.ts +1 -1
- package/src/test/velodrome.test.ts +141 -0
- package/src/test/wallet.ts +8 -0
- package/src/types.ts +21 -1
- package/src/test/sushi.test.ts +0 -173
package/src/entities/pool.ts
CHANGED
|
@@ -29,7 +29,11 @@ import {
|
|
|
29
29
|
Transaction,
|
|
30
30
|
FundComposition,
|
|
31
31
|
AssetEnabled,
|
|
32
|
-
Network
|
|
32
|
+
Network,
|
|
33
|
+
LyraOptionMarket,
|
|
34
|
+
LyraOptionType,
|
|
35
|
+
LyraTradeType,
|
|
36
|
+
LyraPosition
|
|
33
37
|
} from "../types";
|
|
34
38
|
|
|
35
39
|
import { Utils } from "./utils";
|
|
@@ -43,6 +47,16 @@ import { getUniswapV3SwapTxData } from "../services/uniswap/V3Trade";
|
|
|
43
47
|
import { getEasySwapperTxData } from "../services/toros/easySwapper";
|
|
44
48
|
import { getOneInchProtocols } from "../services/oneInch/protocols";
|
|
45
49
|
import { getAaveV3ClaimTxData } from "../services/aave/incentives";
|
|
50
|
+
import {
|
|
51
|
+
getVelodromeAddLiquidityTxData,
|
|
52
|
+
getVelodromeRemoveLiquidityTxData
|
|
53
|
+
} from "../services/velodrome/liquidity";
|
|
54
|
+
import {
|
|
55
|
+
getVelodromeClaimTxData,
|
|
56
|
+
getVelodromeStakeTxData
|
|
57
|
+
} from "../services/velodrome/staking";
|
|
58
|
+
import { getLyraOptionTxData } from "../services/lyra/trade";
|
|
59
|
+
import { getOptionPositions } from "../services/lyra/positions";
|
|
46
60
|
|
|
47
61
|
export class Pool {
|
|
48
62
|
public readonly poolLogic: Contract;
|
|
@@ -430,20 +444,34 @@ export class Pool {
|
|
|
430
444
|
|
|
431
445
|
/**
|
|
432
446
|
* Stake liquidity pool tokens in gauge contract
|
|
447
|
+
* @param {Dapp} dapp Platform like Balancer or Velodrome
|
|
433
448
|
* @param {string} gauge Gauge contract address
|
|
434
449
|
* @param {BigNumber | string} amount Amount of liquidity pool tokens
|
|
435
450
|
* @param {any} options Transaction options
|
|
436
451
|
* @returns {Promise<any>} Transaction
|
|
437
452
|
*/
|
|
438
453
|
async stakeInGauge(
|
|
454
|
+
dapp: Dapp,
|
|
439
455
|
gauge: string,
|
|
440
456
|
amount: BigNumber | string,
|
|
441
457
|
options: any = null
|
|
442
458
|
): Promise<any> {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
459
|
+
let stakeTxData;
|
|
460
|
+
switch (dapp) {
|
|
461
|
+
case Dapp.BALANCER:
|
|
462
|
+
const rewardsGauge = new ethers.utils.Interface(
|
|
463
|
+
IBalancerRewardsGauge.abi
|
|
464
|
+
);
|
|
465
|
+
stakeTxData = rewardsGauge.encodeFunctionData("deposit(uint256)", [
|
|
466
|
+
amount
|
|
467
|
+
]);
|
|
468
|
+
break;
|
|
469
|
+
case Dapp.VELODROME:
|
|
470
|
+
stakeTxData = getVelodromeStakeTxData(amount);
|
|
471
|
+
break;
|
|
472
|
+
default:
|
|
473
|
+
throw new Error("dapp not supported");
|
|
474
|
+
}
|
|
447
475
|
const tx = await this.poolLogic.execTransaction(
|
|
448
476
|
gauge,
|
|
449
477
|
stakeTxData,
|
|
@@ -1020,21 +1048,29 @@ export class Pool {
|
|
|
1020
1048
|
): Promise<any> {
|
|
1021
1049
|
let txData;
|
|
1022
1050
|
let contractAddress;
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1051
|
+
switch (dapp) {
|
|
1052
|
+
case Dapp.UNISWAPV3:
|
|
1053
|
+
contractAddress = nonfungiblePositionManagerAddress[this.network];
|
|
1054
|
+
const iNonfungiblePositionManager = new ethers.utils.Interface(
|
|
1055
|
+
INonfungiblePositionManager.abi
|
|
1056
|
+
);
|
|
1057
|
+
txData = iNonfungiblePositionManager.encodeFunctionData(
|
|
1058
|
+
Transaction.COLLECT,
|
|
1059
|
+
[[tokenId, this.address, MaxUint128, MaxUint128]]
|
|
1060
|
+
);
|
|
1061
|
+
break;
|
|
1062
|
+
case Dapp.ARRAKIS:
|
|
1063
|
+
case Dapp.BALANCER:
|
|
1064
|
+
contractAddress = tokenId;
|
|
1065
|
+
const abi = new ethers.utils.Interface(ILiquidityGaugeV4.abi);
|
|
1066
|
+
txData = abi.encodeFunctionData("claim_rewards()", []);
|
|
1067
|
+
break;
|
|
1068
|
+
case Dapp.VELODROME:
|
|
1069
|
+
contractAddress = tokenId;
|
|
1070
|
+
txData = getVelodromeClaimTxData(this, tokenId);
|
|
1071
|
+
break;
|
|
1072
|
+
default:
|
|
1073
|
+
throw new Error("dapp not supported");
|
|
1038
1074
|
}
|
|
1039
1075
|
const tx = await this.poolLogic.execTransaction(
|
|
1040
1076
|
contractAddress,
|
|
@@ -1078,4 +1114,115 @@ export class Pool {
|
|
|
1078
1114
|
);
|
|
1079
1115
|
return tx;
|
|
1080
1116
|
}
|
|
1117
|
+
|
|
1118
|
+
/**
|
|
1119
|
+
* Add liquidity to Velodrome pool
|
|
1120
|
+
* @param {string} assetA First asset
|
|
1121
|
+
* @param {string} assetB Second asset
|
|
1122
|
+
* @param {BigNumber | string} amountA Amount first asset
|
|
1123
|
+
* @param {BigNumber | string} amountB Amount second asset
|
|
1124
|
+
* @param { boolean } isStable Is stable pool
|
|
1125
|
+
* @param {any} options Transaction options
|
|
1126
|
+
* @returns {Promise<any>} Transaction
|
|
1127
|
+
*/
|
|
1128
|
+
async addLiquidityVelodrome(
|
|
1129
|
+
assetA: string,
|
|
1130
|
+
assetB: string,
|
|
1131
|
+
amountA: BigNumber | string,
|
|
1132
|
+
amountB: BigNumber | string,
|
|
1133
|
+
isStable: boolean,
|
|
1134
|
+
options: any = null
|
|
1135
|
+
): Promise<any> {
|
|
1136
|
+
const tx = await this.poolLogic.execTransaction(
|
|
1137
|
+
routerAddress[this.network][Dapp.VELODROME],
|
|
1138
|
+
getVelodromeAddLiquidityTxData(
|
|
1139
|
+
this,
|
|
1140
|
+
assetA,
|
|
1141
|
+
assetB,
|
|
1142
|
+
amountA,
|
|
1143
|
+
amountB,
|
|
1144
|
+
isStable
|
|
1145
|
+
),
|
|
1146
|
+
options
|
|
1147
|
+
);
|
|
1148
|
+
return tx;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* Remove liquidity from Velodrome pool
|
|
1153
|
+
* @param {string} assetA First asset
|
|
1154
|
+
* @param {string} assetB Second asset
|
|
1155
|
+
* @param {BigNumber | string} amount Amount of LP tokens
|
|
1156
|
+
* @param { boolean } isStable Is stable pool
|
|
1157
|
+
* @param {any} options Transaction options
|
|
1158
|
+
* @returns {Promise<any>} Transaction
|
|
1159
|
+
*/
|
|
1160
|
+
async removeLiquidityVelodrome(
|
|
1161
|
+
assetA: string,
|
|
1162
|
+
assetB: string,
|
|
1163
|
+
amount: BigNumber | string,
|
|
1164
|
+
isStable: boolean,
|
|
1165
|
+
options: any = null
|
|
1166
|
+
): Promise<any> {
|
|
1167
|
+
const tx = await this.poolLogic.execTransaction(
|
|
1168
|
+
routerAddress[this.network][Dapp.VELODROME],
|
|
1169
|
+
getVelodromeRemoveLiquidityTxData(this, assetA, assetB, amount, isStable),
|
|
1170
|
+
options
|
|
1171
|
+
);
|
|
1172
|
+
return tx;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
/**
|
|
1176
|
+
* Trade options on lyra
|
|
1177
|
+
* @param {LyraOptionMarket} market Underlying market e.g. eth
|
|
1178
|
+
* @param {number} expiry Expiry timestamp
|
|
1179
|
+
* @param { number} strike Strike price
|
|
1180
|
+
* @param {LyraOptionType} optionType Call or put
|
|
1181
|
+
* @param { LyraTradeType} tradeType By or sell
|
|
1182
|
+
* @param {BigNumber | string } optionAmount Option amount
|
|
1183
|
+
* @param {string } assetIn Asset to invest
|
|
1184
|
+
* @param {BigNumber | string } collateralChangeAmount Collateral amount to add when shorting options and to remove when covering shorts
|
|
1185
|
+
* @param {boolean} isCoveredCall Selling covered call options
|
|
1186
|
+
* @param {any} options Transaction options
|
|
1187
|
+
* @returns {Promise<any>} Transaction
|
|
1188
|
+
*/
|
|
1189
|
+
async tradeLyraOption(
|
|
1190
|
+
market: LyraOptionMarket,
|
|
1191
|
+
expiry: number,
|
|
1192
|
+
strike: number,
|
|
1193
|
+
optionType: LyraOptionType,
|
|
1194
|
+
tradeType: LyraTradeType,
|
|
1195
|
+
optionAmount: BigNumber | string,
|
|
1196
|
+
assetIn: string,
|
|
1197
|
+
collateralChangeAmount: BigNumber | string = "0",
|
|
1198
|
+
isCoveredCall = false,
|
|
1199
|
+
options: any = null
|
|
1200
|
+
): Promise<any> {
|
|
1201
|
+
const swapxData = await getLyraOptionTxData(
|
|
1202
|
+
this,
|
|
1203
|
+
market,
|
|
1204
|
+
optionType,
|
|
1205
|
+
expiry,
|
|
1206
|
+
strike,
|
|
1207
|
+
tradeType,
|
|
1208
|
+
optionAmount,
|
|
1209
|
+
assetIn,
|
|
1210
|
+
BigNumber.from(collateralChangeAmount),
|
|
1211
|
+
isCoveredCall
|
|
1212
|
+
);
|
|
1213
|
+
const tx = await this.poolLogic.execTransaction(
|
|
1214
|
+
routerAddress[this.network][Dapp.LYRA],
|
|
1215
|
+
swapxData,
|
|
1216
|
+
options
|
|
1217
|
+
);
|
|
1218
|
+
return tx;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
/**
|
|
1222
|
+
* Gets Lyra option positions
|
|
1223
|
+
* @returns {Promise<Position>} Transaction
|
|
1224
|
+
*/
|
|
1225
|
+
async getLyraPositions(market: LyraOptionMarket): Promise<LyraPosition[]> {
|
|
1226
|
+
return await getOptionPositions(this, market);
|
|
1227
|
+
}
|
|
1081
1228
|
}
|
package/src/entities/utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Contract, ethers, Wallet } from "ethers";
|
|
1
|
+
import { BigNumber, Contract, ethers, Wallet } from "ethers";
|
|
2
2
|
import {
|
|
3
3
|
Token,
|
|
4
4
|
TokenAmount,
|
|
@@ -22,8 +22,18 @@ import {
|
|
|
22
22
|
networkChainIdMap,
|
|
23
23
|
stakingAddress
|
|
24
24
|
} from "../config";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
Dapp,
|
|
27
|
+
LyraOptionMarket,
|
|
28
|
+
LyraOptionType,
|
|
29
|
+
LyraTradeType,
|
|
30
|
+
Network,
|
|
31
|
+
Reserves
|
|
32
|
+
} from "../types";
|
|
26
33
|
import { Pool } from ".";
|
|
34
|
+
import { getExpiries, getStrike, getStrikes } from "../services/lyra/markets";
|
|
35
|
+
import { Quote, Strike } from "@lyrafinance/lyra-js";
|
|
36
|
+
import { getQuote } from "../services/lyra/quote";
|
|
27
37
|
|
|
28
38
|
export class Utils {
|
|
29
39
|
network: Network;
|
|
@@ -328,4 +338,37 @@ export class Utils {
|
|
|
328
338
|
const exitPoolTx = iBalancerV2Vault.encodeFunctionData("exitPool", txData);
|
|
329
339
|
return exitPoolTx;
|
|
330
340
|
}
|
|
341
|
+
|
|
342
|
+
async getLyraOptionExpiries(market: LyraOptionMarket): Promise<number[]> {
|
|
343
|
+
return await getExpiries(this.network, market);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
async getLyraOptionStrikes(
|
|
347
|
+
market: LyraOptionMarket,
|
|
348
|
+
expiry: number
|
|
349
|
+
): Promise<Strike[]> {
|
|
350
|
+
return await getStrikes(this.network, market, expiry);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
async getLyraOptionStrike(
|
|
354
|
+
market: LyraOptionMarket,
|
|
355
|
+
expiry: number,
|
|
356
|
+
strike: number
|
|
357
|
+
): Promise<Strike> {
|
|
358
|
+
return await getStrike(this.network, market, expiry, strike);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
async getLyraOptionQuote(
|
|
362
|
+
strike: Strike,
|
|
363
|
+
type: LyraOptionType,
|
|
364
|
+
tradeType: LyraTradeType,
|
|
365
|
+
amount: BigNumber | string
|
|
366
|
+
): Promise<Quote> {
|
|
367
|
+
return await getQuote(
|
|
368
|
+
strike,
|
|
369
|
+
type,
|
|
370
|
+
tradeType,
|
|
371
|
+
ethers.BigNumber.from(amount)
|
|
372
|
+
);
|
|
373
|
+
}
|
|
331
374
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { ethers, LyraOptionMarket, Network } from "../..";
|
|
3
|
+
import { lyraNetworkMap } from "../../config";
|
|
4
|
+
import Lyra, { Board, Strike } from "@lyrafinance/lyra-js";
|
|
5
|
+
|
|
6
|
+
export async function getBoard(
|
|
7
|
+
network: Network,
|
|
8
|
+
market: LyraOptionMarket,
|
|
9
|
+
expiry: number
|
|
10
|
+
): Promise<Board> {
|
|
11
|
+
const lyra = new Lyra(lyraNetworkMap[network]);
|
|
12
|
+
const optionMarket = await lyra.market(market);
|
|
13
|
+
const filteredBoards = optionMarket
|
|
14
|
+
.liveBoards()
|
|
15
|
+
.filter(e => e.expiryTimestamp === expiry);
|
|
16
|
+
if (filteredBoards.length === 0) throw new Error("no lyra board for expiry");
|
|
17
|
+
return filteredBoards[0];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function getExpiries(
|
|
21
|
+
network: Network,
|
|
22
|
+
market: LyraOptionMarket
|
|
23
|
+
): Promise<number[]> {
|
|
24
|
+
const lyra = new Lyra(lyraNetworkMap[network]);
|
|
25
|
+
const optionMarket = await lyra.market(market);
|
|
26
|
+
return optionMarket.liveBoards().map(e => e.expiryTimestamp);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function getStrikes(
|
|
30
|
+
network: Network,
|
|
31
|
+
market: LyraOptionMarket,
|
|
32
|
+
expiry: number
|
|
33
|
+
): Promise<Strike[]> {
|
|
34
|
+
return (await getBoard(network, market, expiry)).strikes();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function getStrike(
|
|
38
|
+
network: Network,
|
|
39
|
+
market: LyraOptionMarket,
|
|
40
|
+
expiry: number,
|
|
41
|
+
strike: number
|
|
42
|
+
): Promise<Strike> {
|
|
43
|
+
const strikes = await getStrikes(network, market, expiry);
|
|
44
|
+
const filteredStrike = strikes.filter(
|
|
45
|
+
(e: Strike) =>
|
|
46
|
+
parseFloat(ethers.utils.formatEther(e.strikePrice)) === strike
|
|
47
|
+
);
|
|
48
|
+
if (filteredStrike.length === 0)
|
|
49
|
+
throw new Error("no option found for strike price");
|
|
50
|
+
|
|
51
|
+
return filteredStrike[0];
|
|
52
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { ethers, LyraOptionMarket, LyraPosition, Pool } from "../..";
|
|
3
|
+
import Lyra from "@lyrafinance/lyra-js";
|
|
4
|
+
import IOptionToken from "../../abi/IOptionToken.json";
|
|
5
|
+
|
|
6
|
+
export async function getOptionPositions(
|
|
7
|
+
pool: Pool,
|
|
8
|
+
market: LyraOptionMarket
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
): Promise<LyraPosition[]> {
|
|
11
|
+
const lyra = new Lyra();
|
|
12
|
+
const optionMarket = await lyra.market(market);
|
|
13
|
+
const iOptionToken = new ethers.Contract(
|
|
14
|
+
optionMarket.__marketData.marketAddresses.optionToken,
|
|
15
|
+
IOptionToken.abi,
|
|
16
|
+
pool.signer
|
|
17
|
+
);
|
|
18
|
+
return await iOptionToken.getOwnerPositions(pool.address);
|
|
19
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Quote, Strike } from "@lyrafinance/lyra-js";
|
|
2
|
+
import { ethers } from "ethers";
|
|
3
|
+
import { LyraOptionType, LyraTradeType } from "../../types";
|
|
4
|
+
|
|
5
|
+
export async function getQuote(
|
|
6
|
+
strike: Strike,
|
|
7
|
+
type: LyraOptionType,
|
|
8
|
+
tradeType: LyraTradeType,
|
|
9
|
+
amount: ethers.BigNumber
|
|
10
|
+
): Promise<Quote> {
|
|
11
|
+
return await strike.quote(type === "call", tradeType === "buy", amount);
|
|
12
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { BigNumber, ethers } from "ethers";
|
|
3
|
+
import { Pool } from "../..";
|
|
4
|
+
import { LyraOptionMarket, LyraOptionType, LyraTradeType } from "../../types";
|
|
5
|
+
import { getStrike } from "./markets";
|
|
6
|
+
import IOptionMarketWrapper from "../../abi/IOptionMarketWrapper.json";
|
|
7
|
+
import { getLyraTradeOptionType, isCall, isLong } from "./tradeOptionType";
|
|
8
|
+
import { getOptionPositions } from "./positions";
|
|
9
|
+
import { getQuote } from "./quote";
|
|
10
|
+
|
|
11
|
+
export async function getLyraOptionTxData(
|
|
12
|
+
pool: Pool,
|
|
13
|
+
market: LyraOptionMarket,
|
|
14
|
+
optionType: LyraOptionType,
|
|
15
|
+
expiry: number,
|
|
16
|
+
strikePrice: number,
|
|
17
|
+
tradeType: LyraTradeType,
|
|
18
|
+
optionAmount: BigNumber | string,
|
|
19
|
+
assetIn: string,
|
|
20
|
+
collateralAmount: BigNumber,
|
|
21
|
+
isCoveredCall: boolean
|
|
22
|
+
): Promise<string> {
|
|
23
|
+
const strike = await getStrike(pool.network, market, expiry, strikePrice);
|
|
24
|
+
const strikeId = strike.id;
|
|
25
|
+
|
|
26
|
+
const positions = await getOptionPositions(pool, market);
|
|
27
|
+
const filteredPosition = positions.filter(
|
|
28
|
+
e =>
|
|
29
|
+
e.strikeId.toNumber() === strikeId &&
|
|
30
|
+
isCall(e.optionType) == (optionType === "call") &&
|
|
31
|
+
e.state === 1
|
|
32
|
+
);
|
|
33
|
+
const positionId =
|
|
34
|
+
filteredPosition.length > 0 ? filteredPosition[0].positionId : 0;
|
|
35
|
+
|
|
36
|
+
let lyraOptionType = getLyraTradeOptionType(
|
|
37
|
+
optionType === "call",
|
|
38
|
+
tradeType === "buy",
|
|
39
|
+
isCoveredCall
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const amountIn = BigNumber.from(optionAmount);
|
|
43
|
+
const quote = await getQuote(strike, optionType, tradeType, amountIn);
|
|
44
|
+
const netPremiun =
|
|
45
|
+
tradeType === "buy"
|
|
46
|
+
? quote.premium.add(quote.fee)
|
|
47
|
+
: quote.premium.sub(quote.fee);
|
|
48
|
+
|
|
49
|
+
let txFunction = "openPosition";
|
|
50
|
+
let inputAmount = tradeType === "buy" ? netPremiun : collateralAmount;
|
|
51
|
+
let currentCollateral = BigNumber.from(0);
|
|
52
|
+
let setCollateral = collateralAmount;
|
|
53
|
+
if (filteredPosition.length > 0) {
|
|
54
|
+
currentCollateral = filteredPosition[0].collateral ?? BigNumber.from(0);
|
|
55
|
+
setCollateral = currentCollateral.add(collateralAmount);
|
|
56
|
+
if (
|
|
57
|
+
//sell long positions
|
|
58
|
+
(tradeType === "sell" && isLong(filteredPosition[0].optionType)) ||
|
|
59
|
+
//cover short positions
|
|
60
|
+
(tradeType === "buy" && !isLong(filteredPosition[0].optionType))
|
|
61
|
+
) {
|
|
62
|
+
lyraOptionType = filteredPosition[0].optionType;
|
|
63
|
+
txFunction = "closePosition";
|
|
64
|
+
setCollateral = currentCollateral.sub(collateralAmount);
|
|
65
|
+
//cover short
|
|
66
|
+
if (
|
|
67
|
+
!isLong(filteredPosition[0].optionType) &&
|
|
68
|
+
!isCoveredCall &&
|
|
69
|
+
collateralAmount.gt(netPremiun)
|
|
70
|
+
) {
|
|
71
|
+
inputAmount = netPremiun.sub(collateralAmount);
|
|
72
|
+
} else if (!isLong(filteredPosition[0].optionType) && isCoveredCall) {
|
|
73
|
+
inputAmount = netPremiun;
|
|
74
|
+
} else {
|
|
75
|
+
inputAmount = BigNumber.from(0);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const iOptionMarketWrapper = new ethers.utils.Interface(
|
|
81
|
+
IOptionMarketWrapper.abi
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const tradeTx = iOptionMarketWrapper.encodeFunctionData(txFunction, [
|
|
85
|
+
[
|
|
86
|
+
strike.market().contractAddresses.optionMarket,
|
|
87
|
+
strikeId, // strike Id
|
|
88
|
+
positionId, // position Id
|
|
89
|
+
1, // iteration
|
|
90
|
+
setCollateral, // set collateral to
|
|
91
|
+
currentCollateral, // current collateral
|
|
92
|
+
lyraOptionType, // optionType
|
|
93
|
+
amountIn, // amount
|
|
94
|
+
tradeType === "sell" ? netPremiun : 0, // min cost
|
|
95
|
+
tradeType === "buy" ? netPremiun : ethers.constants.MaxUint256, // max cost
|
|
96
|
+
inputAmount,
|
|
97
|
+
assetIn // input asset
|
|
98
|
+
]
|
|
99
|
+
]);
|
|
100
|
+
return tradeTx;
|
|
101
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function getLyraTradeOptionType(
|
|
2
|
+
isCall: boolean,
|
|
3
|
+
isLong: boolean,
|
|
4
|
+
isCoveredCall: boolean
|
|
5
|
+
): number {
|
|
6
|
+
if (isCall) {
|
|
7
|
+
return isLong ? 0 : isCoveredCall ? 2 : 3;
|
|
8
|
+
} else {
|
|
9
|
+
return isLong ? 1 : 4;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function isCall(optionType: number): boolean {
|
|
14
|
+
return [0, 2, 3].includes(optionType);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isLong(optionType: number): boolean {
|
|
18
|
+
return optionType === 0 || optionType === 1;
|
|
19
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { BigNumber, ethers } from "ethers";
|
|
3
|
+
import IVelodromeRouter from "../../abi/IVeldodromeRouter.json";
|
|
4
|
+
import { deadline } from "../../config";
|
|
5
|
+
import { Pool } from "../../entities";
|
|
6
|
+
import { Transaction } from "../../types";
|
|
7
|
+
|
|
8
|
+
export function getVelodromeAddLiquidityTxData(
|
|
9
|
+
pool: Pool,
|
|
10
|
+
assetA: string,
|
|
11
|
+
assetB: string,
|
|
12
|
+
amountA: BigNumber | string,
|
|
13
|
+
amountB: BigNumber | string,
|
|
14
|
+
isStable: boolean
|
|
15
|
+
): any {
|
|
16
|
+
const iVelodromeRouter = new ethers.utils.Interface(IVelodromeRouter.abi);
|
|
17
|
+
return iVelodromeRouter.encodeFunctionData(Transaction.ADD_LIQUIDITY, [
|
|
18
|
+
assetA,
|
|
19
|
+
assetB,
|
|
20
|
+
isStable,
|
|
21
|
+
amountA,
|
|
22
|
+
amountB,
|
|
23
|
+
"0",
|
|
24
|
+
"0",
|
|
25
|
+
pool.address,
|
|
26
|
+
deadline
|
|
27
|
+
]);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getVelodromeRemoveLiquidityTxData(
|
|
31
|
+
pool: Pool,
|
|
32
|
+
assetA: string,
|
|
33
|
+
assetB: string,
|
|
34
|
+
amount: BigNumber | string,
|
|
35
|
+
isStable: boolean
|
|
36
|
+
): any {
|
|
37
|
+
const iVelodromeRouter = new ethers.utils.Interface(IVelodromeRouter.abi);
|
|
38
|
+
return iVelodromeRouter.encodeFunctionData(Transaction.REMOVE_LIQUIDITY, [
|
|
39
|
+
assetA,
|
|
40
|
+
assetB,
|
|
41
|
+
isStable,
|
|
42
|
+
amount,
|
|
43
|
+
"0",
|
|
44
|
+
"0",
|
|
45
|
+
pool.address,
|
|
46
|
+
deadline
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { BigNumber, ethers } from "ethers";
|
|
3
|
+
import IVelodromeGauge from "../../abi/IVelodromeGauge.json";
|
|
4
|
+
import { Pool } from "../../entities";
|
|
5
|
+
import { Transaction } from "../../types";
|
|
6
|
+
import { call } from "../../utils/contract";
|
|
7
|
+
const iVelodromeGauge = new ethers.utils.Interface(IVelodromeGauge.abi);
|
|
8
|
+
|
|
9
|
+
export function getVelodromeStakeTxData(amount: BigNumber | string): any {
|
|
10
|
+
return iVelodromeGauge.encodeFunctionData(Transaction.DEPOSIT, [amount, "0"]);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function getVelodromeClaimTxData(
|
|
14
|
+
pool: Pool,
|
|
15
|
+
gauge: string
|
|
16
|
+
): Promise<any> {
|
|
17
|
+
const rewardAssetCount = await call(pool.signer, IVelodromeGauge.abi, [
|
|
18
|
+
gauge,
|
|
19
|
+
"rewardsListLength",
|
|
20
|
+
[]
|
|
21
|
+
]);
|
|
22
|
+
const rewardAssets = await Promise.all(
|
|
23
|
+
Array.from(Array(rewardAssetCount.toNumber()).keys()).map(e =>
|
|
24
|
+
call(pool.signer, IVelodromeGauge.abi, [gauge, "rewards", [e]])
|
|
25
|
+
)
|
|
26
|
+
);
|
|
27
|
+
return iVelodromeGauge.encodeFunctionData("getReward", [
|
|
28
|
+
pool.address,
|
|
29
|
+
rewardAssets
|
|
30
|
+
]);
|
|
31
|
+
}
|
package/src/test/constants.ts
CHANGED
|
@@ -26,5 +26,8 @@ export const DAI = "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1";
|
|
|
26
26
|
export const USDy = "0x1ec50880101022c11530a069690f5446d1464592";
|
|
27
27
|
export const WBTC = "0x68f180fcCe6836688e9084f035309E29Bf0A2095";
|
|
28
28
|
export const OP = "4200000000000000000000000000000000000042";
|
|
29
|
+
export const WSTETH = "0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb";
|
|
30
|
+
export const VEL = "0x3c8B650257cFb5f272f799F5e2b4e65093a11a05";
|
|
31
|
+
export const SUSD = "0x8c6f28f2f1a3c87f0f938b96d27520d9751ec8d9";
|
|
29
32
|
|
|
30
33
|
export const TEST_POOL = "TEST_POOL";
|