@rhea-finance/cross-chain-aggregation-dex 2.0.1 → 2.0.3

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 (60) hide show
  1. package/README.md +567 -206
  2. package/dist/executors/aptos.d.mts +3 -4
  3. package/dist/executors/aptos.d.ts +3 -4
  4. package/dist/executors/aptos.js +22 -2
  5. package/dist/executors/aptos.js.map +1 -1
  6. package/dist/executors/aptos.mjs +22 -2
  7. package/dist/executors/aptos.mjs.map +1 -1
  8. package/dist/executors/bitcoin.d.mts +3 -4
  9. package/dist/executors/bitcoin.d.ts +3 -4
  10. package/dist/executors/bitcoin.js +22 -2
  11. package/dist/executors/bitcoin.js.map +1 -1
  12. package/dist/executors/bitcoin.mjs +22 -2
  13. package/dist/executors/bitcoin.mjs.map +1 -1
  14. package/dist/executors/evm.d.mts +3 -4
  15. package/dist/executors/evm.d.ts +3 -4
  16. package/dist/executors/evm.js +29 -13
  17. package/dist/executors/evm.js.map +1 -1
  18. package/dist/executors/evm.mjs +29 -13
  19. package/dist/executors/evm.mjs.map +1 -1
  20. package/dist/executors/near.d.mts +3 -4
  21. package/dist/executors/near.d.ts +3 -4
  22. package/dist/executors/near.js +22 -2
  23. package/dist/executors/near.js.map +1 -1
  24. package/dist/executors/near.mjs +22 -2
  25. package/dist/executors/near.mjs.map +1 -1
  26. package/dist/executors/solana.d.mts +3 -4
  27. package/dist/executors/solana.d.ts +3 -4
  28. package/dist/executors/solana.js +22 -2
  29. package/dist/executors/solana.js.map +1 -1
  30. package/dist/executors/solana.mjs +22 -2
  31. package/dist/executors/solana.mjs.map +1 -1
  32. package/dist/executors/sui.d.mts +3 -4
  33. package/dist/executors/sui.d.ts +3 -4
  34. package/dist/executors/sui.js +22 -2
  35. package/dist/executors/sui.js.map +1 -1
  36. package/dist/executors/sui.mjs +22 -2
  37. package/dist/executors/sui.mjs.map +1 -1
  38. package/dist/executors/tron.d.mts +3 -4
  39. package/dist/executors/tron.d.ts +3 -4
  40. package/dist/executors/tron.js +22 -2
  41. package/dist/executors/tron.js.map +1 -1
  42. package/dist/executors/tron.mjs +22 -2
  43. package/dist/executors/tron.mjs.map +1 -1
  44. package/dist/executors/zcash.d.mts +4 -5
  45. package/dist/executors/zcash.d.ts +4 -5
  46. package/dist/executors/zcash.js +24 -10
  47. package/dist/executors/zcash.js.map +1 -1
  48. package/dist/executors/zcash.mjs +24 -10
  49. package/dist/executors/zcash.mjs.map +1 -1
  50. package/dist/index.d.mts +4 -3
  51. package/dist/index.d.ts +4 -3
  52. package/dist/index.js +59 -25
  53. package/dist/index.js.map +1 -1
  54. package/dist/index.mjs +59 -25
  55. package/dist/index.mjs.map +1 -1
  56. package/dist/{registry-DRYUqs7T.d.mts → shared-BEZXY_BM.d.mts} +39 -12
  57. package/dist/{registry-DRYUqs7T.d.ts → shared-BEZXY_BM.d.ts} +39 -12
  58. package/package.json +4 -1
  59. package/dist/shared-BdH3hWuP.d.ts +0 -23
  60. package/dist/shared-BqpFeosz.d.mts +0 -23
package/README.md CHANGED
@@ -1,117 +1,455 @@
1
1
  # @rhea-finance/cross-chain-aggregation-dex
2
2
 
3
- TypeScript SDK for the unified multi-chain Swap API. It provides raw and normalized quote, build, execution, order status, report, and history interfaces without coupling the core package to a wallet or UI framework.
3
+ A TypeScript SDK for the RHEA unified multi-chain Swap API. The SDK handles quote normalization, swap building, wallet execution, EVM approvals, order submission, status polling, reporting, and history. Applications do not need to branch on routers, cross-chain status, or transaction types.
4
4
 
