@rabby-wallet/rabby-bridge 0.0.12 → 0.0.13-alpha.1
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/README.md +159 -1
- package/dist/calldata/abi.d.ts +29 -0
- package/dist/calldata/abi.js +160 -0
- package/dist/calldata/across/deposit.d.ts +2 -0
- package/dist/calldata/across/deposit.js +36 -0
- package/dist/calldata/across/depositNative.d.ts +2 -0
- package/dist/calldata/across/depositNative.js +45 -0
- package/dist/calldata/across/depositNow.d.ts +2 -0
- package/dist/calldata/across/depositNow.js +35 -0
- package/dist/calldata/across/depositV3.d.ts +2 -0
- package/dist/calldata/across/depositV3.js +35 -0
- package/dist/calldata/across/depositV3Now.d.ts +2 -0
- package/dist/calldata/across/depositV3Now.js +34 -0
- package/dist/calldata/across/index.d.ts +4 -0
- package/dist/calldata/across/index.js +31 -0
- package/dist/calldata/across/swapAndBridge.d.ts +2 -0
- package/dist/calldata/across/swapAndBridge.js +70 -0
- package/dist/calldata/across/validate.d.ts +3 -0
- package/dist/calldata/across/validate.js +34 -0
- package/dist/calldata/chains.d.ts +2 -0
- package/dist/calldata/chains.js +35 -0
- package/dist/calldata/destination.d.ts +6 -0
- package/dist/calldata/destination.js +211 -0
- package/dist/calldata/destinationSwap.d.ts +14 -0
- package/dist/calldata/destinationSwap.js +80 -0
- package/dist/calldata/diagnostics.d.ts +4 -0
- package/dist/calldata/diagnostics.js +18 -0
- package/dist/calldata/expect.d.ts +27 -0
- package/dist/calldata/expect.js +158 -0
- package/dist/calldata/hex.d.ts +6 -0
- package/dist/calldata/hex.js +46 -0
- package/dist/calldata/index.d.ts +20 -0
- package/dist/calldata/index.js +88 -0
- package/dist/calldata/lifi/across/acrossV4Erc20Min.d.ts +2 -0
- package/dist/calldata/lifi/across/acrossV4Erc20Min.js +26 -0
- package/dist/calldata/lifi/across/acrossV4NativeMin.d.ts +2 -0
- package/dist/calldata/lifi/across/acrossV4NativeMin.js +22 -0
- package/dist/calldata/lifi/across/index.d.ts +6 -0
- package/dist/calldata/lifi/across/index.js +19 -0
- package/dist/calldata/lifi/allbridge/index.d.ts +3 -0
- package/dist/calldata/lifi/allbridge/index.js +26 -0
- package/dist/calldata/lifi/celer/index.d.ts +4 -0
- package/dist/calldata/lifi/celer/index.js +10 -0
- package/dist/calldata/lifi/centrifuge/index.d.ts +3 -0
- package/dist/calldata/lifi/centrifuge/index.js +22 -0
- package/dist/calldata/lifi/destination.d.ts +5 -0
- package/dist/calldata/lifi/destination.js +40 -0
- package/dist/calldata/lifi/frax/index.d.ts +4 -0
- package/dist/calldata/lifi/frax/index.js +29 -0
- package/dist/calldata/lifi/garden/index.d.ts +3 -0
- package/dist/calldata/lifi/garden/index.js +22 -0
- package/dist/calldata/lifi/gaszip/index.d.ts +6 -0
- package/dist/calldata/lifi/gaszip/index.js +15 -0
- package/dist/calldata/lifi/index.d.ts +4 -0
- package/dist/calldata/lifi/index.js +62 -0
- package/dist/calldata/lifi/intents/index.d.ts +4 -0
- package/dist/calldata/lifi/intents/index.js +10 -0
- package/dist/calldata/lifi/layerswap/index.d.ts +4 -0
- package/dist/calldata/lifi/layerswap/index.js +10 -0
- package/dist/calldata/lifi/m0/index.d.ts +3 -0
- package/dist/calldata/lifi/m0/index.js +33 -0
- package/dist/calldata/lifi/mayan/index.d.ts +4 -0
- package/dist/calldata/lifi/mayan/index.js +10 -0
- package/dist/calldata/lifi/method.d.ts +6 -0
- package/dist/calldata/lifi/method.js +16 -0
- package/dist/calldata/lifi/native/index.d.ts +4 -0
- package/dist/calldata/lifi/native/index.js +80 -0
- package/dist/calldata/lifi/params.d.ts +28 -0
- package/dist/calldata/lifi/params.js +347 -0
- package/dist/calldata/lifi/paxos/index.d.ts +4 -0
- package/dist/calldata/lifi/paxos/index.js +10 -0
- package/dist/calldata/lifi/polymer/index.d.ts +4 -0
- package/dist/calldata/lifi/polymer/index.js +10 -0
- package/dist/calldata/lifi/relay/index.d.ts +6 -0
- package/dist/calldata/lifi/relay/index.js +15 -0
- package/dist/calldata/lifi/shape.d.ts +4 -0
- package/dist/calldata/lifi/shape.js +31 -0
- package/dist/calldata/lifi/squid/index.d.ts +6 -0
- package/dist/calldata/lifi/squid/index.js +15 -0
- package/dist/calldata/lifi/stargate/index.d.ts +5 -0
- package/dist/calldata/lifi/stargate/index.js +15 -0
- package/dist/calldata/lifi/swap/index.d.ts +5 -0
- package/dist/calldata/lifi/swap/index.js +18 -0
- package/dist/calldata/lifi/swap/swapMethod.d.ts +2 -0
- package/dist/calldata/lifi/swap/swapMethod.js +40 -0
- package/dist/calldata/lifi/swapData.d.ts +5 -0
- package/dist/calldata/lifi/swapData.js +33 -0
- package/dist/calldata/match.d.ts +3 -0
- package/dist/calldata/match.js +21 -0
- package/dist/calldata/mayan/destination.d.ts +2 -0
- package/dist/calldata/mayan/destination.js +13 -0
- package/dist/calldata/mayan/fastMctpBridge.d.ts +3 -0
- package/dist/calldata/mayan/fastMctpBridge.js +48 -0
- package/dist/calldata/mayan/fastMctpCreateOrder.d.ts +3 -0
- package/dist/calldata/mayan/fastMctpCreateOrder.js +39 -0
- package/dist/calldata/mayan/forward.d.ts +8 -0
- package/dist/calldata/mayan/forward.js +35 -0
- package/dist/calldata/mayan/forwardERC20.d.ts +2 -0
- package/dist/calldata/mayan/forwardERC20.js +19 -0
- package/dist/calldata/mayan/forwardEth.d.ts +2 -0
- package/dist/calldata/mayan/forwardEth.js +16 -0
- package/dist/calldata/mayan/index.d.ts +4 -0
- package/dist/calldata/mayan/index.js +21 -0
- package/dist/calldata/mayan/mctp.d.ts +5 -0
- package/dist/calldata/mayan/mctp.js +41 -0
- package/dist/calldata/mayan/readProtocol.d.ts +2 -0
- package/dist/calldata/mayan/readProtocol.js +29 -0
- package/dist/calldata/mayan/swapAndForwardERC20.d.ts +2 -0
- package/dist/calldata/mayan/swapAndForwardERC20.js +24 -0
- package/dist/calldata/mayan/swapAndForwardEth.d.ts +2 -0
- package/dist/calldata/mayan/swapAndForwardEth.js +23 -0
- package/dist/calldata/mayan/swiftCreateOrder.d.ts +3 -0
- package/dist/calldata/mayan/swiftCreateOrder.js +49 -0
- package/dist/calldata/mayan/validate.d.ts +3 -0
- package/dist/calldata/mayan/validate.js +20 -0
- package/dist/calldata/protocols.d.ts +9 -0
- package/dist/calldata/protocols.js +57 -0
- package/dist/calldata/relay/calls.d.ts +13 -0
- package/dist/calldata/relay/calls.js +54 -0
- package/dist/calldata/relay/depositErc20.d.ts +2 -0
- package/dist/calldata/relay/depositErc20.js +22 -0
- package/dist/calldata/relay/depositErc20Allowance.d.ts +2 -0
- package/dist/calldata/relay/depositErc20Allowance.js +20 -0
- package/dist/calldata/relay/depositNative.d.ts +2 -0
- package/dist/calldata/relay/depositNative.js +20 -0
- package/dist/calldata/relay/index.d.ts +4 -0
- package/dist/calldata/relay/index.js +42 -0
- package/dist/calldata/relay/multicall.d.ts +2 -0
- package/dist/calldata/relay/multicall.js +15 -0
- package/dist/calldata/relay/permit2TransferAndMulticall.d.ts +2 -0
- package/dist/calldata/relay/permit2TransferAndMulticall.js +42 -0
- package/dist/calldata/relay/permit3009TransferAndMulticall.d.ts +2 -0
- package/dist/calldata/relay/permit3009TransferAndMulticall.js +41 -0
- package/dist/calldata/relay/permit3009TransferAndMulticallSigned.d.ts +2 -0
- package/dist/calldata/relay/permit3009TransferAndMulticallSigned.js +40 -0
- package/dist/calldata/relay/permitTransferAndMulticall.d.ts +2 -0
- package/dist/calldata/relay/permitTransferAndMulticall.js +34 -0
- package/dist/calldata/relay/permitTransferAndMulticallLegacy.d.ts +2 -0
- package/dist/calldata/relay/permitTransferAndMulticallLegacy.js +35 -0
- package/dist/calldata/relay/transferAndMulticall.d.ts +2 -0
- package/dist/calldata/relay/transferAndMulticall.js +26 -0
- package/dist/calldata/relay/validate.d.ts +3 -0
- package/dist/calldata/relay/validate.js +18 -0
- package/dist/calldata/resolve.d.ts +2 -0
- package/dist/calldata/resolve.js +28 -0
- package/dist/calldata/socket/bridge.d.ts +2 -0
- package/dist/calldata/socket/bridge.js +28 -0
- package/dist/calldata/socket/exec.d.ts +2 -0
- package/dist/calldata/socket/exec.js +71 -0
- package/dist/calldata/socket/index.d.ts +4 -0
- package/dist/calldata/socket/index.js +13 -0
- package/dist/calldata/socket/params.d.ts +5 -0
- package/dist/calldata/socket/params.js +14 -0
- package/dist/calldata/socket/protocols/ccip.d.ts +2 -0
- package/dist/calldata/socket/protocols/ccip.js +32 -0
- package/dist/calldata/socket/protocols/cctp.d.ts +2 -0
- package/dist/calldata/socket/protocols/cctp.js +24 -0
- package/dist/calldata/socket/protocols/eco.d.ts +2 -0
- package/dist/calldata/socket/protocols/eco.js +20 -0
- package/dist/calldata/socket/protocols/index.d.ts +3 -0
- package/dist/calldata/socket/protocols/index.js +86 -0
- package/dist/calldata/socket/protocols/native.d.ts +2 -0
- package/dist/calldata/socket/protocols/native.js +70 -0
- package/dist/calldata/socket/protocols/oft.d.ts +2 -0
- package/dist/calldata/socket/protocols/oft.js +33 -0
- package/dist/calldata/socket/protocols/swapsXYZ.d.ts +2 -0
- package/dist/calldata/socket/protocols/swapsXYZ.js +62 -0
- package/dist/calldata/socket/swapAndBridge.d.ts +2 -0
- package/dist/calldata/socket/swapAndBridge.js +41 -0
- package/dist/calldata/socket/validate.d.ts +3 -0
- package/dist/calldata/socket/validate.js +24 -0
- package/dist/calldata/types.d.ts +82 -0
- package/dist/calldata/types.js +20 -0
- package/dist/errors/constants.d.ts +891 -0
- package/dist/errors/constants.js +898 -0
- package/dist/errors/index.d.ts +66 -0
- package/dist/errors/index.js +53 -0
- package/dist/errors/sanitize.d.ts +3 -0
- package/dist/errors/sanitize.js +74 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +3 -0
- package/dist/providers/data.d.ts +23 -0
- package/dist/providers/data.js +116 -0
- package/dist/providers/errors.d.ts +7 -0
- package/dist/providers/errors.js +10 -0
- package/dist/providers/layerswap.d.ts +9 -0
- package/dist/providers/layerswap.js +95 -0
- package/dist/providers/relay.d.ts +59 -0
- package/dist/providers/relay.js +185 -0
- package/dist/providers/socket.d.ts +5 -0
- package/dist/providers/socket.js +57 -0
- package/dist/quote.d.ts +26 -4
- package/dist/quote.js +200 -67
- package/package.json +13 -3
package/README.md
CHANGED
|
@@ -5,8 +5,166 @@ Minimal bridge SDK for Rabby:
|
|
|
5
5
|
- enumerates supported bridge aggregators and chains
|
|
6
6
|
- maintains per-chain spender/router allowlists
|
|
7
7
|
- validates backend bridge quotes before returning them
|
|
8
|
-
-
|
|
8
|
+
- decodes source transactions for Across, LI.FI, Relay, Socket and Mayan
|
|
9
|
+
- keeps chain-state-dependent output fields explicitly unverified, without RPC requests
|
|
10
|
+
- performs local validation only; no direct-provider HTTP requests or RPC reads
|
|
11
|
+
|
|
12
|
+
See [calldata parsing](src/calldata/README.md) for supported paths, integration and verification boundaries.
|
|
13
|
+
See [offline provider evidence](src/providers/README.md) for retained historical fixtures and verification limits.
|
|
9
14
|
|
|
10
15
|
## Test
|
|
11
16
|
|
|
12
17
|
Run `yarn test` to build the package and execute the Jest suite.
|
|
18
|
+
|
|
19
|
+
See [reachable route discovery](tests/fixtures/route-discovery-20261104/README.md) for the latest parsing changes, fixture coverage and remaining verification limits.
|
|
20
|
+
|
|
21
|
+
## Validation rollout
|
|
22
|
+
|
|
23
|
+
The first rollout enforces Router/Spender allowlists and observes local calldata
|
|
24
|
+
validation. No provider API or RPC requests are made. `buildTx` and
|
|
25
|
+
`getQuoteListWithTx` keep the original backend transaction when source, destination
|
|
26
|
+
or receiver checks fail or cannot be completed; `onError` receives those observations.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
const quotes = await getQuoteListWithTx(aggregatorId, {
|
|
30
|
+
...params,
|
|
31
|
+
onError: (report) => reportToBusiness(report),
|
|
32
|
+
}, api);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- Quotes and transactions come from the existing backend flow, including Relay
|
|
36
|
+
and Socket, in both modes. The SDK no longer accepts `providerClient` or exposes
|
|
37
|
+
a direct-provider client/fetch adapter.
|
|
38
|
+
- Router/Spender mismatches, unsupported source chains/aggregators,
|
|
39
|
+
missing required slippage, missing backend results and backend request failures
|
|
40
|
+
keep their original blocking behavior.
|
|
41
|
+
- Source token, source amount, supplied sender/chain and protocol structure are
|
|
42
|
+
checked locally. Missing source fields and mismatches are reported.
|
|
43
|
+
- Socket quote IDs (including CCTP), RFQ outer/vault IDs and Relay multicall
|
|
44
|
+
request IDs are compared locally when a selected quote provides a matching
|
|
45
|
+
identifier. Mismatches are reported without blocking or changing field flags;
|
|
46
|
+
missing/unrecognized keys are skipped. See the [binding limits](src/calldata/README.md).
|
|
47
|
+
- Known destination tokens, minimum amounts and chains are compared. Unknown
|
|
48
|
+
destination paths remain unverified and are reported with available method,
|
|
49
|
+
selector and nested-call diagnostics.
|
|
50
|
+
- Locally derivable final receivers are compared. External order data is skipped
|
|
51
|
+
without a provider request; a skipped receiver is never counted as verified.
|
|
52
|
+
- Parse failures, known mismatches and unexpected missing fields are reported with
|
|
53
|
+
`blocking: false`, including when `lite` is omitted or false.
|
|
54
|
+
- Relay and Socket RFQ/CCTP external destination fields are skipped rather than
|
|
55
|
+
fetched. LayerSwap uses its local receiver; no background order lookup runs.
|
|
56
|
+
Skipping an external receiver does not claim order-hash or provider verification.
|
|
57
|
+
- Known unresolved output token/minimum fields and Relay/Socket external
|
|
58
|
+
receiver/chain fields stay in `unverifiedFields` without producing reports.
|
|
59
|
+
Missing source fields, unknown receivers/paths and a missing expected amount
|
|
60
|
+
for a locally available minimum use `BRIDGE_UNVERIFIED_BRIDGE_FIELDS`.
|
|
61
|
+
Actual mismatches retain their existing error codes. Repeated failures are not
|
|
62
|
+
deduplicated, sampled or rate-limited by the SDK.
|
|
63
|
+
|
|
64
|
+
`validateBridgeQuote` also accepts `{ lite, onError }` as its fourth argument;
|
|
65
|
+
`validateBridgeTx` accepts it after the optional expectation as its sixth argument.
|
|
66
|
+
`lite` retains its legacy missing-spender behavior; it no longer selects strict
|
|
67
|
+
calldata enforcement and never skips a missing Router allowlist.
|
|
68
|
+
|
|
69
|
+
`validateBridgeTx` now returns `BridgeValidationResult` instead of `true`:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const result = validateBridgeTx(aggregatorId, chainId, bridgeId, tx, expectation);
|
|
73
|
+
// result.pass === result.routerPass
|
|
74
|
+
// result.fromPass / result.toPass / result.receiverPass
|
|
75
|
+
// result.unverifiedFields / result.errors
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The three field flags are true only when all required local comparisons for that
|
|
79
|
+
group succeeded. False means a failure or an incomplete check; `errors` and
|
|
80
|
+
`unverifiedFields` distinguish them. Known skipped fields can leave `errors` empty
|
|
81
|
+
while a field flag is false. Without an expectation, field flags are false.
|
|
82
|
+
They do not contribute to `pass` in this rollout. Router rejection still throws
|
|
83
|
+
`InvalidBridgeContractError`; its sanitized detail carries `pass: false`,
|
|
84
|
+
`routerPass: false` and `blocking: true`.
|
|
85
|
+
|
|
86
|
+
Raw decode/calldata-check results retain `ok: false` on failure. Observation
|
|
87
|
+
details include all five pass flags, path diagnostics, `lite` and `blocking: false`.
|
|
88
|
+
These are failure-event/path counts, not distinct user counts or a denominator for
|
|
89
|
+
all successful transactions. See error reporting below for failures that still throw.
|
|
90
|
+
|
|
91
|
+
## Error reporting
|
|
92
|
+
|
|
93
|
+
All stable error codes, stages and messages are defined in
|
|
94
|
+
[`BRIDGE_ERRORS`](src/errors/constants.ts). Codes are explicit constants; callers
|
|
95
|
+
must not classify errors by matching message text. Existing error classes and
|
|
96
|
+
legacy `reason` fields remain available.
|
|
97
|
+
|
|
98
|
+
- `decodeBridgeCalldataResult(aggregatorId, tx)` returns a detailed success/failure
|
|
99
|
+
result. The existing `decodeBridgeCalldata` still returns `null` on failure.
|
|
100
|
+
- `validateBridgeCalldata` returns `errors`, plus `error_code` and `stage` on failure.
|
|
101
|
+
Independent intent mismatches are collected together; decoding or dependent
|
|
102
|
+
protocol operations stop at their first failure.
|
|
103
|
+
- Thrown SDK errors extend `BridgeError`. Use `error.toJSON()` for a report.
|
|
104
|
+
- `onError` receives failures filtered from `getQuote` / `getQuoteListWithTx`,
|
|
105
|
+
plus local validation failures and unexpected missing fields from transaction checks.
|
|
106
|
+
Directly thrown errors are handled by the caller, avoiding duplicate reporting.
|
|
107
|
+
Reporting callback failures do not affect validation or quote filtering.
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { BridgeError, getQuoteListWithTx } from '@rabby-wallet/rabby-bridge';
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const quotes = await getQuoteListWithTx(aggregatorId, {
|
|
114
|
+
...params,
|
|
115
|
+
onError: (report) => reportToBusiness(report),
|
|
116
|
+
}, api);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
if (error instanceof BridgeError) reportToBusiness(error.toJSON());
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
A report contains a primary `error_code` / `stage` and an `errors` list. The primary
|
|
124
|
+
code is the first failure; inspect the list for every collected failure. Each detail
|
|
125
|
+
contains its fixed message and available context: aggregator, chain, bridge,
|
|
126
|
+
provider, operation, method, selector, nested protocol selector, missing fields or
|
|
127
|
+
HTTP status. SDK reports omit wallet addresses, amounts, raw calldata, response
|
|
128
|
+
bodies and arbitrary transport exception messages. Existing Error messages are
|
|
129
|
+
retained for compatibility; prefer `toJSON()` for reporting.
|
|
130
|
+
|
|
131
|
+
Stages distinguish input checks, contract allowlists, ABI decoding, protocol
|
|
132
|
+
structure, intent comparison, provider requests, provider responses, transaction
|
|
133
|
+
binding and completeness. Unexpected uncategorized failures use `BRIDGE_UNKNOWN`.
|
|
134
|
+
Deferred chain-state output fields remain in `unverifiedFields` without producing
|
|
135
|
+
reports merely because a known local limitation prevents verification.
|
|
136
|
+
|
|
137
|
+
### Privacy-safe diagnostics
|
|
138
|
+
|
|
139
|
+
Use `toBridgeErrorReport(resultOrError)` to convert a calldata check,
|
|
140
|
+
transaction validation result, detailed decode result or exception into a report.
|
|
141
|
+
A transaction with `pass: true` can still produce an observation report when its
|
|
142
|
+
`errors` are nonempty. Results without reportable failures return `undefined`,
|
|
143
|
+
including known skipped destination fields.
|
|
144
|
+
The `onError` callback and `BridgeError.toJSON()` use the same
|
|
145
|
+
runtime allowlist. Do not upload the entire check, exception, parsed transaction,
|
|
146
|
+
request parameters or quote response.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
const check = validateBridgeTx(aggregatorId, chainId, bridgeId, tx, expectation);
|
|
150
|
+
const report = toBridgeErrorReport(check);
|
|
151
|
+
if (report) reportToBusiness(report);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Reports can retain recognized aggregator/bridge/method labels, source/destination
|
|
155
|
+
chains, outer/router/protocol selectors, call-data format and byte lengths, ABI
|
|
156
|
+
failure offsets, bounded destination-call selectors/counts, unsupported command
|
|
157
|
+
bytes/counts, static request categories and HTTP status. Nested diagnostics are
|
|
158
|
+
collected where the parser knows the call layout; arbitrary payload bytes are not
|
|
159
|
+
scanned for possible selectors. Destination selector lists are deduplicated and
|
|
160
|
+
limited to 16 entries.
|
|
161
|
+
|
|
162
|
+
Unknown labels become `unknown` or are omitted. Messages and stages are restored
|
|
163
|
+
from the error-code catalogue, even if an error was modified after construction.
|
|
164
|
+
Arbitrary properties are dropped, including wallet/receiver/refund addresses,
|
|
165
|
+
token addresses, amounts, balances, approvals, transaction/order/quote/request IDs,
|
|
166
|
+
signatures, full calldata, URL/query/header/body contents, raw exception messages
|
|
167
|
+
and stack traces. Contract addresses and hashes are not reported either.
|
|
168
|
+
|
|
169
|
+
These reports identify unsupported function families and failure stages. They
|
|
170
|
+
intentionally cannot reconstruct or identify the original user's transaction.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ParsedBridgeCall } from './types.js';
|
|
2
|
+
export type AbiParam = {
|
|
3
|
+
name: string;
|
|
4
|
+
kind: 'address' | 'uint' | 'bool' | 'bytes' | 'string' | 'array' | 'tuple';
|
|
5
|
+
size?: number;
|
|
6
|
+
length?: number;
|
|
7
|
+
item?: AbiParam;
|
|
8
|
+
components?: AbiParam[];
|
|
9
|
+
};
|
|
10
|
+
export type AbiValue = string | bigint | boolean | AbiValue[] | {
|
|
11
|
+
[key: string]: AbiValue;
|
|
12
|
+
};
|
|
13
|
+
export declare const decodeCall: (params: AbiParam[], calldata: string) => {
|
|
14
|
+
[key: string]: AbiValue;
|
|
15
|
+
};
|
|
16
|
+
export declare const decodeParameters: (params: AbiParam[], data: string) => {
|
|
17
|
+
[key: string]: AbiValue;
|
|
18
|
+
};
|
|
19
|
+
export declare const asRecord: (value: AbiValue) => {
|
|
20
|
+
[key: string]: AbiValue;
|
|
21
|
+
};
|
|
22
|
+
export declare const asArray: (value: AbiValue) => AbiValue[];
|
|
23
|
+
export declare const asBigint: (value: AbiValue) => bigint;
|
|
24
|
+
export declare const asString: (value: AbiValue) => string;
|
|
25
|
+
export type CalldataMethod = {
|
|
26
|
+
name: string;
|
|
27
|
+
selector: string;
|
|
28
|
+
decode: (data: string, value: bigint) => ParsedBridgeCall;
|
|
29
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { BRIDGE_ERRORS, BridgeError } from '../errors/index.js';
|
|
2
|
+
import { toUtf8String, Utf8ErrorFuncs } from '@ethersproject/strings';
|
|
3
|
+
import { bytesToHex, hexToBytes } from './hex.js';
|
|
4
|
+
const isDynamic = (param) => {
|
|
5
|
+
if (param.kind === 'string') {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
if (param.kind === 'bytes') {
|
|
9
|
+
return param.size === undefined;
|
|
10
|
+
}
|
|
11
|
+
if (param.kind === 'array') {
|
|
12
|
+
return param.length === undefined || isDynamic(param.item);
|
|
13
|
+
}
|
|
14
|
+
if (param.kind === 'tuple') {
|
|
15
|
+
return (param.components ?? []).some(isDynamic);
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
};
|
|
19
|
+
const staticWordCount = (param) => {
|
|
20
|
+
if (isDynamic(param)) {
|
|
21
|
+
return 1;
|
|
22
|
+
}
|
|
23
|
+
if (param.kind === 'tuple') {
|
|
24
|
+
return (param.components ?? []).reduce((sum, item) => sum + staticWordCount(item), 0);
|
|
25
|
+
}
|
|
26
|
+
if (param.kind === 'array') {
|
|
27
|
+
return (param.length ?? 0) * staticWordCount(param.item);
|
|
28
|
+
}
|
|
29
|
+
return 1;
|
|
30
|
+
};
|
|
31
|
+
const readWord = (buf, offset) => {
|
|
32
|
+
if (offset < 0 || offset + 32 > buf.length) {
|
|
33
|
+
throw new BridgeError(BRIDGE_ERRORS.ABI_WORD_OUT_OF_BOUNDS, { abiOffset: offset, abiBufferBytes: buf.length });
|
|
34
|
+
}
|
|
35
|
+
let value = 0n;
|
|
36
|
+
for (let index = 0; index < 32; index += 1) {
|
|
37
|
+
value = (value << 8n) + BigInt(buf[offset + index]);
|
|
38
|
+
}
|
|
39
|
+
return value;
|
|
40
|
+
};
|
|
41
|
+
const toAddress = (word) => {
|
|
42
|
+
if (word >= (1n << 160n))
|
|
43
|
+
throw new BridgeError(BRIDGE_ERRORS.INVALID_ABI_ADDRESS);
|
|
44
|
+
return `0x${word.toString(16).padStart(40, '0')}`;
|
|
45
|
+
};
|
|
46
|
+
const readByteLength = (buf, offset) => {
|
|
47
|
+
const length = readWord(buf, offset);
|
|
48
|
+
if (length > BigInt(buf.length)) {
|
|
49
|
+
throw new BridgeError(BRIDGE_ERRORS.ABI_BYTES_OUT_OF_BOUNDS, { abiOffset: offset, abiBufferBytes: buf.length });
|
|
50
|
+
}
|
|
51
|
+
return Number(length);
|
|
52
|
+
};
|
|
53
|
+
const readDynamicBytes = (buf, offset) => {
|
|
54
|
+
const length = readByteLength(buf, offset);
|
|
55
|
+
const start = offset + 32;
|
|
56
|
+
if (start + length > buf.length) {
|
|
57
|
+
throw new BridgeError(BRIDGE_ERRORS.ABI_BYTES_OUT_OF_BOUNDS, { abiOffset: offset, abiBufferBytes: buf.length });
|
|
58
|
+
}
|
|
59
|
+
return bytesToHex(buf.subarray(start, start + length));
|
|
60
|
+
};
|
|
61
|
+
const decodeSequence = (params, buf, base) => {
|
|
62
|
+
let cursor = base;
|
|
63
|
+
const locations = [];
|
|
64
|
+
for (const param of params) {
|
|
65
|
+
if (isDynamic(param)) {
|
|
66
|
+
const relative = readWord(buf, cursor);
|
|
67
|
+
if (relative > BigInt(buf.length)) {
|
|
68
|
+
throw new BridgeError(BRIDGE_ERRORS.ABI_OFFSET_OUT_OF_BOUNDS, { abiOffset: cursor, abiBufferBytes: buf.length });
|
|
69
|
+
}
|
|
70
|
+
locations.push(base + Number(relative));
|
|
71
|
+
cursor += 32;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
locations.push(cursor);
|
|
75
|
+
cursor += staticWordCount(param) * 32;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return params.map((param, index) => decodeAt(param, buf, locations[index]));
|
|
79
|
+
};
|
|
80
|
+
const decodeAt = (param, buf, offset) => {
|
|
81
|
+
switch (param.kind) {
|
|
82
|
+
case 'address':
|
|
83
|
+
return toAddress(readWord(buf, offset));
|
|
84
|
+
case 'uint':
|
|
85
|
+
return readWord(buf, offset);
|
|
86
|
+
case 'bool': {
|
|
87
|
+
const word = readWord(buf, offset);
|
|
88
|
+
if (word !== 0n && word !== 1n) {
|
|
89
|
+
throw new BridgeError(BRIDGE_ERRORS.INVALID_BOOL);
|
|
90
|
+
}
|
|
91
|
+
return word === 1n;
|
|
92
|
+
}
|
|
93
|
+
case 'bytes': {
|
|
94
|
+
if (param.size === undefined) {
|
|
95
|
+
return readDynamicBytes(buf, offset);
|
|
96
|
+
}
|
|
97
|
+
if (offset + 32 > buf.length) {
|
|
98
|
+
throw new BridgeError(BRIDGE_ERRORS.ABI_WORD_OUT_OF_BOUNDS, { abiOffset: offset, abiBufferBytes: buf.length });
|
|
99
|
+
}
|
|
100
|
+
return bytesToHex(buf.subarray(offset, offset + param.size));
|
|
101
|
+
}
|
|
102
|
+
case 'string':
|
|
103
|
+
return toUtf8String(readDynamicBytes(buf, offset), Utf8ErrorFuncs.replace).replace(/^\uFEFF/, '');
|
|
104
|
+
case 'tuple':
|
|
105
|
+
return decodeTuple(param.components ?? [], buf, offset);
|
|
106
|
+
case 'array': {
|
|
107
|
+
const item = param.item;
|
|
108
|
+
if (param.length === undefined) {
|
|
109
|
+
const length = readByteLength(buf, offset);
|
|
110
|
+
if (length > 2048) {
|
|
111
|
+
throw new BridgeError(BRIDGE_ERRORS.ABI_ARRAY_TOO_LONG);
|
|
112
|
+
}
|
|
113
|
+
return decodeSequence(Array.from({ length }, () => item), buf, offset + 32);
|
|
114
|
+
}
|
|
115
|
+
return decodeSequence(Array.from({ length: param.length }, () => item), buf, offset);
|
|
116
|
+
}
|
|
117
|
+
default:
|
|
118
|
+
throw new BridgeError(BRIDGE_ERRORS.UNSUPPORTED_ABI_TYPE);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const decodeTuple = (components, buf, offset) => {
|
|
122
|
+
const values = decodeSequence(components, buf, offset);
|
|
123
|
+
return Object.fromEntries(components.map((component, index) => [component.name, values[index]]));
|
|
124
|
+
};
|
|
125
|
+
export const decodeCall = (params, calldata) => {
|
|
126
|
+
const bytes = hexToBytes(calldata);
|
|
127
|
+
if (bytes.length < 4) {
|
|
128
|
+
throw new BridgeError(BRIDGE_ERRORS.MISSING_SELECTOR);
|
|
129
|
+
}
|
|
130
|
+
const values = decodeSequence(params, bytes.subarray(4), 0);
|
|
131
|
+
return Object.fromEntries(params.map((param, index) => [param.name, values[index]]));
|
|
132
|
+
};
|
|
133
|
+
export const decodeParameters = (params, data) => {
|
|
134
|
+
const values = decodeSequence(params, hexToBytes(data), 0);
|
|
135
|
+
return Object.fromEntries(params.map((param, index) => [param.name, values[index]]));
|
|
136
|
+
};
|
|
137
|
+
export const asRecord = (value) => {
|
|
138
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
139
|
+
throw new BridgeError(BRIDGE_ERRORS.EXPECTED_TUPLE);
|
|
140
|
+
}
|
|
141
|
+
return value;
|
|
142
|
+
};
|
|
143
|
+
export const asArray = (value) => {
|
|
144
|
+
if (!Array.isArray(value)) {
|
|
145
|
+
throw new BridgeError(BRIDGE_ERRORS.EXPECTED_ARRAY);
|
|
146
|
+
}
|
|
147
|
+
return value;
|
|
148
|
+
};
|
|
149
|
+
export const asBigint = (value) => {
|
|
150
|
+
if (typeof value !== 'bigint') {
|
|
151
|
+
throw new BridgeError(BRIDGE_ERRORS.EXPECTED_UINT);
|
|
152
|
+
}
|
|
153
|
+
return value;
|
|
154
|
+
};
|
|
155
|
+
export const asString = (value) => {
|
|
156
|
+
if (typeof value !== 'string') {
|
|
157
|
+
throw new BridgeError(BRIDGE_ERRORS.EXPECTED_STRING);
|
|
158
|
+
}
|
|
159
|
+
return value;
|
|
160
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { applyAcrossMessage } from '../destination.js';
|
|
2
|
+
import { asBigint, asString, decodeCall } from '../abi.js';
|
|
3
|
+
import { accountFromBytes32 } from '../hex.js';
|
|
4
|
+
const fields = [
|
|
5
|
+
{ name: 'depositor', kind: 'bytes', size: 32 },
|
|
6
|
+
{ name: 'recipient', kind: 'bytes', size: 32 },
|
|
7
|
+
{ name: 'inputToken', kind: 'bytes', size: 32 },
|
|
8
|
+
{ name: 'outputToken', kind: 'bytes', size: 32 },
|
|
9
|
+
{ name: 'inputAmount', kind: 'uint' },
|
|
10
|
+
{ name: 'outputAmount', kind: 'uint' },
|
|
11
|
+
{ name: 'destinationChainId', kind: 'uint' },
|
|
12
|
+
{ name: 'exclusiveRelayer', kind: 'bytes', size: 32 },
|
|
13
|
+
{ name: 'quoteTimestamp', kind: 'uint' },
|
|
14
|
+
{ name: 'fillDeadline', kind: 'uint' },
|
|
15
|
+
{ name: 'exclusivityParameter', kind: 'uint' },
|
|
16
|
+
{ name: 'message', kind: 'bytes' },
|
|
17
|
+
];
|
|
18
|
+
export const deposit = {
|
|
19
|
+
name: 'deposit',
|
|
20
|
+
selector: '0xad5425c6',
|
|
21
|
+
decode(data) {
|
|
22
|
+
const args = decodeCall(fields, data);
|
|
23
|
+
return applyAcrossMessage({
|
|
24
|
+
aggregatorId: 'across',
|
|
25
|
+
method: 'deposit',
|
|
26
|
+
kind: 'bridge',
|
|
27
|
+
depositor: accountFromBytes32(asString(args.depositor)),
|
|
28
|
+
sourceToken: accountFromBytes32(asString(args.inputToken)),
|
|
29
|
+
sourceAmount: asBigint(args.inputAmount),
|
|
30
|
+
destinationChainId: asBigint(args.destinationChainId),
|
|
31
|
+
receiver: accountFromBytes32(asString(args.recipient)),
|
|
32
|
+
outputToken: accountFromBytes32(asString(args.outputToken)),
|
|
33
|
+
minOutputAmount: asBigint(args.outputAmount),
|
|
34
|
+
}, asString(args.message));
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BRIDGE_ERRORS, BridgeError } from '../../errors/index.js';
|
|
2
|
+
import { applyAcrossMessage } from '../destination.js';
|
|
3
|
+
import { asBigint, asString, decodeCall } from '../abi.js';
|
|
4
|
+
import { accountFromBytes32 } from '../hex.js';
|
|
5
|
+
import { NATIVE_TOKEN } from '../protocols.js';
|
|
6
|
+
const fields = [
|
|
7
|
+
{ name: 'spokePool', kind: 'address' },
|
|
8
|
+
{ name: 'depositor', kind: 'address' },
|
|
9
|
+
{ name: 'recipient', kind: 'bytes', size: 32 },
|
|
10
|
+
{ name: 'inputToken', kind: 'address' },
|
|
11
|
+
{ name: 'inputAmount', kind: 'uint' },
|
|
12
|
+
{ name: 'outputToken', kind: 'bytes', size: 32 },
|
|
13
|
+
{ name: 'outputAmount', kind: 'uint' },
|
|
14
|
+
{ name: 'destinationChainId', kind: 'uint' },
|
|
15
|
+
{ name: 'exclusiveRelayer', kind: 'bytes', size: 32 },
|
|
16
|
+
{ name: 'quoteTimestamp', kind: 'uint' },
|
|
17
|
+
{ name: 'fillDeadline', kind: 'uint' },
|
|
18
|
+
{ name: 'exclusivityParameter', kind: 'uint' },
|
|
19
|
+
{ name: 'message', kind: 'bytes' },
|
|
20
|
+
];
|
|
21
|
+
export const depositNative = {
|
|
22
|
+
name: 'depositNative',
|
|
23
|
+
selector: '0x609ea081',
|
|
24
|
+
decode(data, value) {
|
|
25
|
+
const args = decodeCall(fields, data);
|
|
26
|
+
const inputAmount = asBigint(args.inputAmount);
|
|
27
|
+
if (inputAmount > 0n && value !== inputAmount)
|
|
28
|
+
throw new BridgeError(BRIDGE_ERRORS.ACROSS_NATIVE_VALUE_MISMATCH);
|
|
29
|
+
return applyAcrossMessage({
|
|
30
|
+
aggregatorId: 'across',
|
|
31
|
+
method: 'depositNative',
|
|
32
|
+
kind: 'bridge',
|
|
33
|
+
depositor: asString(args.depositor),
|
|
34
|
+
sourceToken: NATIVE_TOKEN,
|
|
35
|
+
sourceAmount: inputAmount > 0n ? inputAmount : value,
|
|
36
|
+
bridgeToken: asString(args.inputToken),
|
|
37
|
+
bridgeAmount: inputAmount > 0n ? inputAmount : value,
|
|
38
|
+
destinationChainId: asBigint(args.destinationChainId),
|
|
39
|
+
receiver: accountFromBytes32(asString(args.recipient)),
|
|
40
|
+
outputToken: accountFromBytes32(asString(args.outputToken)),
|
|
41
|
+
minOutputAmount: asBigint(args.outputAmount),
|
|
42
|
+
spokePool: asString(args.spokePool),
|
|
43
|
+
}, asString(args.message));
|
|
44
|
+
},
|
|
45
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { applyAcrossMessage } from '../destination.js';
|
|
2
|
+
import { asBigint, asString, decodeCall } from '../abi.js';
|
|
3
|
+
import { accountFromBytes32 } from '../hex.js';
|
|
4
|
+
const fields = [
|
|
5
|
+
{ name: 'depositor', kind: 'bytes', size: 32 },
|
|
6
|
+
{ name: 'recipient', kind: 'bytes', size: 32 },
|
|
7
|
+
{ name: 'inputToken', kind: 'bytes', size: 32 },
|
|
8
|
+
{ name: 'outputToken', kind: 'bytes', size: 32 },
|
|
9
|
+
{ name: 'inputAmount', kind: 'uint' },
|
|
10
|
+
{ name: 'outputAmount', kind: 'uint' },
|
|
11
|
+
{ name: 'destinationChainId', kind: 'uint' },
|
|
12
|
+
{ name: 'exclusiveRelayer', kind: 'bytes', size: 32 },
|
|
13
|
+
{ name: 'fillDeadlineOffset', kind: 'uint' },
|
|
14
|
+
{ name: 'exclusivityParameter', kind: 'uint' },
|
|
15
|
+
{ name: 'message', kind: 'bytes' },
|
|
16
|
+
];
|
|
17
|
+
export const depositNow = {
|
|
18
|
+
name: 'depositNow',
|
|
19
|
+
selector: '0xea86bd46',
|
|
20
|
+
decode(data) {
|
|
21
|
+
const args = decodeCall(fields, data);
|
|
22
|
+
return applyAcrossMessage({
|
|
23
|
+
aggregatorId: 'across',
|
|
24
|
+
method: 'depositNow',
|
|
25
|
+
kind: 'bridge',
|
|
26
|
+
depositor: accountFromBytes32(asString(args.depositor)),
|
|
27
|
+
sourceToken: accountFromBytes32(asString(args.inputToken)),
|
|
28
|
+
sourceAmount: asBigint(args.inputAmount),
|
|
29
|
+
destinationChainId: asBigint(args.destinationChainId),
|
|
30
|
+
receiver: accountFromBytes32(asString(args.recipient)),
|
|
31
|
+
outputToken: accountFromBytes32(asString(args.outputToken)),
|
|
32
|
+
minOutputAmount: asBigint(args.outputAmount),
|
|
33
|
+
}, asString(args.message));
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { applyAcrossMessage } from '../destination.js';
|
|
2
|
+
import { asBigint, asString, decodeCall } from '../abi.js';
|
|
3
|
+
const fields = [
|
|
4
|
+
{ name: 'depositor', kind: 'address' },
|
|
5
|
+
{ name: 'recipient', kind: 'address' },
|
|
6
|
+
{ name: 'inputToken', kind: 'address' },
|
|
7
|
+
{ name: 'outputToken', kind: 'address' },
|
|
8
|
+
{ name: 'inputAmount', kind: 'uint' },
|
|
9
|
+
{ name: 'outputAmount', kind: 'uint' },
|
|
10
|
+
{ name: 'destinationChainId', kind: 'uint' },
|
|
11
|
+
{ name: 'exclusiveRelayer', kind: 'address' },
|
|
12
|
+
{ name: 'quoteTimestamp', kind: 'uint' },
|
|
13
|
+
{ name: 'fillDeadline', kind: 'uint' },
|
|
14
|
+
{ name: 'exclusivityParameter', kind: 'uint' },
|
|
15
|
+
{ name: 'message', kind: 'bytes' },
|
|
16
|
+
];
|
|
17
|
+
export const depositV3 = {
|
|
18
|
+
name: 'depositV3',
|
|
19
|
+
selector: '0x7b939232',
|
|
20
|
+
decode(data) {
|
|
21
|
+
const args = decodeCall(fields, data);
|
|
22
|
+
return applyAcrossMessage({
|
|
23
|
+
aggregatorId: 'across',
|
|
24
|
+
method: 'depositV3',
|
|
25
|
+
kind: 'bridge',
|
|
26
|
+
depositor: asString(args.depositor),
|
|
27
|
+
sourceToken: asString(args.inputToken),
|
|
28
|
+
sourceAmount: asBigint(args.inputAmount),
|
|
29
|
+
destinationChainId: asBigint(args.destinationChainId),
|
|
30
|
+
receiver: asString(args.recipient),
|
|
31
|
+
outputToken: asString(args.outputToken),
|
|
32
|
+
minOutputAmount: asBigint(args.outputAmount),
|
|
33
|
+
}, asString(args.message));
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { applyAcrossMessage } from '../destination.js';
|
|
2
|
+
import { asBigint, asString, decodeCall } from '../abi.js';
|
|
3
|
+
const fields = [
|
|
4
|
+
{ name: 'depositor', kind: 'address' },
|
|
5
|
+
{ name: 'recipient', kind: 'address' },
|
|
6
|
+
{ name: 'inputToken', kind: 'address' },
|
|
7
|
+
{ name: 'outputToken', kind: 'address' },
|
|
8
|
+
{ name: 'inputAmount', kind: 'uint' },
|
|
9
|
+
{ name: 'outputAmount', kind: 'uint' },
|
|
10
|
+
{ name: 'destinationChainId', kind: 'uint' },
|
|
11
|
+
{ name: 'exclusiveRelayer', kind: 'address' },
|
|
12
|
+
{ name: 'fillDeadlineOffset', kind: 'uint' },
|
|
13
|
+
{ name: 'exclusivityParameter', kind: 'uint' },
|
|
14
|
+
{ name: 'message', kind: 'bytes' },
|
|
15
|
+
];
|
|
16
|
+
export const depositV3Now = {
|
|
17
|
+
name: 'depositV3Now',
|
|
18
|
+
selector: '0x7aef642c',
|
|
19
|
+
decode(data) {
|
|
20
|
+
const args = decodeCall(fields, data);
|
|
21
|
+
return applyAcrossMessage({
|
|
22
|
+
aggregatorId: 'across',
|
|
23
|
+
method: 'depositV3Now',
|
|
24
|
+
kind: 'bridge',
|
|
25
|
+
depositor: asString(args.depositor),
|
|
26
|
+
sourceToken: asString(args.inputToken),
|
|
27
|
+
sourceAmount: asBigint(args.inputAmount),
|
|
28
|
+
destinationChainId: asBigint(args.destinationChainId),
|
|
29
|
+
receiver: asString(args.recipient),
|
|
30
|
+
outputToken: asString(args.outputToken),
|
|
31
|
+
minOutputAmount: asBigint(args.outputAmount),
|
|
32
|
+
}, asString(args.message));
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { BridgeCallExpectation } from '../expect.js';
|
|
2
|
+
import type { BridgeCheck, DecodeHit } from '../types.js';
|
|
3
|
+
export declare const decodeAcross: (data: string, value: bigint) => DecodeHit;
|
|
4
|
+
export declare const validateAcross: (data: string, value: bigint, expectation?: BridgeCallExpectation, chainId?: string) => BridgeCheck;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { matchMethod } from '../match.js';
|
|
2
|
+
import { finishCheck } from '../expect.js';
|
|
3
|
+
import { deposit } from './deposit.js';
|
|
4
|
+
import { depositNative } from './depositNative.js';
|
|
5
|
+
import { depositNow } from './depositNow.js';
|
|
6
|
+
import { depositV3 } from './depositV3.js';
|
|
7
|
+
import { depositV3Now } from './depositV3Now.js';
|
|
8
|
+
import { swapAndBridge } from './swapAndBridge.js';
|
|
9
|
+
import { acrossFailure } from './validate.js';
|
|
10
|
+
const METHODS = [
|
|
11
|
+
depositV3,
|
|
12
|
+
deposit,
|
|
13
|
+
depositV3Now,
|
|
14
|
+
depositNow,
|
|
15
|
+
depositNative,
|
|
16
|
+
swapAndBridge,
|
|
17
|
+
];
|
|
18
|
+
export const decodeAcross = (data, value) => matchMethod(METHODS, data, value);
|
|
19
|
+
export const validateAcross = (data, value, expectation, chainId = '') => {
|
|
20
|
+
const hit = decodeAcross(data, value);
|
|
21
|
+
if (!hit.ok) {
|
|
22
|
+
return { ...hit, aggregatorId: 'across' };
|
|
23
|
+
}
|
|
24
|
+
return finishCheck('across', hit.parsed, acrossFailure(hit.parsed, chainId, expectation?.userAddress), expectation, chainId, {
|
|
25
|
+
fromToken: true,
|
|
26
|
+
fromAmount: true,
|
|
27
|
+
toToken: true,
|
|
28
|
+
toAmount: true,
|
|
29
|
+
receiver: true,
|
|
30
|
+
});
|
|
31
|
+
};
|