@avail-project/ca-common 2.3.0 → 3.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.
Files changed (95) hide show
  1. package/dist/cjs/index.js +10593 -20
  2. package/dist/esm/index.mjs +10603 -0
  3. package/dist/types/index.d.ts +2608 -13
  4. package/package.json +41 -37
  5. package/dist/cjs/_polyfill.js +0 -147
  6. package/dist/cjs/balances/ub-api.js +0 -25
  7. package/dist/cjs/cosmos/index.js +0 -31
  8. package/dist/cjs/data/chaindata.js +0 -788
  9. package/dist/cjs/data/chainid.js +0 -93
  10. package/dist/cjs/data/currency.js +0 -78
  11. package/dist/cjs/data/index.js +0 -7
  12. package/dist/cjs/data/utils.js +0 -44
  13. package/dist/cjs/evmabi/erc20.abi.js +0 -349
  14. package/dist/cjs/evmabi/fibrousrouter.abi.js +0 -41
  15. package/dist/cjs/evmabi/index.js +0 -7
  16. package/dist/cjs/evmabi/vault.abi.js +0 -1021
  17. package/dist/cjs/evmabi/yakaggregator.abi.js +0 -275
  18. package/dist/cjs/permitutils/index.js +0 -186
  19. package/dist/cjs/proto/client.js +0 -48
  20. package/dist/cjs/proto/definition.js +0 -4131
  21. package/dist/cjs/proto/grpc.js +0 -298
  22. package/dist/cjs/rff/rff.js +0 -42
  23. package/dist/cjs/types/binarytypes.js +0 -2
  24. package/dist/cjs/types/index.js +0 -5
  25. package/dist/cjs/types/msgpack-axios.js +0 -22
  26. package/dist/cjs/vaultcontracts/index.js +0 -4
  27. package/dist/cjs/vaultcontracts/vaultcontracts.js +0 -222
  28. package/dist/cjs/xcs/autochoice.js +0 -575
  29. package/dist/cjs/xcs/bebop-agg.js +0 -156
  30. package/dist/cjs/xcs/fibrous-agg.js +0 -155
  31. package/dist/cjs/xcs/iface.js +0 -13
  32. package/dist/cjs/xcs/index.js +0 -9
  33. package/dist/cjs/xcs/lifi-agg.js +0 -177
  34. package/dist/cjs/xcs/selectsources.js +0 -255
  35. package/dist/esm/_polyfill.js +0 -143
  36. package/dist/esm/balances/ub-api.js +0 -21
  37. package/dist/esm/cosmos/index.js +0 -26
  38. package/dist/esm/data/chaindata.js +0 -785
  39. package/dist/esm/data/chainid.js +0 -87
  40. package/dist/esm/data/currency.js +0 -73
  41. package/dist/esm/data/index.js +0 -4
  42. package/dist/esm/data/utils.js +0 -34
  43. package/dist/esm/evmabi/erc20.abi.js +0 -346
  44. package/dist/esm/evmabi/fibrousrouter.abi.js +0 -38
  45. package/dist/esm/evmabi/index.js +0 -4
  46. package/dist/esm/evmabi/vault.abi.js +0 -1018
  47. package/dist/esm/evmabi/yakaggregator.abi.js +0 -272
  48. package/dist/esm/index.js +0 -13
  49. package/dist/esm/permitutils/index.js +0 -181
  50. package/dist/esm/proto/client.js +0 -11
  51. package/dist/esm/proto/definition.js +0 -4122
  52. package/dist/esm/proto/grpc.js +0 -292
  53. package/dist/esm/rff/rff.js +0 -38
  54. package/dist/esm/types/binarytypes.js +0 -1
  55. package/dist/esm/types/index.js +0 -2
  56. package/dist/esm/types/msgpack-axios.js +0 -18
  57. package/dist/esm/vaultcontracts/index.js +0 -1
  58. package/dist/esm/vaultcontracts/vaultcontracts.js +0 -218
  59. package/dist/esm/xcs/autochoice.js +0 -559
  60. package/dist/esm/xcs/bebop-agg.js +0 -151
  61. package/dist/esm/xcs/fibrous-agg.js +0 -150
  62. package/dist/esm/xcs/iface.js +0 -10
  63. package/dist/esm/xcs/index.js +0 -6
  64. package/dist/esm/xcs/lifi-agg.js +0 -172
  65. package/dist/esm/xcs/selectsources.js +0 -251
  66. package/dist/types/_polyfill.d.ts +0 -1
  67. package/dist/types/balances/ub-api.d.ts +0 -14
  68. package/dist/types/cosmos/index.d.ts +0 -6
  69. package/dist/types/data/chaindata.d.ts +0 -20
  70. package/dist/types/data/chainid.d.ts +0 -31
  71. package/dist/types/data/currency.d.ts +0 -30
  72. package/dist/types/data/index.d.ts +0 -4
  73. package/dist/types/data/utils.d.ts +0 -10
  74. package/dist/types/evmabi/erc20.abi.d.ts +0 -264
  75. package/dist/types/evmabi/fibrousrouter.abi.d.ts +0 -77
  76. package/dist/types/evmabi/index.d.ts +0 -4
  77. package/dist/types/evmabi/vault.abi.d.ts +0 -785
  78. package/dist/types/evmabi/yakaggregator.abi.d.ts +0 -298
  79. package/dist/types/permitutils/index.d.ts +0 -13
  80. package/dist/types/proto/client.d.ts +0 -2
  81. package/dist/types/proto/definition.d.ts +0 -382
  82. package/dist/types/proto/grpc.d.ts +0 -75
  83. package/dist/types/rff/rff.d.ts +0 -9
  84. package/dist/types/types/binarytypes.d.ts +0 -1
  85. package/dist/types/types/index.d.ts +0 -2
  86. package/dist/types/types/msgpack-axios.d.ts +0 -1
  87. package/dist/types/vaultcontracts/index.d.ts +0 -22
  88. package/dist/types/vaultcontracts/vaultcontracts.d.ts +0 -8
  89. package/dist/types/xcs/autochoice.d.ts +0 -104
  90. package/dist/types/xcs/bebop-agg.d.ts +0 -104
  91. package/dist/types/xcs/fibrous-agg.d.ts +0 -56
  92. package/dist/types/xcs/iface.d.ts +0 -69
  93. package/dist/types/xcs/index.d.ts +0 -6
  94. package/dist/types/xcs/lifi-agg.d.ts +0 -42
  95. package/dist/types/xcs/selectsources.d.ts +0 -27
