@rabby-wallet/rabby-bridge 0.0.13-alpha.0 → 0.0.13

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 (198) hide show
  1. package/README.md +1 -131
  2. package/dist/chains.d.ts +2 -1
  3. package/dist/chains.js +2 -0
  4. package/dist/data.d.ts +3 -0
  5. package/dist/data.js +3 -0
  6. package/dist/index.d.ts +1 -7
  7. package/dist/index.js +0 -3
  8. package/dist/quote.d.ts +4 -18
  9. package/dist/quote.js +65 -282
  10. package/package.json +3 -13
  11. package/dist/calldata/abi.d.ts +0 -29
  12. package/dist/calldata/abi.js +0 -160
  13. package/dist/calldata/across/deposit.d.ts +0 -2
  14. package/dist/calldata/across/deposit.js +0 -36
  15. package/dist/calldata/across/depositNative.d.ts +0 -2
  16. package/dist/calldata/across/depositNative.js +0 -45
  17. package/dist/calldata/across/depositNow.d.ts +0 -2
  18. package/dist/calldata/across/depositNow.js +0 -35
  19. package/dist/calldata/across/depositV3.d.ts +0 -2
  20. package/dist/calldata/across/depositV3.js +0 -35
  21. package/dist/calldata/across/depositV3Now.d.ts +0 -2
  22. package/dist/calldata/across/depositV3Now.js +0 -34
  23. package/dist/calldata/across/index.d.ts +0 -4
  24. package/dist/calldata/across/index.js +0 -31
  25. package/dist/calldata/across/swapAndBridge.d.ts +0 -2
  26. package/dist/calldata/across/swapAndBridge.js +0 -70
  27. package/dist/calldata/across/validate.d.ts +0 -3
  28. package/dist/calldata/across/validate.js +0 -30
  29. package/dist/calldata/chains.d.ts +0 -2
  30. package/dist/calldata/chains.js +0 -35
  31. package/dist/calldata/destination.d.ts +0 -6
  32. package/dist/calldata/destination.js +0 -148
  33. package/dist/calldata/diagnostics.d.ts +0 -4
  34. package/dist/calldata/diagnostics.js +0 -18
  35. package/dist/calldata/expect.d.ts +0 -25
  36. package/dist/calldata/expect.js +0 -129
  37. package/dist/calldata/hex.d.ts +0 -6
  38. package/dist/calldata/hex.js +0 -46
  39. package/dist/calldata/index.d.ts +0 -20
  40. package/dist/calldata/index.js +0 -85
  41. package/dist/calldata/lifi/across/acrossV4Erc20Min.d.ts +0 -2
  42. package/dist/calldata/lifi/across/acrossV4Erc20Min.js +0 -26
  43. package/dist/calldata/lifi/across/acrossV4NativeMin.d.ts +0 -2
  44. package/dist/calldata/lifi/across/acrossV4NativeMin.js +0 -22
  45. package/dist/calldata/lifi/across/index.d.ts +0 -6
  46. package/dist/calldata/lifi/across/index.js +0 -19
  47. package/dist/calldata/lifi/allbridge/index.d.ts +0 -3
  48. package/dist/calldata/lifi/allbridge/index.js +0 -26
  49. package/dist/calldata/lifi/celer/index.d.ts +0 -4
  50. package/dist/calldata/lifi/celer/index.js +0 -10
  51. package/dist/calldata/lifi/centrifuge/index.d.ts +0 -3
  52. package/dist/calldata/lifi/centrifuge/index.js +0 -22
  53. package/dist/calldata/lifi/frax/index.d.ts +0 -4
  54. package/dist/calldata/lifi/frax/index.js +0 -29
  55. package/dist/calldata/lifi/garden/index.d.ts +0 -3
  56. package/dist/calldata/lifi/garden/index.js +0 -22
  57. package/dist/calldata/lifi/gaszip/index.d.ts +0 -6
  58. package/dist/calldata/lifi/gaszip/index.js +0 -15
  59. package/dist/calldata/lifi/index.d.ts +0 -4
  60. package/dist/calldata/lifi/index.js +0 -60
  61. package/dist/calldata/lifi/intents/index.d.ts +0 -4
  62. package/dist/calldata/lifi/intents/index.js +0 -10
  63. package/dist/calldata/lifi/layerswap/index.d.ts +0 -4
  64. package/dist/calldata/lifi/layerswap/index.js +0 -10
  65. package/dist/calldata/lifi/m0/index.d.ts +0 -3
  66. package/dist/calldata/lifi/m0/index.js +0 -33
  67. package/dist/calldata/lifi/mayan/index.d.ts +0 -4
  68. package/dist/calldata/lifi/mayan/index.js +0 -10
  69. package/dist/calldata/lifi/method.d.ts +0 -6
  70. package/dist/calldata/lifi/method.js +0 -16
  71. package/dist/calldata/lifi/native/index.d.ts +0 -4
  72. package/dist/calldata/lifi/native/index.js +0 -80
  73. package/dist/calldata/lifi/params.d.ts +0 -30
  74. package/dist/calldata/lifi/params.js +0 -370
  75. package/dist/calldata/lifi/paxos/index.d.ts +0 -4
  76. package/dist/calldata/lifi/paxos/index.js +0 -10
  77. package/dist/calldata/lifi/polymer/index.d.ts +0 -4
  78. package/dist/calldata/lifi/polymer/index.js +0 -10
  79. package/dist/calldata/lifi/relay/index.d.ts +0 -6
  80. package/dist/calldata/lifi/relay/index.js +0 -15
  81. package/dist/calldata/lifi/shape.d.ts +0 -4
  82. package/dist/calldata/lifi/shape.js +0 -31
  83. package/dist/calldata/lifi/squid/index.d.ts +0 -6
  84. package/dist/calldata/lifi/squid/index.js +0 -15
  85. package/dist/calldata/lifi/stargate/index.d.ts +0 -5
  86. package/dist/calldata/lifi/stargate/index.js +0 -15
  87. package/dist/calldata/lifi/swap/index.d.ts +0 -5
  88. package/dist/calldata/lifi/swap/index.js +0 -18
  89. package/dist/calldata/lifi/swap/swapMethod.d.ts +0 -2
  90. package/dist/calldata/lifi/swap/swapMethod.js +0 -40
  91. package/dist/calldata/match.d.ts +0 -3
  92. package/dist/calldata/match.js +0 -21
  93. package/dist/calldata/mayan/destination.d.ts +0 -2
  94. package/dist/calldata/mayan/destination.js +0 -13
  95. package/dist/calldata/mayan/fastMctpBridge.d.ts +0 -3
  96. package/dist/calldata/mayan/fastMctpBridge.js +0 -43
  97. package/dist/calldata/mayan/fastMctpCreateOrder.d.ts +0 -3
  98. package/dist/calldata/mayan/fastMctpCreateOrder.js +0 -39
  99. package/dist/calldata/mayan/forward.d.ts +0 -8
  100. package/dist/calldata/mayan/forward.js +0 -35
  101. package/dist/calldata/mayan/forwardERC20.d.ts +0 -2
  102. package/dist/calldata/mayan/forwardERC20.js +0 -19
  103. package/dist/calldata/mayan/forwardEth.d.ts +0 -2
  104. package/dist/calldata/mayan/forwardEth.js +0 -16
  105. package/dist/calldata/mayan/index.d.ts +0 -4
  106. package/dist/calldata/mayan/index.js +0 -21
  107. package/dist/calldata/mayan/mctp.d.ts +0 -5
  108. package/dist/calldata/mayan/mctp.js +0 -41
  109. package/dist/calldata/mayan/readProtocol.d.ts +0 -2
  110. package/dist/calldata/mayan/readProtocol.js +0 -29
  111. package/dist/calldata/mayan/swapAndForwardERC20.d.ts +0 -2
  112. package/dist/calldata/mayan/swapAndForwardERC20.js +0 -24
  113. package/dist/calldata/mayan/swapAndForwardEth.d.ts +0 -2
  114. package/dist/calldata/mayan/swapAndForwardEth.js +0 -23
  115. package/dist/calldata/mayan/swiftCreateOrder.d.ts +0 -3
  116. package/dist/calldata/mayan/swiftCreateOrder.js +0 -49
  117. package/dist/calldata/mayan/validate.d.ts +0 -3
  118. package/dist/calldata/mayan/validate.js +0 -20
  119. package/dist/calldata/protocols.d.ts +0 -9
  120. package/dist/calldata/protocols.js +0 -56
  121. package/dist/calldata/relay/calls.d.ts +0 -13
  122. package/dist/calldata/relay/calls.js +0 -54
  123. package/dist/calldata/relay/depositErc20.d.ts +0 -2
  124. package/dist/calldata/relay/depositErc20.js +0 -22
  125. package/dist/calldata/relay/depositErc20Allowance.d.ts +0 -2
  126. package/dist/calldata/relay/depositErc20Allowance.js +0 -20
  127. package/dist/calldata/relay/depositNative.d.ts +0 -2
  128. package/dist/calldata/relay/depositNative.js +0 -20
  129. package/dist/calldata/relay/index.d.ts +0 -4
  130. package/dist/calldata/relay/index.js +0 -40
  131. package/dist/calldata/relay/multicall.d.ts +0 -2
  132. package/dist/calldata/relay/multicall.js +0 -15
  133. package/dist/calldata/relay/permit2TransferAndMulticall.d.ts +0 -2
  134. package/dist/calldata/relay/permit2TransferAndMulticall.js +0 -42
  135. package/dist/calldata/relay/permit3009TransferAndMulticall.d.ts +0 -2
  136. package/dist/calldata/relay/permit3009TransferAndMulticall.js +0 -41
  137. package/dist/calldata/relay/permit3009TransferAndMulticallSigned.d.ts +0 -2
  138. package/dist/calldata/relay/permit3009TransferAndMulticallSigned.js +0 -40
  139. package/dist/calldata/relay/permitTransferAndMulticall.d.ts +0 -2
  140. package/dist/calldata/relay/permitTransferAndMulticall.js +0 -34
  141. package/dist/calldata/relay/permitTransferAndMulticallLegacy.d.ts +0 -2
  142. package/dist/calldata/relay/permitTransferAndMulticallLegacy.js +0 -35
  143. package/dist/calldata/relay/transferAndMulticall.d.ts +0 -2
  144. package/dist/calldata/relay/transferAndMulticall.js +0 -26
  145. package/dist/calldata/relay/validate.d.ts +0 -3
  146. package/dist/calldata/relay/validate.js +0 -18
  147. package/dist/calldata/resolve.d.ts +0 -2
  148. package/dist/calldata/resolve.js +0 -28
  149. package/dist/calldata/socket/bridge.d.ts +0 -2
  150. package/dist/calldata/socket/bridge.js +0 -28
  151. package/dist/calldata/socket/exec.d.ts +0 -2
  152. package/dist/calldata/socket/exec.js +0 -71
  153. package/dist/calldata/socket/index.d.ts +0 -4
  154. package/dist/calldata/socket/index.js +0 -13
  155. package/dist/calldata/socket/params.d.ts +0 -5
  156. package/dist/calldata/socket/params.js +0 -14
  157. package/dist/calldata/socket/protocols/ccip.d.ts +0 -2
  158. package/dist/calldata/socket/protocols/ccip.js +0 -32
  159. package/dist/calldata/socket/protocols/cctp.d.ts +0 -2
  160. package/dist/calldata/socket/protocols/cctp.js +0 -24
  161. package/dist/calldata/socket/protocols/eco.d.ts +0 -2
  162. package/dist/calldata/socket/protocols/eco.js +0 -20
  163. package/dist/calldata/socket/protocols/index.d.ts +0 -3
  164. package/dist/calldata/socket/protocols/index.js +0 -81
  165. package/dist/calldata/socket/protocols/native.d.ts +0 -2
  166. package/dist/calldata/socket/protocols/native.js +0 -70
  167. package/dist/calldata/socket/protocols/oft.d.ts +0 -2
  168. package/dist/calldata/socket/protocols/oft.js +0 -31
  169. package/dist/calldata/socket/protocols/swapsXYZ.d.ts +0 -2
  170. package/dist/calldata/socket/protocols/swapsXYZ.js +0 -62
  171. package/dist/calldata/socket/swapAndBridge.d.ts +0 -2
  172. package/dist/calldata/socket/swapAndBridge.js +0 -37
  173. package/dist/calldata/socket/validate.d.ts +0 -3
  174. package/dist/calldata/socket/validate.js +0 -21
  175. package/dist/calldata/types.d.ts +0 -82
  176. package/dist/calldata/types.js +0 -20
  177. package/dist/errors/constants.d.ts +0 -876
  178. package/dist/errors/constants.js +0 -883
  179. package/dist/errors/index.d.ts +0 -61
  180. package/dist/errors/index.js +0 -53
  181. package/dist/errors/sanitize.d.ts +0 -3
  182. package/dist/errors/sanitize.js +0 -75
  183. package/dist/providers/data.d.ts +0 -23
  184. package/dist/providers/data.js +0 -116
  185. package/dist/providers/errors.d.ts +0 -7
  186. package/dist/providers/errors.js +0 -10
  187. package/dist/providers/index.d.ts +0 -7
  188. package/dist/providers/index.js +0 -340
  189. package/dist/providers/layerswap.d.ts +0 -9
  190. package/dist/providers/layerswap.js +0 -95
  191. package/dist/providers/relay.d.ts +0 -59
  192. package/dist/providers/relay.js +0 -185
  193. package/dist/providers/request.d.ts +0 -23
  194. package/dist/providers/request.js +0 -69
  195. package/dist/providers/socket.d.ts +0 -5
  196. package/dist/providers/socket.js +0 -57
  197. package/dist/providers/types.d.ts +0 -36
  198. package/dist/providers/types.js +0 -1