5
- Supported chain families: EVM, Solana, Aptos, NEAR, Tron, Bitcoin, Zcash, and Sui.
5
+ This package is a client SDK for the RHEA Cross-Chain Swap API. For endpoint contracts, request/response fields, and protocol details, see the [Cross-Chain Swap API documentation](https://github.com/rhea-finance/rhea-sdk-docs/blob/main/CrossChainDexAPI.md).
6
6
 
7
- ## Install
7
+ Supported chain families: EVM, Solana, Aptos, NEAR, Tron, Bitcoin, Zcash, and Sui. How to load the product token list and chain coverage is described in [Supported chains and tokens](#supported-chains-and-tokens).
8
+
9
+ ## Supported chains and tokens
10
+
11
+ The product support list matches `multi-chain-lending` Trade: **18 mainnets**. Use the HTTP API chain ID for `fromChain` / `toChain` in Swap calls, and the token-query alias when fetching token metadata.
12
+
13
+ | Chain | Type | HTTP / SDK chain ID | Token query alias |
14
+ | --- | --- | --- | --- |
15
+ | Ethereum | EVM | `1` | `eth` |
16
+ | BNB Smart Chain | EVM | `56` | `bsc` |
17
+ | Arbitrum One | EVM | `42161` | `arb` |
18
+ | Base | EVM | `8453` | `base` |
19
+ | Optimism | EVM | `10` | `op` |
20
+ | Berachain | EVM | `1385` | `bera` |
21
+ | Monad | EVM | `143` | `monad` |
22
+ | X Layer | EVM | `196` | `xlayer` |
23
+ | Polygon PoS | EVM | `137` | `pol` |
24
+ | Gnosis Chain | EVM | `100` | `gnosis` |
25
+ | Plasma | EVM | `9745` | `plasma` |
26
+ | Solana | Non-EVM | `solana` | `sol` |
27
+ | Bitcoin | Non-EVM | `btc` | `btc` |
28
+ | NEAR | Non-EVM | `near` | `near` |
29
+ | Zcash | Non-EVM | `zcash` | `zcash` (also accepts `zec`) |
30
+ | Aptos | Non-EVM | `aptos` | `aptos` |
31
+ | Tron | Non-EVM | `tron` | `tron` |
32
+ | Sui | Non-EVM | `sui` | `sui` |
33
+
34
+ "Supported" means the product can load tokens for that chain and send them into the unified quote flow. It does **not** guarantee a route for every pair. Live liquidity, routers, amount, and service status still decide whether a quote succeeds.
35
+
36
+ ### Token coverage (Unified Swap)
37
+
38
+ Across the 18 product chains above, Unified Swap currently covers **4,000+** tokens (same-chain DEX metadata plus cross-chain Intents tokens, deduplicated per direction). Snapshot: 2026-07-24. Counts change as liquidity providers and Intents listings update; always fetch the live token APIs below for the current list.
39
+
40
+ ### How to fetch supported tokens
41
+
42
+ Token discovery uses HTTP endpoints **outside** `/api/swap/*`. The SDK does not wrap these calls; applications should `fetch` them directly and map results into `AssetRef` when calling `client.quote()`.
43
+
44
+ #### 1. Product token list (recommended for Trade UI)
45
+
46
+ ```http
47
+ GET https://api.rhea.finance/get_multichain_lending_tokens_data?chains=<COMMA_SEPARATED_ALIASES>
48
+ ```
49
+
50
+ Query all currently supported product chains:
8
51
 
9
52
  ```bash
10
- pnpm add @rhea-finance/cross-chain-aggregation-dex
53
+ curl "https://api.rhea.finance/get_multichain_lending_tokens_data?chains=bsc,eth,arb,base,op,bera,monad,xlayer,pol,gnosis,plasma,sol,btc,near,zcash,zec,aptos,tron,sui"
11
54
  ```
12
55
 
13
- ## Quick start
56
+ A successful response is a **JSON array** of token objects (not the `/api/swap` `{ code, data, msg }` envelope). Typical fields:
14
57
 
15
- All token amounts are base-unit decimal strings. Slippage uses basis points (`50` means 0.5%).
58
+ | Field | Description |
59
+ | --- | --- |
60
+ | `assetId` | Multichain / Intents asset ID |
61
+ | `blockchain` | Token query alias (`eth`, `near`, …) |
62
+ | `symbol` | Display symbol |
63
+ | `decimals` | Token decimals |
64
+ | `contractAddress` | On-chain address; may be empty for natives |
65
+ | `price` / `priceUpdatedAt` | Display price only; not a swap quote |
66
+ | `icon` | Optional icon URL |
16
67
 
17
- ```ts
18
- import { SwapClient, type QuoteRequest } from "@rhea-finance/cross-chain-aggregation-dex";
68
+ Integration tips:
19
69
 
20
- const getAccessToken = async () => sessionStorage.getItem("access-token") ?? "";
70
+ - Group by `blockchain`; do not merge tokens by `symbol` alone.
71
+ - For `quote()`, pass the chain-specific token address/ID as `AssetRef.address`, and use the HTTP/SDK chain ID in `fromChain` / `toChain` / `AssetRef.chain` (for example Base `"8453"`, Solana `"solana"`).
72
+ - Presence in this list means the token is discoverable. Confirm a route with `client.quote()` (or `POST /api/swap/quote`) before trading.
73
+ - Prefer short-lived cache; refresh periodically instead of hard-coding the list.
21
74
 
22
- const client = new SwapClient({
23
- baseUrl: "https://api.rhea.finance",
24
- getAccessToken,
25
- });
75
+ #### 2. Per-chain token price metadata
26
76
 
27
- const request: QuoteRequest = {
28
- fromChain: "btc",
29
- toChain: "near",
30
- tokenIn: {
31
- chain: "btc",
32
- address: "btc",
33
- symbol: "BTC",
34
- decimals: 8,
35
- isNative: true,
36
- },
37
- tokenOut: {
38
- chain: "near",
39
- address: "wrap.near",
40
- symbol: "wNEAR",
41
- decimals: 24,
42
- },
43
- amountIn: "100000",
44
- slippageBps: 50,
45
- sender: "bc1...",
46
- recipient: "alice.near",
47
- };
77
+ ```http
78
+ GET https://api.rhea.finance/get_chain_prices?chain=<TOKEN_QUERY_ALIAS>
79
+ ```
48
80
 
49
- const quote = await client.quote(request);
50
- const build = await client.buildSwap({ quote });
81
+ Example:
51
82
 
52
- // build is safe to inspect or send to another process.
53
- // Register a chain executor before calling executeSwap.
83
+ ```bash
84
+ curl "https://api.rhea.finance/get_chain_prices?chain=eth"
85
+ curl "https://api.rhea.finance/get_chain_prices?chain=bsc"
86
+ curl "https://api.rhea.finance/get_chain_prices?chain=base"
54
87
  ```
55
88
 
56
- `buildSwap()` never opens a wallet. To execute a build, inject one or more `ChainExecutor` implementations when creating the client:
89
+ `chain` is required and must be a **token query alias** (`eth`, `bsc`, `base`, …). A successful response uses `{ code, data, msg }`:
57
90
 
58
91
  ```ts
59
- const clientWithExecutor = new SwapClient({
60
- baseUrl: "https://api.rhea.finance",
61
- getAccessToken,
62
- executors: [bitcoinExecutor],
63
- });
92
+ // code === 0 && msg === "success"
93
+ type ChainPricesResponse = {
94
+ code: number;
95
+ msg: string;
96
+ data: Record<
97
+ string,
98
+ {
99
+ address: string;
100
+ chainId: number;
101
+ decimals: number;
102
+ symbol: string;
103
+ name?: string;
104
+ price: string;
105
+ logoURI?: string;
106
+ updated_at?: number;
107
+ }
108
+ >;
109
+ };
110
+ ```
64
111
 
65
- const result = await clientWithExecutor.executeSwap({
66
- build,
67
- waitFor: "submitted",
68
- });
112
+ Use this endpoint for same-chain token metadata and display prices. It is keyed by token address. It does not replace `get_multichain_lending_tokens_data` for the full multi-chain Trade selector, and some non-EVM aliases may return an empty `data` object.
113
+
114
+ ## 1. What the SDK does
115
+
116
+ The recommended flow has only two steps:
117
+
118
+ ```ts
119
+ const quote = await client.quote(quoteRequest);
120
+ const result = await client.swap({ quote });
69
121
  ```
70
122
 
123
+ The normalized object returned by `quote()` can be passed directly to `swap()`. Internally, `swap()` continues with `buildSwap()` and `executeSwap()`, then selects the registered executor that matches the execution type returned by the API. Applications do not need to determine:
124
+
125
+ - whether the swap is same-chain or cross-chain;
126
+ - which router is used;
127
+ - whether execution requires a transaction, a signed order, or a deposit transfer;
128
+ - whether an EVM approval is required;
129
+ - whether the flow is an MCA deposit, NEAR withdrawal, or relayer withdrawal.
130
+
131
+ The application only provides the request fields and the relevant wallet adapters. Do not modify `quote.buildContext` or rebuild a swap request from `quote.raw`.
132
+
133
+ ## 2. Installation
71
134
 
135
+ ```bash
136
+ pnpm add @rhea-finance/cross-chain-aggregation-dex
137
+ ```
72
138
 
73
- ### Executor adapters
139
+ Node.js 16 or later is required. When running on Node.js 16 without a global `fetch`, inject a compatible implementation through `SwapClientConfig.fetch`.
74
140
 
75
- Each executor is imported from its own subpath and accepts a wallet-neutral adapter. The application decides whether that adapter wraps a browser wallet, server signer, RPC service, or HSM.
141
+ ## 3. Recommended: simple quote swap flow
142
+
143
+ The example below swaps USDC on Base for USDC on Solana. All token amounts use base-unit decimal strings. For example, USDC has 6 decimals, so `"1000000"` represents 1 USDC.
144
+
145
+ ### 3.1 Minimal EVM adapter
146
+
147
+ The SDK does not receive private keys and is not coupled to a specific wallet library. Wrap your wallet implementation in an adapter:
76
148
 
77
149
  ```ts
78
- import { SwapClient } from "@rhea-finance/cross-chain-aggregation-dex";
79
150
  import {
80
151
  createEvmExecutor,
81
152
  type EvmWalletAdapter,
82
153
  } from "@rhea-finance/cross-chain-aggregation-dex/executors/evm";
83
154
 
84
- const evmWallet: EvmWalletAdapter = {
85
- getIdentityKey: () => wallet.address,
86
- signMessage: (message) => wallet.signMessage(message),
87
- sendTransaction: async (tx) => {
155
+ const evmAdapter: EvmWalletAdapter = {
156
+ async sendTransaction(tx) {
88
157
  const response = await wallet.sendTransaction({
89
158
  to: tx.to,
90
159
  data: tx.data,
91
160
  value: tx.value,
92
161
  gasLimit: tx.gasLimit,
162
+ gasPrice: tx.gasPrice,
163
+ maxFeePerGas: tx.maxFeePerGas,
164
+ maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
93
165
  });
94
166
  return { txHash: response.hash, raw: response };
95
167
  },
96
- signTypedData: async (request) =>
97
- wallet.signTypedData(
168
+
169
+ async signTypedData(request) {
170
+ return wallet.signTypedData(
98
171
  request.typedData.domain,
99
172
  request.typedData.types,
100
173
  request.typedData.message
101
- ),
102
- waitForTransaction: async (txHash) => provider.waitForTransaction(txHash),
174
+ );
175
+ },
176
+
177
+ async waitForTransaction(txHash) {
178
+ const receipt = await provider.waitForTransaction(txHash);
179
+ return {
180
+ status: receipt?.status === 1 ? "confirmed" : "failed",
181
+ raw: receipt,
182
+ };
183
+ },
103
184
  };
104
185
 
186
+ const evmExecutor = createEvmExecutor(evmAdapter);
187
+ ```
188
+
189
+ The EVM executor does not read the currently connected chain. It uses `tx.chainId` from the API build response. The wallet should prompt the user or switch networks when sending the transaction.
190
+
191
+ The build normalizer accepts EVM chain IDs as numbers, decimal strings, or JSON-RPC hexadecimal strings and exposes them to the adapter as numbers. It also preserves `from`, `gasPrice`, `maxFeePerGas`, and `maxPriorityFeePerGas`. For standard ERC-20 approval calldata, the SDK treats the encoded allowance spender as authoritative when the API's separate `approve.spender` field is inconsistent.
192
+
193
+ ### 3.2 Create a SwapClient
194
+
195
+ ```ts
196
+ import { SwapClient } from "@rhea-finance/cross-chain-aggregation-dex";
197
+
105
198
  const client = new SwapClient({
106
199
  baseUrl: "https://api.rhea.finance",
107
- getAccessToken,
108
- executors: [createEvmExecutor(evmWallet)],
200
+ getAccessToken: () => sessionStorage.getItem("access-token") ?? "",
201
+ executors: [evmExecutor],
202
+ });
203
+ ```
204
+
205
+ ### 3.3 Request a quote
206
+
207
+ ```ts
208
+ import type {
209
+ AssetRef,
210
+ QuoteRequest,
211
+ } from "@rhea-finance/cross-chain-aggregation-dex";
212
+
213
+ const baseUsdc: AssetRef = {
214
+ chain: "8453",
215
+ address: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
216
+ symbol: "USDC",
217
+ decimals: 6,
218
+ };
219
+
220
+ const solanaUsdc: AssetRef = {
221
+ chain: "solana",
222
+ address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
223
+ symbol: "USDC",
224
+ decimals: 6,
225
+ };
226
+
227
+ const quoteRequest: QuoteRequest = {
228
+ fromChain: "8453",
229
+ toChain: "solana",
230
+ tokenIn: baseUsdc,
231
+ tokenOut: solanaUsdc,
232
+ amountIn: "1000000",
233
+ slippageBps: 50,
234
+ quoteWaitingTimeMs: 3000,
235
+ sender: "0xYourBaseAddress",
236
+ recipient: "YourSolanaAddress",
237
+ };
238
+
239
+ const quote = await client.quote(quoteRequest);
240
+ ```
241
+
242
+ `quote()` calls `POST /api/swap/quote`. `quoteWaitingTimeMs` is a quote API request parameter used by routes such as Near Intents to wait for a quote. It is not an on-chain RPC timeout. The SDK sends `3000` when the field is omitted.
243
+
244
+ ### 3.4 Execute the swap directly
245
+
246
+ ```ts
247
+ const result = await client.swap({
248
+ quote,
249
+ waitFor: "submitted",
250
+ beforeSign(preview) {
251
+ console.log("Wallet action requested", preview);
252
+ },
109
253
  });
254
+
255
+ console.log(result.status, result.txHash, result.orderId);
110
256
  ```
111
257
 
112
- Other executor subpaths follow the same pattern:
258
+ `swap()` does not request another quote. It uses the `buildContext` stored in the quote to call the swap API, normalizes the build response, and invokes the matching executor.
259
+
260
+ The default `waitFor` mode is `"submitted"`. The method returns after the wallet successfully signs or submits the transaction. This does not mean the assets have arrived on the destination chain.
261
+
262
+ To let the SDK continue polling for final delivery:
113
263
 
114
264
  ```ts
265
+ const result = await client.swap({
266
+ quote,
267
+ waitFor: "completed",
268
+ orderPolling: {
269
+ intervalMs: 5000,
270
+ timeoutMs: 600000,
271
+ },
272
+ });
273
+
274
+ if (result.status === "completed") {
275
+ console.log("Order completed");
276
+ }
277
+ ```
278
+
279
+ `"completed"` polls the API only when the build response contains a queryable `orderId`. The default polling interval is 5 seconds. There is no default polling timeout, so polling continues until the order reaches a terminal state or the supplied `AbortSignal` is aborted.
280
+
281
+ Set `orderPolling.timeoutMs` only when the application needs a time limit. An explicit timeout throws `ORDER_TIMEOUT`, but it does not revert an already submitted on-chain transaction.
282
+
283
+ ### 3.5 Check final delivery status
284
+
285
+ If the swap first returns with `"submitted"`, use the returned `orderId` to poll manually:
286
+
287
+ ```ts
288
+ if (result.orderId) {
289
+ const finalStatus = await client.waitForOrder({
290
+ orderId: result.orderId,
291
+ router: result.router,
292
+ intervalMs: 5000,
293
+ timeoutMs: 600000,
294
+ });
295
+
296
+ console.log(finalStatus.status);
297
+ }
298
+ ```
299
+
300
+ For a single status request:
301
+
302
+ ```ts
303
+ const status = await client.getOrderStatus({
304
+ orderId: result.orderId!,
305
+ router: result.router,
306
+ });
307
+ ```
308
+
309
+ Terminal statuses are `completed`, `failed`, `refunded`, and `expired`.
310
+
311
+ ## 4. Simple-flow field reference
312
+
313
+ ### 4.1 SwapClientConfig
314
+
315
+ | Field | Type | Required | Description and default |
316
+ | --- | --- | --- | --- |
317
+ | `baseUrl` | `string` | Yes | API base URL, for example `https://api.rhea.finance`. A trailing `/` is removed. |
318
+ | `apiKey` | `string` | No | API credential sent with requests. |
319
+ | `getAccessToken` | `() => string \| Promise<string>` | No | Reads an access token before each request. Use this for refreshable sessions. |
320
+ | `fetch` | `typeof globalThis.fetch` | No | Custom fetch implementation. The SDK binds its invocation context to avoid browser `Illegal invocation` errors. It is normally required on Node.js 16. |
321
+ | `headers` | `Record<string,string>` or function | No | Additional request headers. The function form may return a promise. |
322
+ | `timeoutMs` | `number` | No | Timeout for each HTTP request in milliseconds. Default: `15000`. |
323
+ | `retry` | `Partial<RetryConfig>` | No | Retry policy for retryable quote/read operations. Defaults: 2 retries, 250ms base delay, 2000ms maximum delay, and jitter enabled. |
324
+ | `logger` | `SdkLogger` | No | Receives structured `api.request`, `api.response`, and `api.retry` entries. |
325
+ | `executors` | `readonly ChainExecutor[]` | Required for execution | Wallet executors. May be omitted when only calling `quote()` or `buildSwap()`. |
326
+ | `maxQuoteAgeMs` | `number \| null` | No | Maximum local quote age in milliseconds. Default: `30000`. Set to `null` to disable the local age check; an API-provided `expiresAt` still applies. |
327
+ | `reportMode` | `"auto" \| "manual" \| "disabled"` | No | Reporting policy. Default: `"auto"`. A reporting failure does not turn a submitted swap into a failed swap. |
328
+ | `onEvent` | `(event) => void` | No | Receives all lifecycle events. |
329
+ | `now` | `() => number` | No | Custom millisecond clock, mainly for testing. Default: `Date.now`. |
330
+
331
+ ### 4.2 AssetRef
332
+
333
+ | Field | Type | Required | Format and meaning |
334
+ | --- | --- | --- | --- |
335
+ | `chain` | `ChainRef` | Yes | The SDK uses one chain ID format everywhere. EVM chains use decimal strings, such as Base `"8453"`. Other values are `"solana"`, `"aptos"`, `"near"`, `"tron"`, `"btc"`, `"zcash"`, and `"sui"`. |
336
+ | `address` | `string` | Yes | Token contract address, mint, coin type, or the API-defined native-token identifier. |
337
+ | `symbol` | `string` | No | Display symbol. It is not used for calculations. |
338
+ | `decimals` | `number` | No | Token precision. Supplying it is recommended so applications can format and convert amounts correctly. |
339
+ | `isNative` | `boolean` | No | Whether the asset is the chain's native token. |
340
+
341
+ `tokenIn.chain` should match `fromChain`, and `tokenOut.chain` should match `toChain`.
342
+
343
+ ### 4.3 QuoteRequest
344
+
345
+ | Field | Type | Required | Format and meaning |
346
+ | --- | --- | --- | --- |
347
+ | `fromChain` | `ChainRef` | Yes | Source chain ID, for example `"8453"`. |
348
+ | `toChain` | `ChainRef` | Yes | Destination chain ID, for example `"solana"`. |
349
+ | `tokenIn` | `AssetRef` | Yes | Asset being spent. |
350
+ | `tokenOut` | `AssetRef` | Yes | Asset being received. |
351
+ | `amountIn` | `string` | Yes | A non-negative base-unit decimal integer string. Do not pass `"1.5"` or scientific notation. |
352
+ | `slippageBps` | `number` | Yes | Slippage in basis points. `50` means 0.5%; `100` means 1%. |
353
+ | `quoteWaitingTimeMs` | `number` | No | Time the quote API may wait for route quotes, in milliseconds. Must be a non-negative integer. Default: `3000`. |
354
+ | `sender` | `string` | Yes | Sender address on the source chain. |
355
+ | `recipient` | `string` | No | Recipient address on the destination chain. Cross-chain requests should normally provide it explicitly. |
356
+ | `extensions` | `Record<string,unknown>` | No | Additional fields forwarded to the API. Regular applications should not use this to replace standard fields. |
357
+
358
+ Important normalized quote fields:
359
+
360
+ | Field | Meaning |
361
+ | --- | --- |
362
+ | `estimatedOut` | Estimated output amount as a base-unit string. |
363
+ | `minAmountOut` | Minimum output after slippage as a base-unit string. |
364
+ | `route.router` | Router selected by the SDK. Use it for display or diagnostics, not application-side execution branching. |
365
+ | `alternatives` | Normalized summaries of other available routes. |
366
+ | `receivedAt` / `expiresAt` | Millisecond timestamps used for quote freshness validation. |
367
+ | `buildContext` | Read-only context used by `swap()` and `buildSwap()`. Do not modify it. |
368
+ | `raw` | Original quote API `data`, useful for diagnostics or fields that are not normalized. |
369
+
370
+ ### 4.4 SwapInput and WaitMode
371
+
372
+ | Field | Type | Required | Description |
373
+ | --- | --- | --- | --- |
374
+ | `quote` | `Quote` | Yes | The value returned by `client.quote()`. Pass it directly without modification. |
375
+ | `waitFor` | `"submitted" \| "source-confirmed" \| "completed"` | No | Default: `"submitted"`. |
376
+ | `orderPolling` | `OrderPollingOptions` | No | Used with `waitFor: "completed"`. `intervalMs` defaults to `5000`; omit `timeoutMs` to poll indefinitely. |
377
+ | `signal` | `AbortSignal` | No | Cancels unfinished SDK requests or waits. It cannot withdraw an already broadcast transaction. |
378
+ | `onEvent` | `(event) => void` | No | Receives lifecycle events for this swap only. |
379
+ | `beforeSign` | `(preview) => void \| Promise<void>` | No | Called before each wallet signature or transaction request. It can be used for application confirmation UI. |
380
+ | `idempotencyKey` | `string` | No | Sent with the build request. Duplicate-execution protection is determined by the server. |
381
+
382
+ Wait modes:
383
+
384
+ | Mode | Return condition |
385
+ | --- | --- |
386
+ | `submitted` | Returns after the wallet signs or broadcasts the source action. |
387
+ | `source-confirmed` | Calls the required wallet confirmation method and returns only when it reports `confirmed`. A `failed` or malformed status throws `BROADCAST_FAILED`. |
388
+ | `completed` | After source execution, polls the server until a delivery terminal state when an order reference exists. Without an order reference, it returns the source execution result. |
389
+
390
+ `waitForOrder()` accepts the same polling values directly:
391
+
392
+ | Field | Type | Required | Description |
393
+ | --- | --- | --- | --- |
394
+ | `intervalMs` | `number` | No | Delay between status requests in milliseconds. Default: `5000`. |
395
+ | `timeoutMs` | `number` | No | Maximum total polling duration in milliseconds. Omit it to poll indefinitely. |
396
+
397
+ ### 4.5 SwapExecutionResult
398
+
399
+ | Field | Type | Description |
400
+ | --- | --- | --- |
401
+ | `executionId` | `string` | Unique identifier for this SDK execution. |
402
+ | `status` | `string` | `submitted`, `source-confirmed`, `processing`, `completed`, `failed`, `refunded`, or `expired`. |
403
+ | `router` | `string` | Router used for execution. Pass it unchanged when querying order status. |
404
+ | `txHash` | `string?` | Hash of a single source-chain transaction. |
405
+ | `txHashes` | `string[]?` | Hashes of multiple source-chain transactions, such as a NEAR transaction batch. |
406
+ | `orderId` | `string?` | Server order identifier. When present, it can be passed to `waitForOrder()`. |
407
+ | `depositAddress` | `string?` | Cross-chain deposit address. |
408
+ | `report` | `object?` | Reporting state: `reported`, `failed`, or `skipped`. A report warning does not invalidate the source submission. |
409
+ | `raw` | `unknown` | Executor confirmation response or original swap API build data. |
410
+
411
+ `submitted` and `source-confirmed` do not mean that the destination assets have arrived. Use `waitFor: "completed"` or `waitForOrder()` to check final delivery.
412
+
413
+ ## 5. Advanced: buildSwap → executeSwap
414
+
415
+ Use the advanced flow only when you need to inspect the build, pass it between processes, or separate building from wallet execution:
416
+
417
+ ```ts
418
+ const quote = await client.quote(quoteRequest);
419
+
420
+ // Builds and normalizes the execution without opening a wallet.
421
+ const build = await client.buildSwap({
422
+ quote,
423
+ idempotencyKey: crypto.randomUUID(),
424
+ });
425
+
426
+ console.log(build.router, build.execution.kind, build.raw);
427
+
428
+ // Wallet execution can happen later.
429
+ const result = await client.executeSwap({
430
+ build,
431
+ waitFor: "submitted",
432
+ });
433
+ ```
434
+
435
+ The following calls are equivalent:
436
+
437
+ ```ts
438
+ await client.swap({ quote });
439
+
440
+ // Equivalent to:
441
+ const build = await client.buildSwap({ quote });
442
+ await client.executeSwap({ build });
443
+ ```
444
+
445
+ `buildSwap()` does not require an executor. `executeSwap()` requires a registered executor that supports `build.execution.kind`. MCA relayer withdrawals include an SDK-managed message-signing and submission flow, so use `swap()` instead of splitting that flow.
446
+
447
+ ## 6. Executor adapters
448
+
449
+ Import each chain executor from its dedicated subpath:
450
+
451
+ ```ts
452
+ import { createEvmExecutor } from "@rhea-finance/cross-chain-aggregation-dex/executors/evm";
115
453
  import { createSolanaExecutor } from "@rhea-finance/cross-chain-aggregation-dex/executors/solana";
116
454
  import { createAptosExecutor } from "@rhea-finance/cross-chain-aggregation-dex/executors/aptos";
117
455
  import { createNearExecutor } from "@rhea-finance/cross-chain-aggregation-dex/executors/near";
@@ -121,229 +459,260 @@ import { createZcashExecutor } from "@rhea-finance/cross-chain-aggregation-dex/e
121
459
  import { createSuiExecutor } from "@rhea-finance/cross-chain-aggregation-dex/executors/sui";
122
460
  ```
123
461
 
124
- Bitcoin requires `feeRate` in the build or a configured fallback:
462
+ | Chain | Supported execution kinds | Core adapter capabilities |
463
+ | --- | --- | --- |
464
+ | EVM | `evm-transaction`, `evm-signature` | `sendTransaction`, `signTypedData`, and `waitForTransaction`. |
465
+ | Solana | `solana-transaction` | Submit a serialized transaction and implement `waitForTransaction`. |
466
+ | Aptos | `aptos-entry-function` | Submit an entry function and implement `waitForTransaction`. |
467
+ | NEAR | `near-transaction-batch` | Submit NEAR transactions and implement `waitForTransactions`. |
468
+ | Tron | `tron-transfer` | Submit a native-token or token transfer and implement `waitForTransaction`. |
469
+ | Bitcoin | `bitcoin-transfer` | Submit a UTXO transfer and implement `waitForTransaction`. Configure `defaultFeeRate` when the build does not provide a fee rate. |
470
+ | Zcash | `zcash-transfer` | Submit a transparent-address transfer and implement `waitForTransaction`. |
471
+ | Sui | `sui-transfer` | Submit a coin transfer and implement `waitForTransaction`. |
472
+
473
+ Zcash follows the same standard as every other chain: a successful wallet submission must return a real transaction hash. The SDK never invents a transaction hash.
474
+
475
+ Every built-in wallet adapter must implement a confirmation method. It must return this normalized result instead of returning a chain-specific receipt directly:
125
476
 
126
477
  ```ts
127
- const bitcoinExecutor = createBitcoinExecutor(bitcoinWallet, {
128
- defaultFeeRate: 4,
129
- });
478
+ type TransactionConfirmation = {
479
+ status: "confirmed" | "failed";
480
+ raw?: unknown;
481
+ };
130
482
  ```
131
483
 
132
- Zcash adapters may return `{ requiresUserAction: true }` for legacy wallets that complete transfer confirmation in an external interface. The SDK returns `requires-user-action` without creating a fake transaction hash.
484
+ The adapter is responsible for interpreting its chain-specific receipt, including EVM `receipt.status`, Solana `meta.err`, Aptos execution success, NEAR final execution status, and the confirmation policy used for UTXO chains. The SDK rejects both `failed` and malformed confirmation statuses.
133
485
 
134
- `swap({ quote })` is the convenience form of `buildSwap({ quote })` followed by `executeSwap({ build })`. It does not request another quote.
486
+ For MCA quotes, the SDK may also read these methods from the registered executor:
135
487
 
136
- ## MCA swaps
488
+ - `getIdentityKey()` generates `mca.signer.identityKey` and is required for MCA quotes;
489
+ - `signMessage()` signs the exact API-provided message when required by an MCA relayer withdrawal.
137
490
 
138
- MCA deposit and withdrawal are execution modes of the unified root API. Use the same `client.quote()`, `client.buildSwap()`, `client.swap()`, `client.report()`, and `client.getHistory()` methods as a regular swap. The SDK does not create MCA accounts or query lending positions.
491
+ These are adapter capabilities. Application code calling `client.swap()` does not pass a separate signer.
139
492
 
140
- ### Deposit into an MCA
493
+ ## 7. EVM approvals
141
494
 
142
- The destination asset address is the Burrow token id expected by the Swap API. Execution reuses the registered source-chain executor.
495
+ When the swap API build response contains an `approval`, the EVM executor performs these steps in order:
496
+
497
+ 1. Call the optional `isApprovalRequired(approval)` method. If it is not implemented, approval is assumed to be required.
498
+ 2. Submit the approval transaction.
499
+ 3. Call the required `waitForTransaction` method and require a `confirmed` result.
500
+ 4. Submit the main swap transaction or request the EIP-712 signature.
501
+
502
+ Applications do not need to query allowances or inspect `needsApprove`. To avoid unnecessary approval transactions, implement `isApprovalRequired` in the adapter:
143
503
 
144
504
  ```ts
145
- const quote = await client.quote({
146
- flow: "deposit",
147
- mcaAccountId: "account.near",
148
- fromChain: "1",
149
- toChain: "near",
150
- tokenIn: ethereumUsdc,
151
- tokenOut: mcaUsdc,
152
- amountIn: "1000000",
153
- slippageBps: 50,
154
- sender: "0x...",
155
- recipient: "account.near",
156
- signerChain: "evm",
157
- collateral: {
158
- useAsCollateral: true,
505
+ const evmAdapter: EvmWalletAdapter = {
506
+ // ...sendTransaction, signTypedData, and other methods
507
+ async isApprovalRequired(approval) {
508
+ const allowance = await readAllowance(approval.spender);
509
+ return allowance < requiredAmount;
159
510
  },
160
- });
161
-
162
- const result = await client.swap({ quote, waitFor: "completed" });
511
+ };
163
512
  ```
164
513
 
165
- The report includes `multi_addr`. Its `tx_type` remains `same-chain` or `cross-chain`, matching the unified Swap API.
514
+ The lifecycle emits `approval-requested`, `approval-submitted`, and the subsequent signing or submission events in order.
515
+
516
+ ## 8. MCA deposits and withdrawals
517
+
518
+ MCA flows use the same `client.quote()` and `client.swap()` methods. The `flow` field distinguishes deposits from withdrawals. Applications do not branch on the returned router.
519
+
520
+ Common MCA fields:
166
521
 
167
- ### Withdraw directly to NEAR
522
+ | Field | Type | Required | Description |
523
+ | --- | --- | --- | --- |
524
+ | `flow` | `"deposit" \| "withdraw"` | Yes | MCA operation. |
525
+ | `mcaAccountId` | `string` | Yes | NEAR account ID of the MCA. |
526
+ | `signerChain` | `McaSignerChain` | Yes | Selects the registered executor that supplies identity and signing capabilities. |
527
+ | `recipientMsgSignatures` | `string[]` | No | Existing recipient-message signatures forwarded in the MCA payload. |
528
+ | `depositSignerProofSignatures` | `string[]` | No | Existing deposit-signer-proof signatures forwarded in the MCA payload. |
168
529
 
169
- Register a NEAR executor and request the NEAR path. The SDK parses `nearMcaWithdrawTx`, builds the MCA `exec` function call, and asks the injected NEAR wallet to send it. This path does not create an additional off-chain MCA message signature.
530
+ ### Deposit
170
531
 
171
532
  ```ts
172
533
  const quote = await client.quote({
173
- flow: "withdraw",
534
+ flow: "deposit",
174
535
  mcaAccountId: "account.near",
175
- fromChain: "near",
536
+ signerChain: "evm",
537
+ fromChain: "42161",
176
538
  toChain: "near",
177
- tokenIn: mcaUsdc,
178
- tokenOut: nearUsdc,
539
+ tokenIn: arbitrumUsdc,
540
+ tokenOut: mcaUsdc,
179
541
  amountIn: "1000000",
180
542
  slippageBps: 50,
181
- sender: "account.near",
182
- recipient: "alice.near",
183
- signerChain: "near",
543
+ sender: "0xYourAddress",
544
+ recipient: "account.near",
184
545
  collateral: {
185
- needDecrease: false,
186
- decreaseAmountBurrow: "0",
546
+ useAsCollateral: true,
187
547
  },
188
- executionPreference: "near",
189
- boundNearAccountId: "alice.near",
190
548
  });
191
549
 
192
- await client.swap({ quote, waitFor: "completed" });
550
+ const result = await client.swap({ quote, waitFor: "completed" });
193
551
  ```
194
552
 
195
- With `executionPreference: "auto"`, NEAR direct execution is selected only when the destination chain is NEAR and `recipient` exactly matches `boundNearAccountId`.
553
+ `collateral.useAsCollateral` is a required boolean that specifies whether the deposited asset should be used as Burrow collateral.
196
554
 
197
- ### Withdraw through the multichain relayer
198
-
199
- For other destination chains, expose `getIdentityKey()` and `signMessage()` on the connected wallet adapter used by its registered executor. The SDK signs the exact `messageToSign` returned by the API, then submits `mcaRelayer` through `POST /api/swap/swap`. No source-chain executor broadcasts a transaction for this path.
555
+ ### Withdraw
200
556
 
201
557
  ```ts
202
558
  const quote = await client.quote({
203
559
  flow: "withdraw",
204
560
  mcaAccountId: "account.near",
561
+ signerChain: "evm",
205
562
  fromChain: "near",
206
- toChain: "1",
563
+ toChain: "8453",
207
564
  tokenIn: mcaUsdc,
208
- tokenOut: ethereumUsdc,
565
+ tokenOut: baseUsdc,
209
566
  amountIn: "1000000",
210
567
  slippageBps: 50,
211
568
  sender: "account.near",
212
- recipient: wallet.address,
213
- signerChain: "evm",
569
+ recipient: "0xYourBaseAddress",
214
570
  collateral: {
215
571
  needDecrease: true,
216
- decreaseAmountBurrow: "1000000",
217
- withdrawAll: true,
572
+ decreaseAmountBurrow: "1.0",
573
+ withdrawAll: false,
218
574
  },
219
575
  executionPreference: "relayer",
220
576
  });
221
577
 
222
- await client.swap({
578
+ const result = await client.swap({
223
579
  quote,
224
580
  waitFor: "completed",
225
581
  beforeSign(preview) {
226
- showMcaSignatureConfirmation(preview);
582
+ console.log("MCA message signature preview", preview);
227
583
  },
228
584
  });
229
585
  ```
230
586
 
231
- Supported MCA signer identity formats are EVM, Solana, Bitcoin, NEAR, Aptos, Sui, Zcash, and Tron. Wallet implementations remain application-owned:
587
+ Withdraw-only fields:
232
588
 
233
- ```ts
234
- import {
235
- formatMcaWallet,
236
- selectMcaSigner,
237
- } from "@rhea-finance/cross-chain-aggregation-dex";
589
+ | Field | Type | Required | Description |
590
+ | --- | --- | --- | --- |
591
+ | `collateral.needDecrease` | `boolean` | Yes | Whether Burrow collateral must be decreased. |
592
+ | `collateral.decreaseAmountBurrow` | `string` | Yes | Human-readable Burrow decimal amount, such as `"1.0"`. This is not a token base-unit amount. |
593
+ | `collateral.withdrawAll` | `boolean` | No | Whether to withdraw the full available amount. |
594
+ | `executionPreference` | `"auto" \| "near" \| "relayer"` | No | Default: `"auto"`. Set explicitly to force direct NEAR or relayer execution. |
595
+ | `boundNearAccountId` | `string` | Required for automatic NEAR selection | In `auto` mode, direct NEAR execution is selected only when `toChain === "near"` and `recipient` exactly matches this field. Otherwise, the relayer is selected. |
238
596
 
239
- formatMcaWallet("evm", "0xAbC"); // { EVM: "AbC" }
597
+ For direct NEAR execution, the NEAR executor submits `nearMcaWithdrawTx`. For relayer execution, the executor selected by `signerChain` uses `signMessage()` to sign the API-provided `messageToSign`, after which the SDK submits the order. Application code only calls `swap()`.
240
598
 
241
- const signer = selectMcaSigner(boundMcaWallets, connectedSignerIdentities);
242
- ```
599
+ ## 9. Lifecycle, errors, and cancellation
243
600
 
244
- The executor registered for the selected chain must expose `signMessage` when the relayer preview requests a message signature. The SDK never receives a private key or recovery phrase.
245
-
246
- ### Collateral policy
247
-
248
- The SDK does not fetch a lending portfolio. Pass collateral decisions explicitly, or calculate the API fields from data already held by the application:
601
+ Lifecycle events can be observed globally on the client or for an individual swap:
249
602
 
250
603
  ```ts
251
- import { resolveMcaWithdrawPolicy } from "@rhea-finance/cross-chain-aggregation-dex";
252
-
253
- const collateral = resolveMcaWithdrawPolicy({
254
- collateralBalance: "12.5",
255
- availableBalance: "1000000",
256
- amountIn: "999999",
257
- isMax: false,
604
+ const client = new SwapClient({
605
+ baseUrl: "https://api.rhea.finance",
606
+ executors: [evmExecutor],
607
+ onEvent(event) {
608
+ console.log("Swap lifecycle", event);
609
+ },
258
610
  });
259
611
  ```
260
612
 
261
- `withdrawAll` becomes true for max selection, exact available balance, or a ratio of at least `0.999999`. The calculation uses decimal strings and `BigInt`, not floating-point arithmetic.
613
+ Events may cover build, approval, signing, submission, source confirmation, order status, completion, warnings, and failures.
262
614
 
263
- MCA history uses the MCA account id as the server-side history search key. The backend matches this value against `sender`, `recipient`, and `multi_addr`:
615
+ SDK errors use the `SwapSdkError` type:
264
616
 
265
617
  ```ts
266
- const history = await client.getHistory({
267
- sender: "account.near",
268
- });
618
+ import { SwapSdkError } from "@rhea-finance/cross-chain-aggregation-dex";
619
+
620
+ try {
621
+ await client.swap({ quote });
622
+ } catch (error) {
623
+ if (error instanceof SwapSdkError) {
624
+ console.error({
625
+ code: error.code,
626
+ stage: error.stage,
627
+ message: error.message,
628
+ retryable: error.retryable,
629
+ cause: error.cause,
630
+ details: error.details,
631
+ });
632
+ }
633
+ }
269
634
  ```
270
635
 
271
- The SDK preserves the server page instead of filtering `record.multi_addr` again. Address fields may be presentation-normalized by the API, so callers should not require exact equality with the MCA account id.
272
-
273
- ## API surfaces
274
-
275
- Normalized methods:
276
-
277
- - `quote()`
278
- - `buildSwap()`
279
- - `executeSwap()` and `swap()`
280
- - `getOrderStatus()` and `waitForOrder()`
281
- - `report()` and `retryReport()`
282
- - `getHistory()`
283
-
284
- Raw methods preserve the unified API `data` shape:
285
-
286
- - `quoteRaw()`
287
- - `buildRaw()`
288
- - `submitOrderRaw()`
289
- - `getOrderStatusRaw()`
290
- - `reportRaw()`
291
- - `getHistoryRaw()`
292
-
293
-
294
-
295
- ## Execution kinds
296
-
297
- Build responses are validated and represented as a discriminated union:
298
-
299
- - `evm-transaction`
300
- - `evm-signature`
301
- - `solana-transaction`
302
- - `aptos-entry-function`
303
- - `near-transaction-batch`
304
- - `tron-transfer`
305
- - `bitcoin-transfer`
306
- - `zcash-transfer`
307
- - `sui-transfer`
308
-
309
- The SDK core defines the executor contract and registry. Wallet-specific implementations are injected by the application, so importing the package does not access browser wallet globals.
310
-
311
- ## Runtime and credentials
312
-
313
- - Browsers and Node.js 18+ use the global Fetch API.
314
- - Node.js 16 requires a compatible `fetch` implementation through `new SwapClient({ fetch })`.
315
- - Supply credentials with `apiKey` or `getAccessToken`; when both are present, `getAccessToken` takes precedence.
316
- - The package contains no fixed API credential and never manages private keys or wallet recovery phrases.
317
- - Use `AbortSignal` on network, build, execute, and polling calls when cancellation is required.
636
+ Common `stage` values are `quote`, `build`, `approve`, `sign`, `broadcast`, `submit`, `report`, `status`, and `history`. Common `code` values include `QUOTE_EXPIRED`, `USER_REJECTED`, `APPROVAL_FAILED`, `SIGNING_FAILED`, `BROADCAST_FAILED`, and `ORDER_TIMEOUT`.
318
637
 
638
+ Pass an `AbortSignal` to stop an unfinished request or wait:
319
639
 
640
+ ```ts
641
+ const controller = new AbortController();
642
+ const promise = client.swap({ quote, signal: controller.signal });
643
+ controller.abort();
644
+ await promise;
645
+ ```
320
646
 
321
- ## Retry and logging
647
+ Cancellation only stops the SDK's current work. It cannot revert an approval, signature, or transaction that has already been submitted.
322
648
 
323
- Quote, history, and order-status requests retry network errors, timeouts, HTTP 429, and retryable 5xx responses twice by default. Build, report, order submission, and wallet execution are never retried automatically.
649
+ ## 10. Retries, logging, and credentials
324
650
 
325
651
  ```ts
326
652
  const client = new SwapClient({
327
653
  baseUrl: "https://api.rhea.finance",
654
+ getAccessToken: async () => authStore.getToken(),
328
655
  retry: {
329
656
  maxRetries: 2,
330
657
  baseDelayMs: 250,
331
- maxDelayMs: 2_000,
658
+ maxDelayMs: 2000,
332
659
  jitter: true,
333
660
  },
334
661
  logger: {
335
662
  log(entry) {
336
- telemetry.emit(entry.event, entry);
663
+ console.log("SDK API", entry);
337
664
  },
338
665
  },
339
666
  });
340
667
  ```
341
668
 
342
- Log entries contain only request stage, endpoint path, attempt, response status, timing, and SDK error code. They do not include credentials, query strings, request bodies, signatures, or serialized transactions.
669
+ The SDK automatically retries only retryable quote/read operations. It does not automatically retry build, broadcast, or order-submission operations that could execute twice. Network failures preserve the underlying error name and message to help diagnose CORS failures, connection resets, timeouts, or fetch invocation problems.
343
670
 
344
- ## Amount conversion
671
+ ## 11. Raw API, reporting, and history
345
672
 
346
- `parseUnits` and `formatUnits` use string arithmetic and never pass token values through floating-point numbers:
673
+ Most applications should use normalized methods. Use the Raw API only when the complete original server fields are required:
674
+
675
+ ```ts
676
+ await client.quoteRaw(rawQuoteRequest);
677
+ await client.buildRaw(rawBuildRequest);
678
+ await client.submitOrderRaw(rawSubmitRequest);
679
+ await client.getOrderStatusRaw(rawStatusRequest);
680
+ await client.reportRaw(rawReportRequest);
681
+ await client.getHistoryRaw(rawHistoryRequest);
682
+ ```
683
+
684
+ The default reporting mode is `reportMode: "auto"`. If a swap succeeds but reporting fails, `result.report.status` is `"failed"` and a warning is emitted. The SDK does not throw a misleading swap failure. For manual reporting:
685
+
686
+ ```ts
687
+ const client = new SwapClient({
688
+ baseUrl: "https://api.rhea.finance",
689
+ executors: [evmExecutor],
690
+ reportMode: "manual",
691
+ });
692
+
693
+ const result = await client.swap({ quote });
694
+ await client.report(result);
695
+
696
+ // Retry after a reporting failure:
697
+ await client.retryReport(result);
698
+ ```
699
+
700
+ Query history with:
701
+
702
+ ```ts
703
+ const history = await client.getHistory({
704
+ sender: "0xYourAddress",
705
+ page: 1,
706
+ pageSize: 20,
707
+ status: ["processing", "completed"],
708
+ });
709
+ ```
710
+
711
+ The SDK applies `status` filtering locally. The returned page has `filteredLocally: true`.
712
+
713
+ ## 12. Amount utilities
714
+
715
+ Avoid JavaScript floating-point arithmetic for token amounts:
347
716
 
348
717
  ```ts
349
718
  import {
@@ -351,16 +720,8 @@ import {
351
720
  parseUnits,
352
721
  } from "@rhea-finance/cross-chain-aggregation-dex";
353
722
 
354
- parseUnits("1.25", 6); // "1250000"
723
+ parseUnits("1.25", 6); // "1250000"
355
724
  formatUnits("1250000", 6); // "1.25"
356
725
  ```
357
726
 
358
- Both functions reject negative values, scientific notation, malformed input, and unsupported precision. Token decimals must be an integer between 0 and 255.
359
-
360
- ## History filtering
361
-
362
- The service handles sender and pagination. `getHistory({ status })` filters the current returned page locally and sets `filteredLocally: true`; server totals remain unchanged.
363
-
364
- ## License
365
-
366
- MIT
727
+ `parseUnits()` rejects fractional precision beyond the token's decimals. `formatUnits()` accepts only non-negative base-unit decimal integer strings.