@trustware/sdk-staging 1.1.10-staging.0 → 1.1.11-staging.2
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/constants.cjs +1 -1
- package/dist/constants.mjs +1 -1
- package/dist/{core-BPLiD1UG.d.ts → core-B1WCJfDI.d.ts} +15 -2
- package/dist/{core-B7Ez-5-r.d.cts → core-CeNTuqPz.d.cts} +15 -2
- package/dist/core.cjs +365 -279
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.mjs +363 -278
- package/dist/core.mjs.map +1 -1
- package/dist/index.cjs +375 -170
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -5
- package/dist/index.d.ts +11 -5
- package/dist/index.mjs +373 -169
- package/dist/index.mjs.map +1 -1
- package/dist/{manager-B6NNV-E_.d.ts → manager-Bw8b1wSD.d.ts} +136 -21
- package/dist/{manager-BwjyFjjz.d.cts → manager-DNGk1YkR.d.cts} +136 -21
- package/dist/{metadata-BiTMMvlY.d.ts → metadata-C__KMeuz.d.ts} +1 -1
- package/dist/{metadata-HCflXcsF.d.cts → metadata-Dk4R8_-T.d.cts} +1 -1
- package/dist/smart-account.cjs +49 -44
- package/dist/smart-account.cjs.map +1 -1
- package/dist/smart-account.d.cts +17 -12
- package/dist/smart-account.d.ts +17 -12
- package/dist/smart-account.mjs +49 -44
- package/dist/smart-account.mjs.map +1 -1
- package/dist/wallet.cjs +54 -39
- package/dist/wallet.cjs.map +1 -1
- package/dist/wallet.d.cts +3 -3
- package/dist/wallet.d.ts +3 -3
- package/dist/wallet.mjs +54 -39
- package/dist/wallet.mjs.map +1 -1
- package/dist/widget.cjs +369 -170
- package/dist/widget.cjs.map +1 -1
- package/dist/widget.mjs +369 -169
- package/dist/widget.mjs.map +1 -1
- package/package.json +73 -5
|
@@ -197,6 +197,13 @@ type BuildRouteBody = {
|
|
|
197
197
|
postHook?: PostHookRequest;
|
|
198
198
|
};
|
|
199
199
|
};
|
|
200
|
+
/**
|
|
201
|
+
* Validates a `BuildRouteBody.hooks` value before it's sent, so a malformed
|
|
202
|
+
* postHook fails fast client-side instead of round-tripping to the backend.
|
|
203
|
+
* A no-op when `hooks`/`hooks.postHook` is omitted. Exported so callers can
|
|
204
|
+
* validate a postHook ahead of time (e.g. in their own form validation).
|
|
205
|
+
*/
|
|
206
|
+
declare function assertValidPostHook(hooks: BuildRouteBody["hooks"]): void;
|
|
200
207
|
type TxRequest = {
|
|
201
208
|
to?: string;
|
|
202
209
|
target?: string;
|
|
@@ -236,7 +243,36 @@ declare function submitReceipt(intentId: string, txHash: string, sponsorshipRequ
|
|
|
236
243
|
* executes from a smart account, so the backend records the tx against the
|
|
237
244
|
* address the user actually connects with. */
|
|
238
245
|
eoaAddress?: string): Promise<any>;
|
|
246
|
+
/**
|
|
247
|
+
* Reports the submitted tx hash for one execution step of a multi-step
|
|
248
|
+
* route — approve steps only; the main tx keeps going through
|
|
249
|
+
* `submitReceipt`. `stepIndex` is the step's position in
|
|
250
|
+
* `route.execution.approvals` (the backend seeds its step plan in the same
|
|
251
|
+
* order). Best-effort telemetry: callers fire-and-forget so a failed report
|
|
252
|
+
* never blocks the payment flow, but a successful one lets the backend tell
|
|
253
|
+
* "approve landed, main never followed" apart from an intent the user
|
|
254
|
+
* abandoned before signing anything.
|
|
255
|
+
*/
|
|
256
|
+
declare function submitStepReceipt(intentId: string, stepIndex: number, txHash: string): Promise<any>;
|
|
257
|
+
/**
|
|
258
|
+
* Fetches the current status for a route intent.
|
|
259
|
+
*
|
|
260
|
+
* Response contract:
|
|
261
|
+
* - 404 (throws) → intent doesn't exist. Stop polling.
|
|
262
|
+
* - 200 status: "pending" → intent exists, no receipt yet. Keep polling.
|
|
263
|
+
* - 200 status: "submitted" → receipt in, tx in flight. Keep polling.
|
|
264
|
+
* - 200 status: "bridging" → cross-chain leg in progress. Keep polling.
|
|
265
|
+
* - 200 status: "success"/"failed" → terminal. Stop polling.
|
|
266
|
+
*
|
|
267
|
+
* A "pending" payload is a stub ({intent_id, status, intent_status,
|
|
268
|
+
* create_date}) — the full Transaction fields appear once a receipt lands.
|
|
269
|
+
*/
|
|
239
270
|
declare function getStatus(intentId: string): Promise<Transaction>;
|
|
271
|
+
/**
|
|
272
|
+
* Polls intent status until terminal ("success"/"failed") or timeout.
|
|
273
|
+
* Non-terminal statuses ("pending", "submitted", "bridging") keep the loop
|
|
274
|
+
* going; a 404 (unknown intent) throws out of the loop — don't retry it.
|
|
275
|
+
*/
|
|
240
276
|
declare function pollStatus(intentId: string, { intervalMs, timeoutMs }?: {
|
|
241
277
|
intervalMs?: number | undefined;
|
|
242
278
|
timeoutMs?: number | undefined;
|
|
@@ -263,31 +299,90 @@ type RouteIntent = {
|
|
|
263
299
|
fromAmountWei: string | number;
|
|
264
300
|
quoteToAmountWei: string | number;
|
|
265
301
|
minToAmountWei: string | number;
|
|
302
|
+
/** Trustware's own request ID (a UUID) for the call that created this
|
|
303
|
+
* intent — the same value the response carried in `X-Request-Id`, so it is
|
|
304
|
+
* the ID to quote in a Trustware support request. Wire field:
|
|
305
|
+
* `request_id`. Absent on intents created before it was split from
|
|
306
|
+
* `providerRequestId`. */
|
|
266
307
|
requestId?: string;
|
|
308
|
+
/** The routing provider's own correlation ID: Squid `requestId`, LiFi/Relay
|
|
309
|
+
* route id, or Khalani's `{quoteId,routeId}` composite — the ID *that
|
|
310
|
+
* provider's* status API and support recognise. Wire field:
|
|
311
|
+
* `provider_request_id`. Absent when the winning provider returned none. */
|
|
312
|
+
providerRequestId?: string;
|
|
267
313
|
routeRaw?: unknown;
|
|
268
314
|
status: "created" | "submitted" | "bridging" | "success" | "failed";
|
|
269
315
|
createdDate: Date | string;
|
|
270
316
|
updatedDate: Date | string;
|
|
271
317
|
};
|
|
318
|
+
/**
|
|
319
|
+
* A status payload from `getStatus`/`pollStatus`.
|
|
320
|
+
*
|
|
321
|
+
* Every field except `status` is optional, because a `"pending"` payload is a
|
|
322
|
+
* stub — the intent exists but no receipt has landed, so there is no
|
|
323
|
+
* transaction row to describe yet. Check `status` before reading anything
|
|
324
|
+
* else.
|
|
325
|
+
*
|
|
326
|
+
* The wire is snake_case (`source_tx_hash`, `intent_id`, ...) while this type
|
|
327
|
+
* is camelCase. `getStatus` maps one onto the other (see
|
|
328
|
+
* `normalizeStatusPayload` in core/routes.ts), so anything reaching you through
|
|
329
|
+
* `getStatus`/`pollStatus`/`runTopUp` has the camelCase names populated.
|
|
330
|
+
*
|
|
331
|
+
* The raw snake_case keys are still present **at runtime** — dropping them
|
|
332
|
+
* would break callers that already read them — but they are deliberately not
|
|
333
|
+
* declared here, because camelCase is the supported spelling and the raw ones
|
|
334
|
+
* are only kept for back-compat. Reading `tx.source_tx_hash` therefore needs a
|
|
335
|
+
* cast, and new code should not: use `tx.sourceTxHash`.
|
|
336
|
+
*
|
|
337
|
+
* `origin_eoa` and `landed_amount_verified` are the exception — the wire has no
|
|
338
|
+
* camelCase spelling for those two, so they are declared as-is below.
|
|
339
|
+
*/
|
|
272
340
|
type Transaction = {
|
|
273
|
-
id
|
|
274
|
-
intentId
|
|
275
|
-
fromAddress
|
|
276
|
-
toAddress
|
|
341
|
+
id?: string;
|
|
342
|
+
intentId?: string;
|
|
343
|
+
fromAddress?: string;
|
|
344
|
+
toAddress?: string;
|
|
277
345
|
/** Connected wallet (EOA) that originated the payment when the sender is a
|
|
278
346
|
* smart account. Wire field: `origin_eoa`. */
|
|
279
347
|
origin_eoa?: string;
|
|
280
|
-
fromChainId
|
|
281
|
-
toChainId
|
|
282
|
-
sourceTxHash
|
|
283
|
-
destTxHash
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
348
|
+
fromChainId?: string | number;
|
|
349
|
+
toChainId?: string | number;
|
|
350
|
+
sourceTxHash?: string;
|
|
351
|
+
destTxHash?: string;
|
|
352
|
+
/** Trustware's own request ID (a UUID), copied from the intent. Wire field:
|
|
353
|
+
* `request_id`. Optional: absent on a "pending" payload, and on rows
|
|
354
|
+
* created before it was split from `providerRequestId`. */
|
|
355
|
+
requestId?: string;
|
|
356
|
+
/** The routing provider's own correlation ID, copied from the intent — what
|
|
357
|
+
* that provider's status API polls with. Wire field:
|
|
358
|
+
* `provider_request_id`. See RouteIntent.providerRequestId. */
|
|
359
|
+
providerRequestId?: string;
|
|
360
|
+
transactionRequest?: unknown;
|
|
361
|
+
/**
|
|
362
|
+
* "pending" means the intent exists but no receipt has been submitted yet —
|
|
363
|
+
* the backend returns it (HTTP 200) instead of the old 404 so pollers can
|
|
364
|
+
* tell "not ready yet, keep polling" apart from "unknown intent" (a real
|
|
365
|
+
* 404, which means stop polling). A pending response carries only
|
|
366
|
+
* `intent_id`, `status`, `intent_status`, `create_date` and — once the
|
|
367
|
+
* intent has an execution step plan — `steps`; every other field here is
|
|
368
|
+
* absent until a receipt lands.
|
|
369
|
+
*/
|
|
370
|
+
status: "pending" | "submitted" | "bridging" | "success" | "failed";
|
|
287
371
|
statusRaw?: unknown;
|
|
288
372
|
routePath?: unknown;
|
|
289
373
|
routeStatus?: unknown;
|
|
374
|
+
/**
|
|
375
|
+
* Exact once landed_amount_verified is true; otherwise a pre-trade quote
|
|
376
|
+
* estimate copied in when the transaction was submitted — neither Squid's
|
|
377
|
+
* nor LiFi's status API carries a real landed-amount field, so the
|
|
378
|
+
* backend confirms it by reading the destination chain directly instead
|
|
379
|
+
* (see BVT-246). Check `landed_amount_verified` before auto-continuing
|
|
380
|
+
* on this value.
|
|
381
|
+
*/
|
|
290
382
|
toAmountWei?: string | number;
|
|
383
|
+
/** True once toAmountWei has been confirmed on-chain rather than being the
|
|
384
|
+
* pre-trade quote estimate. Wire field: `landed_amount_verified`. */
|
|
385
|
+
landed_amount_verified?: boolean;
|
|
291
386
|
fromChainBlock: number;
|
|
292
387
|
toChainBlock: number;
|
|
293
388
|
fromChainTxUrl?: string;
|
|
@@ -410,6 +505,11 @@ type RoutePlan = {
|
|
|
410
505
|
};
|
|
411
506
|
steps?: unknown[];
|
|
412
507
|
provider?: string;
|
|
508
|
+
/** The winning provider's own correlation ID, not Trustware's — it is
|
|
509
|
+
* absent when that provider issued none, and it is what lands on the
|
|
510
|
+
* intent as `providerRequestId`. Trustware's request ID for the same call
|
|
511
|
+
* comes back in the `X-Request-Id` response header (the provider's is also
|
|
512
|
+
* mirrored there as `X-Provider-Request-Id`). */
|
|
413
513
|
requestId?: string;
|
|
414
514
|
reliabilityScore?: number;
|
|
415
515
|
diagnostics?: {
|
|
@@ -628,13 +728,14 @@ type RateLimitInfo = {
|
|
|
628
728
|
/** Seconds until rate limit resets (only present on 429 responses) */
|
|
629
729
|
retryAfter?: number;
|
|
630
730
|
};
|
|
731
|
+
/**
|
|
732
|
+
* Rate limit *observability*. Retry timing itself is not configurable: the
|
|
733
|
+
* limit is enforced server-side per API key, so the only retry schedule that
|
|
734
|
+
* can actually succeed is the one the server dictates through Retry-After.
|
|
735
|
+
* Tuning it client-side could only make requests fail sooner or hammer a
|
|
736
|
+
* limit that is already closed — see RETRY_POLICY.
|
|
737
|
+
*/
|
|
631
738
|
type RetryConfig = {
|
|
632
|
-
/** Enable automatic retry on 429 responses (default: true). Note: This does NOT disable backend rate limits, only client-side retry behavior. */
|
|
633
|
-
autoRetry?: boolean;
|
|
634
|
-
/** Maximum number of retries on 429 (default: 3) */
|
|
635
|
-
maxRetries?: number;
|
|
636
|
-
/** Base delay in ms for exponential backoff (default: 1000) */
|
|
637
|
-
baseDelayMs?: number;
|
|
638
739
|
/** Callback when rate limit info is received from server */
|
|
639
740
|
onRateLimitInfo?: (info: RateLimitInfo) => void;
|
|
640
741
|
/** Callback when rate limit is hit (429 received) */
|
|
@@ -645,15 +746,29 @@ type RetryConfig = {
|
|
|
645
746
|
approachingThreshold?: number;
|
|
646
747
|
};
|
|
647
748
|
type ResolvedRetryConfig = {
|
|
648
|
-
autoRetry: boolean;
|
|
649
|
-
maxRetries: number;
|
|
650
|
-
baseDelayMs: number;
|
|
651
749
|
approachingThreshold: number;
|
|
652
750
|
onRateLimitInfo?: (info: RateLimitInfo) => void;
|
|
653
751
|
onRateLimited?: (info: RateLimitInfo, retryCount: number) => void;
|
|
654
752
|
onRateLimitApproaching?: (info: RateLimitInfo, threshold: number) => void;
|
|
655
753
|
};
|
|
656
754
|
declare const DEFAULT_RETRY_CONFIG: ResolvedRetryConfig;
|
|
755
|
+
/**
|
|
756
|
+
* The one retry number the SDK chooses for itself: the total time it will
|
|
757
|
+
* spend waiting out rate limits before handing the caller a RateLimitError.
|
|
758
|
+
*
|
|
759
|
+
* Everything else — how long to wait, and so whether to retry at all — is read
|
|
760
|
+
* off the response. The limit is per API key and settable per key server-side
|
|
761
|
+
* (rate_limit_per_min), and the backend reports the state of *that* key on
|
|
762
|
+
* every response: X-RateLimit-Limit / -Remaining / -Reset, plus Retry-After on
|
|
763
|
+
* a 429. A schedule hardcoded here could only disagree with it.
|
|
764
|
+
*
|
|
765
|
+
* This budget stays client-side because the server cannot know it: it is a
|
|
766
|
+
* property of the caller, not of the key. A payment widget cannot sit on a
|
|
767
|
+
* spinner for the minute a fresh window might be away, so past the budget the
|
|
768
|
+
* SDK stops and reports the wait (retriesExhausted: false, retryAfter set) for
|
|
769
|
+
* the app to render.
|
|
770
|
+
*/
|
|
771
|
+
declare const RATE_LIMIT_WAIT_BUDGET_MS = 10000;
|
|
657
772
|
declare const DEFAULT_FEATURE_FLAGS: ResolvedFeatureFlags;
|
|
658
773
|
|
|
659
774
|
type WagmiConnector = {
|
|
@@ -793,4 +908,4 @@ declare function useWalletInfo(wagmi?: WagmiBridge): {
|
|
|
793
908
|
};
|
|
794
909
|
declare function useWalletExternalDisconnect(cb: () => void): void;
|
|
795
910
|
|
|
796
|
-
export { type
|
|
911
|
+
export { type WalletCategory as $, type ResolvedTrustwareConfig as A, type BuildRouteBody as B, type ResolvedWalletConnectConfig as C, type DetectedWallet as D, type EIP1193 as E, type FeatureFlags as F, type RetryConfig as G, type RouteApproval as H, IdentityStore as I, type RouteEstimate as J, type RouteIntent as K, type RouteParams as L, type RoutePlan as M, type RouteSponsorship as N, type RoutesConfig as O, type PostHookRequest as P, type SimpleWalletInterface as Q, type RateLimitInfo as R, type SolanaProviderLike as S, type TrustwareConfigOptions as T, type SponsorshipApproval as U, type SwapTokenRef as V, type WalletMeta as W, type TrustwareTheme as X, type TrustwareWidgetMessages as Y, type WalletAddressResolution as Z, type WalletAddressSource as _, type WalletId as a, type WalletConnectConfig as a0, type WalletEcosystem as a1, type WalletIdentity as a2, type WalletIdentityAddress as a3, type WalletIdentityChainLike as a4, assertValidPostHook as a5, buildWalletIdentityAddress as a6, createWalletIdentity as a7, resolveWalletAddressForChain as a8, upsertWalletIdentityAddress as a9, buildRoute as aa, buildDepositAddress as ab, submitReceipt as ac, submitStepReceipt as ad, getStatus as ae, pollStatus as af, type SolanaWalletInterface as b, type WagmiBridge as c, type WagmiConnector as d, type WalletSnapshot as e, useWalletExternalDisconnect as f, useWalletInfo as g, useWireDetectionIntoManager as h, type WalletInterFaceAPI as i, TrustwareError as j, type Transaction as k, type TrustwareEvent as l, type BuildRouteResponse as m, type BuildRouteResult as n, DEFAULT_AUTO_DETECT_PROVIDER as o, DEFAULT_FEATURE_FLAGS as p, DEFAULT_MESSAGES as q, DEFAULT_RETRY_CONFIG as r, DEFAULT_SLIPPAGE as s, type EIP6963ProviderDetail as t, useWalletConnectConnect as u, type EvmWalletInterface as v, walletManager as w, RATE_LIMIT_WAIT_BUDGET_MS as x, type ResolvedFeatureFlags as y, type ResolvedRetryConfig as z };
|
|
@@ -197,6 +197,13 @@ type BuildRouteBody = {
|
|
|
197
197
|
postHook?: PostHookRequest;
|
|
198
198
|
};
|
|
199
199
|
};
|
|
200
|
+
/**
|
|
201
|
+
* Validates a `BuildRouteBody.hooks` value before it's sent, so a malformed
|
|
202
|
+
* postHook fails fast client-side instead of round-tripping to the backend.
|
|
203
|
+
* A no-op when `hooks`/`hooks.postHook` is omitted. Exported so callers can
|
|
204
|
+
* validate a postHook ahead of time (e.g. in their own form validation).
|
|
205
|
+
*/
|
|
206
|
+
declare function assertValidPostHook(hooks: BuildRouteBody["hooks"]): void;
|
|
200
207
|
type TxRequest = {
|
|
201
208
|
to?: string;
|
|
202
209
|
target?: string;
|
|
@@ -236,7 +243,36 @@ declare function submitReceipt(intentId: string, txHash: string, sponsorshipRequ
|
|
|
236
243
|
* executes from a smart account, so the backend records the tx against the
|
|
237
244
|
* address the user actually connects with. */
|
|
238
245
|
eoaAddress?: string): Promise<any>;
|
|
246
|
+
/**
|
|
247
|
+
* Reports the submitted tx hash for one execution step of a multi-step
|
|
248
|
+
* route — approve steps only; the main tx keeps going through
|
|
249
|
+
* `submitReceipt`. `stepIndex` is the step's position in
|
|
250
|
+
* `route.execution.approvals` (the backend seeds its step plan in the same
|
|
251
|
+
* order). Best-effort telemetry: callers fire-and-forget so a failed report
|
|
252
|
+
* never blocks the payment flow, but a successful one lets the backend tell
|
|
253
|
+
* "approve landed, main never followed" apart from an intent the user
|
|
254
|
+
* abandoned before signing anything.
|
|
255
|
+
*/
|
|
256
|
+
declare function submitStepReceipt(intentId: string, stepIndex: number, txHash: string): Promise<any>;
|
|
257
|
+
/**
|
|
258
|
+
* Fetches the current status for a route intent.
|
|
259
|
+
*
|
|
260
|
+
* Response contract:
|
|
261
|
+
* - 404 (throws) → intent doesn't exist. Stop polling.
|
|
262
|
+
* - 200 status: "pending" → intent exists, no receipt yet. Keep polling.
|
|
263
|
+
* - 200 status: "submitted" → receipt in, tx in flight. Keep polling.
|
|
264
|
+
* - 200 status: "bridging" → cross-chain leg in progress. Keep polling.
|
|
265
|
+
* - 200 status: "success"/"failed" → terminal. Stop polling.
|
|
266
|
+
*
|
|
267
|
+
* A "pending" payload is a stub ({intent_id, status, intent_status,
|
|
268
|
+
* create_date}) — the full Transaction fields appear once a receipt lands.
|
|
269
|
+
*/
|
|
239
270
|
declare function getStatus(intentId: string): Promise<Transaction>;
|
|
271
|
+
/**
|
|
272
|
+
* Polls intent status until terminal ("success"/"failed") or timeout.
|
|
273
|
+
* Non-terminal statuses ("pending", "submitted", "bridging") keep the loop
|
|
274
|
+
* going; a 404 (unknown intent) throws out of the loop — don't retry it.
|
|
275
|
+
*/
|
|
240
276
|
declare function pollStatus(intentId: string, { intervalMs, timeoutMs }?: {
|
|
241
277
|
intervalMs?: number | undefined;
|
|
242
278
|
timeoutMs?: number | undefined;
|
|
@@ -263,31 +299,90 @@ type RouteIntent = {
|
|
|
263
299
|
fromAmountWei: string | number;
|
|
264
300
|
quoteToAmountWei: string | number;
|
|
265
301
|
minToAmountWei: string | number;
|
|
302
|
+
/** Trustware's own request ID (a UUID) for the call that created this
|
|
303
|
+
* intent — the same value the response carried in `X-Request-Id`, so it is
|
|
304
|
+
* the ID to quote in a Trustware support request. Wire field:
|
|
305
|
+
* `request_id`. Absent on intents created before it was split from
|
|
306
|
+
* `providerRequestId`. */
|
|
266
307
|
requestId?: string;
|
|
308
|
+
/** The routing provider's own correlation ID: Squid `requestId`, LiFi/Relay
|
|
309
|
+
* route id, or Khalani's `{quoteId,routeId}` composite — the ID *that
|
|
310
|
+
* provider's* status API and support recognise. Wire field:
|
|
311
|
+
* `provider_request_id`. Absent when the winning provider returned none. */
|
|
312
|
+
providerRequestId?: string;
|
|
267
313
|
routeRaw?: unknown;
|
|
268
314
|
status: "created" | "submitted" | "bridging" | "success" | "failed";
|
|
269
315
|
createdDate: Date | string;
|
|
270
316
|
updatedDate: Date | string;
|
|
271
317
|
};
|
|
318
|
+
/**
|
|
319
|
+
* A status payload from `getStatus`/`pollStatus`.
|
|
320
|
+
*
|
|
321
|
+
* Every field except `status` is optional, because a `"pending"` payload is a
|
|
322
|
+
* stub — the intent exists but no receipt has landed, so there is no
|
|
323
|
+
* transaction row to describe yet. Check `status` before reading anything
|
|
324
|
+
* else.
|
|
325
|
+
*
|
|
326
|
+
* The wire is snake_case (`source_tx_hash`, `intent_id`, ...) while this type
|
|
327
|
+
* is camelCase. `getStatus` maps one onto the other (see
|
|
328
|
+
* `normalizeStatusPayload` in core/routes.ts), so anything reaching you through
|
|
329
|
+
* `getStatus`/`pollStatus`/`runTopUp` has the camelCase names populated.
|
|
330
|
+
*
|
|
331
|
+
* The raw snake_case keys are still present **at runtime** — dropping them
|
|
332
|
+
* would break callers that already read them — but they are deliberately not
|
|
333
|
+
* declared here, because camelCase is the supported spelling and the raw ones
|
|
334
|
+
* are only kept for back-compat. Reading `tx.source_tx_hash` therefore needs a
|
|
335
|
+
* cast, and new code should not: use `tx.sourceTxHash`.
|
|
336
|
+
*
|
|
337
|
+
* `origin_eoa` and `landed_amount_verified` are the exception — the wire has no
|
|
338
|
+
* camelCase spelling for those two, so they are declared as-is below.
|
|
339
|
+
*/
|
|
272
340
|
type Transaction = {
|
|
273
|
-
id
|
|
274
|
-
intentId
|
|
275
|
-
fromAddress
|
|
276
|
-
toAddress
|
|
341
|
+
id?: string;
|
|
342
|
+
intentId?: string;
|
|
343
|
+
fromAddress?: string;
|
|
344
|
+
toAddress?: string;
|
|
277
345
|
/** Connected wallet (EOA) that originated the payment when the sender is a
|
|
278
346
|
* smart account. Wire field: `origin_eoa`. */
|
|
279
347
|
origin_eoa?: string;
|
|
280
|
-
fromChainId
|
|
281
|
-
toChainId
|
|
282
|
-
sourceTxHash
|
|
283
|
-
destTxHash
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
348
|
+
fromChainId?: string | number;
|
|
349
|
+
toChainId?: string | number;
|
|
350
|
+
sourceTxHash?: string;
|
|
351
|
+
destTxHash?: string;
|
|
352
|
+
/** Trustware's own request ID (a UUID), copied from the intent. Wire field:
|
|
353
|
+
* `request_id`. Optional: absent on a "pending" payload, and on rows
|
|
354
|
+
* created before it was split from `providerRequestId`. */
|
|
355
|
+
requestId?: string;
|
|
356
|
+
/** The routing provider's own correlation ID, copied from the intent — what
|
|
357
|
+
* that provider's status API polls with. Wire field:
|
|
358
|
+
* `provider_request_id`. See RouteIntent.providerRequestId. */
|
|
359
|
+
providerRequestId?: string;
|
|
360
|
+
transactionRequest?: unknown;
|
|
361
|
+
/**
|
|
362
|
+
* "pending" means the intent exists but no receipt has been submitted yet —
|
|
363
|
+
* the backend returns it (HTTP 200) instead of the old 404 so pollers can
|
|
364
|
+
* tell "not ready yet, keep polling" apart from "unknown intent" (a real
|
|
365
|
+
* 404, which means stop polling). A pending response carries only
|
|
366
|
+
* `intent_id`, `status`, `intent_status`, `create_date` and — once the
|
|
367
|
+
* intent has an execution step plan — `steps`; every other field here is
|
|
368
|
+
* absent until a receipt lands.
|
|
369
|
+
*/
|
|
370
|
+
status: "pending" | "submitted" | "bridging" | "success" | "failed";
|
|
287
371
|
statusRaw?: unknown;
|
|
288
372
|
routePath?: unknown;
|
|
289
373
|
routeStatus?: unknown;
|
|
374
|
+
/**
|
|
375
|
+
* Exact once landed_amount_verified is true; otherwise a pre-trade quote
|
|
376
|
+
* estimate copied in when the transaction was submitted — neither Squid's
|
|
377
|
+
* nor LiFi's status API carries a real landed-amount field, so the
|
|
378
|
+
* backend confirms it by reading the destination chain directly instead
|
|
379
|
+
* (see BVT-246). Check `landed_amount_verified` before auto-continuing
|
|
380
|
+
* on this value.
|
|
381
|
+
*/
|
|
290
382
|
toAmountWei?: string | number;
|
|
383
|
+
/** True once toAmountWei has been confirmed on-chain rather than being the
|
|
384
|
+
* pre-trade quote estimate. Wire field: `landed_amount_verified`. */
|
|
385
|
+
landed_amount_verified?: boolean;
|
|
291
386
|
fromChainBlock: number;
|
|
292
387
|
toChainBlock: number;
|
|
293
388
|
fromChainTxUrl?: string;
|
|
@@ -410,6 +505,11 @@ type RoutePlan = {
|
|
|
410
505
|
};
|
|
411
506
|
steps?: unknown[];
|
|
412
507
|
provider?: string;
|
|
508
|
+
/** The winning provider's own correlation ID, not Trustware's — it is
|
|
509
|
+
* absent when that provider issued none, and it is what lands on the
|
|
510
|
+
* intent as `providerRequestId`. Trustware's request ID for the same call
|
|
511
|
+
* comes back in the `X-Request-Id` response header (the provider's is also
|
|
512
|
+
* mirrored there as `X-Provider-Request-Id`). */
|
|
413
513
|
requestId?: string;
|
|
414
514
|
reliabilityScore?: number;
|
|
415
515
|
diagnostics?: {
|
|
@@ -628,13 +728,14 @@ type RateLimitInfo = {
|
|
|
628
728
|
/** Seconds until rate limit resets (only present on 429 responses) */
|
|
629
729
|
retryAfter?: number;
|
|
630
730
|
};
|
|
731
|
+
/**
|
|
732
|
+
* Rate limit *observability*. Retry timing itself is not configurable: the
|
|
733
|
+
* limit is enforced server-side per API key, so the only retry schedule that
|
|
734
|
+
* can actually succeed is the one the server dictates through Retry-After.
|
|
735
|
+
* Tuning it client-side could only make requests fail sooner or hammer a
|
|
736
|
+
* limit that is already closed — see RETRY_POLICY.
|
|
737
|
+
*/
|
|
631
738
|
type RetryConfig = {
|
|
632
|
-
/** Enable automatic retry on 429 responses (default: true). Note: This does NOT disable backend rate limits, only client-side retry behavior. */
|
|
633
|
-
autoRetry?: boolean;
|
|
634
|
-
/** Maximum number of retries on 429 (default: 3) */
|
|
635
|
-
maxRetries?: number;
|
|
636
|
-
/** Base delay in ms for exponential backoff (default: 1000) */
|
|
637
|
-
baseDelayMs?: number;
|
|
638
739
|
/** Callback when rate limit info is received from server */
|
|
639
740
|
onRateLimitInfo?: (info: RateLimitInfo) => void;
|
|
640
741
|
/** Callback when rate limit is hit (429 received) */
|
|
@@ -645,15 +746,29 @@ type RetryConfig = {
|
|
|
645
746
|
approachingThreshold?: number;
|
|
646
747
|
};
|
|
647
748
|
type ResolvedRetryConfig = {
|
|
648
|
-
autoRetry: boolean;
|
|
649
|
-
maxRetries: number;
|
|
650
|
-
baseDelayMs: number;
|
|
651
749
|
approachingThreshold: number;
|
|
652
750
|
onRateLimitInfo?: (info: RateLimitInfo) => void;
|
|
653
751
|
onRateLimited?: (info: RateLimitInfo, retryCount: number) => void;
|
|
654
752
|
onRateLimitApproaching?: (info: RateLimitInfo, threshold: number) => void;
|
|
655
753
|
};
|
|
656
754
|
declare const DEFAULT_RETRY_CONFIG: ResolvedRetryConfig;
|
|
755
|
+
/**
|
|
756
|
+
* The one retry number the SDK chooses for itself: the total time it will
|
|
757
|
+
* spend waiting out rate limits before handing the caller a RateLimitError.
|
|
758
|
+
*
|
|
759
|
+
* Everything else — how long to wait, and so whether to retry at all — is read
|
|
760
|
+
* off the response. The limit is per API key and settable per key server-side
|
|
761
|
+
* (rate_limit_per_min), and the backend reports the state of *that* key on
|
|
762
|
+
* every response: X-RateLimit-Limit / -Remaining / -Reset, plus Retry-After on
|
|
763
|
+
* a 429. A schedule hardcoded here could only disagree with it.
|
|
764
|
+
*
|
|
765
|
+
* This budget stays client-side because the server cannot know it: it is a
|
|
766
|
+
* property of the caller, not of the key. A payment widget cannot sit on a
|
|
767
|
+
* spinner for the minute a fresh window might be away, so past the budget the
|
|
768
|
+
* SDK stops and reports the wait (retriesExhausted: false, retryAfter set) for
|
|
769
|
+
* the app to render.
|
|
770
|
+
*/
|
|
771
|
+
declare const RATE_LIMIT_WAIT_BUDGET_MS = 10000;
|
|
657
772
|
declare const DEFAULT_FEATURE_FLAGS: ResolvedFeatureFlags;
|
|
658
773
|
|
|
659
774
|
type WagmiConnector = {
|
|
@@ -793,4 +908,4 @@ declare function useWalletInfo(wagmi?: WagmiBridge): {
|
|
|
793
908
|
};
|
|
794
909
|
declare function useWalletExternalDisconnect(cb: () => void): void;
|
|
795
910
|
|
|
796
|
-
export { type
|
|
911
|
+
export { type WalletCategory as $, type ResolvedTrustwareConfig as A, type BuildRouteBody as B, type ResolvedWalletConnectConfig as C, type DetectedWallet as D, type EIP1193 as E, type FeatureFlags as F, type RetryConfig as G, type RouteApproval as H, IdentityStore as I, type RouteEstimate as J, type RouteIntent as K, type RouteParams as L, type RoutePlan as M, type RouteSponsorship as N, type RoutesConfig as O, type PostHookRequest as P, type SimpleWalletInterface as Q, type RateLimitInfo as R, type SolanaProviderLike as S, type TrustwareConfigOptions as T, type SponsorshipApproval as U, type SwapTokenRef as V, type WalletMeta as W, type TrustwareTheme as X, type TrustwareWidgetMessages as Y, type WalletAddressResolution as Z, type WalletAddressSource as _, type WalletId as a, type WalletConnectConfig as a0, type WalletEcosystem as a1, type WalletIdentity as a2, type WalletIdentityAddress as a3, type WalletIdentityChainLike as a4, assertValidPostHook as a5, buildWalletIdentityAddress as a6, createWalletIdentity as a7, resolveWalletAddressForChain as a8, upsertWalletIdentityAddress as a9, buildRoute as aa, buildDepositAddress as ab, submitReceipt as ac, submitStepReceipt as ad, getStatus as ae, pollStatus as af, type SolanaWalletInterface as b, type WagmiBridge as c, type WagmiConnector as d, type WalletSnapshot as e, useWalletExternalDisconnect as f, useWalletInfo as g, useWireDetectionIntoManager as h, type WalletInterFaceAPI as i, TrustwareError as j, type Transaction as k, type TrustwareEvent as l, type BuildRouteResponse as m, type BuildRouteResult as n, DEFAULT_AUTO_DETECT_PROVIDER as o, DEFAULT_FEATURE_FLAGS as p, DEFAULT_MESSAGES as q, DEFAULT_RETRY_CONFIG as r, DEFAULT_SLIPPAGE as s, type EIP6963ProviderDetail as t, useWalletConnectConnect as u, type EvmWalletInterface as v, walletManager as w, RATE_LIMIT_WAIT_BUDGET_MS as x, type ResolvedFeatureFlags as y, type ResolvedRetryConfig as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as DetectedWallet, c as WagmiBridge, i as WalletInterFaceAPI, E as EIP1193, a as WalletId, t as EIP6963ProviderDetail, W as WalletMeta } from './manager-
|
|
1
|
+
import { D as DetectedWallet, c as WagmiBridge, i as WalletInterFaceAPI, E as EIP1193, a as WalletId, t as EIP6963ProviderDetail, W as WalletMeta } from './manager-Bw8b1wSD.js';
|
|
2
2
|
|
|
3
3
|
/** Try wagmi bridge first (if provided), otherwise return EIP-1193 adapter. */
|
|
4
4
|
declare function connectDetectedWallet(dw: DetectedWallet, opts?: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as DetectedWallet, c as WagmiBridge, i as WalletInterFaceAPI, E as EIP1193, a as WalletId, t as EIP6963ProviderDetail, W as WalletMeta } from './manager-
|
|
1
|
+
import { D as DetectedWallet, c as WagmiBridge, i as WalletInterFaceAPI, E as EIP1193, a as WalletId, t as EIP6963ProviderDetail, W as WalletMeta } from './manager-DNGk1YkR.cjs';
|
|
2
2
|
|
|
3
3
|
/** Try wagmi bridge first (if provided), otherwise return EIP-1193 adapter. */
|
|
4
4
|
declare function connectDetectedWallet(dw: DetectedWallet, opts?: {
|
package/dist/smart-account.cjs
CHANGED
|
@@ -12265,7 +12265,7 @@ var init_constants = __esm({
|
|
|
12265
12265
|
"src/constants.ts"() {
|
|
12266
12266
|
"use strict";
|
|
12267
12267
|
SDK_NAME = "@trustware/sdk";
|
|
12268
|
-
SDK_VERSION = "1.1.
|
|
12268
|
+
SDK_VERSION = "1.1.11-staging.2";
|
|
12269
12269
|
API_ROOT = "https://bv-staging-api.trustware.io";
|
|
12270
12270
|
API_PREFIX = "/api";
|
|
12271
12271
|
}
|
|
@@ -12286,16 +12286,14 @@ var init_defaults3 = __esm({
|
|
|
12286
12286
|
});
|
|
12287
12287
|
|
|
12288
12288
|
// src/types/config.ts
|
|
12289
|
-
var DEFAULT_RETRY_CONFIG, DEFAULT_FEATURE_FLAGS;
|
|
12289
|
+
var DEFAULT_RETRY_CONFIG, RATE_LIMIT_WAIT_BUDGET_MS, DEFAULT_FEATURE_FLAGS;
|
|
12290
12290
|
var init_config = __esm({
|
|
12291
12291
|
"src/types/config.ts"() {
|
|
12292
12292
|
"use strict";
|
|
12293
12293
|
DEFAULT_RETRY_CONFIG = {
|
|
12294
|
-
autoRetry: true,
|
|
12295
|
-
maxRetries: 3,
|
|
12296
|
-
baseDelayMs: 1e3,
|
|
12297
12294
|
approachingThreshold: 5
|
|
12298
12295
|
};
|
|
12296
|
+
RATE_LIMIT_WAIT_BUDGET_MS = 1e4;
|
|
12299
12297
|
DEFAULT_FEATURE_FLAGS = {
|
|
12300
12298
|
tokensPagination: true,
|
|
12301
12299
|
balanceStreaming: false,
|
|
@@ -13571,9 +13569,6 @@ function resolveConfig(input) {
|
|
|
13571
13569
|
const theme = input.theme ?? "system";
|
|
13572
13570
|
const messages = deepMerge(DEFAULT_MESSAGES, input.messages);
|
|
13573
13571
|
const retry = {
|
|
13574
|
-
autoRetry: input.retry?.autoRetry ?? DEFAULT_RETRY_CONFIG.autoRetry,
|
|
13575
|
-
maxRetries: input.retry?.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries,
|
|
13576
|
-
baseDelayMs: input.retry?.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs,
|
|
13577
13572
|
approachingThreshold: input.retry?.approachingThreshold ?? DEFAULT_RETRY_CONFIG.approachingThreshold,
|
|
13578
13573
|
onRateLimitInfo: input.retry?.onRateLimitInfo,
|
|
13579
13574
|
onRateLimited: input.retry?.onRateLimited,
|
|
@@ -13684,60 +13679,66 @@ function notifyRateLimitCallbacks(info, isRateLimited, retryCount) {
|
|
|
13684
13679
|
retry.onRateLimitApproaching(info, retry.approachingThreshold);
|
|
13685
13680
|
}
|
|
13686
13681
|
}
|
|
13687
|
-
function
|
|
13688
|
-
if (
|
|
13689
|
-
|
|
13682
|
+
function serverDirectedWaitMs(info) {
|
|
13683
|
+
if (!info) return null;
|
|
13684
|
+
if (typeof info.retryAfter === "number" && info.retryAfter > 0) {
|
|
13685
|
+
return info.retryAfter * 1e3;
|
|
13690
13686
|
}
|
|
13691
|
-
|
|
13687
|
+
if (typeof info.reset === "number" && info.reset > 0) {
|
|
13688
|
+
const untilReset = info.reset * 1e3 - Date.now();
|
|
13689
|
+
if (untilReset > 0) return untilReset;
|
|
13690
|
+
}
|
|
13691
|
+
return null;
|
|
13692
13692
|
}
|
|
13693
13693
|
function sleep(ms) {
|
|
13694
13694
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
13695
13695
|
}
|
|
13696
|
-
async function
|
|
13697
|
-
|
|
13698
|
-
const cfg = TrustwareConfigStore.get();
|
|
13699
|
-
if (!cfg.retry.autoRetry || skipRateLimit) {
|
|
13700
|
-
return fetch(url, fetchOptions);
|
|
13701
|
-
}
|
|
13702
|
-
const { maxRetries, baseDelayMs } = cfg.retry;
|
|
13696
|
+
async function withRateLimitRetry(attempt) {
|
|
13697
|
+
let waitedMs = 0;
|
|
13703
13698
|
let retryCount = 0;
|
|
13704
13699
|
while (true) {
|
|
13705
|
-
const response = await
|
|
13700
|
+
const response = await attempt();
|
|
13706
13701
|
const rateLimitInfo = parseRateLimitHeaders(response);
|
|
13707
|
-
if (response.status
|
|
13702
|
+
if (response.status !== 429) {
|
|
13708
13703
|
if (rateLimitInfo) {
|
|
13709
|
-
notifyRateLimitCallbacks(rateLimitInfo,
|
|
13710
|
-
}
|
|
13711
|
-
if (retryCount >= maxRetries) {
|
|
13712
|
-
throw new RateLimitError(
|
|
13713
|
-
rateLimitInfo || { limit: 0, remaining: 0, reset: 0 },
|
|
13714
|
-
true
|
|
13715
|
-
);
|
|
13704
|
+
notifyRateLimitCallbacks(rateLimitInfo, false, 0);
|
|
13716
13705
|
}
|
|
13717
|
-
|
|
13718
|
-
baseDelayMs,
|
|
13719
|
-
retryCount,
|
|
13720
|
-
rateLimitInfo?.retryAfter
|
|
13721
|
-
);
|
|
13722
|
-
await sleep(delay);
|
|
13723
|
-
retryCount++;
|
|
13724
|
-
continue;
|
|
13706
|
+
return response;
|
|
13725
13707
|
}
|
|
13726
13708
|
if (rateLimitInfo) {
|
|
13727
|
-
notifyRateLimitCallbacks(rateLimitInfo,
|
|
13709
|
+
notifyRateLimitCallbacks(rateLimitInfo, true, retryCount);
|
|
13710
|
+
}
|
|
13711
|
+
const waitMs = serverDirectedWaitMs(rateLimitInfo);
|
|
13712
|
+
const info = rateLimitInfo || { limit: 0, remaining: 0, reset: 0 };
|
|
13713
|
+
if (waitMs === null) {
|
|
13714
|
+
throw new RateLimitError(info, true);
|
|
13715
|
+
}
|
|
13716
|
+
if (waitedMs + waitMs > RATE_LIMIT_WAIT_BUDGET_MS) {
|
|
13717
|
+
throw new RateLimitError(info, false);
|
|
13728
13718
|
}
|
|
13729
|
-
|
|
13719
|
+
await sleep(waitMs);
|
|
13720
|
+
waitedMs += waitMs;
|
|
13721
|
+
retryCount++;
|
|
13730
13722
|
}
|
|
13731
13723
|
}
|
|
13724
|
+
async function rateLimitedFetch(url, options = {}) {
|
|
13725
|
+
const { skipRateLimit, ...fetchOptions } = options;
|
|
13726
|
+
if (skipRateLimit) {
|
|
13727
|
+
return fetch(url, fetchOptions);
|
|
13728
|
+
}
|
|
13729
|
+
return withRateLimitRetry(() => fetch(url, fetchOptions));
|
|
13730
|
+
}
|
|
13732
13731
|
var RateLimitError;
|
|
13733
13732
|
var init_http = __esm({
|
|
13734
13733
|
"src/core/http.ts"() {
|
|
13735
13734
|
"use strict";
|
|
13736
13735
|
init_constants();
|
|
13737
13736
|
init_config2();
|
|
13737
|
+
init_config();
|
|
13738
13738
|
RateLimitError = class extends Error {
|
|
13739
13739
|
constructor(info, retriesExhausted) {
|
|
13740
|
-
const
|
|
13740
|
+
const seconds = info.retryAfter ?? (info.reset > 0 ? Math.max(0, Math.ceil((info.reset * 1e3 - Date.now()) / 1e3)) : null);
|
|
13741
|
+
const message = seconds === null ? "Rate limit exceeded. The server did not say when to retry." : `Rate limit exceeded. Try again in ${seconds} seconds.`;
|
|
13741
13742
|
super(message);
|
|
13742
13743
|
this.name = "RateLimitError";
|
|
13743
13744
|
this.rateLimitInfo = info;
|
|
@@ -13748,7 +13749,7 @@ var init_http = __esm({
|
|
|
13748
13749
|
});
|
|
13749
13750
|
|
|
13750
13751
|
// src/smart-account/client.ts
|
|
13751
|
-
async function
|
|
13752
|
+
async function fetchOnceWithTimeout(url, init) {
|
|
13752
13753
|
const controller = new AbortController();
|
|
13753
13754
|
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
13754
13755
|
try {
|
|
@@ -13769,6 +13770,9 @@ async function fetchWithTimeout(url, init) {
|
|
|
13769
13770
|
clearTimeout(timer);
|
|
13770
13771
|
}
|
|
13771
13772
|
}
|
|
13773
|
+
async function fetchWithTimeout(url, init) {
|
|
13774
|
+
return withRateLimitRetry(() => fetchOnceWithTimeout(url, init));
|
|
13775
|
+
}
|
|
13772
13776
|
function extractRevertHex(err) {
|
|
13773
13777
|
if (typeof err.data === "string" && err.data.startsWith("0x"))
|
|
13774
13778
|
return err.data;
|
|
@@ -14261,7 +14265,7 @@ async function estimateRelayFeeInToken(valueWei, fromAmountWei, fromAmountUSD, c
|
|
|
14261
14265
|
tokenUnitsPerDollar = Number(fromAmountWei) / fromUSD;
|
|
14262
14266
|
} else if (fromToken && fromDecimals !== void 0) {
|
|
14263
14267
|
try {
|
|
14264
|
-
const resp = await
|
|
14268
|
+
const resp = await rateLimitedFetch(
|
|
14265
14269
|
`${apiBase()}/v1/price/token?chainId=${cid}&address=${fromToken}`,
|
|
14266
14270
|
{ headers: jsonHeaders() }
|
|
14267
14271
|
);
|
|
@@ -14277,9 +14281,10 @@ async function estimateRelayFeeInToken(valueWei, fromAmountWei, fromAmountUSD, c
|
|
|
14277
14281
|
return 0n;
|
|
14278
14282
|
}
|
|
14279
14283
|
try {
|
|
14280
|
-
const resp = await
|
|
14281
|
-
|
|
14282
|
-
|
|
14284
|
+
const resp = await rateLimitedFetch(
|
|
14285
|
+
`${apiBase()}/v1/price/native?chainId=${cid}`,
|
|
14286
|
+
{ headers: jsonHeaders() }
|
|
14287
|
+
);
|
|
14283
14288
|
if (!resp.ok) throw new Error(`native price HTTP ${resp.status}`);
|
|
14284
14289
|
const json = await resp.json();
|
|
14285
14290
|
const ethPriceUSD = parseFloat(json.data?.priceUSD ?? "0");
|