@@ -1,575 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AggregateAggregatorsMode = exports.AutoSelectionError = void 0;
4
- exports.aggregateAggregators = aggregateAggregators;
5
- exports.autoSelectSourcesV2 = autoSelectSourcesV2;
6
- exports.autoSelectSourcesV2ByRecipient = autoSelectSourcesV2ByRecipient;
7
- exports.determineDestinationSwaps = determineDestinationSwaps;
8
- exports.liquidateInputHoldings = liquidateInputHoldings;
9
- exports.liquidateInputHoldingsByRecipient = liquidateInputHoldingsByRecipient;
10
- exports.destinationSwapWithExactIn = destinationSwapWithExactIn;
11
- exports.getDestinationExactOutSwap = getDestinationExactOutSwap;
12
- exports.getDestinationExactInSwap = getDestinationExactInSwap;
13
- exports.liquidateSourceHoldings = liquidateSourceHoldings;
14
- exports.autoSelectSources = autoSelectSources;
15
- const tslib_1 = require("tslib");
16
- const es_toolkit_1 = require("es-toolkit");
17
- const viem_1 = require("viem");
18
- const decimal_js_1 = tslib_1.__importDefault(require("decimal.js"));
19
- const iface_1 = require("./iface");
20
- const data_1 = require("../data");
21
- class AutoSelectionError extends Error {
22
- }
23
- exports.AutoSelectionError = AutoSelectionError;
24
- const safetyMultiplier = new decimal_js_1.default("1.025");
25
- var AggregateAggregatorsMode;
26
- (function (AggregateAggregatorsMode) {
27
- AggregateAggregatorsMode[AggregateAggregatorsMode["MaximizeOutput"] = 0] = "MaximizeOutput";
28
- AggregateAggregatorsMode[AggregateAggregatorsMode["MinimizeInput"] = 1] = "MinimizeInput";
29
- })(AggregateAggregatorsMode || (exports.AggregateAggregatorsMode = AggregateAggregatorsMode = {}));
30
- async function aggregateAggregators(requests, aggregators, mode) {
31
- const responses = await Promise.all(aggregators.map(async (agg) => {
32
- let quotes;
33
- try {
34
- quotes = await agg.getQuotes(requests);
35
- }
36
- catch (e) {
37
- console.log("XCS | Failed to get quote from", agg, "in aggregateAggregators.", requests, "with:", e);
38
- quotes = new Array(requests.length).fill(null);
39
- }
40
- return {
41
- quotes,
42
- agg,
43
- };
44
- }));
45
- const final = new Array(requests.length);
46
- switch (mode) {
47
- case AggregateAggregatorsMode.MaximizeOutput: {
48
- for (let i = 0; i < requests.length; i++) {
49
- const best = (0, data_1.maxByBigInt)(responses.map((ra) => ({ quote: ra.quotes[i], aggregator: ra.agg })), (r) => r.quote?.output.amountRaw ?? 0n);
50
- if (best != null) {
51
- final[i] = best;
52
- }
53
- else {
54
- final[i] = {
55
- quote: null,
56
- aggregator: aggregators[0],
57
- };
58
- }
59
- }
60
- break;
61
- }
62
- case AggregateAggregatorsMode.MinimizeInput: {
63
- for (let i = 0; i < requests.length; i++) {
64
- const best = (0, data_1.minByBigInt)(responses.map((ra) => ({ quote: ra.quotes[i], aggregator: ra.agg })),
65
- // Default null quotes to MAX so they never win as the minimum
66
- (r) => r.quote?.input.amountRaw ?? BigInt(Number.MAX_SAFE_INTEGER));
67
- if (best != null) {
68
- final[i] = best;
69
- }
70
- else {
71
- final[i] = {
72
- quote: null,
73
- aggregator: aggregators[0],
74
- };
75
- }
76
- }
77
- break;
78
- }
79
- }
80
- return final;
81
- }
82
- /*
83
- In original autoSelectSources:
84
- Assets = [1 ETH, 1 COT, 1 ETH, 1 USDT, 1 COT]
85
- Output = 4
86
-
87
- First loop that just removes cot:
88
- quoteAssets = [1 ETH, 1 ETH, 1 USDT]
89
- Output = 4
90
-
91
- Outside the function we can just remove all COT's and assume those as being used
92
- but that's incorrect as we want to use assets in exact order as holdings array.
93
- We can't remove only COT's that are going to be used because we don't know which ones are going
94
- to get used.
95
-
96
- Proposed solution:
97
- It should actually use assets in exact order, so it cant be done outside the function
98
- 1. The function has to keep an order of assets, separate out COT and non-COT assets.
99
- 2. Get quote for non-COT assets, then loop over the original order
100
- 3. Used either COT or quote depending on original order
101
- 4. Send back quotes and COT's used
102
-
103
- Alg:
104
- Assets = [1 ETH, 1 COT, 1 ETH, 1 USDT, 1 COT]
105
- Output = 4
106
-
107
- 1. separate into two with indexes:
108
- quotes = [(1 ETH, 0), (1 ETH, 2), (1 USDT, 3)]
109
- cots = [(1 COT, 1), (1 COT, 4)]
110
-
111
- 2. Get quotes using only quotes
112
- 3. merge quote cots and sort by order
113
- 4. loop assets (original order):
114
- if a quote:
115
- output = output - quote_output_amount
116
- if a cot:
117
- output = output - cot_amount
118
- if output <= 0:
119
- break
120
- 5. return quotes and assets used.
121
- */
122
- /**
123
- * @deprecated Use {@link autoSelectSources} (object args; per-holding `takerAddress` and
124
- * `receiverAddress` on each `HoldingWithSwapAddresses`).
125
- */
126
- async function autoSelectSourcesV2(userAddress, holdings, outputRequired, aggregators, commonCurrencyID = data_1.CurrencyID.USDC) {
127
- return autoSelectSourcesV2ByRecipient(holdings.map((holding) => ({ ...holding, recipient: userAddress })), outputRequired, aggregators, commonCurrencyID);
128
- }
129
- /**
130
- * @deprecated Use {@link autoSelectSources} (object args; per-holding `takerAddress` and
131
- * `receiverAddress` on each `HoldingWithSwapAddresses`).
132
- */
133
- async function autoSelectSourcesV2ByRecipient(holdings, outputRequired, aggregators, commonCurrencyID = data_1.CurrencyID.USDC) {
134
- // Assumption: Holding is already sorted in usage priority
135
- console.debug("XCS | SSV2:", {
136
- holdings,
137
- outputRequired: outputRequired.toFixed(),
138
- });
139
- const fullLiquidationQuotes = [];
140
- const cotList = [];
141
- for (const [idx, holding] of holdings.entries()) {
142
- const chain = data_1.ChaindataMap.get(holding.chainID);
143
- if (chain == null) {
144
- throw new AutoSelectionError("Chain not found");
145
- }
146
- const correspondingCurrency = chain.Currencies.find((cur) => cur.currencyID === commonCurrencyID);
147
- if (correspondingCurrency == null) {
148
- console.debug("XCS | SS | Skipping because correspondingCurrency is null", {
149
- chain,
150
- correspondingCurrency,
151
- });
152
- continue;
153
- }
154
- if (Buffer.compare(holding.tokenAddress, correspondingCurrency.tokenAddress) === 0) {
155
- const normalizedAmount = new decimal_js_1.default(holding.amountRaw).div(decimal_js_1.default.pow(10, correspondingCurrency.decimals));
156
- cotList.push({
157
- amount: normalizedAmount,
158
- idx,
159
- chainID: holding.chainID,
160
- currency: correspondingCurrency,
161
- originalHolding: holding,
162
- });
163
- }
164
- else {
165
- fullLiquidationQuotes.push({
166
- req: {
167
- userAddress: holding.recipient,
168
- // New wrappers thread per-holding receiver via this field. Falls back to taker
169
- // (`recipient`) when absent — preserves legacy positional-call behavior.
170
- receiverAddress: holding.receiverAddress,
171
- type: iface_1.QuoteType.EXACT_IN,
172
- chain: chain.ChainID,
173
- inputToken: holding.tokenAddress,
174
- inputAmount: holding.amountRaw,
175
- outputToken: correspondingCurrency.tokenAddress,
176
- seriousness: iface_1.QuoteSeriousness.PRICE_SURVEY,
177
- },
178
- originalHolding: holding,
179
- cur: correspondingCurrency,
180
- idx,
181
- });
182
- }
183
- }
184
- // Check if continuous COTs from the start can cover the entire requirement
185
- // We can skip quoting unused holdings
186
- if (cotList.length > 0 && cotList[0].idx === 0) {
187
- let continuousCOTAmount = new decimal_js_1.default(0);
188
- let continuousCount = 0;
189
- for (const cot of cotList) {
190
- // only consecutive cots allowed, otherwise we need to go to quoting
191
- if (cot.idx !== continuousCount)
192
- break;
193
- continuousCOTAmount = continuousCOTAmount.add(cot.amount);
194
- continuousCount++;
195
- if (continuousCOTAmount.gte(outputRequired)) {
196
- console.log("XCS | SS | Continuous COTs can satisfy requirement, skipping quotes");
197
- const usedCOTs = [];
198
- let remainder = outputRequired;
199
- for (let i = 0; i < continuousCount; i++) {
200
- const cot = cotList[i];
201
- const amountToUse = decimal_js_1.default.min(remainder, cot.amount);
202
- usedCOTs.push({
203
- originalHolding: cot.originalHolding,
204
- amountUsed: amountToUse,
205
- idx: cot.idx,
206
- cur: cot.currency,
207
- });
208
- remainder = remainder.minus(amountToUse);
209
- if (remainder.lte(0))
210
- break;
211
- }
212
- console.debug("XCS | SS | Early return with continuous COTs:", {
213
- cots: usedCOTs,
214
- });
215
- return { quoteResponses: [], usedCOTs };
216
- }
217
- }
218
- }
219
- const processingQueue = [];
220
- // Add COT holdings
221
- for (const cot of cotList) {
222
- processingQueue.push({
223
- idx: cot.idx,
224
- isCOT: true,
225
- cotData: cot,
226
- });
227
- }
228
- // Add non-COT holdings
229
- for (let i = 0; i < fullLiquidationQuotes.length; i++) {
230
- processingQueue.push({
231
- idx: fullLiquidationQuotes[i].idx,
232
- isCOT: false,
233
- quoteData: fullLiquidationQuotes[i],
234
- responseIdx: i,
235
- });
236
- }
237
- // Sort by original index to maintain priority
238
- processingQueue.sort((a, b) => a.idx - b.idx);
239
- const responses = await aggregateAggregators(fullLiquidationQuotes.map((fq) => fq.req), aggregators, AggregateAggregatorsMode.MaximizeOutput);
240
- console.debug("AutoSelectSources:Quotes", responses);
241
- const final = [];
242
- const usedCOTs = [];
243
- let remainder = outputRequired;
244
- for (const item of processingQueue) {
245
- if (remainder.lte(0)) {
246
- break;
247
- }
248
- if (item.isCOT) {
249
- // Process COT holding - direct usage, no quote
250
- const { cotData } = item;
251
- const amountToUse = decimal_js_1.default.min(remainder, cotData.amount);
252
- usedCOTs.push({
253
- originalHolding: cotData.originalHolding,
254
- amountUsed: amountToUse,
255
- idx: cotData.idx,
256
- cur: cotData.currency,
257
- });
258
- remainder = remainder.minus(amountToUse);
259
- console.debug("selection:cot", {
260
- idx: cotData.idx,
261
- amountToUse: amountToUse.toFixed(),
262
- remainder: remainder.toFixed(),
263
- });
264
- }
265
- else {
266
- // Process non-COT holding - use existing quote logic
267
- const { quoteData, responseIdx } = item;
268
- const { quote: resp, aggregator } = responses[responseIdx];
269
- if (resp == null) {
270
- continue;
271
- }
272
- console.debug("selection:quote", {
273
- remainder: remainder.toFixed(),
274
- input: resp.input,
275
- output: resp.output,
276
- });
277
- const divisor = decimal_js_1.default.pow(10, quoteData.cur.decimals);
278
- const oamD = new decimal_js_1.default(resp.output.amount);
279
- if (oamD.gt(remainder)) {
280
- const indicativePrice = decimal_js_1.default.div(resp.input.amountRaw, resp.output.amountRaw);
281
- const userBal = new decimal_js_1.default(quoteData.originalHolding.amountRaw);
282
- // remainder is the output we want, so the input amount is remainder × indicativePrice
283
- let expectedInput = decimal_js_1.default.min(remainder.mul(divisor).mul(indicativePrice).mul(safetyMultiplier), userBal);
284
- let attempts = 0;
285
- while (true) {
286
- if (++attempts > 10) {
287
- throw new AutoSelectionError("Partial quote did not converge");
288
- }
289
- console.debug("partial_quote_loop", {
290
- indicativePrice: indicativePrice.toFixed(),
291
- expectedInput: expectedInput.toFixed(),
292
- userBal: userBal.toFixed(),
293
- remainder: remainder.toFixed(),
294
- });
295
- const adequateQuoteResult = await aggregateAggregators([
296
- {
297
- ...quoteData.req,
298
- seriousness: iface_1.QuoteSeriousness.SERIOUS,
299
- inputAmount: (0, data_1.convertDecimalToBigInt)(expectedInput),
300
- },
301
- ], aggregators, AggregateAggregatorsMode.MaximizeOutput);
302
- if (adequateQuoteResult.length !== 1) {
303
- throw new AutoSelectionError("Unexpected response length from aggregateAggregators");
304
- }
305
- const adequateQuote = adequateQuoteResult[0];
306
- if (adequateQuote.quote == null) {
307
- throw new AutoSelectionError("Couldn't get buy quote");
308
- }
309
- const quote = adequateQuote.quote;
310
- console.log("partial_quote", {
311
- quote,
312
- });
313
- const oam2D = new decimal_js_1.default(adequateQuote.quote.output.amount);
314
- if (oam2D.gte(remainder)) {
315
- final.push({
316
- quote,
317
- aggregator: adequateQuote.aggregator,
318
- holding: quoteData.originalHolding,
319
- chainID: Number(quoteData.req.chain.chainID),
320
- });
321
- remainder = remainder.minus(oam2D);
322
- break;
323
- }
324
- else if (expectedInput.eq(userBal)) {
325
- throw new AutoSelectionError("Holding was supposedly enough to meet the full requirement but ceased to be so subsequently");
326
- }
327
- else {
328
- expectedInput = decimal_js_1.default.min(expectedInput.mul(safetyMultiplier), userBal); // try again with higher amount
329
- }
330
- }
331
- }
332
- else {
333
- console.debug("full_quote", resp);
334
- final.push({
335
- quote: resp,
336
- holding: quoteData.originalHolding,
337
- aggregator,
338
- chainID: Number(quoteData.req.chain.chainID),
339
- });
340
- remainder = remainder.minus(resp.output.amount);
341
- }
342
- }
343
- }
344
- console.debug("quotes_and_remainder", {
345
- remainder: remainder.toFixed(),
346
- final,
347
- });
348
- if (remainder.gt(0)) {
349
- throw new AutoSelectionError("NOT_ENOUGH_SWAP_FOR_REQUIREMENT");
350
- }
351
- console.log("final_quotes", { quotes: final, cots: usedCOTs });
352
- return { quoteResponses: final, usedCOTs };
353
- }
354
- /**
355
- * @deprecated Use {@link getDestinationExactOutSwap} (object args; explicit `takerAddress` and
356
- * `receiverAddress`, both required).
357
- */
358
- async function determineDestinationSwaps(userAddress, requirement, aggregators, commonCurrencyID = data_1.CurrencyID.USDC, receiverAddress) {
359
- const chaindata = data_1.ChaindataMap.get(requirement.chainID);
360
- if (chaindata == null) {
361
- throw new AutoSelectionError("Chain not found");
362
- }
363
- const COT = chaindata.Currencies.find((cur) => cur.currencyID === commonCurrencyID);
364
- if (COT == null) {
365
- throw new AutoSelectionError("COT not present on the destination chain");
366
- }
367
- // FIXME: Replace with oracle usage - should reduce time.
368
- // what happens if we happen to sell the requirement for the COT, what would the amount be?
369
- const fullLiquidationQR = {
370
- type: iface_1.QuoteType.EXACT_IN,
371
- chain: requirement.chainID,
372
- userAddress,
373
- receiverAddress,
374
- inputToken: requirement.tokenAddress,
375
- outputToken: COT.tokenAddress,
376
- inputAmount: requirement.amountRaw,
377
- seriousness: iface_1.QuoteSeriousness.PRICE_SURVEY,
378
- };
379
- const fullLiquidationResult = await aggregateAggregators([fullLiquidationQR], aggregators, AggregateAggregatorsMode.MaximizeOutput);
380
- if (fullLiquidationResult.length !== 1) {
381
- throw new AutoSelectionError("Unexpected response length from aggregateAggregators");
382
- }
383
- const fullLiquidationQuote = fullLiquidationResult[0];
384
- if (fullLiquidationQuote.quote == null) {
385
- throw new AutoSelectionError("Couldn't get full liquidation quote");
386
- }
387
- let curAmount = (0, data_1.convertBigIntToDecimal)(fullLiquidationQuote.quote.output.amountRaw).mul(safetyMultiplier);
388
- let attempts = 0;
389
- while (true) {
390
- if (++attempts > 10) {
391
- throw new AutoSelectionError("Destination swap quote did not converge");
392
- }
393
- const buyQuoteResult = await aggregateAggregators([
394
- {
395
- type: iface_1.QuoteType.EXACT_IN,
396
- userAddress,
397
- receiverAddress,
398
- chain: requirement.chainID,
399
- inputToken: COT.tokenAddress,
400
- outputToken: requirement.tokenAddress,
401
- inputAmount: (0, data_1.convertDecimalToBigInt)(curAmount),
402
- seriousness: iface_1.QuoteSeriousness.SERIOUS,
403
- },
404
- ], aggregators, AggregateAggregatorsMode.MaximizeOutput);
405
- if (buyQuoteResult.length !== 1) {
406
- throw new AutoSelectionError("Unexpected response length from aggregateAggregators");
407
- }
408
- const buyQuote = buyQuoteResult[0];
409
- if (buyQuote.quote == null) {
410
- throw new AutoSelectionError("Couldn't get buy quote");
411
- }
412
- console.debug("XCS | DDS | 2⒜ iteration", {
413
- buyQuote,
414
- curAmount,
415
- });
416
- if (buyQuote.quote.output.amountRaw >= requirement.amountRaw) {
417
- return {
418
- chainID: Number(requirement.chainID.chainID),
419
- quote: buyQuote.quote,
420
- aggregator: buyQuote.aggregator,
421
- holding: requirement,
422
- };
423
- }
424
- else {
425
- curAmount = curAmount.mul(safetyMultiplier); // try again with higher amount
426
- }
427
- }
428
- }
429
- /**
430
- * @deprecated Use {@link liquidateSourceHoldings} (object args; per-holding `takerAddress`
431
- * and `receiverAddress` on each `HoldingWithSwapAddresses`).
432
- */
433
- async function liquidateInputHoldings(userAddress, holdings, aggregators, commonCurrencyID = data_1.CurrencyID.USDC, receiverAddress) {
434
- return liquidateInputHoldingsByRecipient(holdings.map((holding) => ({ ...holding, recipient: userAddress })), aggregators, commonCurrencyID, receiverAddress);
435
- }
436
- /**
437
- * @deprecated Use {@link liquidateSourceHoldings} (object args; per-holding `takerAddress`
438
- * and `receiverAddress` on each `HoldingWithSwapAddresses`).
439
- */
440
- async function liquidateInputHoldingsByRecipient(holdings, aggregators, commonCurrencyID = data_1.CurrencyID.USDC, receiverAddress) {
441
- console.debug("XCS | LIH | Holdings:", holdings);
442
- const groupedByChainID = (0, es_toolkit_1.groupBy)(holdings, (h) => (0, viem_1.bytesToHex)(h.chainID.toBytes()));
443
- const fullLiquidationQuotes = [];
444
- for (const holdings of Object.values(groupedByChainID)) {
445
- const chain = data_1.ChaindataMap.get(holdings[0].chainID);
446
- if (chain == null) {
447
- throw new AutoSelectionError("Chain not found");
448
- }
449
- const correspondingCurrency = chain.Currencies.find((cur) => cur.currencyID === commonCurrencyID);
450
- if (correspondingCurrency == null) {
451
- console.debug("XCS | LIH | Skipping because correspondingCurrency is null", {
452
- chain,
453
- correspondingCurrency,
454
- });
455
- continue;
456
- }
457
- for (const holding of holdings) {
458
- if (Buffer.compare(holding.tokenAddress, correspondingCurrency.tokenAddress) === 0) {
459
- console.log("XCS | LIH | Disqualifying", holding, "because holding.tokenAddress = CA asset");
460
- continue;
461
- }
462
- fullLiquidationQuotes.push({
463
- req: {
464
- userAddress: holding.recipient,
465
- // Per-holding receiver wins (set by the new wrappers); shared param is the legacy
466
- // positional-call fallback.
467
- receiverAddress: holding.receiverAddress ?? receiverAddress,
468
- type: iface_1.QuoteType.EXACT_IN,
469
- chain: chain.ChainID,
470
- inputToken: holding.tokenAddress,
471
- inputAmount: holding.amountRaw,
472
- outputToken: correspondingCurrency.tokenAddress,
473
- seriousness: iface_1.QuoteSeriousness.SERIOUS,
474
- },
475
- // necessary for various purposes
476
- originalHolding: holding,
477
- cur: correspondingCurrency,
478
- });
479
- }
480
- }
481
- const responses = await aggregateAggregators(fullLiquidationQuotes.map((fq) => fq.req), aggregators, AggregateAggregatorsMode.MaximizeOutput);
482
- console.debug("XCS | LIH | Responses:", responses);
483
- const quotes = [];
484
- for (const [i, response] of responses.entries()) {
485
- if (response.quote !== null) {
486
- quotes.push({
487
- quote: response.quote,
488
- aggregator: response.aggregator,
489
- holding: fullLiquidationQuotes[i].originalHolding,
490
- chainID: Number(fullLiquidationQuotes[i].req.chain.chainID),
491
- });
492
- }
493
- }
494
- return quotes;
495
- }
496
- /**
497
- * @deprecated Use {@link getDestinationExactInSwap} (object args; explicit `takerAddress`
498
- * and `receiverAddress`, both required).
499
- */
500
- async function destinationSwapWithExactIn(userAddress, omniChainID, inputAmount, outputToken, aggregators, inputCurrency = data_1.CurrencyID.USDC, receiverAddress) {
501
- const chaindata = data_1.ChaindataMap.get(omniChainID);
502
- if (chaindata == null) {
503
- throw new AutoSelectionError("Chain not found");
504
- }
505
- const COT = chaindata.Currencies.find((cur) => cur.currencyID === inputCurrency);
506
- if (COT == null) {
507
- throw new AutoSelectionError("COT not present on the destination chain");
508
- }
509
- const fullLiquidationResult = await aggregateAggregators([
510
- {
511
- type: iface_1.QuoteType.EXACT_IN,
512
- chain: omniChainID,
513
- userAddress,
514
- receiverAddress,
515
- inputToken: COT.tokenAddress,
516
- outputToken: outputToken,
517
- inputAmount: inputAmount,
518
- seriousness: iface_1.QuoteSeriousness.SERIOUS,
519
- },
520
- ], aggregators, AggregateAggregatorsMode.MaximizeOutput);
521
- if (fullLiquidationResult.length !== 1) {
522
- throw new AutoSelectionError("Unexpected response length from aggregateAggregators");
523
- }
524
- const fullLiquidationQuote = fullLiquidationResult[0];
525
- if (fullLiquidationQuote.quote == null) {
526
- throw new AutoSelectionError("Couldn't get full liquidation quote");
527
- }
528
- return {
529
- chainID: Number(omniChainID.chainID),
530
- quote: fullLiquidationQuote.quote,
531
- aggregator: fullLiquidationQuote.aggregator,
532
- holding: {
533
- amountRaw: inputAmount,
534
- chainID: omniChainID,
535
- tokenAddress: COT.tokenAddress,
536
- },
537
- };
538
- }
539
- // =====================================================================================
540
- // Object-arg wrappers around the legacy positional functions above.
541
- //
542
- // Aggregator vocabulary:
543
- // takerAddress — on-chain executor of the swap (drives aggregator simulation /
544
- // permit / approval routing). On 7702 chains this is the ephemeral; on
545
- // non-Pectra chains it's the deployed Safe. Maps to the underlying
546
- // QuoteRequest's `userAddress`.
547
- // receiverAddress — recipient of the swap output. Maps to the underlying QuoteRequest's
548
- // `receiverAddress`. Required on all 4 wrappers — the GS013-class bug we
549
- // fixed came from forgetting this and silently defaulting to the wrong
550
- // address. Even on source side (where it equals the taker today), require
551
- // it explicitly so the type system forces every call site to acknowledge
552
- // both roles.
553
- //
554
- // Wrap-only: each wrapper delegates to the deprecated positional fn. No business logic added.
555
- // =====================================================================================
556
- async function getDestinationExactOutSwap(args) {
557
- return determineDestinationSwaps(args.takerAddress, args.requirement, args.aggregators, args.commonCurrencyID, args.receiverAddress);
558
- }
559
- async function getDestinationExactInSwap(args) {
560
- return destinationSwapWithExactIn(args.takerAddress, args.chain, args.inputAmount, args.outputToken, args.aggregators, args.inputCurrency, args.receiverAddress);
561
- }
562
- async function liquidateSourceHoldings(args) {
563
- return liquidateInputHoldingsByRecipient(args.holdings.map((h) => ({
564
- ...h,
565
- recipient: h.takerAddress,
566
- receiverAddress: h.receiverAddress,
567
- })), args.aggregators, args.commonCurrencyID);
568
- }
569
- async function autoSelectSources(args) {
570
- return autoSelectSourcesV2ByRecipient(args.holdings.map((h) => ({
571
- ...h,
572
- recipient: h.takerAddress,
573
- receiverAddress: h.receiverAddress,
574
- })), args.outputRequired, args.aggregators, args.commonCurrencyID);
575
- }