@openfort/react 1.1.4 → 1.3.0

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 (182) hide show
  1. package/build/assets/icons.js +1 -1
  2. package/build/assets/logos.d.ts +15 -0
  3. package/build/assets/logos.js +9 -0
  4. package/build/assets/logos.js.map +1 -1
  5. package/build/components/Common/CopyToClipboard/CopyIconButton.d.ts +3 -1
  6. package/build/components/Common/CopyToClipboard/CopyIconButton.js +4 -4
  7. package/build/components/Common/CustomQRCode/index.d.ts +1 -1
  8. package/build/components/Common/CustomQRCode/index.js +3 -3
  9. package/build/components/Common/CustomQRCode/styles.d.ts +1 -0
  10. package/build/components/Common/CustomQRCode/styles.js +4 -4
  11. package/build/components/Common/CustomQRCode/types.d.ts +2 -0
  12. package/build/components/Common/Modal/styles.js +4 -1
  13. package/build/components/Common/Modal/styles.js.map +1 -1
  14. package/build/components/Common/SolanaChain/index.d.ts +8 -0
  15. package/build/components/Common/SolanaChain/index.js +40 -0
  16. package/build/components/Common/SolanaChain/index.js.map +1 -0
  17. package/build/components/ConnectModal/index.js +16 -2
  18. package/build/components/ConnectModal/index.js.map +1 -1
  19. package/build/components/Openfort/OpenfortProvider.js +4 -1
  20. package/build/components/Openfort/OpenfortProvider.js.map +1 -1
  21. package/build/components/Openfort/types.d.ts +92 -0
  22. package/build/components/Openfort/types.js +23 -1
  23. package/build/components/Openfort/types.js.map +1 -1
  24. package/build/components/Pages/AssetInventory/SolanaAssetInventory.d.ts +6 -0
  25. package/build/components/Pages/AssetInventory/SolanaAssetInventory.js +42 -0
  26. package/build/components/Pages/AssetInventory/SolanaAssetInventory.js.map +1 -0
  27. package/build/components/Pages/Buy/coinbaseApi.d.ts +1 -1
  28. package/build/components/Pages/Buy/coinbaseApi.js +2 -13
  29. package/build/components/Pages/Buy/coinbaseApi.js.map +1 -1
  30. package/build/components/Pages/Buy/evmCurrencies.d.ts +11 -0
  31. package/build/components/Pages/Buy/evmCurrencies.js +27 -0
  32. package/build/components/Pages/Buy/evmCurrencies.js.map +1 -0
  33. package/build/components/Pages/Buy/index.js +11 -3
  34. package/build/components/Pages/Buy/index.js.map +1 -1
  35. package/build/components/Pages/Buy/onrampApi.d.ts +8 -1
  36. package/build/components/Pages/Buy/onrampApi.js +24 -14
  37. package/build/components/Pages/Buy/onrampApi.js.map +1 -1
  38. package/build/components/Pages/Buy/solanaCurrencies.d.ts +9 -0
  39. package/build/components/Pages/Buy/solanaCurrencies.js +25 -0
  40. package/build/components/Pages/Buy/solanaCurrencies.js.map +1 -0
  41. package/build/components/Pages/Buy/stripeApi.d.ts +1 -1
  42. package/build/components/Pages/Buy/stripeApi.js +2 -13
  43. package/build/components/Pages/Buy/stripeApi.js.map +1 -1
  44. package/build/components/Pages/BuyComplete/index.js +7 -1
  45. package/build/components/Pages/BuyComplete/index.js.map +1 -1
  46. package/build/components/Pages/BuyProcessing/index.js +9 -5
  47. package/build/components/Pages/BuyProcessing/index.js.map +1 -1
  48. package/build/components/Pages/BuySelectProvider/index.js +11 -6
  49. package/build/components/Pages/BuySelectProvider/index.js.map +1 -1
  50. package/build/components/Pages/Connected/EthereumConnected.js +8 -32
  51. package/build/components/Pages/Connected/EthereumConnected.js.map +1 -1
  52. package/build/components/Pages/Connected/SolanaConnected.js +11 -5
  53. package/build/components/Pages/Connected/SolanaConnected.js.map +1 -1
  54. package/build/components/Pages/Deposit/AddressPageLink.d.ts +7 -0
  55. package/build/components/Pages/Deposit/AddressPageLink.js +17 -0
  56. package/build/components/Pages/Deposit/AddressPageLink.js.map +1 -0
  57. package/build/components/Pages/Deposit/AssetChainLogo.d.ts +9 -0
  58. package/build/components/Pages/Deposit/AssetChainLogo.js +24 -0
  59. package/build/components/Pages/Deposit/AssetChainLogo.js.map +1 -0
  60. package/build/components/Pages/Deposit/DepositAddressBlock.d.ts +21 -0
  61. package/build/components/Pages/Deposit/DepositAddressBlock.js +28 -0
  62. package/build/components/Pages/Deposit/DepositAddressBlock.js.map +1 -0
  63. package/build/components/Pages/Deposit/DepositProgress.d.ts +15 -0
  64. package/build/components/Pages/Deposit/DepositProgress.js +111 -0
  65. package/build/components/Pages/Deposit/DepositProgress.js.map +1 -0
  66. package/build/components/Pages/Deposit/DepositStatus.d.ts +9 -0
  67. package/build/components/Pages/Deposit/DepositStatus.js +43 -0
  68. package/build/components/Pages/Deposit/DepositStatus.js.map +1 -0
  69. package/build/components/Pages/Deposit/DepositSuccess.d.ts +6 -0
  70. package/build/components/Pages/Deposit/DepositSuccess.js +25 -0
  71. package/build/components/Pages/Deposit/DepositSuccess.js.map +1 -0
  72. package/build/components/Pages/Deposit/Details.d.ts +12 -0
  73. package/build/components/Pages/Deposit/Details.js +40 -0
  74. package/build/components/Pages/Deposit/Details.js.map +1 -0
  75. package/build/components/Pages/Deposit/LogoSelect.d.ts +12 -0
  76. package/build/components/Pages/Deposit/LogoSelect.js +95 -0
  77. package/build/components/Pages/Deposit/LogoSelect.js.map +1 -0
  78. package/build/components/Pages/Deposit/OrDivider.d.ts +2 -0
  79. package/build/components/Pages/Deposit/OrDivider.js +10 -0
  80. package/build/components/Pages/Deposit/OrDivider.js.map +1 -0
  81. package/build/components/Pages/Deposit/RouteSelectors.d.ts +13 -0
  82. package/build/components/Pages/Deposit/RouteSelectors.js +19 -0
  83. package/build/components/Pages/Deposit/RouteSelectors.js.map +1 -0
  84. package/build/components/Pages/Deposit/cexChains.d.ts +9 -0
  85. package/build/components/Pages/Deposit/cexChains.js +23 -0
  86. package/build/components/Pages/Deposit/cexChains.js.map +1 -0
  87. package/build/components/Pages/Deposit/formStyles.d.ts +24 -0
  88. package/build/components/Pages/Deposit/formStyles.js +83 -0
  89. package/build/components/Pages/Deposit/formStyles.js.map +1 -0
  90. package/build/components/Pages/Deposit/index.d.ts +7 -0
  91. package/build/components/Pages/Deposit/index.js +114 -0
  92. package/build/components/Pages/Deposit/index.js.map +1 -0
  93. package/build/components/Pages/Deposit/paymentOptions.d.ts +49 -0
  94. package/build/components/Pages/Deposit/paymentOptions.js +63 -0
  95. package/build/components/Pages/Deposit/paymentOptions.js.map +1 -0
  96. package/build/components/Pages/Deposit/sources.d.ts +17 -0
  97. package/build/components/Pages/Deposit/sources.js +22 -0
  98. package/build/components/Pages/Deposit/sources.js.map +1 -0
  99. package/build/components/Pages/Deposit/styles.d.ts +25 -0
  100. package/build/components/Pages/Deposit/styles.js +167 -0
  101. package/build/components/Pages/Deposit/styles.js.map +1 -0
  102. package/build/components/Pages/Deposit/useDepositRoute.d.ts +34 -0
  103. package/build/components/Pages/Deposit/useDepositRoute.js +106 -0
  104. package/build/components/Pages/Deposit/useDepositRoute.js.map +1 -0
  105. package/build/components/Pages/Deposit/useFundingTarget.d.ts +11 -0
  106. package/build/components/Pages/Deposit/useFundingTarget.js +25 -0
  107. package/build/components/Pages/Deposit/useFundingTarget.js.map +1 -0
  108. package/build/components/Pages/DepositCex/index.d.ts +11 -0
  109. package/build/components/Pages/DepositCex/index.js +229 -0
  110. package/build/components/Pages/DepositCex/index.js.map +1 -0
  111. package/build/components/Pages/DepositCrypto/index.d.ts +8 -0
  112. package/build/components/Pages/DepositCrypto/index.js +31 -0
  113. package/build/components/Pages/DepositCrypto/index.js.map +1 -0
  114. package/build/components/Pages/DepositWallet/DepositWalletDesktop.d.ts +20 -0
  115. package/build/components/Pages/DepositWallet/DepositWalletDesktop.js +139 -0
  116. package/build/components/Pages/DepositWallet/DepositWalletDesktop.js.map +1 -0
  117. package/build/components/Pages/DepositWallet/index.d.ts +9 -0
  118. package/build/components/Pages/DepositWallet/index.js +107 -0
  119. package/build/components/Pages/DepositWallet/index.js.map +1 -0
  120. package/build/components/Pages/DepositWallet/walletDeeplinks.d.ts +50 -0
  121. package/build/components/Pages/DepositWallet/walletDeeplinks.js +109 -0
  122. package/build/components/Pages/DepositWallet/walletDeeplinks.js.map +1 -0
  123. package/build/components/Pages/ExportKey/index.js +10 -2
  124. package/build/components/Pages/ExportKey/index.js.map +1 -1
  125. package/build/components/Pages/NoAssetsAvailable/index.js +5 -21
  126. package/build/components/Pages/NoAssetsAvailable/index.js.map +1 -1
  127. package/build/components/Pages/SelectToken/SolanaSelectToken.d.ts +1 -0
  128. package/build/components/Pages/SelectToken/SolanaSelectToken.js +50 -0
  129. package/build/components/Pages/SelectToken/SolanaSelectToken.js.map +1 -0
  130. package/build/components/Pages/SelectToken/index.js +13 -2
  131. package/build/components/Pages/SelectToken/index.js.map +1 -1
  132. package/build/components/Pages/SelectToken/styles.js +1 -1
  133. package/build/components/Pages/Send/SolanaSend.d.ts +1 -0
  134. package/build/components/Pages/Send/SolanaSend.js +89 -0
  135. package/build/components/Pages/Send/SolanaSend.js.map +1 -0
  136. package/build/components/Pages/Send/index.d.ts +2 -1
  137. package/build/components/Pages/Send/index.js +0 -1
  138. package/build/components/Pages/Send/index.js.map +1 -1
  139. package/build/components/Pages/Send/utils.js +4 -1
  140. package/build/components/Pages/Send/utils.js.map +1 -1
  141. package/build/components/Pages/SendConfirmation/EstimatedFees.js +5 -3
  142. package/build/components/Pages/SendConfirmation/EstimatedFees.js.map +1 -1
  143. package/build/components/Pages/SendConfirmation/SolanaSendConfirmation.d.ts +1 -0
  144. package/build/components/Pages/SendConfirmation/SolanaSendConfirmation.js +121 -0
  145. package/build/components/Pages/SendConfirmation/SolanaSendConfirmation.js.map +1 -0
  146. package/build/components/Pages/SendConfirmation/index.js +4 -3
  147. package/build/components/Pages/SendConfirmation/index.js.map +1 -1
  148. package/build/constants/logos.js +1 -0
  149. package/build/constants/logos.js.map +1 -1
  150. package/build/ethereum/hooks/useEthereumWalletAssets.js +212 -95
  151. package/build/ethereum/hooks/useEthereumWalletAssets.js.map +1 -1
  152. package/build/hooks/openfort/fundingClient.d.ts +34 -0
  153. package/build/hooks/openfort/fundingClient.js +60 -0
  154. package/build/hooks/openfort/fundingClient.js.map +1 -0
  155. package/build/hooks/openfort/useFunding.d.ts +159 -0
  156. package/build/hooks/openfort/useFunding.js +204 -0
  157. package/build/hooks/openfort/useFunding.js.map +1 -0
  158. package/build/hooks/openfort/useFundingChains.d.ts +49 -0
  159. package/build/hooks/openfort/useFundingChains.js +100 -0
  160. package/build/hooks/openfort/useFundingChains.js.map +1 -0
  161. package/build/hooks/useBalance.js +6 -1
  162. package/build/hooks/useBalance.js.map +1 -1
  163. package/build/index.d.ts +4 -1
  164. package/build/index.js +2 -1
  165. package/build/index.js.map +1 -1
  166. package/build/shared/hooks/useAsyncData.d.ts +11 -0
  167. package/build/shared/hooks/useAsyncData.js +73 -13
  168. package/build/shared/hooks/useAsyncData.js.map +1 -1
  169. package/build/solana/hooks/useSolanaWalletAssets.d.ts +24 -0
  170. package/build/solana/hooks/useSolanaWalletAssets.js +86 -0
  171. package/build/solana/hooks/useSolanaWalletAssets.js.map +1 -0
  172. package/build/solana/transfer.d.ts +61 -0
  173. package/build/solana/transfer.js +219 -0
  174. package/build/solana/transfer.js.map +1 -0
  175. package/build/solana/types.d.ts +8 -0
  176. package/build/utils/index.d.ts +2 -1
  177. package/build/utils/index.js +1 -1
  178. package/build/version.d.ts +1 -1
  179. package/build/version.js +1 -1
  180. package/build/wagmi/defaultConnectors.js +5 -1
  181. package/build/wagmi/defaultConnectors.js.map +1 -1
  182. package/package.json +13 -1
