@1delta/trade-sdk 0.1.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 (108) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +63 -0
  3. package/dist/aggregator/fetchAggregatorTrade.d.ts +6 -0
  4. package/dist/aggregator/fetchAggregatorTrade.d.ts.map +1 -0
  5. package/dist/aggregator/fetchAggregatorTrade.js +14 -0
  6. package/dist/aggregator/getAvailableAggregators.d.ts +2 -0
  7. package/dist/aggregator/getAvailableAggregators.d.ts.map +1 -0
  8. package/dist/aggregator/getAvailableAggregators.js +11 -0
  9. package/dist/aggregator/index.d.ts +3 -0
  10. package/dist/aggregator/index.d.ts.map +1 -0
  11. package/dist/aggregator/index.js +2 -0
  12. package/dist/bridge/fetchBridgeTrade.d.ts +5 -0
  13. package/dist/bridge/fetchBridgeTrade.d.ts.map +1 -0
  14. package/dist/bridge/fetchBridgeTrade.js +195 -0
  15. package/dist/bridge/index.d.ts +2 -0
  16. package/dist/bridge/index.d.ts.map +1 -0
  17. package/dist/bridge/index.js +1 -0
  18. package/dist/composedTrades/across/acrossRoutes.d.ts +17 -0
  19. package/dist/composedTrades/across/acrossRoutes.d.ts.map +1 -0
  20. package/dist/composedTrades/across/acrossRoutes.js +64 -0
  21. package/dist/composedTrades/across/acrossWithSwap.d.ts +11 -0
  22. package/dist/composedTrades/across/acrossWithSwap.d.ts.map +1 -0
  23. package/dist/composedTrades/across/acrossWithSwap.integration.spec.d.ts +1 -0
  24. package/dist/composedTrades/across/acrossWithSwap.integration.spec.d.ts.map +1 -0
  25. package/dist/composedTrades/across/acrossWithSwap.integration.spec.js +116 -0
  26. package/dist/composedTrades/across/acrossWithSwap.js +122 -0
  27. package/dist/composedTrades/across/acrossWithSwaps.d.ts +5 -0
  28. package/dist/composedTrades/across/acrossWithSwaps.d.ts.map +1 -0
  29. package/dist/composedTrades/across/acrossWithSwaps.integration.spec.d.ts +1 -0
  30. package/dist/composedTrades/across/acrossWithSwaps.integration.spec.d.ts.map +1 -0
  31. package/dist/composedTrades/across/acrossWithSwaps.integration.spec.js +110 -0
  32. package/dist/composedTrades/across/acrossWithSwaps.js +121 -0
  33. package/dist/composedTrades/across/calldata/createAcrossMessage.d.ts +23 -0
  34. package/dist/composedTrades/across/calldata/createAcrossMessage.d.ts.map +1 -0
  35. package/dist/composedTrades/across/calldata/createAcrossMessage.js +69 -0
  36. package/dist/composedTrades/across/calldata/createAcrossMultiCallMessage.d.ts +14 -0
  37. package/dist/composedTrades/across/calldata/createAcrossMultiCallMessage.d.ts.map +1 -0
  38. package/dist/composedTrades/across/calldata/createAcrossMultiCallMessage.js +38 -0
  39. package/dist/composedTrades/across/calldata/types.d.ts +7 -0
  40. package/dist/composedTrades/across/calldata/types.d.ts.map +1 -0
  41. package/dist/composedTrades/across/calldata/types.js +1 -0
  42. package/dist/composedTrades/axelar/AxelarWithSwaps.d.ts +5 -0
  43. package/dist/composedTrades/axelar/AxelarWithSwaps.d.ts.map +1 -0
  44. package/dist/composedTrades/axelar/AxelarWithSwaps.js +117 -0
  45. package/dist/composedTrades/axelar/axelarRoutes.d.ts +7 -0
  46. package/dist/composedTrades/axelar/axelarRoutes.d.ts.map +1 -0
  47. package/dist/composedTrades/axelar/axelarRoutes.js +31 -0
  48. package/dist/composedTrades/axelar/axelarWithSwap.d.ts +12 -0
  49. package/dist/composedTrades/axelar/axelarWithSwap.d.ts.map +1 -0
  50. package/dist/composedTrades/axelar/axelarWithSwap.js +107 -0
  51. package/dist/composedTrades/axelar/constants.d.ts +9 -0
  52. package/dist/composedTrades/axelar/constants.d.ts.map +1 -0
  53. package/dist/composedTrades/axelar/constants.js +9 -0
  54. package/dist/composedTrades/axelar/squid/createSquidPayload.d.ts +22 -0
  55. package/dist/composedTrades/axelar/squid/createSquidPayload.d.ts.map +1 -0
  56. package/dist/composedTrades/axelar/squid/createSquidPayload.js +112 -0
  57. package/dist/composedTrades/axelar/squid/types.d.ts +15 -0
  58. package/dist/composedTrades/axelar/squid/types.d.ts.map +1 -0
  59. package/dist/composedTrades/axelar/squid/types.js +7 -0
  60. package/dist/composedTrades/gaszip/gaszipWithSwaps.d.ts +5 -0
  61. package/dist/composedTrades/gaszip/gaszipWithSwaps.d.ts.map +1 -0
  62. package/dist/composedTrades/gaszip/gaszipWithSwaps.js +114 -0
  63. package/dist/composedTrades/index.d.ts +4 -0
  64. package/dist/composedTrades/index.d.ts.map +1 -0
  65. package/dist/composedTrades/index.js +3 -0
  66. package/dist/composedTrades/utils/createSwapAndBridgeCalldata.d.ts +10 -0
  67. package/dist/composedTrades/utils/createSwapAndBridgeCalldata.d.ts.map +1 -0
  68. package/dist/composedTrades/utils/createSwapAndBridgeCalldata.js +146 -0
  69. package/dist/composedTrades/utils/fetchBridgeAndGasTrade.d.ts +8 -0
  70. package/dist/composedTrades/utils/fetchBridgeAndGasTrade.d.ts.map +1 -0
  71. package/dist/composedTrades/utils/fetchBridgeAndGasTrade.js +41 -0
  72. package/dist/composedTrades/utils/index.d.ts +3 -0
  73. package/dist/composedTrades/utils/index.d.ts.map +1 -0
  74. package/dist/composedTrades/utils/index.js +2 -0
  75. package/dist/composedTrades/utils/multichainUtils.d.ts +10 -0
  76. package/dist/composedTrades/utils/multichainUtils.d.ts.map +1 -0
  77. package/dist/composedTrades/utils/multichainUtils.js +105 -0
  78. package/dist/core.d.ts +5 -0
  79. package/dist/core.d.ts.map +1 -0
  80. package/dist/core.js +13 -0
  81. package/dist/data/chainData.d.ts +2 -0
  82. package/dist/data/chainData.d.ts.map +1 -0
  83. package/dist/data/chainData.js +20 -0
  84. package/dist/data/readinessStore.d.ts +5 -0
  85. package/dist/data/readinessStore.d.ts.map +1 -0
  86. package/dist/data/readinessStore.js +25 -0
  87. package/dist/index.d.ts +8 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +7 -0
  90. package/dist/initialize.d.ts +11 -0
  91. package/dist/initialize.d.ts.map +1 -0
  92. package/dist/initialize.js +16 -0
  93. package/dist/types/aggregator.d.ts +11 -0
  94. package/dist/types/aggregator.d.ts.map +1 -0
  95. package/dist/types/aggregator.js +1 -0
  96. package/dist/types/bridgeInput.d.ts +32 -0
  97. package/dist/types/bridgeInput.d.ts.map +1 -0
  98. package/dist/types/bridgeInput.js +1 -0
  99. package/dist/types/index.d.ts +3 -0
  100. package/dist/types/index.d.ts.map +1 -0
  101. package/dist/types/index.js +2 -0
  102. package/dist/utils/index.d.ts +2 -0
  103. package/dist/utils/index.d.ts.map +1 -0
  104. package/dist/utils/index.js +1 -0
  105. package/dist/utils/utils.d.ts +32 -0
  106. package/dist/utils/utils.d.ts.map +1 -0
  107. package/dist/utils/utils.js +41 -0
  108. package/package.json +35 -0
