@trustware/sdk-staging 1.1.11-staging.1 → 1.1.12-staging.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 +54 -21
- package/dist/{blockchain-BxAFzp0s.d.cts → blockchain-DmCPxnxr.d.cts} +25 -1
- package/dist/{blockchain-BxAFzp0s.d.ts → blockchain-DmCPxnxr.d.ts} +25 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.mjs +1 -1
- package/dist/{core-BgYLe9Q7.d.ts → core-B4YDGtJT.d.ts} +3 -3
- package/dist/{core-fLSt4qD2.d.cts → core-Ck7dinYj.d.cts} +3 -3
- package/dist/core.cjs +141 -52
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +4 -4
- package/dist/core.d.ts +4 -4
- package/dist/core.mjs +139 -51
- package/dist/core.mjs.map +1 -1
- package/dist/index.cjs +166 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -8
- package/dist/index.d.ts +14 -8
- package/dist/index.mjs +164 -75
- package/dist/index.mjs.map +1 -1
- package/dist/{manager-DT8enQbE.d.cts → manager-BZ8gyHGT.d.cts} +90 -23
- package/dist/{manager-BY3NHAks.d.ts → manager-D8nQsod2.d.ts} +90 -23
- package/dist/{metadata-DyxUcKHk.d.cts → metadata-B23D0oO9.d.cts} +1 -1
- package/dist/{metadata-BPvFYMlc.d.ts → metadata-BOjEF7oo.d.ts} +1 -1
- package/dist/smart-account.cjs +62 -47
- package/dist/smart-account.cjs.map +1 -1
- package/dist/smart-account.d.cts +6 -0
- package/dist/smart-account.d.ts +6 -0
- package/dist/smart-account.mjs +62 -47
- package/dist/smart-account.mjs.map +1 -1
- package/dist/{types-BJY9r-mz.d.ts → types-CMmx0S4U.d.ts} +1 -1
- package/dist/{types-DX3HtFcn.d.cts → types-DEUb5IZA.d.cts} +1 -1
- package/dist/wallet.cjs +51 -40
- package/dist/wallet.cjs.map +1 -1
- package/dist/wallet.d.cts +4 -4
- package/dist/wallet.d.ts +4 -4
- package/dist/wallet.mjs +51 -40
- package/dist/wallet.mjs.map +1 -1
- package/dist/widget.cjs +160 -75
- package/dist/widget.cjs.map +1 -1
- package/dist/widget.d.cts +2 -2
- package/dist/widget.d.ts +2 -2
- package/dist/widget.mjs +160 -75
- package/dist/widget.mjs.map +1 -1
- package/package.json +74 -5
package/README.md
CHANGED
|
@@ -37,8 +37,6 @@ The current widget flow is:
|
|
|
37
37
|
|
|
38
38
|
`Home -> Select Token -> Confirm Deposit -> Processing -> Success/Error`
|
|
39
39
|
|
|
40
|
-
The refactored widget keeps the same behavior, but the configuration surface is now documented around the actual `TrustwareConfigOptions` shape and the current widget step model.
|
|
41
|
-
|
|
42
40
|
## Installation
|
|
43
41
|
|
|
44
42
|
Supports React `18.2+` and `19`.
|
|
@@ -115,7 +113,7 @@ type TrustwareConfigOptions = {
|
|
|
115
113
|
};
|
|
116
114
|
};
|
|
117
115
|
autoDetectProvider?: boolean;
|
|
118
|
-
theme?:
|
|
116
|
+
theme?: "light" | "dark" | "system"; // TrustwareTheme
|
|
119
117
|
messages?: Partial<TrustwareWidgetMessages>;
|
|
120
118
|
retry?: RetryConfig;
|
|
121
119
|
walletConnect?: WalletConnectConfig;
|
|
@@ -172,7 +170,8 @@ type TrustwareConfigOptions = {
|
|
|
172
170
|
### Other Config Groups
|
|
173
171
|
|
|
174
172
|
- `autoDetectProvider`: enables Trustware-managed wallet discovery.
|
|
175
|
-
- `theme`: widget color
|
|
173
|
+
- `theme`: widget color mode — `"light" | "dark" | "system"` (default
|
|
174
|
+
`"system"`). Switch it at runtime with `Trustware.setTheme("dark")`.
|
|
176
175
|
- `messages`: top-level copy overrides.
|
|
177
176
|
- `retry`: API retry and rate-limit behavior.
|
|
178
177
|
- `walletConnect`: WalletConnect overrides.
|
|
@@ -232,6 +231,13 @@ export function DepositPanel() {
|
|
|
232
231
|
}
|
|
233
232
|
```
|
|
234
233
|
|
|
234
|
+
`useWagmi` (like `useEIP1193`) is a plain adapter factory, not a React hook,
|
|
235
|
+
despite the `use` prefix. If your ESLint setup runs `react-hooks/rules-of-hooks`
|
|
236
|
+
it will flag the call inside the `useMemo` callback above; silence it with an
|
|
237
|
+
`eslint-disable-next-line react-hooks/rules-of-hooks` comment — the call is
|
|
238
|
+
safe. See [docs.trustware.io](https://docs.trustware.io/guides/embedded-wallets#adapt-the-embedded-wallet)
|
|
239
|
+
for the same pattern with embedded wallets.
|
|
240
|
+
|
|
235
241
|
Use this mode when:
|
|
236
242
|
|
|
237
243
|
- your app already owns wallet state
|
|
@@ -285,19 +291,28 @@ Use this when you want Trustware’s routing and wallet plumbing without the wid
|
|
|
285
291
|
```ts
|
|
286
292
|
import { Trustware } from "@trustware/sdk";
|
|
287
293
|
|
|
294
|
+
// buildRoute states both sides explicitly. fromAmount is in the source token's
|
|
295
|
+
// smallest unit, and the estimate comes back on the route — there is no
|
|
296
|
+
// separate quote call.
|
|
288
297
|
const route = await Trustware.buildRoute({
|
|
289
|
-
|
|
298
|
+
fromChain: "1",
|
|
299
|
+
fromToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC on Ethereum
|
|
300
|
+
toChain: "8453",
|
|
301
|
+
toToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", // native on Base
|
|
302
|
+
fromAmount: "25000000", // 25 USDC (6 decimals)
|
|
290
303
|
fromAddress: await Trustware.getAddress(),
|
|
304
|
+
toAddress: "0xDestination...",
|
|
291
305
|
});
|
|
306
|
+
console.log(route.route?.estimate, route.finalExchangeRate);
|
|
292
307
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
fromAddress: await Trustware.getAddress(),
|
|
298
|
-
});
|
|
308
|
+
// Or let the SDK own route + submit + receipt + polling. Missing route fields
|
|
309
|
+
// come from the provider config; the sender comes from the attached wallet.
|
|
310
|
+
const tx = await Trustware.runTopUp({ fromAmount: "25000000" });
|
|
311
|
+
console.log(tx.status, tx.destTxHash);
|
|
299
312
|
```
|
|
300
313
|
|
|
314
|
+
See [docs.trustware.io](https://docs.trustware.io) for the full headless flow.
|
|
315
|
+
|
|
301
316
|
## Common Config Examples
|
|
302
317
|
|
|
303
318
|
### Fixed Amount Deposit
|
|
@@ -347,26 +362,44 @@ Trustware.setDestinationAddress("0xDestination...");
|
|
|
347
362
|
|
|
348
363
|
## Rate Limiting
|
|
349
364
|
|
|
350
|
-
|
|
365
|
+
The API is rate limited per API key, and that limit is shared by everyone using
|
|
366
|
+
your key — not per end user. Your key's limit, its remaining requests and the
|
|
367
|
+
window boundary come back on every response (`X-RateLimit-Limit`, `-Remaining`,
|
|
368
|
+
`-Reset`, plus `Retry-After` on a 429).
|
|
369
|
+
|
|
370
|
+
The SDK retries 429s on the schedule those headers state — it keeps no schedule
|
|
371
|
+
of its own to disagree with them. It waits exactly as long as the server asks,
|
|
372
|
+
for as long as the total stays under 10 seconds. Past that it stops and throws,
|
|
373
|
+
because how long your app can afford to block is the one thing the server can't
|
|
374
|
+
know. If a response carries no timing at all, the SDK stops rather than
|
|
375
|
+
guessing: the limit is a fixed window, so an invented delay either lands inside
|
|
376
|
+
the same closed window or overshoots one it could have read exactly.
|
|
377
|
+
|
|
378
|
+
None of that is configurable — the limit is enforced server-side, so no client
|
|
379
|
+
setting can widen it. If you need more headroom, ask us to raise the limit on
|
|
380
|
+
your key. `retry` configures observability only:
|
|
351
381
|
|
|
352
382
|
```ts
|
|
353
383
|
const config = {
|
|
354
384
|
...trustwareConfig,
|
|
355
385
|
retry: {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
386
|
+
onRateLimitInfo: (info) => console.debug(info.remaining, "requests left"),
|
|
387
|
+
onRateLimited: (info, attempt) => console.warn("429", attempt, info),
|
|
388
|
+
onRateLimitApproaching: (info) => showSoftWarning(info),
|
|
359
389
|
approachingThreshold: 5,
|
|
360
390
|
},
|
|
361
391
|
} satisfies TrustwareConfigOptions;
|
|
362
392
|
```
|
|
363
393
|
|
|
364
|
-
|
|
394
|
+
`RateLimitError` distinguishes the two ways the SDK gives up:
|
|
395
|
+
|
|
396
|
+
- `retriesExhausted: false` — the wait is known and simply longer than the SDK
|
|
397
|
+
will block for. `rateLimitInfo.retryAfter` holds it, so show the user when to
|
|
398
|
+
come back instead of leaving them on a spinner.
|
|
399
|
+
- `retriesExhausted: true` — the response carried no usable timing, so there was
|
|
400
|
+
nothing to retry against.
|
|
365
401
|
|
|
366
402
|
## Docs
|
|
367
403
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
- [Backend RPC Offload PDR](docs/backend-rpc-offload-pdr.md)
|
|
371
|
-
- [Widget Architecture Boundaries](docs/widget-architecture-boundaries.md)
|
|
372
|
-
- [Widget Refactor Baseline](docs/widget-refactor-baseline.md)
|
|
404
|
+
Full API reference, integration guides, and examples live at
|
|
405
|
+
[docs.trustware.io](https://docs.trustware.io).
|
|
@@ -47,10 +47,34 @@ type TokenPageResult = {
|
|
|
47
47
|
data: TokenDef[];
|
|
48
48
|
pageInfo: TokenPageInfo;
|
|
49
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* Terminal state of an address balance scan.
|
|
52
|
+
*
|
|
53
|
+
* `partial` is the one field a caller cannot reconstruct from the chunks: the
|
|
54
|
+
* backend scans every configured chain and reports `partial: true` when any of
|
|
55
|
+
* them failed, so "no balance on chain X" and "we could not reach chain X" look
|
|
56
|
+
* identical in the rows themselves. Rendering an empty wallet off a partial
|
|
57
|
+
* scan is the failure this exists to prevent.
|
|
58
|
+
*/
|
|
59
|
+
type BalanceStreamSummary = {
|
|
60
|
+
address: string;
|
|
61
|
+
partial: boolean;
|
|
62
|
+
/** Chains that reported a result — equal to `total` on a complete scan. */
|
|
63
|
+
completed: number;
|
|
64
|
+
total: number;
|
|
65
|
+
/** Server-side scan duration. Absent on the buffered path, which does not report it. */
|
|
66
|
+
elapsedMs?: number;
|
|
67
|
+
};
|
|
50
68
|
type BalanceStreamOptions = {
|
|
51
69
|
stream?: boolean;
|
|
52
70
|
signal?: AbortSignal;
|
|
53
71
|
strict?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Called once per scan with its terminal state, on the streamed and buffered
|
|
74
|
+
* paths alike — including when a stream fails and falls back — so a consumer
|
|
75
|
+
* can trust `partial` without knowing which path served it.
|
|
76
|
+
*/
|
|
77
|
+
onSummary?: (summary: BalanceStreamSummary) => void;
|
|
54
78
|
};
|
|
55
79
|
type GetBalancesOptions = {
|
|
56
80
|
/** Bypass the in-memory balance cache and re-fetch fresh data from the network. */
|
|
@@ -111,4 +135,4 @@ type TokenWithBalance = TokenDef & {
|
|
|
111
135
|
balance?: bigint;
|
|
112
136
|
};
|
|
113
137
|
|
|
114
|
-
export type { BalanceRow as B, ChainDef as C, GetBalancesOptions as G, NativeCurrency as N, TokenDef as T, WalletAddressBalanceWrapper as W, BalanceStreamOptions as a,
|
|
138
|
+
export type { BalanceRow as B, ChainDef as C, GetBalancesOptions as G, NativeCurrency as N, TokenDef as T, WalletAddressBalanceWrapper as W, BalanceStreamOptions as a, BalanceStreamSummary as b, ChainMeta as c, ChainType as d, TokenMeta as e, TokenPageInfo as f, TokenPageOptions as g, TokenPageResult as h, TokenType as i, TokenWithBalance as j };
|
|
@@ -47,10 +47,34 @@ type TokenPageResult = {
|
|
|
47
47
|
data: TokenDef[];
|
|
48
48
|
pageInfo: TokenPageInfo;
|
|
49
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* Terminal state of an address balance scan.
|
|
52
|
+
*
|
|
53
|
+
* `partial` is the one field a caller cannot reconstruct from the chunks: the
|
|
54
|
+
* backend scans every configured chain and reports `partial: true` when any of
|
|
55
|
+
* them failed, so "no balance on chain X" and "we could not reach chain X" look
|
|
56
|
+
* identical in the rows themselves. Rendering an empty wallet off a partial
|
|
57
|
+
* scan is the failure this exists to prevent.
|
|
58
|
+
*/
|
|
59
|
+
type BalanceStreamSummary = {
|
|
60
|
+
address: string;
|
|
61
|
+
partial: boolean;
|
|
62
|
+
/** Chains that reported a result — equal to `total` on a complete scan. */
|
|
63
|
+
completed: number;
|
|
64
|
+
total: number;
|
|
65
|
+
/** Server-side scan duration. Absent on the buffered path, which does not report it. */
|
|
66
|
+
elapsedMs?: number;
|
|
67
|
+
};
|
|
50
68
|
type BalanceStreamOptions = {
|
|
51
69
|
stream?: boolean;
|
|
52
70
|
signal?: AbortSignal;
|
|
53
71
|
strict?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Called once per scan with its terminal state, on the streamed and buffered
|
|
74
|
+
* paths alike — including when a stream fails and falls back — so a consumer
|
|
75
|
+
* can trust `partial` without knowing which path served it.
|
|
76
|
+
*/
|
|
77
|
+
onSummary?: (summary: BalanceStreamSummary) => void;
|
|
54
78
|
};
|
|
55
79
|
type GetBalancesOptions = {
|
|
56
80
|
/** Bypass the in-memory balance cache and re-fetch fresh data from the network. */
|
|
@@ -111,4 +135,4 @@ type TokenWithBalance = TokenDef & {
|
|
|
111
135
|
balance?: bigint;
|
|
112
136
|
};
|
|
113
137
|
|
|
114
|
-
export type { BalanceRow as B, ChainDef as C, GetBalancesOptions as G, NativeCurrency as N, TokenDef as T, WalletAddressBalanceWrapper as W, BalanceStreamOptions as a,
|
|
138
|
+
export type { BalanceRow as B, ChainDef as C, GetBalancesOptions as G, NativeCurrency as N, TokenDef as T, WalletAddressBalanceWrapper as W, BalanceStreamOptions as a, BalanceStreamSummary as b, ChainMeta as c, ChainType as d, TokenMeta as e, TokenPageInfo as f, TokenPageOptions as g, TokenPageResult as h, TokenType as i, TokenWithBalance as j };
|
package/dist/constants.cjs
CHANGED
|
@@ -30,7 +30,7 @@ __export(constants_exports, {
|
|
|
30
30
|
});
|
|
31
31
|
module.exports = __toCommonJS(constants_exports);
|
|
32
32
|
var SDK_NAME = "@trustware/sdk";
|
|
33
|
-
var SDK_VERSION = "1.1.
|
|
33
|
+
var SDK_VERSION = "1.1.12-staging.1";
|
|
34
34
|
var API_ROOT = "https://bv-staging-api.trustware.io";
|
|
35
35
|
var GTM_ID = "GTM-TZDGNCXB";
|
|
36
36
|
var API_PREFIX = "/api";
|
package/dist/constants.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as BuildRouteResult, k as Transaction, T as TrustwareConfigOptions, i as WalletInterFaceAPI,
|
|
2
|
-
import { C as ChainDef,
|
|
3
|
-
import { T as Token } from './types-
|
|
1
|
+
import { n as BuildRouteResult, k as Transaction, T as TrustwareConfigOptions, i as WalletInterFaceAPI, A as ResolvedTrustwareConfig, X as TrustwareTheme, a2 as WalletIdentity, w as walletManager, Z as WalletAddressResolution, aa as buildRoute, ab as buildDepositAddress, ac as submitReceipt, ad as submitStepReceipt, ae as getStatus, af as pollStatus } from './manager-D8nQsod2.js';
|
|
2
|
+
import { C as ChainDef, d as ChainType, G as GetBalancesOptions, B as BalanceRow, a as BalanceStreamOptions, W as WalletAddressBalanceWrapper } from './blockchain-DmCPxnxr.js';
|
|
3
|
+
import { T as Token } from './types-CMmx0S4U.js';
|
|
4
4
|
|
|
5
5
|
type AddressValidationResult = {
|
|
6
6
|
isValid: boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as BuildRouteResult, k as Transaction, T as TrustwareConfigOptions, i as WalletInterFaceAPI,
|
|
2
|
-
import { C as ChainDef,
|
|
3
|
-
import { T as Token } from './types-
|
|
1
|
+
import { n as BuildRouteResult, k as Transaction, T as TrustwareConfigOptions, i as WalletInterFaceAPI, A as ResolvedTrustwareConfig, X as TrustwareTheme, a2 as WalletIdentity, w as walletManager, Z as WalletAddressResolution, aa as buildRoute, ab as buildDepositAddress, ac as submitReceipt, ad as submitStepReceipt, ae as getStatus, af as pollStatus } from './manager-BZ8gyHGT.cjs';
|
|
2
|
+
import { C as ChainDef, d as ChainType, G as GetBalancesOptions, B as BalanceRow, a as BalanceStreamOptions, W as WalletAddressBalanceWrapper } from './blockchain-DmCPxnxr.cjs';
|
|
3
|
+
import { T as Token } from './types-DEUb5IZA.cjs';
|
|
4
4
|
|
|
5
5
|
type AddressValidationResult = {
|
|
6
6
|
isValid: boolean;
|
package/dist/core.cjs
CHANGED
|
@@ -47,19 +47,27 @@ var init_defaults = __esm({
|
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
// src/types/config.ts
|
|
50
|
-
var DEFAULT_RETRY_CONFIG, DEFAULT_FEATURE_FLAGS;
|
|
50
|
+
var DEFAULT_RETRY_CONFIG, RATE_LIMIT_WAIT_BUDGET_MS, DEFAULT_FEATURE_FLAGS;
|
|
51
51
|
var init_config = __esm({
|
|
52
52
|
"src/types/config.ts"() {
|
|
53
53
|
"use strict";
|
|
54
54
|
DEFAULT_RETRY_CONFIG = {
|
|
55
|
-
autoRetry: true,
|
|
56
|
-
maxRetries: 3,
|
|
57
|
-
baseDelayMs: 1e3,
|
|
58
55
|
approachingThreshold: 5
|
|
59
56
|
};
|
|
57
|
+
RATE_LIMIT_WAIT_BUDGET_MS = 1e4;
|
|
60
58
|
DEFAULT_FEATURE_FLAGS = {
|
|
61
59
|
tokensPagination: true,
|
|
62
|
-
|
|
60
|
+
// On by default: an address scan covers every configured chain and takes
|
|
61
|
+
// seconds end to end, so streaming turns one long wait into a wallet that
|
|
62
|
+
// fills in as results land — first chunk in ~200ms against a ~2.3s buffered
|
|
63
|
+
// response, measured on a live backend.
|
|
64
|
+
//
|
|
65
|
+
// Safe to default because the path degrades on its own: a backend with
|
|
66
|
+
// BALANCE_STREAM_ENABLED off refuses the stream, and the SDK falls back to
|
|
67
|
+
// the buffered endpoint (emitting balance_stream_fallback), as does any
|
|
68
|
+
// runtime whose fetch has no readable body — React Native, most notably.
|
|
69
|
+
// The cost of defaulting ahead of a backend is one refused request per scan.
|
|
70
|
+
balanceStreaming: true,
|
|
63
71
|
shouldAllowGA4: true,
|
|
64
72
|
swapMode: false,
|
|
65
73
|
swapDefaultDestToken: null,
|
|
@@ -75,7 +83,7 @@ var init_constants = __esm({
|
|
|
75
83
|
"src/constants.ts"() {
|
|
76
84
|
"use strict";
|
|
77
85
|
SDK_NAME = "@trustware/sdk";
|
|
78
|
-
SDK_VERSION = "1.1.
|
|
86
|
+
SDK_VERSION = "1.1.12-staging.1";
|
|
79
87
|
API_ROOT = "https://bv-staging-api.trustware.io";
|
|
80
88
|
API_PREFIX = "/api";
|
|
81
89
|
WALLETCONNECT_PROJECT_ID = "72ea74c400f5111d43aea638d7d83a24";
|
|
@@ -118,7 +126,7 @@ async function assertOK(r) {
|
|
|
118
126
|
throw new Error(`HTTP ${r.status}: ${msg}`);
|
|
119
127
|
}
|
|
120
128
|
async function validateSdkAccess() {
|
|
121
|
-
const r = await fetch(`${apiBase()}/sdk/validate`, {
|
|
129
|
+
const r = await fetch(`${apiBase()}/v1/sdk/validate`, {
|
|
122
130
|
method: "GET",
|
|
123
131
|
headers: jsonHeaders()
|
|
124
132
|
});
|
|
@@ -157,50 +165,54 @@ function notifyRateLimitCallbacks(info, isRateLimited, retryCount) {
|
|
|
157
165
|
retry.onRateLimitApproaching(info, retry.approachingThreshold);
|
|
158
166
|
}
|
|
159
167
|
}
|
|
160
|
-
function
|
|
161
|
-
if (
|
|
162
|
-
|
|
168
|
+
function serverDirectedWaitMs(info) {
|
|
169
|
+
if (!info) return null;
|
|
170
|
+
if (typeof info.retryAfter === "number" && info.retryAfter > 0) {
|
|
171
|
+
return info.retryAfter * 1e3;
|
|
163
172
|
}
|
|
164
|
-
|
|
173
|
+
if (typeof info.reset === "number" && info.reset > 0) {
|
|
174
|
+
const untilReset = info.reset * 1e3 - Date.now();
|
|
175
|
+
if (untilReset > 0) return untilReset;
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
165
178
|
}
|
|
166
179
|
function sleep(ms) {
|
|
167
180
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
168
181
|
}
|
|
169
|
-
async function
|
|
170
|
-
|
|
171
|
-
const cfg = TrustwareConfigStore.get();
|
|
172
|
-
if (!cfg.retry.autoRetry || skipRateLimit) {
|
|
173
|
-
return fetch(url, fetchOptions);
|
|
174
|
-
}
|
|
175
|
-
const { maxRetries, baseDelayMs } = cfg.retry;
|
|
182
|
+
async function withRateLimitRetry(attempt) {
|
|
183
|
+
let waitedMs = 0;
|
|
176
184
|
let retryCount = 0;
|
|
177
185
|
while (true) {
|
|
178
|
-
const response = await
|
|
186
|
+
const response = await attempt();
|
|
179
187
|
const rateLimitInfo = parseRateLimitHeaders(response);
|
|
180
|
-
if (response.status
|
|
188
|
+
if (response.status !== 429) {
|
|
181
189
|
if (rateLimitInfo) {
|
|
182
|
-
notifyRateLimitCallbacks(rateLimitInfo,
|
|
183
|
-
}
|
|
184
|
-
if (retryCount >= maxRetries) {
|
|
185
|
-
throw new RateLimitError(
|
|
186
|
-
rateLimitInfo || { limit: 0, remaining: 0, reset: 0 },
|
|
187
|
-
true
|
|
188
|
-
);
|
|
190
|
+
notifyRateLimitCallbacks(rateLimitInfo, false, 0);
|
|
189
191
|
}
|
|
190
|
-
|
|
191
|
-
baseDelayMs,
|
|
192
|
-
retryCount,
|
|
193
|
-
rateLimitInfo?.retryAfter
|
|
194
|
-
);
|
|
195
|
-
await sleep(delay);
|
|
196
|
-
retryCount++;
|
|
197
|
-
continue;
|
|
192
|
+
return response;
|
|
198
193
|
}
|
|
199
194
|
if (rateLimitInfo) {
|
|
200
|
-
notifyRateLimitCallbacks(rateLimitInfo,
|
|
195
|
+
notifyRateLimitCallbacks(rateLimitInfo, true, retryCount);
|
|
196
|
+
}
|
|
197
|
+
const waitMs = serverDirectedWaitMs(rateLimitInfo);
|
|
198
|
+
const info = rateLimitInfo || { limit: 0, remaining: 0, reset: 0 };
|
|
199
|
+
if (waitMs === null) {
|
|
200
|
+
throw new RateLimitError(info, true);
|
|
201
201
|
}
|
|
202
|
-
|
|
202
|
+
if (waitedMs + waitMs > RATE_LIMIT_WAIT_BUDGET_MS) {
|
|
203
|
+
throw new RateLimitError(info, false);
|
|
204
|
+
}
|
|
205
|
+
await sleep(waitMs);
|
|
206
|
+
waitedMs += waitMs;
|
|
207
|
+
retryCount++;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async function rateLimitedFetch(url, options = {}) {
|
|
211
|
+
const { skipRateLimit, ...fetchOptions } = options;
|
|
212
|
+
if (skipRateLimit) {
|
|
213
|
+
return fetch(url, fetchOptions);
|
|
203
214
|
}
|
|
215
|
+
return withRateLimitRetry(() => fetch(url, fetchOptions));
|
|
204
216
|
}
|
|
205
217
|
var RateLimitError;
|
|
206
218
|
var init_http = __esm({
|
|
@@ -208,9 +220,11 @@ var init_http = __esm({
|
|
|
208
220
|
"use strict";
|
|
209
221
|
init_constants();
|
|
210
222
|
init_config2();
|
|
223
|
+
init_config();
|
|
211
224
|
RateLimitError = class extends Error {
|
|
212
225
|
constructor(info, retriesExhausted) {
|
|
213
|
-
const
|
|
226
|
+
const seconds = info.retryAfter ?? (info.reset > 0 ? Math.max(0, Math.ceil((info.reset * 1e3 - Date.now()) / 1e3)) : null);
|
|
227
|
+
const message = seconds === null ? "Rate limit exceeded. The server did not say when to retry." : `Rate limit exceeded. Try again in ${seconds} seconds.`;
|
|
214
228
|
super(message);
|
|
215
229
|
this.name = "RateLimitError";
|
|
216
230
|
this.rateLimitInfo = info;
|
|
@@ -1795,6 +1809,16 @@ function mergeBalanceWrappers(current, incoming) {
|
|
|
1795
1809
|
}
|
|
1796
1810
|
return Array.from(merged.values());
|
|
1797
1811
|
}
|
|
1812
|
+
function toSummary(frame, address) {
|
|
1813
|
+
const total = toNumberOrUndefined(frame.total) ?? 0;
|
|
1814
|
+
return {
|
|
1815
|
+
address: toStringOrUndefined(frame.address) ?? address,
|
|
1816
|
+
partial: Boolean(frame.partial),
|
|
1817
|
+
completed: toNumberOrUndefined(frame.completed) ?? 0,
|
|
1818
|
+
total,
|
|
1819
|
+
elapsedMs: toNumberOrUndefined(frame.elapsed)
|
|
1820
|
+
};
|
|
1821
|
+
}
|
|
1798
1822
|
async function parseStreamingBalances(response, address, options = {}) {
|
|
1799
1823
|
if (!response.body) {
|
|
1800
1824
|
throw new Error("balances stream: empty response body");
|
|
@@ -1815,7 +1839,12 @@ async function parseStreamingBalances(response, address, options = {}) {
|
|
|
1815
1839
|
if (!trimmed) continue;
|
|
1816
1840
|
try {
|
|
1817
1841
|
const parsed = JSON.parse(trimmed);
|
|
1818
|
-
if (!parsed.chain_id)
|
|
1842
|
+
if (!parsed.chain_id) {
|
|
1843
|
+
if (parsed.type === "summary") {
|
|
1844
|
+
options.onSummary?.(toSummary(parsed, address));
|
|
1845
|
+
}
|
|
1846
|
+
continue;
|
|
1847
|
+
}
|
|
1819
1848
|
const chunk = normalizeStreamChunk(parsed);
|
|
1820
1849
|
emitBalanceStreamChunk(address, chunk.length);
|
|
1821
1850
|
yield chunk;
|
|
@@ -1834,6 +1863,8 @@ async function parseStreamingBalances(response, address, options = {}) {
|
|
|
1834
1863
|
const chunk = normalizeStreamChunk(parsed);
|
|
1835
1864
|
emitBalanceStreamChunk(address, chunk.length);
|
|
1836
1865
|
yield chunk;
|
|
1866
|
+
} else if (parsed.type === "summary") {
|
|
1867
|
+
options.onSummary?.(toSummary(parsed, address));
|
|
1837
1868
|
}
|
|
1838
1869
|
} catch (error) {
|
|
1839
1870
|
if (options.strict) {
|
|
@@ -1867,7 +1898,7 @@ async function getBalances(chainRef, address, opts) {
|
|
|
1867
1898
|
if (cached) return cached;
|
|
1868
1899
|
}
|
|
1869
1900
|
const url = `${apiBase()}/v1/data/wallets/${encodeURIComponent(chainKey)}/${trimmedAddress}/balances`;
|
|
1870
|
-
const response = await
|
|
1901
|
+
const response = await rateLimitedFetch(url, {
|
|
1871
1902
|
method: "GET",
|
|
1872
1903
|
credentials: "omit",
|
|
1873
1904
|
headers: jsonHeaders()
|
|
@@ -1888,7 +1919,7 @@ async function getBalancesByAddress(address, opts) {
|
|
|
1888
1919
|
}
|
|
1889
1920
|
return merged;
|
|
1890
1921
|
}
|
|
1891
|
-
const url = `${apiBase()}/data/balances/${address}`;
|
|
1922
|
+
const url = `${apiBase()}/v1/data/balances/${address}`;
|
|
1892
1923
|
const r = await rateLimitedFetch(url, {
|
|
1893
1924
|
method: "GET",
|
|
1894
1925
|
credentials: "omit",
|
|
@@ -1896,14 +1927,27 @@ async function getBalancesByAddress(address, opts) {
|
|
|
1896
1927
|
});
|
|
1897
1928
|
if (!r.ok) throw new Error(`balances: HTTP ${r.status}`);
|
|
1898
1929
|
const j = await r.json();
|
|
1899
|
-
|
|
1930
|
+
const results = Array.isArray(j) ? j : j.results ?? [];
|
|
1931
|
+
if (opts?.onSummary) {
|
|
1932
|
+
const completed = results.length;
|
|
1933
|
+
opts.onSummary({
|
|
1934
|
+
address,
|
|
1935
|
+
partial: Array.isArray(j) ? false : Boolean(j.partial),
|
|
1936
|
+
completed,
|
|
1937
|
+
total: completed
|
|
1938
|
+
});
|
|
1939
|
+
}
|
|
1940
|
+
return results;
|
|
1941
|
+
}
|
|
1942
|
+
function bufferedOptions(opts) {
|
|
1943
|
+
return { ...opts, stream: false };
|
|
1900
1944
|
}
|
|
1901
1945
|
async function* getBalancesByAddressStream(address, opts = {}) {
|
|
1902
1946
|
if (!TrustwareConfigStore.get().features.balanceStreaming) {
|
|
1903
|
-
yield await getBalancesByAddress(address);
|
|
1947
|
+
yield await getBalancesByAddress(address, bufferedOptions(opts));
|
|
1904
1948
|
return;
|
|
1905
1949
|
}
|
|
1906
|
-
const url = `${apiBase()}/data/balances/${address}?stream=1`;
|
|
1950
|
+
const url = `${apiBase()}/v1/data/balances/${address}?stream=1`;
|
|
1907
1951
|
try {
|
|
1908
1952
|
const response = await rateLimitedFetch(url, {
|
|
1909
1953
|
method: "GET",
|
|
@@ -1919,7 +1963,14 @@ async function* getBalancesByAddressStream(address, opts = {}) {
|
|
|
1919
1963
|
const contentType = response.headers.get("content-type") ?? "";
|
|
1920
1964
|
if (contentType.includes("application/json")) {
|
|
1921
1965
|
const payload = await response.json();
|
|
1922
|
-
|
|
1966
|
+
const results = Array.isArray(payload) ? payload : payload.results ?? [];
|
|
1967
|
+
opts.onSummary?.({
|
|
1968
|
+
address,
|
|
1969
|
+
partial: Array.isArray(payload) ? false : Boolean(payload.partial),
|
|
1970
|
+
completed: results.length,
|
|
1971
|
+
total: results.length
|
|
1972
|
+
});
|
|
1973
|
+
yield results;
|
|
1923
1974
|
return;
|
|
1924
1975
|
}
|
|
1925
1976
|
const stream = await parseStreamingBalances(response, address, opts);
|
|
@@ -1928,7 +1979,7 @@ async function* getBalancesByAddressStream(address, opts = {}) {
|
|
|
1928
1979
|
}
|
|
1929
1980
|
} catch (error) {
|
|
1930
1981
|
emitBalanceStreamFallback(address, error);
|
|
1931
|
-
yield await getBalancesByAddress(address);
|
|
1982
|
+
yield await getBalancesByAddress(address, bufferedOptions(opts));
|
|
1932
1983
|
}
|
|
1933
1984
|
}
|
|
1934
1985
|
async function ensureRegistry() {
|
|
@@ -4115,7 +4166,18 @@ async function getStatus(intentId) {
|
|
|
4115
4166
|
);
|
|
4116
4167
|
await assertOK(r);
|
|
4117
4168
|
const j = await r.json();
|
|
4118
|
-
return j.data;
|
|
4169
|
+
return normalizeStatusPayload(j.data);
|
|
4170
|
+
}
|
|
4171
|
+
function normalizeStatusPayload(raw) {
|
|
4172
|
+
if (!raw || typeof raw !== "object") return raw;
|
|
4173
|
+
const wire = raw;
|
|
4174
|
+
const out = { ...wire };
|
|
4175
|
+
for (const [snake, camel] of Object.entries(STATUS_WIRE_TO_CAMEL)) {
|
|
4176
|
+
if (out[camel] !== void 0) continue;
|
|
4177
|
+
if (!(snake in wire)) continue;
|
|
4178
|
+
out[camel] = wire[snake];
|
|
4179
|
+
}
|
|
4180
|
+
return out;
|
|
4119
4181
|
}
|
|
4120
4182
|
async function pollStatus(intentId, { intervalMs = 2e3, timeoutMs = 5 * 6e4 } = {}) {
|
|
4121
4183
|
const t0 = Date.now();
|
|
@@ -4126,12 +4188,39 @@ async function pollStatus(intentId, { intervalMs = 2e3, timeoutMs = 5 * 6e4 } =
|
|
|
4126
4188
|
await new Promise((r) => setTimeout(r, intervalMs));
|
|
4127
4189
|
}
|
|
4128
4190
|
}
|
|
4191
|
+
var STATUS_WIRE_TO_CAMEL;
|
|
4129
4192
|
var init_routes = __esm({
|
|
4130
4193
|
"src/core/routes.ts"() {
|
|
4131
4194
|
"use strict";
|
|
4132
4195
|
init_http();
|
|
4133
4196
|
init_store();
|
|
4134
4197
|
init_address();
|
|
4198
|
+
STATUS_WIRE_TO_CAMEL = {
|
|
4199
|
+
intent_id: "intentId",
|
|
4200
|
+
from_address: "fromAddress",
|
|
4201
|
+
to_address: "toAddress",
|
|
4202
|
+
from_chain_id: "fromChainId",
|
|
4203
|
+
to_chain_id: "toChainId",
|
|
4204
|
+
source_tx_hash: "sourceTxHash",
|
|
4205
|
+
dest_tx_hash: "destTxHash",
|
|
4206
|
+
request_id: "requestId",
|
|
4207
|
+
provider_request_id: "providerRequestId",
|
|
4208
|
+
transaction_request: "transactionRequest",
|
|
4209
|
+
status_raw: "statusRaw",
|
|
4210
|
+
route_path: "routePath",
|
|
4211
|
+
route_status: "routeStatus",
|
|
4212
|
+
to_amount_wei: "toAmountWei",
|
|
4213
|
+
from_chain_block: "fromChainBlock",
|
|
4214
|
+
to_chain_block: "toChainBlock",
|
|
4215
|
+
from_chain_tx_url: "fromChainTxUrl",
|
|
4216
|
+
to_chain_tx_url: "toChainTxUrl",
|
|
4217
|
+
gas_status: "gasStatus",
|
|
4218
|
+
is_gmp_transaction: "isGMPTransaction",
|
|
4219
|
+
axelar_transaction_url: "axelarTransactionUrl",
|
|
4220
|
+
create_date: "createdDate",
|
|
4221
|
+
update_date: "updatedDate",
|
|
4222
|
+
time_spent_ms: "timeSpentMs"
|
|
4223
|
+
};
|
|
4135
4224
|
}
|
|
4136
4225
|
});
|
|
4137
4226
|
|
|
@@ -6604,9 +6693,6 @@ function resolveConfig(input) {
|
|
|
6604
6693
|
const theme = input.theme ?? "system";
|
|
6605
6694
|
const messages = deepMerge(DEFAULT_MESSAGES, input.messages);
|
|
6606
6695
|
const retry = {
|
|
6607
|
-
autoRetry: input.retry?.autoRetry ?? DEFAULT_RETRY_CONFIG.autoRetry,
|
|
6608
|
-
maxRetries: input.retry?.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries,
|
|
6609
|
-
baseDelayMs: input.retry?.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs,
|
|
6610
6696
|
approachingThreshold: input.retry?.approachingThreshold ?? DEFAULT_RETRY_CONFIG.approachingThreshold,
|
|
6611
6697
|
onRateLimitInfo: input.retry?.onRateLimitInfo,
|
|
6612
6698
|
onRateLimited: input.retry?.onRateLimited,
|
|
@@ -6739,6 +6825,7 @@ var init_core = __esm({
|
|
|
6739
6825
|
init_store();
|
|
6740
6826
|
init_wallets();
|
|
6741
6827
|
init_routes();
|
|
6828
|
+
init_routes();
|
|
6742
6829
|
init_balances();
|
|
6743
6830
|
init_tx();
|
|
6744
6831
|
init_http();
|
|
@@ -6893,7 +6980,8 @@ var init_core = __esm({
|
|
|
6893
6980
|
// src/core.ts
|
|
6894
6981
|
var core_exports = {};
|
|
6895
6982
|
__export(core_exports, {
|
|
6896
|
-
Trustware: () => Trustware
|
|
6983
|
+
Trustware: () => Trustware,
|
|
6984
|
+
assertValidPostHook: () => assertValidPostHook
|
|
6897
6985
|
});
|
|
6898
6986
|
module.exports = __toCommonJS(core_exports);
|
|
6899
6987
|
var init_core2 = __esm({
|
|
@@ -6904,6 +6992,7 @@ var init_core2 = __esm({
|
|
|
6904
6992
|
init_core2();
|
|
6905
6993
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6906
6994
|
0 && (module.exports = {
|
|
6907
|
-
Trustware
|
|
6995
|
+
Trustware,
|
|
6996
|
+
assertValidPostHook
|
|
6908
6997
|
});
|
|
6909
6998
|
//# sourceMappingURL=core.cjs.map
|