@@ -0,0 +1,34 @@
1
+ import { type FundingChain, type FundingCurrency } from '../../../hooks/openfort/useFundingChains';
2
+ /** Which rail the route feeds: self-custody wallet send vs exchange withdrawal. */
3
+ type DepositRouteKind = 'crypto' | 'cex';
4
+ /**
5
+ * Shared state for a deposit route: the source chain/currency selection (sourced
6
+ * live from Relay via {@link useFundingChains}) plus the resolved deposit
7
+ * address. Both the "from wallet"/"from exchange" tabs and the standalone "from
8
+ * address" page build on this — they differ only in the lead buttons.
9
+ */
10
+ export declare function useDepositRoute(kind: DepositRouteKind): {
11
+ chains: FundingChain[];
12
+ chainsLoading: boolean;
13
+ chain: string;
14
+ setChain: import("react").Dispatch<import("react").SetStateAction<string>>;
15
+ currency: string;
16
+ setCurrency: import("react").Dispatch<import("react").SetStateAction<string>>;
17
+ currencies: FundingCurrency[];
18
+ activeChain: FundingChain;
19
+ activeCurrency: FundingCurrency;
20
+ address: string | undefined;
21
+ target: {
22
+ chain: string;
23
+ currency: string;
24
+ };
25
+ pm: import("../../../hooks/openfort/useFunding").PaymentMethod | null;
26
+ receiverAddress: string | null;
27
+ sameChain: boolean;
28
+ status: import("../../../hooks/openfort/useFunding").SessionStatus | "idle";
29
+ loading: boolean;
30
+ error: Error | null;
31
+ isAvailable: boolean;
32
+ payLink: (params: import("../../../hooks/openfort/useFunding").PayLinkParams) => Promise<string>;
33
+ };
34
+ export {};
@@ -0,0 +1,106 @@
1
+ import { useState, useRef, useEffect } from 'react';
2
+ import { useEthereumEmbeddedWallet } from '../../../ethereum/hooks/useEthereumEmbeddedWallet.js';
3
+ import { useFunding } from '../../../hooks/openfort/useFunding.js';
4
+ import { useFundingChains, nominalUnits } from '../../../hooks/openfort/useFundingChains.js';
5
+ import { useSolanaEmbeddedWallet } from '../../../solana/hooks/useSolanaEmbeddedWallet.js';
6
+ import { logger } from '../../../utils/logger.js';
7
+ import { isCexDeliverable } from './cexChains.js';
8
+ import { isSolana } from './sources.js';
9
+ import { useFundingTarget } from './useFundingTarget.js';
10
+
11
+ function paymentMethodFor(chain, currency) {
12
+ const source = { chain, currency: currency.address, amount: nominalUnits(currency.decimals, currency.native) };
13
+ // A CEX withdrawal is just an on-chain send to the Relay deposit address — the
14
+ // funding API has no separate 'cex' type, so every source resolves to evm/solana.
15
+ return { type: isSolana(chain) ? 'solana' : 'evm', source };
16
+ }
17
+ /**
18
+ * Shared state for a deposit route: the source chain/currency selection (sourced
19
+ * live from Relay via {@link useFundingChains}) plus the resolved deposit
20
+ * address. Both the "from wallet"/"from exchange" tabs and the standalone "from
21
+ * address" page build on this — they differ only in the lead buttons.
22
+ */
23
+ function useDepositRoute(kind) {
24
+ var _a, _b, _c, _d, _e, _f, _g, _h;
25
+ const ethWallet = useEthereumEmbeddedWallet();
26
+ const solWallet = useSolanaEmbeddedWallet();
27
+ const { session, status, error, loading, isAvailable, fund, payLink, reset } = useFunding();
28
+ const { chains: allChains, loading: chainsLoading } = useFundingChains();
29
+ const target = useFundingTarget();
30
+ // The deposit recipient must live on the TARGET chain, so resolve the wallet by
31
+ // the target's family — not the active chainType, which can disagree with the
32
+ // target (e.g. an EVM session whose funding target is still Solana) and would
33
+ // send an EVM address as the recipient for a Solana destination.
34
+ const wallet = isSolana(target.chain) ? solWallet : ethWallet;
35
+ // Sources are the full Relay list, including the destination chain itself so
36
+ // same-chain deposits (e.g. Solana → Solana) are offered as a plain transfer to
37
+ // the wallet address, alongside the cross-chain bridge routes. The CEX rail rides
38
+ // Coinbase Onramp, which only delivers to a fixed set of EVM chains.
39
+ const chains = kind === 'cex' ? allChains.filter((c) => isCexDeliverable(c.id)) : allChains;
40
+ // Where funds land: the active embedded wallet (the Relay deposit recipient).
41
+ const address = wallet.status === 'connected' ? wallet.address : undefined;
42
+ const [chainId, setChainId] = useState('');
43
+ const [currencySymbol, setCurrencySymbol] = useState('');
44
+ const lastKey = useRef('');
45
+ // Derive the active selection, falling back to the first available chain/currency
46
+ // so the picker is valid before the user touches it and as chains load in.
47
+ const activeChain = (_a = chains.find((c) => c.id === chainId)) !== null && _a !== void 0 ? _a : chains[0];
48
+ const currencies = (_b = activeChain === null || activeChain === void 0 ? void 0 : activeChain.currencies) !== null && _b !== void 0 ? _b : [];
49
+ const activeCurrency = (_c = currencies.find((c) => c.symbol === currencySymbol)) !== null && _c !== void 0 ? _c : currencies[0];
50
+ const chain = (_d = activeChain === null || activeChain === void 0 ? void 0 : activeChain.id) !== null && _d !== void 0 ? _d : target.chain;
51
+ const sameChain = chain === target.chain;
52
+ const receiverAddress = sameChain
53
+ ? (address !== null && address !== void 0 ? address : null)
54
+ : ((_f = (_e = session === null || session === void 0 ? void 0 : session.paymentMethod) === null || _e === void 0 ? void 0 : _e.receiverAddress) !== null && _f !== void 0 ? _f : null);
55
+ const pm = (_g = session === null || session === void 0 ? void 0 : session.paymentMethod) !== null && _g !== void 0 ? _g : null;
56
+ useEffect(() => {
57
+ if (!address || !isAvailable || !activeChain || !activeCurrency)
58
+ return;
59
+ if (sameChain) {
60
+ lastKey.current = '';
61
+ reset();
62
+ return;
63
+ }
64
+ const key = `${kind}:${activeChain.id}:${activeCurrency.symbol}`;
65
+ if (lastKey.current === key)
66
+ return;
67
+ lastKey.current = key;
68
+ logger.log('[funding:route] resolved', {
69
+ kind,
70
+ sourceChain: activeChain.id,
71
+ currency: activeCurrency.symbol,
72
+ destChain: target.chain,
73
+ });
74
+ fund({ chain: target.chain, currency: target.currency, address }, paymentMethodFor(activeChain.id, activeCurrency)).catch(() => { });
75
+ }, [address, activeChain, activeCurrency, isAvailable, sameChain, fund, reset, target.chain, target.currency, kind]);
76
+ // Surface an empty source list (e.g. no Coinbase-deliverable chains) for diagnosis.
77
+ useEffect(() => {
78
+ if (!isAvailable || chainsLoading || chains.length > 0)
79
+ return;
80
+ logger.warn('[funding:route] no source chains available', { kind, destChain: target.chain });
81
+ }, [isAvailable, chainsLoading, chains.length, kind, target.chain]);
82
+ return {
83
+ chains,
84
+ chainsLoading,
85
+ chain,
86
+ setChain: setChainId,
87
+ currency: (_h = activeCurrency === null || activeCurrency === void 0 ? void 0 : activeCurrency.symbol) !== null && _h !== void 0 ? _h : '',
88
+ setCurrency: setCurrencySymbol,
89
+ currencies,
90
+ activeChain,
91
+ activeCurrency,
92
+ address,
93
+ target,
94
+ pm,
95
+ receiverAddress,
96
+ sameChain,
97
+ status,
98
+ loading,
99
+ error,
100
+ isAvailable,
101
+ payLink,
102
+ };
103
+ }
104
+
105
+ export { useDepositRoute };
106
+ //# sourceMappingURL=useDepositRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDepositRoute.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The destination route Deposit-hub funding settles into. Integrators override the
3
+ * chain and currency via `uiConfig.funding.{targetChain,targetCurrency}`; both
4
+ * default to USDC on the active chain type (Base for EVM, Solana mainnet for SVM)
5
+ * so the flow works with zero configuration. The deposit recipient is always the
6
+ * active embedded wallet for the destination chain family — callers resolve it.
7
+ */
8
+ export declare function useFundingTarget(): {
9
+ chain: string;
10
+ currency: string;
11
+ };
@@ -0,0 +1,25 @@
1
+ import { ChainTypeEnum } from '@openfort/openfort-js';
2
+ import { useOpenfortCore } from '../../../openfort/useOpenfort.js';
3
+ import { useOpenfort } from '../../Openfort/useOpenfort.js';
4
+ import { DEST_CHAIN_SOL, DEST_CHAIN, DEST_USDC_SOL, DEST_USDC } from './sources.js';
5
+
6
+ /**
7
+ * The destination route Deposit-hub funding settles into. Integrators override the
8
+ * chain and currency via `uiConfig.funding.{targetChain,targetCurrency}`; both
9
+ * default to USDC on the active chain type (Base for EVM, Solana mainnet for SVM)
10
+ * so the flow works with zero configuration. The deposit recipient is always the
11
+ * active embedded wallet for the destination chain family — callers resolve it.
12
+ */
13
+ function useFundingTarget() {
14
+ var _a, _b, _c, _d;
15
+ const { uiConfig } = useOpenfort();
16
+ const { chainType } = useOpenfortCore();
17
+ const isSolana = chainType === ChainTypeEnum.SVM;
18
+ return {
19
+ chain: (_b = (_a = uiConfig.funding) === null || _a === void 0 ? void 0 : _a.targetChain) !== null && _b !== void 0 ? _b : (isSolana ? DEST_CHAIN_SOL : DEST_CHAIN),
20
+ currency: (_d = (_c = uiConfig.funding) === null || _c === void 0 ? void 0 : _c.targetCurrency) !== null && _d !== void 0 ? _d : (isSolana ? DEST_USDC_SOL : DEST_USDC),
21
+ };
22
+ }
23
+
24
+ export { useFundingTarget };
25
+ //# sourceMappingURL=useFundingTarget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFundingTarget.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Transfer from Exchange — the user enters an amount; "Open Coinbase" hands off to
3
+ * a hosted Coinbase pay-link that delivers to the embedded wallet on the
4
+ * destination chain. The destination (chain + currency + address) is bound to a
5
+ * funding session created up-front, so the client can't redirect the funds — only
6
+ * the amount is chosen here. After hand-off the bound session is polled until it
7
+ * settles (advanced by the Coinbase webhook on the backend), driving the
8
+ * success / failed screen. No Relay routing; Binance is gated until its rail lands.
9
+ */
10
+ declare const DepositCex: () => import("react/jsx-runtime").JSX.Element;
11
+ export default DepositCex;
@@ -0,0 +1,229 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { ChainTypeEnum } from '@openfort/openfort-js';
3
+ import { useState, useRef, useEffect, useMemo } from 'react';
4
+ import Logos from '../../../assets/logos.js';
5
+ import { useEthereumEmbeddedWallet } from '../../../ethereum/hooks/useEthereumEmbeddedWallet.js';
6
+ import { useFunding } from '../../../hooks/openfort/useFunding.js';
7
+ import { useFundingChains } from '../../../hooks/openfort/useFundingChains.js';
8
+ import { invalidateBalance } from '../../../hooks/useBalance.js';
9
+ import { useOpenfortCore } from '../../../openfort/useOpenfort.js';
10
+ import { logger } from '../../../utils/logger.js';
11
+ import { ModalHeading, ModalBody } from '../../Common/Modal/styles.js';
12
+ import { routes } from '../../Openfort/types.js';
13
+ import { useOpenfort } from '../../Openfort/useOpenfort.js';
14
+ import { PageContent } from '../../PageContent/index.js';
15
+ import { Section, SectionLabel, AmountCard, CurrencySymbol, AmountInput, PresetList, PresetButton } from '../Buy/styles.js';
16
+ import { isCexDeliverable, CEX_CHAIN_NAMES } from '../Deposit/cexChains.js';
17
+ import { isDepositFlowActive, DepositProgress } from '../Deposit/DepositProgress.js';
18
+ import { DepositStatus } from '../Deposit/DepositStatus.js';
19
+ import { walletListBtn } from '../Deposit/formStyles.js';
20
+ import { isSolana, DEST_USDC } from '../Deposit/sources.js';
21
+ import { StepDivider, ButtonLogo } from '../Deposit/styles.js';
22
+ import { useFundingTarget } from '../Deposit/useFundingTarget.js';
23
+ import { sanitizeForParsing, sanitizeAmountInput } from '../Send/utils.js';
24
+
25
+ /** Exchange rails. Binance is gated until its rail lands. */
26
+ const EXCHANGES = [
27
+ { id: 'coinbase', comingSoon: false },
28
+ { id: 'binance', comingSoon: true },
29
+ ];
30
+ /** Exchange brand logos keyed by exchange id. */
31
+ const EXCHANGE_LOGO = {
32
+ coinbase: jsx(Logos.Coinbase, { background: true }),
33
+ binance: jsx(Logos.Binance, {}),
34
+ };
35
+ /** Coinbase Onramp minimum (USD, ≈ USDC units); enforced client-side for UX. */
36
+ const MIN_AMOUNT = 5;
37
+ const PRESETS = [10, 25, 50];
38
+ function titleCase(s) {
39
+ return s.charAt(0).toUpperCase() + s.slice(1);
40
+ }
41
+ const helperText = { fontSize: 12, color: 'var(--ck-body-color-muted, #6b7280)' };
42
+ const errorHelper = { fontSize: 12, color: '#dc2626' };
43
+ const destinationRow = { display: 'flex', alignItems: 'center', gap: 6, ...helperText };
44
+ const destinationLogo = { width: 14, height: 14, borderRadius: '50%' };
45
+ const hideBrokenLogo = (e) => {
46
+ e.currentTarget.style.display = 'none';
47
+ };
48
+ /**
49
+ * Transfer from Exchange — the user enters an amount; "Open Coinbase" hands off to
50
+ * a hosted Coinbase pay-link that delivers to the embedded wallet on the
51
+ * destination chain. The destination (chain + currency + address) is bound to a
52
+ * funding session created up-front, so the client can't redirect the funds — only
53
+ * the amount is chosen here. After hand-off the bound session is polled until it
54
+ * settles (advanced by the Coinbase webhook on the backend), driving the
55
+ * success / failed screen. No Relay routing; Binance is gated until its rail lands.
56
+ */
57
+ const DepositCex = () => {
58
+ var _a, _b, _c, _d, _e, _f;
59
+ const { triggerResize } = useOpenfort();
60
+ const target = useFundingTarget();
61
+ // CEX (Coinbase pay-link + session) is served by the Openfort API, not the
62
+ // standalone funding service — resolve this rail's base URL from the API backend.
63
+ const { isAvailable, createSession, track, payLink, status } = useFunding({ useBackendUrl: true });
64
+ const wallet = useEthereumEmbeddedWallet();
65
+ const { embeddedAccounts } = useOpenfortCore();
66
+ const { chains } = useFundingChains();
67
+ const [amount, setAmount] = useState(String(MIN_AMOUNT));
68
+ const [pressedPreset, setPressedPreset] = useState(null);
69
+ const [session, setSession] = useState(null);
70
+ const [error, setError] = useState(null);
71
+ const [opened, setOpened] = useState(false);
72
+ // Resolve the destination by chain family: EVM targets use the EVM embedded
73
+ // wallet, Solana targets the Solana (SVM) embedded account — never cross families
74
+ // (an EVM address on a Solana target would be rejected / mis-delivered). Accounts
75
+ // come from the core store so EVM-only apps don't need the Solana React context.
76
+ const solanaAddress = (_a = embeddedAccounts === null || embeddedAccounts === void 0 ? void 0 : embeddedAccounts.find((acc) => acc.chainType === ChainTypeEnum.SVM)) === null || _a === void 0 ? void 0 : _a.address;
77
+ const address = isSolana(target.chain) ? solanaAddress : wallet.address;
78
+ const chainSupported = isCexDeliverable(target.chain);
79
+ // Resolve the destination asset + chain for the "Arrives as …" line. The live
80
+ // chain list is curated for source selection, so the destination may be absent;
81
+ // only claim a symbol we resolved, or USDC for the zero-config default.
82
+ const destChain = chains.find((c) => c.id === target.chain);
83
+ const destChainName = (_c = (_b = destChain === null || destChain === void 0 ? void 0 : destChain.name) !== null && _b !== void 0 ? _b : CEX_CHAIN_NAMES[target.chain]) !== null && _c !== void 0 ? _c : target.chain;
84
+ const destAsset = destChain === null || destChain === void 0 ? void 0 : destChain.currencies.find((c) => c.address.toLowerCase() === target.currency.toLowerCase());
85
+ const isDefaultUsdc = target.currency.toLowerCase() === DEST_USDC.toLowerCase();
86
+ const destAssetLabel = (_d = destAsset === null || destAsset === void 0 ? void 0 : destAsset.symbol) !== null && _d !== void 0 ? _d : (isDefaultUsdc ? 'USDC' : null);
87
+ const destAssetLogo = (_e = destAsset === null || destAsset === void 0 ? void 0 : destAsset.logo) !== null && _e !== void 0 ? _e : null;
88
+ const destChainLogo = (_f = destChain === null || destChain === void 0 ? void 0 : destChain.logo) !== null && _f !== void 0 ? _f : null;
89
+ // Mint the destination-bound session up-front (per target wallet), so the click
90
+ // that opens Coinbase is a single fast pay-link call and stays popup-safe.
91
+ //
92
+ // `createSession` is held in a ref and kept OUT of the effect deps: its identity
93
+ // churns whenever the core client re-memoizes (e.g. during Solana recovery
94
+ // retries, which re-render rapidly). If it were a dep, a churn mid-flight would
95
+ // re-run the effect, fire its cleanup (`cancelled = true`), then early-return on
96
+ // the unchanged sessionKey — so the in-flight create resolves but its result is
97
+ // dropped and never retried, stranding the page on "Preparing…". The effect must
98
+ // only re-run on a genuine destination change.
99
+ const sessionKey = useRef('');
100
+ const createSessionRef = useRef(createSession);
101
+ createSessionRef.current = createSession;
102
+ useEffect(() => {
103
+ if (!isAvailable || !address || !chainSupported)
104
+ return;
105
+ const key = `${target.chain}|${target.currency}|${address}`;
106
+ if (sessionKey.current === key)
107
+ return;
108
+ sessionKey.current = key;
109
+ let cancelled = false;
110
+ setSession(null);
111
+ setError(null);
112
+ createSessionRef
113
+ .current({ chain: target.chain, currency: target.currency, address })
114
+ .then((s) => {
115
+ if (!cancelled)
116
+ setSession({ id: s.id, clientSecret: s.clientSecret });
117
+ })
118
+ .catch((e) => {
119
+ if (!cancelled)
120
+ setError(e instanceof Error ? e : new Error(String(e)));
121
+ });
122
+ return () => {
123
+ cancelled = true;
124
+ // Clear the key so a genuine destination change re-creates the session;
125
+ // without this the guard above would block the retry after this cancel.
126
+ sessionKey.current = '';
127
+ };
128
+ }, [isAvailable, address, chainSupported, target.chain, target.currency]);
129
+ const fiatAmount = useMemo(() => {
130
+ const normalized = sanitizeForParsing(sanitizeAmountInput(amount));
131
+ if (!normalized)
132
+ return null;
133
+ const numeric = Number(normalized);
134
+ return Number.isFinite(numeric) ? numeric : null;
135
+ }, [amount]);
136
+ const amountValid = fiatAmount !== null && fiatAmount >= MIN_AMOUNT;
137
+ const amountTooLow = fiatAmount !== null && fiatAmount < MIN_AMOUNT;
138
+ const infraReady = isAvailable && chainSupported && Boolean(session) && !error;
139
+ const payReady = infraReady && amountValid;
140
+ // Resize when a block that changes the modal's height toggles.
141
+ useEffect(() => {
142
+ triggerResize();
143
+ }, [isAvailable, chainSupported, session, error, opened, amountTooLow, triggerResize]);
144
+ // Once the bound session settles, refresh balances so delivered funds show
145
+ // without a manual reload.
146
+ useEffect(() => {
147
+ if (status === 'succeeded')
148
+ invalidateBalance();
149
+ }, [status]);
150
+ const handleAmountChange = (event) => {
151
+ const raw = sanitizeAmountInput(event.target.value);
152
+ if (raw === '' || /^[0-9]*\.?[0-9]*$/.test(raw)) {
153
+ setPressedPreset(null);
154
+ setAmount(raw);
155
+ }
156
+ };
157
+ const handleAmountBlur = () => {
158
+ const normalized = sanitizeForParsing(sanitizeAmountInput(amount));
159
+ if (!normalized)
160
+ return;
161
+ const numeric = Number(normalized);
162
+ if (Number.isFinite(numeric) && numeric > 0)
163
+ setAmount(numeric.toFixed(2));
164
+ };
165
+ const handlePreset = (value) => {
166
+ setPressedPreset(value);
167
+ setAmount(value.toFixed(2));
168
+ };
169
+ const openExchange = () => {
170
+ if (!session || fiatAmount === null || !amountValid)
171
+ return;
172
+ // Open the tab up-front (sync) so the popup blocker permits it. Passing
173
+ // `noopener` makes window.open return null, leaving the tab stuck on
174
+ // about:blank — keep the handle and sever the opener link manually instead.
175
+ const w = window.open('about:blank', '_blank');
176
+ if (w)
177
+ w.opener = null;
178
+ logger.log('[funding:cex] open pay-link', { sessionId: session.id, amount: fiatAmount, asset: destAssetLabel });
179
+ void payLink({
180
+ sessionId: session.id,
181
+ clientSecret: session.clientSecret,
182
+ amount: String(fiatAmount),
183
+ ...(destAssetLabel ? { asset: destAssetLabel } : {}),
184
+ })
185
+ .then((url) => {
186
+ if (!url) {
187
+ w === null || w === void 0 ? void 0 : w.close(); // no URL resolved — don't strand the popup on "undefined"
188
+ return;
189
+ }
190
+ if (w)
191
+ w.location.href = url;
192
+ else
193
+ window.location.assign(url); // popup blocked — fall back to this tab
194
+ setOpened(true);
195
+ // Watch the destination-bound session settle so the modal can show the
196
+ // success / failed outcome instead of stranding the user on the form.
197
+ if (session)
198
+ void track({ id: session.id, clientSecret: session.clientSecret }).catch(() => { });
199
+ })
200
+ .catch((e) => {
201
+ w === null || w === void 0 ? void 0 : w.close();
202
+ setError(e instanceof Error ? e : new Error(String(e)));
203
+ });
204
+ };
205
+ // Once the deposit lands, the session-status flow takes over the modal with the
206
+ // success / refunded / expired screen (shared with the crypto rail).
207
+ if (isDepositFlowActive(status))
208
+ return jsx(DepositProgress, { status: status });
209
+ return (jsxs(PageContent, { onBack: routes.DEPOSIT, children: [jsx(ModalHeading, { children: "Transfer from Exchange" }), jsxs(Section, { children: [jsx(SectionLabel, { children: "Amount" }), jsxs(AmountCard, { children: [jsx(CurrencySymbol, { children: "$" }), jsx(AmountInput, { value: amount, onChange: handleAmountChange, onBlur: handleAmountBlur, placeholder: "0.00", inputMode: "decimal", autoComplete: "off" })] }), jsx(PresetList, { children: PRESETS.map((preset) => (jsxs(PresetButton, { type: "button", "$active": pressedPreset === preset, onClick: () => handlePreset(preset), children: ["$", preset] }, preset))) }), amountTooLow ? (jsxs("span", { style: errorHelper, children: ["Enter at least $", MIN_AMOUNT, ".00 \u2014 the Coinbase minimum."] })) : (jsxs("span", { style: helperText, children: ["Minimum $", MIN_AMOUNT, ".00"] })), chainSupported && (jsxs("span", { style: destinationRow, children: [destAssetLogo && jsx("img", { src: destAssetLogo, alt: "", style: destinationLogo, onError: hideBrokenLogo }), destChainLogo && jsx("img", { src: destChainLogo, alt: "", style: destinationLogo, onError: hideBrokenLogo })] }))] }), !isAvailable && jsx(ModalBody, { children: "Funding isn't available right now." }), isAvailable && !chainSupported && jsxs(ModalBody, { children: ["Coinbase can't deliver to ", destChainName, " yet."] }), error && jsx(ModalBody, { style: { color: '#dc2626' }, children: error.message }), jsx(StepDivider, { children: "Then open an exchange" }), jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 8, marginTop: 12 }, children: EXCHANGES.map((ex) => ex.comingSoon ? (jsxs("button", { type: "button", disabled: true, style: {
210
+ ...walletListBtn,
211
+ display: 'flex',
212
+ alignItems: 'center',
213
+ gap: 8,
214
+ opacity: 0.55,
215
+ cursor: 'not-allowed',
216
+ }, children: [jsx(ButtonLogo, { children: EXCHANGE_LOGO[ex.id] }), jsx("span", { children: titleCase(ex.id) }), jsx("span", { style: { marginLeft: 'auto', fontSize: 11, fontWeight: 600 }, children: "Coming soon" })] }, ex.id)) : (jsxs("button", { type: "button", disabled: !payReady, style: {
217
+ ...walletListBtn,
218
+ display: 'flex',
219
+ alignItems: 'center',
220
+ justifyContent: 'center',
221
+ gap: 8,
222
+ opacity: payReady ? 1 : 0.55,
223
+ cursor: payReady ? 'pointer' : 'not-allowed',
224
+ }, onClick: openExchange, children: [jsx(ButtonLogo, { children: EXCHANGE_LOGO[ex.id] }), infraReady ? `Open ${titleCase(ex.id)} ↗` : 'Preparing…'] }, ex.id))) }), opened &&
225
+ (status === 'waiting_payment' ? (jsx(DepositStatus, { status: status })) : (jsx(ModalBody, { style: { marginTop: 12 }, children: "Finish in the Coinbase tab \u2014 we'll confirm here once your funds arrive." })))] }));
226
+ };
227
+
228
+ export { DepositCex as default };
229
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Transfer from address — choose a source chain + token and send to the deposit
3
+ * address / QR that appears. Same-chain is a plain transfer to the wallet;
4
+ * cross-chain routes bridge via Relay. Wallet deeplinks live on the separate
5
+ * "Transfer from wallet" tab.
6
+ */
7
+ declare const DepositCrypto: () => import("react/jsx-runtime").JSX.Element;
8
+ export default DepositCrypto;
@@ -0,0 +1,31 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useEffect } from 'react';
3
+ import { ModalHeading, ModalBody } from '../../Common/Modal/styles.js';
4
+ import { routes } from '../../Openfort/types.js';
5
+ import { useOpenfort } from '../../Openfort/useOpenfort.js';
6
+ import { PageContent } from '../../PageContent/index.js';
7
+ import { DepositAddressBlock } from '../Deposit/DepositAddressBlock.js';
8
+ import { isDepositFlowActive, DepositProgress } from '../Deposit/DepositProgress.js';
9
+ import { RouteSelectors } from '../Deposit/RouteSelectors.js';
10
+ import { useDepositRoute } from '../Deposit/useDepositRoute.js';
11
+
12
+ /**
13
+ * Transfer from address — choose a source chain + token and send to the deposit
14
+ * address / QR that appears. Same-chain is a plain transfer to the wallet;
15
+ * cross-chain routes bridge via Relay. Wallet deeplinks live on the separate
16
+ * "Transfer from wallet" tab.
17
+ */
18
+ const DepositCrypto = () => {
19
+ var _a, _b, _c, _d;
20
+ const { triggerResize } = useOpenfort();
21
+ const route = useDepositRoute('crypto');
22
+ useEffect(() => {
23
+ triggerResize();
24
+ }, [route.receiverAddress, route.loading, route.status, triggerResize]);
25
+ if (isDepositFlowActive(route.status))
26
+ return jsx(DepositProgress, { status: route.status });
27
+ return (jsxs(PageContent, { onBack: routes.DEPOSIT, children: [jsx(ModalHeading, { children: "Transfer from address" }), jsx(RouteSelectors, { chains: route.chains, chain: route.chain, currency: route.currency, chainLabel: "Supported chain", onChainChange: route.setChain, onCurrencyChange: route.setCurrency }), !route.isAvailable && jsx(ModalBody, { children: "Funding isn't available right now." }), jsx(DepositAddressBlock, { assetLogo: (_b = (_a = route.activeCurrency) === null || _a === void 0 ? void 0 : _a.logo) !== null && _b !== void 0 ? _b : null, chainLogo: (_d = (_c = route.activeChain) === null || _c === void 0 ? void 0 : _c.logo) !== null && _d !== void 0 ? _d : null, receiverAddress: route.receiverAddress, pm: route.pm, sourceCurrency: route.activeCurrency ? { symbol: route.activeCurrency.symbol, decimals: route.activeCurrency.decimals } : null, sameChain: route.sameChain, loading: route.loading, status: route.status }), route.error && jsx(ModalBody, { style: { color: '#dc2626', marginTop: 12 }, children: route.error.message })] }));
28
+ };
29
+
30
+ export { DepositCrypto as default };
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,20 @@
1
+ import type { FundingChain, FundingCurrency } from '../../../hooks/openfort/useFundingChains';
2
+ type Props = {
3
+ /** Relay deposit address the source funds are sent to. */
4
+ receiverAddress: string | null;
5
+ activeChain: FundingChain | undefined;
6
+ activeCurrency: FundingCurrency | undefined;
7
+ loading: boolean;
8
+ /** Amount to send, in the source token's units. Owned by the parent so the
9
+ * amount input + presets are shared with the mobile (deeplink) path. */
10
+ amount: string;
11
+ };
12
+ /**
13
+ * Desktop "transfer from wallet": send the source token to the Relay deposit
14
+ * address straight from the user's EXTERNAL browser-extension wallet
15
+ * (MetaMask/Rabby/…), via that connector's own provider — never the active
16
+ * Openfort embedded account (that one is the destination, not the source).
17
+ * Once the deposit lands, the funding session's status polling drives progress.
18
+ */
19
+ export declare function DepositWalletDesktop({ receiverAddress, activeChain, activeCurrency, loading, amount }: Props): import("react/jsx-runtime").JSX.Element | null;
20
+ export {};
@@ -0,0 +1,139 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { parseUnits, formatUnits, encodeFunctionData, erc20Abi } from 'viem';
4
+ import { WalletIcon } from '../../../assets/icons.js';
5
+ import Logos from '../../../assets/logos.js';
6
+ import { useEthereumBridge } from '../../../ethereum/OpenfortEthereumBridgeContext.js';
7
+ import { ModalBody } from '../../Common/Modal/styles.js';
8
+ import { useOpenfort } from '../../Openfort/useOpenfort.js';
9
+ import { DepositStatus } from '../Deposit/DepositStatus.js';
10
+ import { walletListBtn } from '../Deposit/formStyles.js';
11
+ import { ButtonLogo } from '../Deposit/styles.js';
12
+ import { caipToChainId } from './walletDeeplinks.js';
13
+
14
+ /** Hardcoded brand logo for a connector, matched by id/name; falls back to its own icon, then a generic. */
15
+ function brandLogo(connector) {
16
+ const k = `${connector.id} ${connector.name}`.toLowerCase();
17
+ if (k.includes('metamask'))
18
+ return jsx(Logos.MetaMask, { background: true });
19
+ if (k.includes('rabby'))
20
+ return jsx(Logos.Rabby, {});
21
+ if (k.includes('coinbase'))
22
+ return jsx(Logos.Coinbase, { background: true });
23
+ if (k.includes('phantom'))
24
+ return jsx(Logos.Phantom, { background: true });
25
+ if (k.includes('trust'))
26
+ return jsx(Logos.Trust, {});
27
+ if (k.includes('rainbow'))
28
+ return jsx(Logos.Rainbow, { round: true });
29
+ if (connector.icon)
30
+ return jsx("img", { src: connector.icon, alt: "", width: 20, height: 20, style: { borderRadius: 6 } });
31
+ return jsx(WalletIcon, {});
32
+ }
33
+ /** Readable message from a wallet/provider error; null for a user rejection (4001). */
34
+ function walletErrorMessage(e) {
35
+ if (e && typeof e === 'object') {
36
+ const o = e;
37
+ if (o.code === 4001)
38
+ return null; // user rejected — nothing to flag
39
+ return o.shortMessage || o.message || o.details || 'Transaction failed';
40
+ }
41
+ return typeof e === 'string' ? e : 'Transaction failed';
42
+ }
43
+ /**
44
+ * Desktop "transfer from wallet": send the source token to the Relay deposit
45
+ * address straight from the user's EXTERNAL browser-extension wallet
46
+ * (MetaMask/Rabby/…), via that connector's own provider — never the active
47
+ * Openfort embedded account (that one is the destination, not the source).
48
+ * Once the deposit lands, the funding session's status polling drives progress.
49
+ */
50
+ function DepositWalletDesktop({ receiverAddress, activeChain, activeCurrency, loading, amount }) {
51
+ const bridge = useEthereumBridge();
52
+ const { triggerResize } = useOpenfort();
53
+ const [busyId, setBusyId] = useState(null);
54
+ const [error, setError] = useState(null);
55
+ const [sent, setSent] = useState(false);
56
+ // Grow the modal when the busy / error / sent feedback toggles, so the "Confirm
57
+ // in your wallet…" and insufficient-balance messages are revealed instead of
58
+ // clipped below the fold (which reads as "nothing happened" after a click).
59
+ useEffect(() => {
60
+ triggerResize();
61
+ }, [busyId, error, sent, triggerResize]);
62
+ if (!bridge)
63
+ return null; // EVM-only (no wagmi) — nothing to send through
64
+ // bridge.connectors already excludes the Openfort embedded connector, so these
65
+ // are the user's external wallets. Drop WalletConnect: its provider needs a
66
+ // connect()/session flow our direct request() path doesn't support.
67
+ const connectors = bridge.connectors.filter((c) => !c.id.toLowerCase().includes('walletconnect'));
68
+ const srcChainId = caipToChainId(activeChain === null || activeChain === void 0 ? void 0 : activeChain.id);
69
+ const amountValid = Number.parseFloat(amount) > 0;
70
+ const sendVia = async (c) => {
71
+ var _a, _b;
72
+ if (!receiverAddress || !activeCurrency || !srcChainId || !amountValid)
73
+ return;
74
+ setBusyId(c.id);
75
+ setError(null);
76
+ setSent(false);
77
+ try {
78
+ const provider = (await ((_a = c.getProvider) === null || _a === void 0 ? void 0 : _a.call(c)));
79
+ if (!provider)
80
+ throw new Error('Wallet provider unavailable');
81
+ const accounts = (await provider.request({ method: 'eth_requestAccounts' }));
82
+ const from = accounts === null || accounts === void 0 ? void 0 : accounts[0];
83
+ if (!from)
84
+ throw new Error('No account in wallet');
85
+ // Ask the wallet to switch to the source chain (ignored if already there).
86
+ await provider
87
+ .request({ method: 'wallet_switchEthereumChain', params: [{ chainId: `0x${srcChainId.toString(16)}` }] })
88
+ .catch(() => { });
89
+ const value = parseUnits(amount, activeCurrency.decimals);
90
+ const to = receiverAddress;
91
+ // Guard: confirm the wallet holds enough on this chain. Otherwise the transfer
92
+ // just reverts (wasted gas) and the deposit never arrives — the bug we hit.
93
+ const balance = activeCurrency.native
94
+ ? BigInt((await provider.request({ method: 'eth_getBalance', params: [from, 'latest'] })))
95
+ : BigInt((await provider.request({
96
+ method: 'eth_call',
97
+ params: [
98
+ { to: activeCurrency.address, data: `0x70a08231${from.slice(2).padStart(64, '0')}` },
99
+ 'latest',
100
+ ],
101
+ })) || '0x0');
102
+ if (balance < value) {
103
+ setError(`Not enough ${activeCurrency.symbol} on ${(_b = activeChain === null || activeChain === void 0 ? void 0 : activeChain.name) !== null && _b !== void 0 ? _b : 'this chain'} — you have ${formatUnits(balance, activeCurrency.decimals)}.`);
104
+ return;
105
+ }
106
+ if (activeCurrency.native) {
107
+ await provider.request({
108
+ method: 'eth_sendTransaction',
109
+ params: [{ from, to, value: `0x${value.toString(16)}` }],
110
+ });
111
+ }
112
+ else {
113
+ const data = encodeFunctionData({ abi: erc20Abi, functionName: 'transfer', args: [to, value] });
114
+ await provider.request({
115
+ method: 'eth_sendTransaction',
116
+ params: [{ from, to: activeCurrency.address, data }],
117
+ });
118
+ }
119
+ setSent(true);
120
+ }
121
+ catch (e) {
122
+ setError(walletErrorMessage(e));
123
+ }
124
+ finally {
125
+ setBusyId(null);
126
+ }
127
+ };
128
+ return (jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 10, marginTop: 14 }, children: [connectors.length === 0 && jsx(ModalBody, { children: "No browser wallet detected. Install MetaMask or Rabby." }), connectors.map((c) => (jsxs("button", { type: "button", disabled: !amountValid || busyId !== null || loading, style: {
129
+ ...walletListBtn,
130
+ display: 'flex',
131
+ alignItems: 'center',
132
+ justifyContent: 'flex-start',
133
+ gap: 10,
134
+ opacity: !amountValid || busyId !== null ? 0.55 : 1,
135
+ }, onClick: () => sendVia(c), children: [jsx(ButtonLogo, { children: brandLogo(c) }), jsx("span", { children: busyId === c.id ? 'Confirm in your wallet…' : `Send via ${c.name}` })] }, c.id))), sent && jsx(DepositStatus, { status: "waiting_payment" }), error && jsx(ModalBody, { style: { color: '#dc2626' }, children: error })] }));
136
+ }
137
+
138
+ export { DepositWalletDesktop };
139
+ //# sourceMappingURL=DepositWalletDesktop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DepositWalletDesktop.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}