@@ -0,0 +1,117 @@
1
+ import { convertRawAmount } from '@1delta/aggregators';
2
+ import { CurrencyHandler, getDeltaComposerProxyAddress, getForwarderAddress, getSafeChainId, minimumAmountOutFromTrade, splitSlippage, TradeType, } from '@1delta/lib-utils';
3
+ import { fetchBestTrade, increaseAmountBySlippage } from '../utils';
4
+ import { createSwapAndBridgeCalldata } from '../utils/createSwapAndBridgeCalldata';
5
+ import { fetchAxelarRoute } from './axelarRoutes';
6
+ import fetchAxelarTradeWithSwap from './axelarWithSwap';
7
+ // Extract contract address validation
8
+ const validateContracts = (fromChainId) => {
9
+ const forwarder = getForwarderAddress(fromChainId);
10
+ if (!forwarder)
11
+ throw new Error('Forwarder contract not found');
12
+ const composer = getDeltaComposerProxyAddress(fromChainId);
13
+ if (!composer)
14
+ throw new Error('Composer proxy contract not found');
15
+ return { forwarder, composer };
16
+ };
17
+ const DUMMY_ADDRESS = '0x0000000000000000000000000000000000000001';
18
+ export const fetchAxelarTradeWithSwaps = async (input, getCurrency, getPrices, controller) => {
19
+ if (!input.fromCurrency || !input.toCurrency)
20
+ return undefined;
21
+ if (input.tradeType === TradeType.EXACT_OUTPUT)
22
+ throw new Error('Exact-out not supported for composed Axelar trade!');
23
+ // use a dummy to make axelar quote without a user address
24
+ // IMPORTANT: block assemble in this case
25
+ const isDummy = !input.receiver || !input.caller;
26
+ let sourceSwapTrade = undefined;
27
+ const fromChainId = getSafeChainId(input.fromCurrency?.chainId);
28
+ const toChainId = getSafeChainId(input.toCurrency?.chainId);
29
+ const { forwarder, composer } = validateContracts(fromChainId);
30
+ const route = await fetchAxelarRoute(fromChainId, toChainId);
31
+ if (!route)
32
+ return undefined;
33
+ const fromBridgeCurrency = getCurrency(fromChainId, route.fromBridgeToken);
34
+ const toBridgeCurrency = getCurrency(toChainId, route.toBridgeToken);
35
+ const outputIsBridgeAsset = CurrencyHandler.equal(CurrencyHandler.wrapped(input.toCurrency), toBridgeCurrency);
36
+ const inputIsBridgeAsset = CurrencyHandler.equal(CurrencyHandler.wrapped(input.fromCurrency), fromBridgeCurrency);
37
+ const [swapSlippage, bridgeSlippage] = splitSlippage(input.slippage, inputIsBridgeAsset, outputIsBridgeAsset);
38
+ if (!inputIsBridgeAsset) {
39
+ const sourceSwapInput = {
40
+ chainId: fromChainId,
41
+ tradeType: TradeType.EXACT_INPUT,
42
+ fromCurrency: input.fromCurrency,
43
+ toCurrency: fromBridgeCurrency,
44
+ slippage: swapSlippage,
45
+ swapAmount: input.swapAmount,
46
+ txOrigin: input.caller,
47
+ caller: forwarder,
48
+ receiver: forwarder,
49
+ flashSwap: undefined,
50
+ };
51
+ sourceSwapTrade = await fetchBestTrade(sourceSwapInput, controller);
52
+ }
53
+ const bridgeExtendedAmount = sourceSwapTrade
54
+ ? minimumAmountOutFromTrade(sourceSwapTrade, sourceSwapTrade.slippage).amount.toString()
55
+ : input.swapAmount;
56
+ const bridgeExtendedInput = {
57
+ ...input,
58
+ slippage: bridgeSlippage,
59
+ swapAmount: bridgeExtendedAmount,
60
+ fromCurrency: fromBridgeCurrency,
61
+ bridgeToCurrency: toBridgeCurrency,
62
+ caller: forwarder,
63
+ receiver: isDummy ? DUMMY_ADDRESS : input.receiver,
64
+ };
65
+ const { trade: bridgeTradeWithSwap, gasTrade, receiver: bridgeReceiver, } = await fetchAxelarTradeWithSwap(bridgeExtendedInput, getPrices, controller);
66
+ if (!bridgeTradeWithSwap)
67
+ return undefined;
68
+ const trades = [];
69
+ if (sourceSwapTrade)
70
+ trades.push(sourceSwapTrade);
71
+ if (gasTrade)
72
+ trades.push(gasTrade);
73
+ trades.push(bridgeTradeWithSwap);
74
+ const assemble = async () => {
75
+ if (isDummy)
76
+ return undefined;
77
+ const fundsToPull = [
78
+ {
79
+ address: input.fromCurrency.address,
80
+ amount: BigInt(input.swapAmount),
81
+ },
82
+ ];
83
+ const { calldata, value, to } = await createSwapAndBridgeCalldata(trades, input.caller, bridgeReceiver, true, fundsToPull, false, true);
84
+ return {
85
+ EVM: {
86
+ to,
87
+ calldata,
88
+ value: value.toString(),
89
+ },
90
+ };
91
+ };
92
+ const refresh = async (inputOverride) => {
93
+ const newAggregatorInput = {
94
+ ...input,
95
+ slippage: inputOverride?.slippage ?? input.slippage,
96
+ };
97
+ return fetchAxelarTradeWithSwaps(newAggregatorInput, getCurrency, getPrices);
98
+ };
99
+ const outputAmount = !!sourceSwapTrade
100
+ ? increaseAmountBySlippage(bridgeTradeWithSwap.outputAmount.amount, Number(swapSlippage))
101
+ : bridgeTradeWithSwap.outputAmount.amount;
102
+ return {
103
+ ...bridgeTradeWithSwap,
104
+ inputAmount: CurrencyHandler.fromRawAmount(input.fromCurrency, input.swapAmount),
105
+ inputAmountRealized: convertRawAmount(input.swapAmount, input.fromCurrency.decimals),
106
+ outputAmount: CurrencyHandler.fromRawAmount(bridgeTradeWithSwap.outputAmount.currency, outputAmount),
107
+ outputAmountRealized: convertRawAmount(outputAmount, bridgeTradeWithSwap.outputAmount.currency.decimals),
108
+ stringified: trades.map((t) => t.stringified).join('-'),
109
+ target: composer,
110
+ approvalTarget: composer,
111
+ slippage: input.slippage,
112
+ assemble,
113
+ refresh,
114
+ gasAmount: undefined,
115
+ };
116
+ };
117
+ export default fetchAxelarTradeWithSwaps;
@@ -0,0 +1,7 @@
1
+ interface AxelarRoute {
2
+ fromBridgeToken: string;
3
+ toBridgeToken: string;
4
+ }
5
+ export declare function fetchAxelarRoute(fromChainId: string, toChainId: string): Promise<AxelarRoute | undefined>;
6
+ export {};
7
+ //# sourceMappingURL=axelarRoutes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axelarRoutes.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/axelar/axelarRoutes.ts"],"names":[],"mappings":"AAcA,UAAU,WAAW;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAWlC"}
@@ -0,0 +1,31 @@
1
+ import { getAxelarTokenAddress, getCachedAxelarConfig, } from '@1delta/bridge-configs';
2
+ import { devLog } from '@1delta/lib-utils';
3
+ import { AxelarTokenSymbol } from './constants';
4
+ const BRIDGE_TOKENS_ORDERED = [
5
+ AxelarTokenSymbol.axlUSDC,
6
+ AxelarTokenSymbol.axlETH,
7
+ AxelarTokenSymbol.axlUSDT,
8
+ ];
9
+ export async function fetchAxelarRoute(fromChainId, toChainId) {
10
+ for (const axelarToken of BRIDGE_TOKENS_ORDERED) {
11
+ const bridgeTokens = await getBridgeTokens(fromChainId, toChainId, axelarToken);
12
+ if (bridgeTokens)
13
+ return bridgeTokens;
14
+ }
15
+ return undefined;
16
+ }
17
+ async function getBridgeTokens(fromChainId, toChainId, tokenSymbol) {
18
+ try {
19
+ const axelarConfig = await getCachedAxelarConfig();
20
+ const fromBridgeToken = getAxelarTokenAddress(axelarConfig, fromChainId, tokenSymbol);
21
+ const toBridgeToken = getAxelarTokenAddress(axelarConfig, toChainId, tokenSymbol);
22
+ return {
23
+ fromBridgeToken,
24
+ toBridgeToken,
25
+ };
26
+ }
27
+ catch (e) {
28
+ devLog('Axelar: invalid route', e);
29
+ return undefined;
30
+ }
31
+ }
@@ -0,0 +1,12 @@
1
+ import { GenericTrade, RawCurrency, useGeneralPricesCallbackType } from '@1delta/lib-utils';
2
+ import { BridgeInput } from '../../types';
3
+ export interface AxelarWithSwapInput extends BridgeInput {
4
+ bridgeToCurrency: RawCurrency | undefined;
5
+ }
6
+ export declare const fetchAxelarTradeWithSwap: (input: AxelarWithSwapInput, getPrices: useGeneralPricesCallbackType, controller?: AbortController) => Promise<{
7
+ trade: GenericTrade | undefined;
8
+ gasTrade: GenericTrade | undefined;
9
+ receiver: string;
10
+ }>;
11
+ export default fetchAxelarTradeWithSwap;
12
+ //# sourceMappingURL=axelarWithSwap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axelarWithSwap.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/axelar/axelarWithSwap.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,YAAY,EAGZ,WAAW,EAEX,4BAA4B,EAC7B,MAAM,mBAAmB,CAAA;AAI1B,OAAO,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAA;AAK1D,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACtD,gBAAgB,EAAE,WAAW,GAAG,SAAS,CAAA;CAC1C;AAED,eAAO,MAAM,wBAAwB,GACnC,OAAO,mBAAmB,EAC1B,WAAW,4BAA4B,EACvC,aAAa,eAAe,KAC3B,OAAO,CAAC;IACT,KAAK,EAAE,YAAY,GAAG,SAAS,CAAA;IAC/B,QAAQ,EAAE,YAAY,GAAG,SAAS,CAAA;IAClC,QAAQ,EAAE,MAAM,CAAA;CACjB,CA2CA,CAAA;AAED,eAAe,wBAAwB,CAAA"}
@@ -0,0 +1,107 @@
1
+ import { Bridge, createSquidPayload, getRequiredSquidMulticaller, getRequiredSquidRouter, } from '@1delta/bridge-configs';
2
+ import { CurrencyHandler, normalizeDecimals, TradeType, } from '@1delta/lib-utils';
3
+ import { fetchBridgeTrade } from '../../bridge/fetchBridgeTrade';
4
+ import { fetchBridgeAndGasTrade } from '../utils/fetchBridgeAndGasTrade';
5
+ import { fetchBestTrade } from '../utils/multichainUtils';
6
+ import { createSquidSwapPayload } from './squid/createSquidPayload';
7
+ export const fetchAxelarTradeWithSwap = async (input, getPrices, controller) => {
8
+ if (!input.bridgeToCurrency)
9
+ throw new Error('BridgeToCurrency undefined');
10
+ if (!input.toCurrency)
11
+ throw new Error('ToCurrency undefined');
12
+ const toChainId = input.toCurrency.chainId;
13
+ const toTokenIsBridgeToken = CurrencyHandler.equal(input.bridgeToCurrency, input.toCurrency);
14
+ const squidRouter = await getRequiredSquidRouter(toChainId);
15
+ if (toTokenIsBridgeToken) {
16
+ // direct case
17
+ const message = createSquidPayload(input.receiver);
18
+ const bridgeAndGasTrade = await fetchBridgeAndGasTrade(Bridge.AXELAR, { ...input, message }, getPrices, controller);
19
+ return {
20
+ trade: bridgeAndGasTrade?.bridgeTrade,
21
+ gasTrade: bridgeAndGasTrade?.gasTrade,
22
+ receiver: squidRouter,
23
+ };
24
+ }
25
+ else {
26
+ // swap case
27
+ const bridgeAndGasTrade = await fetchAxelarTradeWithDestinationSwap(input, getPrices, controller);
28
+ return {
29
+ trade: bridgeAndGasTrade?.bridgeTrade,
30
+ gasTrade: bridgeAndGasTrade?.gasTrade,
31
+ receiver: squidRouter,
32
+ };
33
+ }
34
+ };
35
+ export default fetchAxelarTradeWithSwap;
36
+ const fetchAxelarTradeWithDestinationSwap = async (input, getPrices, controller) => {
37
+ if (!input.swapAmount)
38
+ throw new Error('Swap amount undefined');
39
+ if (!input.fromCurrency)
40
+ throw new Error('FromCurrency undefined');
41
+ if (!input.toCurrency)
42
+ throw new Error('ToCurrency undefined');
43
+ if (!input.bridgeToCurrency)
44
+ throw new Error('BridgeToCurrency undefined');
45
+ const toChainId = input.toCurrency.chainId;
46
+ const squidMulticall = await getRequiredSquidMulticaller(toChainId);
47
+ const fetchSwapAndMessage = async (amount) => {
48
+ const destinationSwapInput = {
49
+ chainId: toChainId,
50
+ tradeType: TradeType.EXACT_INPUT,
51
+ fromCurrency: input.bridgeToCurrency,
52
+ toCurrency: input.toCurrency,
53
+ slippage: input.slippage,
54
+ swapAmount: amount.toString(),
55
+ txOrigin: squidMulticall,
56
+ caller: squidMulticall,
57
+ receiver: squidMulticall,
58
+ flashSwap: undefined,
59
+ };
60
+ const destinationSwapTrade = await fetchBestTrade(destinationSwapInput, controller);
61
+ if (!destinationSwapTrade || !destinationSwapTrade.assemble)
62
+ return undefined;
63
+ const tx = await destinationSwapTrade.assemble();
64
+ if (!tx?.EVM)
65
+ return undefined;
66
+ const message = createSquidSwapPayload(destinationSwapTrade.inputAmount.currency.address, destinationSwapTrade.inputAmount.amount, destinationSwapTrade.target, [tx.EVM], input.receiver, [
67
+ destinationSwapTrade.inputAmount.currency.address,
68
+ destinationSwapTrade.outputAmount.currency.address,
69
+ ]);
70
+ return { message, destinationSwapTrade };
71
+ };
72
+ const destinationSwapAmount = normalizeDecimals(BigInt(input.swapAmount), input.fromCurrency.decimals, input.bridgeToCurrency.decimals);
73
+ const swap = await fetchSwapAndMessage(destinationSwapAmount);
74
+ if (!swap)
75
+ return undefined;
76
+ const axelarInput = {
77
+ ...input,
78
+ toCurrency: input.bridgeToCurrency,
79
+ message: swap.message,
80
+ destinationGasLimit: 1000000n,
81
+ };
82
+ const bridgeAndGasTrade = await fetchBridgeAndGasTrade(Bridge.AXELAR, axelarInput, getPrices, controller);
83
+ if (!bridgeAndGasTrade)
84
+ return undefined;
85
+ const { bridgeTrade, gasTrade } = bridgeAndGasTrade;
86
+ const updatedSwap = await fetchSwapAndMessage(bridgeTrade.outputAmount.amount);
87
+ if (!updatedSwap)
88
+ return undefined;
89
+ const updatedAxelarTrade = await fetchBridgeTrade(Bridge.AXELAR, { ...axelarInput, message: updatedSwap.message }, controller);
90
+ if (!updatedAxelarTrade)
91
+ return undefined;
92
+ const refresh = async (inputOverride) => {
93
+ const newAggregatorInput = {
94
+ ...input,
95
+ slippage: inputOverride?.slippage ?? input.slippage,
96
+ };
97
+ return (await fetchAxelarTradeWithSwap(newAggregatorInput, getPrices)).trade;
98
+ };
99
+ const composedTrade = {
100
+ ...updatedAxelarTrade,
101
+ outputAmount: updatedSwap.destinationSwapTrade.outputAmount,
102
+ outputAmountRealized: updatedSwap.destinationSwapTrade.outputAmountRealized,
103
+ stringified: `${updatedAxelarTrade?.stringified}-${updatedSwap.destinationSwapTrade.stringified}`,
104
+ refresh,
105
+ };
106
+ return { bridgeTrade: composedTrade, gasTrade };
107
+ };
@@ -0,0 +1,9 @@
1
+ export declare enum AxelarTokenSymbol {
2
+ axlUSDC = "uusdc",
3
+ AXL = "uaxl",
4
+ axlDAI = "dai-wei",
5
+ axlUSDT = "uusdt",
6
+ axlWBTC = "wbtc-satoshi",
7
+ axlETH = "weth-wei"
8
+ }
9
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/axelar/constants.ts"],"names":[],"mappings":"AAAA,oBAAY,iBAAiB;IAC3B,OAAO,UAAU;IACjB,GAAG,SAAS;IACZ,MAAM,YAAY;IAClB,OAAO,UAAU;IACjB,OAAO,iBAAiB;IACxB,MAAM,aAAa;CACpB"}
@@ -0,0 +1,9 @@
1
+ export var AxelarTokenSymbol;
2
+ (function (AxelarTokenSymbol) {
3
+ AxelarTokenSymbol["axlUSDC"] = "uusdc";
4
+ AxelarTokenSymbol["AXL"] = "uaxl";
5
+ AxelarTokenSymbol["axlDAI"] = "dai-wei";
6
+ AxelarTokenSymbol["axlUSDT"] = "uusdt";
7
+ AxelarTokenSymbol["axlWBTC"] = "wbtc-satoshi";
8
+ AxelarTokenSymbol["axlETH"] = "weth-wei";
9
+ })(AxelarTokenSymbol || (AxelarTokenSymbol = {}));
@@ -0,0 +1,22 @@
1
+ import { EvmGenericCallInfo } from '@1delta/lib-utils';
2
+ import { Hex } from 'viem';
3
+ /**
4
+ * Creates the final `payload` for a complete "Approve -> Execute -> Drain" sequence
5
+ * using the Squid multicaller.
6
+ *
7
+ * This is a high-level helper that orchestrates the entire flow:
8
+ * 1. **TransferFrom** pull funds from caller to SquidMulticaller.
9
+ * 1. **Approves** an ERC20 token for a spender.
10
+ * 2. **Executes** a series of one or more "middle" calls (e.g., a swap).
11
+ * 3. **Drains** the resulting tokens from the multicall contract back to a specified address.
12
+ *
13
+ * @param tokenToApprove - The address of the ERC20 token to approve (the input token).
14
+ * @param amountToApprove - The amount of the token to approve.
15
+ * @param spender - The address that will spend the approved token (e.g., a DEX router).
16
+ * @param calls - An array of generic call objects to execute after approval.
17
+ * @param refundAndDrainAddress - The single address that serves as both the refund recipient (safety net) and the destination for the drained tokens.
18
+ * @param tokensToDrain - An array of ERC20 token addresses expected as output from the middle calls.
19
+ * @returns The final, ABI-encoded `payload` as a hex string (`Hex`).
20
+ */
21
+ export declare function createSquidSwapPayload(tokenToApprove: string, amountToApprove: bigint, spender: string, calls: EvmGenericCallInfo[], refundAndDrainAddress: string, tokensToDrain: string[]): Hex;
22
+ //# sourceMappingURL=createSquidPayload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSquidPayload.d.ts","sourceRoot":"","sources":["../../../../src/composedTrades/axelar/squid/createSquidPayload.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAIL,GAAG,EAIJ,MAAM,MAAM,CAAA;AAiEb;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CACpC,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,kBAAkB,EAAE,EAC3B,qBAAqB,EAAE,MAAM,EAC7B,aAAa,EAAE,MAAM,EAAE,GACtB,GAAG,CAqDL"}
@@ -0,0 +1,112 @@
1
+ import { createSquidPayload } from '@1delta/bridge-configs';
2
+ import { encodeAbiParameters, encodeFunctionData, parseAbi, parseAbiParameters, zeroAddress, } from 'viem';
3
+ import { SquidCallType } from './types';
4
+ /**
5
+ * [Helper] Creates the specific "drain" calls for the SquidMulticall contract.
6
+ *
7
+ * This function constructs standard ERC20 `transfer` calls but uses the special
8
+ * `FULL_TOKEN_BALANCE` callType. This instructs the multicall contract to
9
+ * substitute the transfer `amount` with its entire balance of the token at execution time.
10
+ *
11
+ * @param receiverAddress - The destination address for the drained tokens.
12
+ * @param tokensToDrain - An array of ERC20 token addresses to drain from the multicall contract.
13
+ * @returns An array of `SquidCall` objects configured for draining.
14
+ */
15
+ function createSquidDrainCalls(receiverAddress, tokensToDrain) {
16
+ const erc20TransferAbi = parseAbi([
17
+ 'function transfer(address recipient, uint256 amount)',
18
+ ]);
19
+ const fullTokenBalancePayloadAbi = parseAbiParameters('address, uint256');
20
+ const drainCalls = tokensToDrain.map((tokenToDrain) => {
21
+ const isNative = tokenToDrain === zeroAddress;
22
+ if (isNative) {
23
+ const nativeDrainCall = {
24
+ callType: SquidCallType.FULL_NATIVE_BALANCE,
25
+ target: receiverAddress,
26
+ value: 0n,
27
+ callData: '0x',
28
+ payload: '0x',
29
+ };
30
+ return nativeDrainCall;
31
+ }
32
+ const transferCalldata = encodeFunctionData({
33
+ abi: erc20TransferAbi,
34
+ functionName: 'transfer',
35
+ args: [receiverAddress, 0n], // Amount is a placeholder
36
+ });
37
+ const specialPayload = encodeAbiParameters(fullTokenBalancePayloadAbi, [
38
+ tokenToDrain,
39
+ 1n, // The `amount` is the parameter at index 1
40
+ ]);
41
+ const drainCall = {
42
+ callType: SquidCallType.FULL_TOKEN_BALANCE,
43
+ target: tokenToDrain,
44
+ value: 0n,
45
+ callData: transferCalldata,
46
+ payload: specialPayload,
47
+ };
48
+ return drainCall;
49
+ });
50
+ return drainCalls;
51
+ }
52
+ /**
53
+ * Creates the final `payload` for a complete "Approve -> Execute -> Drain" sequence
54
+ * using the Squid multicaller.
55
+ *
56
+ * This is a high-level helper that orchestrates the entire flow:
57
+ * 1. **TransferFrom** pull funds from caller to SquidMulticaller.
58
+ * 1. **Approves** an ERC20 token for a spender.
59
+ * 2. **Executes** a series of one or more "middle" calls (e.g., a swap).
60
+ * 3. **Drains** the resulting tokens from the multicall contract back to a specified address.
61
+ *
62
+ * @param tokenToApprove - The address of the ERC20 token to approve (the input token).
63
+ * @param amountToApprove - The amount of the token to approve.
64
+ * @param spender - The address that will spend the approved token (e.g., a DEX router).
65
+ * @param calls - An array of generic call objects to execute after approval.
66
+ * @param refundAndDrainAddress - The single address that serves as both the refund recipient (safety net) and the destination for the drained tokens.
67
+ * @param tokensToDrain - An array of ERC20 token addresses expected as output from the middle calls.
68
+ * @returns The final, ABI-encoded `payload` as a hex string (`Hex`).
69
+ */
70
+ export function createSquidSwapPayload(tokenToApprove, amountToApprove, spender, calls, refundAndDrainAddress, tokensToDrain) {
71
+ if (calls.some((call) => !call.to || !call.calldata)) {
72
+ throw new Error('Invalid call data');
73
+ }
74
+ const tokenAddressPayload = encodeAbiParameters(parseAbiParameters('address'), [tokenToApprove]);
75
+ const transferFromCall = {
76
+ callType: SquidCallType.COLLECT_TOKEN_BALANCE,
77
+ target: zeroAddress,
78
+ value: 0n,
79
+ callData: '0x',
80
+ payload: tokenAddressPayload,
81
+ };
82
+ const erc20ApproveAbi = parseAbi([
83
+ 'function approve(address spender, uint256 amount)',
84
+ ]);
85
+ const approveCalldata = encodeFunctionData({
86
+ abi: erc20ApproveAbi,
87
+ functionName: 'approve',
88
+ args: [spender, amountToApprove],
89
+ });
90
+ const approveCall = {
91
+ callType: SquidCallType.DEFAULT,
92
+ target: tokenToApprove,
93
+ value: 0n,
94
+ callData: approveCalldata,
95
+ payload: '0x',
96
+ };
97
+ const middleCalls = calls.map((call) => ({
98
+ callType: SquidCallType.DEFAULT,
99
+ target: call.to,
100
+ callData: call.calldata,
101
+ value: BigInt(call.value ?? 0n),
102
+ payload: '0x',
103
+ }));
104
+ const drainCalls = createSquidDrainCalls(refundAndDrainAddress, tokensToDrain);
105
+ const allCalls = [
106
+ transferFromCall,
107
+ approveCall,
108
+ ...middleCalls,
109
+ ...drainCalls,
110
+ ];
111
+ return createSquidPayload(refundAndDrainAddress, allCalls);
112
+ }
@@ -0,0 +1,15 @@
1
+ import { Address, Hex } from 'viem';
2
+ export declare enum SquidCallType {
3
+ DEFAULT = 0,
4
+ FULL_TOKEN_BALANCE = 1,
5
+ FULL_NATIVE_BALANCE = 2,
6
+ COLLECT_TOKEN_BALANCE = 3
7
+ }
8
+ export interface SquidCall {
9
+ callType: SquidCallType;
10
+ target: Address;
11
+ value: bigint;
12
+ callData: Hex;
13
+ payload: Hex;
14
+ }
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/composedTrades/axelar/squid/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAEnC,oBAAY,aAAa;IACvB,OAAO,IAAI;IACX,kBAAkB,IAAI;IACtB,mBAAmB,IAAI;IACvB,qBAAqB,IAAI;CAC1B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,aAAa,CAAA;IACvB,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,GAAG,CAAA;IACb,OAAO,EAAE,GAAG,CAAA;CACb"}
@@ -0,0 +1,7 @@
1
+ export var SquidCallType;
2
+ (function (SquidCallType) {
3
+ SquidCallType[SquidCallType["DEFAULT"] = 0] = "DEFAULT";
4
+ SquidCallType[SquidCallType["FULL_TOKEN_BALANCE"] = 1] = "FULL_TOKEN_BALANCE";
5
+ SquidCallType[SquidCallType["FULL_NATIVE_BALANCE"] = 2] = "FULL_NATIVE_BALANCE";
6
+ SquidCallType[SquidCallType["COLLECT_TOKEN_BALANCE"] = 3] = "COLLECT_TOKEN_BALANCE";
7
+ })(SquidCallType || (SquidCallType = {}));
@@ -0,0 +1,5 @@
1
+ import { GenericTrade } from '@1delta/lib-utils';
2
+ import { BridgeInput } from '../../types';
3
+ export declare const fetchGaszipTradeWithSwaps: (input: BridgeInput, controller?: AbortController) => Promise<GenericTrade | undefined>;
4
+ export default fetchGaszipTradeWithSwaps;
5
+ //# sourceMappingURL=gaszipWithSwaps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gaszipWithSwaps.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/gaszip/gaszipWithSwaps.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,YAAY,EASb,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAA;AAoB1D,eAAO,MAAM,yBAAyB,GACpC,OAAO,WAAW,EAClB,aAAa,eAAe,KAC3B,OAAO,CAAC,YAAY,GAAG,SAAS,CAkJlC,CAAA;AAED,eAAe,yBAAyB,CAAA"}
@@ -0,0 +1,114 @@
1
+ import { convertRawAmount } from '@1delta/aggregators';
2
+ import { Bridge } from '@1delta/bridge-configs';
3
+ import { CurrencyHandler, getDeltaComposerProxyAddress, getForwarderAddress, getSafeChainId, minimumAmountOutFromTrade, nativeOnChain, splitSlippage, TradeType, } from '@1delta/lib-utils';
4
+ import { fetchBridgeTrade } from '../../bridge';
5
+ import { createSwapAndBridgeCalldata } from '../utils/createSwapAndBridgeCalldata';
6
+ import { fetchBestTrade, increaseAmountBySlippage, } from '../utils/multichainUtils';
7
+ // Extract contract address validation
8
+ const validateContracts = (fromChainId) => {
9
+ const forwarder = getForwarderAddress(fromChainId);
10
+ if (!forwarder)
11
+ throw new Error('Forwarder contract not found');
12
+ const composer = getDeltaComposerProxyAddress(fromChainId);
13
+ if (!composer)
14
+ throw new Error('Composer proxy contract not found');
15
+ return { forwarder, composer };
16
+ };
17
+ const DUMMY_ADDRESS = '0x0000000000000000000000000000000000000001';
18
+ export const fetchGaszipTradeWithSwaps = async (input, controller) => {
19
+ if (!input.fromCurrency || !input.toCurrency)
20
+ return undefined;
21
+ // if (input.tradeType === TradeType.EXACT_OUTPUT)
22
+ // throw new Error('Exact-out not supported for composed Gaszip trade!')
23
+ if (!CurrencyHandler.isNative(input.toCurrency))
24
+ throw new Error('Gaszip only supports Native as output token!');
25
+ // use a dummy to make gaszip quote without a user address
26
+ // IMPORTANT: block assemble in this case
27
+ const isDummy = !input.receiver || !input.caller;
28
+ let sourceSwapTrade = undefined;
29
+ const fromChainId = getSafeChainId(input.fromCurrency?.chainId);
30
+ const toChainId = getSafeChainId(input.toCurrency?.chainId);
31
+ const { forwarder, composer } = validateContracts(fromChainId);
32
+ const fromGaszipCurrency = nativeOnChain(fromChainId);
33
+ const toGaszipCurrency = nativeOnChain(toChainId);
34
+ const inputIsGaszipAsset = CurrencyHandler.equal(input.fromCurrency, fromGaszipCurrency);
35
+ const [swapSlippage, gaszipSlippage] = splitSlippage(input.slippage, inputIsGaszipAsset, true);
36
+ if (!inputIsGaszipAsset) {
37
+ const sourceSwapInput = {
38
+ chainId: fromChainId,
39
+ tradeType: TradeType.EXACT_INPUT,
40
+ fromCurrency: input.fromCurrency,
41
+ toCurrency: fromGaszipCurrency,
42
+ slippage: swapSlippage,
43
+ swapAmount: input.swapAmount,
44
+ txOrigin: input.caller,
45
+ caller: forwarder,
46
+ receiver: forwarder,
47
+ flashSwap: undefined,
48
+ };
49
+ sourceSwapTrade = await fetchBestTrade(sourceSwapInput, controller);
50
+ }
51
+ const gaszipExtendedAmount = sourceSwapTrade
52
+ ? minimumAmountOutFromTrade(sourceSwapTrade, sourceSwapTrade.slippage).amount.toString()
53
+ : input.swapAmount;
54
+ const gaszipInput = {
55
+ tradeType: TradeType.EXACT_INPUT,
56
+ caller: isDummy ? DUMMY_ADDRESS : input.caller,
57
+ receiver: isDummy ? DUMMY_ADDRESS : input.receiver,
58
+ slippage: gaszipSlippage,
59
+ swapAmount: gaszipExtendedAmount,
60
+ fromCurrency: fromGaszipCurrency,
61
+ toCurrency: toGaszipCurrency,
62
+ order: 'CHEAPEST',
63
+ };
64
+ const gaszipTrade = await fetchBridgeTrade(Bridge.GASZIP, gaszipInput, controller);
65
+ if (!gaszipTrade)
66
+ return undefined;
67
+ const trades = sourceSwapTrade
68
+ ? [sourceSwapTrade, gaszipTrade]
69
+ : [gaszipTrade];
70
+ const assemble = async () => {
71
+ if (isDummy)
72
+ return undefined;
73
+ const fundsToPull = [
74
+ {
75
+ address: input.fromCurrency.address,
76
+ amount: BigInt(input.swapAmount),
77
+ },
78
+ ];
79
+ const { calldata, value, to } = await createSwapAndBridgeCalldata(trades, input.caller, input.receiver, false, fundsToPull, false);
80
+ return {
81
+ EVM: {
82
+ to,
83
+ calldata,
84
+ value: value.toString(),
85
+ },
86
+ };
87
+ };
88
+ const refresh = async (inputOverride) => {
89
+ const newAggregatorInput = {
90
+ ...input,
91
+ slippage: inputOverride?.slippage ?? input.slippage,
92
+ };
93
+ return fetchGaszipTradeWithSwaps(newAggregatorInput);
94
+ };
95
+ const outputAmount = !!sourceSwapTrade
96
+ ? increaseAmountBySlippage(gaszipTrade.outputAmount.amount, Number(swapSlippage))
97
+ : gaszipTrade.outputAmount.amount;
98
+ return {
99
+ ...gaszipTrade,
100
+ inputAmount: sourceSwapTrade?.inputAmount ?? gaszipTrade.inputAmount,
101
+ inputAmountRealized: sourceSwapTrade?.inputAmountRealized ?? gaszipTrade.inputAmountRealized,
102
+ outputAmount: CurrencyHandler.fromRawAmount(gaszipTrade.outputAmount.currency, outputAmount),
103
+ outputAmountRealized: convertRawAmount(outputAmount, gaszipTrade.outputAmount.currency.decimals),
104
+ stringified: sourceSwapTrade
105
+ ? `${sourceSwapTrade?.stringified}-${gaszipTrade.stringified}`
106
+ : gaszipTrade.stringified,
107
+ target: composer,
108
+ approvalTarget: composer,
109
+ slippage: input.slippage,
110
+ assemble,
111
+ refresh,
112
+ };
113
+ };
114
+ export default fetchGaszipTradeWithSwaps;
@@ -0,0 +1,4 @@
1
+ export * from './across/acrossWithSwaps';
2
+ export * from './axelar/AxelarWithSwaps';
3
+ export * from './gaszip/gaszipWithSwaps';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composedTrades/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA"}
@@ -0,0 +1,3 @@
1
+ export * from './across/acrossWithSwaps';
2
+ export * from './axelar/AxelarWithSwaps';
3
+ export * from './gaszip/gaszipWithSwaps';
@@ -0,0 +1,10 @@
1
+ import { InternalTrade } from '@1delta/lib-utils';
2
+ export declare function createSwapAndBridgeCalldata(trades: InternalTrade[], account: string, bridgeReceiver: string, sweep: boolean, fundsToPull?: {
3
+ address: string;
4
+ amount: bigint;
5
+ }[], catchRevert?: boolean, sweepDust?: boolean): Promise<{
6
+ calldata: `0x${string}`;
7
+ value: bigint;
8
+ to: string;
9
+ }>;
10
+ //# sourceMappingURL=createSwapAndBridgeCalldata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSwapAndBridgeCalldata.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/utils/createSwapAndBridgeCalldata.ts"],"names":[],"mappings":"AAcA,OAAO,EAOL,aAAa,EAKd,MAAM,mBAAmB,CAAA;AAG1B,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,aAAa,EAAE,EACvB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,OAAO,EACd,WAAW,GAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAO,EACvD,WAAW,GAAE,OAAc,EAC3B,SAAS,GAAE,OAAe;;;;GAgO3B"}