@paraswap/dex-lib 3.8.24 → 3.8.26-aave-gsm

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.
Files changed (42) hide show
  1. package/build/abi/Aave_GSM.json +751 -0
  2. package/build/dex/aave-gsm/aave-gsm.d.ts +33 -0
  3. package/build/dex/aave-gsm/aave-gsm.js +278 -0
  4. package/build/dex/aave-gsm/aave-gsm.js.map +1 -0
  5. package/build/dex/aave-gsm/config.d.ts +3 -0
  6. package/build/dex/aave-gsm/config.js +17 -0
  7. package/build/dex/aave-gsm/config.js.map +1 -0
  8. package/build/dex/aave-gsm/types.d.ts +11 -0
  9. package/build/dex/aave-gsm/types.js +3 -0
  10. package/build/dex/aave-gsm/types.js.map +1 -0
  11. package/build/dex/generic-rfq/rate-fetcher.js +1 -1
  12. package/build/dex/generic-rfq/rate-fetcher.js.map +1 -1
  13. package/build/dex/inception/inception-event-pool.d.ts +6 -4
  14. package/build/dex/inception/inception-event-pool.js +31 -8
  15. package/build/dex/inception/inception-event-pool.js.map +1 -1
  16. package/build/dex/inception/inception.js +16 -1
  17. package/build/dex/inception/inception.js.map +1 -1
  18. package/build/dex/index.js +4 -0
  19. package/build/dex/index.js.map +1 -1
  20. package/build/dex/oswap/oswap-pool.js +8 -8
  21. package/build/dex/oswap/oswap-pool.js.map +1 -1
  22. package/build/dex/oswap/oswap.d.ts +3 -3
  23. package/build/dex/oswap/oswap.js +21 -12
  24. package/build/dex/oswap/oswap.js.map +1 -1
  25. package/build/dex/oswap/types.d.ts +4 -4
  26. package/package.json +1 -1
  27. package/src/abi/Aave_GSM.json +751 -0
  28. package/src/abi/oswap/oswap.abi.json +452 -0
  29. package/src/dex/aave-gsm/aave-gsm-e2e.test.ts +109 -0
  30. package/src/dex/aave-gsm/aave-gsm-integration.test.ts +318 -0
  31. package/src/dex/aave-gsm/aave-gsm.ts +359 -0
  32. package/src/dex/aave-gsm/config.ts +16 -0
  33. package/src/dex/aave-gsm/types.ts +15 -0
  34. package/src/dex/generic-rfq/rate-fetcher.ts +6 -5
  35. package/src/dex/index.ts +4 -0
  36. package/src/dex/oswap/config.ts +32 -0
  37. package/src/dex/oswap/oswap-e2e.test.ts +91 -0
  38. package/src/dex/oswap/oswap-events.test.ts +88 -0
  39. package/src/dex/oswap/oswap-integration.test.ts +291 -0
  40. package/src/dex/oswap/oswap-pool.ts +190 -0
  41. package/src/dex/oswap/oswap.ts +414 -0
  42. package/src/dex/oswap/types.ts +29 -0
