@stridge/kit 0.1.0-alpha.4 → 0.1.0-alpha.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/README.md +22 -6
  2. package/dist/KitProvider.d.ts +29 -0
  3. package/dist/KitProvider.js +1 -1
  4. package/dist/_internal/drivers/stridge/index.d.ts +3 -2
  5. package/dist/_internal/drivers/stridge/index.js +1 -1
  6. package/dist/_internal/withdraw/driver/index.d.ts +2 -2
  7. package/dist/deposit/compound/index.d.ts +3 -3
  8. package/dist/drivers/stridge/catalog.d.ts +54 -0
  9. package/dist/drivers/stridge/catalog.js +1 -0
  10. package/dist/drivers/stridge/createStridgeDepositDriver.d.ts +9 -0
  11. package/dist/drivers/stridge/createStridgeDepositDriver.js +1 -1
  12. package/dist/drivers/stridge/createStridgeWithdrawDriver.d.ts +34 -13
  13. package/dist/drivers/stridge/createStridgeWithdrawDriver.js +1 -1
  14. package/dist/drivers/stridge/internal/retry.js +1 -0
  15. package/dist/drivers/stridge/internal/supportedChains.js +1 -0
  16. package/dist/drivers/stridge/types.d.ts +20 -14
  17. package/dist/drivers/stridge/types.js +1 -1
  18. package/dist/drivers/stridge-mock/createStridgeMockDriver.d.ts +2 -2
  19. package/dist/drivers/stridge-mock/createStridgeMockDriver.js +1 -1
  20. package/dist/drivers/stridge-mock/createStridgeMockWithdrawDriver.d.ts +15 -3
  21. package/dist/drivers/stridge-mock/createStridgeMockWithdrawDriver.js +1 -1
  22. package/dist/drivers/stridge-mock/fixtures.d.ts +13 -11
  23. package/dist/drivers/stridge-mock/fixtures.js +1 -1
  24. package/dist/events/bus/createBus.d.ts +7 -0
  25. package/dist/events/bus/createBus.js +1 -0
  26. package/dist/events/bus/flowIdRegistry.d.ts +17 -0
  27. package/dist/events/bus/flowIdRegistry.js +1 -0
  28. package/dist/events/bus/index.js +1 -0
  29. package/dist/events/bus/metadata.js +1 -0
  30. package/dist/events/context.js +1 -0
  31. package/dist/events/emit/index.js +1 -0
  32. package/dist/events/emit/mapFailure.js +1 -0
  33. package/dist/events/emit/useDepositEmissions.js +1 -0
  34. package/dist/events/emit/useKitEmitter.js +1 -0
  35. package/dist/events/emit/useWithdrawEmissions.js +1 -0
  36. package/dist/events/hooks/index.d.ts +6 -0
  37. package/dist/events/hooks/index.js +1 -0
  38. package/dist/events/hooks/useCurrentFlowId.d.ts +6 -0
  39. package/dist/events/hooks/useCurrentFlowId.js +1 -0
  40. package/dist/events/hooks/useStableHandler.js +1 -0
  41. package/dist/events/hooks/useStridgeEvent.d.ts +8 -0
  42. package/dist/events/hooks/useStridgeEvent.js +1 -0
  43. package/dist/events/hooks/useStridgeEventBus.d.ts +33 -0
  44. package/dist/events/hooks/useStridgeEventBus.js +1 -0
  45. package/dist/events/hooks/useStridgeEvents.d.ts +6 -0
  46. package/dist/events/hooks/useStridgeEvents.js +1 -0
  47. package/dist/events/hooks/useStridgeFlowEvent.d.ts +8 -0
  48. package/dist/events/hooks/useStridgeFlowEvent.js +1 -0
  49. package/dist/events/hooks/useStridgeFlowEvents.d.ts +6 -0
  50. package/dist/events/hooks/useStridgeFlowEvents.js +1 -0
  51. package/dist/events/index.d.ts +14 -0
  52. package/dist/events/index.js +1 -0
  53. package/dist/events/publish.js +1 -0
  54. package/dist/events/types/deposit.d.ts +235 -0
  55. package/dist/events/types/envelope.d.ts +145 -0
  56. package/dist/events/types/index.d.ts +31 -0
  57. package/dist/events/types/kit.d.ts +23 -0
  58. package/dist/events/types/withdraw.d.ts +150 -0
  59. package/dist/flows/deposit/dialog/DepositDialog.d.ts +14 -81
  60. package/dist/flows/deposit/dialog/DepositDialog.js +1 -1
  61. package/dist/flows/deposit/dialog/WalletRequiredState.js +1 -0
  62. package/dist/flows/deposit/dialog/WalletRequiredState.styles.js +1 -0
  63. package/dist/flows/deposit/driver/payloads.d.ts +10 -4
  64. package/dist/flows/deposit/driver/transformers/balanceToBalancesPayload.js +1 -1
  65. package/dist/flows/deposit/driver/transformers/startToAddressesPayload.js +1 -1
  66. package/dist/flows/deposit/driver/transformers/startToTargetPayload.js +1 -1
  67. package/dist/flows/deposit/driver/types.d.ts +11 -0
  68. package/dist/flows/deposit/orchestrator/controller.js +1 -1
  69. package/dist/flows/deposit/orchestrator/types.d.ts +30 -1
  70. package/dist/flows/deposit/orchestrator/useDeposit.d.ts +45 -1
  71. package/dist/flows/deposit/orchestrator/useDeposit.js +1 -1
  72. package/dist/flows/deposit/widgets/amount-entry/AmountEntry.d.ts +1 -1
  73. package/dist/flows/deposit/widgets/amount-entry/AmountEntry.js +1 -1
  74. package/dist/flows/deposit/widgets/amount-entry/footerIntent.js +1 -0
  75. package/dist/flows/deposit/widgets/confirm-deposit/ConfirmDeposit.js +1 -1
  76. package/dist/flows/deposit/widgets/deposit/Deposit.js +1 -1
  77. package/dist/flows/deposit/widgets/deposit/compound/components/Method.d.ts +6 -0
  78. package/dist/flows/deposit/widgets/deposit/compound/components/Method.js +1 -1
  79. package/dist/flows/deposit/widgets/deposit/compound/types.d.ts +6 -3
  80. package/dist/flows/deposit/widgets/deposit-status-banner/DepositStatusBanner.d.ts +7 -0
  81. package/dist/flows/deposit/widgets/deposit-status-banner/DepositStatusBanner.js +1 -1
  82. package/dist/flows/deposit/widgets/deposit-status-banner/compound/DepositStatusBanner.js +1 -1
  83. package/dist/flows/deposit/widgets/deposit-status-banner/compound/components/Hero.js +1 -1
  84. package/dist/flows/deposit/widgets/deposit-status-banner/compound/components/PrimaryAction.js +1 -1
  85. package/dist/flows/deposit/widgets/processing-state/ProcessingState.js +1 -1
  86. package/dist/flows/deposit/widgets/transfer-crypto/TransferCrypto.js +1 -1
  87. package/dist/flows/deposit/widgets/transfer-crypto/compound/TransferCrypto.d.ts +1 -1
  88. package/dist/flows/deposit/widgets/transfer-crypto/compound/components/Address.js +1 -1
  89. package/dist/flows/deposit/widgets/transfer-crypto/compound/components/Disclosure.d.ts +2 -1
  90. package/dist/flows/deposit/widgets/transfer-crypto/compound/components/Disclosure.js +1 -1
  91. package/dist/flows/deposit/widgets/transfer-crypto/compound/components/QrCode.d.ts +4 -10
  92. package/dist/flows/deposit/widgets/transfer-crypto/compound/components/QrCode.js +1 -1
  93. package/dist/flows/shared/transformers/pickRelevantSettlement.js +1 -1
  94. package/dist/flows/shared/transformers/testnets.js +1 -0
  95. package/dist/flows/withdraw/bindings/WithdrawBindings.d.ts +92 -0
  96. package/dist/flows/withdraw/bindings/WithdrawBindings.js +1 -0
  97. package/dist/flows/withdraw/bindings/index.d.ts +1 -0
  98. package/dist/flows/withdraw/bindings/index.js +1 -0
  99. package/dist/flows/withdraw/dialog/WithdrawDialog.d.ts +35 -71
  100. package/dist/flows/withdraw/dialog/WithdrawDialog.js +1 -1
  101. package/dist/flows/withdraw/driver/payloads.d.ts +16 -1
  102. package/dist/flows/withdraw/driver/transformers/settlementToWithdrawalPayload.js +1 -1
  103. package/dist/flows/withdraw/driver/transformers/supportedAssetsToReceiveOptionsPayload.js +1 -1
  104. package/dist/flows/withdraw/driver/types.d.ts +76 -13
  105. package/dist/flows/withdraw/orchestrator/controller.js +1 -1
  106. package/dist/flows/withdraw/orchestrator/index.d.ts +1 -1
  107. package/dist/flows/withdraw/orchestrator/reducer.js +1 -1
  108. package/dist/flows/withdraw/orchestrator/types.d.ts +131 -32
  109. package/dist/flows/withdraw/orchestrator/useWithdraw.d.ts +36 -1
  110. package/dist/flows/withdraw/orchestrator/useWithdraw.js +1 -1
  111. package/dist/flows/withdraw/widgets/withdraw-form/WithdrawForm.d.ts +5 -13
  112. package/dist/flows/withdraw/widgets/withdraw-form/WithdrawForm.js +1 -1
  113. package/dist/flows/withdraw/widgets/withdraw-form/compound/WithdrawForm.js +1 -1
  114. package/dist/flows/withdraw/widgets/withdraw-form/compound/components/RecipientField.d.ts +7 -5
  115. package/dist/flows/withdraw/widgets/withdraw-form/compound/components/RecipientField.js +1 -1
  116. package/dist/flows/withdraw/widgets/withdraw-form/compound/types.d.ts +15 -5
  117. package/dist/flows/withdraw/widgets/withdraw-form/validation.js +1 -1
  118. package/dist/flows/withdraw/widgets/withdraw-in-progress/WithdrawInProgress.d.ts +2 -1
  119. package/dist/flows/withdraw/widgets/withdraw-in-progress/WithdrawInProgress.js +1 -1
  120. package/dist/flows/withdraw/widgets/withdraw-success/WithdrawSuccess.js +1 -1
  121. package/dist/i18n/index.d.ts +5 -4
  122. package/dist/i18n/index.js +1 -1
  123. package/dist/i18n/locales/ar.js +1 -1
  124. package/dist/i18n/locales/es.js +1 -1
  125. package/dist/i18n/locales/source-keys.d.ts +12 -0
  126. package/dist/i18n/locales/source-keys.js +0 -0
  127. package/dist/icons/index.d.ts +2 -1
  128. package/dist/icons/index.js +1 -1
  129. package/dist/index.d.ts +21 -9
  130. package/dist/index.js +1 -1
  131. package/dist/package.js +1 -1
  132. package/dist/scope/KitPortalScope.js +1 -1
  133. package/dist/scope/KitScope.d.ts +18 -1
  134. package/dist/scope/KitScope.js +1 -1
  135. package/dist/scope/context.d.ts +17 -1
  136. package/dist/scope/index.d.ts +1 -1
  137. package/dist/shared/attribution/Attribution.js +1 -0
  138. package/dist/shared/attribution/Attribution.slots.js +1 -0
  139. package/dist/shared/attribution/Attribution.styles.js +1 -0
  140. package/dist/shared/attribution/index.js +1 -0
  141. package/dist/shared/chains/index.d.ts +48 -29
  142. package/dist/shared/chains/index.js +1 -1
  143. package/dist/shared/constants/brand-intercom.js +1 -0
  144. package/dist/shared/cuer/Cuer.js +1 -0
  145. package/dist/shared/cuer/QrCode.js +1 -0
  146. package/dist/shared/cuer/index.js +1 -0
  147. package/dist/shared/dialog/Frame.js +1 -1
  148. package/dist/shared/dialog/LoadingState.js +1 -0
  149. package/dist/shared/dialog/LoadingState.styles.js +1 -0
  150. package/dist/shared/dialog/StepTransition.js +1 -1
  151. package/dist/shared/driver/types.d.ts +4 -3
  152. package/dist/shared/i18n/KitI18nProvider.d.ts +11 -8
  153. package/dist/shared/i18n/KitI18nProvider.js +1 -1
  154. package/dist/shared/i18n/createKitI18n.d.ts +79 -16
  155. package/dist/shared/i18n/createKitI18n.js +1 -1
  156. package/dist/shared/i18n/useLingui.d.ts +11 -3
  157. package/dist/shared/icons/LogoIcon.d.ts +13 -0
  158. package/dist/shared/icons/LogoIcon.js +1 -0
  159. package/dist/shared/merchant-link/MerchantLink.d.ts +1 -0
  160. package/dist/shared/merchant-link/MerchantLink.js +1 -0
  161. package/dist/shared/merchant-link/MerchantLinkButton.d.ts +1 -0
  162. package/dist/shared/merchant-link/MerchantLinkButton.js +1 -0
  163. package/dist/shared/merchant-link/index.d.ts +1 -0
  164. package/dist/shared/merchant-link/index.js +1 -0
  165. package/dist/shared/merchant-link/resolveMerchantLink.js +1 -0
  166. package/dist/shared/orchestrator/useSettlementWatcher.js +1 -1
  167. package/dist/shared/primitives/TxHashValue/TxHashValue.js +1 -1
  168. package/dist/shared/support/SupportConfigContext.d.ts +1 -0
  169. package/dist/shared/support/SupportConfigContext.js +1 -0
  170. package/dist/shared/support/SupportLink.d.ts +1 -0
  171. package/dist/shared/support/SupportLink.js +1 -0
  172. package/dist/shared/support/SupportSpinner.d.ts +1 -0
  173. package/dist/shared/support/SupportSpinner.js +1 -0
  174. package/dist/shared/support/index.d.ts +2 -0
  175. package/dist/shared/support/index.js +1 -0
  176. package/dist/shared/support/intercom-loader.d.ts +17 -0
  177. package/dist/shared/support/intercom-loader.js +1 -0
  178. package/dist/shared/support/types.d.ts +43 -0
  179. package/dist/shared/support/useIntercomMerchantContext.d.ts +27 -0
  180. package/dist/shared/support/useIntercomMerchantContext.js +1 -0
  181. package/dist/shared/support/useIntercomShutdownOnUnmount.js +1 -0
  182. package/dist/shared/support/useMerchantContext.d.ts +1 -0
  183. package/dist/shared/support/useMerchantContext.js +1 -0
  184. package/dist/shared/support/useSupportTrigger.js +1 -0
  185. package/dist/shared/terms/TermsConfigContext.d.ts +1 -0
  186. package/dist/shared/terms/TermsConfigContext.js +1 -0
  187. package/dist/shared/terms/TermsLink.d.ts +1 -0
  188. package/dist/shared/terms/TermsLink.js +1 -0
  189. package/dist/shared/terms/index.d.ts +1 -0
  190. package/dist/shared/terms/index.js +1 -0
  191. package/dist/shared/terms/types.d.ts +43 -0
  192. package/dist/shared/ui/Card/Card.styles.js +1 -1
  193. package/dist/shared/ui/Details/Details.d.ts +9 -1
  194. package/dist/shared/ui/Details/Details.styles.js +1 -1
  195. package/dist/shared/ui/Dialog/Dialog.js +1 -1
  196. package/dist/shared/ui/Dialog/Dialog.styles.js +1 -1
  197. package/dist/shared/ui/Select/Select.js +1 -1
  198. package/dist/shared/ui/WalletRow/WalletRow.d.ts +1 -1
  199. package/dist/shared/ui/WalletRow/WalletRow.js +1 -1
  200. package/dist/shared/utils/useDeepMemo.js +1 -0
  201. package/dist/shared/wallet/ConnectWalletContext.d.ts +17 -0
  202. package/dist/shared/wallet/ConnectWalletContext.js +1 -0
  203. package/dist/shared/widgets/amount-entry/compound/components/Hero/Hero.js +1 -1
  204. package/dist/shared/widgets/amount-entry/compound/components/Hero/SwapBackdrop.js +1 -1
  205. package/dist/shared/widgets/asset-picker/compound/components/Asset.d.ts +7 -1
  206. package/dist/shared/widgets/asset-picker/compound/components/Asset.js +1 -1
  207. package/dist/shared/widgets/confirm-transfer/compound/components/Disclaimer.d.ts +4 -3
  208. package/dist/shared/widgets/confirm-transfer/compound/components/Disclaimer.js +1 -1
  209. package/dist/shared/widgets/error-state/compound/components/AssetValue.js +1 -1
  210. package/dist/shared/widgets/error-state/compound/components/HelpInfo.js +1 -1
  211. package/dist/shared/widgets/error-state/compound/components/StatusValue.js +1 -1
  212. package/dist/shared/widgets/processing-state/compound/ProcessingState.d.ts +1 -5
  213. package/dist/shared/widgets/processing-state/compound/ProcessingState.js +1 -1
  214. package/dist/shared/widgets/processing-state/compound/ProcessingState.slots.d.ts +0 -1
  215. package/dist/shared/widgets/processing-state/compound/ProcessingState.slots.js +1 -1
  216. package/dist/shared/widgets/processing-state/compound/ProcessingState.styles.js +1 -1
  217. package/dist/shared/widgets/processing-state/compound/components/Details.d.ts +6 -1
  218. package/dist/shared/widgets/processing-state/compound/components/Details.js +1 -1
  219. package/dist/shared/widgets/processing-state/compound/components/Header.d.ts +4 -3
  220. package/dist/shared/widgets/processing-state/compound/components/Header.js +1 -1
  221. package/dist/shared/widgets/processing-state/compound/components/Hero.d.ts +14 -7
  222. package/dist/shared/widgets/processing-state/compound/components/Hero.js +1 -1
  223. package/dist/shared/widgets/processing-state/compound/components/Rows.js +1 -1
  224. package/dist/shared/widgets/processing-state/compound/components/StatusPill.js +1 -1
  225. package/dist/shared/widgets/processing-state/compound/components/splitAmount.js +1 -0
  226. package/dist/shared/widgets/processing-state/compound/index.d.ts +1 -1
  227. package/dist/shared/widgets/processing-state/compound/types.d.ts +7 -26
  228. package/dist/shared/widgets/success-state/compound/components/Actions.js +1 -1
  229. package/dist/shared/widgets/success-state/compound/components/AssetValue.js +1 -1
  230. package/dist/shared/widgets/success-state/compound/components/RouteValue.js +1 -1
  231. package/dist/shared/widgets/success-state/compound/components/StatusPill.js +1 -1
  232. package/dist/stridge/StridgeProvider.d.ts +165 -35
  233. package/dist/stridge/StridgeProvider.js +1 -1
  234. package/dist/stridge/depositOwner.js +1 -0
  235. package/dist/stridge/optionalWagmi.js +1 -0
  236. package/dist/stridge/stubs.js +1 -1
  237. package/dist/styles/index.css +126 -10
  238. package/dist/types.d.ts +5 -4
  239. package/dist/ui/index.js +1 -1
  240. package/dist/withdraw/compound/index.d.ts +2 -2
  241. package/dist/withdraw/dialog/index.d.ts +3 -1
  242. package/package.json +13 -9
  243. package/dist/flows/withdraw/dialog/WithdrawDialogEventsContext.d.ts +0 -36
  244. package/dist/flows/withdraw/dialog/WithdrawDialogEventsContext.js +0 -1
  245. package/dist/shared/widgets/processing-state/compound/components/Actions.d.ts +0 -17
  246. package/dist/shared/widgets/processing-state/compound/components/Actions.js +0 -1
  247. package/dist/stridge/StridgeContext.d.ts +0 -29
  248. package/dist/stridge/StridgeContext.js +0 -1