@@ -1,340 +0,0 @@
1
- import { BRIDGE_ERRORS, BridgeError, asBridgeError } from '../errors/index.js';
2
- import { validateBridgeQuote, validateBridgeTx } from '../quote.js';
3
- import { address, array, assertIntent, bytes, chain, feeDisplay, intentKey, object, sameTransaction, slippageBps, tokenAddress, uint } from './data.js';
4
- import { InvalidBridgeProviderError } from './errors.js';
5
- import { layerSwapOrderRows, layerSwapSequence, readLayerSwapDeposit, readLayerSwapOrder } from './layerswap.js';
6
- import { readRelayQuote, relayChains } from './relay.js';
7
- import { requestProvider } from './request.js';
8
- import { readSocketQuote, SOCKET_PROVIDER_ROUTES, socketBridgeId } from './socket.js';
9
- const FEE_RECIPIENT = '0x9899f62ecf16b70bffc88677023026c47e48c218';
10
- const MAX_CACHE_ENTRIES = 100;
11
- const EXCLUDED_SOCKET_PROVIDERS = [
12
- 'symbiosis', 'symbiosis-btc-citrea', 'synapse', 'celer', 'stargate', 'stargate-v2',
13
- 'arbitrum-bridge', 'mayan', 'across', 'relay', 'near-intents', 'squid',
14
- ];
15
- const feeBps = (params) => {
16
- const percent = params.feeRate ?? 0.25;
17
- const bps = percent * 100;
18
- if (!Number.isFinite(bps) || bps < 0 || bps > 300 || Math.abs(bps - Math.round(bps)) > 1e-8)
19
- throw new BridgeError(BRIDGE_ERRORS.UNSUPPORTED_FEE_RATE);
20
- return Math.round(bps);
21
- };
22
- export const isDirectBridgeProviderRoute = (provider, bridgeId) => provider === 'relay' || (provider === 'socket' && SOCKET_PROVIDER_ROUTES.includes(bridgeId));
23
- const quoteMetadata = (provider, bridgeId) => {
24
- const name = provider === 'relay' ? 'Relay' : 'Socket';
25
- const logo = provider === 'relay'
26
- ? 'https://static.debank.com/image/bridge/logo_url/4acc023e14cf2d02da4c365d3940b15d/4acc023e14cf2d02da4c365d3940b15d.png'
27
- : 'https://media.socket.tech/bridges/socket-icon.png';
28
- return { aggregator: { id: provider, name, logo_url: logo, bridge_list: [] },
29
- bridge: { id: bridgeId, name: { relay: 'Relay', 'rfq-vault-executor': 'Socket Intents',
30
- 'cctp-v2': 'CCTP V2', 'cctp-v2-slow': 'CCTP V2 Slow' }[bridgeId] ?? bridgeId,
31
- logo_url: logo }, bridge_id: bridgeId };
32
- };
33
- // Convert service USD display fees to output-token raw units. These estimates
34
- // never participate in transaction/order comparisons.
35
- const displayOutputFee = (usdValue, output, expectedAmount) => {
36
- const usd = Number(usdValue ?? 0);
37
- const outputUsd = Number(output.amountUsd ?? output.valueInUsd ?? 0);
38
- if (!Number.isFinite(usd) || usd < 0 || !Number.isFinite(outputUsd) || outputUsd < 0)
39
- throw new BridgeError(BRIDGE_ERRORS.INVALID_FEE_DISPLAY);
40
- const feeUnits = Math.round(usd * 1e8), outputUnits = Math.round(outputUsd * 1e8);
41
- const raw = Number.isSafeInteger(feeUnits) && Number.isSafeInteger(outputUnits) && outputUnits > 0
42
- ? expectedAmount * BigInt(feeUnits) / BigInt(outputUnits) : 0n;
43
- return feeDisplay(raw, usd);
44
- };
45
- // Quote/UI number fields are legacy API compatibility only. Comparisons and the
46
- // quote cache always use bigint/raw hex, never these floating-point values.
47
- const makeQuote = (provider, bridgeId, data, decimals) => ({
48
- ...quoteMetadata(provider, bridgeId),
49
- to_token_amount: Number(data.expectedAmount) / 10 ** decimals,
50
- to_token_raw_amount: Number(data.expectedAmount),
51
- to_token_raw_amount_hex_str: `0x${data.expectedAmount.toString(16)}`,
52
- approve_contract_id: data.approveAddress,
53
- quote_key: { provider, order_id: data.orderId, request_id: data.requestId,
54
- to_token_raw_amount: data.expectedAmount.toString() },
55
- gas_fee: feeDisplay('0'), protocol_fee: feeDisplay('0'), rabby_fee: feeDisplay('0'),
56
- duration: 0, routePath: '',
57
- });
58
- export const createBridgeProviderClient = (options) => {
59
- const timeoutMs = options.timeoutMs ?? 15000;
60
- if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 60000)
61
- throw new BridgeError(BRIDGE_ERRORS.INVALID_PROVIDER_TIMEOUT);
62
- const request = options.request;
63
- const socketApi = options.socketApi ?? 'public';
64
- if (socketApi !== 'public' && socketApi !== 'dedicated')
65
- throw new BridgeError(BRIDGE_ERRORS.INVALID_SOCKET_API);
66
- const entries = new Map();
67
- let generation = 0;
68
- let chains;
69
- let chainsRequest;
70
- const readChains = async () => {
71
- if (chains)
72
- return chains;
73
- if (!chainsRequest) {
74
- chainsRequest = requestProvider(request, timeoutMs, 'relay', '/chains')
75
- .then(relayChains).then((value) => (chains = value))
76
- .finally(() => { chainsRequest = undefined; });
77
- }
78
- return chainsRequest;
79
- };
80
- const guard = async (provider, work, context) => {
81
- try {
82
- return await work();
83
- }
84
- catch (error) {
85
- const failure = asBridgeError(error, BRIDGE_ERRORS.INVALID_RESPONSE, { ...context, provider });
86
- if (failure instanceof InvalidBridgeProviderError)
87
- throw failure;
88
- throw new InvalidBridgeProviderError(provider, failure);
89
- }
90
- };
91
- const cacheKey = (provider, fromChainId, orderId) => `${provider}:${provider === 'layerswap' ? `${chain(fromChainId)}:` : ''}${orderId}`;
92
- const save = (provider, params, data, bridgeId, startedGeneration) => {
93
- if (startedGeneration !== generation)
94
- throw new BridgeError(BRIDGE_ERRORS.QUOTE_REQUEST_WAS_INVALIDATED);
95
- assertIntent(data.parsed, params, data.expectedAmount, data.minimumQuantum);
96
- validateBridgeTx(provider === 'layerswap' ? 'lifi' : provider, params.fromChainId, bridgeId, data.tx, {
97
- userAddress: params.userAddress, fromTokenId: params.fromTokenId, fromTokenRawAmount: params.fromTokenRawAmount,
98
- toChainId: params.toChainId, toTokenId: params.toTokenId,
99
- });
100
- if (entries.size >= MAX_CACHE_ENTRIES)
101
- entries.delete(entries.keys().next().value);
102
- entries.set(cacheKey(provider, params.fromChainId, data.orderId), { provider, bridgeId, intent: intentKey(params), data });
103
- };
104
- const store = (provider, params, data, quote, startedGeneration) => {
105
- validateBridgeQuote(provider, params.fromChainId, quote);
106
- save(provider, params, data, quote.bridge_id, startedGeneration);
107
- // No proof/transaction references escape the client cache.
108
- return { ...quote, quote_key: { ...quote.quote_key }, gas_fee: { ...quote.gas_fee },
109
- protocol_fee: { ...quote.protocol_fee }, rabby_fee: { ...quote.rabby_fee } };
110
- };
111
- const layerSwapExpected = (params) => {
112
- if (params.toTokenRawAmount !== undefined)
113
- return uint(params.toTokenRawAmount);
114
- let key = params.quoteKey;
115
- if (typeof key === 'string') {
116
- try {
117
- key = JSON.parse(key);
118
- }
119
- catch {
120
- throw new BridgeError(BRIDGE_ERRORS.INVALID_QUOTE_KEY);
121
- }
122
- }
123
- return uint(object(key).to_token_raw_amount);
124
- };
125
- const entryFor = (provider, params, tx) => {
126
- let orderId;
127
- let requestId;
128
- let quotedAmount = params.toTokenRawAmount;
129
- if (provider === 'layerswap') {
130
- if (!tx)
131
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_TRANSACTION_IS_REQUIRED);
132
- orderId = bytes(readLayerSwapDeposit(tx, params).parsed.orderId, 32);
133
- requestId = orderId;
134
- }
135
- else {
136
- let key = params.quoteKey;
137
- if (typeof key === 'string') {
138
- try {
139
- key = JSON.parse(key);
140
- }
141
- catch {
142
- throw new BridgeError(BRIDGE_ERRORS.INVALID_QUOTE_KEY);
143
- }
144
- }
145
- const quoteKey = object(key);
146
- if (quoteKey.provider !== provider)
147
- throw new BridgeError(BRIDGE_ERRORS.A_DIRECT_PROVIDER_QUOTE_IS_REQUIRED);
148
- orderId = bytes(quoteKey.order_id, 32);
149
- requestId = quoteKey.request_id;
150
- quotedAmount ?? (quotedAmount = quoteKey.to_token_raw_amount);
151
- }
152
- const key = cacheKey(provider, params.fromChainId, orderId);
153
- const entry = entries.get(key);
154
- if (!entry || entry.intent !== intentKey(params) || entry.bridgeId !== params.bridgeId || entry.data.requestId !== requestId)
155
- throw new BridgeError(BRIDGE_ERRORS.QUOTE_DOES_NOT_MATCH_LOCAL_INTENT);
156
- const expected = provider === 'layerswap' ? layerSwapExpected(params) : uint(quotedAmount);
157
- if (expected !== entry.data.expectedAmount)
158
- throw new BridgeError(BRIDGE_ERRORS.QUOTED_AMOUNT_CHANGED);
159
- return entry;
160
- };
161
- const client = {
162
- async getQuotes(provider, originalParams) {
163
- // Capture user intent before the first await. Host state may change while requesting.
164
- const params = { ...originalParams };
165
- const startedGeneration = generation;
166
- return guard(provider, async () => {
167
- if (provider !== 'relay' && provider !== 'socket')
168
- throw new BridgeError(BRIDGE_ERRORS.UNSUPPORTED_DIRECT_PROVIDER);
169
- intentKey(params);
170
- const bps = slippageBps(params.slippage), appFeeBps = feeBps(params);
171
- if (provider === 'relay') {
172
- const metadata = await readChains();
173
- if (startedGeneration !== generation)
174
- throw new BridgeError(BRIDGE_ERRORS.QUOTE_REQUEST_WAS_INVALIDATED);
175
- const raw = await requestProvider(request, timeoutMs, provider, '/quote/v2', {
176
- user: address(params.userAddress), recipient: address(params.userAddress),
177
- originChainId: Number(chain(params.fromChainId)), destinationChainId: Number(chain(params.toChainId)),
178
- originCurrency: tokenAddress(params.fromTokenId, params.fromChainId), destinationCurrency: tokenAddress(params.toTokenId, params.toChainId),
179
- amount: uint(params.fromTokenRawAmount).toString(), tradeType: 'EXACT_INPUT', slippageTolerance: String(bps),
180
- includeProtocolData: true, useExternalLiquidity: false,
181
- ...(appFeeBps ? { appFees: [{ recipient: FEE_RECIPIENT, fee: String(appFeeBps) }] } : {}),
182
- });
183
- const data = readRelayQuote(raw, params, metadata);
184
- const details = object(object(raw).details), output = object(details.currencyOut);
185
- if (uint(output.amount) !== data.expectedAmount || uint(output.minimumAmount) !== data.parsed.minOutputAmount)
186
- throw new BridgeError(BRIDGE_ERRORS.RELAY_DISPLAY_AMOUNT_MISMATCH);
187
- const quote = makeQuote(provider, 'relay', data, Number(uint(object(output.currency).decimals, 8)));
188
- quote.duration = Number(uint(details.timeEstimate ?? 60, 32));
189
- const fees = object(object(raw).fees ?? {});
190
- const gas = object(fees.gas ?? {}), relayer = object(fees.relayerService ?? {}), app = object(fees.app ?? {});
191
- quote.gas_fee = feeDisplay(gas.amount, gas.amountUsd);
192
- quote.protocol_fee = displayOutputFee(relayer.amountUsd, output, data.expectedAmount);
193
- quote.rabby_fee = displayOutputFee(app.amountUsd, output, data.expectedAmount);
194
- return [store(provider, params, data, quote, startedGeneration)];
195
- }
196
- if (socketApi === 'public' && appFeeBps !== 0)
197
- throw new BridgeError(BRIDGE_ERRORS.SOCKET_PUBLIC_APP_FEE_UNSUPPORTED);
198
- const query = {
199
- userOps: 'tx', userAddress: address(params.userAddress), receiverAddress: address(params.userAddress),
200
- originChainId: chain(params.fromChainId).toString(), destinationChainId: chain(params.toChainId).toString(),
201
- inputToken: tokenAddress(params.fromTokenId, params.fromChainId), outputToken: tokenAddress(params.toTokenId, params.toChainId),
202
- inputAmount: uint(params.fromTokenRawAmount).toString(), slippage: String(bps / 100),
203
- excludeProvider: EXCLUDED_SOCKET_PROVIDERS.join(','), simulatedQuotesRequired: 'true',
204
- ...(appFeeBps ? { feeBps: String(appFeeBps), feeTakerAddress: FEE_RECIPIENT } : {}),
205
- };
206
- const raw = object(await requestProvider(request, timeoutMs, provider, '/v3/swap/quote?' +
207
- Object.entries(query).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&'), undefined, socketApi));
208
- if (raw.success !== true)
209
- throw new BridgeError(BRIDGE_ERRORS.SOCKET_QUOTE_REQUEST_REJECTED);
210
- const result = object(raw.result);
211
- const quotes = [];
212
- for (const routeValue of array(result.routes)) {
213
- const route = object(routeValue), details = object(route.routeDetails);
214
- if (!details.bridgeDetails)
215
- continue;
216
- const bridgeId = socketBridgeId(object(object(details.bridgeDetails).protocol).name);
217
- if (!SOCKET_PROVIDER_ROUTES.includes(bridgeId))
218
- continue;
219
- try {
220
- const data = readSocketQuote(result, route, params);
221
- const quote = makeQuote(provider, bridgeId, data, Number(uint(object(object(route.output).token).decimals, 8)));
222
- quote.duration = Number(uint(route.estimatedTime ?? 360, 32));
223
- const gas = object(route.gasFee ?? {}), fee = object(details.feeDetails ?? {});
224
- quote.gas_fee = feeDisplay(gas.estimatedFee, gas.feeInUsd);
225
- const input = object(result.input), inputToken = object(input.token);
226
- const output = object(route.output), outputToken = object(output.token);
227
- const feeToken = fee.feeToken ? object(fee.feeToken) : undefined;
228
- let feeUsd = 0;
229
- if (feeToken) {
230
- const priced = uint(feeToken.chainId) === uint(inputToken.chainId) && address(feeToken.address) === address(inputToken.address) ? input
231
- : uint(feeToken.chainId) === uint(outputToken.chainId) && address(feeToken.address) === address(outputToken.address) ? output : undefined;
232
- if (priced)
233
- feeUsd = Number(uint(fee.feeAmount ?? '0')) / 10 ** Number(uint(feeToken.decimals, 8)) * Number(priced.priceInUsd ?? 0);
234
- }
235
- const feeDisplayValue = displayOutputFee(feeUsd, output, data.expectedAmount);
236
- if (fee.feeTakerAddress && address(fee.feeTakerAddress) === FEE_RECIPIENT)
237
- quote.rabby_fee = feeDisplayValue;
238
- else
239
- quote.protocol_fee = feeDisplayValue;
240
- quotes.push(store(provider, params, data, quote, startedGeneration));
241
- }
242
- catch (error) {
243
- throw asBridgeError(error, BRIDGE_ERRORS.INVALID_RESPONSE, { bridgeId });
244
- }
245
- }
246
- return quotes;
247
- }, { aggregatorId: provider, chainId: params.fromChainId, toChainId: params.toChainId, ...(provider === 'relay' ? { bridgeId: 'relay' } : {}), operation: 'getQuote' });
248
- },
249
- async buildTx(provider, originalParams) {
250
- const params = { ...originalParams };
251
- return guard(provider, () => {
252
- const entry = entryFor(provider, params);
253
- const tx = { ...entry.data.tx };
254
- client.verifyTx(provider, params, tx);
255
- return tx;
256
- }, { aggregatorId: provider, chainId: params.fromChainId, toChainId: params.toChainId, bridgeId: params.bridgeId, operation: 'buildTx' });
257
- },
258
- async verifyLayerSwapTx(originalParams, tx) {
259
- const params = { ...originalParams };
260
- const startedGeneration = generation;
261
- return guard('layerswap', async () => {
262
- params.toTokenRawAmount = layerSwapExpected(params).toString();
263
- const deposit = readLayerSwapDeposit(tx, params);
264
- validateBridgeTx('lifi', params.fromChainId, params.bridgeId, deposit.tx, {
265
- userAddress: params.userAddress, fromTokenId: params.fromTokenId, fromTokenRawAmount: params.fromTokenRawAmount,
266
- toChainId: params.toChainId, toTokenId: params.toTokenId,
267
- });
268
- const key = cacheKey('layerswap', params.fromChainId, bytes(deposit.parsed.orderId, 32));
269
- const cached = entries.get(key);
270
- if (cached)
271
- return client.verifyTx('layerswap', params, deposit.tx);
272
- const end = Date.now() + timeoutMs;
273
- const seenPages = new Set();
274
- for (let page = 1; page <= 10; page++) {
275
- if (startedGeneration !== generation)
276
- throw new BridgeError(BRIDGE_ERRORS.QUOTE_REQUEST_WAS_INVALIDATED);
277
- const remaining = end - Date.now();
278
- if (remaining <= 0)
279
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_LOOKUP_TIMED_OUT);
280
- const raw = await requestProvider(request, remaining, 'layerswap', `/api/v2/explorer/${address(deposit.parsed.receiver)}?page=${page}`);
281
- const rows = layerSwapOrderRows(raw);
282
- const matches = rows.filter((row) => {
283
- try {
284
- return layerSwapSequence(row) === uint(deposit.parsed.orderId);
285
- }
286
- catch {
287
- return false;
288
- }
289
- });
290
- if (matches.length > 1)
291
- throw new BridgeError(BRIDGE_ERRORS.AMBIGUOUS_LAYERSWAP_REQUEST_ID);
292
- if (matches.length === 1) {
293
- const data = readLayerSwapOrder(matches[0], params, deposit);
294
- if (data.expectedAmount !== uint(params.toTokenRawAmount))
295
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_QUOTED_AMOUNT_CHANGED);
296
- save('layerswap', params, data, 'layerswap', startedGeneration);
297
- return client.verifyTx('layerswap', params, deposit.tx);
298
- }
299
- if (!rows.length)
300
- break;
301
- const fingerprint = JSON.stringify(rows.map((row) => object(object(row).swap).id));
302
- if (seenPages.has(fingerprint))
303
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_PAGINATION_DID_NOT_ADVANCE);
304
- seenPages.add(fingerprint);
305
- }
306
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_ORDER_NOT_FOUND);
307
- }, { aggregatorId: 'lifi', chainId: params.fromChainId, toChainId: params.toChainId, bridgeId: params.bridgeId, operation: 'verifyLayerSwapTx' });
308
- },
309
- verifyTx(provider, params, tx) {
310
- try {
311
- const entry = entryFor(provider, params, tx);
312
- if (!sameTransaction(tx, entry.data.tx))
313
- throw new BridgeError(BRIDGE_ERRORS.SOURCE_TRANSACTION_CHANGED);
314
- assertIntent(entry.data.parsed, params, entry.data.expectedAmount, entry.data.minimumQuantum);
315
- validateBridgeTx(provider === 'layerswap' ? 'lifi' : provider, params.fromChainId, params.bridgeId, tx);
316
- return { provider, binding: provider === 'relay' ? 'order-hash' : provider === 'layerswap' ? 'provider-record' : 'provider-transaction',
317
- parsed: { ...entry.data.parsed, unresolvedFields: [] } };
318
- }
319
- catch (error) {
320
- const failure = asBridgeError(error, BRIDGE_ERRORS.INVALID_TRANSACTION, { provider,
321
- aggregatorId: provider === 'layerswap' ? 'lifi' : provider, chainId: params.fromChainId, toChainId: params.toChainId,
322
- bridgeId: params.bridgeId, operation: 'verifyTx' });
323
- if (failure instanceof InvalidBridgeProviderError)
324
- throw failure;
325
- throw new InvalidBridgeProviderError(provider, failure);
326
- }
327
- },
328
- captureContext() {
329
- const expected = generation;
330
- return () => {
331
- if (generation !== expected)
332
- throw new InvalidBridgeProviderError('context', BRIDGE_ERRORS.PROVIDER_CLIENT_CONTEXT_CHANGED);
333
- };
334
- },
335
- clear() { generation++; entries.clear(); },
336
- };
337
- return client;
338
- };
339
- export { InvalidBridgeProviderError } from './errors.js';
340
- export { BRIDGE_PROVIDER_ORIGINS, createBridgeFetchRequest } from './request.js';
@@ -1,9 +0,0 @@
1
- import type { BridgeBuildTxParams, BridgeTx } from '../quote.js';
2
- import type { ProviderQuoteData } from './relay.js';
3
- export declare const readLayerSwapDeposit: (tx: BridgeTx, params: BridgeBuildTxParams) => {
4
- tx: BridgeTx;
5
- parsed: import("../calldata/types.js").ParsedBridgeCall;
6
- };
7
- export declare const layerSwapSequence: (row: unknown) => bigint;
8
- export declare const readLayerSwapOrder: (raw: unknown, params: BridgeBuildTxParams, deposit: ReturnType<typeof readLayerSwapDeposit>) => ProviderQuoteData;
9
- export declare const layerSwapOrderRows: (raw: unknown) => unknown[];
@@ -1,95 +0,0 @@
1
- import { BRIDGE_ERRORS, BridgeError } from '../errors/index.js';
2
- import { decodeCall, asRecord, asString } from '../calldata/abi.js';
3
- import { decodeBridgeCalldataResult } from '../calldata/index.js';
4
- import { bridgeDataParam, layerSwapDataParam, swapDataArrayParam } from '../calldata/lifi/params.js';
5
- import { address, array, bytes, chain, object, text, tokenAddress, transaction, uint, ZERO_ADDRESS } from './data.js';
6
- /** The API uses decimal quantities, sometimes in scientific notation. No float multiplication. */
7
- const decimalAmount = (value, decimals) => {
8
- if (typeof value === 'number' && (!Number.isFinite(value) || value < 0 ||
9
- (Number.isInteger(value) && !Number.isSafeInteger(value))))
10
- throw new BridgeError(BRIDGE_ERRORS.UNSAFE_LAYERSWAP_AMOUNT);
11
- if (typeof value !== 'string' && typeof value !== 'number')
12
- throw new BridgeError(BRIDGE_ERRORS.MISSING_LAYERSWAP_AMOUNT);
13
- const match = /^(\d+)(?:\.(\d+))?(?:e([+-]?\d+))?$/i.exec(String(value));
14
- if (!match)
15
- throw new BridgeError(BRIDGE_ERRORS.INVALID_LAYERSWAP_AMOUNT);
16
- const fraction = match[2] ?? '';
17
- const exponent = Number(match[3] ?? 0);
18
- if (!Number.isSafeInteger(exponent) || Math.abs(exponent) > 255)
19
- throw new BridgeError(BRIDGE_ERRORS.INVALID_AMOUNT_EXPONENT);
20
- const scale = decimals + exponent - fraction.length;
21
- const digits = BigInt(match[1] + fraction);
22
- if (scale >= 0)
23
- return uint(digits * 10n ** BigInt(scale));
24
- const divisor = 10n ** BigInt(-scale);
25
- if (digits % divisor !== 0n)
26
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_AMOUNT_EXCEEDS_TOKEN_PRECISION);
27
- return uint(digits / divisor);
28
- };
29
- const token = (raw, chainId) => {
30
- const t = object(raw);
31
- const decimals = Number(uint(t.decimals, 8));
32
- return { address: t.contract === null ? ZERO_ADDRESS : tokenAddress(text(t.contract), chainId), decimals,
33
- precision: t.precision === undefined ? decimals : Number(uint(t.precision, 8)) };
34
- };
35
- export const readLayerSwapDeposit = (tx, params) => {
36
- if (params.bridgeId !== 'layerswap')
37
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_BRIDGE_ID_MISMATCH);
38
- const sourceTx = transaction(tx, params);
39
- const decodedResult = decodeBridgeCalldataResult('lifi', sourceTx);
40
- if (!decodedResult.ok)
41
- throw new BridgeError(BRIDGE_ERRORS.INVALID_CALLDATA, {}, decodedResult.errors);
42
- const parsed = decodedResult.parsed;
43
- if (!parsed || !parsed.method.endsWith('ViaLayerSwap') || !parsed.orderId || !parsed.receiver)
44
- throw new BridgeError(BRIDGE_ERRORS.UNSUPPORTED_LAYERSWAP_TRANSACTION);
45
- const args = decodeCall([bridgeDataParam,
46
- ...(parsed.method.startsWith('swapAnd') ? [swapDataArrayParam] : []), layerSwapDataParam], sourceTx.data);
47
- const layerData = asRecord(args.layerSwapData);
48
- if (asString(layerData.refundRecipient) !== address(params.userAddress))
49
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_REFUND_RECIPIENT_MISMATCH);
50
- if (uint(asString(layerData.nonEVMReceiver)) !== 0n)
51
- throw new BridgeError(BRIDGE_ERRORS.UNSUPPORTED_LAYERSWAP_NON_EVM_RECEIVER);
52
- const native = tokenAddress(parsed.sourceToken ?? '', params.fromChainId) === ZERO_ADDRESS;
53
- if (uint(sourceTx.value) !== (native ? parsed.sourceAmount : 0n))
54
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_SOURCE_VALUE_MISMATCH);
55
- return { tx: sourceTx, parsed };
56
- };
57
- export const layerSwapSequence = (row) => uint(object(object(object(row).swap).metadata).sequence_number);
58
- export const readLayerSwapOrder = (raw, params, deposit) => {
59
- const row = object(raw), swap = object(row.swap), quote = object(row.quote);
60
- const { parsed, tx } = deposit;
61
- if (layerSwapSequence(row) !== uint(parsed.orderId))
62
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_REQUEST_ID_MISMATCH);
63
- if (typeof swap.id !== 'string' || !/^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(swap.id))
64
- throw new BridgeError(BRIDGE_ERRORS.INVALID_LAYERSWAP_SWAP_ID);
65
- const assertNetworks = (data) => {
66
- if (object(data.source_network).type !== 'evm' || object(data.destination_network).type !== 'evm' ||
67
- uint(object(data.source_network).chain_id) !== chain(params.fromChainId) ||
68
- uint(object(data.destination_network).chain_id) !== chain(params.toChainId))
69
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_CHAIN_MISMATCH);
70
- };
71
- assertNetworks(swap);
72
- assertNetworks(quote);
73
- const source = token(swap.source_token, params.fromChainId), destination = token(swap.destination_token, params.toChainId);
74
- const quotedSource = token(quote.source_token, params.fromChainId), quotedDestination = token(quote.destination_token, params.toChainId);
75
- if (source.address !== quotedSource.address || source.decimals !== quotedSource.decimals ||
76
- destination.address !== quotedDestination.address || destination.decimals !== quotedDestination.decimals ||
77
- destination.precision !== quotedDestination.precision || destination.precision > destination.decimals)
78
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_QUOTE_TOKEN_MISMATCH);
79
- if (source.address !== tokenAddress(parsed.bridgeToken ?? parsed.sourceToken ?? '', params.fromChainId) ||
80
- decimalAmount(swap.requested_amount, source.decimals) !== parsed.bridgeAmount ||
81
- decimalAmount(quote.requested_amount, source.decimals) !== parsed.bridgeAmount)
82
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_BRIDGE_INPUT_MISMATCH);
83
- const receiver = address(swap.destination_address);
84
- if (receiver !== parsed.receiver || receiver !== address(params.userAddress))
85
- throw new BridgeError(BRIDGE_ERRORS.LAYERSWAP_RECEIVER_MISMATCH);
86
- const expectedAmount = decimalAmount(quote.receive_amount, destination.decimals);
87
- const minOutputAmount = decimalAmount(quote.min_receive_amount, destination.decimals);
88
- if (expectedAmount <= 0n || minOutputAmount <= 0n || minOutputAmount > expectedAmount)
89
- throw new BridgeError(BRIDGE_ERRORS.INVALID_LAYERSWAP_OUTPUT_AMOUNT);
90
- return { tx, parsed: { ...parsed, outputToken: destination.address, minOutputAmount, receiver, unresolvedFields: [] },
91
- expectedAmount,
92
- orderId: bytes(parsed.orderId, 32), requestId: bytes(parsed.orderId, 32), approveAddress: '',
93
- minimumQuantum: 10n ** BigInt(destination.decimals - destination.precision) };
94
- };
95
- export const layerSwapOrderRows = (raw) => array(object(raw).data);
@@ -1,59 +0,0 @@
1
- import type { ParsedBridgeCall } from '../calldata/types.js';
2
- import type { BridgeQuoteListParams, BridgeTx } from '../quote.js';
3
- export type RelayChain = {
4
- evmId: bigint;
5
- protocolId: string;
6
- depository: string;
7
- };
8
- export declare const relayChains: (value: unknown) => RelayChain[];
9
- export declare const relayOrder: (raw: unknown, metadata: RelayChain[]) => {
10
- version: string;
11
- solverChainId: string;
12
- solver: string;
13
- salt: string;
14
- inputs: {
15
- payment: {
16
- chainId: string;
17
- currency: string;
18
- amount: string;
19
- weight: string;
20
- };
21
- refunds: {
22
- chainId: string;
23
- recipient: string;
24
- currency: string;
25
- minimumAmount: string;
26
- deadline: string;
27
- extraData: string;
28
- }[];
29
- }[];
30
- output: {
31
- chainId: string;
32
- deadline: string;
33
- extraData: string;
34
- calls: string[];
35
- payments: {
36
- recipient: string;
37
- currency: string;
38
- minimumAmount: string;
39
- expectedAmount: string;
40
- }[];
41
- };
42
- fees: {
43
- recipientChainId: string;
44
- recipient: string;
45
- currencyChainId: string;
46
- currency: string;
47
- amount: string;
48
- }[];
49
- };
50
- export type ProviderQuoteData = {
51
- tx: BridgeTx;
52
- parsed: ParsedBridgeCall;
53
- expectedAmount: bigint;
54
- approveAddress: string;
55
- orderId: string;
56
- requestId: string;
57
- minimumQuantum?: bigint;
58
- };
59
- export declare const readRelayQuote: (raw: unknown, params: BridgeQuoteListParams, metadata: RelayChain[]) => ProviderQuoteData;