@coinlist-co/react 0.12.2-rc.4851c6a → 0.12.2-rc.4cc3d7e

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.
@@ -1,24 +1,23 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, MouseEventHandler } from 'react';
3
- import { A as AuthorizationCode, C as CodeVerifier, W as WalletError, a as AssetSymbol, E as EthereumChain, O as OfferVaultContract, b as EvmContractAddress, B as BlockchainAmount, c as CentrifugeVaultBuyTransaction, d as CentrifugeClaimDirection, e as CentrifugeNamespace, f as OfferId, g as OfferOptionId, h as AssetId, P as Participation, i as CoinListTokenSaleNamespace, j as OfferSwapContract, k as OndoBuyTransaction, l as OndoSellTransaction, m as OndoNamespace, n as OndoSwapTransactionCore, o as OrderBookSide, S as SwapQuote, p as Bps, q as EvmWalletAddress, r as SuperstateSwapNamespace, R as RequirementsNamespace, s as Requirement, t as WalletChallengeType, u as OfferOptionAddress, v as WalletsNamespace, w as Config, x as OAuthAccessToken, y as OffersNamespace, z as Erc20Namespace, T as TokensNamespace, D as StablecoinSymbol, F as Erc20Asset, G as OfferType, H as CoinListTokenSaleOfferDetail, I as OfferDetail, J as CentrifugeVaultLegId, K as CentrifugeVaultOfferDetail, L as Seconds, M as AsyncOfferType, N as AsyncOfferDetail, Q as Offer, U as TokenMetadata, V as RequirementStatusInfo, X as KycLevelName, Y as RequirementType, Z as RequirementStatusValue, _ as RequirementId, $ as PinoLoggerOptions, a0 as Logger, a1 as BuildCentrifugeVaultBuyParams, a2 as BuildOndoBuyParams, a3 as OndoSwapOfferDetail, a4 as BuildOndoSellParams, a5 as OndoQuote, a6 as OndoQuoteSize, a7 as OndoTradingStatus, a8 as AssetDecimals, a9 as SuperstateSwapOfferDetail, aa as CentrifugeVaultLeg, ab as CentrifugeVaultRef, ac as OfferOptionAddressId, ad as DocumentSubmission, ae as CentrifugeVaultStatus, af as TokenIdentifier } from '../time-Bzgi6FbG.js';
3
+ import { A as AuthorizationGrant, W as WalletError, E as EthereumChain, a as AssetSymbol, O as OfferVaultContract, b as EvmContractAddress, B as BlockchainAmount, C as CentrifugeVaultBuyTransaction, c as CentrifugeClaimDirection, d as CentrifugeNamespace, e as CoinListTokenSaleOfferDetail, f as OfferOptionId, S as StablecoinSymbol, P as Participation, g as CoinListTokenSaleNamespace, h as OfferSwapContract, i as OndoBuyTransaction, j as OndoSellTransaction, k as OndoNamespace, l as OndoSwapTransactionCore, m as OrderBookSide, n as OfferId, o as SwapQuote, p as Bps, q as EvmWalletAddress, r as SuperstateSwapNamespace, R as RequirementsNamespace, s as Requirement, t as WalletChallengeType, u as OfferOptionAddress, v as WalletsNamespace, w as Config, x as OAuthAccessToken, y as OffersNamespace, z as Erc20Namespace, T as TokensNamespace, D as Offer, F as TokenMetadata, G as OfferDetail, H as Erc20Asset, I as CentrifugeVaultLegId, J as CentrifugeVaultOfferDetail, K as Seconds, L as AsyncOfferDetail, M as RequirementStatusInfo, N as KycLevelName, Q as RequirementType, U as RequirementStatusValue, V as RequirementId, X as PinoLoggerOptions, Y as Logger, Z as AuthorizationCode, _ as CodeVerifier, $ as CentrifugeVaultStatus, a0 as CentrifugeVaultRef, a1 as BuildOndoBuyParams, a2 as OndoSwapOfferDetail, a3 as BuildOndoSellParams, a4 as OndoQuote, a5 as OndoQuoteSize, a6 as OndoTradingStatus, a7 as AssetDecimals, a8 as SuperstateSwapOfferDetail, a9 as CentrifugeVaultLeg, aa as CentrifugeVault, ab as OfferOptionAddressId, ac as DocumentSubmission, ad as TokenIdentifier } from '../time-BgR3LVER.js';
4
4
  import { Hash } from 'viem';
5
- import { E as EvmWallet, C as ConnectWallet, F as FormattedAmountAssetUi, T as TxExplorerUrl, A as AssetIconUrl, W as WalletSelection, a as WalletLabelResolver, S as ShortenedWalletAddress, b as FormattedPercentUi, N as NonEmptyArray, c as TokenRegistrySnapshot } from '../token-registry-snapshot-BmjXOvvg.js';
5
+ import { E as EvmWallet, C as ConnectWallet, W as WalletSelection, F as FormattedAmountAssetUi, T as TxExplorerUrl, A as AssetIconUrl, a as WalletLabelResolver, S as ShortenedWalletAddress, b as FormattedPercentUi, N as NonEmptyArray, c as TokenRegistrySnapshot } from '../token-registry-snapshot-CE21sVyi.js';
6
6
 
7
7
  type AuthState = 'unknown' | 'logged-in' | 'logged-out';
8
8
  /** Discriminated error reasons from {@link CoinListClient.completeOAuth}. */
9
9
  type OAuthClientErrorReason = 'user_canceled' | 'missing_state' | 'invalid_state' | 'missing_code' | 'missing_code_verifier';