@@ -1,4 +1,5 @@
1
1
  import { Entity, SettlementFailureKind, TxRef } from "../../../shared/driver/types.js";
2
+ import { FormattedField } from "../../../shared/format/types.js";
2
3
  import { ReceiveOptionDto, ReceiveOptionsResponse, WithdrawableBalanceDto, WithdrawableBalancesResponse, WithdrawalQuoteDto, WithdrawalQuoteResponse, WithdrawalSettlementDto, WithdrawalSettlementResponse } from "./dto.js";
3
4
  import { ReceiveChainPayload, ReceiveTokenOptionPayload, WithdrawableBalanceItemPayload, WithdrawalQuoteBreakdownPayload, WithdrawalQuotePayload, WithdrawalReceiveAssetPayload, WithdrawalSettlementFailurePayload, WithdrawalSettlementPayload, WithdrawalSettlementPendingPayload, WithdrawalSettlementSuccessPayload } from "./payloads.js";
4
5
 
@@ -8,8 +9,9 @@ import { ReceiveChainPayload, ReceiveTokenOptionPayload, WithdrawableBalanceItem
8
9
  * {@link WithdrawDriver.getSnapshot} and consumed by `useSyncExternalStore`. The kit's
9
10
  * `useWithdrawSnapshot()` hook returns this shape.
10
11
  *
11
- * Each field is an {@link Entity} envelope — components switch on `status` and read `payload` on
12
- * the `ready` / `stale` variants.
12
+ * Most fields are {@link Entity} envelopes — components switch on `status` and read `payload` on
13
+ * the `ready` / `stale` variants. The optional `minAmountUsd` / `maxAmountUsd` carry static
14
+ * config-derived USD bounds (set once at driver construction) and stay outside the entity model.
13
15
  */
14
16
  interface WithdrawSnapshot {
15
17
  /**
@@ -37,6 +39,18 @@ interface WithdrawSnapshot {
37
39
  * error state screen renders.
38
40
  */
39
41
  settlement: Entity<WithdrawalSettlementPayload, WithdrawalSettlementDto, WithdrawalSettlementResponse>;
42
+ /**
43
+ * Optional lower USD bound on the withdraw amount. The withdraw form blocks submit with a
44
+ * localized "Min $X" CTA when the typed amount sits below `value`. Set from
45
+ * `<StridgeProvider flows.withdraw.minAmountUsd>` and constant across the driver's lifetime.
46
+ */
47
+ minAmountUsd?: FormattedField<number>;
48
+ /**
49
+ * Optional upper USD bound on the withdraw amount. The withdraw form blocks submit with a
50
+ * localized "Max $X" CTA when the typed amount sits above `value`. Set from
51
+ * `<StridgeProvider flows.withdraw.maxAmountUsd>` and constant across the driver's lifetime.
52
+ */
53
+ maxAmountUsd?: FormattedField<number>;
40
54
  }
41
55
  /**
42
56
  * Input to {@link WithdrawDriver.requestQuote}. The form widget builds this from current field
@@ -57,17 +71,57 @@ interface RequestWithdrawalQuoteInput {
57
71
  recipientAddress: string;
58
72
  }
59
73
  /**
60
- * Input to {@link WithdrawDriver.submitWithdrawal}. Identical to {@link RequestWithdrawalQuoteInput}
61
- * — the live driver re-uses the most recent quote for submit, so the same identifying fields
62
- * scope both calls.
74
+ * Input to {@link WithdrawDriver.prepareWithdrawal}. Identical to {@link RequestWithdrawalQuoteInput}
75
+ * — the live driver re-uses the most recent quote shape for the gateway/start call, so the same
76
+ * identifying fields scope both calls.
63
77
  */
64
- type SubmitWithdrawalInput = RequestWithdrawalQuoteInput;
78
+ type PrepareWithdrawalInput = RequestWithdrawalQuoteInput;
65
79
  /**
66
- * Input to {@link WithdrawDriver.watchSettlement}. Carries the broadcast tx ref so the watcher
67
- * can scope its poll to the in-flight withdraw.
80
+ * Result of {@link WithdrawDriver.prepareWithdrawal}. Carries everything the host's `onSubmit`
81
+ * callback needs to broadcast a transfer to the Stridge UDA on the brand-currency chain — the
82
+ * UDA address, the chain, the token, the amount — plus the Stridge correlation fields the host
83
+ * may want to mirror into their own backend logs.
84
+ */
85
+ interface WithdrawPreparation {
86
+ /**
87
+ * Where the host should send brand-currency funds. The kit has already provisioned a UDA
88
+ * (via `gateway/start`); the host's job is to broadcast a single on-chain transfer of
89
+ * `amount` of `tokenSymbol` from their treasury / custodial wallet to `address` on `chainId`.
90
+ * Stridge takes over from there to bridge into the user's chosen recipient/chain/token.
91
+ */
92
+ depositTarget: {
93
+ /** UDA deposit address on the brand-currency chain. */address: string; /** EIP-155 chain id of the brand-currency network. */
94
+ chainId: number; /** Brand-currency token symbol (e.g. `"USDC"`). */
95
+ tokenSymbol: string; /** ERC-20 contract address of the brand currency. Empty string for native gas tokens. */
96
+ tokenAddress: string; /** On-chain decimal precision (e.g. `6` for USDC on Ethereum, `18` for ETH). */
97
+ tokenDecimals: number; /** `true` when the brand currency is the chain's native gas token. */
98
+ isNative: boolean; /** Exact amount to transfer, in display units (kit-managed decimals already factored in). */
99
+ amount: number;
100
+ };
101
+ /**
102
+ * Stridge correlation slot the host can pass through to their own backend / logs. `owner`
103
+ * is the same value the kit threaded into `gateway/start.owner` for this UDA.
104
+ */
105
+ correlation: {
106
+ owner: string;
107
+ };
108
+ }
109
+ /**
110
+ * Input to {@link WithdrawDriver.watchSettlement}. `tx` is optional — when the host has
111
+ * surfaced a broadcast tx hash via the orchestrator's `setTxHash` action, the watcher anchors
112
+ * to it for precise matching. When omitted, the watcher falls back to a best-match heuristic
113
+ * (destination tuple + amount tolerance + submit-time window) so the kit can find the relevant
114
+ * settlement even if the host never surfaces a tx hash.
68
115
  */
69
116
  interface WatchWithdrawalSettlementInput {
70
- tx: TxRef;
117
+ tx?: TxRef;
118
+ /**
119
+ * Form snapshot at submit time. The driver uses this in best-match mode to filter
120
+ * `gateway/{owner}` to settlements whose destination matches the user's selection.
121
+ */
122
+ form: RequestWithdrawalQuoteInput;
123
+ /** Unix-ms timestamp the host called `beginProcessing` — the start of the matching window. */
124
+ submittedAt: number;
71
125
  }
72
126
  /**
73
127
  * Input to {@link WithdrawDriver.watchWithdrawableBalances}. Optional listener — the form's
@@ -107,16 +161,25 @@ interface WithdrawDriver {
107
161
  getSnapshot(): WithdrawSnapshot;
108
162
  /** Subscribe to entity transitions outside React (analytics, headless integrations). */
109
163
  subscribe(listener: () => void): () => void;
164
+ /**
165
+ * Idempotent bootstrap trigger. The kit calls this from `useWithdraw().open()` and the
166
+ * headless `usePrefetchWithdraw()` hook. First call kicks off any deferred network work
167
+ * (e.g. `supportedAssets` + the initial `balance/onchain` fetch); subsequent calls are
168
+ * no-ops while bootstrap is in flight or completed.
169
+ */
170
+ arm(): void;
110
171
  /**
111
172
  * Fetches a fresh quote for `input` and updates the `quote` entity through its lifecycle
112
173
  * (`idle | loading → ready | error`). The `signal` cancels in-flight work.
113
174
  */
114
175
  requestQuote(input: RequestWithdrawalQuoteInput, signal: AbortSignal): Promise<void>;
115
176
  /**
116
- * Submits the confirmed withdrawal. Resolves with the broadcast tx ref. The settlement
117
- * watcher takes over from there to populate the `settlement` entity.
177
+ * Provisions a fresh UDA for this withdrawal (via `gateway/start`) and returns the deposit
178
+ * target + Stridge correlation slot for the host's `onSubmit` callback to act on. The kit
179
+ * never signs the withdraw transfer itself — the host's backend (treasury wallet, custodial
180
+ * signer, hot-wallet service) does. See {@link WithdrawPreparation}.
118
181
  */
119
- submitWithdrawal(input: SubmitWithdrawalInput, signal: AbortSignal): Promise<TxRef>;
182
+ prepareWithdrawal(input: PrepareWithdrawalInput, signal: AbortSignal): Promise<WithdrawPreparation>;
120
183
  /**
121
184
  * Watches the settlement entity through its lifecycle (pending → succeeded / failed). The
122
185
  * listener fires on every transition with the new envelope; the FSM consumes these via the
@@ -130,4 +193,4 @@ interface WithdrawDriver {
130
193
  watchWithdrawableBalances?(input: WatchWithdrawableBalancesInput, listener: (entity: WithdrawSnapshot["withdrawableBalances"]) => void, signal: AbortSignal): void;
131
194
  }
132
195
  //#endregion
133
- export { RequestWithdrawalQuoteInput, SubmitWithdrawalInput, WatchWithdrawableBalancesInput, WatchWithdrawalSettlementInput, WithdrawDriver, WithdrawSnapshot };
196
+ export { PrepareWithdrawalInput, RequestWithdrawalQuoteInput, WatchWithdrawableBalancesInput, WatchWithdrawalSettlementInput, WithdrawDriver, WithdrawPreparation, WithdrawSnapshot };
@@ -1 +1 @@
1
- "use client";import{useLingui as e}from"../../../shared/i18n/useLingui.js";import"../../../i18n/index.js";import{toFailure as t}from"../../../shared/orchestrator/toFailure.js";import{useDriverSettlementListener as n}from"../../../shared/orchestrator/useDriverSettlementListener.js";import{useEffectiveState as r}from"../../../shared/orchestrator/useEffectiveState.js";import{useSettlementWatcher as i}from"../../../shared/orchestrator/useSettlementWatcher.js";import"../../../shared/orchestrator/index.js";import{useWithdrawDriverInstance as a}from"../driver/context.js";import{initialState as o,reducer as s}from"./reducer.js";import{createContext as c,use as l,useCallback as u,useMemo as d,useReducer as f,useRef as p}from"react";import{jsx as m}from"react/jsx-runtime";const h={id:`ldK3jJ`,message:`Failed to submit withdrawal.`},g={id:`kUFhUv`,message:`Withdrawal failed.`},_=c(null);_.displayName=`WithdrawControllerContext`;function v(){let e=l(_);if(!e)throw Error(`useWithdraw / WithdrawControllerProvider must be used inside <KitProvider withdraw={…} />. Mount KitProvider once at the host's app root with a withdraw driver.`);return e}function y(){return v().state}function b(){return v().effectiveState}function x(){return v().actions}function S({children:e}){let t=a(),[n,c]=f(s,o),l=w(n,c,t);i(t,n.name===`inProgress`?n.ctx.tx:void 0),T(n,c,t);let u=r(n),p=C(c,l);return m(_,{value:d(()=>({state:n,effectiveState:u,dispatch:c,controller:p,actions:l}),[n,u,p,l]),children:e})}function C(e,t){let n=u(()=>{e({type:`OPEN`})},[e]),r=u(()=>{e({type:`CLOSE`})},[e]);return d(()=>({open:n,close:r,actions:t}),[n,r,t])}function w(n,r,i){let a=p(n);a.current=n;let o=p(i);o.current=i;let s=p(r);s.current=r;let{i18n:c}=e(),l=p(c);l.current=c;let f=u(e=>{let n=o.current;s.current({type:`SUBMIT`,input:e});let r=new AbortController,i={sourceAssetSymbol:e.sourceAssetSymbol,sourceChainId:e.sourceChainId,amount:e.amount,receiveTokenSymbol:e.receiveTokenSymbol,receiveChainId:e.receiveChainId,recipientAddress:e.recipientAddress};n.submitWithdrawal(i,r.signal).then(e=>{r.signal.aborted||s.current({type:`SUBMIT_CONFIRMED`,tx:e})}).catch(n=>{r.signal.aborted||s.current({type:`SUBMIT_FAILED`,failure:t(n,l.current._(h)),input:e})})},[]),m=u(()=>{s.current({type:`CLOSE`})},[]),g=u(()=>{s.current({type:`RESET`})},[]),_=u(()=>{s.current({type:`CLEAR_NOTICE`})},[]);return d(()=>({submit:f,close:m,reset:g,clearNotice:_}),[f,m,g,_])}function T(t,r,i){let a=p(t);a.current=t;let{i18n:o}=e(),s=p(o);s.current=o,n(i,(e,t)=>{if(a.current.name===`inProgress`){if(e===`succeeded`){r({type:`SETTLEMENT_SUCCEEDED`});return}if(e===`failed`){let e=t.settlement,n=e.status===`ready`||e.status===`stale`?e.payload:null,i=n&&n.kind===`failed`?{reason:s.current._(g),code:n.failureKind}:void 0;r({type:`SETTLEMENT_FAILED`,...i?{failure:i}:{}})}}})}export{S as WithdrawControllerProvider,v as useControllerContext,x as useWithdrawActions,b as useWithdrawEffectiveState,y as useWithdrawState};
1
+ "use client";import{useLingui as e}from"../../../shared/i18n/useLingui.js";import"../../../i18n/index.js";import{toFailure as t}from"../../../shared/orchestrator/toFailure.js";import{useDriverSettlementListener as n}from"../../../shared/orchestrator/useDriverSettlementListener.js";import{useEffectiveState as r}from"../../../shared/orchestrator/useEffectiveState.js";import{useSettlementWatcher as i}from"../../../shared/orchestrator/useSettlementWatcher.js";import"../../../shared/orchestrator/index.js";import{useWithdrawBindingsRef as a}from"../bindings/WithdrawBindings.js";import"../bindings/index.js";import{useWithdrawDriverInstance as o}from"../driver/context.js";import{initialState as s,reducer as c}from"./reducer.js";import{createContext as l,use as u,useCallback as d,useMemo as f,useReducer as p,useRef as m}from"react";import{jsx as h}from"react/jsx-runtime";const g={id:`ldK3jJ`,message:`Failed to submit withdrawal.`},_={id:`kUFhUv`,message:`Withdrawal failed.`},v={id:`srsA0x`,message:`Withdrawal declined.`},y=l(null);y.displayName=`WithdrawControllerContext`;function b(){let e=u(y);if(!e)throw Error(`useWithdraw / WithdrawControllerProvider must be used inside <KitProvider withdraw={…} />. Mount KitProvider once at the host's app root with a withdraw driver.`);return e}function x(){return u(y)}function S(){return b().state}function C(){return b().effectiveState}function w(){return b().actions}function T({children:e}){let t=o(),[n,a]=p(c,s),l=D(n,a,t),u=n.name===`inProgress`?{form:n.ctx.input,submittedAt:n.ctx.submittedAt,...n.ctx.tx?{tx:n.ctx.tx}:{}}:void 0;i(t,u,u?`${u.submittedAt}|${u.tx?.hash??``}`:void 0),O(n,a,t);let d=r(n),m=E(a,l,t);return h(y,{value:f(()=>({state:n,effectiveState:d,dispatch:a,controller:m,actions:l}),[n,d,m,l]),children:e})}function E(e,t,n){let r=m(n);r.current=n;let i=d(()=>{r.current.arm(),e({type:`OPEN`})},[e]),a=d(()=>{e({type:`CLOSE`})},[e]);return f(()=>({open:i,close:a,actions:t}),[i,a,t])}function D(n,r,i){let o=m(n);o.current=n;let s=m(i);s.current=i;let c=m(r);c.current=r;let{i18n:l}=e(),u=m(l);u.current=l;let p=a(),h=d(e=>{let n=s.current;c.current({type:`SUBMIT`,input:e});let r=new AbortController,i={sourceAssetSymbol:e.sourceAssetSymbol,sourceChainId:e.sourceChainId,amount:e.amount,receiveTokenSymbol:e.receiveTokenSymbol,receiveChainId:e.receiveChainId,recipientAddress:e.recipientAddress},a={beginProcessing(e){c.current({type:`BEGIN_PROCESSING`,submittedAt:Date.now(),...e?{tx:e}:{}})},setTxHash(e){c.current({type:`SET_TX_HASH`,tx:e,submittedAt:Date.now()})},fail(e){c.current({type:`MARK_FAILED`,...e?{failure:e}:{}})},decline(){c.current({type:`SUBMIT_FAILED`,failure:{reason:u.current._(v),code:`UserRejectedRequestError`},input:e})},succeed(){c.current({type:`MARK_SUCCEEDED`})}};n.prepareWithdrawal(i,r.signal).then(i=>{if(r.signal.aborted)return;let o=p.current.onSubmit;if(!o){c.current({type:`SUBMIT_FAILED`,failure:t(Error(`WithdrawDialog onSubmit is missing.`),u.current._(g)),input:e});return}let s=n.getSnapshot().quote,l=s.status===`ready`||s.status===`stale`?s.payload:void 0;try{let n=o({form:e,depositTarget:i.depositTarget,correlation:i.correlation,...l?{quote:l}:{}},a,r.signal);n&&typeof n.catch==`function`&&n.catch(n=>{r.signal.aborted||c.current({type:`SUBMIT_FAILED`,failure:t(n,u.current._(g)),input:e})})}catch(n){if(r.signal.aborted)return;c.current({type:`SUBMIT_FAILED`,failure:t(n,u.current._(g)),input:e})}}).catch(n=>{r.signal.aborted||c.current({type:`SUBMIT_FAILED`,failure:t(n,u.current._(g)),input:e})})},[]),_=d(()=>{c.current({type:`CLOSE`})},[]),y=d(()=>{c.current({type:`RESET`})},[]),b=d(()=>{c.current({type:`CLEAR_NOTICE`})},[]);return f(()=>({submit:h,close:_,reset:y,clearNotice:b}),[h,_,y,b])}function O(t,r,i){let a=m(t);a.current=t;let{i18n:o}=e(),s=m(o);s.current=o,n(i,(e,t)=>{if(a.current.name===`inProgress`){if(e===`succeeded`){r({type:`SETTLEMENT_SUCCEEDED`});return}if(e===`failed`){let e=t.settlement,n=e.status===`ready`||e.status===`stale`?e.payload:null,i=n&&n.kind===`failed`?{reason:s.current._(_),code:n.failureKind}:void 0;r({type:`SETTLEMENT_FAILED`,...i?{failure:i}:{}})}}})}export{T as WithdrawControllerProvider,b as useControllerContext,x as useOptionalControllerContext,w as useWithdrawActions,C as useWithdrawEffectiveState,S as useWithdrawState};
@@ -1,4 +1,4 @@
1
1
  import { FailureInfo } from "../../../shared/orchestrator/types.js";
2
2
  import { WithdrawActions, WithdrawController, WithdrawEvent, WithdrawState, WithdrawStateName, WithdrawalFormSnapshot } from "./types.js";
3
3
  import { useWithdrawState } from "./controller.js";
4
- import { useWithdraw } from "./useWithdraw.js";
4
+ import { useOptionalWithdraw, usePrefetchWithdraw, useWithdraw } from "./useWithdraw.js";
@@ -1 +1 @@
1
- import{isUserRejectionFailure as e}from"../../../shared/orchestrator/userRejection.js";import"../../../shared/orchestrator/index.js";const t={name:`closed`};function n(e,t){switch(e.name){case`closed`:return r(t);case`form`:return i(e,t);case`submitting`:return a(e,t);case`inProgress`:return o(e,t);case`success`:return s(e,t);case`error`:return c(e,t);default:return l(e)}}function r(e){return e.type===`OPEN`?{name:`form`}:{name:`closed`}}function i(e,t){switch(t.type){case`SUBMIT`:return{name:`submitting`,ctx:{input:t.input}};case`CLEAR_NOTICE`:return e.ctx?.notice?{name:`form`}:e;case`CLOSE`:return{name:`closed`};default:return e}}function a(t,n){switch(n.type){case`SUBMIT_CONFIRMED`:return{name:`inProgress`,ctx:{input:t.ctx.input,tx:n.tx}};case`SUBMIT_FAILED`:return e(n.failure)?{name:`form`,ctx:{notice:n.failure.reason}}:{name:`error`,ctx:{input:n.input,failure:n.failure}};case`CLOSE`:return{name:`closed`};default:return t}}function o(e,t){switch(t.type){case`SETTLEMENT_SUCCEEDED`:return{name:`success`,ctx:{input:e.ctx.input,tx:e.ctx.tx}};case`SETTLEMENT_FAILED`:return{name:`error`,ctx:{input:e.ctx.input,tx:e.ctx.tx,...t.failure?{failure:t.failure}:{}}};case`CLOSE`:return{name:`closed`};default:return e}}function s(e,t){switch(t.type){case`RESET`:return{name:`form`};case`CLOSE`:return{name:`closed`};default:return e}}function c(e,t){switch(t.type){case`RESET`:return{name:`form`};case`CLOSE`:return{name:`closed`};default:return e}}function l(e){throw Error(`Unhandled withdraw state: ${JSON.stringify(e)}`)}export{t as initialState,n as reducer};
1
+ import{isUserRejectionFailure as e}from"../../../shared/orchestrator/userRejection.js";import"../../../shared/orchestrator/index.js";const t={name:`closed`};function n(e,t){switch(e.name){case`closed`:return r(t);case`form`:return i(e,t);case`submitting`:return a(e,t);case`inProgress`:return o(e,t);case`success`:return s(e,t);case`error`:return c(e,t);default:return l(e)}}function r(e){return e.type===`OPEN`?{name:`form`}:{name:`closed`}}function i(e,t){switch(t.type){case`SUBMIT`:return{name:`submitting`,ctx:{input:t.input}};case`CLEAR_NOTICE`:return e.ctx?.notice?{name:`form`}:e;case`CLOSE`:return{name:`closed`};default:return e}}function a(t,n){switch(n.type){case`BEGIN_PROCESSING`:return{name:`inProgress`,ctx:{input:t.ctx.input,submittedAt:n.submittedAt,...n.tx?{tx:n.tx}:{}}};case`SET_TX_HASH`:return{name:`inProgress`,ctx:{input:t.ctx.input,submittedAt:n.submittedAt,tx:n.tx}};case`MARK_SUCCEEDED`:return{name:`success`,ctx:{input:t.ctx.input}};case`MARK_FAILED`:return{name:`error`,ctx:{input:t.ctx.input,...n.failure?{failure:n.failure}:{}}};case`SUBMIT_FAILED`:return e(n.failure)?{name:`form`,ctx:{notice:n.failure.reason}}:{name:`error`,ctx:{input:n.input,failure:n.failure}};case`CLOSE`:return{name:`closed`};default:return t}}function o(e,t){switch(t.type){case`SET_TX_HASH`:return{name:`inProgress`,ctx:{...e.ctx,tx:t.tx}};case`BEGIN_PROCESSING`:return{name:`inProgress`,ctx:{input:e.ctx.input,submittedAt:e.ctx.submittedAt,...e.ctx.tx?{tx:e.ctx.tx}:t.tx?{tx:t.tx}:{}}};case`MARK_SUCCEEDED`:return{name:`success`,ctx:{input:e.ctx.input,...e.ctx.tx?{tx:e.ctx.tx}:{}}};case`MARK_FAILED`:return{name:`error`,ctx:{input:e.ctx.input,...e.ctx.tx?{tx:e.ctx.tx}:{},...t.failure?{failure:t.failure}:{}}};case`SETTLEMENT_SUCCEEDED`:return{name:`success`,ctx:{input:e.ctx.input,...e.ctx.tx?{tx:e.ctx.tx}:{}}};case`SETTLEMENT_FAILED`:return{name:`error`,ctx:{input:e.ctx.input,...e.ctx.tx?{tx:e.ctx.tx}:{},...t.failure?{failure:t.failure}:{}}};case`CLOSE`:return{name:`closed`};default:return e}}function s(e,t){switch(t.type){case`RESET`:return{name:`form`};case`CLOSE`:return{name:`closed`};default:return e}}function c(e,t){switch(t.type){case`RESET`:return{name:`form`};case`CLOSE`:return{name:`closed`};default:return e}}function l(e){throw Error(`Unhandled withdraw state: ${JSON.stringify(e)}`)}export{t as initialState,n as reducer};
@@ -1,6 +1,7 @@
1
1
  import { TxRef } from "../../../shared/driver/types.js";
2
2
  import { FailureInfo } from "../../../shared/orchestrator/types.js";
3
-
3
+ import { WithdrawalQuotePayload } from "../driver/payloads.js";
4
+ import { WithdrawPreparation } from "../driver/types.js";
4
5
  //#region src/flows/withdraw/orchestrator/types.d.ts
5
6
  /**
6
7
  * Form values captured at submit time. The orchestrator carries this snapshot through every
@@ -20,24 +21,34 @@ interface WithdrawalFormSnapshot {
20
21
  receiveTokenSymbol: string;
21
22
  /** Receive-side chain id (EIP-155 numeric). */
22
23
  receiveChainId: number;
24
+ /**
25
+ * Pre-formatted USD figure the form displayed under the amount input at submit time. Carried
26
+ * through the FSM so the in-progress / success heroes can render the same dollar value the
27
+ * user just saw on the form, before the indexer prices the settlement legs. Optional because
28
+ * the form's USD computation already returns `undefined` for invalid amounts; the snapshot
29
+ * mirrors that. Pre-formatted (locale-aware) — the orchestrator does not re-format.
30
+ */
31
+ amountUsd?: string;
23
32
  }
