@defisaver/automation-sdk 2.0.5 → 2.0.8
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.dev +5 -0
- package/.tests.sh +3 -0
- package/README.md +3 -1
- package/esm/automation/private/LegacyProtocol.test.d.ts +1 -0
- package/esm/automation/private/LegacyProtocol.test.js +25 -0
- package/esm/automation/private/Protocol.test.d.ts +1 -0
- package/esm/automation/private/Protocol.test.js +25 -0
- package/esm/automation/private/StrategiesAutomation.js +1 -1
- package/esm/constants/index.js +15 -0
- package/esm/services/contractService.d.ts +3 -2
- package/esm/services/contractService.js +7 -1
- package/esm/services/ethereumService.test.d.ts +1 -0
- package/esm/services/ethereumService.test.js +241 -0
- package/esm/services/strategiesService.js +40 -0
- package/esm/services/strategiesService.test.d.ts +1 -0
- package/esm/services/strategiesService.test.js +108 -0
- package/esm/services/strategySubService.d.ts +17 -3
- package/esm/services/strategySubService.js +17 -6
- package/esm/services/strategySubService.test.d.ts +1 -0
- package/esm/services/strategySubService.test.js +692 -0
- package/esm/services/subDataService.d.ts +8 -1
- package/esm/services/subDataService.js +23 -14
- package/esm/services/subDataService.test.d.ts +1 -0
- package/esm/services/subDataService.test.js +993 -0
- package/esm/services/triggerService.d.ts +17 -0
- package/esm/services/triggerService.js +42 -1
- package/esm/services/triggerService.test.js +119 -17
- package/esm/types/enums.d.ts +10 -2
- package/esm/types/enums.js +8 -0
- package/esm/types/index.d.ts +19 -2
- package/package.json +3 -3
- package/src/automation/private/LegacyProtocol.test.ts +24 -0
- package/src/automation/private/Protocol.test.ts +24 -0
- package/src/automation/private/StrategiesAutomation.ts +1 -1
- package/src/constants/index.ts +15 -0
- package/src/services/contractService.ts +17 -4
- package/src/services/ethereumService.test.ts +256 -0
- package/src/services/ethereumService.ts +2 -1
- package/src/services/strategiesService.test.ts +103 -0
- package/src/services/strategiesService.ts +66 -3
- package/src/services/strategySubService.test.ts +835 -0
- package/src/services/strategySubService.ts +50 -15
- package/src/services/subDataService.test.ts +1063 -0
- package/src/services/subDataService.ts +29 -14
- package/src/services/triggerService.test.ts +133 -20
- package/src/services/triggerService.ts +55 -0
- package/src/services/utils.test.ts +1 -1
- package/src/types/enums.ts +8 -0
- package/src/types/index.ts +27 -3
- package/umd/index.js +282 -115
|
@@ -4,6 +4,7 @@ import { assetAmountInEth, getAssetInfo, getAssetInfoByAddress } from '@defisave
|
|
|
4
4
|
import { otherAddresses } from '@defisaver/sdk';
|
|
5
5
|
|
|
6
6
|
import type { EthereumAddress, SubData } from '../types';
|
|
7
|
+
import type { OrderType } from '../types/enums';
|
|
7
8
|
import { ChainId, RatioState } from '../types/enums';
|
|
8
9
|
|
|
9
10
|
import { ZERO_ADDRESS } from '../constants';
|
|
@@ -82,7 +83,7 @@ export const makerCloseSubData = {
|
|
|
82
83
|
const vaultId = +AbiCoder.decodeParameter('uint256', subData[0])!;
|
|
83
84
|
// if closing to collateral, asset addr will be 2nd param out of 4
|
|
84
85
|
// if closing to DAI, will return 2nd param out of 3, which will be DAI addr
|
|
85
|
-
const closeToAssetAddr = AbiCoder.decodeParameter('address', subData[1])!.toString()
|
|
86
|
+
const closeToAssetAddr = AbiCoder.decodeParameter('address', subData[1])!.toString();
|
|
86
87
|
|
|
87
88
|
return {
|
|
88
89
|
vaultId, closeToAssetAddr,
|
|
@@ -91,14 +92,6 @@ export const makerCloseSubData = {
|
|
|
91
92
|
};
|
|
92
93
|
|
|
93
94
|
export const makerLeverageManagementSubData = {
|
|
94
|
-
// encode: (vaultId:number, repayFrom, boostFrom, boostTo, repayTo, boostEnabled) => [
|
|
95
|
-
// vaultId,
|
|
96
|
-
// new Dec(repayFrom).mul(1e16).toString(),
|
|
97
|
-
// new Dec(boostFrom).mul(1e16).toString(),
|
|
98
|
-
// new Dec(boostTo).mul(1e16).toString(),
|
|
99
|
-
// new Dec(repayTo).mul(1e16).toString(),
|
|
100
|
-
// boostEnabled,
|
|
101
|
-
// ],
|
|
102
95
|
decode: (subData:SubData) => {
|
|
103
96
|
const vaultId = +AbiCoder.decodeParameter('uint256', subData[0])!.toString();
|
|
104
97
|
const weiRatio = AbiCoder.decodeParameter('uint256', subData[1]) as any as string;
|
|
@@ -106,6 +99,7 @@ export const makerLeverageManagementSubData = {
|
|
|
106
99
|
return { vaultId, targetRatio };
|
|
107
100
|
},
|
|
108
101
|
};
|
|
102
|
+
|
|
109
103
|
export const liquityLeverageManagementSubData = {
|
|
110
104
|
decode: (subData:SubData) => {
|
|
111
105
|
const weiRatio = AbiCoder.decodeParameter('uint256', subData[1]) as any as string;
|
|
@@ -113,6 +107,7 @@ export const liquityLeverageManagementSubData = {
|
|
|
113
107
|
return { targetRatio };
|
|
114
108
|
},
|
|
115
109
|
};
|
|
110
|
+
|
|
116
111
|
export const liquityCloseSubData = {
|
|
117
112
|
encode(
|
|
118
113
|
closeToAssetAddr: EthereumAddress,
|
|
@@ -125,16 +120,16 @@ export const liquityCloseSubData = {
|
|
|
125
120
|
|
|
126
121
|
const collAddrEncoded = AbiCoder.encodeParameter('address', _collAddr);
|
|
127
122
|
const debtAddrEncoded = AbiCoder.encodeParameter('address', _debtAddr);
|
|
128
|
-
// if (compareAddresses(closeToAssetAddr,
|
|
123
|
+
// if (compareAddresses(closeToAssetAddr, _debtAddr)) { // Closing to debt strategy was not implemented, but it should be in the future
|
|
129
124
|
// // close to LUSD strategy
|
|
130
|
-
// return [
|
|
125
|
+
// return [debtAddrEncoded, collAddrEncoded];
|
|
131
126
|
// }
|
|
132
127
|
// close to collateral strategy
|
|
133
128
|
return [collAddrEncoded, debtAddrEncoded];
|
|
134
129
|
},
|
|
135
130
|
decode(subData: SubData): { closeToAssetAddr: EthereumAddress, debtAddr: string } {
|
|
136
|
-
const closeToAssetAddr = AbiCoder.decodeParameter('address', subData[0])!.toString()
|
|
137
|
-
const debtAddr = AbiCoder.decodeParameter('address', subData[1])!.toString()
|
|
131
|
+
const closeToAssetAddr = AbiCoder.decodeParameter('address', subData[0])!.toString();
|
|
132
|
+
const debtAddr = AbiCoder.decodeParameter('address', subData[1])!.toString();
|
|
138
133
|
|
|
139
134
|
return { closeToAssetAddr, debtAddr };
|
|
140
135
|
},
|
|
@@ -342,7 +337,7 @@ export const exchangeDcaSubData = {
|
|
|
342
337
|
};
|
|
343
338
|
|
|
344
339
|
export const exchangeLimitOrderSubData = {
|
|
345
|
-
encode(fromToken: EthereumAddress, toToken: EthereumAddress, amount: string, targetPrice: string, goodUntil: string | number, orderType:
|
|
340
|
+
encode(fromToken: EthereumAddress, toToken: EthereumAddress, amount: string, targetPrice: string, goodUntil: string | number, orderType: OrderType) : SubData {
|
|
346
341
|
return [
|
|
347
342
|
fromToken,
|
|
348
343
|
toToken,
|
|
@@ -437,3 +432,23 @@ export const liquityDsrSupplySubData = {
|
|
|
437
432
|
return { targetRatio };
|
|
438
433
|
},
|
|
439
434
|
};
|
|
435
|
+
|
|
436
|
+
export const liquityDebtInFrontRepaySubData = {
|
|
437
|
+
encode: (targetRatioIncrease: number) => {
|
|
438
|
+
const wethAddress = getAssetInfo('WETH').address;
|
|
439
|
+
const lusdAddress = getAssetInfo('LUSD').address;
|
|
440
|
+
|
|
441
|
+
const wethAddressEncoded = AbiCoder.encodeParameter('address', wethAddress);
|
|
442
|
+
const lusdAddressEncoded = AbiCoder.encodeParameter('address', lusdAddress);
|
|
443
|
+
const targetRatioIncreaseEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatioIncrease));
|
|
444
|
+
const withdrawIdEncoded = AbiCoder.encodeParameter('uint8', 1); // withdraw - 1
|
|
445
|
+
const paybackIdEncoded = AbiCoder.encodeParameter('uint8', 0); // payback - 0
|
|
446
|
+
|
|
447
|
+
return [wethAddressEncoded, lusdAddressEncoded, targetRatioIncreaseEncoded, withdrawIdEncoded, paybackIdEncoded];
|
|
448
|
+
},
|
|
449
|
+
decode: (subData: SubData) => {
|
|
450
|
+
const weiRatio = AbiCoder.decodeParameter('uint256', subData[2]) as any as string;
|
|
451
|
+
const targetRatioIncrease = weiToRatioPercentage(weiRatio);
|
|
452
|
+
return { targetRatioIncrease };
|
|
453
|
+
},
|
|
454
|
+
};
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { expect } from 'chai';
|
|
2
|
-
import { getAssetInfo } from '@defisaver/tokens';
|
|
2
|
+
import { getAssetInfo, MAXUINT } from '@defisaver/tokens';
|
|
3
3
|
import * as web3Utils from 'web3-utils';
|
|
4
4
|
|
|
5
5
|
import { ChainId, OrderType, RatioState } from '../types/enums';
|
|
6
|
-
import { EthereumAddress, TriggerData } from '../types';
|
|
6
|
+
import type { EthereumAddress, TriggerData } from '../types';
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
aaveV2RatioTrigger,
|
|
10
10
|
aaveV3QuotePriceTrigger,
|
|
11
|
+
aaveV3QuotePriceWithMaximumGasPriceTrigger,
|
|
11
12
|
aaveV3RatioTrigger,
|
|
12
13
|
cBondsRebondTrigger,
|
|
13
14
|
chainlinkPriceTrigger,
|
|
14
15
|
compoundV2RatioTrigger,
|
|
15
16
|
compoundV3RatioTrigger,
|
|
16
|
-
curveUsdBorrowRateTrigger,
|
|
17
|
+
curveUsdBorrowRateTrigger,
|
|
18
|
+
curveUsdSoftLiquidationTrigger,
|
|
17
19
|
exchangeOffchainPriceTrigger,
|
|
18
20
|
exchangeTimestampTrigger,
|
|
19
21
|
liquityDebtInFrontTrigger,
|
|
@@ -22,6 +24,7 @@ import {
|
|
|
22
24
|
sparkQuotePriceTrigger,
|
|
23
25
|
sparkRatioTrigger,
|
|
24
26
|
trailingStopTrigger,
|
|
27
|
+
liquityDebtInFrontWithLimitTrigger,
|
|
25
28
|
} from './triggerService';
|
|
26
29
|
|
|
27
30
|
describe('Feature: triggerService.ts', () => {
|
|
@@ -59,7 +62,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
59
62
|
];
|
|
60
63
|
|
|
61
64
|
examples.forEach(([expected, actual]) => {
|
|
62
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
65
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
63
66
|
expect(chainlinkPriceTrigger.decode(actual)).to.eql(expected);
|
|
64
67
|
});
|
|
65
68
|
});
|
|
@@ -99,7 +102,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
99
102
|
];
|
|
100
103
|
|
|
101
104
|
examples.forEach(([expected, actual]) => {
|
|
102
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
105
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
103
106
|
expect(trailingStopTrigger.decode(actual)).to.eql(expected);
|
|
104
107
|
});
|
|
105
108
|
});
|
|
@@ -139,7 +142,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
139
142
|
];
|
|
140
143
|
|
|
141
144
|
examples.forEach(([expected, actual]) => {
|
|
142
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
145
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
143
146
|
expect(makerRatioTrigger.decode(actual)).to.eql(expected);
|
|
144
147
|
});
|
|
145
148
|
});
|
|
@@ -179,7 +182,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
179
182
|
];
|
|
180
183
|
|
|
181
184
|
examples.forEach(([expected, actual]) => {
|
|
182
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
185
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
183
186
|
expect(aaveV3RatioTrigger.decode(actual)).to.eql(expected);
|
|
184
187
|
});
|
|
185
188
|
});
|
|
@@ -219,7 +222,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
219
222
|
];
|
|
220
223
|
|
|
221
224
|
examples.forEach(([expected, actual]) => {
|
|
222
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
225
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
223
226
|
expect(morphoAaveV2RatioTrigger.decode(actual)).to.eql(expected);
|
|
224
227
|
});
|
|
225
228
|
});
|
|
@@ -269,13 +272,77 @@ describe('Feature: triggerService.ts', () => {
|
|
|
269
272
|
];
|
|
270
273
|
|
|
271
274
|
examples.forEach(([expected, actual]) => {
|
|
272
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
275
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
273
276
|
expect(aaveV3QuotePriceTrigger.decode(actual)).to.eql(expected);
|
|
274
277
|
});
|
|
275
278
|
});
|
|
276
279
|
});
|
|
277
280
|
});
|
|
278
281
|
|
|
282
|
+
describe('When testing triggerService.aaveV3QuotePriceWithMaximumGasPriceTrigger', () => {
|
|
283
|
+
describe('encode()', () => {
|
|
284
|
+
const examples: Array<[TriggerData, [baseTokenAddress: EthereumAddress, quoteTokenAddress: EthereumAddress, price: number, ratioState: RatioState, maximumGasPriceInGwei?: number]]> = [
|
|
285
|
+
[
|
|
286
|
+
[
|
|
287
|
+
'0x0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000009c400000000000000000000000000000000000000000000000000000000000000001',
|
|
288
|
+
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
|
|
289
|
+
],
|
|
290
|
+
[getAssetInfo('DAI', ChainId.Ethereum).address, getAssetInfo('WETH', ChainId.Ethereum).address, 0.0004, RatioState.UNDER]
|
|
291
|
+
],
|
|
292
|
+
[
|
|
293
|
+
[
|
|
294
|
+
'0x0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000000',
|
|
295
|
+
'0x00000000000000000000000000000000000000000000000000000002cb417800',
|
|
296
|
+
],
|
|
297
|
+
[getAssetInfo('WBTC', ChainId.Ethereum).address, getAssetInfo('USDT', ChainId.Ethereum).address, 0.00000023, RatioState.OVER, 12]
|
|
298
|
+
],
|
|
299
|
+
];
|
|
300
|
+
|
|
301
|
+
examples.forEach(([expected, actual]) => {
|
|
302
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
303
|
+
expect(aaveV3QuotePriceWithMaximumGasPriceTrigger.encode(...actual)).to.eql(expected);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
describe('decode()', () => {
|
|
309
|
+
const examples: Array<[{ baseTokenAddress: EthereumAddress, quoteTokenAddress: EthereumAddress, price: string, ratioState: RatioState, maximumGasPrice: string }, TriggerData]> = [
|
|
310
|
+
[
|
|
311
|
+
{
|
|
312
|
+
baseTokenAddress: web3Utils.toChecksumAddress(getAssetInfo('DAI', ChainId.Ethereum).address),
|
|
313
|
+
quoteTokenAddress: web3Utils.toChecksumAddress(getAssetInfo('WETH', ChainId.Ethereum).address),
|
|
314
|
+
price: '0.0004',
|
|
315
|
+
ratioState: RatioState.UNDER,
|
|
316
|
+
maximumGasPrice: web3Utils.fromWei(MAXUINT, 'gwei')
|
|
317
|
+
},
|
|
318
|
+
[
|
|
319
|
+
'0x0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000009c400000000000000000000000000000000000000000000000000000000000000001',
|
|
320
|
+
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
|
|
321
|
+
],
|
|
322
|
+
],
|
|
323
|
+
[
|
|
324
|
+
{
|
|
325
|
+
baseTokenAddress: web3Utils.toChecksumAddress(getAssetInfo('WBTC', ChainId.Ethereum).address),
|
|
326
|
+
quoteTokenAddress: web3Utils.toChecksumAddress(getAssetInfo('USDT', ChainId.Ethereum).address),
|
|
327
|
+
price: '0.00000023',
|
|
328
|
+
ratioState: RatioState.OVER,
|
|
329
|
+
maximumGasPrice: '12',
|
|
330
|
+
},
|
|
331
|
+
[
|
|
332
|
+
'0x0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000000',
|
|
333
|
+
'0x00000000000000000000000000000000000000000000000000000002cb417800',
|
|
334
|
+
],
|
|
335
|
+
]
|
|
336
|
+
];
|
|
337
|
+
|
|
338
|
+
examples.forEach(([expected, actual]) => {
|
|
339
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
340
|
+
expect(aaveV3QuotePriceWithMaximumGasPriceTrigger.decode(actual)).to.eql(expected);
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
|
|
279
346
|
describe('When testing triggerService.liquityRatioTrigger', () => {
|
|
280
347
|
describe('encode()', () => {
|
|
281
348
|
const examples: Array<[[string], [owner: EthereumAddress, ratioPercentage: number, ratioState: RatioState]]> = [
|
|
@@ -317,7 +384,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
317
384
|
];
|
|
318
385
|
|
|
319
386
|
examples.forEach(([expected, actual]) => {
|
|
320
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
387
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
321
388
|
expect(compoundV2RatioTrigger.decode(actual)).to.eql(expected);
|
|
322
389
|
});
|
|
323
390
|
});
|
|
@@ -363,7 +430,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
363
430
|
];
|
|
364
431
|
|
|
365
432
|
examples.forEach(([expected, actual]) => {
|
|
366
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
433
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
367
434
|
expect(liquityDebtInFrontTrigger.decode(actual)).to.eql(expected);
|
|
368
435
|
});
|
|
369
436
|
});
|
|
@@ -400,7 +467,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
400
467
|
];
|
|
401
468
|
|
|
402
469
|
examples.forEach(([expected, actual]) => {
|
|
403
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
470
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
404
471
|
expect(aaveV2RatioTrigger.decode(actual)).to.eql(expected);
|
|
405
472
|
});
|
|
406
473
|
});
|
|
@@ -440,7 +507,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
440
507
|
];
|
|
441
508
|
|
|
442
509
|
examples.forEach(([expected, actual]) => {
|
|
443
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
510
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
444
511
|
expect(cBondsRebondTrigger.decode(actual)).to.eql(expected);
|
|
445
512
|
});
|
|
446
513
|
});
|
|
@@ -490,7 +557,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
490
557
|
];
|
|
491
558
|
|
|
492
559
|
examples.forEach(([expected, actual]) => {
|
|
493
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
560
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
494
561
|
expect(compoundV3RatioTrigger.decode(actual)).to.eql(expected);
|
|
495
562
|
});
|
|
496
563
|
});
|
|
@@ -534,7 +601,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
534
601
|
];
|
|
535
602
|
|
|
536
603
|
examples.forEach(([expected, actual]) => {
|
|
537
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
604
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
538
605
|
expect(exchangeTimestampTrigger.decode(actual)).to.eql(expected);
|
|
539
606
|
});
|
|
540
607
|
});
|
|
@@ -586,7 +653,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
586
653
|
];
|
|
587
654
|
|
|
588
655
|
examples.forEach(([expected, actual]) => {
|
|
589
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
656
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
590
657
|
expect(exchangeOffchainPriceTrigger.decode(...actual)).to.eql(expected);
|
|
591
658
|
});
|
|
592
659
|
});
|
|
@@ -626,7 +693,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
626
693
|
];
|
|
627
694
|
|
|
628
695
|
examples.forEach(([expected, actual]) => {
|
|
629
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
696
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
630
697
|
expect(sparkRatioTrigger.decode(actual)).to.eql(expected);
|
|
631
698
|
});
|
|
632
699
|
});
|
|
@@ -676,7 +743,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
676
743
|
];
|
|
677
744
|
|
|
678
745
|
examples.forEach(([expected, actual]) => {
|
|
679
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
746
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
680
747
|
expect(sparkQuotePriceTrigger.decode(actual)).to.eql(expected);
|
|
681
748
|
});
|
|
682
749
|
});
|
|
@@ -726,7 +793,7 @@ describe('Feature: triggerService.ts', () => {
|
|
|
726
793
|
];
|
|
727
794
|
|
|
728
795
|
examples.forEach(([expected, actual]) => {
|
|
729
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
796
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
730
797
|
expect(curveUsdBorrowRateTrigger.decode(actual)).to.eql(expected);
|
|
731
798
|
});
|
|
732
799
|
});
|
|
@@ -774,11 +841,57 @@ describe('Feature: triggerService.ts', () => {
|
|
|
774
841
|
];
|
|
775
842
|
|
|
776
843
|
examples.forEach(([expected, actual]) => {
|
|
777
|
-
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
844
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
778
845
|
expect(curveUsdSoftLiquidationTrigger.decode(actual)).to.eql(expected);
|
|
779
846
|
});
|
|
780
847
|
});
|
|
781
848
|
});
|
|
782
849
|
});
|
|
783
850
|
|
|
851
|
+
describe('When testing triggerService.liquityDebtInFrontWithLimitTrigger', () => {
|
|
852
|
+
describe('encode()', () => {
|
|
853
|
+
const examples: Array<[[string], [owner: EthereumAddress, debtInFrontMin: string]]> = [
|
|
854
|
+
[
|
|
855
|
+
['0x000000000000000000000000235d6a8db3c57c3f7b4eba749e1738db6093732a0000000000000000000000000000000000000000019d971e4fe8401e74000000'],
|
|
856
|
+
[web3Utils.toChecksumAddress('0x235d6A8DB3C57c3f7b4ebA749E1738Db6093732a'), '500000000']
|
|
857
|
+
],
|
|
858
|
+
[
|
|
859
|
+
['0x000000000000000000000000235d6a8db3c57c3f7b4eba749e1738db6093732a00000000000000000000000000000000000000000001a784379d99db42000000'],
|
|
860
|
+
[web3Utils.toChecksumAddress('0x235d6A8DB3C57c3f7b4ebA749E1738Db6093732a'), '2000000']
|
|
861
|
+
],
|
|
862
|
+
];
|
|
863
|
+
|
|
864
|
+
examples.forEach(([expected, actual]) => {
|
|
865
|
+
it(`Given ${actual} should return expected value: ${expected}`, () => {
|
|
866
|
+
expect(liquityDebtInFrontWithLimitTrigger.encode(...actual)).to.eql(expected);
|
|
867
|
+
});
|
|
868
|
+
});
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
describe('decode()', () => {
|
|
872
|
+
const examples: Array<[{ owner: EthereumAddress, debtInFrontMin: string }, TriggerData]> = [
|
|
873
|
+
[
|
|
874
|
+
{
|
|
875
|
+
owner: web3Utils.toChecksumAddress('0x235d6A8DB3C57c3f7b4ebA749E1738Db6093732a'),
|
|
876
|
+
debtInFrontMin: '500000000',
|
|
877
|
+
},
|
|
878
|
+
['0x000000000000000000000000235d6a8db3c57c3f7b4eba749e1738db6093732a0000000000000000000000000000000000000000019d971e4fe8401e74000000'],
|
|
879
|
+
],
|
|
880
|
+
[
|
|
881
|
+
{
|
|
882
|
+
owner: web3Utils.toChecksumAddress('0x235d6A8DB3C57c3f7b4ebA749E1738Db6093732a'),
|
|
883
|
+
debtInFrontMin: '2000000',
|
|
884
|
+
},
|
|
885
|
+
['0x000000000000000000000000235d6a8db3c57c3f7b4eba749e1738db6093732a00000000000000000000000000000000000000000001a784379d99db42000000'],
|
|
886
|
+
],
|
|
887
|
+
];
|
|
888
|
+
|
|
889
|
+
examples.forEach(([expected, actual]) => {
|
|
890
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
891
|
+
expect(liquityDebtInFrontWithLimitTrigger.decode(actual)).to.eql(expected);
|
|
892
|
+
});
|
|
893
|
+
});
|
|
894
|
+
});
|
|
895
|
+
});
|
|
896
|
+
|
|
784
897
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Dec from 'decimal.js';
|
|
2
|
+
import { MAXUINT } from '@defisaver/tokens';
|
|
2
3
|
import AbiCoder from 'web3-eth-abi';
|
|
3
4
|
import * as web3Utils from 'web3-utils';
|
|
4
5
|
|
|
@@ -100,6 +101,46 @@ export const aaveV3QuotePriceTrigger = {
|
|
|
100
101
|
},
|
|
101
102
|
};
|
|
102
103
|
|
|
104
|
+
export const aaveV3QuotePriceWithMaximumGasPriceTrigger = {
|
|
105
|
+
encode(
|
|
106
|
+
baseTokenAddress: EthereumAddress,
|
|
107
|
+
quoteTokenAddress: EthereumAddress,
|
|
108
|
+
price: number,
|
|
109
|
+
ratioState: RatioState,
|
|
110
|
+
maximumGasPriceInGwei?: number,
|
|
111
|
+
) {
|
|
112
|
+
// Price is always in 8 decimals
|
|
113
|
+
const _price = new Dec(price.toString()).mul(10 ** 8).floor().toString();
|
|
114
|
+
|
|
115
|
+
const _maximumGasPrice = maximumGasPriceInGwei
|
|
116
|
+
? new Dec(maximumGasPriceInGwei.toString()).mul(10 ** 9).floor().toString() // We convert it to WEI
|
|
117
|
+
: MAXUINT; // If undefined than set to MAXUINT
|
|
118
|
+
|
|
119
|
+
return [
|
|
120
|
+
AbiCoder.encodeParameters(['address', 'address', 'uint256', 'uint8'], [baseTokenAddress, quoteTokenAddress, _price, ratioState]),
|
|
121
|
+
AbiCoder.encodeParameters(['uint256'], [_maximumGasPrice]),
|
|
122
|
+
];
|
|
123
|
+
},
|
|
124
|
+
decode(
|
|
125
|
+
triggerData: TriggerData,
|
|
126
|
+
): { baseTokenAddress: EthereumAddress, quoteTokenAddress: EthereumAddress, price: string, ratioState: RatioState, maximumGasPrice: string } {
|
|
127
|
+
const decodedPriceTrigger = AbiCoder.decodeParameters(['address', 'address', 'uint256', 'uint8'], triggerData[0]) as Array<string>;
|
|
128
|
+
const decodedMaximumGasPriceTrigger = AbiCoder.decodeParameters(['uint256'], triggerData[1]) as Array<string>;
|
|
129
|
+
// Price is always in 8 decimals
|
|
130
|
+
const price = new Dec(decodedPriceTrigger[2]).div(10 ** 8).toDP(8).toString();
|
|
131
|
+
|
|
132
|
+
const maximumGasPrice = new Dec(decodedMaximumGasPriceTrigger[0]).div(10 ** 9).toDP(9).toString();
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
baseTokenAddress: decodedPriceTrigger[0],
|
|
136
|
+
quoteTokenAddress: decodedPriceTrigger[1],
|
|
137
|
+
price,
|
|
138
|
+
ratioState: +decodedPriceTrigger[3],
|
|
139
|
+
maximumGasPrice,
|
|
140
|
+
};
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
103
144
|
export const compoundV2RatioTrigger = {
|
|
104
145
|
encode(owner: EthereumAddress, ratioPercentage: number, ratioState: RatioState) {
|
|
105
146
|
const ratioWei = ratioPercentageToWei(ratioPercentage);
|
|
@@ -143,6 +184,20 @@ export const liquityDebtInFrontTrigger = {
|
|
|
143
184
|
},
|
|
144
185
|
};
|
|
145
186
|
|
|
187
|
+
export const liquityDebtInFrontWithLimitTrigger = {
|
|
188
|
+
encode(owner: EthereumAddress, debtInFrontMin: string) {
|
|
189
|
+
const debtInFrontMinWei = web3Utils.toWei(new Dec(debtInFrontMin).toString(), 'ether');
|
|
190
|
+
return [AbiCoder.encodeParameters(['address', 'uint256'], [owner, debtInFrontMinWei])];
|
|
191
|
+
},
|
|
192
|
+
decode(triggerData: TriggerData): { owner: EthereumAddress, debtInFrontMin: string } {
|
|
193
|
+
const decodedData = AbiCoder.decodeParameters(['address', 'uint256'], triggerData[0]);
|
|
194
|
+
return {
|
|
195
|
+
owner: decodedData[0] as EthereumAddress,
|
|
196
|
+
debtInFrontMin: new Dec(decodedData[1] as string).div(10 ** 18).toString(),
|
|
197
|
+
};
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
|
|
146
201
|
export const aaveV2RatioTrigger = {
|
|
147
202
|
encode(owner: EthereumAddress, market: EthereumAddress, ratioPercentage: number, ratioState: RatioState) {
|
|
148
203
|
const ratioWei = ratioPercentageToWei(ratioPercentage);
|
|
@@ -3,7 +3,7 @@ import * as web3Utils from 'web3-utils';
|
|
|
3
3
|
import AbiCoder from 'web3-eth-abi';
|
|
4
4
|
import { getAssetInfo } from '@defisaver/tokens';
|
|
5
5
|
|
|
6
|
-
import { EthereumAddress } from '../types';
|
|
6
|
+
import type { EthereumAddress } from '../types';
|
|
7
7
|
import { ChainId, RatioState } from '../types/enums';
|
|
8
8
|
|
|
9
9
|
import { sparkEncode } from './strategySubService';
|
package/src/types/enums.ts
CHANGED
|
@@ -62,6 +62,7 @@ export namespace Strategies {
|
|
|
62
62
|
EXCHANGE_LIMIT_ORDER = 51,
|
|
63
63
|
LIQUITY_DSR_PAYBACK = 69,
|
|
64
64
|
LIQUITY_DSR_SUPPLY = 70,
|
|
65
|
+
LIQUITY_DEBT_IN_FRONT_REPAY = 75,
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
export enum OptimismIds {
|
|
@@ -83,7 +84,9 @@ export namespace Strategies {
|
|
|
83
84
|
Boost = 'boost',
|
|
84
85
|
EoaBoost = 'eoa-boost',
|
|
85
86
|
CloseToDebt = 'close-to-debt',
|
|
87
|
+
CloseToDebtWithGasPrice = 'close-to-debt-with-gas-price',
|
|
86
88
|
CloseToCollateral = 'close-to-collateral',
|
|
89
|
+
CloseToCollateralWithGasPrice = 'close-to-collateral-with-gas-price',
|
|
87
90
|
CloseOnPriceToDebt = 'close-on-price-to-debt',
|
|
88
91
|
CloseOnPriceToColl = 'close-on-price-to-collateral',
|
|
89
92
|
TrailingStopToColl = 'trailing-stop-to-collateral',
|
|
@@ -92,10 +95,13 @@ export namespace Strategies {
|
|
|
92
95
|
BondProtection = 'bond-protection',
|
|
93
96
|
Dca = 'dca',
|
|
94
97
|
LimitOrder = 'limit-order',
|
|
98
|
+
DebtInFrontRepay = 'debt-in-front-repay',
|
|
95
99
|
}
|
|
96
100
|
export enum IdOverrides {
|
|
97
101
|
TakeProfit = 'take-profit',
|
|
98
102
|
StopLoss = 'stop-loss',
|
|
103
|
+
TakeProfitWithGasPrice = 'take-profit-with-gas-price',
|
|
104
|
+
StopLossWithGasPrice = 'stop-loss-with-gas-price',
|
|
99
105
|
TrailingStop = 'trailing-stop',
|
|
100
106
|
LeverageManagement = 'leverage-management',
|
|
101
107
|
EoaLeverageManagement = 'leverage-management-eoa',
|
|
@@ -117,7 +123,9 @@ export namespace Bundles {
|
|
|
117
123
|
MAKER_REPAY = 10,
|
|
118
124
|
MAKER_BOOST = 11,
|
|
119
125
|
AAVE_V3_CLOSE_TO_DEBT = 12,
|
|
126
|
+
AAVE_V3_CLOSE_TO_DEBT_WITH_GAS_PRICE = 24,
|
|
120
127
|
AAVE_V3_CLOSE_TO_COLLATERAL = 13,
|
|
128
|
+
AAVE_V3_CLOSE_TO_COLLATERAL_WITH_GAS_PRICE = 25,
|
|
121
129
|
MORPHO_AAVE_V2_REPAY = 14,
|
|
122
130
|
MORPHO_AAVE_V2_BOOST = 15,
|
|
123
131
|
LIQUITY_REPAY = 16,
|
package/src/types/index.ts
CHANGED
|
@@ -140,14 +140,32 @@ export declare namespace Position {
|
|
|
140
140
|
price: string,
|
|
141
141
|
ratioState: RatioState,
|
|
142
142
|
}
|
|
143
|
+
|
|
144
|
+
interface CloseOnPriceWithMaximumGasPriceAave extends Base {
|
|
145
|
+
collAsset: EthereumAddress,
|
|
146
|
+
collAssetId: number,
|
|
147
|
+
debtAsset: EthereumAddress,
|
|
148
|
+
debtAssetId: number,
|
|
149
|
+
baseToken: EthereumAddress,
|
|
150
|
+
quoteToken: EthereumAddress,
|
|
151
|
+
price: string,
|
|
152
|
+
maximumGasPrice: string,
|
|
153
|
+
ratioState: RatioState,
|
|
154
|
+
}
|
|
155
|
+
|
|
143
156
|
interface TrailingStop extends Base {
|
|
144
157
|
roundId: number,
|
|
145
158
|
triggerPercentage: number,
|
|
146
159
|
closeToAssetAddr: EthereumAddress,
|
|
147
160
|
}
|
|
161
|
+
|
|
162
|
+
interface DebtInFrontRepay extends Base {
|
|
163
|
+
debtInFrontMin: string,
|
|
164
|
+
targetRepayRatioIncrease: number,
|
|
165
|
+
}
|
|
148
166
|
}
|
|
149
167
|
|
|
150
|
-
type SpecificAny = Specific.CloseOnPrice | Specific.TrailingStop | Specific.RatioProtection | Specific.CloseOnPriceAave;
|
|
168
|
+
type SpecificAny = Specific.CloseOnPrice | Specific.TrailingStop | Specific.RatioProtection | Specific.CloseOnPriceAave | Specific.CloseOnPriceWithMaximumGasPriceAave | Specific.DebtInFrontRepay;
|
|
151
169
|
|
|
152
170
|
export interface Automated {
|
|
153
171
|
chainId: ChainId,
|
|
@@ -189,11 +207,13 @@ type StrategyInfo<T extends number> = Record<T, Strategy<T>>;
|
|
|
189
207
|
export type MainnetStrategiesInfo = StrategyInfo<Strategies.MainnetIds>;
|
|
190
208
|
export type OptimismStrategiesInfo = StrategyInfo<Strategies.OptimismIds>;
|
|
191
209
|
export type ArbitrumStrategiesInfo = StrategyInfo<Strategies.ArbitrumIds>;
|
|
210
|
+
export type StrategyInfoUnion = MainnetStrategiesInfo | OptimismStrategiesInfo | ArbitrumStrategiesInfo;
|
|
192
211
|
|
|
193
212
|
type BundleInfo<T extends number> = Record<T, BundleOrStrategy<T>>;
|
|
194
213
|
export type MainnetBundleInfo = BundleInfo<Bundles.MainnetIds>;
|
|
195
214
|
export type OptimismBundleInfo = BundleInfo<Bundles.OptimismIds>;
|
|
196
215
|
export type ArbitrumBundleInfo = BundleInfo<Bundles.ArbitrumIds>;
|
|
216
|
+
export type BundleInfoUnion = MainnetBundleInfo | OptimismBundleInfo | ArbitrumBundleInfo;
|
|
197
217
|
|
|
198
218
|
export interface StrategiesInfo {
|
|
199
219
|
[ChainId.Ethereum]: MainnetStrategiesInfo,
|
|
@@ -208,8 +228,12 @@ export interface BundlesInfo {
|
|
|
208
228
|
}
|
|
209
229
|
|
|
210
230
|
export type StrategyOrBundleIds =
|
|
211
|
-
Strategies.MainnetIds
|
|
212
|
-
|
|
231
|
+
typeof Strategies.MainnetIds[keyof typeof Strategies.MainnetIds]
|
|
232
|
+
| typeof Strategies.OptimismIds[keyof typeof Strategies.OptimismIds]
|
|
233
|
+
| typeof Strategies.ArbitrumIds[keyof typeof Strategies.ArbitrumIds]
|
|
234
|
+
| typeof Bundles.MainnetIds[keyof typeof Bundles.MainnetIds]
|
|
235
|
+
| typeof Bundles.OptimismIds[keyof typeof Bundles.OptimismIds]
|
|
236
|
+
| typeof Bundles.ArbitrumIds[keyof typeof Bundles.ArbitrumIds];
|
|
213
237
|
|
|
214
238
|
export interface ParseData {
|
|
215
239
|
chainId: ChainId,
|