@@ -0,0 +1,318 @@
1
+ /* eslint-disable no-console */
2
+ import dotenv from 'dotenv';
3
+ dotenv.config();
4
+
5
+ import { Interface, Result } from '@ethersproject/abi';
6
+ import { DummyDexHelper } from '../../dex-helper/index';
7
+ import { Network, SwapSide } from '../../constants';
8
+ import { BI_POWS } from '../../bigint-constants';
9
+ import { AaveGsm } from './aave-gsm';
10
+ import {
11
+ checkPoolPrices,
12
+ checkPoolsLiquidity,
13
+ checkConstantPoolPrices,
14
+ } from '../../../tests/utils';
15
+ import { Tokens } from '../../../tests/constants-e2e';
16
+ import GSM_ABI from '../../abi/Aave_GSM.json';
17
+
18
+ function getReaderCalldata(
19
+ exchangeAddress: string,
20
+ readerIface: Interface,
21
+ amounts: bigint[],
22
+ funcName: string,
23
+ ) {
24
+ return amounts.map(amount => ({
25
+ target: exchangeAddress,
26
+ callData: readerIface.encodeFunctionData(funcName, [amount]),
27
+ }));
28
+ }
29
+
30
+ function decodeReaderResult(
31
+ results: Result,
32
+ readerIface: Interface,
33
+ funcName: string,
34
+ index: number,
35
+ ) {
36
+ return results.map(result => {
37
+ const parsed = readerIface.decodeFunctionResult(funcName, result);
38
+ return BigInt(parsed[index]._hex);
39
+ });
40
+ }
41
+
42
+ async function checkOnChainPricing(
43
+ aaveGsm: AaveGsm,
44
+ funcName: string,
45
+ blockNumber: number,
46
+ prices: bigint[],
47
+ amounts: bigint[],
48
+ ) {
49
+ const exchangeAddress = '0x686F8D21520f4ecEc7ba577be08354F4d1EB8262'; // TODO: Put here the real exchange address
50
+ const readerIface = new Interface(GSM_ABI);
51
+
52
+ const readerCallData = getReaderCalldata(
53
+ exchangeAddress,
54
+ readerIface,
55
+ amounts.slice(1),
56
+ funcName,
57
+ );
58
+
59
+ const readerResult = (
60
+ await aaveGsm.dexHelper.multiContract.methods
61
+ .aggregate(readerCallData)
62
+ .call({}, blockNumber)
63
+ ).returnData;
64
+
65
+ const expectedPrices = [0n].concat(
66
+ decodeReaderResult(
67
+ readerResult,
68
+ readerIface,
69
+ funcName,
70
+ funcName.indexOf('getGho') == 0 ? 1 : 0,
71
+ ),
72
+ );
73
+
74
+ expect(prices).toEqual(expectedPrices);
75
+ }
76
+
77
+ async function testPricingOnNetwork(
78
+ aaveGsm: AaveGsm,
79
+ network: Network,
80
+ dexKey: string,
81
+ blockNumber: number,
82
+ srcTokenSymbol: string,
83
+ destTokenSymbol: string,
84
+ side: SwapSide,
85
+ amounts: bigint[],
86
+ funcNameToCheck: string,
87
+ ) {
88
+ const networkTokens = Tokens[network];
89
+
90
+ const pools = await aaveGsm.getPoolIdentifiers(
91
+ networkTokens[srcTokenSymbol],
92
+ networkTokens[destTokenSymbol],
93
+ side,
94
+ blockNumber,
95
+ );
96
+ console.log(
97
+ `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `,
98
+ pools,
99
+ );
100
+
101
+ expect(pools.length).toBeGreaterThan(0);
102
+
103
+ const poolPrices = await aaveGsm.getPricesVolume(
104
+ networkTokens[srcTokenSymbol],
105
+ networkTokens[destTokenSymbol],
106
+ amounts,
107
+ side,
108
+ blockNumber,
109
+ pools,
110
+ );
111
+ console.log(
112
+ `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `,
113
+ poolPrices,
114
+ );
115
+
116
+ expect(poolPrices).not.toBeNull();
117
+ if (aaveGsm.hasConstantPriceLargeAmounts) {
118
+ checkConstantPoolPrices(poolPrices!, amounts, dexKey);
119
+ } else {
120
+ checkPoolPrices(poolPrices!, amounts, side, dexKey);
121
+ }
122
+
123
+ // Check if onchain pricing equals to calculated ones
124
+ await checkOnChainPricing(
125
+ aaveGsm,
126
+ funcNameToCheck,
127
+ blockNumber,
128
+ poolPrices![0].prices,
129
+ amounts,
130
+ );
131
+ }
132
+
133
+ describe('AaveGsm', function () {
134
+ const dexKey = 'AaveGsm';
135
+ let blockNumber: number;
136
+ let aaveGsm: AaveGsm;
137
+
138
+ describe('Mainnet GSM_USDT', () => {
139
+ const network = Network.MAINNET;
140
+ const dexHelper = new DummyDexHelper(network);
141
+
142
+ const tokens = Tokens[network];
143
+
144
+ const srcTokenSymbol = 'USDT';
145
+ const destTokenSymbol = 'GHO';
146
+
147
+ const amountsForSell = [
148
+ 0n,
149
+ 1n * BI_POWS[tokens[srcTokenSymbol].decimals],
150
+ 2n * BI_POWS[tokens[srcTokenSymbol].decimals],
151
+ 3n * BI_POWS[tokens[srcTokenSymbol].decimals],
152
+ 4n * BI_POWS[tokens[srcTokenSymbol].decimals],
153
+ 5n * BI_POWS[tokens[srcTokenSymbol].decimals],
154
+ 6n * BI_POWS[tokens[srcTokenSymbol].decimals],
155
+ 7n * BI_POWS[tokens[srcTokenSymbol].decimals],
156
+ 8n * BI_POWS[tokens[srcTokenSymbol].decimals],
157
+ 9n * BI_POWS[tokens[srcTokenSymbol].decimals],
158
+ 10n * BI_POWS[tokens[srcTokenSymbol].decimals],
159
+ ];
160
+
161
+ const amountsForBuy = [
162
+ 0n,
163
+ 1n * BI_POWS[tokens[destTokenSymbol].decimals],
164
+ 2n * BI_POWS[tokens[destTokenSymbol].decimals],
165
+ 3n * BI_POWS[tokens[destTokenSymbol].decimals],
166
+ 4n * BI_POWS[tokens[destTokenSymbol].decimals],
167
+ 5n * BI_POWS[tokens[destTokenSymbol].decimals],
168
+ 6n * BI_POWS[tokens[destTokenSymbol].decimals],
169
+ 7n * BI_POWS[tokens[destTokenSymbol].decimals],
170
+ 8n * BI_POWS[tokens[destTokenSymbol].decimals],
171
+ 9n * BI_POWS[tokens[destTokenSymbol].decimals],
172
+ 10n * BI_POWS[tokens[destTokenSymbol].decimals],
173
+ ];
174
+
175
+ beforeAll(async () => {
176
+ blockNumber = await dexHelper.web3Provider.eth.getBlockNumber();
177
+ aaveGsm = new AaveGsm(network, dexKey, dexHelper);
178
+ });
179
+
180
+ it('getPoolIdentifiers and getPricesVolume SELL', async function () {
181
+ await testPricingOnNetwork(
182
+ aaveGsm,
183
+ network,
184
+ dexKey,
185
+ blockNumber,
186
+ srcTokenSymbol,
187
+ destTokenSymbol,
188
+ SwapSide.SELL,
189
+ amountsForSell,
190
+ 'getGhoAmountForSellAsset',
191
+ );
192
+ });
193
+
194
+ it('getPoolIdentifiers and getPricesVolume BUY', async function () {
195
+ await testPricingOnNetwork(
196
+ aaveGsm,
197
+ network,
198
+ dexKey,
199
+ blockNumber,
200
+ srcTokenSymbol,
201
+ destTokenSymbol,
202
+ SwapSide.BUY,
203
+ amountsForBuy,
204
+ 'getAssetAmountForSellAsset',
205
+ );
206
+ });
207
+
208
+ it('getTopPoolsForToken', async function () {
209
+ // We have to check without calling initializePricing, because
210
+ // pool-tracker is not calling that function
211
+ const newAaveGsm = new AaveGsm(network, dexKey, dexHelper);
212
+ const poolLiquidity = await newAaveGsm.getTopPoolsForToken(
213
+ tokens[srcTokenSymbol].address,
214
+ 10,
215
+ );
216
+ console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity);
217
+
218
+ if (!newAaveGsm.hasConstantPriceLargeAmounts) {
219
+ checkPoolsLiquidity(
220
+ poolLiquidity,
221
+ Tokens[network][srcTokenSymbol].address,
222
+ dexKey,
223
+ );
224
+ }
225
+ });
226
+ });
227
+
228
+ describe('Mainnet GSM_USDC', () => {
229
+ const network = Network.MAINNET;
230
+ const dexHelper = new DummyDexHelper(network);
231
+
232
+ const tokens = Tokens[network];
233
+
234
+ // Don't forget to update relevant tokens in constant-e2e.ts
235
+ const srcTokenSymbol = 'USDC';
236
+ const destTokenSymbol = 'GHO';
237
+
238
+ const amountsForSell = [
239
+ 0n,
240
+ 1n * BI_POWS[tokens[srcTokenSymbol].decimals],
241
+ 2n * BI_POWS[tokens[srcTokenSymbol].decimals],
242
+ 3n * BI_POWS[tokens[srcTokenSymbol].decimals],
243
+ 4n * BI_POWS[tokens[srcTokenSymbol].decimals],
244
+ 5n * BI_POWS[tokens[srcTokenSymbol].decimals],
245
+ 6n * BI_POWS[tokens[srcTokenSymbol].decimals],
246
+ 7n * BI_POWS[tokens[srcTokenSymbol].decimals],
247
+ 8n * BI_POWS[tokens[srcTokenSymbol].decimals],
248
+ 9n * BI_POWS[tokens[srcTokenSymbol].decimals],
249
+ 10n * BI_POWS[tokens[srcTokenSymbol].decimals],
250
+ ];
251
+
252
+ const amountsForBuy = [
253
+ 0n,
254
+ 1n * BI_POWS[tokens[destTokenSymbol].decimals],
255
+ 2n * BI_POWS[tokens[destTokenSymbol].decimals],
256
+ 3n * BI_POWS[tokens[destTokenSymbol].decimals],
257
+ 4n * BI_POWS[tokens[destTokenSymbol].decimals],
258
+ 5n * BI_POWS[tokens[destTokenSymbol].decimals],
259
+ 6n * BI_POWS[tokens[destTokenSymbol].decimals],
260
+ 7n * BI_POWS[tokens[destTokenSymbol].decimals],
261
+ 8n * BI_POWS[tokens[destTokenSymbol].decimals],
262
+ 9n * BI_POWS[tokens[destTokenSymbol].decimals],
263
+ 10n * BI_POWS[tokens[destTokenSymbol].decimals],
264
+ ];
265
+
266
+ beforeAll(async () => {
267
+ blockNumber = await dexHelper.web3Provider.eth.getBlockNumber();
268
+ aaveGsm = new AaveGsm(network, dexKey, dexHelper);
269
+ });
270
+
271
+ it('getPoolIdentifiers and getPricesVolume SELL', async function () {
272
+ await testPricingOnNetwork(
273
+ aaveGsm,
274
+ network,
275
+ dexKey,
276
+ blockNumber,
277
+ srcTokenSymbol,
278
+ destTokenSymbol,
279
+ SwapSide.SELL,
280
+ amountsForSell,
281
+ 'getGhoAmountForSellAsset',
282
+ );
283
+ });
284
+
285
+ it('getPoolIdentifiers and getPricesVolume BUY', async function () {
286
+ await testPricingOnNetwork(
287
+ aaveGsm,
288
+ network,
289
+ dexKey,
290
+ blockNumber,
291
+ srcTokenSymbol,
292
+ destTokenSymbol,
293
+ SwapSide.BUY,
294
+ amountsForBuy,
295
+ 'getAssetAmountForSellAsset',
296
+ );
297
+ });
298
+
299
+ it('getTopPoolsForToken', async function () {
300
+ // We have to check without calling initializePricing, because
301
+ // pool-tracker is not calling that function
302
+ const newAaveGsm = new AaveGsm(network, dexKey, dexHelper);
303
+ const poolLiquidity = await newAaveGsm.getTopPoolsForToken(
304
+ tokens[srcTokenSymbol].address,
305
+ 10,
306
+ );
307
+ console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity);
308
+
309
+ if (!newAaveGsm.hasConstantPriceLargeAmounts) {
310
+ checkPoolsLiquidity(
311
+ poolLiquidity,
312
+ Tokens[network][srcTokenSymbol].address,
313
+ dexKey,
314
+ );
315
+ }
316
+ });
317
+ });
318
+ });
@@ -0,0 +1,359 @@
1
+ import {
2
+ Token,
3
+ Address,
4
+ ExchangePrices,
5
+ PoolPrices,
6
+ AdapterExchangeParam,
7
+ PoolLiquidity,
8
+ Logger,
9
+ NumberAsString,
10
+ DexExchangeParam,
11
+ } from '../../types';
12
+ import { SwapSide, Network } from '../../constants';
13
+ import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
14
+ import { getDexKeysWithNetwork } from '../../utils';
15
+ import { IDex } from '../../dex/idex';
16
+ import { IDexHelper } from '../../dex-helper/idex-helper';
17
+ import { AaveGsmData, DexParams } from './types';
18
+ import { SimpleExchange } from '../simple-exchange';
19
+ import { AaveGsmConfig } from './config';
20
+
21
+ import GSM_ABI from '../../abi/Aave_GSM.json';
22
+ import { Interface } from '@ethersproject/abi';
23
+ import { MultiResult } from '../../lib/multi-wrapper';
24
+ import { BytesLike } from 'ethers';
25
+ import { generalDecoder } from '../../lib/decoders';
26
+ import { parseUnits } from 'ethers/lib/utils';
27
+
28
+ export class AaveGsm extends SimpleExchange implements IDex<AaveGsmData> {
29
+ static readonly gsmInterface = new Interface(GSM_ABI);
30
+
31
+ protected config: DexParams;
32
+
33
+ readonly hasConstantPriceLargeAmounts = false;
34
+ readonly needWrapNative = false;
35
+
36
+ readonly isFeeOnTransferSupported = false;
37
+
38
+ public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
39
+ getDexKeysWithNetwork(AaveGsmConfig);
40
+
41
+ logger: Logger;
42
+
43
+ constructor(
44
+ readonly network: Network,
45
+ readonly dexKey: string,
46
+ readonly dexHelper: IDexHelper,
47
+ ) {
48
+ super(dexHelper, dexKey);
49
+ const config = AaveGsmConfig[dexKey][network];
50
+ this.config = {
51
+ GSM_USDT: config.GSM_USDT.toLowerCase(),
52
+ GSM_USDC: config.GSM_USDC.toLowerCase(),
53
+ USDT: config.USDT.toLowerCase(),
54
+ USDC: config.USDC.toLowerCase(),
55
+ GHO: config.GHO.toLowerCase(),
56
+ };
57
+
58
+ this.logger = dexHelper.getLogger(dexKey);
59
+ }
60
+
61
+ getAdapters(side: SwapSide): { name: string; index: number }[] | null {
62
+ return null;
63
+ }
64
+
65
+ async getPoolIdentifiers(
66
+ srcToken: Token,
67
+ destToken: Token,
68
+ side: SwapSide,
69
+ blockNumber: number,
70
+ ): Promise<string[]> {
71
+ const srcTokenAddress = srcToken.address.toLowerCase();
72
+ const destTokenAddress = destToken.address.toLowerCase();
73
+
74
+ if (
75
+ (srcTokenAddress === this.config.GHO &&
76
+ destTokenAddress === this.config.USDT) ||
77
+ (srcTokenAddress === this.config.USDT &&
78
+ destTokenAddress === this.config.GHO)
79
+ ) {
80
+ return [`${this.dexKey}_${this.config.GSM_USDT}`];
81
+ } else if (
82
+ (srcTokenAddress === this.config.GHO &&
83
+ destTokenAddress === this.config.USDC) ||
84
+ (srcTokenAddress === this.config.USDC &&
85
+ destTokenAddress === this.config.GHO)
86
+ ) {
87
+ return [`${this.dexKey}_${this.config.GSM_USDC}`];
88
+ } else {
89
+ return [];
90
+ }
91
+ }
92
+
93
+ // Returns pool prices for amounts.
94
+ // If limitPools is defined only pools in limitPools
95
+ // should be used. If limitPools is undefined then
96
+ // any pools can be used.
97
+ async getPricesVolume(
98
+ srcToken: Token,
99
+ destToken: Token,
100
+ amounts: bigint[],
101
+ side: SwapSide,
102
+ blockNumber: number,
103
+ limitPools?: string[],
104
+ ): Promise<null | ExchangePrices<AaveGsmData>> {
105
+ const srcTokenAddress = srcToken.address.toLowerCase();
106
+ const destTokenAddress = destToken.address.toLowerCase();
107
+
108
+ if (
109
+ !(
110
+ (srcTokenAddress == this.config.GHO &&
111
+ (destTokenAddress == this.config.USDC ||
112
+ destTokenAddress == this.config.USDT)) ||
113
+ (destTokenAddress == this.config.GHO &&
114
+ (srcTokenAddress == this.config.USDC ||
115
+ srcTokenAddress == this.config.USDT))
116
+ )
117
+ ) {
118
+ return null;
119
+ }
120
+
121
+ let endpoint: string;
122
+ let target: string;
123
+ let resultIsGho: boolean;
124
+ if (srcTokenAddress == this.config.GHO && side == SwapSide.BUY) {
125
+ endpoint = 'getGhoAmountForBuyAsset';
126
+ resultIsGho = true;
127
+ } else if (srcTokenAddress == this.config.GHO && side == SwapSide.SELL) {
128
+ endpoint = 'getAssetAmountForBuyAsset';
129
+ resultIsGho = false;
130
+ } else if (destTokenAddress == this.config.GHO && side == SwapSide.SELL) {
131
+ endpoint = 'getGhoAmountForSellAsset';
132
+ resultIsGho = true;
133
+ } else {
134
+ endpoint = 'getAssetAmountForSellAsset';
135
+ resultIsGho = false;
136
+ }
137
+
138
+ if (
139
+ srcTokenAddress == this.config.USDT ||
140
+ destTokenAddress == this.config.USDT
141
+ ) {
142
+ target = this.config.GSM_USDT;
143
+ } else {
144
+ target = this.config.GSM_USDC;
145
+ }
146
+
147
+ const unit = parseUnits(
148
+ '1',
149
+ side == SwapSide.SELL ? srcToken.decimals : destToken.decimals,
150
+ ).toBigInt();
151
+
152
+ const amountsWithUnit = [...amounts, unit];
153
+
154
+ const calls = amountsWithUnit.map(amount => ({
155
+ target,
156
+ callData: AaveGsm.gsmInterface.encodeFunctionData(endpoint, [amount]),
157
+ decodeFunction: (
158
+ result: MultiResult<BytesLike> | BytesLike,
159
+ ): { underlying: bigint; gho: bigint } => {
160
+ return generalDecoder(
161
+ result,
162
+ ['uint256', 'uint256', 'uint256', 'uint256'],
163
+ {
164
+ underlying: 0n,
165
+ gho: 0n,
166
+ },
167
+ value => ({
168
+ underlying: value[0].toBigInt(),
169
+ gho: value[1].toBigInt(),
170
+ }),
171
+ );
172
+ },
173
+ }));
174
+
175
+ let results = await this.dexHelper.multiWrapper.tryAggregate<{
176
+ underlying: bigint;
177
+ gho: bigint;
178
+ }>(true, calls, blockNumber);
179
+
180
+ const unitPriceResult = results.pop()!;
181
+
182
+ return [
183
+ {
184
+ unit: resultIsGho
185
+ ? unitPriceResult.returnData.gho
186
+ : unitPriceResult.returnData.underlying,
187
+ prices: results.map(result =>
188
+ resultIsGho ? result.returnData.gho : result.returnData.underlying,
189
+ ),
190
+ data: {
191
+ exchange: this.dexKey,
192
+ },
193
+ poolAddresses: [target],
194
+ exchange: this.dexKey,
195
+ gasCost: endpoint.indexOf('BuyAsset') > 0 ? 80000 : 74000,
196
+ poolIdentifier: `${this.dexKey}_${target}`,
197
+ },
198
+ ];
199
+ }
200
+
201
+ // Returns estimated gas cost of calldata for this DEX in multiSwap
202
+ getCalldataGasCost(poolPrices: PoolPrices<AaveGsmData>): number | number[] {
203
+ return CALLDATA_GAS_COST.DEX_NO_PAYLOAD;
204
+ }
205
+
206
+ getAdapterParam(
207
+ srcToken: string,
208
+ destToken: string,
209
+ srcAmount: string,
210
+ destAmount: string,
211
+ data: AaveGsmData,
212
+ side: SwapSide,
213
+ ): AdapterExchangeParam {
214
+ const { exchange } = data;
215
+
216
+ const payload = '';
217
+
218
+ return {
219
+ targetExchange: exchange,
220
+ payload,
221
+ networkFee: '0',
222
+ };
223
+ }
224
+
225
+ async getDexParam(
226
+ srcToken: Address,
227
+ destToken: Address,
228
+ srcAmount: NumberAsString,
229
+ destAmount: NumberAsString,
230
+ recipient: Address,
231
+ data: AaveGsmData,
232
+ side: SwapSide,
233
+ ): Promise<DexExchangeParam> {
234
+ const isSrcGho = srcToken.toLowerCase() === this.config.GHO;
235
+ const swapFunction = isSrcGho ? 'buyAsset' : 'sellAsset';
236
+ const ghoAmount = isSrcGho ? srcAmount : destAmount;
237
+ let assetAmount = isSrcGho ? destAmount : srcAmount;
238
+ const targetExchange =
239
+ srcToken.toLowerCase() === this.config.USDT ||
240
+ destToken.toLowerCase() === this.config.USDT
241
+ ? this.config.GSM_USDT
242
+ : this.config.GSM_USDC;
243
+
244
+ if (BigInt(assetAmount) == 1n) {
245
+ const endpoint = isSrcGho
246
+ ? 'getAssetAmountForBuyAsset'
247
+ : 'getAssetAmountForSellAsset';
248
+
249
+ const calldata = {
250
+ target: targetExchange,
251
+ callData: AaveGsm.gsmInterface.encodeFunctionData(endpoint, [
252
+ ghoAmount,
253
+ ]),
254
+ decodeFunction: (
255
+ result: MultiResult<BytesLike> | BytesLike,
256
+ ): { underlying: bigint; gho: bigint } => {
257
+ return generalDecoder(
258
+ result,
259
+ ['uint256', 'uint256', 'uint256', 'uint256'],
260
+ {
261
+ underlying: 0n,
262
+ gho: 0n,
263
+ },
264
+ value => ({
265
+ underlying: value[0].toBigInt(),
266
+ gho: value[1].toBigInt(),
267
+ }),
268
+ );
269
+ },
270
+ };
271
+
272
+ const result = await this.dexHelper.multiWrapper.tryAggregate<{
273
+ underlying: bigint;
274
+ gho: bigint;
275
+ }>(true, [calldata]);
276
+
277
+ assetAmount = result[0].returnData.underlying.toString();
278
+ }
279
+
280
+ const exchangeData = AaveGsm.gsmInterface.encodeFunctionData(swapFunction, [
281
+ assetAmount,
282
+ recipient,
283
+ ]);
284
+
285
+ return {
286
+ needWrapNative: this.needWrapNative,
287
+ dexFuncHasRecipient: true,
288
+ exchangeData,
289
+ targetExchange,
290
+ returnAmountPos: isSrcGho ? 1 : 0,
291
+ };
292
+ }
293
+
294
+ // Returns list of top pools based on liquidity. Max
295
+ // limit number pools should be returned.
296
+ async getTopPoolsForToken(
297
+ tokenAddress: Address,
298
+ limit: number,
299
+ ): Promise<PoolLiquidity[]> {
300
+ tokenAddress = tokenAddress.toLowerCase();
301
+
302
+ if (tokenAddress == this.config.GHO) {
303
+ return [
304
+ {
305
+ exchange: this.dexKey,
306
+ address: this.config.GSM_USDC,
307
+ connectorTokens: [
308
+ {
309
+ decimals: 6,
310
+ address: this.config.USDC,
311
+ },
312
+ ],
313
+ liquidityUSD: 1000000000, // Just returning a big number so this DEX will be preferred
314
+ },
315
+ {
316
+ exchange: this.dexKey,
317
+ address: this.config.GSM_USDT,
318
+ connectorTokens: [
319
+ {
320
+ decimals: 6,
321
+ address: this.config.USDT,
322
+ },
323
+ ],
324
+ liquidityUSD: 1000000000, // Just returning a big number so this DEX will be preferred
325
+ },
326
+ ];
327
+ } else if (tokenAddress == this.config.USDC) {
328
+ return [
329
+ {
330
+ exchange: this.dexKey,
331
+ address: this.config.GSM_USDC,
332
+ connectorTokens: [
333
+ {
334
+ decimals: 18,
335
+ address: this.config.GHO,
336
+ },
337
+ ],
338
+ liquidityUSD: 1000000000, // Just returning a big number so this DEX will be preferred
339
+ },
340
+ ];
341
+ } else if (tokenAddress == this.config.USDT) {
342
+ return [
343
+ {
344
+ exchange: this.dexKey,
345
+ address: this.config.GSM_USDT,
346
+ connectorTokens: [
347
+ {
348
+ decimals: 18,
349
+ address: this.config.GHO,
350
+ },
351
+ ],
352
+ liquidityUSD: 1000000000, // Just returning a big number so this DEX will be preferred
353
+ },
354
+ ];
355
+ } else {
356
+ return [];
357
+ }
358
+ }
359
+ }
@@ -0,0 +1,16 @@
1
+ import { DexParams } from './types';
2
+ import { DexConfigMap, AdapterMappings } from '../../types';
3
+ import { Network, SwapSide } from '../../constants';
4
+ import { AaveV3Ethereum, MiscEthereum } from '@bgd-labs/aave-address-book';
5
+
6
+ export const AaveGsmConfig: DexConfigMap<DexParams> = {
7
+ AaveGsm: {
8
+ [Network.MAINNET]: {
9
+ GSM_USDT: MiscEthereum.GSM_USDT,
10
+ GSM_USDC: MiscEthereum.GSM_USDC,
11
+ USDT: AaveV3Ethereum.ASSETS.USDT.UNDERLYING,
12
+ USDC: AaveV3Ethereum.ASSETS.USDC.UNDERLYING,
13
+ GHO: AaveV3Ethereum.ASSETS.GHO.UNDERLYING,
14
+ },
15
+ },
16
+ };
@@ -0,0 +1,15 @@
1
+ import { Address } from '../../types';
2
+
3
+ export type AaveGsmData = {
4
+ // returned by the API that can be used for
5
+ // tx building. The data structure should be minimal.
6
+ exchange: Address;
7
+ };
8
+
9
+ export type DexParams = {
10
+ GSM_USDT: string;
11
+ GSM_USDC: string;
12
+ USDT: string;
13
+ USDC: string;
14
+ GHO: string;
15
+ };