24
33
  /**
25
- * State machine state for the orchestrated withdraw dialog. Per-state discriminated `ctx` narrows
26
- * what data is available — illegal states (e.g. `inProgress` without a tx ref) are
27
- * unrepresentable.
34
+ * State machine state for the orchestrated withdraw dialog. Per-state discriminated `ctx`
35
+ * narrows what data is available.
28
36
  *
29
- * The reducer carries navigation intent only — entity-derived data (quote payload, settlement
30
- * payload, balances) lives on the driver and is read directly by widgets.
37
+ * **Host-paced lifecycle** (different from the old wagmi-signed model): the kit stays in
38
+ * `submitting` until the host's `onSubmit` callback calls one of the controller's actions
39
+ * (`beginProcessing`, `fail`, `succeed`). `inProgress` accepts an optional `tx` — the host may
40
+ * move the user into processing before a broadcast tx hash exists; the kit polls
41
+ * `gateway/{owner}` and best-matches the relevant settlement (destination tuple + amount +
42
+ * submit-time window) until the host supplies a tx hash via `setTxHash`. `success` / `error`
43
+ * similarly accept optional `tx` since the host may declare a terminal verdict directly.
31
44
  */
32
45
  type WithdrawState = {
33
46
  name: "closed";
34
47
  } | {
35
48
  name: "form";
36
49
  /**
37
- * Optional notice rendered inline near the submit footer. Currently set when the user
38
- * declines the wallet signature: the FSM lands the user back on the form (preserving
39
- * recipient + amount + receive selection) with `notice = "Signature declined…"` so they
40
- * can retry without losing context. Cleared on the next SUBMIT or CLOSE.
50
+ * Optional notice rendered inline near the submit footer. Cleared on the next SUBMIT
51
+ * or CLOSE.
41
52
  */
42
53
  ctx?: {
43
54
  notice?: string;
@@ -50,24 +61,28 @@ type WithdrawState = {
50
61
  } | {
51
62
  name: "inProgress";
52
63
  ctx: {
53
- input: WithdrawalFormSnapshot;
54
- tx: TxRef;
64
+ input: WithdrawalFormSnapshot; /** Unix-ms timestamp the host moved the FSM into processing (drives best-match windowing). */
65
+ submittedAt: number;
66
+ /**
67
+ * Source-chain broadcast hash, when the host has surfaced one via
68
+ * `actions.setTxHash`. Absent while the kit relies on the best-match heuristic.
69
+ */
70
+ tx?: TxRef;
55
71
  };
56
72
  } | {
57
73
  name: "success";
58
74
  ctx: {
59
75
  input: WithdrawalFormSnapshot;
60
- tx: TxRef;
76
+ tx?: TxRef;
61
77
  };
62
78
  } | {
63
79
  name: "error";
64
80
  ctx: {
65
81
  /**
66
82
  * Form snapshot captured at submit time. Set when error follows a submit attempt;
67
- * absent when the error path was reached without a known prior submit (currently
68
- * unreachable in V2 — kept optional so resume-style entries can re-use the slot).
83
+ * absent when the error path was reached without a known prior submit.
69
84
  */
70
- input?: WithdrawalFormSnapshot; /** Optional non-settlement failure (quote / submission rejection). */
85
+ input?: WithdrawalFormSnapshot; /** Optional non-settlement failure (quote / submission rejection, host-supplied failure). */
71
86
  failure?: FailureInfo; /** Source-chain broadcast tx hash when the error followed a successful broadcast. */
72
87
  tx?: TxRef;
73
88
  };
@@ -79,6 +94,16 @@ type WithdrawState = {
79
94
  type WithdrawStateName = WithdrawState["name"];
80
95
  /**
81
96
  * Reducer event union. Strict discriminated; no stringly-typed transitions.
97
+ *
98
+ * The host-paced lifecycle splits the old `SUBMIT_CONFIRMED { tx }` event into three pieces so
99
+ * the host can move the user forward at whichever step their backend actually completes:
100
+ *
101
+ * - `BEGIN_PROCESSING { tx?, submittedAt }` — host accepted the request; move to inProgress with
102
+ * or without a tx hash.
103
+ * - `SET_TX_HASH { tx }` — host surfaced a broadcast hash later; upgrade best-match polling to
104
+ * tx-anchored.
105
+ * - `MARK_SUCCEEDED` / `MARK_FAILED { failure? }` — host short-circuits to a terminal verdict
106
+ * (e.g. their own settlement verification ran independently of Stridge's poll).
82
107
  */
83
108
  type WithdrawEvent = {
84
109
  type: "OPEN";
@@ -88,12 +113,22 @@ type WithdrawEvent = {
88
113
  type: "SUBMIT";
89
114
  input: WithdrawalFormSnapshot;
90
115
  } | {
91
- type: "SUBMIT_CONFIRMED";
116
+ type: "BEGIN_PROCESSING";
117
+ submittedAt: number;
118
+ tx?: TxRef;
119
+ } | {
120
+ type: "SET_TX_HASH";
92
121
  tx: TxRef;
122
+ submittedAt: number;
93
123
  } | {
94
124
  type: "SUBMIT_FAILED";
95
125
  failure: FailureInfo;
96
126
  input: WithdrawalFormSnapshot;
127
+ } | {
128
+ type: "MARK_SUCCEEDED";
129
+ } | {
130
+ type: "MARK_FAILED";
131
+ failure?: FailureInfo;
97
132
  } | {
98
133
  type: "SETTLEMENT_SUCCEEDED";
99
134
  } | {
@@ -101,15 +136,7 @@ type WithdrawEvent = {
101
136
  failure?: FailureInfo;
102
137
  } | {
103
138
  type: "RESET";
104
- }
105
- /**
106
- * Drops the inline notice on the `form` state. Dispatched by the form widget when the user
107
- * starts editing again after a wallet-rejection landed them back on `form{notice}`. Mirror of
108
- * deposit's `regenerating → ready` transition (where the notice clears as a side-effect of
109
- * the next quote resolving) — withdraw's form has no FSM-driven phase to ride on, so the
110
- * widget signals it explicitly.
111
- */
112
- | {
139
+ } | {
113
140
  type: "CLEAR_NOTICE";
114
141
  };
115
142
  /**
@@ -134,9 +161,11 @@ interface WithdrawController {
134
161
  */
135
162
  interface WithdrawActions {
136
163
  /**
137
- * Submits the withdrawal through the driver. Dispatches `SUBMIT` synchronously (so the form
138
- * flips to the loading-button state) and then `SUBMIT_CONFIRMED` / `SUBMIT_FAILED` based on
139
- * the driver's `submitWithdrawal` resolution.
164
+ * Submits the withdrawal. Dispatches `SUBMIT` synchronously (so the form flips to the
165
+ * loading-button state) and then fires the host's `<WithdrawDialog onSubmit>` callback with
166
+ * the prepared UDA target + a `WithdrawSubmitActions` handle. The kit stays in `submitting`
167
+ * until the host calls one of those actions (`beginProcessing`, `setTxHash`, `decline`,
168
+ * `fail`, `succeed`).
140
169
  */
141
170
  submit(input: WithdrawalFormSnapshot): void;
142
171
  /** Close the dialog. Idempotent. */
@@ -147,10 +176,80 @@ interface WithdrawActions {
147
176
  */
148
177
  reset(): void;
149
178
  /**
150
- * Clear the form's inline notice (typically the post-rejection "Signature declined." hint).
151
- * No-op when there's no notice or the FSM isn't on `form`.
179
+ * Clear the form's inline notice. No-op when there's no notice or the FSM isn't on `form`.
152
180
  */
153
181
  clearNotice(): void;
154
182
  }
183
+ /**
184
+ * Payload the kit hands to the host's `<WithdrawDialog onSubmit>` callback. Carries everything
185
+ * the host needs to broadcast the source-chain transfer to the UDA (or to validate the request
186
+ * server-side before broadcasting / queueing).
187
+ */
188
+ interface WithdrawSubmitInput {
189
+ /** What the user picked on the form (recipient, amount, receive token + chain). */
190
+ form: WithdrawalFormSnapshot;
191
+ /** Where the host should send brand-currency funds to trigger the bridge. */
192
+ depositTarget: WithdrawPreparation["depositTarget"];
193
+ /** Stridge correlation slot — useful for backend logs / cross-system traces. */
194
+ correlation: WithdrawPreparation["correlation"];
195
+ /** Active quote payload at submit time, when one is available. */
196
+ quote?: WithdrawalQuotePayload;
197
+ }
198
+ /**
199
+ * Imperative handles the host's `onSubmit` callback receives. Each action advances the kit's
200
+ * FSM at the point the host's backend reaches the matching state. All actions are optional —
201
+ * the host calls only what fits their flow (e.g. backend pre-validates and accepts ⇒
202
+ * `beginProcessing()`; later the broadcast lands ⇒ `setTxHash({ hash })`; settlement watching
203
+ * via Stridge takes over from there). The kit also exposes a `signal` for cancellation when
204
+ * the user closes the dialog mid-submit.
205
+ */
206
+ interface WithdrawSubmitActions {
207
+ /**
208
+ * Move the FSM into `inProgress`. Pass `tx` if a broadcast hash already exists at this point;
209
+ * otherwise omit — the kit polls `gateway/{owner}` with a best-match heuristic until you
210
+ * call {@link setTxHash}. Idempotent — calling more than once is a no-op.
211
+ */
212
+ beginProcessing(tx?: TxRef): void;
213
+ /**
214
+ * Surface a broadcast hash mid-processing. Upgrades the watcher from best-match to
215
+ * tx-anchored. Legal from `inProgress` or `submitting` (auto-promotes to `inProgress`).
216
+ */
217
+ setTxHash(tx: TxRef): void;
218
+ /**
219
+ * Mark the withdraw failed. Legal from `submitting` (pre-broadcast rejection) and
220
+ * `inProgress` (post-broadcast failure). The optional `failure` carries a localized
221
+ * reason + machine code for analytics; omit when the host has nothing meaningful to
222
+ * report and just needs to terminate the flow.
223
+ *
224
+ * For user-rejection (the user said no in their wallet), prefer {@link decline} so the
225
+ * kit can emit `withdraw.submission.declined` instead of `withdraw.submission.failed`.
226
+ */
227
+ fail(failure?: FailureInfo): void;
228
+ /**
229
+ * Mark the withdraw as user-declined. Use when the user explicitly refused a wallet
230
+ * prompt or backed out of a host-side confirmation step. The kit routes the FSM back to
231
+ * `form{notice}` (same as the wallet-rejection heuristic) and emits
232
+ * `withdraw.submission.declined` on the unified bus — distinct from `*.failed` because
233
+ * declining is a user choice, not an error. Analytics that count `.failed` events stay
234
+ * accurate.
235
+ *
236
+ * Legal from `submitting`. When the host doesn't call this explicitly, the kit's
237
+ * built-in rejection heuristic still classifies wallet-rejection-shaped errors as
238
+ * declines automatically.
239
+ */
240
+ decline(): void;
241
+ /**
242
+ * Mark the withdraw succeeded directly. Useful when the host runs their own settlement
243
+ * verification independently of Stridge's poll. Legal from `submitting` and `inProgress`.
244
+ */
245
+ succeed(): void;
246
+ }
247
+ /**
248
+ * Host-supplied callback fired when the user submits the withdrawal form. The kit hands the
249
+ * callback the resolved {@link WithdrawSubmitInput} plus a {@link WithdrawSubmitActions} handle
250
+ * the host calls to advance the FSM. The kit does NOT await the callback's promise — the host
251
+ * is in control of pacing via the actions. The `signal` aborts when the user closes the dialog.
252
+ */
253
+ type WithdrawSubmitCallback = (input: WithdrawSubmitInput, actions: WithdrawSubmitActions, signal: AbortSignal) => void | Promise<void>;
155
254
  //#endregion
156
- export { WithdrawActions, WithdrawController, WithdrawEvent, WithdrawState, WithdrawStateName, WithdrawalFormSnapshot };
255
+ export { WithdrawActions, WithdrawController, WithdrawEvent, WithdrawState, WithdrawStateName, WithdrawSubmitActions, WithdrawSubmitCallback, WithdrawSubmitInput, WithdrawalFormSnapshot };
@@ -19,5 +19,40 @@ import { WithdrawController } from "./types.js";
19
19
  * ```
20
20
  */
21
21
  declare function useWithdraw(): WithdrawController;
22
+ /**
23
+ * Non-throwing variant of {@link useWithdraw} — returns `null` when called outside a
24
+ * `<KitProvider withdraw={…} />`. Lets hosts mount `<StridgeProvider />` conditionally
25
+ * (e.g. only after a wallet is connected) without descendants crashing the moment they render
26
+ * before the provider exists.
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * const withdraw = useOptionalWithdraw();
31
+ * return (
32
+ * <button onClick={() => withdraw?.open()} disabled={!withdraw}>
33
+ * Withdraw
34
+ * </button>
35
+ * );
36
+ * ```
37
+ */
38
+ declare function useOptionalWithdraw(): WithdrawController | null;
39
+ /**
40
+ * Headless prefetch handle for the withdraw driver. Returns a stable function that arms the
41
+ * driver — kicks off the deferred `supportedAssets` + initial `balance/onchain` bootstrap.
42
+ * Calling it before the user opens the dialog warms the cache so the subsequent
43
+ * `useWithdraw().open()` lands on populated data without a perceptible loading window.
44
+ *
45
+ * Fire-and-forget: returns `void`. Observe bootstrap state via
46
+ * `useWithdrawSnapshot().receiveOptions.status` if needed.
47
+ *
48
+ * ```tsx
49
+ * const withdraw = useWithdraw();
50
+ * const prefetchWithdraw = usePrefetchWithdraw();
51
+ * <button onMouseEnter={prefetchWithdraw} onClick={() => withdraw.open()}>Withdraw</button>;
52
+ * ```
53
+ *
54
+ * Idempotent — subsequent calls are no-ops while the driver is already armed.
55
+ */
56
+ declare function usePrefetchWithdraw(): () => void;
22
57
  //#endregion
23
- export { useWithdraw };
58
+ export { useOptionalWithdraw, usePrefetchWithdraw, useWithdraw };
@@ -1 +1 @@
1
- "use client";import{useControllerContext as e}from"./controller.js";function t(){return e().controller}export{t as useWithdraw};
1
+ "use client";import{useWithdrawDriverInstance as e}from"../driver/context.js";import{useControllerContext as t,useOptionalControllerContext as n}from"./controller.js";import{useCallback as r}from"react";function i(){return t().controller}function a(){return n()?.controller??null}function o(){let t=e();return r(()=>{t.arm()},[t])}export{a as useOptionalWithdraw,o as usePrefetchWithdraw,i as useWithdraw};
@@ -1,16 +1,6 @@
1
- import { WithdrawFormEventCallbacks } from "../../dialog/WithdrawDialogEventsContext.js";
2
- import { ComponentProps } from "react";
3
1
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
4
2
 
5
3
  //#region src/flows/withdraw/widgets/withdraw-form/WithdrawForm.d.ts
6
- type OrchestratedProps = ComponentProps<"div"> & {
7
- /**
8
- * Form-level event callbacks. Optional — when omitted, the form falls back to whatever the
9
- * enclosing `<WithdrawDialog>` provides via context. Hosts using `<WithdrawForm>` directly
10
- * (custom UI without the dialog) can pass callbacks here.
11
- */
12
- events?: WithdrawFormEventCallbacks;
13
- };
14
4
  /**
15
5
  * Orchestrated `WithdrawForm` widget. Reads source-side balances, the receive-options catalog,
16
6
  * and the active quote payload from the driver, drives the FSM via `useWithdrawActions().submit`,
@@ -21,9 +11,11 @@ type OrchestratedProps = ComponentProps<"div"> & {
21
11
  * Quote lifecycle: the form fires `driver.requestQuote(...)` (debounced ~400ms) whenever both
22
12
  * `recipientAddress` and `amount > 0` are populated and re-fires on receive-side changes. Stale
23
13
  * entity transitions keep showing the last-known payload until the user changes a field.
14
+ *
15
+ * Interaction events (`withdraw.recipient.changed`, `withdraw.amount.changed`, `withdraw.amount.maxed`,
16
+ * `withdraw.receive.token.changed`, `withdraw.receive.chain.changed`, `withdraw.submit.clicked`)
17
+ * flow through the unified event bus — the form takes no callback props.
24
18
  */
25
- declare function WithdrawForm({
26
- events: localEvents
27
- }: OrchestratedProps): _$react_jsx_runtime0.JSX.Element | null;
19
+ declare function WithdrawForm(): _$react_jsx_runtime0.JSX.Element | null;
28
20
  //#endregion
29
21
  export { WithdrawForm };
@@ -1 +1 @@
1
- "use client";import{useKitI18n as e}from"../../../../shared/i18n/useKitI18n.js";import{useLingui as t}from"../../../../shared/i18n/useLingui.js";import"../../../../i18n/index.js";import{useWithdrawDriverInstance as n,useWithdrawSnapshot as r}from"../../driver/context.js";import{useWithdrawActions as i,useWithdrawEffectiveState as ee}from"../../orchestrator/controller.js";import{parseAmountInputValue as a}from"../../../../shared/ui/AmountInput/utils.js";import"../../../../shared/ui/AmountInput/index.js";import{toAssetDescriptor as o}from"../../../../shared/widgets/asset-descriptor.js";import{useQuoteCountdown as te}from"../../../../shared/quote/useQuoteCountdown.js";import"../../../../shared/quote/index.js";import{WithdrawForm as s}from"./compound/WithdrawForm.js";import"./compound/index.js";import{useWithdrawDialogEvents as ne}from"../../dialog/WithdrawDialogEventsContext.js";import{isValidEvmAddress as re,resolveSubmitLabel as ie}from"./validation.js";import{useCallback as c,useEffect as l,useMemo as u,useRef as d,useState as f}from"react";import{jsx as p,jsxs as ae}from"react/jsx-runtime";import{useAccount as oe}from"wagmi";function m({events:m}){let h=r(),g=n(),_=ee(),v=i(),{_:y}=t(),b=ne(),se=u(()=>({...b,...m??{}}),[b,m]),x=d(se);x.current=se;let{address:ce}=oe(),le=ce??``,[S,ue]=f(``),[de,fe]=f(``),C=_.name===`submitting`,w=_.name===`form`?_.ctx?.notice:void 0,T=d(w);T.current=w;let E=h.withdrawableBalances.status===`ready`||h.withdrawableBalances.status===`stale`?h.withdrawableBalances.payload[0]:void 0,D=u(()=>o(E)??{symbol:`USDC`},[E]),pe=u(()=>o(E?{symbol:E.networkName,eip155Id:E.eip155Id,isNative:!0,logoUrl:E.chainLogoUrl}:void 0)??{symbol:`BSC`},[E]),me=E?{amount:E.amount.formatted,symbol:E.symbol}:void 0,O=h.receiveOptions.status===`ready`||h.receiveOptions.status===`stale`?h.receiveOptions.payload:[],k=E?.eip155Id?Number(E.eip155Id):void 0,A=E?.symbol??D.symbol,j=u(()=>{let e=new Map;for(let t of O)for(let n of t.tokens){let r=n.symbol.toUpperCase(),i=e.get(r);i?i.push({chain:t,token:n}):e.set(r,[{chain:t,token:n}])}return e},[O]),M=u(()=>{if(j.size===0)return;let e=A.toUpperCase();return j.has(e)?e:j.keys().next().value},[j,A]),N=c(e=>{let t=j.get(e);if(!(!t||t.length===0))return(k===void 0?void 0:t.find(e=>e.chain.eip155Id===k))??t[0]},[j,k]),[P,F]=f(void 0),[I,L]=f(void 0);l(()=>{if(I||!M)return;let e=N(M);e&&(F(e.chain),L(e.token))},[M,N,I]);let R=c(()=>{T.current&&v.clearNotice()},[v]),he=c(e=>{R(),ue(e),x.current.onRecipientChanged?.(e)},[R]),z=e().locale,B=c(e=>{R(),fe(e);let t=a(e,z);x.current.onAmountChanged?.({raw:e,numeric:t})},[R,z]),V=c(e=>{R();let t=e.symbol.toUpperCase(),n=j.get(t)?.find(e=>e.chain.eip155Id===P?.eip155Id)??N(t);n&&(F(n.chain),L(n.token),x.current.onReceiveTokenChanged?.(n.token),n.chain.eip155Id!==P?.eip155Id&&x.current.onReceiveChainChanged?.(n.chain))},[R,j,N,P?.eip155Id]),ge=c(e=>{R(),F(e);let t=I?.symbol.toUpperCase(),n=(t?e.tokens.find(e=>e.symbol.toUpperCase()===t):void 0)??e.tokens[0];n&&L(n),x.current.onReceiveChainChanged?.(e),n&&n.symbol!==I?.symbol&&x.current.onReceiveTokenChanged?.(n)},[R,I?.symbol]),H=a(de,z),U=H!==null&&H>0,_e=S.trim(),ve=_e.length>0,W=re(_e),G=P!==void 0&&I!==void 0,K=U&&E!==void 0&&H>E.amount.value,[q,ye]=f(null),J=(h.quote.status===`ready`||h.quote.status===`stale`)&&ve&&U&&G&&q!==null&&q.recipient===S&&q.amount===H&&q.receiveChainId===P.eip155Id&&q.receiveSymbol===I.symbol?h.quote.payload:void 0,be=u(()=>j.size===0?[D]:[...j.values()].map(e=>{let t=e[0];return o({symbol:t.token.symbol,eip155Id:t.chain.eip155Id,address:t.token.address,isNative:t.token.isNative,logoUrl:t.token.assetLogoUrl})??{symbol:t.token.symbol}}),[j,D]),xe=u(()=>{let e=I?.symbol.toUpperCase(),t=e?j.get(e):void 0;return(t?t.map(e=>e.chain):O).map(e=>o({symbol:e.networkName,eip155Id:e.eip155Id,isNative:!0,logoUrl:e.chainLogoUrl})??{symbol:e.networkName})},[I?.symbol,j,O]),Se=I?o({symbol:I.symbol,eip155Id:P?.eip155Id,address:I.address,isNative:I.isNative,logoUrl:I.assetLogoUrl}):D,Ce=P?o({symbol:P.networkName,eip155Id:P.eip155Id,isNative:!0,logoUrl:P.chainLogoUrl}):pe,we=u(()=>{if(J?.breakdown)return{route:J.breakdown.selectedRoute?.label,networkCost:J.breakdown.networkCost?.formatted,priceImpact:J.breakdown.priceImpact?.formatted}},[J]),Te=u(()=>{if(U)return J?.receiveAmountUsd?J.receiveAmountUsd.formatted:`$${H.toFixed(2)}`},[H,U,J]),Ee=J&&U?J.receiveAmount.formatted:void 0,De=J?.receiveAmountUsd?.formatted,Y=W&&U&&!K&&G&&J===void 0&&h.quote.status!==`error`,X=W&&U&&!K&&G&&J!==void 0,Oe=te({expiresAt:J?.expiresAt,enabled:X}),ke=X&&J?J.quoteTotalSeconds:void 0,[Z,Q]=f(!1);l(()=>{Q(!1)},[S,H,P?.eip155Id,I?.symbol,_.name]),l(()=>{if(!X||!J||_.name!==`form`||Z)return;let e=Math.max(0,J.expiresAt-Date.now()),t=setTimeout(()=>{Q(!0)},e);return()=>clearTimeout(t)},[X,J,_.name,Z]),l(()=>{if(!Z||_.name!==`form`||k===void 0||!P||!I||!W||!U||K)return;let e=new AbortController,t={recipient:S,amount:H??0,receiveChainId:P.eip155Id,receiveSymbol:I.symbol},n={sourceAssetSymbol:A,sourceChainId:k,amount:H??0,receiveTokenSymbol:I.symbol,receiveChainId:P.eip155Id,recipientAddress:S};return x.current.onQuoteRequested?.(n),g.requestQuote(n,e.signal).then(()=>{e.signal.aborted||ye(t)}).catch(()=>{}).finally(()=>{e.signal.aborted||Q(!1)}),()=>e.abort()},[Z,g,S,H,W,U,K,k,A,P,I,_.name]);let $=!W||!U||K||!G||Y||Z,Ae=ie({enterRecipientAddress:y({id:`nr03QI`,message:`Enter Recipient Address`}),enterValidRecipientAddress:y({id:`GZPxmc`,message:`Enter Valid Recipient Address`}),enterAmount:y({id:`yH9V_J`,message:`Enter Amount`}),insufficientBalance:y({id:`N2DUxS`,message:`Insufficient Balance`}),regeneratingQuote:y({id:`Ly6geA`,message:`Regenerating quote…`}),estimatingQuote:y({id:`Uevt3L`,message:`Estimating quote`})},{isRecipientFilled:ve,isRecipientValid:W,isAmountValid:U,exceedsBalance:K,quoteEstimating:Y,quoteRegenerating:Z}),je=d(null);l(()=>{if(je.current?.abort(),!W||!U||K||!G||_.name!==`form`||k===void 0)return;let e=new AbortController;je.current=e;let t={recipient:S,amount:H,receiveChainId:P.eip155Id,receiveSymbol:I.symbol},n=setTimeout(()=>{let n={sourceAssetSymbol:A,sourceChainId:k,amount:H,receiveTokenSymbol:I.symbol,receiveChainId:P.eip155Id,recipientAddress:S};x.current.onQuoteRequested?.(n),g.requestQuote(n,e.signal).then(()=>{e.signal.aborted||ye(t)}).catch(()=>{})},400);return()=>{clearTimeout(n),e.abort()}},[g,S,H,W,U,K,G,k,A,P?.eip155Id,I?.symbol,_.name]);let Me=c(()=>{E&&B(E.amount.formatted)},[E,B]),Ne=c(()=>{C||$||k===void 0||!P||!I||v.submit({sourceAssetSymbol:A,sourceChainId:k,amount:H??0,recipientAddress:S,receiveTokenSymbol:I.symbol,receiveChainId:P.eip155Id})},[v,H,k,A,P,I,S,$,C]),Pe=c(e=>{let t=O.find(t=>String(t.eip155Id)===String(e.chainId));t&&ge(t)},[ge,O]),Fe=c(e=>{let t=e.symbol.toUpperCase(),n=j.get(t);!n||n.length===0||V((n.find(e=>e.chain.eip155Id===P?.eip155Id)??n[0]).token)},[V,j,P?.eip155Id]);return _.name!==`form`&&_.name!==`submitting`?null:ae(s,{recipientAddress:S,onRecipientChange:he,connectedAddress:le,amount:de,onAmountChange:B,onAmountMax:Me,sourceAsset:D,sourceChain:pe,receiveAsset:Se,receiveChain:Ce,receiveAssetOptions:be,onReceiveAssetChange:Fe,receiveChainOptions:xe,onReceiveChainChange:Pe,balance:me,amountUsd:Te,receiveAmount:Ee,receiveAmountUsd:De,breakdown:we,quoteEstimating:Y,quoteRegenerating:Z,...Oe===void 0?{}:{quoteSeconds:Oe},...ke===void 0?{}:{quoteTotalSeconds:ke},submitting:C,submitDisabled:$,submitLabel:Ae,...w?{notice:w}:{},onSubmit:Ne,children:[p(s.Header,{}),ae(s.Body,{children:[p(s.RecipientField,{}),p(s.AmountField,{}),p(s.ReceiveSelectors,{}),p(s.BreakdownCard,{})]}),p(s.Footer,{})]})}export{m as WithdrawForm};
1
+ "use client";import{isValidAddressForChainType as e}from"../../../../shared/chains/index.js";import{useKitI18n as t}from"../../../../shared/i18n/useKitI18n.js";import{useLingui as n}from"../../../../shared/i18n/useLingui.js";import"../../../../i18n/index.js";import{useWithdrawBindingsValue as r}from"../../bindings/WithdrawBindings.js";import"../../bindings/index.js";import{useWithdrawDriverInstance as ee,useWithdrawSnapshot as te}from"../../driver/context.js";import{useWithdrawActions as ne,useWithdrawEffectiveState as re}from"../../orchestrator/controller.js";import{formatTokenAmount as ie}from"../../../../shared/format/formatTokenAmount.js";import{useKitEmitter as ae}from"../../../../events/emit/useKitEmitter.js";import"../../../../events/emit/index.js";import{parseAmountInputValue as oe}from"../../../../shared/ui/AmountInput/utils.js";import"../../../../shared/ui/AmountInput/index.js";import{toAssetDescriptor as i}from"../../../../shared/widgets/asset-descriptor.js";import{useQuoteCountdown as se}from"../../../../shared/quote/useQuoteCountdown.js";import"../../../../shared/quote/index.js";import{WithdrawForm as a}from"./compound/WithdrawForm.js";import"./compound/index.js";import{resolveSubmitLabel as ce}from"./validation.js";import{useCallback as o,useEffect as s,useMemo as c,useRef as le,useState as l}from"react";import{jsx as u,jsxs as ue}from"react/jsx-runtime";function d(){let d=te(),f=ee(),p=re(),m=ne(),{i18n:de,_:h}=n(),g=ae(),{balance:_,suggestedRecipient:fe}=r(),[v,pe]=l(``),[me,he]=l(``),ge=p.name===`submitting`,y=p.name===`form`?p.ctx?.notice:void 0,_e=le(y);_e.current=y;let b=d.withdrawableBalances.status===`ready`||d.withdrawableBalances.status===`stale`?d.withdrawableBalances.payload[0]:void 0,x=c(()=>i(b)??{symbol:`USDC`},[b]),ve=c(()=>i(b?{symbol:b.networkName,eip155Id:b.eip155Id,isNative:!0,logoUrl:b.chainLogoUrl}:void 0)??{symbol:`BSC`},[b]),S=typeof _==`number`?_:typeof _==`object`?_.amount:void 0,ye=b?.symbol??x.symbol,C=S??b?.amount.value,be=S===void 0?b?.symbol:ye,w=C!==void 0&&be!==void 0?{amount:S===void 0?b?.amount.formatted??ie(C,de):ie(S,de),symbol:be}:void 0,T=d.receiveOptions.status===`ready`||d.receiveOptions.status===`stale`?d.receiveOptions.payload:[],E=b?.eip155Id?Number(b.eip155Id):void 0,D=b?.symbol??x.symbol,O=c(()=>{let e=new Map;for(let t of T)for(let n of t.tokens){let r=n.symbol.toUpperCase(),ee=e.get(r);ee?ee.push({chain:t,token:n}):e.set(r,[{chain:t,token:n}])}return e},[T]),k=c(()=>{if(O.size===0)return;let e=D.toUpperCase();return O.has(e)?e:O.keys().next().value},[O,D]),A=o(e=>{let t=O.get(e);if(!(!t||t.length===0))return(E===void 0?void 0:t.find(e=>e.chain.eip155Id===E))??t[0]},[O,E]),[j,M]=l(void 0),[N,P]=l(void 0);s(()=>{if(N||!k)return;let e=A(k);e&&(M(e.chain),P(e.token))},[k,A,N]);let F=o(()=>{_e.current&&m.clearNotice()},[m]),xe=o(e=>{F(),pe(e),g({type:`withdraw.recipient.changed`,flow:`withdraw`,tier:`ui`,payload:{value:e}})},[F,g]),I=t().locale,L=o(e=>{F(),he(e),g({type:`withdraw.amount.changed`,flow:`withdraw`,tier:`ui`,payload:{raw:e,numeric:oe(e,I)}})},[F,g,I]),Se=o(e=>{F();let t=e.symbol.toUpperCase(),n=O.get(t)?.find(e=>e.chain.eip155Id===j?.eip155Id)??A(t);n&&(M(n.chain),P(n.token),g({type:`withdraw.receive.token.changed`,flow:`withdraw`,tier:`ui`,payload:{token:n.token}}),n.chain.eip155Id!==j?.eip155Id&&g({type:`withdraw.receive.chain.changed`,flow:`withdraw`,tier:`ui`,payload:{chain:n.chain}}))},[F,g,O,A,j?.eip155Id]),Ce=o(e=>{F(),M(e);let t=N?.symbol.toUpperCase(),n=(t?e.tokens.find(e=>e.symbol.toUpperCase()===t):void 0)??e.tokens[0];n&&P(n),g({type:`withdraw.receive.chain.changed`,flow:`withdraw`,tier:`ui`,payload:{chain:e}}),n!==void 0&&(N===void 0||n.address!==N.address)&&g({type:`withdraw.receive.token.changed`,flow:`withdraw`,tier:`ui`,payload:{token:n}})},[F,g,N]),R=oe(me,I),z=R!==null&&R>0,we=v.trim(),Te=we.length>0,Ee=j?.chainType??`unknown`,B=e(we,Ee),V=j!==void 0&&N!==void 0,H=z&&C!==void 0&&R>C,U=d.minAmountUsd,W=d.maxAmountUsd,De=b?.amountUsd&&b.amount.value>0?b.amountUsd.value/b.amount.value:void 0,G=De!==void 0&&R!==null?R*De:void 0,K=z&&G!==void 0&&U!==void 0&&U.value>0&&G<U.value,q=z&&G!==void 0&&W!==void 0&&W.value>0&&G>W.value,[J,Oe]=l(null),Y=(d.quote.status===`ready`||d.quote.status===`stale`)&&Te&&z&&V&&J!==null&&J.recipient===v&&J.amount===R&&J.receiveChainId===j.eip155Id&&J.receiveSymbol===N.symbol?d.quote.payload:void 0,ke=c(()=>O.size===0?[x]:[...O.values()].map(e=>{let t=e[0];return i({symbol:t.token.symbol,eip155Id:t.chain.eip155Id,address:t.token.address,isNative:t.token.isNative,logoUrl:t.token.assetLogoUrl})??{symbol:t.token.symbol}}),[O,x]),Ae=c(()=>{let e=N?.symbol.toUpperCase(),t=e?O.get(e):void 0;return(t?t.map(e=>e.chain):T).map(e=>i({symbol:e.networkName,eip155Id:e.eip155Id,isNative:!0,logoUrl:e.chainLogoUrl})??{symbol:e.networkName})},[N?.symbol,O,T]),je=N?i({symbol:N.symbol,eip155Id:j?.eip155Id,address:N.address,isNative:N.isNative,logoUrl:N.assetLogoUrl}):x,Me=j?i({symbol:j.networkName,eip155Id:j.eip155Id,isNative:!0,logoUrl:j.chainLogoUrl}):ve,Ne=c(()=>{if(Y?.breakdown)return{route:Y.breakdown.selectedRoute?.label,networkCost:Y.breakdown.networkCost?.formatted,priceImpact:Y.breakdown.priceImpact?.formatted}},[Y]),X=c(()=>{if(z)return Y?.receiveAmountUsd?Y.receiveAmountUsd.formatted:`$${R.toFixed(2)}`},[R,z,Y]),Pe=Y&&z?Y.receiveAmount.formatted:void 0,Fe=Y?.receiveAmountUsd?.formatted,Ie=B&&z&&!H&&!K&&!q&&V&&Y===void 0&&d.quote.status!==`error`,Z=B&&z&&!H&&!K&&!q&&V&&Y!==void 0,Le=se({expiresAt:Y?.expiresAt,enabled:Z}),Re=Z&&Y?Y.quoteTotalSeconds:void 0,[Q,ze]=l(!1);s(()=>{ze(!1)},[v,R,j?.eip155Id,N?.symbol,p.name]),s(()=>{if(!Z||!Y||p.name!==`form`||Q)return;let e=Math.max(0,Y.expiresAt-Date.now()),t=setTimeout(()=>{ze(!0),g({type:`withdraw.quote.expired`,flow:`withdraw`,tier:`flow`,payload:{}})},e);return()=>clearTimeout(t)},[g,Z,Y,p.name,Q]),s(()=>{if(!Q||p.name!==`form`||E===void 0||!j||!N||!B||!z||H||K||q)return;let e=new AbortController,t={recipient:v,amount:R??0,receiveChainId:j.eip155Id,receiveSymbol:N.symbol},n={sourceAssetSymbol:D,sourceChainId:E,amount:R??0,receiveTokenSymbol:N.symbol,receiveChainId:j.eip155Id,recipientAddress:v};return g({type:`withdraw.quote.requested`,flow:`withdraw`,tier:`flow`,payload:{input:n}}),f.requestQuote(n,e.signal).then(()=>{e.signal.aborted||Oe(t)}).catch(()=>{}).finally(()=>{e.signal.aborted||ze(!1)}),()=>e.abort()},[g,Q,f,v,R,B,z,H,K,q,E,D,j,N,p.name]);let $=!B||!z||H||K||q||!V||Ie||Q,Be=ce({enterRecipientAddress:h({id:`nr03QI`,message:`Enter Recipient Address`}),enterValidRecipientAddress:h({id:`GZPxmc`,message:`Enter Valid Recipient Address`}),enterAmount:h({id:`yH9V_J`,message:`Enter Amount`}),insufficientBalance:h({id:`N2DUxS`,message:`Insufficient Balance`}),...U?{belowMinimumAmount:h({id:`WkRH60`,message:`Min {0}`,values:{0:U.formatted}})}:{},...W?{aboveCapAmount:h({id:`AHyker`,message:`Max {0}`,values:{0:W.formatted}})}:{},regeneratingQuote:h({id:`Ly6geA`,message:`Regenerating quote…`}),estimatingQuote:h({id:`Uevt3L`,message:`Estimating quote`})},{isRecipientFilled:Te,isRecipientValid:B,isAmountValid:z,exceedsBalance:H,belowMinimum:K,aboveCap:q,quoteEstimating:Ie,quoteRegenerating:Q}),Ve=le(null);s(()=>{if(Ve.current?.abort(),!B||!z||H||K||q||!V||p.name!==`form`||E===void 0)return;let e=new AbortController;Ve.current=e;let t={recipient:v,amount:R,receiveChainId:j.eip155Id,receiveSymbol:N.symbol},n=setTimeout(()=>{let n={sourceAssetSymbol:D,sourceChainId:E,amount:R,receiveTokenSymbol:N.symbol,receiveChainId:j.eip155Id,recipientAddress:v};g({type:`withdraw.quote.requested`,flow:`withdraw`,tier:`flow`,payload:{input:n}}),f.requestQuote(n,e.signal).then(()=>{e.signal.aborted||Oe(t)}).catch(()=>{})},400);return()=>{clearTimeout(n),e.abort()}},[g,f,v,R,B,z,H,K,q,V,E,D,j?.eip155Id,N?.symbol,p.name]);let He=o(()=>{w&&(L(w.amount),g({type:`withdraw.max.clicked`,flow:`withdraw`,tier:`ui`,payload:{}}))},[w,g,L]),Ue=o(()=>{g({type:`withdraw.submit.clicked`,flow:`withdraw`,tier:`ui`,payload:{}}),!(ge||$)&&(E===void 0||!j||!N||m.submit({sourceAssetSymbol:D,sourceChainId:E,amount:R??0,recipientAddress:v,receiveTokenSymbol:N.symbol,receiveChainId:j.eip155Id,...X?{amountUsd:X}:{}}))},[m,R,X,g,E,D,j,N,v,$,ge]),We=o(e=>{let t=T.find(t=>String(t.eip155Id)===String(e.chainId));t&&Ce(t)},[Ce,T]),Ge=o(e=>{let t=e.symbol.toUpperCase(),n=O.get(t);!n||n.length===0||Se((n.find(e=>e.chain.eip155Id===j?.eip155Id)??n[0]).token)},[Se,O,j?.eip155Id]);return p.name!==`form`&&p.name!==`submitting`?null:ue(a,{recipientAddress:v,onRecipientChange:xe,recipientChainType:Ee,...fe?{suggestedRecipient:fe}:{},amount:me,onAmountChange:L,onAmountMax:He,sourceAsset:x,sourceChain:ve,receiveAsset:je,receiveChain:Me,receiveAssetOptions:ke,onReceiveAssetChange:Ge,receiveChainOptions:Ae,onReceiveChainChange:We,balance:w,amountUsd:X,receiveAmount:Pe,receiveAmountUsd:Fe,breakdown:Ne,quoteEstimating:Ie,quoteRegenerating:Q,...Le===void 0?{}:{quoteSeconds:Le},...Re===void 0?{}:{quoteTotalSeconds:Re},submitting:ge,submitDisabled:$,submitLabel:Be,...y?{notice:y}:{},onSubmit:Ue,onBreakdownOpenChange:e=>g({type:`withdraw.breakdown.clicked`,flow:`withdraw`,tier:`ui`,payload:{open:e}}),children:[u(a.Header,{}),ue(a.Body,{children:[u(a.RecipientField,{}),u(a.AmountField,{}),u(a.ReceiveSelectors,{}),u(a.BreakdownCard,{})]}),u(a.Footer,{})]})}export{d as WithdrawForm};
@@ -1 +1 @@
1
- "use client";import{DialogShell as e}from"../../../../../shared/dialog/DialogShell.js";import{Tooltip as t}from"../../../../../shared/ui/Tooltip/Tooltip.js";import"../../../../../shared/ui/Tooltip/index.js";import{Frame as n}from"../../../../../shared/dialog/Frame.js";import{WithdrawFormContext as r}from"./context.js";import{WITHDRAW_FORM_SLOTS as i}from"./WithdrawForm.slots.js";import{styles as a}from"./WithdrawForm.styles.js";import{WithdrawFormAmountField as o}from"./components/AmountField.js";import{WithdrawFormBody as s}from"./components/Body.js";import{WithdrawFormBreakdownCard as c}from"./components/BreakdownCard.js";import{WithdrawFormFooter as l}from"./components/Footer.js";import{WithdrawFormHeader as u}from"./components/Header.js";import{WithdrawFormReceiveSelectors as d}from"./components/ReceiveSelectors.js";import{WithdrawFormRecipientField as f}from"./components/RecipientField.js";import{useCallback as p,useMemo as m,useState as h}from"react";import{jsx as g}from"react/jsx-runtime";import*as _ from"@stylexjs/stylex";const v=()=>void 0;function y(e){let{recipientAddress:o=``,onRecipientChange:s,connectedAddress:c,amount:l=``,onAmountChange:u,onAmountMax:d,sourceAsset:f,sourceChain:y,receiveAsset:b,receiveChain:x,receiveAssetOptions:S,onReceiveAssetChange:C,receiveChainOptions:w,onReceiveChainChange:T,balance:E,amountUsd:D,receiveAmount:O,receiveAmountUsd:k,breakdown:A,quoteEstimating:j=!1,quoteRegenerating:M=!1,quoteSeconds:N,quoteTotalSeconds:P,submitting:F=!1,submitDisabled:I=!1,submitLabel:L,notice:R,onSubmit:z,defaultBreakdownOpen:B=!1,breakdownOpen:V,onBreakdownOpenChange:H,children:U}=e,[W,G]=h(B),K=V!==void 0,q=K?V:W,J=p(e=>{K||G(e),H?.(e)},[K,H]),Y=b??f,X=x??y;return g(r,{value:m(()=>({recipientAddress:o,onRecipientChange:s??v,connectedAddress:c,amount:l,onAmountChange:u??v,onAmountMax:d,sourceAsset:f,sourceChain:y,receiveAsset:Y,receiveChain:X,receiveAssetOptions:S,onReceiveAssetChange:C,receiveChainOptions:w,onReceiveChainChange:T,balance:E,amountUsd:D,receiveAmount:O,receiveAmountUsd:k,breakdown:A,quoteEstimating:j,quoteRegenerating:M,quoteSeconds:N,quoteTotalSeconds:P,submitting:F,submitDisabled:I,submitLabel:L,notice:R,onSubmit:z,breakdownOpen:q,onBreakdownOpenChange:J}),[o,s,c,l,u,d,f,y,Y,X,S,C,w,T,E,D,O,k,A,j,M,N,P,F,I,L,R,z,q,J]),children:g(t.Provider,{children:g(n,{"data-stridge-slot":i.root,..._.props(a.root),children:U})})})}function b({open:t,defaultOpen:n,onOpenChange:r,trigger:i,children:a,...o}){return g(e,{open:t,defaultOpen:n,onOpenChange:r,trigger:i,children:g(y,{...o,children:a})})}(function(e){e.Header=u,e.Body=s,e.RecipientField=f,e.AmountField=o,e.ReceiveSelectors=d,e.BreakdownCard=c,e.Footer=l,e.Dialog=b})(y||={});export{y as WithdrawForm};
1
+ "use client";import{DialogShell as e}from"../../../../../shared/dialog/DialogShell.js";import{Tooltip as t}from"../../../../../shared/ui/Tooltip/Tooltip.js";import"../../../../../shared/ui/Tooltip/index.js";import{Frame as n}from"../../../../../shared/dialog/Frame.js";import{WithdrawFormContext as r}from"./context.js";import{WITHDRAW_FORM_SLOTS as i}from"./WithdrawForm.slots.js";import{styles as a}from"./WithdrawForm.styles.js";import{WithdrawFormAmountField as o}from"./components/AmountField.js";import{WithdrawFormBody as s}from"./components/Body.js";import{WithdrawFormBreakdownCard as c}from"./components/BreakdownCard.js";import{WithdrawFormFooter as l}from"./components/Footer.js";import{WithdrawFormHeader as u}from"./components/Header.js";import{WithdrawFormReceiveSelectors as d}from"./components/ReceiveSelectors.js";import{WithdrawFormRecipientField as f}from"./components/RecipientField.js";import{useCallback as p,useMemo as m,useState as h}from"react";import{jsx as g}from"react/jsx-runtime";import*as _ from"@stylexjs/stylex";const v=()=>void 0;function y(e){let{recipientAddress:o=``,onRecipientChange:s,recipientChainType:c=`evm`,suggestedRecipient:l,amount:u=``,onAmountChange:d,onAmountMax:f,sourceAsset:y,sourceChain:b,receiveAsset:x,receiveChain:S,receiveAssetOptions:C,onReceiveAssetChange:w,receiveChainOptions:T,onReceiveChainChange:E,balance:D,amountUsd:O,receiveAmount:k,receiveAmountUsd:A,breakdown:j,quoteEstimating:M=!1,quoteRegenerating:N=!1,quoteSeconds:P,quoteTotalSeconds:F,submitting:I=!1,submitDisabled:L=!1,submitLabel:R,notice:z,onSubmit:B,defaultBreakdownOpen:V=!1,breakdownOpen:H,onBreakdownOpenChange:U,children:W}=e,[G,K]=h(V),q=H!==void 0,J=q?H:G,Y=p(e=>{q||K(e),U?.(e)},[q,U]),X=x??y,Z=S??b;return g(r,{value:m(()=>({recipientAddress:o,onRecipientChange:s??v,recipientChainType:c,suggestedRecipient:l,amount:u,onAmountChange:d??v,onAmountMax:f,sourceAsset:y,sourceChain:b,receiveAsset:X,receiveChain:Z,receiveAssetOptions:C,onReceiveAssetChange:w,receiveChainOptions:T,onReceiveChainChange:E,balance:D,amountUsd:O,receiveAmount:k,receiveAmountUsd:A,breakdown:j,quoteEstimating:M,quoteRegenerating:N,quoteSeconds:P,quoteTotalSeconds:F,submitting:I,submitDisabled:L,submitLabel:R,notice:z,onSubmit:B,breakdownOpen:J,onBreakdownOpenChange:Y}),[o,s,c,l,u,d,f,y,b,X,Z,C,w,T,E,D,O,k,A,j,M,N,P,F,I,L,R,z,B,J,Y]),children:g(t.Provider,{children:g(n,{"data-stridge-slot":i.root,..._.props(a.root),children:W})})})}function b({open:t,defaultOpen:n,onOpenChange:r,trigger:i,children:a,...o}){return g(e,{open:t,defaultOpen:n,onOpenChange:r,trigger:i,children:g(y,{...o,children:a})})}(function(e){e.Header=u,e.Body=s,e.RecipientField=f,e.AmountField=o,e.ReceiveSelectors=d,e.BreakdownCard=c,e.Footer=l,e.Dialog=b})(y||={});export{y as WithdrawForm};
@@ -2,17 +2,19 @@ import * as _$react_jsx_runtime0 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/flows/withdraw/widgets/withdraw-form/compound/components/RecipientField.d.ts
4
4
  /**
5
- * Recipient address field — label + auto-growing textarea + trailing wallet pill.
5
+ * Recipient address field — label + auto-growing textarea + trailing prefill chip.
6
6
  *
7
7
  * The textarea wraps long hex addresses up to `maxBlockSize`, then scrolls. Single-line semantics
8
8
  * are kept by stripping any `\r\n` in `onChange` — no `onKeyDown` Enter-blocker, since that would
9
9
  * also swallow IME composition keys for CJK input. The stripping handler lives here (not in
10
10
  * `InputGroup.Textarea`) so the kit primitive stays neutral on the single-vs-multi-line decision.
11
11
  *
12
- * The pill becomes an interactive button when `connectedAddress` is set; clicking it fills the
13
- * input. Omitted entirely when `connectedAddress` is absent. The pill renders the truncated
14
- * address (`0x70…79C8`) the user recognizes their own address, making the action self-evident
15
- * while keeping pill width deterministic across locales.
12
+ * The chip is host-controlled via `suggestedRecipient` on `<WithdrawDialog>` (or the compound
13
+ * root prop). Clicking it fills the input. Hidden entirely when no suggestion is supplied. The
14
+ * chip's `aria-label` reads off the host-supplied `label` so screen readers describe which
15
+ * address is being prefilled; the visible text shows the truncated address so sighted users
16
+ * see "this is mine" recognition. The kit no longer auto-derives this from `wagmi.address` —
17
+ * that misled users on embedded-wallet integrations.
16
18
  */
17
19
  declare function WithdrawFormRecipientField(): _$react_jsx_runtime0.JSX.Element;
18
20
  //#endregion