@avail-project/ca-common 1.0.1 → 2.0.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/cjs/xcs/autochoice.js +96 -237
- package/dist/cjs/xcs/bebop-agg.js +34 -5
- package/dist/cjs/xcs/index.js +0 -1
- package/dist/cjs/xcs/lifi-agg.js +34 -5
- package/dist/esm/xcs/autochoice.js +98 -238
- package/dist/esm/xcs/bebop-agg.js +34 -5
- package/dist/esm/xcs/index.js +0 -1
- package/dist/esm/xcs/lifi-agg.js +34 -5
- package/dist/types/xcs/autochoice.d.ts +6 -52
- package/dist/types/xcs/bebop-agg.d.ts +2 -2
- package/dist/types/xcs/iface.d.ts +37 -5
- package/dist/types/xcs/index.d.ts +0 -1
- package/dist/types/xcs/lifi-agg.d.ts +18 -14
- package/package.json +1 -1
- package/dist/cjs/xcs/yieldyak-agg.js +0 -113
- package/dist/esm/xcs/yieldyak-agg.js +0 -109
- package/dist/types/xcs/yieldyak-agg.d.ts +0 -21
|
@@ -3,6 +3,7 @@ import { bytesToHex, getAddress } from "viem";
|
|
|
3
3
|
import { QuoteType, } from "./iface";
|
|
4
4
|
import { Universe } from "../proto/definition";
|
|
5
5
|
import { encodeChainID36 } from "../data";
|
|
6
|
+
import Decimal from "decimal.js";
|
|
6
7
|
// https://api.bebop.xyz/{jam|pmm}/chains
|
|
7
8
|
const ChainNameMapping = new Map(Object.entries({
|
|
8
9
|
ethereum: 1,
|
|
@@ -38,6 +39,7 @@ export class BebopAggregator {
|
|
|
38
39
|
params: {
|
|
39
40
|
source: "arcana",
|
|
40
41
|
},
|
|
42
|
+
timeout: 10_000,
|
|
41
43
|
});
|
|
42
44
|
}
|
|
43
45
|
async getQuotes(requests) {
|
|
@@ -100,12 +102,39 @@ export class BebopAggregator {
|
|
|
100
102
|
return null;
|
|
101
103
|
}
|
|
102
104
|
const buyT = bestRoute.quote.buyTokens[outputTokenAddr];
|
|
105
|
+
const sellT = bestRoute.quote.sellTokens[inputTokenAddr];
|
|
106
|
+
const outputAmountInDecimal = new Decimal(buyT.minimumAmount)
|
|
107
|
+
.div(Decimal.pow(10, buyT.decimals))
|
|
108
|
+
.toFixed(buyT.decimals);
|
|
109
|
+
const inputAmountInDecimal = new Decimal(sellT.amount)
|
|
110
|
+
.div(Decimal.pow(10, sellT.decimals))
|
|
111
|
+
.toFixed(sellT.decimals);
|
|
103
112
|
return {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
expiry: bestRoute.quote.expiry,
|
|
114
|
+
input: {
|
|
115
|
+
amount: inputAmountInDecimal,
|
|
116
|
+
amountRaw: BigInt(sellT.amount),
|
|
117
|
+
contractAddress: inputTokenAddr,
|
|
118
|
+
decimals: sellT.decimals,
|
|
119
|
+
value: Decimal.mul(inputAmountInDecimal, sellT.priceUsd).toNumber(),
|
|
120
|
+
symbol: sellT.symbol,
|
|
121
|
+
},
|
|
122
|
+
output: {
|
|
123
|
+
amount: outputAmountInDecimal,
|
|
124
|
+
amountRaw: BigInt(buyT.minimumAmount),
|
|
125
|
+
contractAddress: outputTokenAddr,
|
|
126
|
+
decimals: buyT.decimals,
|
|
127
|
+
value: Decimal.mul(buyT.priceUsd, outputAmountInDecimal).toNumber(),
|
|
128
|
+
symbol: buyT.symbol,
|
|
129
|
+
},
|
|
130
|
+
txData: {
|
|
131
|
+
approvalAddress: bestRoute.quote.approvalTarget,
|
|
132
|
+
tx: {
|
|
133
|
+
to: bestRoute.quote.tx.to,
|
|
134
|
+
value: bestRoute.quote.tx.value,
|
|
135
|
+
data: bestRoute.quote.tx.data,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
109
138
|
};
|
|
110
139
|
}));
|
|
111
140
|
return list.map((item) => {
|
package/dist/esm/xcs/index.js
CHANGED
package/dist/esm/xcs/lifi-agg.js
CHANGED
|
@@ -2,11 +2,13 @@ import axios, { AxiosError } from "axios";
|
|
|
2
2
|
import { bytesToHex, getAddress } from "viem";
|
|
3
3
|
import { QuoteType, } from "./iface";
|
|
4
4
|
import { Universe } from "../proto/definition";
|
|
5
|
+
import Decimal from "decimal.js";
|
|
5
6
|
export class LiFiAggregator {
|
|
6
7
|
static BASE_URL_V1 = "https://li.quest/v1";
|
|
7
8
|
static COMMON_OPTIONS = {
|
|
8
9
|
denyExchanges: "openocean",
|
|
9
10
|
slippage: "0.01",
|
|
11
|
+
skipSimulation: true,
|
|
10
12
|
};
|
|
11
13
|
axios;
|
|
12
14
|
constructor(apiKey) {
|
|
@@ -15,6 +17,7 @@ export class LiFiAggregator {
|
|
|
15
17
|
headers: {
|
|
16
18
|
"x-lifi-api-key": apiKey,
|
|
17
19
|
},
|
|
20
|
+
timeout: 10_000,
|
|
18
21
|
});
|
|
19
22
|
}
|
|
20
23
|
async getQuotes(requests) {
|
|
@@ -76,12 +79,38 @@ export class LiFiAggregator {
|
|
|
76
79
|
}
|
|
77
80
|
throw e;
|
|
78
81
|
}
|
|
82
|
+
const { estimate, transactionRequest: { to, value, data }, action: { fromToken, toToken }, } = resp.data;
|
|
83
|
+
const inputAmountInDecimal = new Decimal(estimate.fromAmount)
|
|
84
|
+
.div(Decimal.pow(10, fromToken.decimals))
|
|
85
|
+
.toFixed(fromToken.decimals);
|
|
86
|
+
const outputAmountInDecimal = new Decimal(estimate.toAmountMin)
|
|
87
|
+
.div(Decimal.pow(10, toToken.decimals))
|
|
88
|
+
.toFixed(toToken.decimals);
|
|
79
89
|
return {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
90
|
+
input: {
|
|
91
|
+
amount: inputAmountInDecimal,
|
|
92
|
+
amountRaw: BigInt(estimate.fromAmount),
|
|
93
|
+
contractAddress: inputTokenAddr,
|
|
94
|
+
decimals: fromToken.decimals,
|
|
95
|
+
value: Decimal.mul(inputAmountInDecimal, fromToken.priceUSD).toNumber(),
|
|
96
|
+
symbol: fromToken.symbol,
|
|
97
|
+
},
|
|
98
|
+
output: {
|
|
99
|
+
amount: outputAmountInDecimal,
|
|
100
|
+
amountRaw: BigInt(estimate.toAmountMin),
|
|
101
|
+
contractAddress: outputTokenAddr,
|
|
102
|
+
decimals: toToken.decimals,
|
|
103
|
+
value: Decimal.mul(outputAmountInDecimal, toToken.priceUSD).toNumber(),
|
|
104
|
+
symbol: toToken.symbol,
|
|
105
|
+
},
|
|
106
|
+
txData: {
|
|
107
|
+
approvalAddress: estimate.approvalAddress,
|
|
108
|
+
tx: {
|
|
109
|
+
to,
|
|
110
|
+
value,
|
|
111
|
+
data,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
85
114
|
};
|
|
86
115
|
}));
|
|
87
116
|
return list.map((item) => {
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import Decimal from "decimal.js";
|
|
2
|
-
import { Aggregator, Quote, QuoteRequestExactInput, QuoteRequestExactOutput } from "./iface";
|
|
2
|
+
import { Aggregator, Quote, QuoteRequestExactInput, QuoteRequestExactOutput, QuoteResponse } from "./iface";
|
|
3
3
|
import { Currency, CurrencyID, OmniversalChainID } from "../data";
|
|
4
4
|
import { Bytes } from "../types";
|
|
5
|
-
import {
|
|
6
|
-
type Asset = {
|
|
7
|
-
tokenAddress: Bytes;
|
|
8
|
-
amount: bigint;
|
|
9
|
-
};
|
|
10
|
-
export type Holding = {
|
|
11
|
-
chainID: OmniversalChainID;
|
|
12
|
-
value: number;
|
|
13
|
-
} & Asset;
|
|
5
|
+
import { Holding } from "./iface";
|
|
14
6
|
export declare class AutoSelectionError extends Error {
|
|
15
7
|
}
|
|
16
8
|
declare const enum AggregateAggregatorsMode {
|
|
@@ -22,15 +14,7 @@ export declare function aggregateAggregators(requests: (QuoteRequestExactInput |
|
|
|
22
14
|
aggregator: Aggregator;
|
|
23
15
|
}[]>;
|
|
24
16
|
export declare function autoSelectSourcesV2(userAddress: Bytes, holdings: Holding[], outputRequired: Decimal, aggregators: Aggregator[], commonCurrencyID?: CurrencyID): Promise<{
|
|
25
|
-
|
|
26
|
-
req: QuoteRequestExactInput;
|
|
27
|
-
originalHolding: Holding;
|
|
28
|
-
cur: Currency;
|
|
29
|
-
idx: number;
|
|
30
|
-
} & {
|
|
31
|
-
quote: Quote;
|
|
32
|
-
agg: Aggregator;
|
|
33
|
-
})[];
|
|
17
|
+
quoteResponses: QuoteResponse[];
|
|
34
18
|
usedCOTs: {
|
|
35
19
|
originalHolding: Holding;
|
|
36
20
|
amountUsed: Decimal;
|
|
@@ -38,37 +22,7 @@ export declare function autoSelectSourcesV2(userAddress: Bytes, holdings: Holdin
|
|
|
38
22
|
cur: Currency;
|
|
39
23
|
}[];
|
|
40
24
|
}>;
|
|
41
|
-
export declare function
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
originalHolding: Holding;
|
|
45
|
-
cur: Currency;
|
|
46
|
-
} & {
|
|
47
|
-
quote: Quote;
|
|
48
|
-
agg: Aggregator;
|
|
49
|
-
})[]>;
|
|
50
|
-
export declare function determineDestinationSwaps(userAddress: Bytes, chainID: OmniversalChainID, requirement: Asset, aggregators: Aggregator[], commonCurrencyID?: CurrencyID): Promise<{
|
|
51
|
-
quote: Quote | null;
|
|
52
|
-
aggregator: Aggregator;
|
|
53
|
-
inputAmount: Decimal;
|
|
54
|
-
outputAmount: bigint;
|
|
55
|
-
}>;
|
|
56
|
-
export declare function liquidateInputHoldings(userAddress: Bytes, holdings: Holding[], aggregators: Aggregator[], collectionFees: FixedFeeTuple[], commonCurrencyID?: CurrencyID): Promise<{
|
|
57
|
-
quotes: {
|
|
58
|
-
agg: Aggregator;
|
|
59
|
-
quote: Quote;
|
|
60
|
-
req: QuoteRequestExactInput;
|
|
61
|
-
cfee: bigint;
|
|
62
|
-
originalHolding: Holding;
|
|
63
|
-
cur: Currency;
|
|
64
|
-
aggregator: Aggregator;
|
|
65
|
-
}[];
|
|
66
|
-
total: Decimal;
|
|
67
|
-
}>;
|
|
68
|
-
export declare function destinationSwapWithExactIn(userAddress: Bytes, chainID: OmniversalChainID, inputAmount: bigint, outputToken: Bytes, aggregators: Aggregator[], commonCurrencyID?: CurrencyID): Promise<{
|
|
69
|
-
inputAmount: Decimal;
|
|
70
|
-
outputAmount: bigint;
|
|
71
|
-
quote: Quote | null;
|
|
72
|
-
aggregator: Aggregator;
|
|
73
|
-
}>;
|
|
25
|
+
export declare function determineDestinationSwaps(userAddress: Bytes, requirement: Holding, aggregators: Aggregator[], commonCurrencyID?: CurrencyID): Promise<QuoteResponse>;
|
|
26
|
+
export declare function liquidateInputHoldings(userAddress: Bytes, holdings: Holding[], aggregators: Aggregator[], commonCurrencyID?: CurrencyID): Promise<QuoteResponse[]>;
|
|
27
|
+
export declare function destinationSwapWithExactIn(userAddress: Bytes, omniChainID: OmniversalChainID, inputAmount: bigint, outputToken: Bytes, aggregators: Aggregator[], inputCurrency?: CurrencyID): Promise<QuoteResponse>;
|
|
74
28
|
export {};
|
|
@@ -35,7 +35,7 @@ export type BebopCommonQuote = {
|
|
|
35
35
|
priceBeforeFee: number;
|
|
36
36
|
}>;
|
|
37
37
|
settlementAddress: string;
|
|
38
|
-
approvalTarget:
|
|
38
|
+
approvalTarget: Hex;
|
|
39
39
|
requiredSignatures: Array<never>;
|
|
40
40
|
priceImpact: number;
|
|
41
41
|
warnings: Array<never>;
|
|
@@ -100,5 +100,5 @@ export declare class BebopAggregator implements Aggregator {
|
|
|
100
100
|
private static readonly COMMON_OPTIONS;
|
|
101
101
|
private readonly axios;
|
|
102
102
|
constructor(apiKey: string);
|
|
103
|
-
getQuotes(requests: (QuoteRequestExactInput | QuoteRequestExactOutput)[]): Promise<(
|
|
103
|
+
getQuotes(requests: (QuoteRequestExactInput | QuoteRequestExactOutput)[]): Promise<(Quote | null)[]>;
|
|
104
104
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Bytes } from "../types";
|
|
2
2
|
import { OmniversalChainID } from "../data";
|
|
3
|
+
import { Hex } from "viem";
|
|
3
4
|
export declare enum QuoteType {
|
|
4
5
|
EXACT_IN = 0,
|
|
5
6
|
EXACT_OUT = 1
|
|
@@ -8,12 +9,43 @@ export declare enum QuoteSeriousness {
|
|
|
8
9
|
PRICE_SURVEY = 0,
|
|
9
10
|
SERIOUS = 1
|
|
10
11
|
}
|
|
12
|
+
export type QuoteResponse = {
|
|
13
|
+
chainID: number;
|
|
14
|
+
quote: Quote;
|
|
15
|
+
holding: Holding;
|
|
16
|
+
aggregator: Aggregator;
|
|
17
|
+
};
|
|
18
|
+
export type Holding = {
|
|
19
|
+
chainID: OmniversalChainID;
|
|
20
|
+
tokenAddress: Bytes;
|
|
21
|
+
amountRaw: bigint;
|
|
22
|
+
};
|
|
11
23
|
export interface Quote {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
expiry?: number;
|
|
25
|
+
input: {
|
|
26
|
+
contractAddress: Hex;
|
|
27
|
+
amount: string;
|
|
28
|
+
amountRaw: bigint;
|
|
29
|
+
decimals: number;
|
|
30
|
+
value: number;
|
|
31
|
+
symbol: string;
|
|
32
|
+
};
|
|
33
|
+
output: {
|
|
34
|
+
contractAddress: Hex;
|
|
35
|
+
amount: string;
|
|
36
|
+
amountRaw: bigint;
|
|
37
|
+
decimals: number;
|
|
38
|
+
value: number;
|
|
39
|
+
symbol: string;
|
|
40
|
+
};
|
|
41
|
+
txData: {
|
|
42
|
+
approvalAddress: Hex;
|
|
43
|
+
tx: {
|
|
44
|
+
to: Hex;
|
|
45
|
+
data: Hex;
|
|
46
|
+
value: Hex;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
17
49
|
}
|
|
18
50
|
type CommonQuoteParameters = {
|
|
19
51
|
userAddress: Bytes;
|
|
@@ -1,35 +1,39 @@
|
|
|
1
|
+
import { Hex } from "viem";
|
|
1
2
|
import { Aggregator, Quote, QuoteRequestExactInput, QuoteRequestExactOutput } from "./iface";
|
|
2
3
|
export type LiFiResponse = {
|
|
3
4
|
type: string;
|
|
4
5
|
id: string;
|
|
5
6
|
estimate: {
|
|
6
7
|
tool: string;
|
|
7
|
-
approvalAddress:
|
|
8
|
+
approvalAddress: Hex;
|
|
8
9
|
toAmountMin: string;
|
|
9
10
|
toAmount: string;
|
|
10
11
|
fromAmount: string;
|
|
11
12
|
executionDuration: number;
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
};
|
|
14
|
+
action: {
|
|
15
|
+
fromToken: {
|
|
16
|
+
symbol: string;
|
|
17
|
+
decimals: number;
|
|
18
|
+
priceUSD: string;
|
|
19
|
+
};
|
|
20
|
+
toToken: {
|
|
21
|
+
symbol: string;
|
|
22
|
+
decimals: number;
|
|
23
|
+
priceUSD: string;
|
|
24
|
+
};
|
|
14
25
|
};
|
|
15
26
|
integrator: string;
|
|
16
27
|
transactionRequest: {
|
|
17
|
-
value:
|
|
18
|
-
to:
|
|
19
|
-
data:
|
|
20
|
-
chainId: number;
|
|
21
|
-
gasPrice: string;
|
|
22
|
-
gasLimit: string;
|
|
23
|
-
from: string;
|
|
28
|
+
value: Hex;
|
|
29
|
+
to: Hex;
|
|
30
|
+
data: Hex;
|
|
24
31
|
};
|
|
25
32
|
};
|
|
26
|
-
export type LiFiQuote = Quote & {
|
|
27
|
-
originalResponse: LiFiResponse;
|
|
28
|
-
};
|
|
29
33
|
export declare class LiFiAggregator implements Aggregator {
|
|
30
34
|
private static readonly BASE_URL_V1;
|
|
31
35
|
private static readonly COMMON_OPTIONS;
|
|
32
36
|
private readonly axios;
|
|
33
37
|
constructor(apiKey: string);
|
|
34
|
-
getQuotes(requests: (QuoteRequestExactInput | QuoteRequestExactOutput)[]): Promise<(
|
|
38
|
+
getQuotes(requests: (QuoteRequestExactInput | QuoteRequestExactOutput)[]): Promise<(Quote | null)[]>;
|
|
35
39
|
}
|
package/package.json
CHANGED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.YieldYakAggregator = void 0;
|
|
4
|
-
const viem_1 = require("viem");
|
|
5
|
-
const es_toolkit_1 = require("es-toolkit");
|
|
6
|
-
const iface_1 = require("./iface");
|
|
7
|
-
const data_1 = require("../data");
|
|
8
|
-
const definition_1 = require("../proto/definition");
|
|
9
|
-
const yakaggregator_abi_1 = require("../evmabi/yakaggregator.abi");
|
|
10
|
-
const YakAggregatorAddresses = new Map([
|
|
11
|
-
[(0, data_1.encodeChainID36)(definition_1.Universe.ETHEREUM, 42161), '0xb32C79a25291265eF240Eb32E9faBbc6DcEE3cE3'],
|
|
12
|
-
[(0, data_1.encodeChainID36)(definition_1.Universe.ETHEREUM, 10), '0xCd887F78c77b36B0b541E77AfD6F91C0253182A2'],
|
|
13
|
-
[(0, data_1.encodeChainID36)(definition_1.Universe.ETHEREUM, 43114), '0xC4729E56b831d74bBc18797e0e17A295fA77488c'],
|
|
14
|
-
].map(([chainID, addr]) => {
|
|
15
|
-
return [(0, viem_1.bytesToHex)(chainID), addr];
|
|
16
|
-
}));
|
|
17
|
-
class YieldYakAggregator {
|
|
18
|
-
clients = new Map();
|
|
19
|
-
constructor(clients) {
|
|
20
|
-
for (const client of clients) {
|
|
21
|
-
const chainIDHex = (0, viem_1.bytesToHex)(client.chainID.toBytes());
|
|
22
|
-
const aggAddr = YakAggregatorAddresses.get(chainIDHex);
|
|
23
|
-
if (aggAddr == null) {
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
this.clients.set(chainIDHex, {
|
|
27
|
-
chainID: client.chainID,
|
|
28
|
-
client: client.client,
|
|
29
|
-
aggregatorAddress: aggAddr
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
async getQuotes(_requests) {
|
|
34
|
-
const requestsWithOriginalIndexes = _requests.map((r, rid) => {
|
|
35
|
-
return {
|
|
36
|
-
req: r,
|
|
37
|
-
idx: rid,
|
|
38
|
-
};
|
|
39
|
-
});
|
|
40
|
-
const responses = new Array(_requests.length).fill(null);
|
|
41
|
-
// it's so sad that JS doesn't have a proper binary data type
|
|
42
|
-
const groupedByChainID = (0, es_toolkit_1.groupBy)(requestsWithOriginalIndexes, r => (0, viem_1.bytesToHex)(r.req.chain.toBytes()));
|
|
43
|
-
await Promise.all(Array.from(Object.entries(groupedByChainID)).map(async ([chainIDHex, requests]) => {
|
|
44
|
-
const config = this.clients.get(chainIDHex);
|
|
45
|
-
if (config == null) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const reverseIndexes = [];
|
|
49
|
-
const mc3calls = [];
|
|
50
|
-
for (const req of requests) {
|
|
51
|
-
const inputTokenHex = (0, viem_1.bytesToHex)(req.req.inputToken.subarray(12));
|
|
52
|
-
const outputTokenHex = (0, viem_1.bytesToHex)(req.req.outputToken.subarray(12));
|
|
53
|
-
let args;
|
|
54
|
-
switch (req.req.type) {
|
|
55
|
-
case iface_1.QuoteType.EXACT_IN: {
|
|
56
|
-
args = [req.req.inputAmount, inputTokenHex, outputTokenHex, 0, 1];
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
case iface_1.QuoteType.EXACT_OUT: {
|
|
60
|
-
args = [req.req.outputAmount, outputTokenHex, inputTokenHex, 0, 1];
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
const indexes = [];
|
|
65
|
-
for (let steps = 1; steps !== 5; steps++) {
|
|
66
|
-
const clonedArgs = (0, es_toolkit_1.clone)(args);
|
|
67
|
-
clonedArgs[3] = steps;
|
|
68
|
-
const idx = mc3calls.push({
|
|
69
|
-
address: config.aggregatorAddress,
|
|
70
|
-
abi: yakaggregator_abi_1.YakAggregatorABI,
|
|
71
|
-
functionName: 'findBestPathWithGas',
|
|
72
|
-
args: clonedArgs
|
|
73
|
-
});
|
|
74
|
-
indexes.push(idx - 1);
|
|
75
|
-
}
|
|
76
|
-
reverseIndexes.push([req, indexes]);
|
|
77
|
-
}
|
|
78
|
-
const _final = await config.client.multicall({
|
|
79
|
-
allowFailure: false,
|
|
80
|
-
contracts: mc3calls,
|
|
81
|
-
multicallAddress: '0xcA11bde05977b3631167028862bE2a173976CA11'
|
|
82
|
-
});
|
|
83
|
-
for (const [req, indexes] of reverseIndexes) {
|
|
84
|
-
const collected = [];
|
|
85
|
-
for (const index of indexes) {
|
|
86
|
-
collected.push(_final[index]);
|
|
87
|
-
}
|
|
88
|
-
// @ts-expect-error the typing in maxBy is wrong, it can work with anything that is comparable
|
|
89
|
-
const optimalChoice = (0, es_toolkit_1.maxBy)(collected, route => (0, es_toolkit_1.last)(route.amounts));
|
|
90
|
-
if (optimalChoice.path.length === 0) {
|
|
91
|
-
responses[req.idx] = null;
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
// we have to reverse everything
|
|
95
|
-
if (req.req.type === iface_1.QuoteType.EXACT_OUT) {
|
|
96
|
-
optimalChoice.adapters.reverse();
|
|
97
|
-
optimalChoice.amounts.reverse();
|
|
98
|
-
optimalChoice.path.reverse();
|
|
99
|
-
}
|
|
100
|
-
const output = (0, es_toolkit_1.last)(optimalChoice.amounts);
|
|
101
|
-
responses[req.idx] = {
|
|
102
|
-
type: req.req.type,
|
|
103
|
-
inputAmount: optimalChoice.amounts[0],
|
|
104
|
-
outputAmountLikely: output,
|
|
105
|
-
outputAmountMinimum: output,
|
|
106
|
-
offer: optimalChoice
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
}));
|
|
110
|
-
return responses;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
exports.YieldYakAggregator = YieldYakAggregator;
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { bytesToHex } from "viem";
|
|
2
|
-
import { clone as _clone, groupBy, last as _last, maxBy } from "es-toolkit";
|
|
3
|
-
import { QuoteType } from "./iface";
|
|
4
|
-
import { encodeChainID36 } from "../data";
|
|
5
|
-
import { Universe } from "../proto/definition";
|
|
6
|
-
import { YakAggregatorABI } from "../evmabi/yakaggregator.abi";
|
|
7
|
-
const YakAggregatorAddresses = new Map([
|
|
8
|
-
[encodeChainID36(Universe.ETHEREUM, 42161), '0xb32C79a25291265eF240Eb32E9faBbc6DcEE3cE3'],
|
|
9
|
-
[encodeChainID36(Universe.ETHEREUM, 10), '0xCd887F78c77b36B0b541E77AfD6F91C0253182A2'],
|
|
10
|
-
[encodeChainID36(Universe.ETHEREUM, 43114), '0xC4729E56b831d74bBc18797e0e17A295fA77488c'],
|
|
11
|
-
].map(([chainID, addr]) => {
|
|
12
|
-
return [bytesToHex(chainID), addr];
|
|
13
|
-
}));
|
|
14
|
-
export class YieldYakAggregator {
|
|
15
|
-
clients = new Map();
|
|
16
|
-
constructor(clients) {
|
|
17
|
-
for (const client of clients) {
|
|
18
|
-
const chainIDHex = bytesToHex(client.chainID.toBytes());
|
|
19
|
-
const aggAddr = YakAggregatorAddresses.get(chainIDHex);
|
|
20
|
-
if (aggAddr == null) {
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
this.clients.set(chainIDHex, {
|
|
24
|
-
chainID: client.chainID,
|
|
25
|
-
client: client.client,
|
|
26
|
-
aggregatorAddress: aggAddr
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
async getQuotes(_requests) {
|
|
31
|
-
const requestsWithOriginalIndexes = _requests.map((r, rid) => {
|
|
32
|
-
return {
|
|
33
|
-
req: r,
|
|
34
|
-
idx: rid,
|
|
35
|
-
};
|
|
36
|
-
});
|
|
37
|
-
const responses = new Array(_requests.length).fill(null);
|
|
38
|
-
// it's so sad that JS doesn't have a proper binary data type
|
|
39
|
-
const groupedByChainID = groupBy(requestsWithOriginalIndexes, r => bytesToHex(r.req.chain.toBytes()));
|
|
40
|
-
await Promise.all(Array.from(Object.entries(groupedByChainID)).map(async ([chainIDHex, requests]) => {
|
|
41
|
-
const config = this.clients.get(chainIDHex);
|
|
42
|
-
if (config == null) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const reverseIndexes = [];
|
|
46
|
-
const mc3calls = [];
|
|
47
|
-
for (const req of requests) {
|
|
48
|
-
const inputTokenHex = bytesToHex(req.req.inputToken.subarray(12));
|
|
49
|
-
const outputTokenHex = bytesToHex(req.req.outputToken.subarray(12));
|
|
50
|
-
let args;
|
|
51
|
-
switch (req.req.type) {
|
|
52
|
-
case QuoteType.EXACT_IN: {
|
|
53
|
-
args = [req.req.inputAmount, inputTokenHex, outputTokenHex, 0, 1];
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
case QuoteType.EXACT_OUT: {
|
|
57
|
-
args = [req.req.outputAmount, outputTokenHex, inputTokenHex, 0, 1];
|
|
58
|
-
break;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
const indexes = [];
|
|
62
|
-
for (let steps = 1; steps !== 5; steps++) {
|
|
63
|
-
const clonedArgs = _clone(args);
|
|
64
|
-
clonedArgs[3] = steps;
|
|
65
|
-
const idx = mc3calls.push({
|
|
66
|
-
address: config.aggregatorAddress,
|
|
67
|
-
abi: YakAggregatorABI,
|
|
68
|
-
functionName: 'findBestPathWithGas',
|
|
69
|
-
args: clonedArgs
|
|
70
|
-
});
|
|
71
|
-
indexes.push(idx - 1);
|
|
72
|
-
}
|
|
73
|
-
reverseIndexes.push([req, indexes]);
|
|
74
|
-
}
|
|
75
|
-
const _final = await config.client.multicall({
|
|
76
|
-
allowFailure: false,
|
|
77
|
-
contracts: mc3calls,
|
|
78
|
-
multicallAddress: '0xcA11bde05977b3631167028862bE2a173976CA11'
|
|
79
|
-
});
|
|
80
|
-
for (const [req, indexes] of reverseIndexes) {
|
|
81
|
-
const collected = [];
|
|
82
|
-
for (const index of indexes) {
|
|
83
|
-
collected.push(_final[index]);
|
|
84
|
-
}
|
|
85
|
-
// @ts-expect-error the typing in maxBy is wrong, it can work with anything that is comparable
|
|
86
|
-
const optimalChoice = maxBy(collected, route => _last(route.amounts));
|
|
87
|
-
if (optimalChoice.path.length === 0) {
|
|
88
|
-
responses[req.idx] = null;
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
// we have to reverse everything
|
|
92
|
-
if (req.req.type === QuoteType.EXACT_OUT) {
|
|
93
|
-
optimalChoice.adapters.reverse();
|
|
94
|
-
optimalChoice.amounts.reverse();
|
|
95
|
-
optimalChoice.path.reverse();
|
|
96
|
-
}
|
|
97
|
-
const output = _last(optimalChoice.amounts);
|
|
98
|
-
responses[req.idx] = {
|
|
99
|
-
type: req.req.type,
|
|
100
|
-
inputAmount: optimalChoice.amounts[0],
|
|
101
|
-
outputAmountLikely: output,
|
|
102
|
-
outputAmountMinimum: output,
|
|
103
|
-
offer: optimalChoice
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
}));
|
|
107
|
-
return responses;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Hex, PublicClient } from "viem";
|
|
2
|
-
import { Aggregator, Quote, QuoteRequestExactInput, QuoteRequestExactOutput } from "./iface";
|
|
3
|
-
import { OmniversalChainID } from "../data";
|
|
4
|
-
type YakOffer = {
|
|
5
|
-
amounts: bigint[];
|
|
6
|
-
adapters: Hex[];
|
|
7
|
-
path: Hex[];
|
|
8
|
-
gasEstimate: bigint;
|
|
9
|
-
};
|
|
10
|
-
export type YakAggregatorQuote = Quote & {
|
|
11
|
-
offer: YakOffer;
|
|
12
|
-
};
|
|
13
|
-
export declare class YieldYakAggregator implements Aggregator {
|
|
14
|
-
private readonly clients;
|
|
15
|
-
constructor(clients: {
|
|
16
|
-
chainID: OmniversalChainID;
|
|
17
|
-
client: PublicClient;
|
|
18
|
-
}[]);
|
|
19
|
-
getQuotes(_requests: (QuoteRequestExactInput | QuoteRequestExactOutput)[]): Promise<(YakAggregatorQuote | null)[]>;
|
|
20
|
-
}
|
|
21
|
-
export {};
|