10
- type OAuthClientResult = {
10
+ type OAuthClientResult = ({
11
11
  type: 'ok';
12
- code: AuthorizationCode;
13
- codeVerifier: CodeVerifier;
14
- } | {
12
+ } & AuthorizationGrant) | {
15
13
  type: 'error';
16
14
  reason: OAuthClientErrorReason;
17
15
  };
18
16
 
19
17
  /**
20
18
  * Everything the browser half of the SDK knows about the current user's
21
- * session, and the OAuth 2.0 + PKCE flow that establishes one.
19
+ * session, and the OAuth 2.0 + PKCE flow that establishes one - e.g.
20
+ * `coinlist.auth.getState()` or `coinlist.auth.startOAuth()`.
22
21
  *
23
22
  * The SDK never holds a client secret in the browser: {@link startOAuth}
24
23
  * redirects the user to CoinList, and {@link completeOAuth} only parses and
@@ -73,7 +72,7 @@ interface ClientAuthNamespace {
73
72
  logout(): void;
74
73
  }
75
74
 
76
- type Erc20AllowancePhase = 'checking-allowance' | 'resetting-allowance' | 'confirming-allowance-reset' | 'approving' | 'confirming-approval';
75
+ type Erc20AllowancePhase = 'checking-allowance' | ResetThenApprovePhase;
77
76
  type Erc20AllowanceError = {
78
77
  step: 'allowance-check';
79
78
  } | Erc20ApprovalError;
@@ -84,24 +83,32 @@ type Erc20ApprovalError = {
84
83
  } | {
85
84
  step: 'approval-reverted';
86
85
  };
86
+ /**
87
+ * The phases {@link resetThenApprove} reports, in order. The two reset phases
88
+ * occur only when there is a non-zero allowance to reset.
89
+ */
90
+ type ResetThenApprovePhase = 'resetting-allowance' | 'confirming-allowance-reset' | 'approving' | 'confirming-approval';
87
91
 
88
92
  /**
89
- * Progress phases emitted while a request is being prepared, in order. An
90
- * allowance that already covers the deposit skips the approval phases.
91
- *
92
- * @alpha
93
+ * Progress phases emitted while a backend-built order is being prepared, in
94
+ * the order they occur. An allowance that already covers the order skips the
95
+ * approval phases.
93
96
  */
94
- type CentrifugeBuyPreparationPhase = Erc20AllowancePhase | 'building-transaction';
97
+ type ApproveThenBuildPhase = Erc20AllowancePhase | 'building-transaction';
95
98
  /**
96
99
  * A step-tagged reason a preparation failed.
97
100
  *
98
- * `insufficient-allowance` is the one with a remedy that is not a new
99
- * approval: the approval this flow just mined is not the one frontline sees,
100
- * usually because its node is a block behind. Retrying reads it again.
101
+ * Every arm names a *remedy* rather than a provider or a trade: an unsupported
102
+ * chain, a refused approval and a build that would not complete are fixed the
103
+ * same way whichever token was being approved, and whoever built it.
101
104
  *
102
- * @alpha
105
+ * `insufficient-allowance` is separated from the generic build failure because
106
+ * it is the one with a remedy: the backend reads the allowance itself before
107
+ * building, so reaching it means the approval this flow just mined is not the
108
+ * one the backend sees. That is usually its RPC node lagging a block behind,
109
+ * which retrying fixes - so it is a retry, not a re-approval.
103
110
  */
104
- type CentrifugeBuyPreparationError = {
111
+ type ApproveThenBuildError = {
105
112
  step: 'unsupported-chain';
106
113
  chain: EthereumChain;
107
114
  } | Erc20AllowanceError | {
@@ -109,14 +116,34 @@ type CentrifugeBuyPreparationError = {
109
116
  } | {
110
117
  step: 'build-transaction';
111
118
  };
112
- /** @alpha */
113
- type CentrifugeBuyPreparationResult = {
119
+ /**
120
+ * A prepared order of whichever kind was asked for, or the step that stopped
121
+ * it. Generic in the transaction, so a caller gets back the type its `build`
122
+ * returned.
123
+ */
124
+ type ApproveThenBuildResult<T> = {
114
125
  type: 'success';
115
- transaction: CentrifugeVaultBuyTransaction;
126
+ transaction: T;
116
127
  } | {
117
128
  type: 'error';
118
- error: CentrifugeBuyPreparationError;
129
+ error: ApproveThenBuildError;
119
130
  };
131
+
132
+ /**
133
+ * Progress phases emitted while a request is being prepared, in order. An
134
+ * allowance that already covers the deposit skips the approval phases.
135
+ *
136
+ * @alpha
137
+ */
138
+ type CentrifugeBuyPreparationPhase = ApproveThenBuildPhase;
139
+ /**
140
+ * A step-tagged reason a preparation failed - see {@link ApproveThenBuildError}.
141
+ *
142
+ * @alpha
143
+ */
144
+ type CentrifugeBuyPreparationError = ApproveThenBuildError;
145
+ /** @alpha */
146
+ type CentrifugeBuyPreparationResult = ApproveThenBuildResult<CentrifugeVaultBuyTransaction>;
120
147
  /** @alpha */
121
148
  type PrepareCentrifugeBuyParams = {
122
149
  wallet: EvmWallet;
@@ -250,7 +277,7 @@ type CentrifugeClaimResult = {
250
277
  direction: CentrifugeClaimDirection;
251
278
  txHash: Hash;
252
279
  /**
253
- * What the calldata was built to collect: shares for `invest`, the
280
+ * What the calldata was built to collect: shares for `deposit`, the
254
281
  * funding token for `redeem`. A floor rather than an exact figure - a
255
282
  * fill landing before the broadcast raises it, and the claim collects
256
283
  * everything.
@@ -283,8 +310,8 @@ type ClaimCentrifugeVaultParams = {
283
310
  * broadcast. The two halves stay beside it. The checkout runs them itself so
284
311
  * it can drop a build that finishes after the user has left, and a host that
285
312
  * wants to show the calldata before broadcasting can do the same. The amount
286
- * step calls neither. The request settles later. Broadcasting it does not
287
- * buy shares.
313
+ * step calls neither, and like the builders they wrap they are not free to
314
+ * poll. The request settles later. Broadcasting it does not buy shares.
288
315
  *
289
316
  * @alpha
290
317
  */
@@ -326,6 +353,10 @@ type TokenSaleExecutionPhase = 'checking-allowance' | 'resetting-allowance' | 'c
326
353
  /**
327
354
  * A step-tagged reason `ClientCoinListTokenSaleNamespace.execute` failed.
328
355
  *
356
+ * The first three are refusals before anything is signed: the offer names no
357
+ * funding contract on the chain, does not accept the coin there, or has no
358
+ * option with that id.
359
+ *
329
360
  * The reset-to-zero step (`allowance-reset` / `allowance-reset-reverted`) is
330
361
  * reported distinctly from the main approval (`approval` /
331
362
  * `approval-reverted`, reused from {@link Erc20ApprovalError}) so consumers can
@@ -333,6 +364,12 @@ type TokenSaleExecutionPhase = 'checking-allowance' | 'resetting-allowance' | 'c
333
364
  * reverted on-chain.
334
365
  */
335
366
  type TokenSaleExecutionError = {
367
+ step: 'unsupported-chain';
368
+ } | {
369
+ step: 'unsupported-asset';
370
+ } | {
371
+ step: 'unknown-option';
372
+ } | {
336
373
  step: 'allowance-check';
337
374
  } | {
338
375
  step: 'allowance-reset';
@@ -351,25 +388,44 @@ type TokenSaleExecutionResult = {
351
388
  type: 'error';
352
389
  error: TokenSaleExecutionError;
353
390
  };
391
+ /**
392
+ * Which approval a participation is recorded against.
393
+ *
394
+ * `fresh` sends a new one, which is what every first attempt does. `mined`
395
+ * reuses one that already mined for this amount - the `approvalTxHash` of a
396
+ * `participation` failure - so retrying the write asks the wallet for nothing.
397
+ */
398
+ type TokenSaleApproval = {
399
+ type: 'fresh';
400
+ } | {
401
+ type: 'mined';
402
+ txHash: Hash;
403
+ };
354
404
  type ExecuteTokenSaleParams = {
355
405
  wallet: EvmWallet;
356
- offerId: OfferId;
357
- offerOptionId: OfferOptionId;
358
- assetId: AssetId;
359
- /** ERC-20 the user pays with (e.g. USDC/USDT). */
360
- paymentTokenAddress: EvmContractAddress;
361
- /** Contract that pulls the payment — the `approve()` spender. */
362
- fundingContractAddress: EvmContractAddress;
406
+ /**
407
+ * The sale being bought into. The funding contract, the coin's address and
408
+ * its asset id are all read off it, so the caller never supplies one.
409
+ */
410
+ offer: CoinListTokenSaleOfferDetail;
411
+ /** The option being bought, which sets the price. */
412
+ optionId: OfferOptionId;
363
413
  chain: EthereumChain;
414
+ /** The coin the user pays in. It must be one of the offer's funding assets. */
415
+ inputAsset: StablecoinSymbol;
416
+ /** How much of `inputAsset` to commit, in its base units. */
364
417
  amount: BlockchainAmount;
418
+ /** Defaults to `{ type: 'fresh' }`. */
419
+ approval?: TokenSaleApproval;
365
420
  onProgress?: (phase: TokenSaleExecutionPhase) => void;
366
421
  };
367
422
 
368
423
  /**
369
424
  * The client-side token-sale namespace: everything the shared
370
425
  * {@link CoinListTokenSaleNamespace} reads/writes over the API, plus the
371
- * on-chain flow that drives a wallet (`execute`). The flow takes the wallet
372
- * and addresses per call; the namespace supplies the participation writes and
426
+ * on-chain flow that drives a caller-supplied `EvmWallet` (`execute`) -
427
+ * e.g. `coinlist.tokenSale.execute({ ... })`. The flow takes the wallet and
428
+ * addresses per call; the namespace supplies the participation writes and
373
429
  * (via the ERC-20 namespace) the allowance read it depends on.
374
430
  */
375
431
  interface ClientCoinListTokenSaleNamespace extends CoinListTokenSaleNamespace {
@@ -388,28 +444,13 @@ interface ClientCoinListTokenSaleNamespace extends CoinListTokenSaleNamespace {
388
444
  * Progress phases emitted while an order is being prepared, in the order they
389
445
  * occur. An allowance that already covers the order skips the approval phases.
390
446
  */
391
- type OndoSwapPreparationPhase = Erc20AllowancePhase | 'building-transaction';
447
+ type OndoSwapPreparationPhase = ApproveThenBuildPhase;
392
448
  /**
393
- * A step-tagged reason a preparation failed.
394
- *
395
- * Shared by both directions because every arm names a *remedy* rather than a
396
- * trade: an unsupported chain, a refused approval and a build that would not
397
- * complete are fixed the same way whichever token was being approved.
398
- *
399
- * `insufficient-allowance` is separated from the generic build failure because
400
- * it is the one with a remedy: frontline reads the allowance before asking
401
- * Ninshubur for anything, so reaching it means the approval this flow just
402
- * mined is not the one frontline sees. That is usually its RPC node lagging a
403
- * block behind, which retrying fixes - so it is a retry, not a re-approval.
449
+ * A step-tagged reason a preparation failed. Shared by both directions, and
450
+ * with every other backend-built checkout, because every arm names a remedy
451
+ * rather than a trade - see {@link ApproveThenBuildError}.
404
452
  */
405
- type OndoSwapPreparationError = {
406
- step: 'unsupported-chain';
407
- chain: EthereumChain;
408
- } | Erc20AllowanceError | {
409
- step: 'insufficient-allowance';
410
- } | {
411
- step: 'build-transaction';
412
- };
453
+ type OndoSwapPreparationError = ApproveThenBuildError;
413
454
  /**
414
455
  * A prepared order of whichever kind was asked for, or the step that stopped
415
456
  * it.
@@ -417,13 +458,7 @@ type OndoSwapPreparationError = {
417
458
  * Generic in the transaction rather than a union over the two, so a caller
418
459
  * that asked for a sale cannot be handed a purchase to narrow.
419
460
  */
420
- type OndoSwapPreparationResult<T> = {
421
- type: 'success';
422
- transaction: T;
423
- } | {
424
- type: 'error';
425
- error: OndoSwapPreparationError;
426
- };
461
+ type OndoSwapPreparationResult<T> = ApproveThenBuildResult<T>;
427
462
  type OndoBuyPreparationResult = OndoSwapPreparationResult<OndoBuyTransaction>;
428
463
  type OndoSellPreparationResult = OndoSwapPreparationResult<OndoSellTransaction>;
429
464
  /** What both preparations take, before the two fields whose meaning forks. */
@@ -477,12 +512,21 @@ type OndoSwapExecutionPhase = 'broadcasting-swap' | 'confirming-swap';
477
512
  * `quote-expired` is a refusal to broadcast rather than a failure of a
478
513
  * broadcast: it would revert on chain and cost the user gas, and it is fixed
479
514
  * by building a fresh transaction.
515
+ *
516
+ * `swap` means the wallet never sent it, so placing again is safe.
517
+ * `swap-unconfirmed` means it was sent and the receipt wait failed: the swap
518
+ * may still mine, and placing again can fill the order twice. `txHash` is
519
+ * the transaction to look up before doing anything else.
480
520
  */
481
521
  type OndoSwapExecutionError = {
482
522
  step: 'quote-expired';
483
523
  } | {
484
524
  step: 'swap';
485
525
  cause: WalletError;
526
+ } | {
527
+ step: 'swap-unconfirmed';
528
+ txHash: Hash;
529
+ cause: WalletError;
486
530
  } | {
487
531
  step: 'swap-reverted';
488
532
  };
@@ -520,7 +564,12 @@ type ExecuteOndoSwapParams<T> = {
520
564
 
521
565
  /**
522
566
  * The Ondo namespace plus the halves of placing an order that need a wallet,
523
- * and so cannot live on the shared namespace.
567
+ * and so cannot live on the shared namespace: `prepareBuy` / `prepareSell`
568
+ * (approve, then commit a firm quote) and `executeSwap` (broadcast it).
569
+ *
570
+ * Like the builders they wrap, the prepare methods spend an attestation, so
571
+ * unlike the reads they are not free to poll: call one when the user commits
572
+ * to an amount, never on a timer.
524
573
  *
525
574
  * Preparing and executing are two calls rather than one because the flow is
526
575
  * two user decisions: the trader commits to an amount (approving the spend),
@@ -585,9 +634,21 @@ type SwapExecutionError = {
585
634
  step: 'swap-paused';
586
635
  } | {
587
636
  step: 'swap-stopped';
588
- } | Erc20AllowanceError | {
637
+ } | Erc20AllowanceError
638
+ /** The wallet never sent the swap, so swapping again is safe. */
639
+ | {
589
640
  step: 'swap';
590
641
  cause: WalletError;
642
+ }
643
+ /**
644
+ * The swap was sent and the receipt wait failed. It may still mine, so
645
+ * swapping again can fill the order twice: `txHash` is the transaction to
646
+ * look up before doing anything else.
647
+ */
648
+ | {
649
+ step: 'swap-unconfirmed';
650
+ txHash: Hash;
651
+ cause: WalletError;
591
652
  } | {
592
653
  step: 'swap-reverted';
593
654
  };
@@ -642,9 +703,21 @@ type WalletAuthorizationError = {
642
703
  cause: WalletError;
643
704
  } | {
644
705
  step: 'allow-wallet';
645
- } | {
706
+ }
707
+ /** The wallet never sent the allow-list transaction. */
708
+ | {
646
709
  step: 'broadcast';
647
710
  cause: WalletError;
711
+ }
712
+ /**
713
+ * The allow-list transaction was sent and the receipt wait failed. It may
714
+ * still mine, so authorizing again would send a second one: `txHash` is the
715
+ * transaction to look up first.
716
+ */
717
+ | {
718
+ step: 'broadcast-unconfirmed';
719
+ txHash: Hash;
720
+ cause: WalletError;
648
721
  } | {
649
722
  step: 'not-authorized';
650
723
  };
@@ -665,7 +738,8 @@ type AuthorizeWalletParams = {
665
738
  /**
666
739
  * The client-side swap namespace: everything the shared
667
740
  * {@link SuperstateSwapNamespace} reads/writes over the API, plus the on-chain flows
668
- * that drive a wallet (`execute`, `authorizeWallet`). The flows take the
741
+ * that drive a caller-supplied wallet (`execute`, `authorizeWallet`) and
742
+ * return a step-tagged result rather than throwing. The flows take the
669
743
  * wallet and addresses per call; the namespace itself supplies the API reads
670
744
  * they depend on.
671
745
  */
@@ -706,7 +780,7 @@ interface ClientRequirementsNamespace extends RequirementsNamespace {
706
780
  }
707
781
 
708
782
  /**
709
- * Getting the user to a human at CoinList.
783
+ * Getting the user to a human at CoinList - `coinlist.support.contact()`.
710
784
  *
711
785
  * This namespace is client-only: it opens a browser tab and has no
712
786
  * `CoinListServer` counterpart. No method here requires authentication.
@@ -767,7 +841,8 @@ type ConnectWalletParams = {
767
841
 
768
842
  /**
769
843
  * The wallets namespace plus the one operation that needs the host's wallet:
770
- * proving ownership of it and binding it to an offer option, in one call.
844
+ * proving ownership of it and binding it to an offer option, in one call -
845
+ * `coinlist.wallets.connect({ wallet, offerId, offerOptionId })`.
771
846
  *
772
847
  * The shared {@link WalletsNamespace} already has both halves -
773
848
  * `createOwnershipChallenge` and `connectExternal` - but a signature has to
@@ -826,96 +901,27 @@ interface ClientConfig extends Config {
826
901
  * when the user is not authenticated.
827
902
  */
828
903
  interface CoinListClient {
829
- /**
830
- * Authentication: the current {@link AuthState}, and the browser half of the
831
- * OAuth 2.0 + PKCE flow — e.g. `coinlist.auth.startOAuth()`.
832
- */
904
+ /** Auth state and the browser half of OAuth - see {@link ClientAuthNamespace}. */
833
905
  readonly auth: ClientAuthNamespace;
834
- /**
835
- * The offer catalogue: listing offers and reading one in full — e.g.
836
- * `coinlist.offers.get(offerId)`.
837
- */
906
+ /** The offer catalogue, e.g. `coinlist.offers.get(offerId)` - see {@link OffersNamespace}. */
838
907
  readonly offers: OffersNamespace;
839
- /**
840
- * What the user must satisfy before participating in an offer: the
841
- * checklist and its statuses, identity verification (KYC), and tax-document
842
- * signing — e.g. `coinlist.requirements.statuses(offerId)`.
843
- *
844
- * Also exposes `handle(requirement)`, which sends the user to the CoinList
845
- * page that satisfies a requirement.
846
- */
908
+ /** What a user must satisfy to participate - see {@link ClientRequirementsNamespace}. */
847
909
  readonly requirements: ClientRequirementsNamespace;
848
- /**
849
- * The user's external wallets: proving ownership, binding a wallet to an
850
- * offer option, and managing those bindings — e.g.
851
- * `coinlist.wallets.connect({ wallet, offerId, offerOptionId })`.
852
- */
910
+ /** Wallet ownership proofs and offer-option bindings - see {@link ClientWalletsNamespace}. */
853
911
  readonly wallets: ClientWalletsNamespace;
854
- /**
855
- * Generic ERC-20 reads (token allowance and balance) shared across the
856
- * on-chain flows — e.g. `coinlist.erc20.getBalance({ ... })`.
857
- */
912
+ /** Generic ERC-20 allowance and balance reads - see {@link Erc20Namespace}. */
858
913
  readonly erc20: Erc20Namespace;
859
- /**
860
- * Token-sale operations: listing/reading/recording participations, plus the
861
- * on-chain `execute` flow that submits the ERC-20 approval and records the
862
- * participation over a caller-supplied {@link EvmWallet} — e.g.
863
- * `coinlist.tokenSale.execute({ ... })`.
864
- *
865
- * `execute` drives a caller-supplied wallet and returns a step-tagged result
866
- * rather than throwing.
867
- */
914
+ /** Token-sale participations and the on-chain purchase - see {@link ClientCoinListTokenSaleNamespace}. */
868
915
  readonly tokenSale: ClientCoinListTokenSaleNamespace;
869
- /**
870
- * On-chain swap operations: quoting a swap, reading swap-contract state, and
871
- * allow-listing a proven wallet — e.g.
872
- * `coinlist.superstate.getOutputToken({ contractAddress, chain })`.
873
- *
874
- * The on-chain flows (`execute`, `authorizeWallet`) additionally drive a
875
- * caller-supplied wallet.
876
- */
916
+ /** Superstate swaps - see {@link ClientSuperstateSwapNamespace}. */
877
917
  readonly superstate: ClientSuperstateSwapNamespace;
878
- /**
879
- * Ondo swaps: whether an asset is tradable right now and what it costs - e.g.
880
- * `coinlist.ondo.getQuote({ ... })` - plus placing an order, in the two
881
- * halves the flow actually has: `prepareBuy` / `prepareSell` (approve, then
882
- * commit a firm quote) and `executeSwap` (broadcast it).
883
- *
884
- * Preparing is two methods because the directions approve different tokens -
885
- * the funding coin on a purchase, the asset on a sale - and commit to
886
- * different terms; broadcasting is one, because it reads calldata and a
887
- * deadline and knows about neither.
888
- *
889
- * The reads are free to poll while the user edits an order. Preparing is
890
- * not: committing a quote spends an attestation.
891
- *
892
- * No CoinList fee is applied to a read quote; see
893
- * {@link ClientOndoNamespace}.
894
- */
918
+ /** Ondo swap quotes and orders - see {@link ClientOndoNamespace}. */
895
919
  readonly ondo: ClientOndoNamespace;
896
- /**
897
- * Centrifuge vault deposits and claims: the vault-wide ordering gate, each
898
- * wallet's position, the two halves of placing a request, and the claim
899
- * that settles a filled one.
900
- *
901
- * The reads are free to poll. `prepareBuy` and `placeRequest` are not.
902
- * Broadcasting places a request. It does not buy shares.
903
- */
920
+ /** Centrifuge vault requests and claims - see {@link ClientCentrifugeNamespace}. */
904
921
  readonly centrifuge: ClientCentrifugeNamespace;
905
- /**
906
- * Token display metadata (name, symbol, decimals, logos) from CoinList's
907
- * public token registry, keyed by chain + contract address — e.g.
908
- * `coinlist.tokens.get({ chain, address })` for an entry of
909
- * `Offer.tokens`, or `coinlist.tokens.list()` for the whole
910
- * catalogue in one request.
911
- *
912
- * Public and unauthenticated: unlike the other namespaces, its methods never
913
- * require a logged-in user.
914
- */
922
+ /** Public token display metadata - see {@link TokensNamespace}. */
915
923
  readonly tokens: TokensNamespace;
916
- /**
917
- * Contacting CoinList support — `coinlist.support.contact()`.
918
- */
924
+ /** Contacting CoinList support - see {@link ClientSupportNamespace}. */
919
925
  readonly support: ClientSupportNamespace;
920
926
  /**
921
927
  * Calls the provided {@link ClientConfig.getAccessToken} lambda to determine
@@ -1025,140 +1031,348 @@ interface CoinListSignInCardContainerProps {
1025
1031
  declare function CoinListSignInCardContainer({ state, onSignIn, onClose, className, }?: CoinListSignInCardContainerProps): ReactNode;
1026
1032
 
1027
1033
  /**
1028
- * A deposit request that has been broadcast and mined.
1029
- *
1030
- * Named without `Buy` so it does not collide with the dialog component when
1031
- * both are re-exported from the client barrel.
1032
- *
1033
- * Success means the request was placed. The fund fulfils it later, at a price
1034
- * set then.
1035
- *
1036
- * @alpha
1034
+ * What the grid fetches, pre-fetched on the server instead. Each half is
1035
+ * independent: seed `offers` (via `CoinListServer#offers.list()`) and the
1036
+ * client still fetches the registry, seed `tokens` (via
1037
+ * `CoinListServer#tokens.list()`) and it still fetches the offers, seed both
1038
+ * and the grid makes no request of its own.
1037
1039
  */
1038
- type CentrifugeOrderPlaced = {
1039
- wallet: EvmWallet;
1040
- /** What the request deposits, in the funding token's base units. */
1041
- amount: BlockchainAmount;
1042
- transaction: CentrifugeVaultBuyTransaction;
1043
- txHash: Hash;
1044
- };
1040
+ interface OffersGridData {
1041
+ offers?: Offer[];
1042
+ tokens?: TokenMetadata[];
1043
+ }
1045
1044
 
1045
+ interface OffersGridContainerProps {
1046
+ /** Maximum number of columns to render when horizontal space allows. */
1047
+ maxColumns?: number;
1048
+ /** Optional className applied to the grid element. */
1049
+ className?: string;
1050
+ /** Optional className applied to the outer wrapper element. */
1051
+ containerClassName?: string;
1052
+ /** Optional loading slot shown while offers are being fetched. */
1053
+ loading?: ReactNode;
1054
+ /** Optional error slot shown when loading offers fails. */
1055
+ error?: ReactNode;
1056
+ /** Optional empty state slot shown when there are no available offers. */
1057
+ emptyState?: ReactNode;
1058
+ /** Optional per-offer click handler; when omitted, cards are not clickable. */
1059
+ onOfferClick?: (offer: Offer) => void;
1060
+ /**
1061
+ * What the grid would otherwise fetch, pre-fetched on the server: `offers`
1062
+ * via `CoinListServer#offers.list()`, `tokens` via
1063
+ * `CoinListServer#tokens.list()`. Each half skips its own client-side
1064
+ * fetch; pass both for a grid that makes no request of its own.
1065
+ */
1066
+ data?: OffersGridData;
1067
+ /**
1068
+ * Default `true`. When `false` nothing is fetched, so the container can be
1069
+ * mounted while the grid is not needed yet.
1070
+ */
1071
+ enabled?: boolean;
1072
+ }
1046
1073
  /**
1047
- * A filled Ondo order, as the confirmation dialog and the host's
1048
- * `onOrderConfirmed` callback need it.
1049
- *
1050
- * It lives here rather than beside either review viewmodel because both
1051
- * products produce one. Declaring it in `ondo/buy/` would make the sell
1052
- * viewmodel import a sibling product's module - which the `shared/` ladder
1053
- * forbids for the reason it always does: two products that reach sideways can
1054
- * no longer be moved or deleted on their own.
1074
+ * Displays a responsive live-sale grid of {@link OfferSaleCard}, backed by
1075
+ * {@link useOffersGridViewModel}. Each card is named and illustrated by the
1076
+ * public token registry where it lists the offer's token, and by the offer's
1077
+ * own fields otherwise - list offers carry no display name, so an unlisted
1078
+ * one shows logo + tagline until the host maps from detail. For equities /
1079
+ * past-sales browse rows, compose {@link OffersAssetGrid} instead.
1055
1080
  *
1056
- * It names no asset beyond the one that was spent. The transaction does not
1057
- * carry one, and rebuilding an `Erc20Asset` here would mean inventing a
1058
- * `decimals` - the quote's answers for a different quantity, and the
1059
- * transaction's is a scale rather than a property of the token. A host that
1060
- * wants to know what was traded has the `offer` it passed in.
1061
- */
1062
- type OndoOrderPlaced = OndoBuyOrderPlaced | OndoSellOrderPlaced;
1063
- /**
1064
- * The common half of an {@link OndoOrderPlaced}, before its side's terms.
1081
+ * Pass `data` (offers and tokens pre-fetched server-side) to use them as-is
1082
+ * and skip the client-side fetches. Pass `enabled={false}` to skip the fetches
1083
+ * when the container is mounted but the grid is not needed yet. Uses the
1084
+ * `loading` / `error` / `emptyState` slots when provided; otherwise renders
1085
+ * the standard fallbacks. Cards are interactive only when `onOfferClick` is
1086
+ * provided.
1065
1087
  *
1066
- * The transaction that was broadcast is not here, because it is not common:
1067
- * it carries the same `side` this order does, and saying so in prose left a
1068
- * sell order holding a buy transaction constructible and its
1069
- * `minimumReceiveOutputAmount` unreachable behind a narrowed `side`. Each arm
1070
- * names its own instead.
1071
- */
1072
- type OndoOrderPlacedCore = {
1073
- txHash: Hash;
1074
- /** What the trader spent, in the input asset's base units. */
1075
- amount: BlockchainAmount;
1076
- wallet: EvmWallet;
1077
- };
1078
- /** A filled purchase: a stablecoin spent, the asset received. */
1079
- type OndoBuyOrderPlaced = OndoOrderPlacedCore & OndoBuyOrderTerms;
1080
- /** A filled sale: the asset spent, the settlement coin received. */
1081
- type OndoSellOrderPlaced = OndoOrderPlacedCore & OndoSellOrderTerms;
1082
- /**
1083
- * A buy spends a stablecoin the SDK ships a registry entry for, so its input
1084
- * asset is narrowed to one - which is what keeps `TOKEN_REGISTRY.erc20` total
1085
- * at the call sites that name it.
1088
+ * Self-scoped: renders fully styled on its own, with no `CoinListStyleScope`
1089
+ * needed.
1086
1090
  */
1087
- type OndoBuyOrderTerms = {
1088
- side: 'buy';
1089
- inputAsset: StablecoinSymbol;
1090
- /** The purchase that was broadcast, and the deposit it was struck against. */
1091
- transaction: OndoBuyTransaction;
1092
- };
1091
+ declare function OffersGridContainer({ data, onOfferClick, enabled, ...viewProps }?: OffersGridContainerProps): ReactNode;
1092
+
1093
1093
  /**
1094
- * A sell spends the Ondo asset, which is in no registry: its address and
1095
- * decimals come off the quote, and only its symbol is carried here. Hence the
1096
- * wider `AssetSymbol`, and hence a SUM rather than one widened field - a buy
1097
- * that lost its stablecoin guarantee would be the cost of sharing one.
1094
+ * One image as an `<img>` renders it: a `src` for a consumer that takes a
1095
+ * single URL, and the `srcSet` candidates for one that also knows the size
1096
+ * it renders at. `srcSet` is absent for a vector logo and for the offer's own
1097
+ * artwork, neither of which offers the browser a choice.
1098
1098
  */
1099
- type OndoSellOrderTerms = {
1100
- side: 'sell';
1101
- inputAsset: AssetSymbol;
1102
- /** The sale that was broadcast, and the floor under the proceeds it names. */
1103
- transaction: OndoSellTransaction;
1099
+ type LogoImageUi = {
1100
+ src: string;
1101
+ srcSet?: string;
1104
1102
  };
1105
-
1106
1103
  /**
1107
- * The wallets a checkout can spend from, supplied by the host.
1108
- *
1109
- * The SDK ships no wallet stack and is not coupled to Privy, AppKit or
1110
- * anything else - a partner may be a wallet provider themselves - so wallet
1111
- * discovery and connection are inverted onto the host. It hands over ready
1112
- * {@link EvmWallet}s and two lambdas; the SDK decides nothing about how they
1113
- * came to exist.
1114
- *
1115
- * There is no separate wallet model here on purpose: `EvmWallet` already
1116
- * carries the `address`, so a `{ address, signer }` pair would be a second
1117
- * wallet type to keep in sync with the first.
1104
+ * The logo a catalogue card renders for an offer, with the registry's
1105
+ * dark-theme counterpart when it configures one.
1118
1106
  *
1119
- * Everything the row displays beyond the address - the network name - comes
1120
- * from the checkout's execution chain rather than from the wallet, because
1121
- * that is the chain the transaction goes to whatever the wallet is currently
1122
- * pointed at.
1107
+ * `dark` is `null` rather than absent so a renderer has to decide what to do
1108
+ * without one: fall back to `light`, which is the registry's own rule.
1123
1109
  */
1124
- type CheckoutWalletSelection = {
1125
- /**
1126
- * The user's embedded (custodial) wallets, in display order. Empty when they
1127
- * have none, which is a normal state, not an error.
1128
- */
1129
- embedded: EvmWallet[];
1130
- /** The connected external wallet, or `null` while none is connected. */
1131
- external: EvmWallet | null;
1110
+ type OfferLogoUi = {
1111
+ light: LogoImageUi;
1112
+ dark: LogoImageUi | null;
1113
+ };
1114
+ declare const OfferLogoUi: {
1132
1115
  /**
1133
- * A wallet the host has already settled on, or `null` to let the user pick.
1134
- *
1135
- * When set, a checkout that supports it skips its wallet step entirely and
1136
- * opens on the amount, renumbering the steps that remain. That is for the
1137
- * host that already knows the answer - a sell page reached from a position
1138
- * knows which wallet holds it, and asking again would be a question with one
1139
- * possible answer.
1140
- *
1141
- * It does not have to appear in `embedded` or `external`. The host supplies a
1142
- * ready {@link EvmWallet} either way, and the SDK never resolves this back to
1143
- * a row.
1116
+ * The registry's logo for the token an offer is about, or the offer's own
1117
+ * artwork otherwise, or `null` when neither exists.
1144
1118
  *
1145
- * **Only the Ondo sell checkout honours it today.** The field is on this seam
1146
- * rather than on one provider's config because nothing about it is Ondo's -
1147
- * any flow that opens on a wallet step could skip one - but a provider that
1148
- * has not adopted it ignores it rather than half-implementing it, so do not
1149
- * assume a skip from the field being set.
1119
+ * The registry wins when both exist because it is the token's real artwork
1120
+ * where `Offer.logoUrl` is catalogue artwork, and because a swap publishes
1121
+ * without artwork more often than not - which is why `logoUrl` is `null`
1122
+ * on the swap variants.
1150
1123
  */
1151
- preselected: EvmWallet | null;
1124
+ fromOffer: (offer: {
1125
+ logoUrl: string | null;
1126
+ }, tokenMetadata: TokenMetadata | null) => OfferLogoUi | null;
1127
+ };
1128
+
1129
+ /**
1130
+ * An offer as {@link OfferAssetCard} renders it. Browse chrome: circular
1131
+ * `logo`, `name`, and asset `symbol`. No wordmark.
1132
+ *
1133
+ * All three come from the public token registry when the caller hands over
1134
+ * the metadata of the token the offer is about. Without it, `fromOffer`
1135
+ * omits `name` and `symbol` - the list payload has neither - so a list-mapped
1136
+ * card is honest about being logo-only, and `fromDetail` reads them from the
1137
+ * detail payload (`name`, `asset.code`).
1138
+ */
1139
+ type OfferAssetCardUi = {
1140
+ id: OfferId;
1141
+ /** Absent when neither the registry nor a detail payload names the offer. */
1142
+ name?: string;
1143
+ /** Absent when neither the registry nor a detail payload carries a ticker. */
1144
+ symbol?: string;
1145
+ /** `null` when neither the registry nor the offer carries artwork. */
1146
+ logo: OfferLogoUi | null;
1147
+ };
1148
+ declare const OfferAssetCardUi: {
1149
+ /**
1150
+ * `tokenMetadata` is the registry's entry for the token the offer is about
1151
+ * (`TokenRegistrySnapshot.forOffer`), or `null` when it lists none. The
1152
+ * registry names win over the offer's own where both exist: they are the
1153
+ * token's canonical name, ticker and artwork, where the offer's are
1154
+ * catalogue copy.
1155
+ */
1156
+ fromOffer: (offer: Offer, tokenMetadata?: TokenMetadata | null) => OfferAssetCardUi;
1157
+ fromDetail: (detail: OfferDetail, tokenMetadata?: TokenMetadata | null) => OfferAssetCardUi;
1158
+ };
1159
+
1160
+ interface OfferAssetCardProps {
1161
+ offer: OfferAssetCardUi;
1162
+ /** When set, the whole card is the hit target. */
1163
+ onClick?: () => void;
1164
+ /** Optional className applied to the card root element. */
1165
+ className?: string;
1166
+ /** Optional className applied to an outer wrapper element. */
1167
+ containerClassName?: string;
1168
+ }
1169
+ /**
1170
+ * Light browse-row catalogue card. Self-scoped. Header is the offer's `logo`
1171
+ * (the token registry's where it lists the token, with its dark-theme
1172
+ * variant, the catalogue's otherwise) beside `name` (h2) and asset `symbol`
1173
+ * under it — not a wordmark.
1174
+ * Responsive hug: tighter pad / logo / type below `md`, desktop keeps the
1175
+ * H4 + 48px logo row. Hosts compose this beside {@link OfferSaleCard}; the
1176
+ * card does not pick a variant itself.
1177
+ */
1178
+ declare function OfferAssetCard({ offer, onClick, className, containerClassName, }: OfferAssetCardProps): ReactNode;
1179
+
1180
+ /**
1181
+ * An offer as {@link OfferSaleCard} renders it. Countdown copy is derived in
1182
+ * the leaf from `startsAt` / `endsAt` so it can tick; the mapper does not
1183
+ * invent a price, FDV, unlock schedule, banner overlay, or wordmark.
1184
+ *
1185
+ * `name` and `logo` come from the public token registry when the caller
1186
+ * hands over the metadata of the token the offer is about, and from the
1187
+ * offer otherwise. The list payload carries no name, so `fromOffer` leaves
1188
+ * `name` absent without registry metadata - do not derive one from `slug`.
1189
+ * The card pairs `logo` with `name` as an h2 and renders each only when
1190
+ * present. Prefer {@link OfferSaleCardUi.fromDetail} when the host has a
1191
+ * name and no registry answer.
1192
+ *
1193
+ * `tagline` and `startsAt` are null for an offer that runs no sale window, an
1194
+ * Ondo swap: the card then omits the tagline and, with nothing to count down
1195
+ * to, reads as live.
1196
+ */
1197
+ type OfferSaleCardUi = {
1198
+ id: OfferId;
1199
+ /** Absent when neither the registry nor a detail payload names the offer. */
1200
+ name?: string;
1201
+ tagline: string | null;
1202
+ /** `null` when neither the registry nor the offer carries artwork. */
1203
+ logo: OfferLogoUi | null;
1204
+ startsAt: Date | null;
1205
+ endsAt: Date | null;
1206
+ };
1207
+ declare const OfferSaleCardUi: {
1152
1208
  /**
1153
- * Opens the host's wallet connector. Resolves once the attempt finishes; the
1154
- * SDK reads the outcome from `external` on the next render rather than from
1155
- * a return value, so a host that connects through a redirect still works.
1209
+ * `tokenMetadata` is the registry's entry for the token the offer is about
1210
+ * (`TokenRegistrySnapshot.forOffer`), or `null` when it lists none. The
1211
+ * registry names win over the offer's own where both exist: they are the
1212
+ * token's canonical name and artwork, where the offer's are catalogue copy.
1213
+ */
1214
+ fromOffer: (offer: Offer, tokenMetadata?: TokenMetadata | null) => OfferSaleCardUi;
1215
+ fromDetail: (detail: OfferDetail, tokenMetadata?: TokenMetadata | null) => OfferSaleCardUi;
1216
+ };
1217
+
1218
+ interface OfferSaleCardProps {
1219
+ offer: OfferSaleCardUi;
1220
+ /** Host click handler. View offer always renders; this wires the hit target. */
1221
+ onClick?: () => void;
1222
+ /** Optional className applied to the card root element. */
1223
+ className?: string;
1224
+ /** Optional className applied to an outer wrapper element. */
1225
+ containerClassName?: string;
1226
+ }
1227
+ /**
1228
+ * Dark live-sale catalogue card. Self-scoped. Header is the offer's `logo`
1229
+ * (the token registry's where it lists the token, the catalogue's otherwise)
1230
+ * beside the `name` as an h2, then the tagline — not a wordmark. The same
1231
+ * logo is painted as a faint right-shifted watermark over the gradient.
1232
+ * Responsive hug layout; View offer always renders. No token price, FDV or unlock.
1233
+ */
1234
+ declare function OfferSaleCard({ offer, onClick, className, containerClassName, }: OfferSaleCardProps): ReactNode;
1235
+
1236
+ /**
1237
+ * A deposit request that has been broadcast and mined.
1238
+ *
1239
+ * Named without `Buy` so it does not collide with the dialog component when
1240
+ * both are re-exported from the client barrel.
1241
+ *
1242
+ * Success means the request was placed. The fund fulfils it later, at a price
1243
+ * set then.
1244
+ *
1245
+ * @alpha
1246
+ */
1247
+ type CentrifugeOrderPlaced = {
1248
+ wallet: EvmWallet;
1249
+ /** What the request deposits, in the funding token's base units. */
1250
+ amount: BlockchainAmount;
1251
+ transaction: CentrifugeVaultBuyTransaction;
1252
+ txHash: Hash;
1253
+ };
1254
+
1255
+ /**
1256
+ * A token-sale order the checkout placed: the approval mined and the
1257
+ * participation is recorded.
1258
+ *
1259
+ * It is a commitment, not a purchase. The sale pulls the payment through the
1260
+ * approval and allocates tokens when it settles, so `participation.status`
1261
+ * starts out pending.
1262
+ *
1263
+ * @alpha
1264
+ */
1265
+ type TokenSaleOrderPlaced = {
1266
+ /** The wallet that approved the payment, and that receives the tokens. */
1267
+ wallet: EvmWallet;
1268
+ /** What was committed, in `inputAsset`'s base units. */
1269
+ amount: BlockchainAmount;
1270
+ inputAsset: StablecoinSymbol;
1271
+ participation: Participation;
1272
+ /** The approval the participation was recorded against. */
1273
+ approvalTxHash: Hash;
1274
+ };
1275
+
1276
+ /**
1277
+ * A filled Ondo order, as the confirmation dialog and the host's
1278
+ * `onOrderConfirmed` callback need it.
1279
+ *
1280
+ * It lives here rather than beside either review viewmodel because both
1281
+ * products produce one. Declaring it in `ondo/buy/` would make the sell
1282
+ * viewmodel import a sibling product's module - which the `shared/` ladder
1283
+ * forbids for the reason it always does: two products that reach sideways can
1284
+ * no longer be moved or deleted on their own.
1285
+ *
1286
+ * It names no asset beyond the one that was spent. The transaction does not
1287
+ * carry one, and rebuilding an `Erc20Asset` here would mean inventing a
1288
+ * `decimals` - the quote's answers for a different quantity, and the
1289
+ * transaction's is a scale rather than a property of the token. A host that
1290
+ * wants to know what was traded has the `offer` it passed in.
1291
+ */
1292
+ type OndoOrderPlaced = OndoBuyOrderPlaced | OndoSellOrderPlaced;
1293
+ /**
1294
+ * The common half of an {@link OndoOrderPlaced}, before its side's terms.
1295
+ *
1296
+ * The transaction that was broadcast is not here, because it is not common:
1297
+ * it carries the same `side` this order does, and saying so in prose left a
1298
+ * sell order holding a buy transaction constructible and its
1299
+ * `minimumReceiveOutputAmount` unreachable behind a narrowed `side`. Each arm
1300
+ * names its own instead.
1301
+ */
1302
+ type OndoOrderPlacedCore = {
1303
+ txHash: Hash;
1304
+ /** What the trader spent, in the input asset's base units. */
1305
+ amount: BlockchainAmount;
1306
+ wallet: EvmWallet;
1307
+ };
1308
+ /** A filled purchase: a stablecoin spent, the asset received. */
1309
+ type OndoBuyOrderPlaced = OndoOrderPlacedCore & OndoBuyOrderTerms;
1310
+ /** A filled sale: the asset spent, the settlement coin received. */
1311
+ type OndoSellOrderPlaced = OndoOrderPlacedCore & OndoSellOrderTerms;
1312
+ /**
1313
+ * A buy spends a stablecoin the SDK ships a registry entry for, so its input
1314
+ * asset is narrowed to one - which is what keeps `TOKEN_REGISTRY.erc20` total
1315
+ * at the call sites that name it.
1316
+ */
1317
+ type OndoBuyOrderTerms = {
1318
+ side: 'buy';
1319
+ inputAsset: StablecoinSymbol;
1320
+ /** The purchase that was broadcast, and the deposit it was struck against. */
1321
+ transaction: OndoBuyTransaction;
1322
+ };
1323
+ /**
1324
+ * A sell spends the Ondo asset, which is in no registry: its address and
1325
+ * decimals come off the quote, and only its symbol is carried here. Hence the
1326
+ * wider `AssetSymbol`, and hence a SUM rather than one widened field - a buy
1327
+ * that lost its stablecoin guarantee would be the cost of sharing one.
1328
+ */
1329
+ type OndoSellOrderTerms = {
1330
+ side: 'sell';
1331
+ inputAsset: AssetSymbol;
1332
+ /** The sale that was broadcast, and the floor under the proceeds it names. */
1333
+ transaction: OndoSellTransaction;
1334
+ };
1335
+
1336
+ /**
1337
+ * The wallets a checkout can spend from, supplied by the host: the shared
1338
+ * {@link WalletSelection} every screen reads its wallets from, plus the one
1339
+ * thing only a checkout asks for.
1340
+ *
1341
+ * A `null` `externalAdapter` hides the external-wallet row entirely, for a
1342
+ * host that only offers embedded wallets.
1343
+ *
1344
+ * Everything a wallet row displays beyond the address - the network name -
1345
+ * comes from the checkout's execution chain rather than from the wallet,
1346
+ * because that is the chain the transaction goes to whatever the wallet is
1347
+ * currently pointed at.
1348
+ */
1349
+ type CheckoutWalletSelection = WalletSelection & {
1350
+ /**
1351
+ * A wallet the host has already settled on, or `null` to let the user pick.
1352
+ *
1353
+ * That is for the host that already knows the answer - a sell page reached
1354
+ * from a position knows which wallet holds it, and a host with a single
1355
+ * embedded wallet has only one answer on a buy too - so asking again would
1356
+ * be a question with one possible answer. Every checkout honours it, in one
1357
+ * of two ways:
1156
1358
  *
1157
- * Rejecting is how a declined or failed connection is reported.
1359
+ * - **Ondo buy, Ondo sell and Centrifuge buy skip their wallet step** and
1360
+ * open on the amount, renumbering the steps that remain. The wallet does
1361
+ * not have to appear in `embedded` or `external`: the host supplies a
1362
+ * ready {@link EvmWallet}, and these flows never resolve it back to a row.
1363
+ * - **Superstate never skips its wallet step**, because that step
1364
+ * allow-lists the wallet on-chain and no preselection can stand in for it.
1365
+ * The step opens with the preselected wallet's row already selected, so
1366
+ * the user confirms it rather than finding it. That needs a row: a wallet
1367
+ * matching neither an `embedded` one nor the connected `external` one by
1368
+ * address selects nothing, and the user picks as if none was preselected.
1369
+ *
1370
+ * Read **once**, when the checkout mounts. The approval a checkout asks for
1371
+ * is granted by one specific wallet, so a change mid-flow is ignored; remount
1372
+ * the checkout (a `key`) to apply a new one. After an order the flow resets
1373
+ * to the step it opened on, so a skipped wallet step stays skipped.
1158
1374
  */
1159
- connectExternal: () => Promise<void>;
1160
- /** Disconnects the external wallet. Resolves when it is gone. */
1161
- disconnectExternal: () => Promise<void>;
1375
+ preselected: EvmWallet | null;
1162
1376
  };
1163
1377
 
1164
1378
  /** What the swap actually filled at, once it has mined. */
@@ -1194,131 +1408,61 @@ type SuperstateOrderPlaced = {
1194
1408
  * Everything `CheckoutContainer` needs that the offer cannot tell it, keyed by
1195
1409
  * the offer type it belongs to.
1196
1410
  *
1197
- * Keyed by `OfferType` rather than by provider name, and with every key
1198
- * required, because a host that renders `CheckoutContainer` is saying it will
1199
- * handle whatever offer it is given. Adding a member to `OfferTypeDto` then
1200
- * breaks every host at compile time, which is the point: a new offer type
1201
- * arriving in a catalogue is a thing they have to decide about, not a blank
1202
- * screen their users find first.
1411
+ * Keyed by `OfferType` rather than by provider name. Every entry is optional,
1412
+ * and so is the whole object: a host that says nothing about a provider gets
1413
+ * its defaults. A new provider that needs config cannot be wired up without a
1414
+ * key here, since its branch in {@link CheckoutContainer} has to index one.
1203
1415
  *
1204
- * Almost nothing here is per-offer: it is per-*integration*, so a host builds
1205
- * it once and passes the same object for every offer it renders. The one
1206
- * exception is `side`, on `ondo::swap` and `centrifuge::vault`, which is
1207
- * per-*render* rather than per offer or per integration - the same offer is
1208
- * both buyable and sellable - so a host with a buy page and a sell page builds
1209
- * one object for each. See {@link OndoCheckoutConfig}.
1416
+ * Everything here is per-*integration*: a host builds it once and passes the
1417
+ * same object for every offer it renders. Which way the order runs is
1418
+ * per-render, so it is not here - see {@link CheckoutContainerProps.side}.
1210
1419
  */
1211
1420
  type CheckoutConfig = {
1212
- [K in OfferType]: CheckoutConfigByOfferType[K];
1213
- };
1214
- /**
1215
- * What each offer type needs, before {@link CheckoutConfig} maps `OfferType`
1216
- * over it.
1217
- *
1218
- * Private, and separate from `CheckoutConfig`, because the mapping is what
1219
- * enforces the promise above: a new member of `OfferTypeDto` with no entry here
1220
- * fails to index this type, so the compile error lands in the SDK *and* the
1221
- * shape hosts must satisfy changes with it. Declaring the keys directly on
1222
- * `CheckoutConfig` would leave both sides compiling happily against a type that
1223
- * had quietly stopped covering every offer.
1224
- */
1225
- type CheckoutConfigByOfferType = {
1226
- 'ondo::swap': OndoCheckoutConfig;
1227
- 'superstate::swap': SuperstateCheckoutConfig;
1228
- 'coinlist::token_sale': CoinListTokenSaleCheckoutConfig;
1229
- 'centrifuge::vault': CentrifugeVaultCheckoutConfig;
1421
+ 'ondo::swap'?: OndoCheckoutConfig;
1422
+ 'superstate::swap'?: SuperstateCheckoutConfig;
1423
+ 'coinlist::token_sale'?: CoinListTokenSaleCheckoutConfig;
1424
+ 'centrifuge::vault'?: CentrifugeVaultCheckoutConfig;
1230
1425
  };
1231
1426
  type OndoCheckoutConfig = {
1232
- /**
1233
- * Which way the trade runs: `buy` invests in the asset, `sell` liquidates a
1234
- * holding of it.
1235
- *
1236
- * Config rather than something the offer says, because no offer can answer
1237
- * it: `offer.type` is `ondo::swap` for both directions, since frontline
1238
- * exposes one Ondo offer type and the side is a property of the page rather
1239
- * than of the catalogue.
1240
- *
1241
- * Required, with no default. The wire parameter behind it defaults to `buy`
1242
- * silently, and an unstated direction should be a compile error rather than
1243
- * a purchase.
1244
- *
1245
- * **Read once, at mount.** The Ondo flow holds a committed quote and an
1246
- * approval granted for one specific token, so a later value is ignored
1247
- * rather than obeyed. To switch sides, remount with a `key` - see
1248
- * {@link CheckoutContainer}.
1249
- */
1250
- side: OrderBookSide;
1251
1427
  /** Fired once an Ondo swap has mined, either way. The dialog shows anyway. */
1252
1428
  onOrderConfirmed?: (order: OndoOrderPlaced) => void;
1253
1429
  };
1254
1430
  /**
1255
- * Superstate needs nothing required today — the swap contract is looked up from
1431
+ * Superstate needs nothing required today - the swap contract is looked up from
1256
1432
  * the chain, and the funding assets and issuer are the provider's own
1257
- * constants. The key still has to be supplied, so that the day it does need
1258
- * something the omission is a compile error rather than a runtime surprise.
1433
+ * constants.
1259
1434
  */
1260
1435
  type SuperstateCheckoutConfig = {
1261
1436
  /** Fired once a Superstate swap has mined. The dialog shows either way. */
1262
1437
  onOrderConfirmed?: (order: SuperstateOrderPlaced) => void;
1263
1438
  };
1264
1439
  /**
1265
- * The SDK ships no token-sale UI, so the host supplies it.
1266
- *
1267
- * A render function rather than a `ReactNode`, because the container knows
1268
- * which offer it is being asked about and a host with a working token-sale page
1269
- * of its own needs that offer to render it. A host that never lists token-sale
1270
- * offers returns `null`.
1271
- *
1272
- * Alpha: becomes optional once the SDK ships its own token-sale checkout.
1440
+ * What a CoinList token-sale checkout can be configured with. Nothing is
1441
+ * required: the funding contract, the coins and the price are all read off
1442
+ * the offer. Which option is bought is per-render, so it is a prop - see
1443
+ * {@link CheckoutContainerProps.optionId}.
1273
1444
  *
1274
1445
  * @alpha
1275
1446
  */
1276
1447
  type CoinListTokenSaleCheckoutConfig = {
1277
- render: (offer: CoinListTokenSaleOfferDetail) => ReactNode;
1448
+ /**
1449
+ * Fired once the participation is recorded. The dialog shows either way.
1450
+ * The order is a commitment: the sale collects the payment and allocates
1451
+ * the tokens when it settles.
1452
+ */
1453
+ onOrderPlaced?: (order: TokenSaleOrderPlaced) => void;
1278
1454
  };
1279
1455
  /**
1280
- * What a Centrifuge vault checkout needs that the offer cannot tell it.
1456
+ * What a Centrifuge vault checkout can be configured with.
1281
1457
  *
1282
1458
  * Alpha: the sell side is not built yet, and its arrival may add to this.
1283
1459
  *
1284
1460
  * @alpha
1285
1461
  */
1286
1462
  type CentrifugeVaultCheckoutConfig = {
1287
- /**
1288
- * Which way the order runs: `buy` deposits into the vault, `sell` redeems
1289
- * shares. Read once, at mount, as Ondo's is - see
1290
- * {@link OndoCheckoutConfig.side}.
1291
- *
1292
- * `sell` renders nothing yet.
1293
- */
1294
- side: OrderBookSide;
1295
1463
  /** Fired once a deposit request has mined. The dialog shows either way. */
1296
1464
  onOrderPlaced?: (order: CentrifugeOrderPlaced) => void;
1297
1465
  };
1298
- /**
1299
- * The parts of {@link CheckoutConfig} only the host can know.
1300
- *
1301
- * What is missing from this list is what {@link defaultCheckoutConfig} can fill
1302
- * in on its own.
1303
- */
1304
- type RequiredCheckoutConfig = Pick<CheckoutConfig, 'ondo::swap' | 'coinlist::token_sale' | 'centrifuge::vault'>;
1305
- /**
1306
- * Fills in the config entries that have a sensible default, so a host only
1307
- * writes the ones that do not.
1308
- *
1309
- * It exists mostly for the future: today it defaults one empty object, but a
1310
- * provider that gains an *optional* setting can be defaulted here instead of
1311
- * appearing in every host's config object.
1312
- *
1313
- * ```ts
1314
- * const config = defaultCheckoutConfig({
1315
- * 'ondo::swap': { side: 'buy' },
1316
- * 'coinlist::token_sale': { render: (offer) => <MyTokenSalePage offer={offer} /> },
1317
- * 'centrifuge::vault': { side: 'buy' },
1318
- * });
1319
- * ```
1320
- */
1321
- declare function defaultCheckoutConfig(config: RequiredCheckoutConfig & Partial<CheckoutConfig>): CheckoutConfig;
1322
1466
  interface CheckoutContainerProps {
1323
1467
  /**
1324
1468
  * The offer being bought. Its `type` decides which provider renders.
@@ -1335,13 +1479,67 @@ interface CheckoutContainerProps {
1335
1479
  */
1336
1480
  chain: EthereumChain;
1337
1481
  /**
1338
- * The wallets the buyer can spend from, and the lambdas that connect and
1339
- * disconnect an external one. The SDK ships no wallet stack, so this is how
1340
- * a host plugs in Privy, AppKit, or its own.
1482
+ * Which way the order runs: `buy` invests in the asset, `sell` liquidates a
1483
+ * holding of it. Default `'buy'`.
1484
+ *
1485
+ * A prop rather than something the offer says, because no offer can answer
1486
+ * it: `offer.type` is `ondo::swap` for both directions, and the side is a
1487
+ * property of the page rather than of the catalogue. A prop rather than a
1488
+ * config entry, because it is per-render while the config is
1489
+ * per-integration, so one config object serves a buy page and a sell page.
1490
+ *
1491
+ * Honoured by the providers that have a direction: Ondo mounts its buy or
1492
+ * sell checkout, and Centrifuge its deposit flow or (until redeem ships) an
1493
+ * empty container. Superstate and the token sale have one direction and
1494
+ * ignore it.
1495
+ *
1496
+ * **Read once, at mount**, as `offer` and `chain` are. To switch sides,
1497
+ * remount with a `key` - see {@link CheckoutContainer}.
1498
+ */
1499
+ side?: OrderBookSide;
1500
+ /**
1501
+ * Which of a token sale's options is bought - each sets its own price,
1502
+ * minimum and sale agreement. Default: the offer's first option. Every
1503
+ * other provider buys its offer's only option and ignores it.
1504
+ *
1505
+ * A prop rather than a config entry for the same reason as `side`: it is
1506
+ * per-render, chosen on the host's offer page.
1507
+ *
1508
+ * **Read once, at mount**, as `side` is. To switch options, remount with a
1509
+ * `key` covering it.
1510
+ */
1511
+ optionId?: OfferOptionId;
1512
+ /**
1513
+ * The wallets the buyer can spend from, and the host's connector for an
1514
+ * external one. The SDK ships no wallet stack, so this is how a host plugs
1515
+ * in Privy, AppKit, or its own.
1516
+ *
1517
+ * ```tsx
1518
+ * const wallets: CheckoutWalletSelection = {
1519
+ * embedded: myEmbeddedWallets,
1520
+ * external: myConnectedWallet, // or null
1521
+ * // `null` hides the external-wallet row, for a host with embedded
1522
+ * // wallets only.
1523
+ * externalAdapter: {
1524
+ * connect: () => myConnector.open(),
1525
+ * disconnect: () => myConnector.disconnect(),
1526
+ * },
1527
+ * preselected: null, // or the wallet the host already settled on
1528
+ * };
1529
+ * ```
1530
+ *
1531
+ * Every provider honours `wallets.preselected`. Ondo (buy and sell),
1532
+ * Centrifuge and the token sale skip their wallet step and open on the amount, renumbering the
1533
+ * cards that remain. Superstate never skips it, because that step
1534
+ * allow-lists the wallet on-chain: it opens the step with the preselected
1535
+ * wallet's row already selected instead. Read once, at mount - see below.
1341
1536
  */
1342
1537
  wallets: CheckoutWalletSelection;
1343
- /** What each offer type needs beyond the offer itself. */
1344
- config: CheckoutConfig;
1538
+ /**
1539
+ * What each offer type needs beyond the offer itself. Default `{}`: every
1540
+ * provider runs on its defaults.
1541
+ */
1542
+ config?: CheckoutConfig;
1345
1543
  /**
1346
1544
  * Default `true`. `false` turns off every request and timer in the mounted
1347
1545
  * provider, for a checkout that is on the tree but not on screen yet.
@@ -1362,28 +1560,36 @@ interface CheckoutContainerProps {
1362
1560
  * assigns to `const exhaustive: never`, so a new offer type is a compile error
1363
1561
  * here as well as in {@link CheckoutConfig}.
1364
1562
  *
1365
- * ## One mount, one offer, one chain, one side
1366
- *
1367
- * `offer`, `chain` and the `side` are read as fixed for the lifetime of
1368
- * the mount. Each provider's viewmodel owns a step machine — which wallet was
1369
- * authorized, how much is being spent — and that progress is bound to the order
1370
- * it was made against: a Superstate wallet authorization is allow-listed per
1371
- * offer, and an ERC-20 approval is granted per chain, for one specific token.
1372
- * Changing any of the three in place would carry a completed step onto an order
1373
- * it was never made for — a flipped side most sharply of all, since the
1374
- * approval covers the coin the *old* direction spent. So the container does not
1375
- * try to: `side` is read once into state and later values are ignored. A
1376
- * swap could also land mid-execution, between an approval and the broadcast it
1563
+ * ## One mount, one offer, one chain, one side, one preselected wallet
1564
+ *
1565
+ * `offer`, `chain`, the `side`, the `optionId` and `wallets.preselected` are read as fixed for
1566
+ * the lifetime of the mount. Each provider's viewmodel owns a step machine -
1567
+ * which wallet was authorized, how much is being spent - and that progress is
1568
+ * bound to the order it was made against: a Superstate wallet authorization
1569
+ * is allow-listed per offer, and an ERC-20 approval is granted per chain, for
1570
+ * one specific token. Changing any of them in place would carry a completed
1571
+ * step onto an order it was never made for - a flipped side most sharply of
1572
+ * all, since the approval covers the coin the *old* direction spent. So the
1573
+ * container does not try to: `side` is read once into state and later values
1574
+ * are ignored. A swap could also land mid-execution, between an approval and the broadcast it
1377
1575
  * was granted for, which is worse than not switching at all.
1378
1576
  *
1379
- * **To render a different offer, chain or side, remount rather than
1380
- * reassign** — give the container a `key` that changes with them:
1577
+ * The preselected wallet is the same kind of progress: whether the flow has a
1578
+ * wallet step at all is decided from it at mount, and the approval that
1579
+ * follows is granted by that wallet. The rest of `wallets` stays live - a
1580
+ * newly connected external wallet appears as a row without a remount.
1581
+ *
1582
+ * **To render a different offer, chain, side, option or preselected wallet, remount
1583
+ * rather than reassign** - give the container a `key` that changes with them
1584
+ * (add `wallets.preselected?.address` to it if the host's preselection can
1585
+ * change on one page):
1381
1586
  *
1382
1587
  * ```tsx
1383
1588
  * <CheckoutContainer
1384
1589
  * key={`${offer.id}:${chain}:${side}`}
1385
1590
  * offer={offer}
1386
1591
  * chain={chain}
1592
+ * side={side}
1387
1593
  * wallets={wallets}
1388
1594
  * config={config}
1389
1595
  * />
@@ -1395,22 +1601,23 @@ interface CheckoutContainerProps {
1395
1601
  *
1396
1602
  * ### A page per side
1397
1603
  *
1398
- * The simplest way to ship both Ondo directions, and the one that needs no
1399
- * `key` at all: each page hard-codes its own direction, and a mount only ever
1400
- * sees one of them.
1604
+ * The simplest way to ship both directions, and the one that needs no `key`
1605
+ * at all: each page hard-codes its own direction, and a mount only ever sees
1606
+ * one of them. Both pages share one config.
1401
1607
  *
1402
1608
  * ```tsx
1403
- * // The sell page. `side: 'buy'` on the buy page, everything else equal.
1404
- * const config = defaultCheckoutConfig({
1405
- * 'ondo::swap': { side: 'sell' },
1406
- * 'coinlist::token_sale': { render: (o) => <MyTokenSalePage offer={o} /> },
1407
- * 'centrifuge::vault': { side: 'sell' },
1408
- * });
1609
+ * const config: CheckoutConfig = {
1610
+ * 'ondo::swap': { onOrderConfirmed: (order) => track(order) },
1611
+ * };
1612
+ *
1613
+ * // The sell page. The buy page leaves `side` out.
1614
+ * <CheckoutContainer offer={offer} chain={chain} side="sell" wallets={wallets} config={config} />
1409
1615
  * ```
1410
1616
  *
1411
1617
  * A sell page reached from a position also knows which wallet holds it, so it
1412
1618
  * usually sets {@link CheckoutWalletSelection.preselected} and opens on the
1413
- * amount.
1619
+ * amount. A buy page can do the same whenever the host has one answer - a
1620
+ * single embedded wallet, say.
1414
1621
  *
1415
1622
  * ### A buy/sell toggle on one page
1416
1623
  *
@@ -1427,17 +1634,12 @@ interface CheckoutContainerProps {
1427
1634
  * key={`${offer.id}:${chain}:${side}`} // `side` in the key, or the toggle is inert
1428
1635
  * offer={offer}
1429
1636
  * chain={chain}
1637
+ * side={side}
1430
1638
  * wallets={wallets}
1431
- * config={{
1432
- * ...config,
1433
- * 'ondo::swap': { ...config['ondo::swap'], side },
1434
- * }}
1639
+ * config={config}
1435
1640
  * />
1436
1641
  * ```
1437
1642
  *
1438
- * Rebuilding the config object on every render costs nothing here: `side` is
1439
- * read once per mount, so the object's identity never matters.
1440
- *
1441
1643
  * Two things a host owns rather than the SDK:
1442
1644
  *
1443
1645
  * - **The remount clears the flow** — chosen wallet, entered amount, granted
@@ -1449,7 +1651,7 @@ interface CheckoutContainerProps {
1449
1651
  * toggle where it can reach an executing flow — disable the tabs once the
1450
1652
  * user is past the amount step, or confirm before switching.
1451
1653
  */
1452
- declare function CheckoutContainer({ offer, chain, wallets, config, enabled, className, }: CheckoutContainerProps): ReactNode;
1654
+ declare function CheckoutContainer({ offer, chain, side, optionId, wallets, config, enabled, className, }: CheckoutContainerProps): ReactNode;
1453
1655
 
1454
1656
  /**
1455
1657
  * The claim card.
@@ -1490,11 +1692,13 @@ type CentrifugeVaultClaimUiEvent = {
1490
1692
  type: 'ON_CHANGE_WALLET';
1491
1693
  };
1492
1694
  /**
1493
- * Why a claimable row cannot be claimed right now.
1695
+ * Why a claimable row cannot be claimed right now. Vault-wide only: a frozen
1696
+ * wallet is not known before its claim, which then fails with
1697
+ * `wallet-frozen`.
1494
1698
  *
1495
1699
  * @alpha
1496
1700
  */
1497
- type CentrifugeClaimBlockedReasonUi = 'vault-paused' | 'wallet-frozen';
1701
+ type CentrifugeClaimBlockedReasonUi = 'vault-paused';
1498
1702
  /**
1499
1703
  * What a claimable row's Claim button does. `claiming` while a claim on the
1500
1704
  * row has not settled, including one whose dialog was closed: the
@@ -1528,7 +1732,7 @@ type CentrifugeClaimRowUi = {
1528
1732
  iconUrl: AssetIconUrl | null;
1529
1733
  /** The offer's name, e.g. `JTRSY deRWA`. */
1530
1734
  title: string;
1531
- /** What is queued: funding for `invest`, shares for `redeem`. */
1735
+ /** What is queued: funding for `deposit`, shares for `redeem`. */
1532
1736
  amount: FormattedAmountAssetUi;
1533
1737
  wallet: string;
1534
1738
  } | {
@@ -1537,8 +1741,8 @@ type CentrifugeClaimRowUi = {
1537
1741
  legId: CentrifugeVaultLegId;
1538
1742
  iconUrl: AssetIconUrl | null;
1539
1743
  /**
1540
- * What a claim pays out: exact shares for `invest`, an estimate of the
1541
- * funding token (prefixed `~`) for `redeem`.
1744
+ * What a claim takes, exactly: the funding token for `deposit`, shares
1745
+ * for `redeem`.
1542
1746
  */
1543
1747
  amount: FormattedAmountAssetUi;
1544
1748
  wallet: string;
@@ -1627,7 +1831,7 @@ interface UseCentrifugeVaultClaimViewModelResult {
1627
1831
  }
1628
1832
  /**
1629
1833
  * What a host hears once a claim has mined. `claimed` is what the calldata
1630
- * was built to collect: shares for `invest`, the funding token for `redeem`.
1834
+ * was built to collect: shares for `deposit`, the funding token for `redeem`.
1631
1835
  *
1632
1836
  * @alpha
1633
1837
  */
@@ -1658,34 +1862,21 @@ type CentrifugeVaultClaimed = {
1658
1862
  declare function useCentrifugeVaultClaimViewModel({ offer, wallets, walletLabel, onClaimed, pollInterval, enabled, }: UseCentrifugeVaultClaimViewModelOptions): UseCentrifugeVaultClaimViewModelResult;
1659
1863
 
1660
1864
  /**
1661
- * Everything `ClaimContainer` needs that the offer cannot tell it, keyed by
1662
- * the async offer type it belongs to.
1865
+ * What `ClaimContainer` can be configured with that the offer cannot tell it,
1866
+ * keyed by the async offer type it belongs to.
1663
1867
  *
1664
- * Keyed by {@link AsyncOfferType} with every key required, for the same reason
1665
- * as `CheckoutConfig`: a host rendering `ClaimContainer` is saying it will
1666
- * handle whatever async offer it is given, so a new async provider is a
1667
- * compile error in every host rather than a card that silently renders
1868
+ * An entry is optional exactly when every field in it is, as in
1869
+ * `CheckoutConfig`: a provider with nothing the host must decide asks for
1668
1870
  * nothing. Per-integration, not per-offer: a host builds it once.
1669
1871
  *
1670
1872
  * @alpha
1671
1873
  */
1672
1874
  type ClaimConfig = {
1673
- [K in AsyncOfferType]: ClaimConfigByOfferType[K];
1674
- };
1675
- /**
1676
- * What each async offer type needs, before {@link ClaimConfig} maps
1677
- * `AsyncOfferType` over it. Private, so a new member of `AsyncOfferDetail`
1678
- * with no entry here fails to index this type in the SDK first.
1679
- *
1680
- * @alpha
1681
- */
1682
- type ClaimConfigByOfferType = {
1683
- 'centrifuge::vault': CentrifugeVaultClaimConfig;
1875
+ 'centrifuge::vault'?: CentrifugeVaultClaimConfig;
1684
1876
  };
1685
1877
  /**
1686
1878
  * Centrifuge needs nothing required today: the vaults come from the offer and
1687
- * the token registry. The key still has to be supplied, so that the day it
1688
- * does need something the omission is a compile error.
1879
+ * the token registry.
1689
1880
  *
1690
1881
  * @alpha
1691
1882
  */
@@ -1707,253 +1898,52 @@ interface ClaimContainerProps {
1707
1898
  */
1708
1899
  wallets: WalletSelection;
1709
1900
  /**
1710
- * Names a wallet for display, e.g. `'CoinList Wallet'` for the embedded
1711
- * one. Omitted, or returning `null`, shows the shortened address.
1712
- */
1713
- walletLabel?: WalletLabelResolver;
1714
- /** What each async offer type needs beyond the offer itself. */
1715
- config: ClaimConfig;
1716
- /**
1717
- * Default `true`. `false` turns off every request and timer in the mounted
1718
- * provider, for a card that is on the tree but not on screen yet.
1719
- */
1720
- enabled?: boolean;
1721
- className?: string;
1722
- }
1723
- /**
1724
- * The plug-and-play claim card: hand it an async offer and it renders the
1725
- * right provider's positions - what is pending, what is claimable - and the
1726
- * claim that collects them.
1727
- *
1728
- * The second leg of an async trade. The user placed a request earlier, the
1729
- * fund fills it on its own schedule, and they come back - days or weeks later
1730
- * - to claim. So the card is its own entry on the offer page rather than a
1731
- * checkout step.
1732
- *
1733
- * Only the matching provider's container is mounted, so its viewmodel is the
1734
- * only one that runs. The `switch` is exhaustive against
1735
- * {@link AsyncOfferType}, and the `default` branch assigns to
1736
- * `const exhaustive: never`, so a new async offer type is a compile error here
1737
- * as well as in {@link ClaimConfig}.
1738
- *
1739
- * ```tsx
1740
- * {AsyncOfferDetail.is(offer) && (
1741
- * <ClaimContainer
1742
- * key={offer.id}
1743
- * offer={offer}
1744
- * wallets={{ embedded, external, externalAdapter }}
1745
- * walletLabel={(address) => (isEmbedded(address) ? 'CoinList Wallet' : null)}
1746
- * config={{ 'centrifuge::vault': {} }}
1747
- * />
1748
- * )}
1749
- * ```
1750
- *
1751
- * @alpha
1752
- */
1753
- declare function ClaimContainer({ offer, wallets, walletLabel, config, enabled, className, }: ClaimContainerProps): ReactNode;
1754
-
1755
- /**
1756
- * What the grid fetches, pre-fetched on the server instead. Each half is
1757
- * independent: seed `offers` (via `CoinListServer#offers.list()`) and the
1758
- * client still fetches the registry, seed `tokens` (via
1759
- * `CoinListServer#tokens.list()`) and it still fetches the offers, seed both
1760
- * and the grid makes no request of its own.
1761
- */
1762
- interface OffersGridData {
1763
- offers?: Offer[];
1764
- tokens?: TokenMetadata[];
1765
- }
1766
-
1767
- interface OffersGridContainerProps {
1768
- /** Maximum number of columns to render when horizontal space allows. */
1769
- maxColumns?: number;
1770
- /** Optional className applied to the grid element. */
1771
- className?: string;
1772
- /** Optional className applied to the outer wrapper element. */
1773
- containerClassName?: string;
1774
- /** Optional loading slot shown while offers are being fetched. */
1775
- loading?: ReactNode;
1776
- /** Optional error slot shown when loading offers fails. */
1777
- error?: ReactNode;
1778
- /** Optional empty state slot shown when there are no available offers. */
1779
- emptyState?: ReactNode;
1780
- /** Optional per-offer click handler; when omitted, cards are not clickable. */
1781
- onOfferClick?: (offer: Offer) => void;
1782
- /**
1783
- * What the grid would otherwise fetch, pre-fetched on the server: `offers`
1784
- * via `CoinListServer#offers.list()`, `tokens` via
1785
- * `CoinListServer#tokens.list()`. Each half skips its own client-side
1786
- * fetch; pass both for a grid that makes no request of its own.
1787
- */
1788
- data?: OffersGridData;
1789
- /**
1790
- * Default `true`. When `false` nothing is fetched, so the container can be
1791
- * mounted while the grid is not needed yet.
1792
- */
1793
- enabled?: boolean;
1794
- }
1795
- /**
1796
- * Displays a responsive live-sale grid of {@link OfferSaleCard}, backed by
1797
- * {@link useOffersGridViewModel}. Each card is named and illustrated by the
1798
- * public token registry where it lists the offer's token, and by the offer's
1799
- * own fields otherwise - list offers carry no display name, so an unlisted
1800
- * one shows logo + tagline until the host maps from detail. For equities /
1801
- * past-sales browse rows, compose {@link OffersAssetGrid} instead.
1802
- *
1803
- * Pass `data` (offers and tokens pre-fetched server-side) to use them as-is
1804
- * and skip the client-side fetches. Pass `enabled={false}` to skip the fetches
1805
- * when the container is mounted but the grid is not needed yet. Uses the
1806
- * `loading` / `error` / `emptyState` slots when provided; otherwise renders
1807
- * the standard fallbacks. Cards are interactive only when `onOfferClick` is
1808
- * provided.
1809
- *
1810
- * Self-scoped: renders fully styled on its own, with no `CoinListStyleScope`
1811
- * needed.
1812
- */
1813
- declare function OffersGridContainer({ data, onOfferClick, enabled, ...viewProps }?: OffersGridContainerProps): ReactNode;
1814
-
1815
- /**
1816
- * One image as an `<img>` renders it: a `src` for a consumer that takes a
1817
- * single URL, and the `srcSet` candidates for one that also knows the size
1818
- * it renders at. `srcSet` is absent for a vector logo and for the offer's own
1819
- * artwork, neither of which offers the browser a choice.
1820
- */
1821
- type LogoImageUi = {
1822
- src: string;
1823
- srcSet?: string;
1824
- };
1825
- /**
1826
- * The logo a catalogue card renders for an offer, with the registry's
1827
- * dark-theme counterpart when it configures one.
1828
- *
1829
- * `dark` is `null` rather than absent so a renderer has to decide what to do
1830
- * without one: fall back to `light`, which is the registry's own rule.
1831
- */
1832
- type OfferLogoUi = {
1833
- light: LogoImageUi;
1834
- dark: LogoImageUi | null;
1835
- };
1836
- declare const OfferLogoUi: {
1837
- /**
1838
- * The registry's logo for the token an offer is about, or the offer's own
1839
- * artwork otherwise, or `null` when neither exists.
1840
- *
1841
- * The registry wins when both exist because it is the token's real artwork
1842
- * where `Offer.logoUrl` is catalogue artwork, and because a swap publishes
1843
- * without artwork more often than not - which is why `logoUrl` is `null`
1844
- * on the swap variants.
1845
- */
1846
- fromOffer: (offer: {
1847
- logoUrl: string | null;
1848
- }, tokenMetadata: TokenMetadata | null) => OfferLogoUi | null;
1849
- };
1850
-
1851
- /**
1852
- * An offer as {@link OfferAssetCard} renders it. Browse chrome: circular
1853
- * `logo`, `name`, and asset `symbol`. No wordmark.
1854
- *
1855
- * All three come from the public token registry when the caller hands over
1856
- * the metadata of the token the offer is about. Without it, `fromOffer`
1857
- * omits `name` and `symbol` - the list payload has neither - so a list-mapped
1858
- * card is honest about being logo-only, and `fromDetail` reads them from the
1859
- * detail payload (`name`, `asset.code`).
1860
- */
1861
- type OfferAssetCardUi = {
1862
- id: OfferId;
1863
- /** Absent when neither the registry nor a detail payload names the offer. */
1864
- name?: string;
1865
- /** Absent when neither the registry nor a detail payload carries a ticker. */
1866
- symbol?: string;
1867
- /** `null` when neither the registry nor the offer carries artwork. */
1868
- logo: OfferLogoUi | null;
1869
- };
1870
- declare const OfferAssetCardUi: {
1871
- /**
1872
- * `tokenMetadata` is the registry's entry for the token the offer is about
1873
- * (`TokenRegistrySnapshot.forOffer`), or `null` when it lists none. The
1874
- * registry names win over the offer's own where both exist: they are the
1875
- * token's canonical name, ticker and artwork, where the offer's are
1876
- * catalogue copy.
1877
- */
1878
- fromOffer: (offer: Offer, tokenMetadata?: TokenMetadata | null) => OfferAssetCardUi;
1879
- fromDetail: (detail: OfferDetail, tokenMetadata?: TokenMetadata | null) => OfferAssetCardUi;
1880
- };
1881
-
1882
- interface OfferAssetCardProps {
1883
- offer: OfferAssetCardUi;
1884
- /** When set, the whole card is the hit target. */
1885
- onClick?: () => void;
1886
- /** Optional className applied to the card root element. */
1887
- className?: string;
1888
- /** Optional className applied to an outer wrapper element. */
1889
- containerClassName?: string;
1890
- }
1891
- /**
1892
- * Light browse-row catalogue card. Self-scoped. Header is the offer's `logo`
1893
- * (the token registry's where it lists the token, with its dark-theme
1894
- * variant, the catalogue's otherwise) beside `name` (h2) and asset `symbol`
1895
- * under it — not a wordmark.
1896
- * Responsive hug: tighter pad / logo / type below `md`, desktop keeps the
1897
- * H4 + 48px logo row. Hosts compose this beside {@link OfferSaleCard}; the
1898
- * card does not pick a variant itself.
1899
- */
1900
- declare function OfferAssetCard({ offer, onClick, className, containerClassName, }: OfferAssetCardProps): ReactNode;
1901
-
1902
- /**
1903
- * An offer as {@link OfferSaleCard} renders it. Countdown copy is derived in
1904
- * the leaf from `startsAt` / `endsAt` so it can tick; the mapper does not
1905
- * invent a price, FDV, unlock schedule, banner overlay, or wordmark.
1906
- *
1907
- * `name` and `logo` come from the public token registry when the caller
1908
- * hands over the metadata of the token the offer is about, and from the
1909
- * offer otherwise. The list payload carries no name, so `fromOffer` leaves
1910
- * `name` absent without registry metadata - do not derive one from `slug`.
1911
- * The card pairs `logo` with `name` as an h2 and renders each only when
1912
- * present. Prefer {@link OfferSaleCardUi.fromDetail} when the host has a
1913
- * name and no registry answer.
1914
- *
1915
- * `tagline` and `startsAt` are null for an offer that runs no sale window, an
1916
- * Ondo swap: the card then omits the tagline and, with nothing to count down
1917
- * to, reads as live.
1918
- */
1919
- type OfferSaleCardUi = {
1920
- id: OfferId;
1921
- /** Absent when neither the registry nor a detail payload names the offer. */
1922
- name?: string;
1923
- tagline: string | null;
1924
- /** `null` when neither the registry nor the offer carries artwork. */
1925
- logo: OfferLogoUi | null;
1926
- startsAt: Date | null;
1927
- endsAt: Date | null;
1928
- };
1929
- declare const OfferSaleCardUi: {
1930
- /**
1931
- * `tokenMetadata` is the registry's entry for the token the offer is about
1932
- * (`TokenRegistrySnapshot.forOffer`), or `null` when it lists none. The
1933
- * registry names win over the offer's own where both exist: they are the
1934
- * token's canonical name and artwork, where the offer's are catalogue copy.
1901
+ * Names a wallet for display, e.g. `'CoinList Wallet'` for the embedded
1902
+ * one. Omitted, or returning `null`, shows the shortened address.
1935
1903
  */
1936
- fromOffer: (offer: Offer, tokenMetadata?: TokenMetadata | null) => OfferSaleCardUi;
1937
- fromDetail: (detail: OfferDetail, tokenMetadata?: TokenMetadata | null) => OfferSaleCardUi;
1938
- };
1939
-
1940
- interface OfferSaleCardProps {
1941
- offer: OfferSaleCardUi;
1942
- /** Host click handler. View offer always renders; this wires the hit target. */
1943
- onClick?: () => void;
1944
- /** Optional className applied to the card root element. */
1904
+ walletLabel?: WalletLabelResolver;
1905
+ /**
1906
+ * What each async offer type can be configured with beyond the offer
1907
+ * itself. Optional, since no entry has a required field today.
1908
+ */
1909
+ config?: ClaimConfig;
1910
+ /**
1911
+ * Default `true`. `false` turns off every request and timer in the mounted
1912
+ * provider, for a card that is on the tree but not on screen yet.
1913
+ */
1914
+ enabled?: boolean;
1945
1915
  className?: string;
1946
- /** Optional className applied to an outer wrapper element. */
1947
- containerClassName?: string;
1948
1916
  }
1949
1917
  /**
1950
- * Dark live-sale catalogue card. Self-scoped. Header is the offer's `logo`
1951
- * (the token registry's where it lists the token, the catalogue's otherwise)
1952
- * beside the `name` as an h2, then the tagline — not a wordmark. The same
1953
- * logo is painted as a faint right-shifted watermark over the gradient.
1954
- * Responsive hug layout; View offer always renders. No token price, FDV or unlock.
1918
+ * The plug-and-play claim card: hand it an async offer and it renders the
1919
+ * right provider's positions - what is pending, what is claimable - and the
1920
+ * claim that collects them.
1921
+ *
1922
+ * The second leg of an async trade. The user placed a request earlier, the
1923
+ * fund fills it on its own schedule, and they come back - days or weeks later
1924
+ * - to claim. So the card is its own entry on the offer page rather than a
1925
+ * checkout step.
1926
+ *
1927
+ * Only the matching provider's container is mounted, so its viewmodel is the
1928
+ * only one that runs. The `switch` is exhaustive against
1929
+ * {@link AsyncOfferType}, and the `default` branch assigns to
1930
+ * `const exhaustive: never`, so a new async offer type is a compile error
1931
+ * here.
1932
+ *
1933
+ * ```tsx
1934
+ * {AsyncOfferDetail.is(offer) && (
1935
+ * <ClaimContainer
1936
+ * key={offer.id}
1937
+ * offer={offer}
1938
+ * wallets={{ embedded, external, externalAdapter }}
1939
+ * walletLabel={(address) => (isEmbedded(address) ? 'CoinList Wallet' : null)}
1940
+ * />
1941
+ * )}
1942
+ * ```
1943
+ *
1944
+ * @alpha
1955
1945
  */
1956
- declare function OfferSaleCard({ offer, onClick, className, containerClassName, }: OfferSaleCardProps): ReactNode;
1946
+ declare function ClaimContainer({ offer, wallets, walletLabel, config, enabled, className, }: ClaimContainerProps): ReactNode;
1957
1947
 
1958
1948
  type LoadRequirementsReason = 'not-authenticated' | 'generic-error';
1959
1949
  type LoadRequirementsState = {
@@ -2381,21 +2371,241 @@ interface UseCompleteOAuthOptions {
2381
2371
  * {@link UseCompleteOAuthOptions.postOAuthComplete}, {@link UseCompleteOAuthOptions.onFailure},
2382
2372
  * and {@link UseCompleteOAuthOptions.onSuccess} to perform redirects or routing in your app.
2383
2373
  *
2384
- * Must be used within {@link CoinListProvider}.
2374
+ * Must be used within {@link CoinListProvider}.
2375
+ */
2376
+ declare function useCompleteOAuth(options: UseCompleteOAuthOptions): void;
2377
+
2378
+ type LoadOfferDetailsReason = 'not-authenticated' | 'generic-error';
2379
+ type LoadOfferDetailsState = {
2380
+ type: 'LOADING';
2381
+ } | {
2382
+ type: 'ERROR';
2383
+ reason: LoadOfferDetailsReason;
2384
+ } | {
2385
+ type: 'CONTENT';
2386
+ offerDetail: OfferDetail;
2387
+ };
2388
+ interface UseOfferDetailsOptions {
2389
+ /**
2390
+ * Offer detail pre-fetched on the server (e.g. via `CoinListServer#offers.get()`).
2391
+ * When provided, the hook uses this data as-is and skips the client-side fetch entirely.
2392
+ */
2393
+ data?: OfferDetail;
2394
+ /**
2395
+ * When `false`, the hook sends no request. A seeded or already-fetched
2396
+ * `CONTENT` survives; otherwise the hook stays `LOADING`. Defaults to `true`.
2397
+ */
2398
+ enabled?: boolean;
2399
+ }
2400
+ interface UseOfferDetailsResult {
2401
+ offerDetailsState: LoadOfferDetailsState;
2402
+ }
2403
+ /**
2404
+ * Loads CoinList offer details for a given offer id and exposes a UI-friendly state.
2405
+ *
2406
+ * Pass `data` (pre-fetched server-side) to use that data as-is and skip
2407
+ * the client-side fetch entirely. Pass `enabled: false` to skip the fetch
2408
+ * when the hook must be called but the data is not needed yet.
2409
+ *
2410
+ * Returns `LOADING` while CoinList is initializing or while details are being fetched.
2411
+ * Returns `CONTENT` with the offer when `offers.get()` succeeds.
2412
+ * Returns `ERROR` with:
2413
+ * - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}
2414
+ * - `generic-error` for any other failure
2415
+ */
2416
+ declare function useOfferDetails(offerId: OfferId, options?: UseOfferDetailsOptions): UseOfferDetailsResult;
2417
+
2418
+ type LoadOffersReason = 'not-authenticated' | 'generic-error';
2419
+ type LoadOffersState = {
2420
+ type: 'LOADING';
2421
+ } | {
2422
+ type: 'ERROR';
2423
+ reason: LoadOffersReason;
2424
+ } | {
2425
+ type: 'CONTENT';
2426
+ offers: Offer[];
2427
+ };
2428
+ interface UseOffersOptions {
2429
+ /**
2430
+ * Offers pre-fetched on the server (e.g. via `CoinListServer#offers.list()`).
2431
+ * When provided, the hook uses this data as-is and skips the client-side fetch entirely.
2432
+ */
2433
+ data?: Offer[];
2434
+ /**
2435
+ * When `false`, the hook sends no request. A seeded or already-fetched
2436
+ * `CONTENT` survives; otherwise the hook stays `LOADING`. Defaults to `true`.
2437
+ */
2438
+ enabled?: boolean;
2439
+ }
2440
+ interface UseOffersResult {
2441
+ offersState: LoadOffersState;
2442
+ }
2443
+ /**
2444
+ * Loads all CoinList offers for the current user and exposes a UI-friendly state.
2445
+ *
2446
+ * Pass `data` (pre-fetched server-side) to use that data as-is and skip
2447
+ * the client-side fetch entirely. Pass `enabled: false` to skip the fetch
2448
+ * when the hook must be called but the data is not needed yet.
2449
+ *
2450
+ * Returns `LOADING` while CoinList is initializing or while offers are being fetched.
2451
+ * Returns `CONTENT` with all offers when `fetchOffers()` succeeds.
2452
+ * Returns `ERROR` with:
2453
+ * - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}
2454
+ * - `generic-error` for any other failure
2455
+ */
2456
+ declare function useOffers(options?: UseOffersOptions): UseOffersResult;
2457
+
2458
+ /**
2459
+ * Why a read failed, in the only two flavours every UI acts on differently.
2460
+ *
2461
+ * `not-authenticated` is split out because no retry helps until the user
2462
+ * signs in, and because the remedy is one the UI can name. Everything else
2463
+ * collapses into `generic-error` and is offered a retry. A provider that has a
2464
+ * third remedy of its own - Ondo's closed market - widens this union rather
2465
+ * than restating it.
2466
+ */
2467
+ type LoadErrorReason = 'not-authenticated' | 'generic-error';
2468
+
2469
+ /**
2470
+ * Why a Centrifuge read failed. Centrifuge has no remedy of its own to add,
2471
+ * so this is {@link LoadErrorReason} under the name its states already
2472
+ * publish, classified by `loadErrorReason`.
2473
+ *
2474
+ * @alpha
2475
+ */
2476
+ type CentrifugeLoadErrorReason = LoadErrorReason;
2477
+
2478
+ /**
2479
+ * The state of one vault's status poll.
2480
+ *
2481
+ * Stale-preserving: a failed tick with a status in hand keeps it, so a flaky
2482
+ * read never reads as "vault halted". `ERROR` means the status is unknown -
2483
+ * which is not the same as `CONTENT` carrying a blocked orderability, and
2484
+ * callers must not conflate them. A vault that is *known* to be unorderable
2485
+ * may block a request; one that is merely unknown may not.
2486
+ *
2487
+ * `below_minimum` never appears here: it needs an amount, which this
2488
+ * endpoint is never given.
2489
+ *
2490
+ * @alpha
2491
+ */
2492
+ type LoadCentrifugeVaultStatusState = {
2493
+ type: 'DISABLED';
2494
+ } | {
2495
+ type: 'LOADING';
2496
+ } | {
2497
+ type: 'ERROR';
2498
+ reason: CentrifugeLoadErrorReason;
2499
+ } | {
2500
+ type: 'CONTENT';
2501
+ status: CentrifugeVaultStatus;
2502
+ };
2503
+ /** @alpha */
2504
+ interface UseCentrifugeVaultStatusesOptions {
2505
+ /** The vaults to poll, typically one per chain an offer runs on. */
2506
+ vaults: CentrifugeVaultRef[];
2507
+ /** How often to refresh. Defaults to {@link CENTRIFUGE_POLL_INTERVAL_MS}. */
2508
+ pollIntervalMs?: number;
2509
+ /**
2510
+ * Statuses the caller already holds, typically fetched server-side, each
2511
+ * opening the state of the vault it names so a server-rendered panel needs
2512
+ * no loading pass.
2513
+ *
2514
+ * They seed the first render only: the poll still fetches immediately. A
2515
+ * vault that was orderable a minute ago can be unlinked now, so a seed
2516
+ * that suppressed the first read would be answering "can I act right now"
2517
+ * with whenever the page was rendered.
2518
+ */
2519
+ data?: CentrifugeVaultStatus[];
2520
+ /** When false, the hook neither fetches nor polls. */
2521
+ enabled: boolean;
2522
+ }
2523
+ /** @alpha */
2524
+ interface UseCentrifugeVaultStatusesResult {
2525
+ /** One entry per vault asked for, in the order asked. */
2526
+ statuses: {
2527
+ vault: CentrifugeVaultRef;
2528
+ state: LoadCentrifugeVaultStatusState;
2529
+ }[];
2530
+ }
2531
+ /**
2532
+ * Polls whether each of several Centrifuge vaults can be acted on right now,
2533
+ * independent of any wallet or amount.
2534
+ *
2535
+ * Free to poll - it spends no attestation. Centrifuge announces none of the
2536
+ * changes this reports, so the poll is the only way a screen notices a vault
2537
+ * halting under it. Each vault is read independently on one shared timer, so
2538
+ * one failing chain never holds back another.
2539
+ *
2540
+ * A seeded status opens its vault's state instead of `LOADING` and is
2541
+ * otherwise left to the poll: the first tick fires as it always does, and
2542
+ * only replaces the seed once it has a status of its own.
2543
+ *
2544
+ * Disabled it neither fetches nor holds a timer. A vault with no status in
2545
+ * hand reports `DISABLED`, not an empty `CONTENT`: there is no empty vault
2546
+ * status, and an invented one would be worse than none, since `CONTENT` here
2547
+ * is what a caller is allowed to block on. A status already in hand survives
2548
+ * being switched off.
2549
+ *
2550
+ * @alpha
2551
+ */
2552
+ declare function useCentrifugeVaultStatuses(options: UseCentrifugeVaultStatusesOptions): UseCentrifugeVaultStatusesResult;
2553
+
2554
+ /** @alpha */
2555
+ interface UseCentrifugeVaultStatusOptions {
2556
+ /** Share token symbol of the vault, e.g. `deJTRSY`. */
2557
+ symbol: AssetSymbol;
2558
+ chain: EthereumChain;
2559
+ /** How often to refresh. Defaults to `CENTRIFUGE_POLL_INTERVAL_MS`. */
2560
+ pollIntervalMs?: number;
2561
+ /**
2562
+ * A status the caller already holds, typically fetched server-side, used
2563
+ * as the state the hook opens on so a server-rendered panel needs no
2564
+ * loading pass.
2565
+ *
2566
+ * It seeds the first render only: the poll still fetches immediately. A
2567
+ * vault that was orderable a minute ago can be unlinked now, so a seed
2568
+ * that suppressed the first read would be answering "can I invest right
2569
+ * now" with whenever the page was rendered.
2570
+ */
2571
+ data?: CentrifugeVaultStatus;
2572
+ /** When false, the hook neither fetches nor polls. */
2573
+ enabled: boolean;
2574
+ }
2575
+ /** @alpha */
2576
+ interface UseCentrifugeVaultStatusResult {
2577
+ state: LoadCentrifugeVaultStatusState;
2578
+ }
2579
+ /**
2580
+ * Polls whether a Centrifuge vault can take a request at all right now,
2581
+ * independent of any amount.
2582
+ *
2583
+ * Free to poll - it spends no attestation. Centrifuge announces none of the
2584
+ * changes this reports, so the poll is the only way a checkout notices
2585
+ * mid-order.
2586
+ *
2587
+ * The one-vault case of {@link useCentrifugeVaultStatuses}, which carries the
2588
+ * seeding, stale-preserving and disabled semantics.
2589
+ *
2590
+ * @alpha
2385
2591
  */
2386
- declare function useCompleteOAuth(options: UseCompleteOAuthOptions): void;
2592
+ declare function useCentrifugeVaultStatus(options: UseCentrifugeVaultStatusOptions): UseCentrifugeVaultStatusResult;
2387
2593
 
2388
2594
  /**
2389
2595
  * UI models every checkout provider needs. Provider-specific models stay in
2390
2596
  * that provider's `use{X}ViewModel.types`; these live here because Ondo and
2391
2597
  * Superstate both render them.
2392
2598
  *
2393
- * Models only. A screen's `{X}UiState` and `{X}UiEvent` stay in that screen's
2394
- * `use{X}ViewModel.types` even when two providers' happen to agree today: a
2395
- * state machine is where providers diverge, and sharing one would make the
2396
- * divergence a breaking change rather than a local edit. Ondo's wallet step
2397
- * confirms synchronously and Superstate's allow-lists on-chain, from the same
2398
- * rows and the same models.
2599
+ * Models only. A provider screen's `{X}UiState` and `{X}UiEvent` stay in that
2600
+ * screen's `use{X}ViewModel.types` even when two providers' happen to agree
2601
+ * today: a state machine is where providers diverge, and sharing one would
2602
+ * make the divergence a breaking change rather than a local edit. A step with
2603
+ * zero provider input is the exception and is shared whole, in its own
2604
+ * `shared/` screen directory - the wallet step Ondo and Centrifuge render as
2605
+ * it stands, while Superstate's allow-lists on-chain from the same rows and
2606
+ * the same models; and the validate-only amount step Centrifuge and
2607
+ * Superstate render as it stands, while Ondo's approves on confirm and builds
2608
+ * its own from the same rules and leaves.
2399
2609
  *
2400
2610
  * No React and no hooks: this is the module Views and leaf components import.
2401
2611
  */
@@ -2415,6 +2625,17 @@ type CheckoutCtaUi = {
2415
2625
  type: 'loading';
2416
2626
  message: string;
2417
2627
  };
2628
+ /**
2629
+ * What an amount field's number is denominated in, drawn beside it.
2630
+ *
2631
+ * A token symbol follows the number as its unit (`1,000 USDC`); a currency
2632
+ * sign leads it (`$1,000`). One closed variant rather than a `prefix` and a
2633
+ * `suffix` that could both be set, because a figure has one unit.
2634
+ */
2635
+ type CheckoutAmountAdornmentUi = {
2636
+ type: 'prefix' | 'suffix';
2637
+ text: string;
2638
+ };
2418
2639
  /**
2419
2640
  * A status and the copy that names it: an Ondo market that is open, a sale
2420
2641
  * still running, a window that has closed.
@@ -2521,6 +2742,42 @@ type CheckoutWalletUi = {
2521
2742
  type CheckoutEmbeddedWalletUi = CheckoutWalletUi & {
2522
2743
  walletAddress: EvmWalletAddress;
2523
2744
  };
2745
+ /**
2746
+ * The external-wallet row of a checkout's wallet step.
2747
+ *
2748
+ * - `hidden`: the host offers no connector and none is connected, so there is
2749
+ * no row at all - a host that only supports embedded wallets.
2750
+ * - `disconnected`: the host offers a connector and nothing is connected yet.
2751
+ * The row is the invitation to connect one.
2752
+ * - `connected`: a wallet like any other. `canDisconnect` is `false` when the
2753
+ * host offers no connector (it handed over a wallet the user cannot change
2754
+ * from here) or while the step is using that wallet.
2755
+ *
2756
+ * A SUM rather than a nullable wallet beside a flag, so a View cannot offer to
2757
+ * connect a wallet the host has no way of connecting.
2758
+ */
2759
+ type CheckoutExternalWalletUi = {
2760
+ type: 'hidden';
2761
+ } | {
2762
+ type: 'disconnected';
2763
+ } | {
2764
+ type: 'connected';
2765
+ wallet: CheckoutWalletUi;
2766
+ canDisconnect: boolean;
2767
+ };
2768
+ declare const CheckoutExternalWalletUi: {
2769
+ /**
2770
+ * The external-wallet row for the host's wallets.
2771
+ *
2772
+ * `locked` is for a step that is using the external wallet right now - mid
2773
+ * signature, say - and must not let it be disconnected underneath itself.
2774
+ */
2775
+ fromDomain: (wallets: WalletSelection, { network, selected, locked, }: {
2776
+ network: string;
2777
+ selected: boolean;
2778
+ locked: boolean;
2779
+ }) => CheckoutExternalWalletUi;
2780
+ };
2524
2781
  /**
2525
2782
  * The wallet the user settled on.
2526
2783
  *
@@ -2573,107 +2830,23 @@ type CheckoutSelectableInputAssetUi = {
2573
2830
  rawBalance: bigint;
2574
2831
  selected: boolean;
2575
2832
  };
2576
-
2577
- /**
2578
- * Step 2 of the Centrifuge checkout: how much of the funding token to deposit.
2579
- *
2580
- * Nothing here touches the chain. Confirming checks the amount in memory and
2581
- * hands it up. The review step approves and places the request together.
2582
- *
2583
- * @alpha
2584
- */
2585
- type CentrifugeBuyAmountUiState = {
2586
- type: 'incomplete';
2587
- } | {
2588
- type: 'active';
2589
- /** Exactly what the user has typed. `'1.'` is a legal thing to hold. */
2590
- amountInput: string;
2591
- walletAddress: ShortenedWalletAddress;
2592
- inputAssets: CheckoutSelectableInputAssetUi[];
2593
- confirmCta: CheckoutCtaUi;
2594
- error: string | null;
2595
- } | {
2596
- type: 'complete';
2597
- inputAsset: CheckoutAssetUi;
2598
- amountFormatted: FormattedAmountAssetUi;
2599
- };
2600
- /** @alpha */
2601
- type CentrifugeBuyAmountUiEvent = {
2602
- type: 'ON_AMOUNT_CHANGE';
2603
- value: string;
2604
- } | {
2605
- type: 'ON_MAX_AMOUNT_CLICK';
2606
- } | {
2607
- type: 'ON_SELECT_PAY_WITH';
2608
- value: AssetSymbol;
2609
- } | {
2610
- type: 'ON_CONFIRM_AMOUNT';
2611
- } | {
2612
- type: 'ON_EDIT_AMOUNT';
2613
- };
2614
-
2615
- /**
2616
- * Why a Centrifuge read failed, in the only two flavours a UI acts on
2617
- * differently.
2618
- *
2619
- * `not-authenticated` is split out because no retry helps until the user
2620
- * signs in. Everything else collapses into `generic-error` and is offered a
2621
- * retry.
2622
- *
2623
- * @alpha
2624
- */
2625
- type CentrifugeLoadErrorReason = 'not-authenticated' | 'generic-error';
2626
-
2627
2833
  /**
2628
- * The built deposit request a review step can place.
2629
- *
2630
- * `isRefreshing` rides on `CONTENT` so a rebuild never blanks the numbers on
2631
- * screen. A failed rebuild keeps them and says why.
2834
+ * Where a placed order can be checked: the wallet it settles to, and the
2835
+ * transaction on a block explorer.
2632
2836
  *
2633
- * @alpha
2837
+ * Every provider's order dialog carries the pair, and builds it the same way
2838
+ * from the same three facts, so it is one model rather than two fields each
2839
+ * dialog re-derives.
2634
2840
  */
2635
- type LoadCentrifugeBuyTransactionState = {
2636
- type: 'LOADING';
2637
- } | {
2638
- type: 'ERROR';
2639
- reason: CentrifugeLoadErrorReason;
2640
- } | {
2641
- type: 'CONTENT';
2642
- transaction: CentrifugeVaultBuyTransaction;
2643
- isRefreshing: boolean;
2644
- refreshError: CentrifugeLoadErrorReason | null;
2645
- };
2646
- /** @alpha */
2647
- interface UseCentrifugeBuyTransactionOptions {
2648
- /**
2649
- * The request to build, or `null` before an amount is confirmed. A `null`
2650
- * request fetches nothing.
2651
- */
2652
- request: BuildCentrifugeVaultBuyParams | null;
2841
+ type CheckoutReceiptUi = {
2842
+ /** The wallet the order settles to. */
2843
+ recipientAddress: ShortenedWalletAddress;
2653
2844
  /**
2654
- * A request the caller already holds, typically the one `prepareBuy`
2655
- * returned. When present the hook adopts it and skips the initial build.
2656
- * `refetch` still builds.
2845
+ * The order's transaction on a block explorer. Always present: a dialog
2846
+ * only exists once there is a transaction to point at.
2657
2847
  */
2658
- data?: CentrifugeVaultBuyTransaction;
2659
- /** When false, the hook does not build. */
2660
- enabled: boolean;
2661
- }
2662
- /** @alpha */
2663
- interface UseCentrifugeBuyTransactionResult {
2664
- state: LoadCentrifugeBuyTransactionState;
2665
- /** Builds a fresh request for the same deposit. */
2666
- refetch: () => void;
2667
- }
2668
- /**
2669
- * Holds the deposit request the review step places, and rebuilds it when
2670
- * asked.
2671
- *
2672
- * **Never polls.** A request is built once, when the user confirms an amount.
2673
- *
2674
- * @alpha
2675
- */
2676
- declare function useCentrifugeBuyTransaction(options: UseCentrifugeBuyTransactionOptions): UseCentrifugeBuyTransactionResult;
2848
+ txExplorerUrl: TxExplorerUrl;
2849
+ };
2677
2850
 
2678
2851
  /**
2679
2852
  * Step 3 of the Centrifuge checkout: confirming the deposit and placing it.
@@ -2708,38 +2881,37 @@ type CentrifugeBuyReviewUiEvent = {
2708
2881
  };
2709
2882
 
2710
2883
  /**
2711
- * Why a Centrifuge checkout cannot run right now, as opposed to a step of it
2712
- * failing.
2884
+ * Why a checkout cannot run right now, as opposed to a step of it failing.
2713
2885
  *
2714
- * @alpha
2715
- */
2716
- type CentrifugeCheckoutErrorReason =
2717
- /**
2718
- * The offer names no vault proxy on the chain the host asked for, so there
2719
- * is no spender to approve and nothing to broadcast to.
2886
+ * Every provider has the same two kinds of answer, and only the second is
2887
+ * named per provider:
2888
+ *
2889
+ * - `unsupported-chain`: the offer names no contract on the chain the host
2890
+ * asked for, so there is no spender to approve and nothing to broadcast to.
2891
+ * Settled at mount, since the offer and the chain are both fixed for its
2892
+ * lifetime, so nothing can clear it.
2893
+ * - `TBlocked`: the provider is known not to take an order right now - a
2894
+ * closed market, a paused vault. Known from a poll, never assumed from one
2895
+ * that is still loading or failed, and it clears on its own once the poll
2896
+ * says so.
2897
+ *
2898
+ * A union rather than a bare flag because the View switches on it for copy.
2720
2899
  */
2721
- 'unsupported-chain'
2900
+ type CheckoutBlockedReason<TBlocked extends string> = 'unsupported-chain' | TBlocked;
2901
+
2722
2902
  /**
2723
- * The vault is known to be unable to take a request: halted, unlinked, or
2724
- * not permissioned. Known from a status whose orderability is blocked.
2725
- * Loading and failed statuses are unknown, and unknown does not block.
2903
+ * Why a Centrifuge checkout cannot run right now, as opposed to a step of it
2904
+ * failing. See {@link CheckoutBlockedReason} for `unsupported-chain`, which
2905
+ * here means the offer names no vault proxy on the chain.
2906
+ *
2907
+ * `not-orderable` is Centrifuge's block: the vault is known to be unable to
2908
+ * take a request - halted, unlinked, or not permissioned. Known from a status
2909
+ * whose orderability is blocked; loading and failed statuses are unknown, and
2910
+ * unknown does not block.
2726
2911
  *
2727
- * Shown only while the user is still choosing a wallet and no request-placed
2728
- * dialog is up. Past that, a pause belongs to the step it interrupts.
2912
+ * @alpha
2729
2913
  */
2730
- | 'not-orderable';
2731
- /** @alpha */
2732
- declare const CentrifugeCheckoutErrorReason: {
2733
- /**
2734
- * Which reason, if any, replaces the whole checkout. `null` means the steps
2735
- * render.
2736
- */
2737
- of: ({ depositableHere, notOrderable, atEntry, }: {
2738
- depositableHere: boolean;
2739
- notOrderable: boolean;
2740
- atEntry: boolean;
2741
- }) => CentrifugeCheckoutErrorReason | null;
2742
- };
2914
+ type CentrifugeCheckoutErrorReason = CheckoutBlockedReason<'not-orderable'>;
2743
2915
 
2744
2916
  /**
2745
2917
  * The asset panel beside the Centrifuge checkout.
@@ -2794,24 +2966,113 @@ type CentrifugeSidebarMinimumUi = {
2794
2966
  };
2795
2967
 
2796
2968
  /**
2797
- * Step 1 of the Centrifuge checkout: which wallet funds the deposit.
2969
+ * The amount step of a checkout whose amount step takes no provider input:
2970
+ * how much to spend, and which stablecoin to spend it in. Centrifuge and
2971
+ * Superstate render it as it stands.
2972
+ *
2973
+ * Shared whole, state machine included, because it is not a provider state
2974
+ * machine: nothing here touches the chain, so confirming checks the amount in
2975
+ * memory and hands it up, and there is nothing for a provider to diverge on.
2976
+ * It forks the moment one provider needs different behaviour - Ondo's already
2977
+ * has, since its confirm approves and builds an order, so it keeps its own
2978
+ * state over the same rules and leaves.
2979
+ *
2980
+ * The CTA is a `CheckoutCtaUi` all the same, rather than a `confirmEnabled`
2981
+ * flag, so the View renders it through the one CTA every amount step uses. It
2982
+ * is never `loading` here.
2983
+ */
2984
+ type CheckoutAmountUiState = {
2985
+ type: 'incomplete';
2986
+ } | {
2987
+ type: 'active';
2988
+ /**
2989
+ * Exactly what the user has typed, not a parsed number: the field is
2990
+ * mid-edit, and `'1.'` is a legal thing to be holding.
2991
+ */
2992
+ amountInput: string;
2993
+ /**
2994
+ * What the field is denominated in: the selected coin's symbol after the
2995
+ * number, or a `$` before it for a dollar-denominated field.
2996
+ */
2997
+ adornment: CheckoutAmountAdornmentUi;
2998
+ /** The wallet the funds come from, per the wallet step. */
2999
+ walletAddress: ShortenedWalletAddress;
3000
+ /**
3001
+ * Every fundable asset, in display order, whether or not the user holds
3002
+ * any. One entry renders as a plain card, two or more as a picker.
3003
+ */
3004
+ inputAssets: CheckoutSelectableInputAssetUi[];
3005
+ confirmCta: CheckoutCtaUi;
3006
+ /**
3007
+ * Validation copy, e.g. `Insufficient USDC.`, or why no amount can be
3008
+ * confirmed right now, which takes its place.
3009
+ */
3010
+ error: string | null;
3011
+ } | {
3012
+ type: 'complete';
3013
+ inputAsset: CheckoutAssetUi;
3014
+ /**
3015
+ * The confirmed amount as the field asked for it: `1,000.00 USDC`, or
3016
+ * `$1,000.00` for a dollar-denominated field.
3017
+ */
3018
+ amountFormatted: FormattedAmountAssetUi;
3019
+ /**
3020
+ * The same figure in the asset actually being paid, e.g. `1,000.00
3021
+ * USDC`, when the headline names dollars rather than the asset. `null`
3022
+ * when the headline already is in the asset.
3023
+ *
3024
+ * Both are shown for a dollar field because the two are only equal while
3025
+ * the funding asset is a dollar stablecoin - the day a non-dollar one is
3026
+ * fundable, the summary would otherwise silently claim it was.
3027
+ */
3028
+ inputAmountFormatted: FormattedAmountAssetUi | null;
3029
+ };
3030
+ /**
3031
+ * Everything the amount step raises. `ON_CONFIRM_AMOUNT` only moves the flow
3032
+ * to the review step: nothing is placed or paid for here.
3033
+ */
3034
+ type CheckoutAmountUiEvent = {
3035
+ type: 'ON_AMOUNT_CHANGE';
3036
+ value: string;
3037
+ } | {
3038
+ type: 'ON_MAX_AMOUNT_CLICK';
3039
+ } | {
3040
+ type: 'ON_SELECT_PAY_WITH';
3041
+ value: AssetSymbol;
3042
+ } | {
3043
+ type: 'ON_CONFIRM_AMOUNT';
3044
+ } | {
3045
+ type: 'ON_EDIT_AMOUNT';
3046
+ };
3047
+
3048
+ /**
3049
+ * Step 1 of a checkout whose wallet step takes no provider input: which wallet
3050
+ * funds the order and receives the asset. Ondo (buy and sell) and Centrifuge
3051
+ * render it as it stands.
2798
3052
  *
2799
- * There is no `inactive` arm. This step is the first one, so it is either being
2800
- * filled in or already answered — it is never waiting on a step above it.
3053
+ * Shared whole, state machine included, because it is not a provider state
3054
+ * machine: no provider answers anything here, so there is nothing for one to
3055
+ * diverge on. It forks the moment one provider needs different behaviour -
3056
+ * Superstate already has, since its confirm allow-lists the wallet on-chain,
3057
+ * so it keeps its own state over the same rows.
2801
3058
  *
2802
- * Nothing is allow-listed: the user picks a wallet and confirms, and confirming
2803
- * is synchronous. Hence a plain `confirmEnabled`.
3059
+ * There is no `inactive` arm. This step is the first one, so it is either
3060
+ * being filled in or already answered - it is never waiting on a step above
3061
+ * it.
2804
3062
  *
2805
- * @alpha
3063
+ * Nothing is allow-listed: the user picks a wallet and confirms, and
3064
+ * confirming is synchronous. Hence a plain `confirmEnabled` rather than a
3065
+ * `CheckoutCtaUi` with loading copy.
2806
3066
  */
2807
- type CentrifugeWalletSelectUiState = {
3067
+ type CheckoutWalletSelectUiState = {
2808
3068
  type: 'active';
2809
3069
  /** The user's CoinList wallets. Empty when they have none. */
2810
3070
  embeddedWallets: CheckoutEmbeddedWalletUi[];
2811
- /** `null` until an external wallet is connected. The row still renders. */
2812
- externalWallet: CheckoutWalletUi | null;
2813
- /** Whether the connected external wallet may be disconnected here. */
2814
- canDisconnect: boolean;
3071
+ /**
3072
+ * The external-wallet row: absent when the host offers no connector,
3073
+ * an invitation to connect one, or the connected wallet.
3074
+ */
3075
+ externalWallet: CheckoutExternalWalletUi;
2815
3076
  confirmEnabled: boolean;
2816
3077
  /** Copy for a failed connect, e.g. the user rejected the wallet prompt. */
2817
3078
  error: string | null;
@@ -2819,8 +3080,7 @@ type CentrifugeWalletSelectUiState = {
2819
3080
  type: 'completed';
2820
3081
  wallet: CheckoutConfirmedWalletUi;
2821
3082
  };
2822
- /** @alpha */
2823
- type CentrifugeWalletSelectUiEvent = {
3083
+ type CheckoutWalletSelectUiEvent = {
2824
3084
  type: 'ON_SELECT_WALLET';
2825
3085
  value: CheckoutWalletTypeUi;
2826
3086
  }
@@ -2847,8 +3107,13 @@ type CentrifugeWalletSelectUiEvent = {
2847
3107
  */
2848
3108
  type CentrifugeBuyCheckoutUiState = {
2849
3109
  type: 'content';
2850
- wallet: CentrifugeWalletSelectUiState;
2851
- amount: CentrifugeBuyAmountUiState;
3110
+ /**
3111
+ * The wallet step, or `null` when the host preselected a wallet and the
3112
+ * flow skipped it. The later steps are numbered from it. Never `null`
3113
+ * today: this flow does not honour a preselection yet.
3114
+ */
3115
+ wallet: CheckoutWalletSelectUiState | null;
3116
+ amount: CheckoutAmountUiState;
2852
3117
  review: CentrifugeBuyReviewUiState;
2853
3118
  sidebar: CentrifugeSidebarUiState;
2854
3119
  orderPlaced: CentrifugeOrderPlacedUiState;
@@ -2857,7 +3122,7 @@ type CentrifugeBuyCheckoutUiState = {
2857
3122
  reason: CentrifugeCheckoutErrorReason;
2858
3123
  };
2859
3124
  /** @alpha */
2860
- type CentrifugeBuyCheckoutUiEvent = CentrifugeWalletSelectUiEvent | CentrifugeBuyAmountUiEvent | CentrifugeBuyReviewUiEvent | CentrifugeOrderPlacedUiEvent;
3125
+ type CentrifugeBuyCheckoutUiEvent = CheckoutWalletSelectUiEvent | CheckoutAmountUiEvent | CentrifugeBuyReviewUiEvent | CentrifugeOrderPlacedUiEvent;
2861
3126
  /**
2862
3127
  * The dialog that closes the checkout once the request has mined.
2863
3128
  *
@@ -2867,13 +3132,11 @@ type CentrifugeBuyCheckoutUiEvent = CentrifugeWalletSelectUiEvent | CentrifugeBu
2867
3132
  */
2868
3133
  type CentrifugeOrderPlacedUiState = {
2869
3134
  type: 'hidden';
2870
- } | {
3135
+ } | ({
2871
3136
  type: 'visible';
2872
3137
  outputAsset: CheckoutAssetUi;
2873
3138
  totalCost: FormattedAmountAssetUi;
2874
- recipientAddress: ShortenedWalletAddress;
2875
- txExplorerUrl: TxExplorerUrl;
2876
- };
3139
+ } & CheckoutReceiptUi);
2877
3140
  /** @alpha */
2878
3141
  type CentrifugeOrderPlacedUiEvent = {
2879
3142
  type: 'ON_CLOSE_ORDER_PLACED';
@@ -2883,6 +3146,15 @@ type CentrifugeOrderPlacedUiEvent = {
2883
3146
  interface UseCentrifugeBuyCheckoutViewModelOptions {
2884
3147
  offer: CentrifugeVaultOfferDetail;
2885
3148
  chain: EthereumChain;
3149
+ /**
3150
+ * The host's wallets, its connector for an external one if any, and
3151
+ * optionally the wallet it has already settled on.
3152
+ *
3153
+ * `wallets.preselected` is read **once**, to seed the step machine: set, the
3154
+ * flow has no wallet step and opens on the amount. A host that changes it
3155
+ * mid-flow is ignored, because the approval the review grants is granted by
3156
+ * one specific wallet.
3157
+ */
2886
3158
  wallets: CheckoutWalletSelection;
2887
3159
  enabled?: boolean;
2888
3160
  /** Fired once the request has mined. The dialog shows either way. */
@@ -2900,15 +3172,22 @@ interface UseCentrifugeBuyCheckoutViewModelResult {
2900
3172
  * review, and sidebar steps. The status poll lives here. The amount step
2901
3173
  * only validates.
2902
3174
  *
2903
- * A vault that is known to be blocked replaces the checkout only at the
2904
- * wallet step. A status that is still loading, or that failed, does not.
3175
+ * A vault that is known to be blocked replaces the checkout only at the step
3176
+ * the flow opened on: the wallet step, or the amount for a wallet the host
3177
+ * preselected. A status that is still loading, or that failed, does not.
2905
3178
  *
2906
3179
  * @alpha
2907
3180
  */
2908
3181
  declare function useCentrifugeBuyCheckoutViewModel({ offer, chain, wallets, enabled, onOrderPlaced, }: UseCentrifugeBuyCheckoutViewModelOptions): UseCentrifugeBuyCheckoutViewModelResult;
2909
3182
 
2910
- type LoadParticipationsReason = 'not-authenticated' | 'generic-error';
3183
+ type LoadParticipationsReason = LoadErrorReason;
3184
+ /**
3185
+ * The state of the participations read. `DISABLED` means the hook was
3186
+ * switched off before an answer arrived, so nothing is in flight.
3187
+ */
2911
3188
  type LoadParticipationsState = {
3189
+ type: 'DISABLED';
3190
+ } | {
2912
3191
  type: 'LOADING';
2913
3192
  } | {
2914
3193
  type: 'ERROR';
@@ -2917,36 +3196,221 @@ type LoadParticipationsState = {
2917
3196
  type: 'CONTENT';
2918
3197
  participations: Participation[];
2919
3198
  };
2920
- interface UseParticipationsOptions {
3199
+ interface UseParticipationsOptions {
3200
+ /**
3201
+ * Participations pre-fetched on the server (e.g. via `CoinListServer#tokenSale.list()`).
3202
+ * When provided, the hook uses this data as-is and skips the initial
3203
+ * client-side fetch; {@link UseParticipationsResult.refetch} still fetches.
3204
+ */
3205
+ data?: Participation[];
3206
+ /**
3207
+ * When `false`, the hook sends no request. A seeded or already-fetched
3208
+ * `CONTENT` survives; otherwise the hook reports `DISABLED`. Defaults to
3209
+ * `true`.
3210
+ */
3211
+ enabled?: boolean;
3212
+ }
3213
+ interface UseParticipationsResult {
3214
+ participationsState: LoadParticipationsState;
3215
+ /**
3216
+ * Fetches again: the recovery path after an `ERROR`, and the way past a
3217
+ * server seed (`data`), which only the first fetch honours. No-op while
3218
+ * disabled.
3219
+ */
3220
+ refetch: () => void;
3221
+ }
3222
+ /**
3223
+ * Loads all CoinList participations for the current user and exposes a UI-friendly state.
3224
+ * Optionally filters by offer when `offerId` is provided.
3225
+ *
3226
+ * Pass `data` (pre-fetched server-side) to open on it and skip the initial
3227
+ * client-side fetch. Pass `enabled: false` to skip the fetch when the hook
3228
+ * must be called but the data is not needed yet.
3229
+ *
3230
+ * Returns `LOADING` while CoinList is initializing or while participations are being fetched.
3231
+ * Returns `CONTENT` with all participations when the read succeeds.
3232
+ * Returns `ERROR` with:
3233
+ * - `not-authenticated` when the user has to sign in first
3234
+ * - `generic-error` for any other failure
3235
+ */
3236
+ declare function useParticipations(offerId?: OfferId, options?: UseParticipationsOptions): UseParticipationsResult;
3237
+
3238
+ /**
3239
+ * The last step of the token-sale checkout: confirming the commitment and
3240
+ * placing it.
3241
+ *
3242
+ * Placing approves the payment to the sale's funding contract and records the
3243
+ * participation. Nothing is spent yet: the sale pulls the payment and
3244
+ * allocates the tokens when it settles, so the quantity shown is an estimate.
3245
+ *
3246
+ * @alpha
3247
+ */
3248
+ type TokenSaleReviewUiState = {
3249
+ type: 'incomplete';
3250
+ } | {
3251
+ type: 'active';
3252
+ /** The token being bought. */
3253
+ outputAsset: CheckoutAssetUi;
3254
+ /** How many tokens the payment buys at the option's price, e.g. `200.00 TKN`. */
3255
+ estimatedTokens: FormattedAmountAssetUi;
3256
+ /** The option's price for one whole token, e.g. `$0.50`. */
3257
+ pricePerToken: FormattedAmountAssetUi;
3258
+ /** What the user commits, e.g. `100.00 USDC`. No fee comes off it. */
3259
+ payAmount: FormattedAmountAssetUi;
3260
+ /** Where the tokens land - the wallet that approves the payment. */
3261
+ recipientAddress: ShortenedWalletAddress;
3262
+ /** The option's sale agreement, which the order is placed under. */
3263
+ saleAgreementUrl: string | null;
3264
+ placeOrderCta: CheckoutCtaUi;
3265
+ error: string | null;
3266
+ };
3267
+ /** @alpha */
3268
+ type TokenSaleReviewUiEvent = {
3269
+ type: 'ON_PLACE_ORDER';
3270
+ };
3271
+
3272
+ /**
3273
+ * Why a token-sale checkout cannot run at all, as opposed to a step of it
3274
+ * failing. Every one of them is a fact about the offer and the host's props,
3275
+ * so none clears on its own:
3276
+ *
3277
+ * - `unsupported-chain`: the sale names no funding contract on the chain.
3278
+ * - `unknown-option`: the host's `optionId` is not one of the offer's options.
3279
+ * - `no-price`: the option has no fixed price - an auction, which the SDK
3280
+ * does not run.
3281
+ * - `no-payable-asset`: the sale accepts no coin the SDK can pay with on the
3282
+ * chain.
3283
+ *
3284
+ * @alpha
3285
+ */
3286
+ type TokenSaleCheckoutErrorReason = CheckoutBlockedReason<'unknown-option' | 'no-price' | 'no-payable-asset'>;
3287
+
3288
+ /**
3289
+ * The reference panel beside the token-sale checkout: which token is being
3290
+ * bought, what one costs, whether the sale is running, and the terms that do
3291
+ * not move while the order is filled in.
3292
+ *
3293
+ * Read-only, so there is no `UiEvent`. Everything is known from the offer the
3294
+ * moment the checkout renders, so the state is a product rather than a union.
3295
+ *
3296
+ * @alpha
3297
+ */
3298
+ type TokenSaleSidebarUiState = {
3299
+ asset: CheckoutAssetUi;
3300
+ /** Whether the sale is running: a live countdown, or why it is not. */
3301
+ sale: CheckoutStatusUi;
3302
+ /** The option's price for one whole token, e.g. `$0.50`. */
3303
+ pricePerToken: FormattedAmountAssetUi;
3304
+ /**
3305
+ * The price times the option's total token supply, e.g. `$500,000,000.00`.
3306
+ * `-` when the option publishes no supply.
3307
+ */
3308
+ fullyDilutedValuation: FormattedAmountAssetUi;
3309
+ /** Display name of the chain the sale is paid on, e.g. `Ethereum`. */
3310
+ networkName: string;
3311
+ /** What the sale can be paid in, e.g. `USDC, USDT`. */
3312
+ purchaseOptionsLabel: string;
3313
+ /** The option's minimum, e.g. `$100.00`. `-` when it publishes none. */
3314
+ minPurchase: FormattedAmountAssetUi;
3315
+ };
3316
+
3317
+ /**
3318
+ * The whole CoinList token-sale checkout: three steps, the sale panel, and the
3319
+ * dialog that says the order was placed.
3320
+ *
3321
+ * @alpha
3322
+ */
3323
+ type CoinListTokenSaleCheckoutUiState = {
3324
+ type: 'content';
3325
+ /**
3326
+ * The wallet step, or `null` when the host preselected a wallet and the
3327
+ * flow skipped it. The later steps are numbered from it.
3328
+ */
3329
+ wallet: CheckoutWalletSelectUiState | null;
3330
+ amount: CheckoutAmountUiState;
3331
+ review: TokenSaleReviewUiState;
3332
+ sidebar: TokenSaleSidebarUiState;
3333
+ orderPlaced: TokenSaleOrderPlacedUiState;
3334
+ } | {
3335
+ type: 'error';
3336
+ reason: TokenSaleCheckoutErrorReason;
3337
+ };
3338
+ /** @alpha */
3339
+ type CoinListTokenSaleCheckoutUiEvent = CheckoutWalletSelectUiEvent | CheckoutAmountUiEvent | TokenSaleReviewUiEvent | TokenSaleOrderPlacedUiEvent;
3340
+ /**
3341
+ * The dialog that closes the checkout once the order is recorded.
3342
+ *
3343
+ * It reports a commitment, not a purchase: the sale allocates the tokens and
3344
+ * pulls the payment when it settles. The explorer link is the approval's,
3345
+ * the one transaction the order sent.
3346
+ *
3347
+ * @alpha
3348
+ */
3349
+ type TokenSaleOrderPlacedUiState = {
3350
+ type: 'hidden';
3351
+ } | ({
3352
+ type: 'visible';
3353
+ outputAsset: CheckoutAssetUi;
3354
+ /** What was committed, e.g. `100.00 USDC`. */
3355
+ payAmount: FormattedAmountAssetUi;
3356
+ /** How many tokens it buys at the option's price, e.g. `200.00 TKN`. */
3357
+ estimatedTokens: FormattedAmountAssetUi;
3358
+ } & CheckoutReceiptUi);
3359
+ /** @alpha */
3360
+ type TokenSaleOrderPlacedUiEvent = {
3361
+ type: 'ON_CLOSE_ORDER_PLACED';
3362
+ };
3363
+
3364
+ /** @alpha */
3365
+ interface UseCoinListTokenSaleCheckoutViewModelOptions {
3366
+ offer: CoinListTokenSaleOfferDetail;
3367
+ /** The chain the order is paid on. The sale must name a funding contract there. */
3368
+ chain: EthereumChain;
2921
3369
  /**
2922
- * Participations pre-fetched on the server (e.g. via `CoinListServer#tokenSale.list()`).
2923
- * When provided, the hook uses this data as-is and skips the client-side fetch entirely.
3370
+ * The option being bought, which sets the price, the minimum and the sale
3371
+ * agreement. Defaults to the offer's first option.
3372
+ *
3373
+ * **Read once, at mount**: the price, minimum and agreement the steps were
3374
+ * filled in against are this option's. A host whose selection can change
3375
+ * remounts with a `key` covering it.
2924
3376
  */
2925
- data?: Participation[];
3377
+ optionId?: OfferOptionId;
2926
3378
  /**
2927
- * When `false`, the hook sends no request. A seeded or already-fetched
2928
- * `CONTENT` survives; otherwise the hook stays `LOADING`. Defaults to `true`.
3379
+ * The host's wallets, its connector for an external one if any, and
3380
+ * optionally the wallet it has already settled on.
3381
+ *
3382
+ * `wallets.preselected` is read **once**, to seed the step machine: set, the
3383
+ * flow has no wallet step and opens on the amount. A host that changes it
3384
+ * mid-flow is ignored, because the approval the review grants is granted by
3385
+ * one specific wallet.
2929
3386
  */
3387
+ wallets: CheckoutWalletSelection;
2930
3388
  enabled?: boolean;
3389
+ /** Fired once the participation is recorded. The dialog shows either way. */
3390
+ onOrderPlaced?: (order: TokenSaleOrderPlaced) => void;
2931
3391
  }
2932
- interface UseParticipationsResult {
2933
- participationsState: LoadParticipationsState;
3392
+ /** @alpha */
3393
+ interface UseCoinListTokenSaleCheckoutViewModelResult {
3394
+ state: CoinListTokenSaleCheckoutUiState;
3395
+ onEvent: (event: CoinListTokenSaleCheckoutUiEvent) => void;
2934
3396
  }
2935
3397
  /**
2936
- * Loads all CoinList participations for the current user and exposes a UI-friendly state.
2937
- * Optionally filters by offer when `offerId` is provided.
3398
+ * Drives the CoinList token-sale checkout.
2938
3399
  *
2939
- * Pass `data` (pre-fetched server-side) to use that data as-is and skip
2940
- * the client-side fetch entirely. Pass `enabled: false` to skip the fetch
2941
- * when the hook must be called but the data is not needed yet.
3400
+ * The container mounts this hook only. It composes the shared wallet and
3401
+ * amount steps, the review that places the order, and the sale panel. The
3402
+ * amount step only validates; the review approves the payment to the sale's
3403
+ * funding contract and records the participation.
2942
3404
  *
2943
- * Returns `LOADING` while CoinList is initializing or while participations are being fetched.
2944
- * Returns `CONTENT` with all participations when `fetchParticipations()` succeeds.
2945
- * Returns `ERROR` with:
2946
- * - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}
2947
- * - `generic-error` for any other failure
3405
+ * A sale that cannot take an order on this chain at all - no funding
3406
+ * contract, no such option, no fixed price, no coin the SDK can pay with -
3407
+ * replaces the whole checkout. A sale outside its window blocks the amount
3408
+ * and review steps instead, and the panel says when it opens or that it
3409
+ * ended.
3410
+ *
3411
+ * @alpha
2948
3412
  */
2949
- declare function useParticipations(offerId?: OfferId, options?: UseParticipationsOptions): UseParticipationsResult;
3413
+ declare function useCoinListTokenSaleCheckoutViewModel({ offer, chain, optionId: initialOptionId, wallets, enabled, onOrderPlaced, }: UseCoinListTokenSaleCheckoutViewModelOptions): UseCoinListTokenSaleCheckoutViewModelResult;
2950
3414
 
2951
3415
  /**
2952
3416
  * Step 2 of the Ondo checkout: how much to spend, and which asset to spend.
@@ -3012,28 +3476,43 @@ type OndoBuyAmountUiEvent = {
3012
3476
  * branch in every consumer to distinguish. Split it out if that stops being
3013
3477
  * true.
3014
3478
  */
3015
- type OndoLoadErrorReason = 'not-authenticated' | 'not-tradable' | 'generic-error';
3479
+ type OndoLoadErrorReason = LoadErrorReason | 'not-tradable';
3016
3480
 
3017
3481
  /**
3018
- * The state of the built purchase a review step acts on.
3482
+ * The state of a firm, expiring transaction a review step acts on.
3019
3483
  *
3020
- * `isRefreshing` rides on `CONTENT` rather than replacing it, so a refresh in
3021
- * flight never blanks the numbers the user is reading. A refresh that fails
3022
- * keeps them too, and reports why alongside - the previous purchase may still
3023
- * be good, and a failed refresh is fixed by refreshing again.
3484
+ * `DISABLED` means the caller switched the hook off before a transaction was
3485
+ * in hand, so nothing is being built. A transaction already in hand - a seed,
3486
+ * or an earlier build - survives being switched off.
3487
+ *
3488
+ * `isRefreshing` rides on `CONTENT` rather than replacing it, so a rebuild in
3489
+ * flight never blanks the numbers the user is reading. A rebuild that fails
3490
+ * keeps them too, and reports why alongside - the previous transaction may
3491
+ * still be good, and a failed rebuild is fixed by rebuilding again.
3024
3492
  */
3025
- type LoadOndoBuyTransactionState = {
3493
+ type LoadFirmTransactionState<T, R> = {
3494
+ type: 'DISABLED';
3495
+ } | {
3026
3496
  type: 'LOADING';
3027
3497
  } | {
3028
3498
  type: 'ERROR';
3029
- reason: OndoLoadErrorReason;
3499
+ reason: R;
3030
3500
  } | {
3031
3501
  type: 'CONTENT';
3032
- transaction: OndoBuyTransaction;
3502
+ transaction: T;
3033
3503
  isRefreshing: boolean;
3034
- /** Why the last refresh failed; `null` when the purchase is fresh. */
3035
- refreshError: OndoLoadErrorReason | null;
3504
+ /** Why the last rebuild failed; `null` when the transaction is fresh. */
3505
+ refreshError: R | null;
3036
3506
  };
3507
+
3508
+ /**
3509
+ * The state of the built purchase a review step acts on.
3510
+ *
3511
+ * `DISABLED` while switched off with no purchase in hand. `isRefreshing` rides
3512
+ * on `CONTENT`, so a refresh in flight never blanks the numbers the user is
3513
+ * reading, and a refresh that fails keeps them and says why.
3514
+ */
3515
+ type LoadOndoBuyTransactionState = LoadFirmTransactionState<OndoBuyTransaction, OndoLoadErrorReason>;
3037
3516
  interface UseOndoBuyTransactionOptions {
3038
3517
  /**
3039
3518
  * The order to build, or `null` while there is not one yet - before the
@@ -3057,29 +3536,50 @@ interface UseOndoBuyTransactionResult {
3057
3536
  }
3058
3537
  /**
3059
3538
  * Holds the firm, expiring purchase the buy review step places an order
3060
- * against, and rebuilds it on demand.
3061
- *
3062
- * **Never polls.** Building spends an attestation, so a new one is only ever
3063
- * obtained when the caller asks - on `refetch`, or on the first render if no
3064
- * `data` was supplied. That is also why an expired purchase is left expired
3065
- * here: whether to replace it is the user's call, not a timer's.
3066
- *
3067
- * Disabled it fetches nothing and stays on whatever state it opened with. That
3068
- * is `LOADING` and not an empty `CONTENT` because there is no empty
3069
- * purchase: firm calldata for an order that does not exist is not
3070
- * representable. A caller that switches this hook off should switch its own
3071
- * rendering off with it - which is what the review step does, since a step
3072
- * that is not active is `incomplete` and never reads this state at all.
3539
+ * against, and rebuilds it on demand. **Never polls**: each build spends an
3540
+ * attestation.
3073
3541
  *
3074
3542
  * One of a pair with `useOndoSellTransaction`, and deliberately not one hook
3075
- * over both. The two endpoints answer different shapes - a purchase commits to
3076
- * an exact quantity, a sale to a range - so a shared hook would hand every
3077
- * review step a union to narrow after its own directory had already settled
3078
- * which trade it was. The machinery below is the price of that, and it is the
3079
- * cheaper half: what a screen reads off `CONTENT` is the expensive half.
3543
+ * over both (ADR-10). The two endpoints answer different shapes - a purchase
3544
+ * commits to an exact quantity, a sale to a range - so a shared public hook
3545
+ * would hand every review step a union to narrow after its own directory had
3546
+ * already settled which trade it was. The machinery is shared instead, in
3547
+ * `useFirmTransaction`.
3080
3548
  */
3081
3549
  declare function useOndoBuyTransaction(options: UseOndoBuyTransactionOptions): UseOndoBuyTransactionResult;
3082
3550
 
3551
+ /**
3552
+ * Whether the numbers on an Ondo review step can still be traded on.
3553
+ *
3554
+ * A quote is only good for a few seconds, so this drives the line above the CTA
3555
+ * and whether the CTA can be pressed at all. `refresh-failed` is its own arm
3556
+ * rather than folding into the step's `error`, because the remedy differs: a
3557
+ * failed refresh is fixed by refreshing again, a failed order is not.
3558
+ *
3559
+ * One type for both products, because a buy and a sell quote expire, refresh
3560
+ * and fail to refresh in exactly the same way: `useOndoReviewExecution` derives
3561
+ * it for both from the same firm transaction state.
3562
+ */
3563
+ type OndoQuoteStatusUi =
3564
+ /** Still good. `expiresInLabel` is the countdown copy, already formatted. */
3565
+ {
3566
+ type: 'valid';
3567
+ expiresInLabel: string;
3568
+ }
3569
+ /** A refresh is in flight; the previous numbers are still on screen. */
3570
+ | {
3571
+ type: 'refreshing';
3572
+ }
3573
+ /** Too old to trade on. The user must refresh before placing the order. */
3574
+ | {
3575
+ type: 'expired';
3576
+ }
3577
+ /** The refresh failed. `message` says why. */
3578
+ | {
3579
+ type: 'refresh-failed';
3580
+ message: string;
3581
+ };
3582
+
3083
3583
  /**
3084
3584
  * Step 3 of the Ondo checkout: what the order comes to, and placing it.
3085
3585
  *
@@ -3117,38 +3617,11 @@ type OndoBuyReviewUiState = {
3117
3617
  coinlistFee: FormattedAmountAssetUi | null;
3118
3618
  /** What the user pays in the input asset, e.g. `1,000.00 USDC`. */
3119
3619
  total: FormattedAmountAssetUi;
3120
- quote: OndoBuyQuoteStatusUi;
3620
+ quote: OndoQuoteStatusUi;
3121
3621
  placeOrderCta: CheckoutCtaUi;
3122
3622
  /** A failure from placing the order, distinct from a quote problem. */
3123
3623
  error: string | null;
3124
3624
  };
3125
- /**
3126
- * Whether the shown numbers can still be traded on.
3127
- *
3128
- * A quote is only good for a few seconds, so this drives the line above the CTA
3129
- * and whether the CTA can be pressed at all. `refresh-failed` is its own arm
3130
- * rather than folding into the step's `error`, because the remedy differs: a
3131
- * failed refresh is fixed by refreshing again, a failed order is not.
3132
- */
3133
- type OndoBuyQuoteStatusUi =
3134
- /** Still good. `expiresInLabel` is the countdown copy, already formatted. */
3135
- {
3136
- type: 'valid';
3137
- expiresInLabel: string;
3138
- }
3139
- /** A refresh is in flight; the previous numbers are still on screen. */
3140
- | {
3141
- type: 'refreshing';
3142
- }
3143
- /** Too old to trade on. The user must refresh before placing the order. */
3144
- | {
3145
- type: 'expired';
3146
- }
3147
- /** The refresh failed. `message` says why. */
3148
- | {
3149
- type: 'refresh-failed';
3150
- message: string;
3151
- };
3152
3625
  type OndoBuyReviewUiEvent = {
3153
3626
  type: 'ON_REFRESH_QUOTE';
3154
3627
  }
@@ -3161,9 +3634,14 @@ type OndoBuyReviewUiEvent = {
3161
3634
 
3162
3635
  /**
3163
3636
  * Why an Ondo checkout cannot run right now, as opposed to a step of it
3164
- * failing.
3637
+ * failing. See {@link CheckoutBlockedReason} for `unsupported-chain`, which
3638
+ * here means the offer names no CoinList swap contract on the chain (see
3639
+ * `swapSpender`).
3165
3640
  *
3166
- * A union rather than a bare flag because the View switches on it for copy.
3641
+ * `not-tradable` is Ondo's block: it is not filling orders for this asset on
3642
+ * this side right now, because the market is closed or paused, or the asset is
3643
+ * paused or closed for the session. The trading-status poll keeps running
3644
+ * underneath it, and the checkout comes back once the asset is tradable again.
3167
3645
  *
3168
3646
  * Shared by both products because each reason is a property of the integration
3169
3647
  * or of the market rather than of a direction: buying and selling go through
@@ -3172,47 +3650,7 @@ type OndoBuyReviewUiEvent = {
3172
3650
  * exception the provider-level `shared/` exists for, and it is narrow - the
3173
3651
  * step states stay per-product, since that is where the two genuinely diverge.
3174
3652
  */
3175
- type OndoCheckoutErrorReason =
3176
- /**
3177
- * The offer names no CoinList swap contract on the chain the host asked for,
3178
- * so there is no spender to approve and nothing to broadcast to.
3179
- *
3180
- * Not retryable, and not the host's mistake to correct at runtime: both the
3181
- * offer and the chain are fixed for the lifetime of the mount. See
3182
- * `swapSpender`.
3183
- */
3184
- 'unsupported-chain'
3185
- /**
3186
- * Ondo is not filling orders for this asset on this side right now: the
3187
- * market is closed or paused, or the asset is paused or closed for the
3188
- * session. Known from the trading-status poll, never assumed from a status
3189
- * that is still loading or failed to load.
3190
- *
3191
- * Unlike `unsupported-chain` this one clears on its own. The trading-status
3192
- * poll keeps running underneath it, and the checkout comes back once the
3193
- * asset is tradable again. Only shown while the user is on the step the flow
3194
- * opened on: once they are past it, a pause is a step's to report, so it
3195
- * cannot pull an order out from under the user mid-flow.
3196
- */
3197
- | 'not-tradable';
3198
- declare const OndoCheckoutErrorReason: {
3199
- /**
3200
- * Which reason, if any, replaces the whole checkout. `null` means the steps
3201
- * render.
3202
- *
3203
- * `unsupported-chain` wins because it is settled at mount: no market state
3204
- * can make a chain with no contract tradable. `not-tradable` needs both a
3205
- * market *known* to be closed and a user still at the start of the flow,
3206
- * with no order confirmation on screen. Past the first step a pause belongs
3207
- * to the step it interrupts, and a just-placed order's dialog must not be
3208
- * hidden by a market that closed after it filled.
3209
- */
3210
- of: ({ swappableHere, notTradable, atEntry, }: {
3211
- swappableHere: boolean;
3212
- notTradable: boolean;
3213
- atEntry: boolean;
3214
- }) => OndoCheckoutErrorReason | null;
3215
- };
3653
+ type OndoCheckoutErrorReason = CheckoutBlockedReason<'not-tradable'>;
3216
3654
 
3217
3655
  /**
3218
3656
  * The reference panel beside the Ondo checkout: which asset is being bought,
@@ -3283,54 +3721,6 @@ type OndoSidebarPriceUi =
3283
3721
  type: 'unavailable';
3284
3722
  };
3285
3723
 
3286
- /**
3287
- * Step 1 of the Ondo checkout: which wallet funds the purchase and receives the
3288
- * asset.
3289
- *
3290
- * There is no `inactive` arm. This step is the first one, so it is either being
3291
- * filled in or already answered — it is never waiting on a step above it.
3292
- *
3293
- * Unlike Superstate's equivalent, nothing is allow-listed here: the user picks
3294
- * a wallet and confirms, and confirming is synchronous. Hence a plain
3295
- * `confirmEnabled` rather than the `CheckoutCtaUi` Superstate's step carries.
3296
- * The rows themselves are the shared `Checkout*WalletUi` models — the two
3297
- * providers render the same wallets and disagree only about what confirming
3298
- * does.
3299
- */
3300
- type OndoWalletSelectUiState = {
3301
- type: 'active';
3302
- /** The user's CoinList wallets. Empty when they have none. */
3303
- embeddedWallets: CheckoutEmbeddedWalletUi[];
3304
- /** `null` until an external wallet is connected. The row still renders. */
3305
- externalWallet: CheckoutWalletUi | null;
3306
- /** Whether the connected external wallet may be disconnected here. */
3307
- canDisconnect: boolean;
3308
- confirmEnabled: boolean;
3309
- /** Copy for a failed connect, e.g. the user rejected the wallet prompt. */
3310
- error: string | null;
3311
- } | {
3312
- type: 'completed';
3313
- wallet: CheckoutConfirmedWalletUi;
3314
- };
3315
- type OndoWalletSelectUiEvent = {
3316
- type: 'ON_SELECT_WALLET';
3317
- value: CheckoutWalletTypeUi;
3318
- }
3319
- /**
3320
- * Tapping the external row while nothing is connected. Split from
3321
- * `ON_SELECT_WALLET` because it opens the host's wallet connector rather than
3322
- * changing the selection.
3323
- */
3324
- | {
3325
- type: 'ON_CONNECT_WALLET';
3326
- } | {
3327
- type: 'ON_DISCONNECT_WALLET';
3328
- } | {
3329
- type: 'ON_CONFIRM_WALLET';
3330
- } | {
3331
- type: 'ON_EDIT_WALLET';
3332
- };
3333
-
3334
3724
  /**
3335
3725
  * The whole Ondo buy checkout: three step cards, the reference panel beside
3336
3726
  * them, and the dialog that closes the flow.
@@ -3350,7 +3740,12 @@ type OndoWalletSelectUiEvent = {
3350
3740
  */
3351
3741
  type OndoBuyCheckoutUiState = {
3352
3742
  type: 'content';
3353
- wallet: OndoWalletSelectUiState;
3743
+ /**
3744
+ * The wallet step, or `null` when the host preselected a wallet and the
3745
+ * flow skipped it. The later steps are numbered from it. Never `null`
3746
+ * today: the buy flow does not honour a preselection yet.
3747
+ */
3748
+ wallet: CheckoutWalletSelectUiState | null;
3354
3749
  amount: OndoBuyAmountUiState;
3355
3750
  review: OndoBuyReviewUiState;
3356
3751
  /** The asset panel. Read-only, so it raises no events. */
@@ -3376,7 +3771,7 @@ type OndoBuyCheckoutUiState = {
3376
3771
  * tags must stay globally unique, which is why the edit events are
3377
3772
  * `ON_EDIT_WALLET` and `ON_EDIT_AMOUNT` rather than a shared `ON_EDIT`.
3378
3773
  */
3379
- type OndoBuyCheckoutUiEvent = OndoWalletSelectUiEvent | OndoBuyAmountUiEvent | OndoBuyReviewUiEvent | OndoOrderConfirmedUiEvent;
3774
+ type OndoBuyCheckoutUiEvent = CheckoutWalletSelectUiEvent | OndoBuyAmountUiEvent | OndoBuyReviewUiEvent | OndoOrderConfirmedUiEvent;
3380
3775
  /**
3381
3776
  * The dialog that closes the Ondo checkout, once the swap is mined.
3382
3777
  *
@@ -3386,7 +3781,7 @@ type OndoBuyCheckoutUiEvent = OndoWalletSelectUiEvent | OndoBuyAmountUiEvent | O
3386
3781
  */
3387
3782
  type OndoOrderConfirmedUiState = {
3388
3783
  type: 'hidden';
3389
- } | {
3784
+ } | ({
3390
3785
  type: 'visible';
3391
3786
  /**
3392
3787
  * What was bought.
@@ -3402,14 +3797,7 @@ type OndoOrderConfirmedUiState = {
3402
3797
  totalCost: FormattedAmountAssetUi;
3403
3798
  /** Price of one whole token at the time of the fill, e.g. `$378.99`. */
3404
3799
  pricePerShare: FormattedAmountAssetUi;
3405
- /** The wallet the asset was delivered to. */
3406
- recipientAddress: ShortenedWalletAddress;
3407
- /**
3408
- * The settled swap on a block explorer. Always present: the dialog only
3409
- * exists once there is a mined transaction to point at.
3410
- */
3411
- txExplorerUrl: TxExplorerUrl;
3412
- };
3800
+ } & CheckoutReceiptUi);
3413
3801
  /**
3414
3802
  * Closing is the only thing the dialog raises.
3415
3803
  *
@@ -3438,7 +3826,17 @@ interface UseOndoBuyCheckoutViewModelOptions {
3438
3826
  * Fixed for the lifetime of the hook, as `offer` is.
3439
3827
  */
3440
3828
  chain: EthereumChain;
3441
- /** The host's wallets, and the lambdas that connect and disconnect one. */
3829
+ /**
3830
+ * The host's wallets, its connector for an external one if any, and
3831
+ * optionally the wallet it has already settled on.
3832
+ *
3833
+ * `wallets.preselected` is read **once**, to seed the step machine: set, the
3834
+ * flow has no wallet step and opens on the amount. A host that changes it
3835
+ * mid-flow is ignored, because the approval that follows the amount step is
3836
+ * granted by one specific wallet, and moving the flow onto another one under
3837
+ * it would strand that approval and build calldata the new wallet cannot
3838
+ * broadcast.
3839
+ */
3442
3840
  wallets: CheckoutWalletSelection;
3443
3841
  /**
3444
3842
  * Default `true`. When `false` nothing is fetched and no timer runs, for a
@@ -3477,12 +3875,12 @@ interface UseOndoBuyCheckoutViewModelResult {
3477
3875
  * wallet is the same kind of answer for as long as it lasts. See
3478
3876
  * {@link OndoCheckoutErrorReason}.
3479
3877
  *
3480
- * `offer` and `chain` are read as fixed for the lifetime of the hook. The step
3481
- * machine holds a committed quote and an approval granted on one chain for one
3482
- * order, so changing either in place would carry them onto an order they were
3483
- * never priced for. Remount instead: give the component holding this hook a
3484
- * `key` that changes with the offer and the chain, as {@link CheckoutContainer}
3485
- * documents. That discards the flow with its component instance, which is the
3878
+ * `offer` and `chain` are read as fixed for the lifetime of the hook, and so is
3879
+ * the wallet the flow opened on. The step machine holds a committed quote and
3880
+ * an approval granted on one chain by one wallet for one order, so changing any
3881
+ * of them in place would carry them onto an order they were never priced for.
3882
+ * Remount instead: give the component holding this hook a `key` that changes
3883
+ * with the offer and the chain, as {@link CheckoutContainer} documents. That discards the flow with its component instance, which is the
3486
3884
  * only reset that cannot land between an approval and the broadcast it was
3487
3885
  * granted for.
3488
3886
  */
@@ -3566,23 +3964,11 @@ type OndoSellAmountUiEvent = {
3566
3964
  /**
3567
3965
  * The state of the built sale a review step acts on.
3568
3966
  *
3569
- * `isRefreshing` rides on `CONTENT` rather than replacing it, so a refresh in
3570
- * flight never blanks the numbers the user is reading. A refresh that fails
3571
- * keeps them too, and reports why alongside - the previous sale may still
3572
- * be good, and a failed refresh is fixed by refreshing again.
3967
+ * `DISABLED` while switched off with no sale in hand. `isRefreshing` rides on
3968
+ * `CONTENT`, so a refresh in flight never blanks the numbers the user is
3969
+ * reading, and a refresh that fails keeps them and says why.
3573
3970
  */
3574
- type LoadOndoSellTransactionState = {
3575
- type: 'LOADING';
3576
- } | {
3577
- type: 'ERROR';
3578
- reason: OndoLoadErrorReason;
3579
- } | {
3580
- type: 'CONTENT';
3581
- transaction: OndoSellTransaction;
3582
- isRefreshing: boolean;
3583
- /** Why the last refresh failed; `null` when the sale is fresh. */
3584
- refreshError: OndoLoadErrorReason | null;
3585
- };
3971
+ type LoadOndoSellTransactionState = LoadFirmTransactionState<OndoSellTransaction, OndoLoadErrorReason>;
3586
3972
  interface UseOndoSellTransactionOptions {
3587
3973
  /**
3588
3974
  * The order to build, or `null` while there is not one yet - before the
@@ -3605,26 +3991,15 @@ interface UseOndoSellTransactionResult {
3605
3991
  refetch: () => void;
3606
3992
  }
3607
3993
  /**
3608
- * Holds the firm, expiring sale the sell review step places an order
3609
- * against, and rebuilds it on demand.
3610
- *
3611
- * **Never polls.** Building spends an attestation, so a new one is only ever
3612
- * obtained when the caller asks - on `refetch`, or on the first render if no
3613
- * `data` was supplied. That is also why an expired sale is left expired
3614
- * here: whether to replace it is the user's call, not a timer's.
3615
- *
3616
- * Disabled it fetches nothing and stays on whatever state it opened with. That
3617
- * is `LOADING` and not an empty `CONTENT` because there is no empty
3618
- * sale: firm calldata for an order that does not exist is not
3619
- * representable. A caller that switches this hook off should switch its own
3620
- * rendering off with it - which is what the review step does, since a step
3621
- * that is not active is `incomplete` and never reads this state at all.
3994
+ * Holds the firm, expiring sale the sell review step places an order against,
3995
+ * and rebuilds it on demand. **Never polls**: each build spends an
3996
+ * attestation.
3622
3997
  *
3623
3998
  * The sell half of the pair `useOndoBuyTransaction` opens - see there for why
3624
- * the two are not one hook. What differs is entirely in what `CONTENT` carries:
3625
- * an {@link OndoSellTransaction} publishes an expected outcome and a floor
3626
- * beneath it rather than one attested quantity, and the review step renders
3627
- * both.
3999
+ * the two are not one hook. What differs is entirely in what `CONTENT`
4000
+ * carries: an {@link OndoSellTransaction} publishes an expected outcome and a
4001
+ * floor beneath it rather than one attested quantity, and the review step
4002
+ * renders both.
3628
4003
  */
3629
4004
  declare function useOndoSellTransaction(options: UseOndoSellTransactionOptions): UseOndoSellTransactionResult;
3630
4005
 
@@ -3684,7 +4059,7 @@ type OndoSellReviewUiState = {
3684
4059
  * is what the order is expected to fill at.
3685
4060
  */
3686
4061
  pricePerShare: FormattedAmountAssetUi;
3687
- quote: OndoSellQuoteStatusUi;
4062
+ quote: OndoQuoteStatusUi;
3688
4063
  placeOrderCta: CheckoutCtaUi;
3689
4064
  /** A failure from placing the order, distinct from a quote problem. */
3690
4065
  error: string | null;
@@ -3717,33 +4092,6 @@ type OndoSellOutcomeUi = {
3717
4092
  */
3718
4093
  fee: FormattedAmountAssetUi | null;
3719
4094
  };
3720
- /**
3721
- * Whether the shown numbers can still be traded on.
3722
- *
3723
- * A quote is only good for a few seconds, so this drives the line above the CTA
3724
- * and whether the CTA can be pressed at all. `refresh-failed` is its own arm
3725
- * rather than folding into the step's `error`, because the remedy differs: a
3726
- * failed refresh is fixed by refreshing again, a failed order is not.
3727
- */
3728
- type OndoSellQuoteStatusUi =
3729
- /** Still good. `expiresInLabel` is the countdown copy, already formatted. */
3730
- {
3731
- type: 'valid';
3732
- expiresInLabel: string;
3733
- }
3734
- /** A refresh is in flight; the previous numbers are still on screen. */
3735
- | {
3736
- type: 'refreshing';
3737
- }
3738
- /** Too old to trade on. The user must refresh before placing the order. */
3739
- | {
3740
- type: 'expired';
3741
- }
3742
- /** The refresh failed. `message` says why. */
3743
- | {
3744
- type: 'refresh-failed';
3745
- message: string;
3746
- };
3747
4095
  type OndoSellReviewUiEvent = {
3748
4096
  type: 'ON_REFRESH_SELL_QUOTE';
3749
4097
  }
@@ -3779,7 +4127,7 @@ type OndoSellCheckoutUiState = {
3779
4127
  * two-step flow numbered `1, 2` and a three-step flow numbered `1, 2, 3`
3780
4128
  * cannot disagree. A boolean beside a non-null state would have let them.
3781
4129
  */
3782
- wallet: OndoWalletSelectUiState | null;
4130
+ wallet: CheckoutWalletSelectUiState | null;
3783
4131
  amount: OndoSellAmountUiState;
3784
4132
  review: OndoSellReviewUiState;
3785
4133
  /** The asset panel. Read-only, so it raises no events. */
@@ -3807,7 +4155,7 @@ type OndoSellCheckoutUiState = {
3807
4155
  * separate, and a shared tag would make one product's event dispatch into the
3808
4156
  * other's handler in any host that composed both.
3809
4157
  */
3810
- type OndoSellCheckoutUiEvent = OndoWalletSelectUiEvent | OndoSellAmountUiEvent | OndoSellReviewUiEvent | OndoSellOrderConfirmedUiEvent;
4158
+ type OndoSellCheckoutUiEvent = CheckoutWalletSelectUiEvent | OndoSellAmountUiEvent | OndoSellReviewUiEvent | OndoSellOrderConfirmedUiEvent;
3811
4159
  /**
3812
4160
  * The dialog that closes the Ondo sell checkout, once the swap is mined.
3813
4161
  *
@@ -3817,7 +4165,7 @@ type OndoSellCheckoutUiEvent = OndoWalletSelectUiEvent | OndoSellAmountUiEvent |
3817
4165
  */
3818
4166
  type OndoSellOrderConfirmedUiState = {
3819
4167
  type: 'hidden';
3820
- } | {
4168
+ } | ({
3821
4169
  type: 'visible';
3822
4170
  /**
3823
4171
  * What was sold.
@@ -3842,14 +4190,7 @@ type OndoSellOrderConfirmedUiState = {
3842
4190
  proceedsSymbol: AssetSymbol;
3843
4191
  /** Price of one whole token at the time of the fill, e.g. `$378.99`. */
3844
4192
  pricePerShare: FormattedAmountAssetUi;
3845
- /** The wallet the proceeds were delivered to. */
3846
- recipientAddress: ShortenedWalletAddress;
3847
- /**
3848
- * The settled swap on a block explorer. Always present: the dialog only
3849
- * exists once there is a mined transaction to point at.
3850
- */
3851
- txExplorerUrl: TxExplorerUrl;
3852
- };
4193
+ } & CheckoutReceiptUi);
3853
4194
  /**
3854
4195
  * Closing is the only thing the dialog raises.
3855
4196
  *
@@ -3879,7 +4220,7 @@ interface UseOndoSellCheckoutViewModelOptions {
3879
4220
  */
3880
4221
  chain: EthereumChain;
3881
4222
  /**
3882
- * The host's wallets, the lambdas that connect and disconnect one, and
4223
+ * The host's wallets, its connector for an external one if any, and
3883
4224
  * optionally the wallet it has already settled on.
3884
4225
  *
3885
4226
  * `wallets.preselected` is read **once**, to seed the step machine. A host
@@ -3944,6 +4285,7 @@ declare function useOndoSellCheckoutViewModel({ offer, chain, wallets, enabled,
3944
4285
  /**
3945
4286
  * The state of the indicative-price poll.
3946
4287
  *
4288
+ * - `DISABLED`: switched off with no price in hand, so none is coming.
3947
4289
  * - `LOADING`: no price yet (initial, or the provider is still initializing).
3948
4290
  * - `ERROR`: no price could be fetched at all.
3949
4291
  * - `CONTENT`: a price is in hand; `isRefreshing` says whether a newer one is
@@ -3955,6 +4297,8 @@ declare function useOndoSellCheckoutViewModel({ offer, chain, wallets, enabled,
3955
4297
  * when the UI has nothing to show.
3956
4298
  */
3957
4299
  type LoadOndoPriceState = {
4300
+ type: 'DISABLED';
4301
+ } | {
3958
4302
  type: 'LOADING';
3959
4303
  } | {
3960
4304
  type: 'ERROR';
@@ -4001,15 +4345,12 @@ interface UseOndoPriceResult {
4001
4345
  * - committing a fillable quote is `coinlist.ondo.prepareBuy` or
4002
4346
  * `coinlist.ondo.prepareSell`, whichever way the trade runs.
4003
4347
  *
4004
- * Disabled (or before the provider is ready) it neither fetches nor holds a
4005
- * timer, and stays on whatever state it opened with - `LOADING`, or the `data`
4006
- * seed - rather than reporting an error.
4007
- *
4008
- * That is `LOADING` and not an empty `CONTENT` because there is no empty price:
4009
- * a hook whose content is a list can fall back to `[]` the way
4010
- * `useOptionAddresses` does, and one whose content is a number cannot. A caller
4011
- * that switches this hook off should switch its own rendering off with it,
4012
- * rather than read `LOADING` as "a price is coming".
4348
+ * Disabled it neither fetches nor holds a timer. With no price in hand it
4349
+ * reports `DISABLED` - not `LOADING`, since nothing is coming, and not an
4350
+ * empty `CONTENT`, since there is no empty price. A price already in hand (the
4351
+ * `data` seed, or an earlier tick) survives being switched off. Before the
4352
+ * provider is ready it is `LOADING`: the read is coming, it just cannot leave
4353
+ * yet.
4013
4354
  *
4014
4355
  * A `data` price opens the state instead of `LOADING` and is otherwise left to
4015
4356
  * the poll: the first tick fires as it always does, and only replaces the seed
@@ -4029,6 +4370,8 @@ declare function useOndoPrice(options: UseOndoPriceOptions): UseOndoPriceResult;
4029
4370
  * unknown may not.
4030
4371
  */
4031
4372
  type LoadOndoTradingStatusState = {
4373
+ type: 'DISABLED';
4374
+ } | {
4032
4375
  type: 'LOADING';
4033
4376
  } | {
4034
4377
  type: 'ERROR';
@@ -4039,8 +4382,8 @@ type LoadOndoTradingStatusState = {
4039
4382
  };
4040
4383
  /**
4041
4384
  * Whether the market is *known* to be closed for this side: the one reading of
4042
- * the poll a caller may block an order on. `LOADING` and `ERROR` are unknown,
4043
- * and unknown never blocks.
4385
+ * the poll a caller may block an order on. `DISABLED`, `LOADING` and `ERROR`
4386
+ * are unknown, and unknown never blocks.
4044
4387
  */
4045
4388
  declare function isNotTradable(state: LoadOndoTradingStatusState): boolean;
4046
4389
  interface UseOndoTradingStatusOptions {
@@ -4083,94 +4426,30 @@ interface UseOndoTradingStatusResult {
4083
4426
  * the poll: the first tick fires as it always does, and only replaces the seed
4084
4427
  * once it has a status of its own.
4085
4428
  *
4086
- * Disabled it neither fetches nor holds a timer, and stays on whatever state it
4087
- * opened with. That is `LOADING` and not an empty `CONTENT` because there is no
4088
- * empty market status - and an invented one would be worse than none, since
4089
- * `CONTENT` here is what a caller is allowed to block an order on. A caller
4090
- * that switches this hook off should switch its own rendering off with it.
4429
+ * Disabled it neither fetches nor holds a timer. With no status in hand it
4430
+ * reports `DISABLED`, not an empty `CONTENT`: there is no empty market status,
4431
+ * and an invented one would be worse than none, since `CONTENT` here is what a
4432
+ * caller is allowed to block an order on. A status already in hand survives
4433
+ * being switched off.
4091
4434
  */
4092
4435
  declare function useOndoTradingStatus(options: UseOndoTradingStatusOptions): UseOndoTradingStatusResult;
4093
4436
 
4094
4437
  /**
4095
- * Step 2 of the Superstate checkout: how much to spend, and which asset to
4096
- * spend.
4438
+ * The state of the swap's output-token read.
4097
4439
  *
4098
- * Nothing here touches the chain. Unlike Ondo's amount step, which approves and
4099
- * commits a quote, this one only validates locally and hands the amount up — a
4100
- * Superstate swap approves and executes together on the review step. Hence a
4101
- * plain `confirmEnabled` rather than a `CheckoutCtaUi` with loading copy: there
4102
- * is no phase to report.
4103
- */
4104
- type SuperstateAmountUiState = {
4105
- type: 'incomplete';
4106
- } | {
4107
- type: 'active';
4108
- /**
4109
- * Exactly what the user has typed, not a parsed number: the field is
4110
- * mid-edit, and `'1.'` is a legal thing to be holding.
4111
- */
4112
- amountInput: string;
4113
- /** The wallet the funds come from, per step 1. */
4114
- walletAddress: ShortenedWalletAddress;
4115
- /**
4116
- * Every supported input asset, in display order, whether or not the user
4117
- * holds any. One entry renders as a plain card, two or more as a picker.
4118
- */
4119
- inputAssets: CheckoutSelectableInputAssetUi[];
4120
- confirmEnabled: boolean;
4121
- /** Validation copy, e.g. `Amount must be greater than 0.` */
4122
- error: string | null;
4123
- } | {
4124
- type: 'complete';
4125
- inputAsset: CheckoutAssetUi;
4126
- /**
4127
- * What the user is spending, as the field asked for it: dollars, e.g.
4128
- * `$1,000.00`. The Superstate field is dollar-denominated, which is why
4129
- * this is prefixed rather than suffixed with a symbol.
4130
- */
4131
- amountFormatted: FormattedAmountAssetUi;
4132
- /**
4133
- * The same figure in the asset actually being paid, e.g. `1,000.00 USDC`.
4134
- *
4135
- * Both are shown because the two are only equal while the funding asset
4136
- * is a dollar stablecoin — the day a non-dollar one is fundable, the
4137
- * summary would otherwise silently claim it was.
4138
- */
4139
- inputAmountFormatted: FormattedAmountAssetUi;
4140
- };
4141
- type SuperstateAmountUiEvent = {
4142
- type: 'ON_AMOUNT_CHANGE';
4143
- value: string;
4144
- } | {
4145
- type: 'ON_MAX_AMOUNT_CLICK';
4146
- } | {
4147
- type: 'ON_SELECT_PAY_WITH';
4148
- value: AssetSymbol;
4149
- }
4150
- /**
4151
- * Named for what it does rather than for the step: confirming here previews
4152
- * the order on step 3, it does not place or pay for anything.
4440
+ * - `DISABLED`: switched off before an answer arrived.
4441
+ * - `LOADING`: no answer yet (initial, a re-read after the contract or chain
4442
+ * changed, or the provider still initializing).
4443
+ * - `ERROR`: the read failed.
4444
+ * - `CONTENT`: the output token was read.
4153
4445
  */
4154
- | {
4155
- type: 'ON_PREVIEW_ORDER';
4446
+ type LoadSwapOutputTokenState = {
4447
+ type: 'DISABLED';
4156
4448
  } | {
4157
- type: 'ON_EDIT_AMOUNT';
4158
- };
4159
-
4160
- /**
4161
- * The state of the swap's output-token fetch.
4162
- *
4163
- * - `LOADING`: no result yet (initial, or provider still initializing).
4164
- * - `ERROR`: the fetch failed.
4165
- * - `CONTENT`: the output token was fetched successfully.
4166
- *
4167
- * A stale `CONTENT`/`ERROR` is preserved while a re-fetch (e.g. after a chain
4168
- * change) is in flight, rather than flipping back to `LOADING`.
4169
- */
4170
- type SwapOutputTokenState = {
4171
4449
  type: 'LOADING';
4172
4450
  } | {
4173
4451
  type: 'ERROR';
4452
+ reason: LoadErrorReason;
4174
4453
  } | {
4175
4454
  type: 'CONTENT';
4176
4455
  outputToken: Erc20Asset;
@@ -4183,12 +4462,12 @@ interface UseSwapOutputTokenOptions {
4183
4462
  enabled: boolean;
4184
4463
  }
4185
4464
  interface UseSwapOutputTokenResult {
4186
- outputTokenState: SwapOutputTokenState;
4465
+ state: LoadSwapOutputTokenState;
4187
4466
  /**
4188
- * Runs the fetch again after a failure.
4467
+ * Runs the read again after a failure.
4189
4468
  *
4190
4469
  * The output token is read once and never polled, so `ERROR` is otherwise
4191
- * terminal until a dependency changes — and without it there is no quote,
4470
+ * terminal until a dependency changes - and without it there is no quote,
4192
4471
  * no price and no minimum received, which is why the Superstate checkout
4193
4472
  * surfaces it as a whole-flow failure with a retry rather than as one
4194
4473
  * unavailable corner.
@@ -4196,11 +4475,11 @@ interface UseSwapOutputTokenResult {
4196
4475
  refetch: () => void;
4197
4476
  }
4198
4477
  /**
4199
- * Fetches the ERC-20 output token a swap contract pays out. Re-fetches when the
4478
+ * Reads the ERC-20 output token a swap contract pays out. Reads again when the
4200
4479
  * contract or chain changes, and once when `enabled` flips to true.
4201
4480
  *
4202
- * The fetch runs once (no polling); a failure resolves to `ERROR` and is not
4203
- * retried until a dependency changes.
4481
+ * The read runs once (no polling); a failure resolves to `ERROR` and is not
4482
+ * retried until a dependency changes or `refetch` is called.
4204
4483
  */
4205
4484
  declare function useSwapOutputToken(options: UseSwapOutputTokenOptions): UseSwapOutputTokenResult;
4206
4485
 
@@ -4221,21 +4500,45 @@ interface UseSwapQuoteOptions {
4221
4500
  /** When false, the hook neither fetches nor polls. */
4222
4501
  enabled: boolean;
4223
4502
  }
4224
- interface UseSwapQuoteResult {
4225
- /** The latest quote, or `null` until the first successful fetch. */
4226
- quote: SwapQuote | null;
4227
- /** True until the first quote arrives; false while the hook is disabled. */
4228
- isLoading: boolean;
4229
- /** True while a background poll refreshes an existing quote. */
4503
+ /**
4504
+ * The state of the quote poll.
4505
+ *
4506
+ * - `DISABLED`: switched off with no quote in hand, so none is coming.
4507
+ * - `LOADING`: no quote yet - the first read is in flight, the provider is
4508
+ * still initializing, or the output token's decimals are not known yet.
4509
+ * - `ERROR`: no quote could be read at all.
4510
+ * - `CONTENT`: a quote is in hand; `isRefreshing` says whether a newer one is
4511
+ * on the way.
4512
+ *
4513
+ * A tick that fails with a quote already in hand stays `CONTENT`, so `ERROR`
4514
+ * means "never got one". A quote also survives a change of amount until the
4515
+ * new one lands, with `isRefreshing` set: the review step compares the quote
4516
+ * against the amount, and that flag is what tells it the mismatch is a reprice
4517
+ * in flight rather than a quote for the wrong order.
4518
+ */
4519
+ type LoadSwapQuoteState = {
4520
+ type: 'DISABLED';
4521
+ } | {
4522
+ type: 'LOADING';
4523
+ } | {
4524
+ type: 'ERROR';
4525
+ reason: LoadErrorReason;
4526
+ } | {
4527
+ type: 'CONTENT';
4528
+ quote: SwapQuote;
4230
4529
  isRefreshing: boolean;
4530
+ };
4531
+ interface UseSwapQuoteResult {
4532
+ state: LoadSwapQuoteState;
4231
4533
  }
4232
4534
  /**
4233
4535
  * Polls a read-only swap quote for `inputAmount` of `inputTokenAddress` against
4234
4536
  * the given swap contract, refreshing every `pollIntervalMs`.
4235
4537
  *
4236
- * A failed fetch is swallowed: the last quote stays visible and the next poll
4237
- * tick retries. Quoting is skipped while `outputTokenDecimals` is `null` or
4238
- * `enabled` is false, and until the CoinList provider finishes initializing.
4538
+ * A failed tick with a quote in hand keeps it and the next tick retries.
4539
+ * Quoting waits while `outputTokenDecimals` is `null` and until the CoinList
4540
+ * provider finishes initializing. Disabled it neither fetches nor holds a
4541
+ * timer; a quote already in hand survives being switched off.
4239
4542
  */
4240
4543
  declare function useSwapQuote(options: UseSwapQuoteOptions): UseSwapQuoteResult;
4241
4544
 
@@ -4398,10 +4701,11 @@ type SuperstateWalletUiState = {
4398
4701
  type: 'active';
4399
4702
  /** The user's CoinList wallets. Empty when they have none. */
4400
4703
  embeddedWallets: CheckoutEmbeddedWalletUi[];
4401
- /** `null` until an external wallet is connected. The row still renders. */
4402
- externalWallet: CheckoutWalletUi | null;
4403
- /** Whether the connected external wallet may be disconnected here. */
4404
- canDisconnect: boolean;
4704
+ /**
4705
+ * The external-wallet row: absent when the host offers no connector,
4706
+ * an invitation to connect one, or the connected wallet.
4707
+ */
4708
+ externalWallet: CheckoutExternalWalletUi;
4405
4709
  /**
4406
4710
  * Confirming runs the authorization, so this reports its phase as
4407
4711
  * loading copy — `Sign the message in your wallet…` and the rest.
@@ -4445,7 +4749,7 @@ type SuperstateWalletUiEvent = {
4445
4749
  type SuperstateSwapCheckoutUiState = {
4446
4750
  type: 'content';
4447
4751
  wallet: SuperstateWalletUiState;
4448
- amount: SuperstateAmountUiState;
4752
+ amount: CheckoutAmountUiState;
4449
4753
  review: SuperstateReviewUiState;
4450
4754
  /** The sale panel. Read-only, so it raises no events. */
4451
4755
  sidebar: SuperstateSidebarUiState;
@@ -4480,7 +4784,7 @@ type SuperstateSwapLoadErrorReason =
4480
4784
  * edit events are `ON_EDIT_WALLET` and `ON_EDIT_AMOUNT` rather than a shared
4481
4785
  * `ON_EDIT`.
4482
4786
  */
4483
- type SuperstateSwapCheckoutUiEvent = SuperstateWalletUiEvent | SuperstateAmountUiEvent | SuperstateReviewUiEvent | SuperstateOrderConfirmedUiEvent | SuperstateSwapCheckoutRetryUiEvent;
4787
+ type SuperstateSwapCheckoutUiEvent = SuperstateWalletUiEvent | CheckoutAmountUiEvent | SuperstateReviewUiEvent | SuperstateOrderConfirmedUiEvent | SuperstateSwapCheckoutRetryUiEvent;
4484
4788
  /**
4485
4789
  * Retrying the load behind the flow-level `error` arm.
4486
4790
  *
@@ -4500,7 +4804,7 @@ type SuperstateSwapCheckoutRetryUiEvent = {
4500
4804
  */
4501
4805
  type SuperstateOrderConfirmedUiState = {
4502
4806
  type: 'hidden';
4503
- } | {
4807
+ } | ({
4504
4808
  type: 'visible';
4505
4809
  /** What was bought. */
4506
4810
  asset: CheckoutAssetUi;
@@ -4524,14 +4828,7 @@ type SuperstateOrderConfirmedUiState = {
4524
4828
  * `outputAmount`, so `outputAmountConfirmed` covers it too.
4525
4829
  */
4526
4830
  pricePerShare: FormattedAmountAssetUi;
4527
- /** The wallet the asset was delivered to. */
4528
- recipientAddress: ShortenedWalletAddress;
4529
- /**
4530
- * The settled swap on a block explorer. Always present: the dialog only
4531
- * exists once there is a mined transaction to point at.
4532
- */
4533
- txExplorerUrl: TxExplorerUrl;
4534
- };
4831
+ } & CheckoutReceiptUi);
4535
4832
  /**
4536
4833
  * Closing is the only thing the dialog raises.
4537
4834
  *
@@ -4559,7 +4856,17 @@ interface UseSuperstateSwapCheckoutViewModelOptions {
4559
4856
  * Fixed for the lifetime of the hook, as `offer` is.
4560
4857
  */
4561
4858
  chain: EthereumChain;
4562
- /** The host's wallets, and the lambdas that connect and disconnect one. */
4859
+ /**
4860
+ * The host's wallets, its connector for an external one if any, and
4861
+ * optionally the wallet it has already settled on.
4862
+ *
4863
+ * `wallets.preselected` never skips the wallet step here: that step
4864
+ * allow-lists the wallet on-chain, which no preselection can stand in for.
4865
+ * It pre-selects the wallet's row instead, so the user confirms and
4866
+ * allow-lists it rather than picking it again. A preselected wallet that
4867
+ * is neither one of `embedded` nor the connected `external` has no row to
4868
+ * select, and the step opens with nothing picked.
4869
+ */
4563
4870
  wallets: CheckoutWalletSelection;
4564
4871
  /**
4565
4872
  * Default `true`. When `false` nothing is fetched and no timer runs, for a
@@ -4658,11 +4965,14 @@ declare function useCentrifugeClaim(): UseCentrifugeClaimResult;
4658
4965
  * failures: a flaky tick must not make a claimable position vanish under the
4659
4966
  * user. A read that has never answered is absent, not zero. `ERROR` is
4660
4967
  * reserved for the case where nothing answered at all, so a screen has
4661
- * nothing to show but a retry.
4968
+ * nothing to show but a retry. `DISABLED` means the hook is switched off and
4969
+ * holds nothing.
4662
4970
  *
4663
4971
  * @alpha
4664
4972
  */
4665
- type LoadCentrifugeVaultPositionsState = {
4973
+ type LoadCentrifugeClaimPositionsState = {
4974
+ type: 'DISABLED';
4975
+ } | {
4666
4976
  type: 'LOADING';
4667
4977
  } | {
4668
4978
  type: 'ERROR';
@@ -4672,9 +4982,9 @@ type LoadCentrifugeVaultPositionsState = {
4672
4982
  legs: CentrifugeVaultLeg[];
4673
4983
  };
4674
4984
  /** @alpha */
4675
- interface UseCentrifugeVaultPositionsOptions {
4676
- /** The vaults to read, one per chain the offer runs on. */
4677
- vaults: CentrifugeVaultRef[];
4985
+ interface UseCentrifugeClaimPositionsOptions {
4986
+ /** The resolved vaults to read, one per chain the offer runs on. */
4987
+ vaults: CentrifugeVault[];
4678
4988
  /** The wallets to read them for, in display order. */
4679
4989
  walletAddresses: EvmWalletAddress[];
4680
4990
  /**
@@ -4684,19 +4994,18 @@ interface UseCentrifugeVaultPositionsOptions {
4684
4994
  pollIntervalMs?: number;
4685
4995
  /**
4686
4996
  * Reads pre-fetched on the server. When provided, the hook opens on them
4687
- * and skips the first fetch; polling and {@link UseCentrifugeVaultPositionsResult.refetch}
4997
+ * and skips the first fetch; polling and {@link UseCentrifugeClaimPositionsResult.refetch}
4688
4998
  * still fetch.
4689
4999
  */
4690
5000
  data?: CentrifugeVaultLeg[];
4691
5001
  /**
4692
- * Default `true`. When `false`: no requests, no timers, and an empty
4693
- * `CONTENT`.
5002
+ * Default `true`. When `false`: no requests, no timers, and `DISABLED`.
4694
5003
  */
4695
5004
  enabled?: boolean;
4696
5005
  }
4697
5006
  /** @alpha */
4698
- interface UseCentrifugeVaultPositionsResult {
4699
- state: LoadCentrifugeVaultPositionsState;
5007
+ interface UseCentrifugeClaimPositionsResult {
5008
+ state: LoadCentrifugeClaimPositionsState;
4700
5009
  /**
4701
5010
  * Reads every position again: the retry after an `ERROR`, and what a claim
4702
5011
  * calls once it mined so the claimed amount leaves the screen.
@@ -4707,9 +5016,10 @@ interface UseCentrifugeVaultPositionsResult {
4707
5016
  * Reads, and keeps reading, every wallet's position on every vault, on both
4708
5017
  * sides of the trade.
4709
5018
  *
4710
- * A fill lands on the fund's schedule with no signal, so polling is the only
4711
- * way a pending position is seen turning claimable. Each read is fetched once
4712
- * when the inputs change, when {@link UseCentrifugeVaultPositionsResult.refetch}
5019
+ * Positions are read from the vault proxy over RPC. A fill lands on the
5020
+ * fund's schedule with no signal, so polling is the only way a pending
5021
+ * position is seen turning claimable. A read is fetched once
5022
+ * when the inputs change, when {@link UseCentrifugeClaimPositionsResult.refetch}
4713
5023
  * is called and when the page becomes visible again. Between those, only the
4714
5024
  * reads with something still pending are polled - a position with nothing
4715
5025
  * pending cannot change on its own - and only while the page is visible.
@@ -4720,87 +5030,7 @@ interface UseCentrifugeVaultPositionsResult {
4720
5030
  *
4721
5031
  * @alpha
4722
5032
  */
4723
- declare function useCentrifugeVaultPositions(options: UseCentrifugeVaultPositionsOptions): UseCentrifugeVaultPositionsResult;
4724
-
4725
- type LoadOfferDetailsReason = 'not-authenticated' | 'generic-error';
4726
- type LoadOfferDetailsState = {
4727
- type: 'LOADING';
4728
- } | {
4729
- type: 'ERROR';
4730
- reason: LoadOfferDetailsReason;
4731
- } | {
4732
- type: 'CONTENT';
4733
- offerDetail: OfferDetail;
4734
- };
4735
- interface UseOfferDetailsOptions {
4736
- /**
4737
- * Offer detail pre-fetched on the server (e.g. via `CoinListServer#offers.get()`).
4738
- * When provided, the hook uses this data as-is and skips the client-side fetch entirely.
4739
- */
4740
- data?: OfferDetail;
4741
- /**
4742
- * When `false`, the hook sends no request. A seeded or already-fetched
4743
- * `CONTENT` survives; otherwise the hook stays `LOADING`. Defaults to `true`.
4744
- */
4745
- enabled?: boolean;
4746
- }
4747
- interface UseOfferDetailsResult {
4748
- offerDetailsState: LoadOfferDetailsState;
4749
- }
4750
- /**
4751
- * Loads CoinList offer details for a given offer id and exposes a UI-friendly state.
4752
- *
4753
- * Pass `data` (pre-fetched server-side) to use that data as-is and skip
4754
- * the client-side fetch entirely. Pass `enabled: false` to skip the fetch
4755
- * when the hook must be called but the data is not needed yet.
4756
- *
4757
- * Returns `LOADING` while CoinList is initializing or while details are being fetched.
4758
- * Returns `CONTENT` with the offer when `offers.get()` succeeds.
4759
- * Returns `ERROR` with:
4760
- * - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}
4761
- * - `generic-error` for any other failure
4762
- */
4763
- declare function useOfferDetails(offerId: OfferId, options?: UseOfferDetailsOptions): UseOfferDetailsResult;
4764
-
4765
- type LoadOffersReason = 'not-authenticated' | 'generic-error';
4766
- type LoadOffersState = {
4767
- type: 'LOADING';
4768
- } | {
4769
- type: 'ERROR';
4770
- reason: LoadOffersReason;
4771
- } | {
4772
- type: 'CONTENT';
4773
- offers: Offer[];
4774
- };
4775
- interface UseOffersOptions {
4776
- /**
4777
- * Offers pre-fetched on the server (e.g. via `CoinListServer#offers.list()`).
4778
- * When provided, the hook uses this data as-is and skips the client-side fetch entirely.
4779
- */
4780
- data?: Offer[];
4781
- /**
4782
- * When `false`, the hook sends no request. A seeded or already-fetched
4783
- * `CONTENT` survives; otherwise the hook stays `LOADING`. Defaults to `true`.
4784
- */
4785
- enabled?: boolean;
4786
- }
4787
- interface UseOffersResult {
4788
- offersState: LoadOffersState;
4789
- }
4790
- /**
4791
- * Loads all CoinList offers for the current user and exposes a UI-friendly state.
4792
- *
4793
- * Pass `data` (pre-fetched server-side) to use that data as-is and skip
4794
- * the client-side fetch entirely. Pass `enabled: false` to skip the fetch
4795
- * when the hook must be called but the data is not needed yet.
4796
- *
4797
- * Returns `LOADING` while CoinList is initializing or while offers are being fetched.
4798
- * Returns `CONTENT` with all offers when `fetchOffers()` succeeds.
4799
- * Returns `ERROR` with:
4800
- * - `not-authenticated` when fetching fails with {@link NotAuthenticatedError}
4801
- * - `generic-error` for any other failure
4802
- */
4803
- declare function useOffers(options?: UseOffersOptions): UseOffersResult;
5033
+ declare function useCentrifugeClaimPositions(options: UseCentrifugeClaimPositionsOptions): UseCentrifugeClaimPositionsResult;
4804
5034
 
4805
5035
  /**
4806
5036
  * A display-ready connect-wallet error: the core flow's machine-readable code
@@ -5091,120 +5321,6 @@ interface UseRequirementsChecklistViewModelResult {
5091
5321
  */
5092
5322
  declare function useRequirementsChecklistViewModel(options: UseRequirementsChecklistViewModelOptions): UseRequirementsChecklistViewModelResult;
5093
5323
 
5094
- /**
5095
- * The state of one vault's status poll.
5096
- *
5097
- * Stale-preserving: a failed tick with a status in hand keeps it, so a flaky
5098
- * read never reads as "vault halted". `ERROR` means the status is unknown -
5099
- * which is not the same as `CONTENT` carrying a blocked orderability, and
5100
- * callers must not conflate them. A vault that is *known* to be unorderable
5101
- * may block a request; one that is merely unknown may not.
5102
- *
5103
- * `below_minimum` never appears here: it needs an amount, which this
5104
- * endpoint is never given.
5105
- *
5106
- * @alpha
5107
- */
5108
- type LoadCentrifugeVaultStatusState = {
5109
- type: 'LOADING';
5110
- } | {
5111
- type: 'ERROR';
5112
- reason: CentrifugeLoadErrorReason;
5113
- } | {
5114
- type: 'CONTENT';
5115
- status: CentrifugeVaultStatus;
5116
- };
5117
- /** @alpha */
5118
- interface UseCentrifugeVaultStatusesOptions {
5119
- /** The vaults to poll, typically one per chain an offer runs on. */
5120
- vaults: CentrifugeVaultRef[];
5121
- /** How often to refresh. Defaults to {@link CENTRIFUGE_POLL_INTERVAL_MS}. */
5122
- pollIntervalMs?: number;
5123
- /**
5124
- * Statuses the caller already holds, typically fetched server-side, each
5125
- * opening the state of the vault it names so a server-rendered panel needs
5126
- * no loading pass.
5127
- *
5128
- * They seed the first render only: the poll still fetches immediately. A
5129
- * vault that was orderable a minute ago can be unlinked now, so a seed
5130
- * that suppressed the first read would be answering "can I act right now"
5131
- * with whenever the page was rendered.
5132
- */
5133
- data?: CentrifugeVaultStatus[];
5134
- /** When false, the hook neither fetches nor polls. */
5135
- enabled: boolean;
5136
- }
5137
- /** @alpha */
5138
- interface UseCentrifugeVaultStatusesResult {
5139
- /** One entry per vault asked for, in the order asked. */
5140
- statuses: {
5141
- vault: CentrifugeVaultRef;
5142
- state: LoadCentrifugeVaultStatusState;
5143
- }[];
5144
- }
5145
- /**
5146
- * Polls whether each of several Centrifuge vaults can be acted on right now,
5147
- * independent of any wallet or amount.
5148
- *
5149
- * Free to poll - it spends no attestation. Centrifuge announces none of the
5150
- * changes this reports, so the poll is the only way a screen notices a vault
5151
- * halting under it. Each vault is read independently on one shared timer, so
5152
- * one failing chain never holds back another.
5153
- *
5154
- * A seeded status opens its vault's state instead of `LOADING` and is
5155
- * otherwise left to the poll: the first tick fires as it always does, and
5156
- * only replaces the seed once it has a status of its own.
5157
- *
5158
- * Disabled it neither fetches nor holds a timer, and each vault stays on
5159
- * whatever state it held. That is `LOADING` and not an empty `CONTENT`
5160
- * because there is no empty vault status - and an invented one would be
5161
- * worse than none, since `CONTENT` here is what a caller is allowed to block
5162
- * on.
5163
- *
5164
- * @alpha
5165
- */
5166
- declare function useCentrifugeVaultStatuses(options: UseCentrifugeVaultStatusesOptions): UseCentrifugeVaultStatusesResult;
5167
-
5168
- /** @alpha */
5169
- interface UseCentrifugeVaultStatusOptions {
5170
- /** Share token symbol of the vault, e.g. `deJTRSY`. */
5171
- symbol: AssetSymbol;
5172
- chain: EthereumChain;
5173
- /** How often to refresh. Defaults to `CENTRIFUGE_POLL_INTERVAL_MS`. */
5174
- pollIntervalMs?: number;
5175
- /**
5176
- * A status the caller already holds, typically fetched server-side, used
5177
- * as the state the hook opens on so a server-rendered panel needs no
5178
- * loading pass.
5179
- *
5180
- * It seeds the first render only: the poll still fetches immediately. A
5181
- * vault that was orderable a minute ago can be unlinked now, so a seed
5182
- * that suppressed the first read would be answering "can I invest right
5183
- * now" with whenever the page was rendered.
5184
- */
5185
- data?: CentrifugeVaultStatus;
5186
- /** When false, the hook neither fetches nor polls. */
5187
- enabled: boolean;
5188
- }
5189
- /** @alpha */
5190
- interface UseCentrifugeVaultStatusResult {
5191
- state: LoadCentrifugeVaultStatusState;
5192
- }
5193
- /**
5194
- * Polls whether a Centrifuge vault can take a request at all right now,
5195
- * independent of any amount.
5196
- *
5197
- * Free to poll - it spends no attestation. Centrifuge announces none of the
5198
- * changes this reports, so the poll is the only way a checkout notices
5199
- * mid-order.
5200
- *
5201
- * The one-vault case of {@link useCentrifugeVaultStatuses}, which carries the
5202
- * seeding, stale-preserving and disabled semantics.
5203
- *
5204
- * @alpha
5205
- */
5206
- declare function useCentrifugeVaultStatus(options: UseCentrifugeVaultStatusOptions): UseCentrifugeVaultStatusResult;
5207
-
5208
5324
  interface UseErc20BalanceOptions {
5209
5325
  /**
5210
5326
  * The token to read, by contract address.
@@ -5215,26 +5331,47 @@ interface UseErc20BalanceOptions {
5215
5331
  * has one.
5216
5332
  */
5217
5333
  tokenAddress: EvmContractAddress | null;
5218
- owner: EvmWalletAddress;
5334
+ /**
5335
+ * The wallet whose balance is read. `null` when there is no wallet yet,
5336
+ * which reads nothing and holds `DISABLED`, exactly as `enabled: false`
5337
+ * does: there is no holding to wait for.
5338
+ */
5339
+ owner: EvmWalletAddress | null;
5219
5340
  chain: EthereumChain;
5220
5341
  /** How often to refresh. Defaults to {@link ERC20_BALANCE_POLL_INTERVAL_MS}. */
5221
5342
  pollIntervalMs?: number;
5222
5343
  /** When false, the hook neither fetches nor polls. */
5223
5344
  enabled: boolean;
5224
5345
  }
5346
+ /**
5347
+ * The state of one balance read.
5348
+ *
5349
+ * Every arm answers for the token, owner and chain currently named by the
5350
+ * options, and nothing else: from the moment any of them changes the state is
5351
+ * `LOADING` until the read for the new one lands. A balance carried across
5352
+ * that change would be a number read for something else, indistinguishable
5353
+ * from a fresh one.
5354
+ *
5355
+ * - `DISABLED`: switched off. No balance is held, for the same reason.
5356
+ * - `LOADING`: no read has settled for this request yet, or `tokenAddress` is
5357
+ * not known yet.
5358
+ * - `ERROR`: the last read failed. A failed read is not a zero balance, and an
5359
+ * order must not be sized against the one before it, so it is dropped.
5360
+ * - `CONTENT`: raw base units of the token.
5361
+ */
5362
+ type LoadErc20BalanceState = {
5363
+ type: 'DISABLED';
5364
+ } | {
5365
+ type: 'LOADING';
5366
+ } | {
5367
+ type: 'ERROR';
5368
+ reason: LoadErrorReason;
5369
+ } | {
5370
+ type: 'CONTENT';
5371
+ balance: bigint;
5372
+ };
5225
5373
  interface UseErc20BalanceResult {
5226
- /**
5227
- * Raw base units of the token currently named by the options, or `null`.
5228
- *
5229
- * `null` covers every state that is not a settled read of *this* request:
5230
- * before the first one settles, after one fails, while disabled, and from
5231
- * the moment the token, owner or chain changes until the read for the new
5232
- * one lands. A caller cannot tell those apart on purpose - none of them is a
5233
- * number to size an order against - and `isLoading` is what says whether to
5234
- * wait.
5235
- */
5236
- balance: bigint | null;
5237
- isLoading: boolean;
5374
+ state: LoadErc20BalanceState;
5238
5375
  }
5239
5376
  /**
5240
5377
  * Polls one wallet's balance of one ERC-20, named by contract address.
@@ -5248,15 +5385,18 @@ interface UseErc20BalanceResult {
5248
5385
  * each independently, which is a different job from following a single token
5249
5386
  * whose address may not be known yet.
5250
5387
  *
5251
- * A poll tick is skipped while the previous read is in flight, so a slow one
5252
- * cannot resolve last and overwrite a fresher balance. `isLoading` is true only
5253
- * until the first read settles; background polls do not toggle it. Disabled, or
5254
- * with no `tokenAddress`, it neither fetches nor holds a timer.
5388
+ * Disabled, with no `owner`, or with no `tokenAddress`, it neither fetches
5389
+ * nor holds a timer.
5255
5390
  */
5256
5391
  declare function useErc20Balance(options: UseErc20BalanceOptions): UseErc20BalanceResult;
5257
5392
 
5258
5393
  interface UseErc20TokenBalancesOptions {
5259
- address: EvmWalletAddress;
5394
+ /**
5395
+ * The wallet whose balances are read. `null` when there is no wallet yet -
5396
+ * a checkout step waiting on the wallet step - which reads nothing and holds
5397
+ * `DISABLED`, exactly as `enabled: false` does.
5398
+ */
5399
+ address: EvmWalletAddress | null;
5260
5400
  chain: EthereumChain;
5261
5401
  /** The assets to read balances for. */
5262
5402
  assets: NonEmptyArray<StablecoinSymbol>;
@@ -5268,29 +5408,47 @@ interface UseErc20TokenBalancesOptions {
5268
5408
  /** When false, the hook neither fetches nor polls. */
5269
5409
  enabled: boolean;
5270
5410
  }
5271
- interface UseErc20TokenBalancesResult {
5272
- /**
5273
- * Raw on-chain balances keyed by the requested assets. Each requested asset
5274
- * with a deployment on the chain has an entry once a fetch settles
5275
- * (`bigint` on success, `null` on a failed read). Assets the chain has no
5276
- * deployment for (e.g. USDT on Base Sepolia) are omitted entirely, so
5277
- * absence and failure stay tellable apart.
5278
- */
5411
+ /**
5412
+ * The state of the balance reads.
5413
+ *
5414
+ * Every arm answers for the address, chain and assets currently named by the
5415
+ * options: from the moment any of them changes the state is `LOADING` until
5416
+ * the reads for the new ones land, so one wallet's balances never stand in
5417
+ * for another's.
5418
+ *
5419
+ * - `DISABLED`: switched off. No balances are held.
5420
+ * - `LOADING`: no poll has settled for this request yet.
5421
+ * - `ERROR`: every read the last poll made failed, so there is no balance at
5422
+ * all to show.
5423
+ * - `CONTENT`: raw on-chain balances keyed by the requested assets. Each
5424
+ * requested asset with a deployment on the chain has an entry (`bigint` on
5425
+ * success, `null` on a failed read). Assets the chain has no deployment for
5426
+ * (e.g. USDT on Base Sepolia) are omitted entirely, so absence and failure
5427
+ * stay tellable apart.
5428
+ */
5429
+ type LoadErc20TokenBalancesState = {
5430
+ type: 'DISABLED';
5431
+ } | {
5432
+ type: 'LOADING';
5433
+ } | {
5434
+ type: 'ERROR';
5435
+ reason: LoadErrorReason;
5436
+ } | {
5437
+ type: 'CONTENT';
5279
5438
  balances: Map<StablecoinSymbol, bigint | null>;
5280
- isLoading: boolean;
5439
+ };
5440
+ interface UseErc20TokenBalancesResult {
5441
+ state: LoadErc20TokenBalancesState;
5281
5442
  }
5282
5443
  /**
5283
5444
  * Polls the raw ERC-20 balances of `assets` for `address`, refreshing every
5284
5445
  * `pollIntervalMs`. Each asset settles independently: a failed read maps to
5285
5446
  * `null` while the others still resolve, and an asset the chain has no
5286
5447
  * deployment for is omitted from the result rather than read at a fake
5287
- * address. A poll tick is skipped while the previous fetch is still in
5288
- * flight. `assets` is compared by contents, so passing an inline array does
5448
+ * address. `assets` is compared by contents, so passing an inline array does
5289
5449
  * not restart the poll.
5290
5450
  *
5291
- * `isLoading` is true only until the first poll settles; background polls do
5292
- * not toggle it. Disabled (or before the provider is ready) the hook does not
5293
- * fetch.
5451
+ * Disabled, or with no `address`, it neither fetches nor holds a timer.
5294
5452
  */
5295
5453
  declare function useErc20TokenBalances(options: UseErc20TokenBalancesOptions): UseErc20TokenBalancesResult;
5296
5454
 
@@ -5426,4 +5584,4 @@ declare class CoinListClientInitializationError extends Error {
5426
5584
  constructor(message?: string);
5427
5585
  }
5428
5586
 
5429
- export { type AuthState, type AuthorizeWalletParams, type BuyCentrifugeParams, type CentrifugeBuyAmountUiEvent, type CentrifugeBuyAmountUiState, type CentrifugeBuyCheckoutUiEvent, type CentrifugeBuyCheckoutUiState, type CentrifugeBuyError, type CentrifugeBuyPhase, type CentrifugeBuyPlacementError, type CentrifugeBuyPlacementPhase, type CentrifugeBuyPlacementResult, type CentrifugeBuyPreparationError, type CentrifugeBuyPreparationPhase, type CentrifugeBuyPreparationResult, type CentrifugeBuyResult, type CentrifugeBuyReviewUiEvent, type CentrifugeBuyReviewUiState, CentrifugeCheckoutErrorReason, type CentrifugeClaimActionUi, type CentrifugeClaimBlockedReasonUi, type CentrifugeClaimDialogUi, type CentrifugeClaimError, type CentrifugeClaimFailureUi, type CentrifugeClaimParams, type CentrifugeClaimPhase, type CentrifugeClaimProgressUi, type CentrifugeClaimResult, type CentrifugeClaimRowUi, type CentrifugeClaimState, type CentrifugeClaimStepUi, type CentrifugeLoadErrorReason, type CentrifugeOrderPlaced, type CentrifugeOrderPlacedUiEvent, type CentrifugeOrderPlacedUiState, type CentrifugeSidebarMinimumUi, type CentrifugeSidebarUiState, type CentrifugeVaultCheckoutConfig, type CentrifugeVaultClaimConfig, type CentrifugeVaultClaimUiEvent, type CentrifugeVaultClaimUiState, type CentrifugeVaultClaimed, type CentrifugeWalletSelectUiEvent, type CentrifugeWalletSelectUiState, ChecklistStatus, CheckoutAssetUi, type CheckoutConfig, type CheckoutConfigByOfferType, type CheckoutConfirmedWalletUi, CheckoutContainer, type CheckoutContainerProps, type CheckoutCtaUi, type CheckoutEmbeddedWalletUi, type CheckoutNetworkUi, type CheckoutSelectableInputAssetUi, type CheckoutStatusUi, type CheckoutWalletSelection, type CheckoutWalletTypeUi, type CheckoutWalletUi, type ClaimCentrifugeVaultParams, type ClaimConfig, type ClaimConfigByOfferType, ClaimContainer, type ClaimContainerProps, type ClaimExternalWalletUi, type ClientAuthNamespace, type ClientCentrifugeNamespace, type ClientCoinListTokenSaleNamespace, type ClientConfig, type ClientOndoNamespace, type ClientRequirementsNamespace, type ClientSuperstateSwapNamespace, type ClientSupportNamespace, type ClientWalletsNamespace, type CoinListClient, CoinListClientInitializationError, CoinListProvider, type CoinListProviderProps, CoinListSignInButton, type CoinListSignInButtonProps, CoinListSignInCardContainer, type CoinListSignInCardContainerProps, type CoinListSignInCardUiEvent, type CoinListSignInCardUiState, CoinListStyleScope, type CoinListStyleScopeProps, type CoinListTokenSaleCheckoutConfig, type CompleteOAuthFailureReason, type ConnectWalletError, type ConnectWalletErrorCode, type ConnectWalletFlowError, type ConnectWalletFlowResult, type ConnectWalletParams, type ConnectWalletPhase, type ConnectWalletSignState, type ConnectWalletState, type ConnectedWalletUi, type Erc20AllowanceError, type Erc20AllowancePhase, type Erc20ApprovalError, type ExecuteOndoSwapParams, type ExecuteSwapParams, type ExecuteTokenSaleParams, type ExternalWalletRequestUi, type KycTokenErrorReason, type KycTokenState, type LoadCentrifugeBuyTransactionState, type LoadCentrifugeVaultPositionsState, type LoadCentrifugeVaultStatusState, type LoadOfferDetailsReason, type LoadOfferDetailsState, type LoadOffersReason, type LoadOffersState, type LoadOndoBuyTransactionState, type LoadOndoPriceState, type LoadOndoSellTransactionState, type LoadOndoTradingStatusState, type LoadOptionAddressesReason, type LoadOptionAddressesState, type LoadParticipationsReason, type LoadParticipationsState, type LoadRequirementsReason, type LoadRequirementsState, type LoadTokenMetadataState, type LoadTokenRegistryState, type LogoImageUi, type OAuthClientErrorReason, type OAuthClientResult, OfferAssetCard, type OfferAssetCardProps, OfferAssetCardUi, OfferLogoUi, OfferSaleCard, type OfferSaleCardProps, OfferSaleCardUi, OffersGridContainer, type OffersGridContainerProps, type OffersGridData, type OndoBuyAmountUiEvent, type OndoBuyAmountUiState, type OndoBuyCheckoutUiEvent, type OndoBuyCheckoutUiState, type OndoBuyOrderPlaced, type OndoBuyOrderTerms, type OndoBuyPreparationResult, type OndoBuyQuoteStatusUi, type OndoBuyReviewUiEvent, type OndoBuyReviewUiState, type OndoCheckoutConfig, OndoCheckoutErrorReason, type OndoLoadErrorReason, type OndoOrderConfirmedUiEvent, type OndoOrderConfirmedUiState, type OndoOrderPlaced, type OndoOrderPlacedCore, type OndoSellAmountUiEvent, type OndoSellAmountUiState, type OndoSellBalanceUi, type OndoSellCheckoutUiEvent, type OndoSellCheckoutUiState, type OndoSellOrderConfirmedUiEvent, type OndoSellOrderConfirmedUiState, type OndoSellOrderPlaced, type OndoSellOrderTerms, type OndoSellOutcomeUi, type OndoSellPreparationResult, type OndoSellQuoteStatusUi, type OndoSellReviewUiEvent, type OndoSellReviewUiState, type OndoSellSourceWalletUi, type OndoSidebarPriceUi, type OndoSidebarUiState, type OndoSwapExecutionError, type OndoSwapExecutionPhase, type OndoSwapExecutionResult, type OndoSwapPreparationError, type OndoSwapPreparationPhase, type OndoSwapPreparationResult, type OndoWalletSelectUiEvent, type OndoWalletSelectUiState, type PlaceCentrifugeRequestParams, type PrepareCentrifugeBuyParams, type PrepareOndoBuyParams, type PrepareOndoSellParams, type PrepareOndoSwapParamsCore, type RequiredCheckoutConfig, RequirementItemUi, RequirementStatus, RequirementVariant, RequirementsChecklistContainer, type RequirementsChecklistContainerProps, type RequirementsChecklistItemUi, type RequirementsChecklistUiEvent, type RequirementsChecklistUiState, RequirementsChecklistView, type RequirementsChecklistViewProps, type RequirementsData, type RequirementsVerificationUi, type SignState, type SuperstateAmountUiEvent, type SuperstateAmountUiState, type SuperstateCheckoutConfig, type SuperstateOrderConfirmedUiEvent, type SuperstateOrderConfirmedUiState, type SuperstateOrderPlaced, type SuperstateReviewUiEvent, type SuperstateReviewUiState, type SuperstateSidebarPriceUi, type SuperstateSidebarUiState, type SuperstateSlippageOptionUi, type SuperstateSlippageUi, type SuperstateSwapCheckoutRetryUiEvent, type SuperstateSwapCheckoutUiEvent, type SuperstateSwapCheckoutUiState, type SuperstateSwapLoadErrorReason, type SuperstateWalletUiEvent, type SuperstateWalletUiState, type SwapExecutionError, type SwapExecutionPhase, type SwapExecutionResult, type SwapOutputTokenState, type TaxDocumentAddressParts, type TaxDocumentFields, type TaxDocumentState, type TokenSaleExecutionError, type TokenSaleExecutionPhase, type TokenSaleExecutionResult, type UseCentrifugeBuyCheckoutViewModelOptions, type UseCentrifugeBuyCheckoutViewModelResult, type UseCentrifugeBuyTransactionOptions, type UseCentrifugeBuyTransactionResult, type UseCentrifugeClaimResult, type UseCentrifugeVaultClaimViewModelOptions, type UseCentrifugeVaultClaimViewModelResult, type UseCentrifugeVaultPositionsOptions, type UseCentrifugeVaultPositionsResult, type UseCentrifugeVaultStatusOptions, type UseCentrifugeVaultStatusResult, type UseCentrifugeVaultStatusesOptions, type UseCentrifugeVaultStatusesResult, type UseCoinListResult, type UseCoinListSignInCardViewModelOptions, type UseCoinListSignInCardViewModelResult, type UseCompleteOAuthOptions, type UseConnectWalletOptions, type UseConnectWalletResult, type UseErc20BalanceOptions, type UseErc20BalanceResult, type UseErc20TokenBalancesOptions, type UseErc20TokenBalancesResult, type UseKycTokenResult, type UseOfferDetailsOptions, type UseOfferDetailsResult, type UseOffersOptions, type UseOffersResult, type UseOndoBuyCheckoutViewModelOptions, type UseOndoBuyCheckoutViewModelResult, type UseOndoBuyTransactionOptions, type UseOndoBuyTransactionResult, type UseOndoPriceOptions, type UseOndoPriceResult, type UseOndoSellCheckoutViewModelOptions, type UseOndoSellCheckoutViewModelResult, type UseOndoSellTransactionOptions, type UseOndoSellTransactionResult, type UseOndoTradingStatusOptions, type UseOndoTradingStatusResult, type UseOptionAddressesOptions, type UseOptionAddressesResult, type UseParticipationsOptions, type UseParticipationsResult, type UseRequirementsChecklistViewModelOptions, type UseRequirementsChecklistViewModelResult, type UseRequirementsOptions, type UseRequirementsResult, type UseSuperstateSwapCheckoutViewModelOptions, type UseSuperstateSwapCheckoutViewModelResult, type UseSwapOutputTokenOptions, type UseSwapOutputTokenResult, type UseSwapQuoteOptions, type UseSwapQuoteResult, type UseTaxDocumentOptions, type UseTaxDocumentResult, type UseTokenMetadataOptions, type UseTokenMetadataResult, type UseTokenRegistryOptions, type UseTokenRegistryResult, type WalletAuthorizationError, type WalletAuthorizationPhase, type WalletAuthorizationResult, type WalletsStatus, createCoinListClient, defaultCheckoutConfig, isNotTradable, pinoClientLogger, useCentrifugeBuyCheckoutViewModel, useCentrifugeBuyTransaction, useCentrifugeClaim, useCentrifugeVaultClaimViewModel, useCentrifugeVaultPositions, useCentrifugeVaultStatus, useCentrifugeVaultStatuses, useCoinList, useCoinListSignInCardViewModel, useCompleteOAuth, useConnectWallet, useErc20Balance, useErc20TokenBalances, useKycToken, useOfferDetails, useOffers, useOndoBuyCheckoutViewModel, useOndoBuyTransaction, useOndoPrice, useOndoSellCheckoutViewModel, useOndoSellTransaction, useOndoTradingStatus, useOptionAddresses, useParticipations, useRequirements, useRequirementsChecklistViewModel, useSuperstateSwapCheckoutViewModel, useSwapOutputToken, useSwapQuote, useTaxDocument, useTokenMetadata, useTokenRegistry };
5587
+ export { type ApproveThenBuildError, type ApproveThenBuildPhase, type ApproveThenBuildResult, type AuthState, type AuthorizeWalletParams, type BuyCentrifugeParams, type CentrifugeBuyCheckoutUiEvent, type CentrifugeBuyCheckoutUiState, type CentrifugeBuyError, type CentrifugeBuyPhase, type CentrifugeBuyPlacementError, type CentrifugeBuyPlacementPhase, type CentrifugeBuyPlacementResult, type CentrifugeBuyPreparationError, type CentrifugeBuyPreparationPhase, type CentrifugeBuyPreparationResult, type CentrifugeBuyResult, type CentrifugeBuyReviewUiEvent, type CentrifugeBuyReviewUiState, type CentrifugeCheckoutErrorReason, type CentrifugeClaimActionUi, type CentrifugeClaimBlockedReasonUi, type CentrifugeClaimDialogUi, type CentrifugeClaimError, type CentrifugeClaimFailureUi, type CentrifugeClaimParams, type CentrifugeClaimPhase, type CentrifugeClaimProgressUi, type CentrifugeClaimResult, type CentrifugeClaimRowUi, type CentrifugeClaimState, type CentrifugeClaimStepUi, type CentrifugeLoadErrorReason, type CentrifugeOrderPlaced, type CentrifugeOrderPlacedUiEvent, type CentrifugeOrderPlacedUiState, type CentrifugeSidebarMinimumUi, type CentrifugeSidebarUiState, type CentrifugeVaultCheckoutConfig, type CentrifugeVaultClaimConfig, type CentrifugeVaultClaimUiEvent, type CentrifugeVaultClaimUiState, type CentrifugeVaultClaimed, ChecklistStatus, type CheckoutAmountAdornmentUi, type CheckoutAmountUiEvent, type CheckoutAmountUiState, CheckoutAssetUi, type CheckoutBlockedReason, type CheckoutConfig, type CheckoutConfirmedWalletUi, CheckoutContainer, type CheckoutContainerProps, type CheckoutCtaUi, type CheckoutEmbeddedWalletUi, CheckoutExternalWalletUi, type CheckoutNetworkUi, type CheckoutReceiptUi, type CheckoutSelectableInputAssetUi, type CheckoutStatusUi, type CheckoutWalletSelectUiEvent, type CheckoutWalletSelectUiState, type CheckoutWalletSelection, type CheckoutWalletTypeUi, type CheckoutWalletUi, type ClaimCentrifugeVaultParams, type ClaimConfig, ClaimContainer, type ClaimContainerProps, type ClaimExternalWalletUi, type ClientAuthNamespace, type ClientCentrifugeNamespace, type ClientCoinListTokenSaleNamespace, type ClientConfig, type ClientOndoNamespace, type ClientRequirementsNamespace, type ClientSuperstateSwapNamespace, type ClientSupportNamespace, type ClientWalletsNamespace, type CoinListClient, CoinListClientInitializationError, CoinListProvider, type CoinListProviderProps, CoinListSignInButton, type CoinListSignInButtonProps, CoinListSignInCardContainer, type CoinListSignInCardContainerProps, type CoinListSignInCardUiEvent, type CoinListSignInCardUiState, CoinListStyleScope, type CoinListStyleScopeProps, type CoinListTokenSaleCheckoutConfig, type CoinListTokenSaleCheckoutUiEvent, type CoinListTokenSaleCheckoutUiState, type CompleteOAuthFailureReason, type ConnectWalletError, type ConnectWalletErrorCode, type ConnectWalletFlowError, type ConnectWalletFlowResult, type ConnectWalletParams, type ConnectWalletPhase, type ConnectWalletSignState, type ConnectWalletState, type ConnectedWalletUi, type Erc20AllowanceError, type Erc20AllowancePhase, type Erc20ApprovalError, type ExecuteOndoSwapParams, type ExecuteSwapParams, type ExecuteTokenSaleParams, type ExternalWalletRequestUi, type KycTokenErrorReason, type KycTokenState, type LoadCentrifugeClaimPositionsState, type LoadCentrifugeVaultStatusState, type LoadErc20BalanceState, type LoadErc20TokenBalancesState, type LoadErrorReason, type LoadFirmTransactionState, type LoadOfferDetailsReason, type LoadOfferDetailsState, type LoadOffersReason, type LoadOffersState, type LoadOndoBuyTransactionState, type LoadOndoPriceState, type LoadOndoSellTransactionState, type LoadOndoTradingStatusState, type LoadOptionAddressesReason, type LoadOptionAddressesState, type LoadParticipationsReason, type LoadParticipationsState, type LoadRequirementsReason, type LoadRequirementsState, type LoadSwapOutputTokenState, type LoadSwapQuoteState, type LoadTokenMetadataState, type LoadTokenRegistryState, type LogoImageUi, type OAuthClientErrorReason, type OAuthClientResult, OfferAssetCard, type OfferAssetCardProps, OfferAssetCardUi, OfferLogoUi, OfferSaleCard, type OfferSaleCardProps, OfferSaleCardUi, OffersGridContainer, type OffersGridContainerProps, type OffersGridData, type OndoBuyAmountUiEvent, type OndoBuyAmountUiState, type OndoBuyCheckoutUiEvent, type OndoBuyCheckoutUiState, type OndoBuyOrderPlaced, type OndoBuyOrderTerms, type OndoBuyPreparationResult, type OndoBuyReviewUiEvent, type OndoBuyReviewUiState, type OndoCheckoutConfig, type OndoCheckoutErrorReason, type OndoLoadErrorReason, type OndoOrderConfirmedUiEvent, type OndoOrderConfirmedUiState, type OndoOrderPlaced, type OndoOrderPlacedCore, type OndoQuoteStatusUi, type OndoSellAmountUiEvent, type OndoSellAmountUiState, type OndoSellBalanceUi, type OndoSellCheckoutUiEvent, type OndoSellCheckoutUiState, type OndoSellOrderConfirmedUiEvent, type OndoSellOrderConfirmedUiState, type OndoSellOrderPlaced, type OndoSellOrderTerms, type OndoSellOutcomeUi, type OndoSellPreparationResult, type OndoSellReviewUiEvent, type OndoSellReviewUiState, type OndoSellSourceWalletUi, type OndoSidebarPriceUi, type OndoSidebarUiState, type OndoSwapExecutionError, type OndoSwapExecutionPhase, type OndoSwapExecutionResult, type OndoSwapPreparationError, type OndoSwapPreparationPhase, type OndoSwapPreparationResult, type PlaceCentrifugeRequestParams, type PrepareCentrifugeBuyParams, type PrepareOndoBuyParams, type PrepareOndoSellParams, type PrepareOndoSwapParamsCore, RequirementItemUi, RequirementStatus, RequirementVariant, RequirementsChecklistContainer, type RequirementsChecklistContainerProps, type RequirementsChecklistItemUi, type RequirementsChecklistUiEvent, type RequirementsChecklistUiState, RequirementsChecklistView, type RequirementsChecklistViewProps, type RequirementsData, type RequirementsVerificationUi, type ResetThenApprovePhase, type SignState, type SuperstateCheckoutConfig, type SuperstateOrderConfirmedUiEvent, type SuperstateOrderConfirmedUiState, type SuperstateOrderPlaced, type SuperstateReviewUiEvent, type SuperstateReviewUiState, type SuperstateSidebarPriceUi, type SuperstateSidebarUiState, type SuperstateSlippageOptionUi, type SuperstateSlippageUi, type SuperstateSwapCheckoutRetryUiEvent, type SuperstateSwapCheckoutUiEvent, type SuperstateSwapCheckoutUiState, type SuperstateSwapLoadErrorReason, type SuperstateWalletUiEvent, type SuperstateWalletUiState, type SwapExecutionError, type SwapExecutionPhase, type SwapExecutionResult, type TaxDocumentAddressParts, type TaxDocumentFields, type TaxDocumentState, type TokenSaleApproval, type TokenSaleCheckoutErrorReason, type TokenSaleExecutionError, type TokenSaleExecutionPhase, type TokenSaleExecutionResult, type TokenSaleOrderPlaced, type TokenSaleOrderPlacedUiEvent, type TokenSaleOrderPlacedUiState, type TokenSaleReviewUiEvent, type TokenSaleReviewUiState, type TokenSaleSidebarUiState, type UseCentrifugeBuyCheckoutViewModelOptions, type UseCentrifugeBuyCheckoutViewModelResult, type UseCentrifugeClaimPositionsOptions, type UseCentrifugeClaimPositionsResult, type UseCentrifugeClaimResult, type UseCentrifugeVaultClaimViewModelOptions, type UseCentrifugeVaultClaimViewModelResult, type UseCentrifugeVaultStatusOptions, type UseCentrifugeVaultStatusResult, type UseCentrifugeVaultStatusesOptions, type UseCentrifugeVaultStatusesResult, type UseCoinListResult, type UseCoinListSignInCardViewModelOptions, type UseCoinListSignInCardViewModelResult, type UseCoinListTokenSaleCheckoutViewModelOptions, type UseCoinListTokenSaleCheckoutViewModelResult, type UseCompleteOAuthOptions, type UseConnectWalletOptions, type UseConnectWalletResult, type UseErc20BalanceOptions, type UseErc20BalanceResult, type UseErc20TokenBalancesOptions, type UseErc20TokenBalancesResult, type UseKycTokenResult, type UseOfferDetailsOptions, type UseOfferDetailsResult, type UseOffersOptions, type UseOffersResult, type UseOndoBuyCheckoutViewModelOptions, type UseOndoBuyCheckoutViewModelResult, type UseOndoBuyTransactionOptions, type UseOndoBuyTransactionResult, type UseOndoPriceOptions, type UseOndoPriceResult, type UseOndoSellCheckoutViewModelOptions, type UseOndoSellCheckoutViewModelResult, type UseOndoSellTransactionOptions, type UseOndoSellTransactionResult, type UseOndoTradingStatusOptions, type UseOndoTradingStatusResult, type UseOptionAddressesOptions, type UseOptionAddressesResult, type UseParticipationsOptions, type UseParticipationsResult, type UseRequirementsChecklistViewModelOptions, type UseRequirementsChecklistViewModelResult, type UseRequirementsOptions, type UseRequirementsResult, type UseSuperstateSwapCheckoutViewModelOptions, type UseSuperstateSwapCheckoutViewModelResult, type UseSwapOutputTokenOptions, type UseSwapOutputTokenResult, type UseSwapQuoteOptions, type UseSwapQuoteResult, type UseTaxDocumentOptions, type UseTaxDocumentResult, type UseTokenMetadataOptions, type UseTokenMetadataResult, type UseTokenRegistryOptions, type UseTokenRegistryResult, type WalletAuthorizationError, type WalletAuthorizationPhase, type WalletAuthorizationResult, type WalletsStatus, createCoinListClient, isNotTradable, pinoClientLogger, useCentrifugeBuyCheckoutViewModel, useCentrifugeClaim, useCentrifugeClaimPositions, useCentrifugeVaultClaimViewModel, useCentrifugeVaultStatus, useCentrifugeVaultStatuses, useCoinList, useCoinListSignInCardViewModel, useCoinListTokenSaleCheckoutViewModel, useCompleteOAuth, useConnectWallet, useErc20Balance, useErc20TokenBalances, useKycToken, useOfferDetails, useOffers, useOndoBuyCheckoutViewModel, useOndoBuyTransaction, useOndoPrice, useOndoSellCheckoutViewModel, useOndoSellTransaction, useOndoTradingStatus, useOptionAddresses, useParticipations, useRequirements, useRequirementsChecklistViewModel, useSuperstateSwapCheckoutViewModel, useSwapOutputToken, useSwapQuote, useTaxDocument, useTokenMetadata, useTokenRegistry };