@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,122 @@
1
+ import { Bridge } from '@1delta/bridge-configs';
2
+ import { CurrencyHandler, getAcrossMulticallHandler, getSafeChainId, normalizeDecimals, TradeType, } from '@1delta/lib-utils';
3
+ import { fetchBridgeTrade } from '../../bridge/fetchBridgeTrade';
4
+ import { fetchBestTrade } from '../utils/multichainUtils';
5
+ import { createAcrossDrainMessage, createAcrossSwapMessage, } from './calldata/createAcrossMessage';
6
+ export const fetchAcrossTradeWithSwap = async (input, controller) => {
7
+ if (!input.bridgeToCurrency)
8
+ throw new Error('BridgeToCurrency undefined');
9
+ const toChainId = getSafeChainId(input.toCurrency?.chainId);
10
+ const toTokenIsBridgeToken = CurrencyHandler.equal(input.bridgeToCurrency, CurrencyHandler.wrapped(input.toCurrency));
11
+ if (toTokenIsBridgeToken) {
12
+ const toTokenIsWNative = CurrencyHandler.isWNative(input.toCurrency);
13
+ if (toTokenIsWNative) {
14
+ // special case: to receive wrapped native receiver must be contract
15
+ const acrossTrade = await fetchAcrossTradeWithSweep(input, controller);
16
+ return {
17
+ trade: acrossTrade,
18
+ receiver: getAcrossMulticallHandler(toChainId),
19
+ };
20
+ }
21
+ else {
22
+ // normal case: for all other token receiver can directly be EOA
23
+ const acrossTrade = await fetchBridgeTrade(Bridge.ACROSS, input, controller);
24
+ return {
25
+ trade: acrossTrade,
26
+ receiver: input.receiver,
27
+ };
28
+ }
29
+ }
30
+ else {
31
+ const acrossTrade = await fetchAcrossTradeWithDestinationSwap(input, controller);
32
+ return {
33
+ trade: acrossTrade,
34
+ receiver: getAcrossMulticallHandler(toChainId),
35
+ };
36
+ }
37
+ };
38
+ export default fetchAcrossTradeWithSwap;
39
+ const fetchAcrossTradeWithSweep = async (input, controller) => {
40
+ if (!input.swapAmount)
41
+ throw new Error('Swap amount undefined');
42
+ if (!input.fromCurrency)
43
+ throw new Error('FromCurrency undefined');
44
+ if (!input.toCurrency)
45
+ throw new Error('ToCurrency undefined');
46
+ const toChainId = input.toCurrency.chainId;
47
+ const message = createAcrossDrainMessage(getAcrossMulticallHandler(toChainId), input.receiver, [input.toCurrency.address]);
48
+ const acrossInput = {
49
+ ...input,
50
+ receiver: getAcrossMulticallHandler(toChainId),
51
+ message,
52
+ };
53
+ const acrossTrade = await fetchBridgeTrade(Bridge.ACROSS, acrossInput, controller);
54
+ if (!acrossTrade)
55
+ return undefined;
56
+ return acrossTrade;
57
+ };
58
+ const fetchAcrossTradeWithDestinationSwap = async (input, controller) => {
59
+ if (!input.swapAmount)
60
+ throw new Error('Swap amount undefined');
61
+ if (!input.fromCurrency)
62
+ throw new Error('FromCurrency undefined');
63
+ if (!input.toCurrency)
64
+ throw new Error('ToCurrency undefined');
65
+ if (!input.bridgeToCurrency)
66
+ throw new Error('BridgeToCurrency undefined');
67
+ const toChainId = input.toCurrency.chainId;
68
+ const fetchSwapAndMessage = async (amount) => {
69
+ const destinationSwapInput = {
70
+ chainId: toChainId,
71
+ tradeType: TradeType.EXACT_INPUT,
72
+ fromCurrency: input.bridgeToCurrency,
73
+ toCurrency: input.toCurrency,
74
+ slippage: input.slippage,
75
+ swapAmount: amount.toString(),
76
+ txOrigin: getAcrossMulticallHandler(toChainId),
77
+ caller: getAcrossMulticallHandler(toChainId),
78
+ receiver: input.receiver,
79
+ flashSwap: undefined,
80
+ };
81
+ const destinationSwapTrade = await fetchBestTrade(destinationSwapInput, controller);
82
+ if (!destinationSwapTrade || !destinationSwapTrade.assemble)
83
+ return undefined;
84
+ const tx = await destinationSwapTrade.assemble();
85
+ if (!tx?.EVM)
86
+ return undefined;
87
+ const message = createAcrossSwapMessage(getAcrossMulticallHandler(toChainId), destinationSwapTrade.inputAmount.currency.address, destinationSwapTrade.inputAmount.amount, destinationSwapTrade.target, [tx.EVM], input.receiver, [destinationSwapTrade.inputAmount.currency.address]);
88
+ return { message, destinationSwapTrade };
89
+ };
90
+ const destinationSwapAmount = normalizeDecimals(BigInt(input.swapAmount), input.fromCurrency.decimals, input.bridgeToCurrency.decimals);
91
+ const swap = await fetchSwapAndMessage(destinationSwapAmount);
92
+ if (!swap)
93
+ return undefined;
94
+ const acrossInput = {
95
+ ...input,
96
+ toCurrency: input.bridgeToCurrency,
97
+ receiver: getAcrossMulticallHandler(toChainId),
98
+ };
99
+ const acrossTrade = await fetchBridgeTrade(Bridge.ACROSS, { ...acrossInput, message: swap.message }, controller);
100
+ if (!acrossTrade)
101
+ return undefined;
102
+ const updatedSwap = await fetchSwapAndMessage(acrossTrade.outputAmount.amount);
103
+ if (!updatedSwap)
104
+ return undefined;
105
+ const updatedAcrossTrade = await fetchBridgeTrade(Bridge.ACROSS, { ...acrossInput, message: updatedSwap.message }, controller);
106
+ if (!updatedAcrossTrade)
107
+ return undefined;
108
+ const refresh = async (inputOverride) => {
109
+ const newAggregatorInput = {
110
+ ...input,
111
+ slippage: inputOverride?.slippage ?? input.slippage,
112
+ };
113
+ return (await fetchAcrossTradeWithSwap(newAggregatorInput)).trade;
114
+ };
115
+ return {
116
+ ...updatedAcrossTrade,
117
+ outputAmount: updatedSwap.destinationSwapTrade.outputAmount,
118
+ outputAmountRealized: updatedSwap.destinationSwapTrade.outputAmountRealized,
119
+ stringified: `${updatedAcrossTrade?.stringified}-${updatedSwap.destinationSwapTrade.stringified}`,
120
+ refresh,
121
+ };
122
+ };
@@ -0,0 +1,5 @@
1
+ import { GenericTrade, RawCurrency } from '@1delta/lib-utils';
2
+ import { BridgeInput } from '../../types';
3
+ export declare const fetchAcrossTradeWithSwaps: (input: BridgeInput, getCurrency: (chainId: string | undefined, tokenAddress: string | undefined) => RawCurrency | undefined, controller?: AbortController) => Promise<GenericTrade | undefined>;
4
+ export default fetchAcrossTradeWithSwaps;
5
+ //# sourceMappingURL=acrossWithSwaps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acrossWithSwaps.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/across/acrossWithSwaps.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,YAAY,EAOZ,WAAW,EAGZ,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAA;AAsB1D,eAAO,MAAM,yBAAyB,GACpC,OAAO,WAAW,EAClB,aAAa,CACX,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,YAAY,EAAE,MAAM,GAAG,SAAS,KAC7B,WAAW,GAAG,SAAS,EAC5B,aAAa,eAAe,KAC3B,OAAO,CAAC,YAAY,GAAG,SAAS,CAoKlC,CAAA;AAED,eAAe,yBAAyB,CAAA"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=acrossWithSwaps.integration.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acrossWithSwaps.integration.spec.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/across/acrossWithSwaps.integration.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ // import { ChainId, Percent, TradeType } from '@1delta/base-sdk'
3
+ // import { beforeEach, describe, expect, it, vi } from 'vitest'
4
+ // import { BridgeInput } from '@/hooks/bridge/types'
5
+ // import { USDC_ON } from '@/lib/constants/addresses'
6
+ // import { RawCurrency } from '@/lib/types'
7
+ // import fetchAcrossTradeWithSwaps from './acrossWithSwaps'
8
+ // describe('fetchAcrossTradeWithSwaps', () => {
9
+ // beforeEach(() => {
10
+ // vi.clearAllMocks()
11
+ // })
12
+ // const ACCOUNT = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'
13
+ // const WBTC_OP: RawCurrency = {
14
+ // chainId: ChainId.OP_MAINNET,
15
+ // address: '0x68f180fcCe6836688e9084f035309E29Bf0A2095',
16
+ // decimals: 8,
17
+ // symbol: 'WBTC',
18
+ // name: 'Wrapped BTC',
19
+ // }
20
+ // const WBTC_ARB: RawCurrency = {
21
+ // chainId: ChainId.ARBITRUM_ONE,
22
+ // address: '0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f',
23
+ // decimals: 8,
24
+ // symbol: 'WBTC',
25
+ // name: 'Wrapped BTC',
26
+ // }
27
+ // const USDT_ARB: RawCurrency = {
28
+ // chainId: ChainId.ARBITRUM_ONE,
29
+ // address: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',
30
+ // decimals: 6,
31
+ // symbol: 'USDT',
32
+ // name: 'USDT',
33
+ // }
34
+ // const getCurrency = (
35
+ // chainId: string | undefined,
36
+ // tokenAddress: string | undefined
37
+ // ) => {
38
+ // if (!chainId || !tokenAddress) return undefined
39
+ // if (
40
+ // WBTC_ARB.address.toLowerCase() === tokenAddress.toLowerCase() &&
41
+ // WBTC_ARB.chainId === chainId
42
+ // )
43
+ // return WBTC_ARB
44
+ // if (
45
+ // WBTC_OP.address.toLowerCase() === tokenAddress.toLowerCase() &&
46
+ // WBTC_OP.chainId === chainId
47
+ // )
48
+ // return WBTC_OP
49
+ // if (USDC_ON(chainId).address.toLowerCase() === tokenAddress.toLowerCase())
50
+ // return USDC_ON(chainId)
51
+ // return undefined
52
+ // }
53
+ // it('Bridge', async () => {
54
+ // const fromCurrency = USDC_ON(ChainId.ARBITRUM_ONE)
55
+ // const toCurrency = USDC_ON(ChainId.OP_MAINNET)
56
+ // const input: BridgeInput = {
57
+ // tradeType: TradeType.EXACT_INPUT,
58
+ // fromCurrency,
59
+ // toCurrency,
60
+ // slippage: 1,
61
+ // swapAmount: '1000000',
62
+ // caller: ACCOUNT,
63
+ // receiver: ACCOUNT,
64
+ // order: 'FASTEST',
65
+ // }
66
+ // const result = await fetchAcrossTradeWithSwaps(input, getCurrency)
67
+ // console.log('result', result)
68
+ // expect(result).toBeDefined()
69
+ // expect(result?.inputAmount.currency).toEqual(fromCurrency)
70
+ // expect(result?.outputAmount.currency).toEqual(toCurrency)
71
+ // })
72
+ // it('Bridge + Swap', async () => {
73
+ // const fromCurrency = USDC_ON(ChainId.ARBITRUM_ONE)
74
+ // const toCurrency = WBTC_OP
75
+ // const input: BridgeInput = {
76
+ // tradeType: TradeType.EXACT_INPUT,
77
+ // fromCurrency,
78
+ // toCurrency,
79
+ // slippage: 1,
80
+ // swapAmount: '1000000',
81
+ // caller: ACCOUNT,
82
+ // receiver: ACCOUNT,
83
+ // order: 'FASTEST',
84
+ // }
85
+ // const result = await fetchAcrossTradeWithSwaps(input, getCurrency)
86
+ // console.log('result', result)
87
+ // expect(result).toBeDefined()
88
+ // expect(result?.inputAmount.currency).toEqual(fromCurrency)
89
+ // expect(result?.outputAmount.currency).toEqual(toCurrency)
90
+ // })
91
+ // it('Swap + Bridge + Swap', async () => {
92
+ // const fromCurrency = USDT_ARB
93
+ // const toCurrency = WBTC_OP
94
+ // const input: BridgeInput = {
95
+ // tradeType: TradeType.EXACT_INPUT,
96
+ // fromCurrency,
97
+ // toCurrency,
98
+ // slippage: 1,
99
+ // swapAmount: '1000000',
100
+ // caller: ACCOUNT,
101
+ // receiver: ACCOUNT,
102
+ // order: 'FASTEST',
103
+ // }
104
+ // const result = await fetchAcrossTradeWithSwaps(input, getCurrency)
105
+ // console.log('result', result)
106
+ // expect(result).toBeDefined()
107
+ // expect(result?.inputAmount.currency).toEqual(fromCurrency)
108
+ // expect(result?.outputAmount.currency).toEqual(toCurrency)
109
+ // })
110
+ // }, 20000)
@@ -0,0 +1,121 @@
1
+ import { convertRawAmount } from '@1delta/aggregators';
2
+ import { CurrencyHandler, getDeltaComposerProxyAddress, getForwarderAddress, getSafeChainId, minimumAmountOutFromTrade, nativeOnChain, splitSlippage, TradeType, } from '@1delta/lib-utils';
3
+ import { createSwapAndBridgeCalldata } from '../utils/createSwapAndBridgeCalldata';
4
+ import { fetchBestTrade, increaseAmountBySlippage, } from '../utils/multichainUtils';
5
+ import { fetchAcrossRoutes, selectAcrossRoute } from './acrossRoutes';
6
+ import fetchAcrossTradeWithSwap from './acrossWithSwap';
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 fetchAcrossTradeWithSwaps = async (input, getCurrency, 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 Across trade!');
23
+ // use a dummy to make across 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 routes = await fetchAcrossRoutes(fromChainId, toChainId);
31
+ const acrossRoute = selectAcrossRoute(routes, input.fromCurrency, input.toCurrency);
32
+ if (!acrossRoute)
33
+ return undefined;
34
+ const fromAcrossCurrency = getCurrency(acrossRoute.originChainId.toString(), acrossRoute.originToken);
35
+ const toAcrossCurrency = getCurrency(acrossRoute.destinationChainId.toString(), acrossRoute.destinationToken);
36
+ const outputIsAcrossAsset = CurrencyHandler.equal(CurrencyHandler.wrapped(input.toCurrency), toAcrossCurrency);
37
+ const inputIsAcrossAsset = CurrencyHandler.equal(CurrencyHandler.wrapped(input.fromCurrency), fromAcrossCurrency);
38
+ const [swapSlippage, acrossSlippage] = splitSlippage(input.slippage, inputIsAcrossAsset, outputIsAcrossAsset);
39
+ if (!inputIsAcrossAsset) {
40
+ const sourceSwapInput = {
41
+ chainId: fromChainId,
42
+ tradeType: TradeType.EXACT_INPUT,
43
+ fromCurrency: input.fromCurrency,
44
+ toCurrency: fromAcrossCurrency,
45
+ slippage: swapSlippage,
46
+ swapAmount: input.swapAmount,
47
+ txOrigin: input.caller,
48
+ caller: forwarder,
49
+ receiver: forwarder,
50
+ flashSwap: undefined,
51
+ };
52
+ sourceSwapTrade = await fetchBestTrade(sourceSwapInput, controller);
53
+ }
54
+ const acrossExtendedAmount = sourceSwapTrade
55
+ ? minimumAmountOutFromTrade(sourceSwapTrade, sourceSwapTrade.slippage).amount.toString()
56
+ : input.swapAmount;
57
+ const acrossExtendedInput = {
58
+ ...input,
59
+ caller: isDummy ? DUMMY_ADDRESS : input.caller, // placeholder addresses if we have no connection
60
+ receiver: isDummy ? DUMMY_ADDRESS : input.receiver,
61
+ slippage: acrossSlippage,
62
+ swapAmount: acrossExtendedAmount,
63
+ fromCurrency: acrossRoute.isNative
64
+ ? nativeOnChain(acrossRoute.originChainId.toString())
65
+ : fromAcrossCurrency,
66
+ bridgeToCurrency: toAcrossCurrency,
67
+ };
68
+ const { trade: acrossTradeWithSwap, receiver: bridgeReceiver } = await fetchAcrossTradeWithSwap(acrossExtendedInput, controller);
69
+ if (!acrossTradeWithSwap)
70
+ return undefined;
71
+ const trades = sourceSwapTrade
72
+ ? [sourceSwapTrade, acrossTradeWithSwap]
73
+ : [acrossTradeWithSwap];
74
+ const assemble = async () => {
75
+ // block assemble if no user address
76
+ if (isDummy)
77
+ return undefined;
78
+ // otherwise continue
79
+ const fundsToPull = [
80
+ {
81
+ address: input.fromCurrency.address,
82
+ amount: BigInt(input.swapAmount),
83
+ },
84
+ ];
85
+ const { calldata, value, to } = await createSwapAndBridgeCalldata(trades, input.caller, bridgeReceiver, false, fundsToPull, false);
86
+ return {
87
+ EVM: {
88
+ to,
89
+ calldata,
90
+ value: value.toString(),
91
+ },
92
+ };
93
+ };
94
+ const refresh = async (inputOverride) => {
95
+ const newAggregatorInput = {
96
+ ...input,
97
+ slippage: inputOverride?.slippage ?? input.slippage,
98
+ };
99
+ return fetchAcrossTradeWithSwaps(newAggregatorInput, getCurrency);
100
+ };
101
+ const outputAmount = !!sourceSwapTrade
102
+ ? increaseAmountBySlippage(acrossTradeWithSwap.outputAmount.amount, Number(swapSlippage))
103
+ : acrossTradeWithSwap.outputAmount.amount;
104
+ return {
105
+ ...acrossTradeWithSwap,
106
+ inputAmount: sourceSwapTrade?.inputAmount ?? acrossTradeWithSwap.inputAmount,
107
+ inputAmountRealized: sourceSwapTrade?.inputAmountRealized ??
108
+ acrossTradeWithSwap.inputAmountRealized,
109
+ outputAmount: CurrencyHandler.fromRawAmount(acrossTradeWithSwap.outputAmount.currency, outputAmount),
110
+ outputAmountRealized: convertRawAmount(outputAmount, acrossTradeWithSwap.outputAmount.currency.decimals),
111
+ stringified: sourceSwapTrade
112
+ ? `${sourceSwapTrade?.stringified}-${acrossTradeWithSwap.stringified}`
113
+ : acrossTradeWithSwap.stringified,
114
+ target: composer,
115
+ approvalTarget: composer,
116
+ slippage: input.slippage,
117
+ assemble,
118
+ refresh,
119
+ };
120
+ };
121
+ export default fetchAcrossTradeWithSwaps;
@@ -0,0 +1,23 @@
1
+ import { EvmGenericCallInfo } from '@1delta/lib-utils';
2
+ import { Hex } from 'viem';
3
+ /**
4
+ * Creates the ABI-encoded `message` for a complete "Approve -> Execute -> Drain" sequence
5
+ * using the Across MulticallHandler.
6
+ *
7
+ * This is a high-level helper that orchestrates the entire flow:
8
+ * 1. **Approves** an ERC20 token for a spender.
9
+ * 2. **Executes** a series of one or more provided "middle" calls (e.g., a swap).
10
+ * 3. **Drains** the resulting token from the handler back to a specified address.
11
+ *
12
+ * @param multicallHandlerAddress - The address of the deployed MulticallHandler on the destination chain.
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 middleCalls - An array of `AcrossCall` objects to execute after approval (the core logic).
17
+ * @param tokenToDrain - The address of the ERC20 token expected as output from the middle calls.
18
+ * @param fallbackAndDrainAddress - The single address that serves as both the safety net (fallback) and the destination for the drained tokens. This should be your wallet.
19
+ * @returns The final, ABI-encoded `message` as a hex string (`Hex`).
20
+ */
21
+ export declare function createAcrossSwapMessage(multicallHandlerAddress: string, tokenToApprove: string, amountToApprove: bigint, spender: string, calls: EvmGenericCallInfo[], fallbackAndDrainAddress: string, tokensToDrain: string[]): Hex;
22
+ export declare function createAcrossDrainMessage(multicallHandlerAddress: string, fallbackAndDrainAddress: string, tokensToDrain: string[]): Hex;
23
+ //# sourceMappingURL=createAcrossMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAcrossMessage.d.ts","sourceRoot":"","sources":["../../../../src/composedTrades/across/calldata/createAcrossMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAA+B,GAAG,EAAY,MAAM,MAAM,CAAA;AAKjE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CACrC,uBAAuB,EAAE,MAAM,EAC/B,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,kBAAkB,EAAE,EAC3B,uBAAuB,EAAE,MAAM,EAC/B,aAAa,EAAE,MAAM,EAAE,GACtB,GAAG,CAsCL;AAED,wBAAgB,wBAAwB,CACtC,uBAAuB,EAAE,MAAM,EAC/B,uBAAuB,EAAE,MAAM,EAC/B,aAAa,EAAE,MAAM,EAAE,GACtB,GAAG,CAWL"}
@@ -0,0 +1,69 @@
1
+ import { encodeFunctionData, parseAbi } from 'viem';
2
+ import { createAcrossMultiCallMessage } from './createAcrossMultiCallMessage';
3
+ /**
4
+ * Creates the ABI-encoded `message` for a complete "Approve -> Execute -> Drain" sequence
5
+ * using the Across MulticallHandler.
6
+ *
7
+ * This is a high-level helper that orchestrates the entire flow:
8
+ * 1. **Approves** an ERC20 token for a spender.
9
+ * 2. **Executes** a series of one or more provided "middle" calls (e.g., a swap).
10
+ * 3. **Drains** the resulting token from the handler back to a specified address.
11
+ *
12
+ * @param multicallHandlerAddress - The address of the deployed MulticallHandler on the destination chain.
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 middleCalls - An array of `AcrossCall` objects to execute after approval (the core logic).
17
+ * @param tokenToDrain - The address of the ERC20 token expected as output from the middle calls.
18
+ * @param fallbackAndDrainAddress - The single address that serves as both the safety net (fallback) and the destination for the drained tokens. This should be your wallet.
19
+ * @returns The final, ABI-encoded `message` as a hex string (`Hex`).
20
+ */
21
+ export function createAcrossSwapMessage(multicallHandlerAddress, tokenToApprove, amountToApprove, spender, calls, fallbackAndDrainAddress, tokensToDrain) {
22
+ if (calls.some((call) => !call.to || !call.calldata)) {
23
+ throw new Error('Invalid call data');
24
+ }
25
+ const erc20ApproveAbi = parseAbi([
26
+ 'function approve(address spender, uint256 amount)',
27
+ ]);
28
+ const approveCalldata = encodeFunctionData({
29
+ abi: erc20ApproveAbi,
30
+ functionName: 'approve',
31
+ args: [spender, amountToApprove],
32
+ });
33
+ const approveCall = {
34
+ target: tokenToApprove,
35
+ callData: approveCalldata,
36
+ value: 0n,
37
+ };
38
+ const middleCalls = calls.map((call) => ({
39
+ target: call.to,
40
+ callData: call.calldata,
41
+ value: BigInt(call.value ?? 0n),
42
+ }));
43
+ const drainCalls = createDrainCalls(multicallHandlerAddress, fallbackAndDrainAddress, tokensToDrain);
44
+ const allCalls = [approveCall, ...middleCalls, ...drainCalls];
45
+ return createAcrossMultiCallMessage(allCalls, fallbackAndDrainAddress);
46
+ }
47
+ export function createAcrossDrainMessage(multicallHandlerAddress, fallbackAndDrainAddress, tokensToDrain) {
48
+ const drainCalls = createDrainCalls(multicallHandlerAddress, fallbackAndDrainAddress, tokensToDrain);
49
+ return createAcrossMultiCallMessage(drainCalls, fallbackAndDrainAddress);
50
+ }
51
+ function createDrainCalls(multicallHandlerAddress, receiverAddress, tokensToDrain) {
52
+ const multicallHandlerDrainAbi = parseAbi([
53
+ 'function drainLeftoverTokens(address token, address destination)',
54
+ ]);
55
+ const drainCalls = tokensToDrain.map((tokenToDrain) => {
56
+ const drainCalldata = encodeFunctionData({
57
+ abi: multicallHandlerDrainAbi,
58
+ functionName: 'drainLeftoverTokens',
59
+ args: [tokenToDrain, receiverAddress],
60
+ });
61
+ const drainCall = {
62
+ target: multicallHandlerAddress,
63
+ callData: drainCalldata,
64
+ value: 0n,
65
+ };
66
+ return drainCall;
67
+ });
68
+ return drainCalls;
69
+ }
@@ -0,0 +1,14 @@
1
+ import { Address, Hex } from 'viem';
2
+ import { AcrossCall } from './types';
3
+ /**
4
+ * Creates the ABI-encoded `message` for the Across MulticallHandler contract.
5
+ *
6
+ * This function takes a sequence of calls and a fallback recipient and encodes them
7
+ * into the `Instructions` struct format expected by the handler.
8
+ *
9
+ * @param calls - An array of `AcrossCall` objects, defining the sequence of contract calls to execute on the destination chain.
10
+ * @param fallbackAddress - The "safety net" address that receives the funds if any call fails, or any leftover tokens after successful execution.
11
+ * @returns The ABI-encoded `message` as a hex string (`Hex`).
12
+ */
13
+ export declare function createAcrossMultiCallMessage(calls: AcrossCall[], fallbackRecipient: Address): Hex;
14
+ //# sourceMappingURL=createAcrossMultiCallMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAcrossMultiCallMessage.d.ts","sourceRoot":"","sources":["../../../../src/composedTrades/across/calldata/createAcrossMultiCallMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAuB,GAAG,EAAE,MAAM,MAAM,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEpC;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,UAAU,EAAE,EACnB,iBAAiB,EAAE,OAAO,GACzB,GAAG,CAiCL"}
@@ -0,0 +1,38 @@
1
+ import { encodeAbiParameters } from 'viem';
2
+ /**
3
+ * Creates the ABI-encoded `message` for the Across MulticallHandler contract.
4
+ *
5
+ * This function takes a sequence of calls and a fallback recipient and encodes them
6
+ * into the `Instructions` struct format expected by the handler.
7
+ *
8
+ * @param calls - An array of `AcrossCall` objects, defining the sequence of contract calls to execute on the destination chain.
9
+ * @param fallbackAddress - The "safety net" address that receives the funds if any call fails, or any leftover tokens after successful execution.
10
+ * @returns The ABI-encoded `message` as a hex string (`Hex`).
11
+ */
12
+ export function createAcrossMultiCallMessage(calls, fallbackRecipient) {
13
+ if (!fallbackRecipient ||
14
+ fallbackRecipient === '0x0000000000000000000000000000000000000000') {
15
+ throw new Error('Using a zero address for fallbackAddress is highly discouraged. Funds may be unrecoverable on failure.');
16
+ }
17
+ const instructionsAbi = [
18
+ {
19
+ type: 'tuple',
20
+ components: [
21
+ {
22
+ type: 'tuple[]',
23
+ name: 'calls',
24
+ components: [
25
+ { type: 'address', name: 'target' },
26
+ { type: 'bytes', name: 'callData' },
27
+ { type: 'uint256', name: 'value' },
28
+ ],
29
+ },
30
+ { type: 'address', name: 'fallbackRecipient' },
31
+ ],
32
+ },
33
+ ];
34
+ const message = encodeAbiParameters(instructionsAbi, [
35
+ { calls, fallbackRecipient },
36
+ ]);
37
+ return message;
38
+ }
@@ -0,0 +1,7 @@
1
+ import { Address, Hex } from 'viem';
2
+ export type AcrossCall = {
3
+ target: Address;
4
+ callData: Hex;
5
+ value: bigint;
6
+ };
7
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/composedTrades/across/calldata/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAEnC,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,GAAG,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAAA"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import { GenericTrade, RawCurrency, useGeneralPricesCallbackType } from '@1delta/lib-utils';
2
+ import { BridgeInput } from '../../types';
3
+ export declare const fetchAxelarTradeWithSwaps: (input: BridgeInput, getCurrency: (chainId: string | undefined, tokenAddress: string | undefined) => RawCurrency | undefined, getPrices: useGeneralPricesCallbackType, controller?: AbortController) => Promise<GenericTrade | undefined>;
4
+ export default fetchAxelarTradeWithSwaps;
5
+ //# sourceMappingURL=AxelarWithSwaps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AxelarWithSwaps.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/axelar/AxelarWithSwaps.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,YAAY,EAMZ,WAAW,EAGX,4BAA4B,EAC7B,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAA;AAmB1D,eAAO,MAAM,yBAAyB,GACpC,OAAO,WAAW,EAClB,aAAa,CACX,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,YAAY,EAAE,MAAM,GAAG,SAAS,KAC7B,WAAW,GAAG,SAAS,EAC5B,WAAW,4BAA4B,EACvC,aAAa,eAAe,KAC3B,OAAO,CAAC,YAAY,GAAG,SAAS,CA8JlC,CAAA;AAED,eAAe,yBAAyB,CAAA"}