@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.
- package/LICENSE +674 -0
- package/README.md +63 -0
- package/dist/aggregator/fetchAggregatorTrade.d.ts +6 -0
- package/dist/aggregator/fetchAggregatorTrade.d.ts.map +1 -0
- package/dist/aggregator/fetchAggregatorTrade.js +14 -0
- package/dist/aggregator/getAvailableAggregators.d.ts +2 -0
- package/dist/aggregator/getAvailableAggregators.d.ts.map +1 -0
- package/dist/aggregator/getAvailableAggregators.js +11 -0
- package/dist/aggregator/index.d.ts +3 -0
- package/dist/aggregator/index.d.ts.map +1 -0
- package/dist/aggregator/index.js +2 -0
- package/dist/bridge/fetchBridgeTrade.d.ts +5 -0
- package/dist/bridge/fetchBridgeTrade.d.ts.map +1 -0
- package/dist/bridge/fetchBridgeTrade.js +195 -0
- package/dist/bridge/index.d.ts +2 -0
- package/dist/bridge/index.d.ts.map +1 -0
- package/dist/bridge/index.js +1 -0
- package/dist/composedTrades/across/acrossRoutes.d.ts +17 -0
- package/dist/composedTrades/across/acrossRoutes.d.ts.map +1 -0
- package/dist/composedTrades/across/acrossRoutes.js +64 -0
- package/dist/composedTrades/across/acrossWithSwap.d.ts +11 -0
- package/dist/composedTrades/across/acrossWithSwap.d.ts.map +1 -0
- package/dist/composedTrades/across/acrossWithSwap.integration.spec.d.ts +1 -0
- package/dist/composedTrades/across/acrossWithSwap.integration.spec.d.ts.map +1 -0
- package/dist/composedTrades/across/acrossWithSwap.integration.spec.js +116 -0
- package/dist/composedTrades/across/acrossWithSwap.js +122 -0
- package/dist/composedTrades/across/acrossWithSwaps.d.ts +5 -0
- package/dist/composedTrades/across/acrossWithSwaps.d.ts.map +1 -0
- package/dist/composedTrades/across/acrossWithSwaps.integration.spec.d.ts +1 -0
- package/dist/composedTrades/across/acrossWithSwaps.integration.spec.d.ts.map +1 -0
- package/dist/composedTrades/across/acrossWithSwaps.integration.spec.js +110 -0
- package/dist/composedTrades/across/acrossWithSwaps.js +121 -0
- package/dist/composedTrades/across/calldata/createAcrossMessage.d.ts +23 -0
- package/dist/composedTrades/across/calldata/createAcrossMessage.d.ts.map +1 -0
- package/dist/composedTrades/across/calldata/createAcrossMessage.js +69 -0
- package/dist/composedTrades/across/calldata/createAcrossMultiCallMessage.d.ts +14 -0
- package/dist/composedTrades/across/calldata/createAcrossMultiCallMessage.d.ts.map +1 -0
- package/dist/composedTrades/across/calldata/createAcrossMultiCallMessage.js +38 -0
- package/dist/composedTrades/across/calldata/types.d.ts +7 -0
- package/dist/composedTrades/across/calldata/types.d.ts.map +1 -0
- package/dist/composedTrades/across/calldata/types.js +1 -0
- package/dist/composedTrades/axelar/AxelarWithSwaps.d.ts +5 -0
- package/dist/composedTrades/axelar/AxelarWithSwaps.d.ts.map +1 -0
- package/dist/composedTrades/axelar/AxelarWithSwaps.js +117 -0
- package/dist/composedTrades/axelar/axelarRoutes.d.ts +7 -0
- package/dist/composedTrades/axelar/axelarRoutes.d.ts.map +1 -0
- package/dist/composedTrades/axelar/axelarRoutes.js +31 -0
- package/dist/composedTrades/axelar/axelarWithSwap.d.ts +12 -0
- package/dist/composedTrades/axelar/axelarWithSwap.d.ts.map +1 -0
- package/dist/composedTrades/axelar/axelarWithSwap.js +107 -0
- package/dist/composedTrades/axelar/constants.d.ts +9 -0
- package/dist/composedTrades/axelar/constants.d.ts.map +1 -0
- package/dist/composedTrades/axelar/constants.js +9 -0
- package/dist/composedTrades/axelar/squid/createSquidPayload.d.ts +22 -0
- package/dist/composedTrades/axelar/squid/createSquidPayload.d.ts.map +1 -0
- package/dist/composedTrades/axelar/squid/createSquidPayload.js +112 -0
- package/dist/composedTrades/axelar/squid/types.d.ts +15 -0
- package/dist/composedTrades/axelar/squid/types.d.ts.map +1 -0
- package/dist/composedTrades/axelar/squid/types.js +7 -0
- package/dist/composedTrades/gaszip/gaszipWithSwaps.d.ts +5 -0
- package/dist/composedTrades/gaszip/gaszipWithSwaps.d.ts.map +1 -0
- package/dist/composedTrades/gaszip/gaszipWithSwaps.js +114 -0
- package/dist/composedTrades/index.d.ts +4 -0
- package/dist/composedTrades/index.d.ts.map +1 -0
- package/dist/composedTrades/index.js +3 -0
- package/dist/composedTrades/utils/createSwapAndBridgeCalldata.d.ts +10 -0
- package/dist/composedTrades/utils/createSwapAndBridgeCalldata.d.ts.map +1 -0
- package/dist/composedTrades/utils/createSwapAndBridgeCalldata.js +146 -0
- package/dist/composedTrades/utils/fetchBridgeAndGasTrade.d.ts +8 -0
- package/dist/composedTrades/utils/fetchBridgeAndGasTrade.d.ts.map +1 -0
- package/dist/composedTrades/utils/fetchBridgeAndGasTrade.js +41 -0
- package/dist/composedTrades/utils/index.d.ts +3 -0
- package/dist/composedTrades/utils/index.d.ts.map +1 -0
- package/dist/composedTrades/utils/index.js +2 -0
- package/dist/composedTrades/utils/multichainUtils.d.ts +10 -0
- package/dist/composedTrades/utils/multichainUtils.d.ts.map +1 -0
- package/dist/composedTrades/utils/multichainUtils.js +105 -0
- package/dist/core.d.ts +5 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +13 -0
- package/dist/data/chainData.d.ts +2 -0
- package/dist/data/chainData.d.ts.map +1 -0
- package/dist/data/chainData.js +20 -0
- package/dist/data/readinessStore.d.ts +5 -0
- package/dist/data/readinessStore.d.ts.map +1 -0
- package/dist/data/readinessStore.js +25 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/initialize.d.ts +11 -0
- package/dist/initialize.d.ts.map +1 -0
- package/dist/initialize.js +16 -0
- package/dist/types/aggregator.d.ts +11 -0
- package/dist/types/aggregator.d.ts.map +1 -0
- package/dist/types/aggregator.js +1 -0
- package/dist/types/bridgeInput.d.ts +32 -0
- package/dist/types/bridgeInput.d.ts.map +1 -0
- package/dist/types/bridgeInput.js +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/utils.d.ts +32 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +41 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# @1delta/trade-sdk
|
|
2
|
+
|
|
3
|
+
A TypeScript SDK for token swaps and bridge operations.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @1delta/trade-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- Token swaps
|
|
14
|
+
- Bridge operations
|
|
15
|
+
- Support for multiple DEX aggregators and bridges
|
|
16
|
+
- Type-safe API with TypeScript support
|
|
17
|
+
|
|
18
|
+
## Basic Usage
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { initialize, fetchBridgeTrade, fetchAggregatorTrade } from '@1delta/trade-sdk';
|
|
22
|
+
import { WalletClient } from 'viem';
|
|
23
|
+
|
|
24
|
+
// Initialize the SDK
|
|
25
|
+
await initialize({
|
|
26
|
+
isProductionEnv: true,
|
|
27
|
+
loadChainData: true,
|
|
28
|
+
loadSquidData: true,
|
|
29
|
+
load1deltaConfigs: true
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Set up wallet client
|
|
33
|
+
const walletClient: WalletClient = /* your wallet client */;
|
|
34
|
+
setWalletClient(walletClient);
|
|
35
|
+
|
|
36
|
+
// Fetch a bridge trade
|
|
37
|
+
const trade = await fetchBridgeTrade(bridge, {
|
|
38
|
+
fromCurrency: fromToken,
|
|
39
|
+
toCurrency: toToken,
|
|
40
|
+
amount: '1000000000000000000', // 1.0 in wei
|
|
41
|
+
receiver: '0x...',
|
|
42
|
+
caller: '0x...',
|
|
43
|
+
slippage: 0.5, // 0.5%
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API
|
|
48
|
+
|
|
49
|
+
### `initialize(config: SdkConfig): Promise<void>`
|
|
50
|
+
|
|
51
|
+
Initializes the SDK with the given configuration.
|
|
52
|
+
|
|
53
|
+
### `setWalletClient(walletClient: WalletClient): void`
|
|
54
|
+
|
|
55
|
+
Sets the wallet client for transaction signing.
|
|
56
|
+
|
|
57
|
+
### `fetchBridgeTrade(bridge: Bridge, input: BridgeInput): Promise<GenericTrade>`
|
|
58
|
+
|
|
59
|
+
Fetches a bridge trade quote.
|
|
60
|
+
|
|
61
|
+
### `fetchAggregatorTrade(aggregator: TradeAggregator, input: AggregatorApiInput): Promise<GenericTrade>`
|
|
62
|
+
|
|
63
|
+
Fetches a trade quote from a DEX aggregator.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './fetchAggregatorTrade';
|
|
2
|
+
import { TradeAggregator } from '@1delta/aggregators';
|
|
3
|
+
import { Bridge } from '@1delta/bridge-configs';
|
|
4
|
+
import { AggregatorApiInput, GenericTrade, OneDeltaInput } from '@1delta/lib-utils';
|
|
5
|
+
export declare const fetchAggregatorTrade: (aggregator: TradeAggregator | Bridge, input: AggregatorApiInput | OneDeltaInput, controller?: AbortController) => Promise<GenericTrade | undefined>;
|
|
6
|
+
//# sourceMappingURL=fetchAggregatorTrade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetchAggregatorTrade.d.ts","sourceRoot":"","sources":["../../src/aggregator/fetchAggregatorTrade.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA;AACtC,OAAO,EAGL,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,MAAM,EAAsB,MAAM,wBAAwB,CAAA;AACnE,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACd,MAAM,mBAAmB,CAAA;AAI1B,eAAO,MAAM,oBAAoB,GAC/B,YAAY,eAAe,GAAG,MAAM,EACpC,OAAO,kBAAkB,GAAG,aAAa,EACzC,aAAa,eAAe,KAC3B,OAAO,CAAC,YAAY,GAAG,SAAS,CAgBlC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from './fetchAggregatorTrade';
|
|
2
|
+
import { fetchAggregatorTrade as fetchAggregatorTradeWithoutConfigs, getAvailableAggregators, } from '@1delta/aggregators';
|
|
3
|
+
import { getSwapAggregators } from '@1delta/bridge-configs';
|
|
4
|
+
import { fetchBridgeTrade } from '../bridge';
|
|
5
|
+
export const fetchAggregatorTrade = async (aggregator, input, controller) => {
|
|
6
|
+
if (!getAvailableAggregators(input.chainId))
|
|
7
|
+
return undefined;
|
|
8
|
+
if (getSwapAggregators().includes(aggregator)) {
|
|
9
|
+
return await fetchBridgeTrade(aggregator, { ...input, order: 'CHEAPEST' }, controller);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
return await fetchAggregatorTradeWithoutConfigs(aggregator, input, controller);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getAvailableAggregators.d.ts","sourceRoot":"","sources":["../../src/aggregator/getAvailableAggregators.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,uBAAuB,GAAI,SAAS,MAAM,KAAG,MAAM,EAK/D,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { getAvailableAggregators as getAvailableAggregatorsWithoutBridge } from '@1delta/aggregators';
|
|
2
|
+
import { Bridge } from '@1delta/bridge-configs';
|
|
3
|
+
import { SupportedChainId } from '@1delta/lib-utils';
|
|
4
|
+
const TRADE_AGGREGATORS_FROM_BRIDGE_PER_CHAIN = {
|
|
5
|
+
[SupportedChainId.MOONBEAM]: [Bridge.Zenlink],
|
|
6
|
+
};
|
|
7
|
+
export const getAvailableAggregators = (chainId) => {
|
|
8
|
+
const tradeAggregators = getAvailableAggregatorsWithoutBridge(chainId) ?? [];
|
|
9
|
+
const bridgeAggregators = TRADE_AGGREGATORS_FROM_BRIDGE_PER_CHAIN[chainId] ?? [];
|
|
10
|
+
return [...tradeAggregators, ...bridgeAggregators];
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/aggregator/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Bridge } from '@1delta/bridge-configs';
|
|
2
|
+
import { GenericTrade } from '@1delta/lib-utils';
|
|
3
|
+
import { BridgeInput } from '../types';
|
|
4
|
+
export declare const fetchBridgeTrade: (bridge: Bridge, input: BridgeInput, controller?: AbortController) => Promise<GenericTrade | undefined>;
|
|
5
|
+
//# sourceMappingURL=fetchBridgeTrade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetchBridgeTrade.d.ts","sourceRoot":"","sources":["../../src/bridge/fetchBridgeTrade.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAU/C,OAAO,EAKL,YAAY,EAWb,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAEtC,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,MAAM,EACd,OAAO,WAAW,EAClB,aAAa,eAAe,KAC3B,OAAO,CAAC,YAAY,GAAG,SAAS,CAiMlC,CAAA"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { convertRawAmount } from '@1delta/aggregators';
|
|
2
|
+
import { Bridge } from '@1delta/bridge-configs';
|
|
3
|
+
import { buildTransactionData, getQuote, getRoute, getStatus, } from '@1delta/bridge-core';
|
|
4
|
+
import { ChainType, ChainUtils, CurrencyHandler, isDirectlyPermittable, NATIVE_PLACEHOLDER, PermitShared, TradeType, } from '@1delta/lib-utils';
|
|
5
|
+
export const fetchBridgeTrade = async (bridge, input, controller) => {
|
|
6
|
+
const inputSlippage = input.slippage;
|
|
7
|
+
const fromChain = input.fromCurrency.chainId;
|
|
8
|
+
const fromCurrencyAddress = CurrencyHandler.isNative(input.fromCurrency) &&
|
|
9
|
+
!ChainUtils.isFuel(fromChain)
|
|
10
|
+
? NATIVE_PLACEHOLDER
|
|
11
|
+
: CurrencyHandler.wrappedAddress(input.fromCurrency);
|
|
12
|
+
const fromCurrencyDecimals = input.fromCurrency.decimals;
|
|
13
|
+
const toChain = input.toCurrency.chainId;
|
|
14
|
+
const toCurrencyAddress = CurrencyHandler.isNative(input.toCurrency) && !ChainUtils.isFuel(toChain)
|
|
15
|
+
? NATIVE_PLACEHOLDER
|
|
16
|
+
: CurrencyHandler.wrappedAddress(input.toCurrency);
|
|
17
|
+
const toCurrencyDecimals = input.toCurrency.decimals;
|
|
18
|
+
const caller = input.caller;
|
|
19
|
+
const receiver = input.receiver;
|
|
20
|
+
const amount = input.swapAmount;
|
|
21
|
+
const slippage = input.slippage;
|
|
22
|
+
const canDirectlyPermit = isDirectlyPermittable(input.fromCurrency);
|
|
23
|
+
const params = {
|
|
24
|
+
fromChainId: fromChain,
|
|
25
|
+
fromAmount: amount,
|
|
26
|
+
fromTokenAddress: fromCurrencyAddress,
|
|
27
|
+
fromTokenDecimals: fromCurrencyDecimals,
|
|
28
|
+
toChainId: toChain,
|
|
29
|
+
toTokenAddress: toCurrencyAddress,
|
|
30
|
+
toTokenDecimals: toCurrencyDecimals,
|
|
31
|
+
fromAddress: caller,
|
|
32
|
+
toAddress: receiver,
|
|
33
|
+
slippage,
|
|
34
|
+
permitEnabled: input.usePermit,
|
|
35
|
+
message: input.message,
|
|
36
|
+
canDirectlyPermit,
|
|
37
|
+
fromHash: undefined,
|
|
38
|
+
referrer: undefined,
|
|
39
|
+
order: input.order,
|
|
40
|
+
destinationGasLimit: input.destinationGasLimit,
|
|
41
|
+
};
|
|
42
|
+
const route = ChainUtils.isAddress(caller, fromChain) &&
|
|
43
|
+
ChainUtils.isAddress(receiver, toChain)
|
|
44
|
+
? await getRoute(bridge, params, controller?.signal)
|
|
45
|
+
: await getQuote(bridge, params, controller?.signal);
|
|
46
|
+
if (route?.code)
|
|
47
|
+
throw new Error(`${route?.code}: ${route?.message}`);
|
|
48
|
+
const trade = getTradeFromBridgeApi(bridge, route, input.swapAmount, input.fromCurrency, input.toCurrency, input.tradeType, inputSlippage);
|
|
49
|
+
if (!trade)
|
|
50
|
+
return undefined;
|
|
51
|
+
const refresh = async (inputOverride) => {
|
|
52
|
+
const newAggregatorInput = {
|
|
53
|
+
...input,
|
|
54
|
+
slippage: inputOverride?.slippage ?? input.slippage,
|
|
55
|
+
};
|
|
56
|
+
return fetchBridgeTrade(bridge, newAggregatorInput);
|
|
57
|
+
};
|
|
58
|
+
if (route?.orderData?.broadcastIntent) {
|
|
59
|
+
const order = {
|
|
60
|
+
dataToSign: route.orderData.typedData
|
|
61
|
+
? {
|
|
62
|
+
typedData: route.orderData.typedData,
|
|
63
|
+
chainId: fromChain,
|
|
64
|
+
}
|
|
65
|
+
: undefined,
|
|
66
|
+
broadcastIntent: async (orderSignature, permitData) => {
|
|
67
|
+
if (!route.orderData)
|
|
68
|
+
throw new Error('no order data');
|
|
69
|
+
if (permitData) {
|
|
70
|
+
const { v, r, s } = PermitShared.splitSignatureToVRS(permitData.permitSignature);
|
|
71
|
+
const erc20Permit = {
|
|
72
|
+
value: permitData.permitValue,
|
|
73
|
+
deadline: permitData.permitDeadline,
|
|
74
|
+
v: Number(v),
|
|
75
|
+
r,
|
|
76
|
+
s,
|
|
77
|
+
};
|
|
78
|
+
await route.orderData.broadcastIntent(orderSignature, erc20Permit);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const { orderId } = await route.orderData.broadcastIntent(orderSignature);
|
|
82
|
+
if (orderId)
|
|
83
|
+
route.interfaceParamData = { orderId };
|
|
84
|
+
}
|
|
85
|
+
return { success: true };
|
|
86
|
+
},
|
|
87
|
+
trackIntent: async () => {
|
|
88
|
+
// Check for 30 seconds
|
|
89
|
+
const maxAttempts = 30;
|
|
90
|
+
const delayMs = 1000;
|
|
91
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
92
|
+
const status = await getStatus(bridge, params, route.interfaceParamData);
|
|
93
|
+
if (status?.fromHash) {
|
|
94
|
+
const txTrackingInputs = {
|
|
95
|
+
[ChainType.EVM]: {
|
|
96
|
+
chainId: params.fromChainId,
|
|
97
|
+
hash: status.fromHash,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
return txTrackingInputs;
|
|
101
|
+
}
|
|
102
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
103
|
+
}
|
|
104
|
+
throw new Error('Failed to retrieve transaction hash after 30 seconds');
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
return {
|
|
108
|
+
...trade,
|
|
109
|
+
order,
|
|
110
|
+
refresh,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const assemble = !ChainUtils.isAddress(caller, fromChain) ||
|
|
115
|
+
!ChainUtils.isAddress(receiver, toChain)
|
|
116
|
+
? undefined
|
|
117
|
+
: async () => {
|
|
118
|
+
try {
|
|
119
|
+
const tx = route?.transactionData ??
|
|
120
|
+
(await buildTransactionData(bridge, params, route?.interfaceParamData));
|
|
121
|
+
if (ChainUtils.isEvm(fromChain)) {
|
|
122
|
+
const validTx = validateEVMBridgeTx(route, tx);
|
|
123
|
+
return {
|
|
124
|
+
[ChainType.EVM]: {
|
|
125
|
+
calldata: validTx.data,
|
|
126
|
+
value: validTx.value,
|
|
127
|
+
to: validTx.to,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
else if (ChainUtils.isFuel(fromChain)) {
|
|
132
|
+
if (!tx?.data)
|
|
133
|
+
throw new Error('Missing Fuel transaction data');
|
|
134
|
+
return {
|
|
135
|
+
[ChainType.FUEL]: {
|
|
136
|
+
calldata: tx.data,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
console.log(`cannot compose ${bridge.toString()} bridge tx:`, error);
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
return {
|
|
148
|
+
...trade,
|
|
149
|
+
assemble,
|
|
150
|
+
refresh,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const getTradeFromBridgeApi = (bridge, data, amount, fromToken, toToken, tradeType, slippage) => {
|
|
155
|
+
if (!data ||
|
|
156
|
+
!fromToken ||
|
|
157
|
+
!toToken ||
|
|
158
|
+
!amount ||
|
|
159
|
+
slippage === undefined ||
|
|
160
|
+
BigInt(data.toAmount) <= 0n)
|
|
161
|
+
return undefined;
|
|
162
|
+
return {
|
|
163
|
+
tradeType: tradeType || TradeType.EXACT_INPUT,
|
|
164
|
+
inputAmount: CurrencyHandler.fromRawAmount(fromToken, amount),
|
|
165
|
+
outputAmount: CurrencyHandler.fromRawAmount(toToken, data.toAmount),
|
|
166
|
+
aggregator: bridge,
|
|
167
|
+
target: data.transactionData?.to ?? data.depositContract,
|
|
168
|
+
approvalTarget: data.depositContract,
|
|
169
|
+
crossChainParams: data.interfaceParamData,
|
|
170
|
+
stringified: `${amount}-${fromToken.chainId}-${fromToken.symbol}->${data.toAmount}-${toToken.chainId}-${toToken.symbol}-${bridge}`,
|
|
171
|
+
inputAmountRealized: convertRawAmount(amount, fromToken.decimals),
|
|
172
|
+
outputAmountRealized: convertRawAmount(data.toAmount, toToken.decimals),
|
|
173
|
+
estimatedDuration: data.estimatedDuration,
|
|
174
|
+
skipApprove: bridge === Bridge.LAYERSWAP,
|
|
175
|
+
gasAmount: safeBigInt(data.fee.destinationGasFee ?? ''),
|
|
176
|
+
slippage,
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
const validateEVMBridgeTx = (route, tx) => {
|
|
180
|
+
if (!route)
|
|
181
|
+
throw new Error('no data');
|
|
182
|
+
if (!tx)
|
|
183
|
+
throw new Error('no tx');
|
|
184
|
+
if (tx?.code)
|
|
185
|
+
throw new Error(`${tx.code}: ${tx?.message}`);
|
|
186
|
+
return tx;
|
|
187
|
+
};
|
|
188
|
+
const safeBigInt = (value) => {
|
|
189
|
+
try {
|
|
190
|
+
return BigInt(value);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './fetchBridgeTrade';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RawCurrency } from '@1delta/lib-utils';
|
|
2
|
+
interface AcrossRouteResponse {
|
|
3
|
+
originChainId: number;
|
|
4
|
+
originToken: string;
|
|
5
|
+
destinationChainId: number;
|
|
6
|
+
destinationToken: string;
|
|
7
|
+
originTokenSymbol: string;
|
|
8
|
+
destinationTokenSymbol: string;
|
|
9
|
+
isNative: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare const fetchAcrossRoutes: (fromChainId: string, toChainId: string) => Promise<AcrossRouteResponse[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Enhanced route selection with clearer priority logic
|
|
14
|
+
*/
|
|
15
|
+
export declare const selectAcrossRoute: (routes: AcrossRouteResponse[], fromCurrency: RawCurrency, toCurrency: RawCurrency) => AcrossRouteResponse | undefined;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=acrossRoutes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acrossRoutes.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/across/acrossRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEhE,UAAU,mBAAmB;IAC3B,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,gBAAgB,EAAE,MAAM,CAAA;IACxB,iBAAiB,EAAE,MAAM,CAAA;IACzB,sBAAsB,EAAE,MAAM,CAAA;IAC9B,QAAQ,EAAE,OAAO,CAAA;CAClB;AAKD,eAAO,MAAM,iBAAiB,GAC5B,aAAa,MAAM,EACnB,WAAW,MAAM,KAChB,OAAO,CAAC,mBAAmB,EAAE,CAK/B,CAAA;AA4DD;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,mBAAmB,EAAE,EAC7B,cAAc,WAAW,EACzB,YAAY,WAAW,KACtB,mBAAmB,GAAG,SAyBxB,CAAA"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { CurrencyHandler } from '@1delta/lib-utils';
|
|
2
|
+
const getRouteURL = (fromChainId, toChainId) => `https://app.across.to/api/available-routes?originChainId=${fromChainId}&destinationChainId=${toChainId}`;
|
|
3
|
+
export const fetchAcrossRoutes = async (fromChainId, toChainId) => {
|
|
4
|
+
const url = getRouteURL(fromChainId, toChainId);
|
|
5
|
+
const response = await fetch(url);
|
|
6
|
+
const data = await response.json();
|
|
7
|
+
return data;
|
|
8
|
+
};
|
|
9
|
+
const PRIORITY_STABLE_SYMBOLS = ['USDC', 'USDC.e', 'USDT'];
|
|
10
|
+
/**
|
|
11
|
+
* Improved route selection with priority-based matching
|
|
12
|
+
*/
|
|
13
|
+
const findDestinationMatch = (routes, fromCurrency, toCurrency) => {
|
|
14
|
+
const destinationRoutes = routes.filter((route) => route.destinationToken.toLowerCase() ===
|
|
15
|
+
CurrencyHandler.wrapped(toCurrency).address.toLowerCase());
|
|
16
|
+
return destinationRoutes.find((route) => {
|
|
17
|
+
if (CurrencyHandler.isNative(fromCurrency))
|
|
18
|
+
return route.isNative;
|
|
19
|
+
return !route.isNative;
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const findSourceMatch = (routes, fromCurrency) => {
|
|
23
|
+
return routes.find((route) => (route.originToken.toLowerCase() === fromCurrency.address.toLowerCase() &&
|
|
24
|
+
!route.isNative) ||
|
|
25
|
+
(route.isNative && CurrencyHandler.isNative(fromCurrency)));
|
|
26
|
+
};
|
|
27
|
+
const findStableMatch = (routes, toCurrency) => {
|
|
28
|
+
if (!toCurrency.symbol?.includes('USD'))
|
|
29
|
+
return undefined;
|
|
30
|
+
for (const symbol of PRIORITY_STABLE_SYMBOLS) {
|
|
31
|
+
const stableRoute = routes.find((route) => route.originTokenSymbol.includes(symbol));
|
|
32
|
+
if (stableRoute)
|
|
33
|
+
return stableRoute;
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
};
|
|
37
|
+
const findNativeMatch = (routes) => {
|
|
38
|
+
return routes.find((route) => route.originTokenSymbol === 'WETH' && !route.isNative);
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Enhanced route selection with clearer priority logic
|
|
42
|
+
*/
|
|
43
|
+
export const selectAcrossRoute = (routes, fromCurrency, toCurrency) => {
|
|
44
|
+
if (routes.length === 0)
|
|
45
|
+
return undefined;
|
|
46
|
+
// Priority 1: Exact destination match
|
|
47
|
+
const destinationMatch = findDestinationMatch(routes, fromCurrency, toCurrency);
|
|
48
|
+
if (destinationMatch)
|
|
49
|
+
return destinationMatch;
|
|
50
|
+
// Priority 2: Exact source match
|
|
51
|
+
const sourceMatch = findSourceMatch(routes, fromCurrency);
|
|
52
|
+
if (sourceMatch)
|
|
53
|
+
return sourceMatch;
|
|
54
|
+
// Priority 3: Stable coin preference for USD targets
|
|
55
|
+
const stableMatch = findStableMatch(routes, toCurrency);
|
|
56
|
+
if (stableMatch)
|
|
57
|
+
return stableMatch;
|
|
58
|
+
// Priority 4: Native/WETH fallback
|
|
59
|
+
const nativeMatch = findNativeMatch(routes);
|
|
60
|
+
if (nativeMatch)
|
|
61
|
+
return nativeMatch;
|
|
62
|
+
// Fallback to first available
|
|
63
|
+
return routes[0];
|
|
64
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GenericTrade, RawCurrency } from '@1delta/lib-utils';
|
|
2
|
+
import { BridgeInput } from '../../types';
|
|
3
|
+
export interface AcrossWithSwapInput extends BridgeInput {
|
|
4
|
+
bridgeToCurrency: RawCurrency | undefined;
|
|
5
|
+
}
|
|
6
|
+
export declare const fetchAcrossTradeWithSwap: (input: AcrossWithSwapInput, controller?: AbortController) => Promise<{
|
|
7
|
+
trade: GenericTrade | undefined;
|
|
8
|
+
receiver: string;
|
|
9
|
+
}>;
|
|
10
|
+
export default fetchAcrossTradeWithSwap;
|
|
11
|
+
//# sourceMappingURL=acrossWithSwap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acrossWithSwap.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/across/acrossWithSwap.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,YAAY,EAKZ,WAAW,EAEZ,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAA;AAO1D,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACtD,gBAAgB,EAAE,WAAW,GAAG,SAAS,CAAA;CAC1C;AAED,eAAO,MAAM,wBAAwB,GACnC,OAAO,mBAAmB,EAC1B,aAAa,eAAe,KAC3B,OAAO,CAAC;IAAE,KAAK,EAAE,YAAY,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CA6C/D,CAAA;AAED,eAAe,wBAAwB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=acrossWithSwap.integration.spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acrossWithSwap.integration.spec.d.ts","sourceRoot":"","sources":["../../../src/composedTrades/across/acrossWithSwap.integration.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// import { ChainId, Percent, TradeType } from '@1delta/base-sdk'
|
|
3
|
+
// import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
4
|
+
// import { USDC_ON } from '@/lib/constants/addresses'
|
|
5
|
+
// import { getAcrossMulticallHandler } from '@/lib/constants/addresses/multicall/across'
|
|
6
|
+
// import { CurrencyHandler } from '@/lib/services/currencyUtils'
|
|
7
|
+
// import { nativeOnChain } from '@/lib/services/tokens'
|
|
8
|
+
// import { RawCurrency } from '@/lib/types'
|
|
9
|
+
// import fetchAcrossTradeWithSwap, { AcrossWithSwapInput } from './acrossWithSwap'
|
|
10
|
+
// describe('fetchAcrossTradeWithSwap', () => {
|
|
11
|
+
// beforeEach(() => {
|
|
12
|
+
// vi.clearAllMocks()
|
|
13
|
+
// })
|
|
14
|
+
// const ACCOUNT = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'
|
|
15
|
+
// const WBTC_OP: RawCurrency = {
|
|
16
|
+
// chainId: ChainId.OP_MAINNET,
|
|
17
|
+
// address: '0x68f180fcCe6836688e9084f035309E29Bf0A2095',
|
|
18
|
+
// decimals: 8,
|
|
19
|
+
// symbol: 'WBTC',
|
|
20
|
+
// name: 'Wrapped BTC',
|
|
21
|
+
// }
|
|
22
|
+
// it('Bridge Native', async () => {
|
|
23
|
+
// // Receive Native only if receiver address is EOA
|
|
24
|
+
// const fromCurrency = nativeOnChain(ChainId.ARBITRUM_ONE)
|
|
25
|
+
// const toCurrency = nativeOnChain(ChainId.OP_MAINNET)
|
|
26
|
+
// const bridgeToCurrency = CurrencyHandler.wrapped(toCurrency)
|
|
27
|
+
// const input: AcrossWithSwapInput = {
|
|
28
|
+
// tradeType: TradeType.EXACT_INPUT,
|
|
29
|
+
// fromCurrency,
|
|
30
|
+
// bridgeToCurrency,
|
|
31
|
+
// toCurrency,
|
|
32
|
+
// slippage: 1,
|
|
33
|
+
// swapAmount: '1000000000000000000',
|
|
34
|
+
// caller: ACCOUNT,
|
|
35
|
+
// receiver: ACCOUNT,
|
|
36
|
+
// order: 'FASTEST',
|
|
37
|
+
// }
|
|
38
|
+
// const { trade: result, receiver } = await fetchAcrossTradeWithSwap(input)
|
|
39
|
+
// console.log('result', result, receiver)
|
|
40
|
+
// expect(result).toBeDefined()
|
|
41
|
+
// expect(result?.inputAmount.currency).toEqual(fromCurrency)
|
|
42
|
+
// expect(result?.outputAmount.currency).toEqual(toCurrency)
|
|
43
|
+
// expect(receiver).toEqual(ACCOUNT)
|
|
44
|
+
// expect(result?.crossChainParams?.message).toBeUndefined()
|
|
45
|
+
// })
|
|
46
|
+
// it('Bridge Native -> WETH', async () => {
|
|
47
|
+
// // Receive Wrapped Native only if receiver address is contract
|
|
48
|
+
// const fromCurrency = nativeOnChain(ChainId.ARBITRUM_ONE)
|
|
49
|
+
// const toCurrency = CurrencyHandler.wrapped(
|
|
50
|
+
// nativeOnChain(ChainId.OP_MAINNET)
|
|
51
|
+
// )
|
|
52
|
+
// const input: AcrossWithSwapInput = {
|
|
53
|
+
// tradeType: TradeType.EXACT_INPUT,
|
|
54
|
+
// fromCurrency,
|
|
55
|
+
// bridgeToCurrency: toCurrency,
|
|
56
|
+
// toCurrency,
|
|
57
|
+
// slippage: 1,
|
|
58
|
+
// swapAmount: '1000000000000000000',
|
|
59
|
+
// caller: ACCOUNT,
|
|
60
|
+
// receiver: ACCOUNT,
|
|
61
|
+
// order: 'FASTEST',
|
|
62
|
+
// }
|
|
63
|
+
// const { trade: result, receiver } = await fetchAcrossTradeWithSwap(input)
|
|
64
|
+
// console.log('result', result, receiver)
|
|
65
|
+
// expect(result).toBeDefined()
|
|
66
|
+
// expect(result?.inputAmount.currency).toEqual(fromCurrency)
|
|
67
|
+
// expect(result?.outputAmount.currency).toEqual(toCurrency)
|
|
68
|
+
// expect(receiver).toEqual(getAcrossMulticallHandler(ChainId.OP_MAINNET))
|
|
69
|
+
// expect(result?.crossChainParams?.message).toBeDefined()
|
|
70
|
+
// })
|
|
71
|
+
// it('Bridge USDC', async () => {
|
|
72
|
+
// const fromCurrency = USDC_ON(ChainId.ARBITRUM_ONE)
|
|
73
|
+
// const toCurrency = USDC_ON(ChainId.OP_MAINNET)
|
|
74
|
+
// const input: AcrossWithSwapInput = {
|
|
75
|
+
// tradeType: TradeType.EXACT_INPUT,
|
|
76
|
+
// fromCurrency,
|
|
77
|
+
// bridgeToCurrency: toCurrency,
|
|
78
|
+
// toCurrency,
|
|
79
|
+
// slippage: 1,
|
|
80
|
+
// swapAmount: '1000000',
|
|
81
|
+
// caller: ACCOUNT,
|
|
82
|
+
// receiver: ACCOUNT,
|
|
83
|
+
// order: 'FASTEST',
|
|
84
|
+
// }
|
|
85
|
+
// const { trade: result, receiver } = await fetchAcrossTradeWithSwap(input)
|
|
86
|
+
// console.log('result', result, receiver)
|
|
87
|
+
// expect(result).toBeDefined()
|
|
88
|
+
// expect(result?.inputAmount.currency).toEqual(fromCurrency)
|
|
89
|
+
// expect(result?.outputAmount.currency).toEqual(toCurrency)
|
|
90
|
+
// expect(receiver).toEqual(ACCOUNT)
|
|
91
|
+
// expect(result?.crossChainParams?.message).toBeUndefined()
|
|
92
|
+
// })
|
|
93
|
+
// it('Bridge + Swap', async () => {
|
|
94
|
+
// const fromCurrency = USDC_ON(ChainId.ARBITRUM_ONE)
|
|
95
|
+
// const bridgeToCurrency = USDC_ON(ChainId.OP_MAINNET)
|
|
96
|
+
// const toCurrency = WBTC_OP
|
|
97
|
+
// const input: AcrossWithSwapInput = {
|
|
98
|
+
// tradeType: TradeType.EXACT_INPUT,
|
|
99
|
+
// fromCurrency,
|
|
100
|
+
// bridgeToCurrency,
|
|
101
|
+
// toCurrency,
|
|
102
|
+
// slippage: 1,
|
|
103
|
+
// swapAmount: '1000000',
|
|
104
|
+
// caller: ACCOUNT,
|
|
105
|
+
// receiver: ACCOUNT,
|
|
106
|
+
// order: 'FASTEST',
|
|
107
|
+
// }
|
|
108
|
+
// const { trade: result, receiver } = await fetchAcrossTradeWithSwap(input)
|
|
109
|
+
// console.log('result', result, receiver)
|
|
110
|
+
// expect(result).toBeDefined()
|
|
111
|
+
// expect(result?.inputAmount.currency).toEqual(fromCurrency)
|
|
112
|
+
// expect(result?.outputAmount.currency).toEqual(toCurrency)
|
|
113
|
+
// expect(receiver).toEqual(getAcrossMulticallHandler(ChainId.OP_MAINNET))
|
|
114
|
+
// expect(result?.crossChainParams?.message).toBeDefined()
|
|
115
|
+
// })
|
|
116
|
+
// }, 20000)
|