@openfort/react 1.5.1 → 1.6.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 (71) hide show
  1. package/build/components/Common/Chain/styles.d.ts +10 -0
  2. package/build/components/Common/Chain/styles.js +103 -1
  3. package/build/components/Common/Chain/styles.js.map +1 -1
  4. package/build/components/Common/Modal/index.js +2 -0
  5. package/build/components/Common/Modal/index.js.map +1 -1
  6. package/build/components/Common/SolanaChain/index.d.ts +5 -4
  7. package/build/components/Common/SolanaChain/index.js +9 -17
  8. package/build/components/Common/SolanaChain/index.js.map +1 -1
  9. package/build/components/ConnectModal/index.js +2 -0
  10. package/build/components/ConnectModal/index.js.map +1 -1
  11. package/build/components/Openfort/OpenfortProvider.js +4 -0
  12. package/build/components/Openfort/OpenfortProvider.js.map +1 -1
  13. package/build/components/Openfort/context.d.ts +4 -1
  14. package/build/components/Openfort/types.d.ts +22 -0
  15. package/build/components/Openfort/types.js +1 -0
  16. package/build/components/Openfort/types.js.map +1 -1
  17. package/build/components/Pages/Buy/styles.js +10 -10
  18. package/build/components/Pages/Connected/EthereumConnected.js +7 -1
  19. package/build/components/Pages/Connected/EthereumConnected.js.map +1 -1
  20. package/build/components/Pages/Deposit/TestnetNotice.js +15 -3
  21. package/build/components/Pages/Deposit/TestnetNotice.js.map +1 -1
  22. package/build/components/Pages/Deposit/index.js +1 -2
  23. package/build/components/Pages/Deposit/index.js.map +1 -1
  24. package/build/components/Pages/Deposit/sources.d.ts +3 -0
  25. package/build/components/Pages/Deposit/sources.js +4 -1
  26. package/build/components/Pages/Deposit/sources.js.map +1 -1
  27. package/build/components/Pages/Deposit/useFundingTarget.d.ts +6 -4
  28. package/build/components/Pages/Deposit/useFundingTarget.js +18 -7
  29. package/build/components/Pages/Deposit/useFundingTarget.js.map +1 -1
  30. package/build/components/Pages/DepositCex/index.js +2 -1
  31. package/build/components/Pages/DepositCex/index.js.map +1 -1
  32. package/build/components/Pages/Send/EthereumSend.js +10 -4
  33. package/build/components/Pages/Send/EthereumSend.js.map +1 -1
  34. package/build/components/Pages/Send/SolanaSend.js +9 -4
  35. package/build/components/Pages/Send/SolanaSend.js.map +1 -1
  36. package/build/components/Pages/Send/styles.d.ts +0 -1
  37. package/build/components/Pages/Send/styles.js +2 -13
  38. package/build/components/Pages/Send/styles.js.map +1 -1
  39. package/build/components/Pages/SendConfirmation/ConfirmationSummary.d.ts +27 -0
  40. package/build/components/Pages/SendConfirmation/ConfirmationSummary.js +15 -0
  41. package/build/components/Pages/SendConfirmation/ConfirmationSummary.js.map +1 -0
  42. package/build/components/Pages/SendConfirmation/SolanaSendConfirmation.js +3 -3
  43. package/build/components/Pages/SendConfirmation/index.js +14 -30
  44. package/build/components/Pages/SendConfirmation/index.js.map +1 -1
  45. package/build/components/Pages/SendConfirmation/styles.d.ts +7 -1
  46. package/build/components/Pages/SendConfirmation/styles.js +49 -17
  47. package/build/components/Pages/SendConfirmation/styles.js.map +1 -1
  48. package/build/components/Pages/SignMessage/index.d.ts +2 -0
  49. package/build/components/Pages/SignMessage/index.js +81 -0
  50. package/build/components/Pages/SignMessage/index.js.map +1 -0
  51. package/build/components/Pages/SignMessage/styles.d.ts +14 -0
  52. package/build/components/Pages/SignMessage/styles.js +82 -0
  53. package/build/components/Pages/SignMessage/styles.js.map +1 -0
  54. package/build/hooks/openfort/useSignMessage.d.ts +27 -0
  55. package/build/hooks/openfort/useSignMessage.js +52 -0
  56. package/build/hooks/openfort/useSignMessage.js.map +1 -0
  57. package/build/hooks/openfort/useUI.d.ts +6 -1
  58. package/build/hooks/openfort/useUI.js +12 -2
  59. package/build/hooks/openfort/useUI.js.map +1 -1
  60. package/build/index.d.ts +2 -1
  61. package/build/index.js +1 -0
  62. package/build/index.js.map +1 -1
  63. package/build/localizations/locales/en-US.js +1 -1
  64. package/build/utils/rpc.d.ts +6 -0
  65. package/build/utils/rpc.js +12 -1
  66. package/build/utils/rpc.js.map +1 -1
  67. package/build/version.d.ts +1 -1
  68. package/build/version.js +1 -1
  69. package/build/wagmi/components/ChainSelect/index.js +1 -93
  70. package/build/wagmi/components/ChainSelect/index.js.map +1 -1
  71. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { useMemo } from 'react';
2
+ import { useEffect, useMemo } from 'react';
3
3
  import { parseUnits, isAddress, formatUnits } from 'viem';
4
4
  import { useEthereumWalletAssets } from '../../../ethereum/hooks/useEthereumWalletAssets.js';
5
5
  import Button from '../../Common/Button/index.js';
@@ -9,12 +9,18 @@ import { ModalHeading } from '../../Common/Modal/styles.js';
9
9
  import { routes } from '../../Openfort/types.js';
10
10
  import { useOpenfort } from '../../Openfort/useOpenfort.js';
11
11
  import { PageContent } from '../../PageContent/index.js';
12
- import { Form, Field, FieldLabel, TokenSelectorButton, TokenSelectorContent, TokenSelectorValue, TokenSelectorRight, AmountInputWrapper, MaxButton, HelperText, ErrorText } from './styles.js';
12
+ import { AmountCard, AmountInput } from '../Buy/styles.js';
13
+ import { Form, Field, FieldLabel, TokenSelectorButton, TokenSelectorContent, TokenSelectorValue, TokenSelectorRight, MaxButton, HelperText, ErrorText } from './styles.js';
13
14
  import { isSameToken, sanitizeForParsing, formatBalance, sanitizeAmountInput } from './utils.js';
14
15
 
15
16
  const EthereumSend = () => {
16
17
  var _a, _b, _c, _d;
17
- const { sendForm, setSendForm, setRoute } = useOpenfort();
18
+ const { sendForm, setSendForm, setRoute, triggerResize } = useOpenfort();
19
+ // Size the modal to the form on mount. Without this the screen isn't anchored
20
+ // and scrolls within the modal — every other Page triggers a resize on mount.
21
+ useEffect(() => {
22
+ triggerResize();
23
+ }, [triggerResize]);
18
24
  const { data: assets } = useEthereumWalletAssets();
19
25
  const matchedToken = useMemo(() => assets === null || assets === void 0 ? void 0 : assets.find((asset) => isSameToken(asset, sendForm.asset)), [assets, sendForm.asset]);
20
26
  const selectedTokenOption = matchedToken !== null && matchedToken !== void 0 ? matchedToken : assets === null || assets === void 0 ? void 0 : assets[0];
@@ -81,7 +87,7 @@ const EthereumSend = () => {
81
87
  };
82
88
  const availableLabel = formatBalance(selectedBalanceValue, selectedDecimalsValue);
83
89
  const maxDisabled = !selectedBalanceValue;
84
- return (jsxs(PageContent, { onBack: routes.CONNECTED, children: [jsx(ModalHeading, { children: "Send assets" }), jsxs(Form, { onSubmit: handleSubmit, children: [jsxs(Field, { children: [jsx(FieldLabel, { children: "Asset" }), jsxs(TokenSelectorButton, { type: "button", onClick: handleOpenTokenSelector, children: [jsx(TokenSelectorContent, { children: jsx(TokenSelectorValue, { "$primary": true, children: selectedSymbol || 'Select token' }) }), jsxs(TokenSelectorRight, { children: [jsx(TokenSelectorValue, { children: availableLabel === '--' ? '--' : `${availableLabel} ${selectedSymbol !== null && selectedSymbol !== void 0 ? selectedSymbol : ''}` }), jsx(Arrow, { width: "13", height: "12", viewBox: "0 0 13 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx(ArrowChevron, { stroke: "currentColor", d: "M7.51431 1.5L11.757 5.74264M7.5 10.4858L11.7426 6.24314", strokeWidth: "2", strokeLinecap: "round" }) })] })] })] }), jsxs(Field, { children: [jsx(FieldLabel, { children: "Amount" }), jsxs(AmountInputWrapper, { children: [jsx(Input, { placeholder: "0.00", value: sendForm.amount, onChange: handleAmountChange, inputMode: "decimal", autoComplete: "off", style: { paddingRight: '86px' } }), jsx(MaxButton, { type: "button", onClick: handleMax, disabled: maxDisabled, children: "Max" })] }), jsxs(HelperText, { children: ["Available: ", availableLabel, " ", selectedSymbol] }), sendForm.amount && parsedAmount === null && jsx(ErrorText, { children: "Enter a valid amount." }), insufficientBalance && jsx(ErrorText, { children: "Insufficient balance for this transfer." })] }), jsxs(Field, { children: [jsx(FieldLabel, { children: "Recipient address" }), jsx(Input, { placeholder: "0x...", value: sendForm.recipient, onChange: handleRecipientChange, autoComplete: "off" }), sendForm.recipient && !recipientValid && jsx(ErrorText, { children: "Enter a valid wallet address." })] }), jsx(Button, { variant: "primary", disabled: !canProceed, children: "Review transfer" })] })] }));
90
+ return (jsxs(PageContent, { onBack: routes.CONNECTED, children: [jsx(ModalHeading, { children: "Send assets" }), jsxs(Form, { onSubmit: handleSubmit, children: [jsxs(Field, { children: [jsx(FieldLabel, { children: "Asset" }), jsxs(TokenSelectorButton, { type: "button", onClick: handleOpenTokenSelector, children: [jsx(TokenSelectorContent, { children: jsx(TokenSelectorValue, { "$primary": true, children: selectedSymbol || 'Select token' }) }), jsxs(TokenSelectorRight, { children: [jsx(TokenSelectorValue, { children: availableLabel === '--' ? '--' : `${availableLabel} ${selectedSymbol !== null && selectedSymbol !== void 0 ? selectedSymbol : ''}` }), jsx(Arrow, { width: "13", height: "12", viewBox: "0 0 13 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx(ArrowChevron, { stroke: "currentColor", d: "M7.51431 1.5L11.757 5.74264M7.5 10.4858L11.7426 6.24314", strokeWidth: "2", strokeLinecap: "round" }) })] })] })] }), jsxs(Field, { children: [jsx(FieldLabel, { children: "Amount" }), jsxs(AmountCard, { style: { marginTop: 12 }, children: [jsx(AmountInput, { placeholder: "0.00", value: sendForm.amount, onChange: handleAmountChange, inputMode: "decimal", autoComplete: "off" }), jsx(MaxButton, { type: "button", onClick: handleMax, disabled: maxDisabled, children: "Max" })] }), jsxs(HelperText, { children: ["Available: ", availableLabel, " ", selectedSymbol] }), sendForm.amount && parsedAmount === null && jsx(ErrorText, { children: "Enter a valid amount." }), insufficientBalance && jsx(ErrorText, { children: "Insufficient balance for this transfer." })] }), jsxs(Field, { children: [jsx(FieldLabel, { children: "Recipient address" }), jsx(Input, { placeholder: "0x...", value: sendForm.recipient, onChange: handleRecipientChange, autoComplete: "off" }), sendForm.recipient && !recipientValid && jsx(ErrorText, { children: "Enter a valid wallet address." })] }), jsx(Button, { variant: "primary", disabled: !canProceed, children: "Review transfer" })] })] }));
85
91
  };
86
92
 
87
93
  export { EthereumSend };
@@ -1 +1 @@
1
- {"version":3,"file":"EthereumSend.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"EthereumSend.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { useMemo } from 'react';
2
+ import { useEffect, useMemo } from 'react';
3
3
  import { parseUnits, formatUnits } from 'viem';
4
4
  import { useSolanaWalletAssets } from '../../../solana/hooks/useSolanaWalletAssets.js';
5
5
  import Button from '../../Common/Button/index.js';
@@ -9,7 +9,8 @@ import { ModalHeading } from '../../Common/Modal/styles.js';
9
9
  import { routes } from '../../Openfort/types.js';
10
10
  import { useOpenfort } from '../../Openfort/useOpenfort.js';
11
11
  import { PageContent } from '../../PageContent/index.js';
12
- import { Form, Field, FieldLabel, TokenSelectorButton, TokenSelectorContent, TokenSelectorValue, TokenSelectorRight, AmountInputWrapper, MaxButton, HelperText, ErrorText } from './styles.js';
12
+ import { AmountCard, AmountInput } from '../Buy/styles.js';
13
+ import { Form, Field, FieldLabel, TokenSelectorButton, TokenSelectorContent, TokenSelectorValue, TokenSelectorRight, MaxButton, HelperText, ErrorText } from './styles.js';
13
14
  import { sanitizeForParsing, formatBalance, sanitizeAmountInput } from './utils.js';
14
15
 
15
16
  const SOL_DECIMALS = 9;
@@ -26,8 +27,12 @@ function solAsset(balance) {
26
27
  };
27
28
  }
28
29
  const SolanaSend = () => {
29
- const { sendForm, setSendForm, setRoute } = useOpenfort();
30
+ const { sendForm, setSendForm, setRoute, triggerResize } = useOpenfort();
30
31
  const { data: assets } = useSolanaWalletAssets();
32
+ // Size the modal to the form on mount so it's anchored and doesn't scroll.
33
+ useEffect(() => {
34
+ triggerResize();
35
+ }, [triggerResize]);
31
36
  const asset = sendForm.asset;
32
37
  const selected = asset.type === 'spl'
33
38
  ? { isSpl: true, mint: asset.address, decimals: asset.metadata.decimals, symbol: asset.metadata.symbol }
@@ -82,7 +87,7 @@ const SolanaSend = () => {
82
87
  setSendForm((prev) => ({ ...prev, amount: formatUnits(balanceBase, selected.decimals) }));
83
88
  };
84
89
  const handleOpenTokenSelector = () => setRoute(routes.SOL_SEND_TOKEN_SELECT);
85
- return (jsxs(PageContent, { onBack: routes.SOL_CONNECTED, children: [jsx(ModalHeading, { children: "Send assets" }), jsxs(Form, { onSubmit: handleSubmit, children: [jsxs(Field, { children: [jsx(FieldLabel, { children: "Asset" }), jsxs(TokenSelectorButton, { type: "button", onClick: handleOpenTokenSelector, children: [jsx(TokenSelectorContent, { children: jsx(TokenSelectorValue, { "$primary": true, children: selected.symbol }) }), jsxs(TokenSelectorRight, { children: [jsx(TokenSelectorValue, { children: availableLabel === '--' ? '--' : `${availableLabel} ${selected.symbol}` }), jsx(Arrow, { width: "13", height: "12", viewBox: "0 0 13 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx(ArrowChevron, { stroke: "currentColor", d: "M7.51431 1.5L11.757 5.74264M7.5 10.4858L11.7426 6.24314", strokeWidth: "2", strokeLinecap: "round" }) })] })] })] }), jsxs(Field, { children: [jsx(FieldLabel, { children: "Amount" }), jsxs(AmountInputWrapper, { children: [jsx(Input, { placeholder: "0.00", value: sendForm.amount, onChange: handleAmountChange, inputMode: "decimal", autoComplete: "off", style: { paddingRight: '86px' } }), jsx(MaxButton, { type: "button", onClick: handleMax, disabled: balanceBase === undefined, children: "Max" })] }), jsxs(HelperText, { children: ["Available: ", availableLabel, " ", selected.symbol] }), sendForm.amount && parsedAmount === null && jsx(ErrorText, { children: "Enter a valid amount." }), insufficientBalance && jsxs(ErrorText, { children: ["Insufficient ", selected.symbol, " balance for this transfer."] })] }), jsxs(Field, { children: [jsx(FieldLabel, { children: "Recipient address" }), jsx(Input, { placeholder: "Solana address", value: sendForm.recipient, onChange: (e) => setSendForm((prev) => ({ ...prev, recipient: e.target.value })), autoComplete: "off" }), sendForm.recipient && !recipientValid && jsx(ErrorText, { children: "Enter a valid Solana address." })] }), jsx(Button, { variant: "primary", disabled: !canProceed, children: "Review transfer" })] })] }));
90
+ return (jsxs(PageContent, { onBack: routes.SOL_CONNECTED, children: [jsx(ModalHeading, { children: "Send assets" }), jsxs(Form, { onSubmit: handleSubmit, children: [jsxs(Field, { children: [jsx(FieldLabel, { children: "Asset" }), jsxs(TokenSelectorButton, { type: "button", onClick: handleOpenTokenSelector, children: [jsx(TokenSelectorContent, { children: jsx(TokenSelectorValue, { "$primary": true, children: selected.symbol }) }), jsxs(TokenSelectorRight, { children: [jsx(TokenSelectorValue, { children: availableLabel === '--' ? '--' : `${availableLabel} ${selected.symbol}` }), jsx(Arrow, { width: "13", height: "12", viewBox: "0 0 13 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx(ArrowChevron, { stroke: "currentColor", d: "M7.51431 1.5L11.757 5.74264M7.5 10.4858L11.7426 6.24314", strokeWidth: "2", strokeLinecap: "round" }) })] })] })] }), jsxs(Field, { children: [jsx(FieldLabel, { children: "Amount" }), jsxs(AmountCard, { style: { marginTop: 12 }, children: [jsx(AmountInput, { placeholder: "0.00", value: sendForm.amount, onChange: handleAmountChange, inputMode: "decimal", autoComplete: "off" }), jsx(MaxButton, { type: "button", onClick: handleMax, disabled: balanceBase === undefined, children: "Max" })] }), jsxs(HelperText, { children: ["Available: ", availableLabel, " ", selected.symbol] }), sendForm.amount && parsedAmount === null && jsx(ErrorText, { children: "Enter a valid amount." }), insufficientBalance && jsxs(ErrorText, { children: ["Insufficient ", selected.symbol, " balance for this transfer."] })] }), jsxs(Field, { children: [jsx(FieldLabel, { children: "Recipient address" }), jsx(Input, { placeholder: "Solana address", value: sendForm.recipient, onChange: (e) => setSendForm((prev) => ({ ...prev, recipient: e.target.value })), autoComplete: "off" }), sendForm.recipient && !recipientValid && jsx(ErrorText, { children: "Enter a valid Solana address." })] }), jsx(Button, { variant: "primary", disabled: !canProceed, children: "Review transfer" })] })] }));
86
91
  };
87
92
 
88
93
  export { SolanaSend };
@@ -1 +1 @@
1
- {"version":3,"file":"SolanaSend.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"SolanaSend.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -8,7 +8,6 @@ export declare const TokenSelectorValue: import("styled-components").StyledCompo
8
8
  $muted?: boolean;
9
9
  }, never>;
10
10
  export declare const TokenSelectorRight: import("styled-components").StyledComponent<"div", any, {}, never>;
11
- export declare const AmountInputWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
12
11
  export declare const MaxButton: import("styled-components").StyledComponent<"button", any, {}, never>;
13
12
  export declare const HelperText: import("styled-components").StyledComponent<"span", any, {}, never>;
14
13
  export declare const ErrorText: import("styled-components").StyledComponent<"span", any, {}, never>;
@@ -62,19 +62,8 @@ const TokenSelectorRight = styled.div `
62
62
  gap: 6px;
63
63
  color: var(--ck-body-color-muted);
64
64
  `;
65
- const AmountInputWrapper = styled.div `
66
- position: relative;
67
- margin-top: 12px;
68
-
69
- > div {
70
- margin: 0;
71
- }
72
- `;
73
65
  const MaxButton = styled.button `
74
- position: absolute;
75
- right: 12px;
76
- top: 50%;
77
- transform: translateY(-50%);
66
+ flex-shrink: 0;
78
67
  padding: 6px 14px;
79
68
  border-radius: 16px;
80
69
  border: 1px solid var(--ck-body-divider);
@@ -108,5 +97,5 @@ const ErrorText = styled.span `
108
97
  color: var(--ck-body-color-danger);
109
98
  `;
110
99
 
111
- export { AmountInputWrapper, ErrorText, Field, FieldLabel, Form, HelperText, MaxButton, TokenSelectorButton, TokenSelectorContent, TokenSelectorRight, TokenSelectorValue };
100
+ export { ErrorText, Field, FieldLabel, Form, HelperText, MaxButton, TokenSelectorButton, TokenSelectorContent, TokenSelectorRight, TokenSelectorValue };
112
101
  //# sourceMappingURL=styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"styles.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,27 @@
1
+ import type { ReactNode } from 'react';
2
+ type ConfirmationAddress = {
3
+ display: string;
4
+ value: string;
5
+ };
6
+ interface ConfirmationSummaryProps {
7
+ /** Total being sent, e.g. "0.5" + "ETH". */
8
+ amount: string;
9
+ symbol: string;
10
+ /** Optional fiat estimate shown next to the total, e.g. "$180.84". */
11
+ fiat?: string | null;
12
+ /** Recipient address (truncated for display, full for copy). */
13
+ to?: ConfirmationAddress;
14
+ networkName: string;
15
+ networkIcon?: ReactNode;
16
+ /** Fee cell — the live estimate, or a "Sponsored" indicator. */
17
+ fee: ReactNode;
18
+ /** The wallet the funds are paid from. */
19
+ payWith?: ConfirmationAddress;
20
+ }
21
+ /**
22
+ * Shared, chain-agnostic transaction preview used by the EVM and Solana send
23
+ * confirmation screens. Renders the approval-style rows (Total / To / Network /
24
+ * Estimated fee) plus a "Pay with" card.
25
+ */
26
+ export declare function ConfirmationSummary({ amount, symbol, fiat, to, networkName, networkIcon, fee, payWith, }: ConfirmationSummaryProps): import("react/jsx-runtime").JSX.Element;
27
+ export {};
@@ -0,0 +1,15 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { CopyText } from '../../Common/CopyToClipboard/CopyText.js';
3
+ import { SummaryList, SummaryItem, SummaryLabel, AmountValue, FiatValue, AddressValue, NetworkValue, PayWithCard, PayWithMeta, PayWithAddress, PayWithBadge } from './styles.js';
4
+
5
+ /**
6
+ * Shared, chain-agnostic transaction preview used by the EVM and Solana send
7
+ * confirmation screens. Renders the approval-style rows (Total / To / Network /
8
+ * Estimated fee) plus a "Pay with" card.
9
+ */
10
+ function ConfirmationSummary({ amount, symbol, fiat, to, networkName, networkIcon, fee, payWith, }) {
11
+ return (jsxs(Fragment, { children: [jsxs(SummaryList, { children: [jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "Total" }), jsxs(AmountValue, { children: [amount || '0', " ", symbol, fiat ? jsxs(FiatValue, { children: ["\u2248 ", fiat] }) : null] })] }), jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "To" }), jsx(AddressValue, { children: to ? (jsx(CopyText, { size: "1rem", value: to.value, children: to.display })) : ('--') })] }), jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "Network" }), jsxs(NetworkValue, { children: [networkIcon, networkName] })] }), jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "Estimated fee" }), fee] })] }), jsxs(PayWithCard, { children: [jsxs(PayWithMeta, { children: [jsx(SummaryLabel, { children: "Pay with" }), jsx(PayWithAddress, { children: payWith ? (jsx(CopyText, { size: "0.875rem", value: payWith.value, children: payWith.display })) : ('--') })] }), jsxs(PayWithBadge, { children: [amount || '0', " ", symbol] })] })] }));
12
+ }
13
+
14
+ export { ConfirmationSummary };
15
+ //# sourceMappingURL=ConfirmationSummary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmationSummary.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
@@ -8,13 +8,13 @@ import { sendSplTokenGasless, sendSplToken, sendSolGasless, sendSol } from '../.
8
8
  import 'detect-browser';
9
9
  import { truncateSolanaAddress } from '../../../utils/format.js';
10
10
  import Button from '../../Common/Button/index.js';
11
- import { CopyText } from '../../Common/CopyToClipboard/CopyText.js';
12
11
  import Loader from '../../Common/Loading/index.js';
13
12
  import { ModalHeading, ModalBody } from '../../Common/Modal/styles.js';
14
13
  import { routes } from '../../Openfort/types.js';
15
14
  import { useOpenfort } from '../../Openfort/useOpenfort.js';
16
15
  import { PageContent } from '../../PageContent/index.js';
17
- import { ButtonRow, SummaryList, SummaryItem, SummaryLabel, AmountValue, AddressValue, FeesValue, ErrorContainer, ErrorTitle, ErrorMessage } from './styles.js';
16
+ import { ConfirmationSummary } from './ConfirmationSummary.js';
17
+ import { ButtonRow, SponsoredFee, FeesValue, ErrorContainer, ErrorTitle, ErrorMessage } from './styles.js';
18
18
 
19
19
  const SOL_DECIMALS = 9;
20
20
  const SolanaSendConfirmation = () => {
@@ -114,7 +114,7 @@ const SolanaSendConfirmation = () => {
114
114
  if (signature) {
115
115
  return (jsxs(PageContent, { children: [jsx(Loader, { isSuccess: true, header: "Transfer sent", description: `${amount} ${symbol} sent successfully` }), jsxs(ButtonRow, { children: [jsx(Button, { variant: "primary", onClick: handleViewExplorer, children: "View on Explorer" }), jsx(Button, { variant: "secondary", onClick: handleFinish, children: "Back to profile" })] })] }));
116
116
  }
117
- return (jsxs(PageContent, { onBack: routes.SOL_SEND, children: [jsx(ModalHeading, { children: "Confirm transfer" }), jsx(ModalBody, { children: "Review the transaction details before sending." }), jsxs(SummaryList, { children: [jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "Sending" }), jsxs(AmountValue, { children: [amount || '0', " ", symbol] })] }), jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "From" }), jsx(AddressValue, { children: address ? (jsx(CopyText, { size: "1rem", value: address, children: truncateSolanaAddress(address) })) : ('--') })] }), jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "To" }), jsx(AddressValue, { children: recipient ? (jsx(CopyText, { size: "1rem", value: recipient, children: truncateSolanaAddress(recipient) })) : ('--') })] }), isSponsored && (jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "Network fee" }), jsx(FeesValue, { "$completed": true, children: "Sponsored" })] }))] }), error && (jsxs(ErrorContainer, { children: [jsx(ErrorTitle, { children: "Transaction failed" }), jsx(ErrorMessage, { children: error })] })), jsxs(ButtonRow, { children: [jsx(Button, { variant: "primary", onClick: handleConfirm, disabled: !address || isLoading, waiting: isLoading, children: isLoading ? 'Confirming...' : 'Confirm' }), jsx(Button, { variant: "secondary", onClick: () => setRoute(routes.SOL_SEND), disabled: isLoading, children: "Cancel" })] })] }));
117
+ return (jsxs(PageContent, { onBack: routes.SOL_SEND, children: [jsx(ModalHeading, { children: "Confirm transfer" }), jsx(ModalBody, { children: "Review the transaction before sending." }), jsx(ConfirmationSummary, { amount: amount || '0', symbol: symbol, to: recipient ? { display: truncateSolanaAddress(recipient), value: recipient } : undefined, networkName: `Solana ${cluster.charAt(0).toUpperCase()}${cluster.slice(1)}`, payWith: address ? { display: truncateSolanaAddress(address), value: address } : undefined, fee: isSponsored ? jsx(SponsoredFee, { children: "Sponsored \u00B7 gasless" }) : jsx(FeesValue, { children: "Network fee" }) }), error && (jsxs(ErrorContainer, { children: [jsx(ErrorTitle, { children: "Transaction failed" }), jsx(ErrorMessage, { children: error })] })), jsxs(ButtonRow, { children: [jsx(Button, { variant: "primary", onClick: handleConfirm, disabled: !address || isLoading, waiting: isLoading, children: isLoading ? 'Confirming...' : 'Confirm' }), jsx(Button, { variant: "secondary", onClick: () => setRoute(routes.SOL_SEND), disabled: isLoading, children: "Cancel" })] })] }));
118
118
  };
119
119
 
120
120
  export { SolanaSendConfirmation };
@@ -13,23 +13,18 @@ import 'detect-browser';
13
13
  import { truncateEthAddress } from '../../../utils/format.js';
14
14
  import { parseTransactionError } from '../../../utils/errorHandling.js';
15
15
  import { logger } from '../../../utils/logger.js';
16
- import { getChainName, getDefaultEthereumRpcUrl } from '../../../utils/rpc.js';
16
+ import { getDefaultEthereumRpcUrl, getChainName } from '../../../utils/rpc.js';
17
17
  import Button from '../../Common/Button/index.js';
18
- import { CopyText } from '../../Common/CopyToClipboard/CopyText.js';
19
18
  import Loader from '../../Common/Loading/index.js';
20
19
  import { ModalHeading, ModalBody } from '../../Common/Modal/styles.js';
21
20
  import { routes } from '../../Openfort/types.js';
22
21
  import { useOpenfort } from '../../Openfort/useOpenfort.js';
23
22
  import { PageContent } from '../../PageContent/index.js';
24
23
  import { sanitizeForParsing, isSameToken, getAssetDecimals, getAssetSymbol } from '../Send/utils.js';
24
+ import { ConfirmationSummary } from './ConfirmationSummary.js';
25
25
  import { EstimatedFees } from './EstimatedFees.js';
26
- import { ButtonRow, SummaryList, SummaryItem, SummaryLabel, AmountValue, AddressValue, FeesValue, CheckIconWrapper, StatusMessage, ErrorContainer, ErrorTitle, ErrorMessage, ErrorAction } from './styles.js';
26
+ import { ButtonRow, SponsoredFee, FeesValue, StatusMessage, ErrorContainer, ErrorTitle, ErrorMessage, ErrorAction } from './styles.js';
27
27
 
28
- /** Check if chain is a testnet */
29
- function isTestnetChain(chainId) {
30
- const testnets = new Set([5, 11155111, 80001, 84532, 421614, 97, 4002]);
31
- return testnets.has(chainId);
32
- }
33
28
  const SendConfirmation = () => {
34
29
  var _a, _b, _c, _d, _e, _f;
35
30
  const wallet = useEthereumEmbeddedWallet();
@@ -37,19 +32,7 @@ const SendConfirmation = () => {
37
32
  const { sendForm, setRoute, triggerResize, walletConfig } = useOpenfort();
38
33
  const address = wallet.status === 'connected' ? wallet.address : undefined;
39
34
  const chainId = wallet.status === 'connected' ? wallet.chainId : undefined;
40
- // Build chain info for block explorer
41
- const chain = chainId
42
- ? {
43
- id: chainId,
44
- name: getChainName(chainId),
45
- blockExplorers: {
46
- default: {
47
- url: getExplorerUrl(ChainTypeEnum.EVM, { chainId }),
48
- },
49
- },
50
- testnet: isTestnetChain(chainId),
51
- }
52
- : undefined;
35
+ const blockExplorerUrl = chainId ? getExplorerUrl(ChainTypeEnum.EVM, { chainId }) : undefined;
53
36
  const recipientAddress = isAddress(sendForm.recipient) ? sendForm.recipient : undefined;
54
37
  const normalisedAmount = sanitizeForParsing(sendForm.amount);
55
38
  const { data: assets } = useEthereumWalletAssets();
@@ -308,7 +291,6 @@ const SendConfirmation = () => {
308
291
  };
309
292
  const status = isSuccess ? 'success' : firstError ? 'error' : 'idle';
310
293
  const errorDetails = status === 'error' ? parseTransactionError(firstError) : null;
311
- const blockExplorerUrl = (_e = (_d = chain === null || chain === void 0 ? void 0 : chain.blockExplorers) === null || _d === void 0 ? void 0 : _d.default) === null || _e === void 0 ? void 0 : _e.url;
312
294
  const handleOpenBlockExplorer = () => {
313
295
  if ((receipt === null || receipt === void 0 ? void 0 : receipt.transactionHash) && blockExplorerUrl) {
314
296
  window.open(`${blockExplorerUrl}/tx/${receipt.transactionHash}`, '_blank', 'noopener,noreferrer');
@@ -325,19 +307,21 @@ const SendConfirmation = () => {
325
307
  if (typeof feeSponsorship === 'string')
326
308
  return true;
327
309
  return feeSponsorship[chainId !== null && chainId !== void 0 ? chainId : 0] !== undefined;
328
- }, [(_f = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _f === void 0 ? void 0 : _f.ethereumFeeSponsorshipId, chainId]);
310
+ }, [(_d = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _d === void 0 ? void 0 : _d.ethereumFeeSponsorshipId, chainId]);
311
+ const fiatTotal = useMemo(() => {
312
+ var _a, _b;
313
+ const perToken = (_b = (_a = token.metadata) === null || _a === void 0 ? void 0 : _a.fiat) === null || _b === void 0 ? void 0 : _b.value;
314
+ const n = Number(normalisedAmount);
315
+ if (!perToken || !Number.isFinite(n) || n <= 0)
316
+ return null;
317
+ return `$${(n * perToken).toFixed(2)}`;
318
+ }, [(_f = (_e = token.metadata) === null || _e === void 0 ? void 0 : _e.fiat) === null || _f === void 0 ? void 0 : _f.value, normalisedAmount]);
329
319
  if (isSuccess) {
330
320
  const successAmount = normalisedAmount || '0';
331
321
  const successSymbol = getAssetSymbol(token);
332
322
  return (jsxs(PageContent, { children: [jsx(Loader, { isSuccess: true, header: "Transfer Sent", description: `${successAmount} ${successSymbol} sent successfully` }), jsxs(ButtonRow, { children: [blockExplorerUrl && (jsx(Button, { variant: "primary", onClick: handleOpenBlockExplorer, children: "View on Explorer" })), jsx(Button, { variant: "secondary", onClick: handleFinish, children: "Back to profile" })] })] }));
333
323
  }
334
- return (jsxs(PageContent, { children: [jsx(ModalHeading, { children: "Confirm transfer" }), jsx(ModalBody, { children: "Review the transaction details before sending." }), jsxs(SummaryList, { children: [jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "Sending" }), jsxs(AmountValue, { children: [normalisedAmount || '0', " ", getAssetSymbol(token)] })] }), jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "From" }), jsx(AddressValue, { children: address ? (jsx(CopyText, { size: "1rem", value: address, children: truncateEthAddress(address) })) : ('--') })] }), jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "To" }), jsx(AddressValue, { children: recipientAddress ? (jsx(CopyText, { size: "1rem", value: recipientAddress, children: truncateEthAddress(recipientAddress) })) : ('--') })] }), jsxs("div", { children: [jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "Estimated fees" }), jsxs(FeesValue, { "$completed": isSponsored, children: [jsx(EstimatedFees, { account: address, to: token.type === 'erc20' ? token.address : recipientAddress, value: token.type === 'native' && parsedAmount ? parsedAmount : undefined, data: transferData, chainId: chainId, nativeSymbol: nativeSymbol, enabled: Boolean(address && recipientAddress && parsedAmount && parsedAmount > BigInt(0)), hideInfoIcon: isSponsored }), jsx(CheckIconWrapper, { children: jsx(TickIcon, {}) })] })] }), isSponsored && (jsx("div", { style: {
335
- textAlign: 'end',
336
- marginTop: '4px',
337
- width: '100%',
338
- color: 'var(--ck-body-color-valid)',
339
- fontSize: '12px',
340
- }, children: "Sponsored transaction" }))] })] }), insufficientBalance && !isSuccess && (jsx(StatusMessage, { "$status": "error", children: "Insufficient balance for this transfer." })), errorDetails && (jsxs(ErrorContainer, { children: [jsx(ErrorTitle, { children: errorDetails.title }), jsx(ErrorMessage, { children: errorDetails.message }), errorDetails.action && jsx(ErrorAction, { children: errorDetails.action })] })), jsxs(ButtonRow, { children: [jsx(Button, { variant: "primary", onClick: isSuccess ? handleOpenBlockExplorer : handleConfirm, disabled: isSuccess
324
+ return (jsxs(PageContent, { children: [jsx(ModalHeading, { children: "Confirm transfer" }), jsx(ModalBody, { children: "Review the transaction before sending." }), jsx(ConfirmationSummary, { amount: normalisedAmount || '0', symbol: getAssetSymbol(token), fiat: fiatTotal, to: recipientAddress ? { display: truncateEthAddress(recipientAddress), value: recipientAddress } : undefined, networkName: getChainName(chainId !== null && chainId !== void 0 ? chainId : 0), payWith: address ? { display: truncateEthAddress(address), value: address } : undefined, fee: isSponsored ? (jsx(SponsoredFee, { children: "Sponsored \u00B7 gasless" })) : (jsx(FeesValue, { children: jsx(EstimatedFees, { account: address, to: token.type === 'erc20' ? token.address : recipientAddress, value: token.type === 'native' && parsedAmount ? parsedAmount : undefined, data: transferData, chainId: chainId, nativeSymbol: nativeSymbol, enabled: Boolean(address && recipientAddress && parsedAmount && parsedAmount > BigInt(0)), hideInfoIcon: false }) })) }), insufficientBalance && !isSuccess && (jsx(StatusMessage, { "$status": "error", children: "Insufficient balance for this transfer." })), errorDetails && (jsxs(ErrorContainer, { children: [jsx(ErrorTitle, { children: errorDetails.title }), jsx(ErrorMessage, { children: errorDetails.message }), errorDetails.action && jsx(ErrorAction, { children: errorDetails.action })] })), jsxs(ButtonRow, { children: [jsx(Button, { variant: "primary", onClick: isSuccess ? handleOpenBlockExplorer : handleConfirm, disabled: isSuccess
341
325
  ? false
342
326
  : isLoading ||
343
327
  Boolean(transactionHash) ||
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -6,7 +6,13 @@ export declare const AddressValue: import("styled-components").StyledComponent<"
6
6
  export declare const FeesValue: import("styled-components").StyledComponent<"span", any, {
7
7
  $completed?: boolean;
8
8
  }, never>;
9
- export declare const CheckIconWrapper: import("styled-components").StyledComponent<"span", any, {}, never>;
9
+ export declare const FiatValue: import("styled-components").StyledComponent<"span", any, {}, never>;
10
+ export declare const NetworkValue: import("styled-components").StyledComponent<"span", any, {}, never>;
11
+ export declare const SponsoredFee: import("styled-components").StyledComponent<"span", any, {}, never>;
12
+ export declare const PayWithCard: import("styled-components").StyledComponent<"div", any, {}, never>;
13
+ export declare const PayWithMeta: import("styled-components").StyledComponent<"div", any, {}, never>;
14
+ export declare const PayWithAddress: import("styled-components").StyledComponent<"span", any, {}, never>;
15
+ export declare const PayWithBadge: import("styled-components").StyledComponent<"span", any, {}, never>;
10
16
  export declare const InfoIconWrapper: import("styled-components").StyledComponent<"span", any, {}, never>;
11
17
  export declare const ButtonRow: import("styled-components").StyledComponent<"div", any, {}, never>;
12
18
  export declare const StatusMessage: import("styled-components").StyledComponent<"div", any, {
@@ -45,26 +45,58 @@ const FeesValue = styled(SummaryValue) `
45
45
  text-decoration: ${(props) => (props.$completed ? 'line-through' : 'none')};
46
46
  opacity: ${(props) => (props.$completed ? 0.6 : 1)};
47
47
  `;
48
- const CheckIconWrapper = styled.span `
49
- color: var(--ck-body-color);
50
- line-height: 0;
48
+ const FiatValue = styled.span `
49
+ margin-left: 6px;
50
+ font-size: 13px;
51
+ font-weight: 400;
52
+ color: var(--ck-body-color-muted);
53
+ `;
54
+ const NetworkValue = styled(SummaryValue) `
51
55
  display: inline-flex;
52
56
  align-items: center;
53
-
54
- svg {
55
- width: 16px;
56
- height: 16px;
57
+ justify-content: flex-end;
58
+ gap: 6px;
59
+
60
+ svg,
61
+ img {
62
+ width: 18px;
63
+ height: 18px;
64
+ border-radius: 50%;
57
65
  }
58
66
  `;
59
- // export const BalanceSpinnerWrapper = styled.span`
60
- // display: inline-flex;
61
- // align-items: center;
62
- // margin-left: 8px;
63
- // svg {
64
- // width: 14px;
65
- // height: 14px;
66
- // }
67
- // `
67
+ const SponsoredFee = styled(SummaryValue) `
68
+ color: var(--ck-body-color-valid, #16a34a);
69
+ `;
70
+ const PayWithCard = styled.div `
71
+ display: flex;
72
+ align-items: center;
73
+ justify-content: space-between;
74
+ gap: 12px;
75
+ margin-top: 4px;
76
+ padding: 12px 14px;
77
+ border-radius: 14px;
78
+ background: var(--ck-body-background-secondary, rgba(0, 0, 0, 0.04));
79
+ `;
80
+ const PayWithMeta = styled.div `
81
+ display: flex;
82
+ flex-direction: column;
83
+ gap: 2px;
84
+ text-align: left;
85
+ `;
86
+ const PayWithAddress = styled.span `
87
+ font-size: 14px;
88
+ font-weight: 600;
89
+ color: var(--ck-body-color);
90
+ `;
91
+ const PayWithBadge = styled.span `
92
+ flex-shrink: 0;
93
+ padding: 4px 10px;
94
+ border-radius: 999px;
95
+ font-size: 13px;
96
+ font-weight: 600;
97
+ color: var(--ck-body-color-valid, #16a34a);
98
+ background: var(--ck-body-background, rgba(22, 163, 74, 0.12));
99
+ `;
68
100
  const InfoIconWrapper = styled.span `
69
101
  color: var(--ck-body-color-muted);
70
102
  opacity: 0.6;
@@ -125,5 +157,5 @@ const ErrorAction = styled.div `
125
157
  line-height: 1.4;
126
158
  `;
127
159
 
128
- export { AddressValue, AmountValue, ButtonRow, CheckIconWrapper, ErrorAction, ErrorContainer, ErrorMessage, ErrorTitle, FeesValue, InfoIconWrapper, StatusMessage, SummaryItem, SummaryLabel, SummaryList };
160
+ export { AddressValue, AmountValue, ButtonRow, ErrorAction, ErrorContainer, ErrorMessage, ErrorTitle, FeesValue, FiatValue, InfoIconWrapper, NetworkValue, PayWithAddress, PayWithBadge, PayWithCard, PayWithMeta, SponsoredFee, StatusMessage, SummaryItem, SummaryLabel, SummaryList };
129
161
  //# sourceMappingURL=styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"styles.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,2 @@
1
+ declare const SignMessage: () => import("react/jsx-runtime").JSX.Element | null;
2
+ export default SignMessage;
@@ -0,0 +1,81 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useState, useRef, useEffect } from 'react';
3
+ import { useEthereumEmbeddedWallet } from '../../../ethereum/hooks/useEthereumEmbeddedWallet.js';
4
+ import Button from '../../Common/Button/index.js';
5
+ import { CopyButton } from '../../Common/CopyToClipboard/CopyButton.js';
6
+ import { useOpenfort } from '../../Openfort/useOpenfort.js';
7
+ import { PageContent } from '../../PageContent/index.js';
8
+ import { SuccessWrap, SuccessCircle, SuccessTitle, SignaturePreview, SignContent, Subtitle, MessageBox, CopyRow, ErrorText, DataList, DataItem, DataKey } from './styles.js';
9
+
10
+ /** Renders an EIP-712 value as a readable nested bullet list. */
11
+ function DataNode({ value }) {
12
+ if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
13
+ return (jsx(DataList, { children: Object.entries(value).map(([key, child]) => (jsxs(DataItem, { children: [jsxs(DataKey, { children: [key, ":"] }), ' ', child !== null && typeof child === 'object' ? jsx(DataNode, { value: child }) : String(child)] }, key))) }));
14
+ }
15
+ return jsx(Fragment, { children: String(value) });
16
+ }
17
+ const SignMessage = () => {
18
+ var _a;
19
+ const { signRequest, setSignRequest, setOpen, uiConfig, triggerResize } = useOpenfort();
20
+ const wallet = useEthereumEmbeddedWallet();
21
+ const [signing, setSigning] = useState(false);
22
+ const [error, setError] = useState(null);
23
+ const [signature, setSignature] = useState(null);
24
+ const settledRef = useRef(false);
25
+ // Reject the pending request if the screen unmounts before signing (the user
26
+ // closed the modal or navigated away).
27
+ useEffect(() => {
28
+ return () => {
29
+ if (!settledRef.current)
30
+ signRequest === null || signRequest === void 0 ? void 0 : signRequest.reject(new Error('User rejected the signature request'));
31
+ };
32
+ }, [signRequest]);
33
+ // Content height changes between the views; re-measure.
34
+ useEffect(() => {
35
+ triggerResize();
36
+ }, [triggerResize]);
37
+ if (!signRequest)
38
+ return null;
39
+ const appName = (_a = uiConfig.appName) !== null && _a !== void 0 ? _a : 'This app';
40
+ const close = () => {
41
+ setSignRequest(null);
42
+ setOpen(false);
43
+ };
44
+ const handleSign = async () => {
45
+ var _a;
46
+ setError(null);
47
+ setSigning(true);
48
+ try {
49
+ const provider = await ((_a = wallet.activeWallet) === null || _a === void 0 ? void 0 : _a.getProvider());
50
+ const address = wallet.address;
51
+ if (!provider || !address)
52
+ throw new Error('No connected wallet to sign with');
53
+ const signed = (signRequest.kind === 'message'
54
+ ? await provider.request({ method: 'personal_sign', params: [signRequest.message, address] })
55
+ : await provider.request({
56
+ method: 'eth_signTypedData_v4',
57
+ params: [address, JSON.stringify(signRequest.typedData)],
58
+ }));
59
+ settledRef.current = true;
60
+ signRequest.resolve(signed);
61
+ setSignature(signed);
62
+ setSigning(false);
63
+ triggerResize();
64
+ }
65
+ catch (e) {
66
+ setError(e instanceof Error ? e.message : 'Failed to sign the message');
67
+ setSigning(false);
68
+ }
69
+ };
70
+ if (signature) {
71
+ return (jsx(PageContent, { onBack: null, children: jsxs(SuccessWrap, { children: [jsx(SuccessCircle, { children: jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: jsx("path", { d: "M20 6 9 17l-5-5", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), jsx(SuccessTitle, { children: "Message signed" }), jsx(SignaturePreview, { children: `${signature.slice(0, 14)}…${signature.slice(-12)}` }), jsx(Button, { variant: "primary", onClick: close, children: "Done" })] }) }));
72
+ }
73
+ return (jsx(PageContent, { onBack: null, children: jsxs(SignContent, { children: [jsxs(Subtitle, { children: [appName, " wants you to sign a message. It will not cost you any fees."] }), signRequest.kind === 'message' ? (jsx(MessageBox, { children: signRequest.message })) : (jsxs(Fragment, { children: [jsx(MessageBox, { "$scroll": true, children: jsx(DataNode, { value: {
74
+ domain: signRequest.typedData.domain,
75
+ primaryType: signRequest.typedData.primaryType,
76
+ message: signRequest.typedData.message,
77
+ } }) }), jsx(CopyRow, { children: jsx(CopyButton, { value: JSON.stringify(signRequest.typedData, null, 2), children: "Copy to clipboard" }) })] })), error && jsx(ErrorText, { children: error }), jsx(Button, { variant: "primary", onClick: handleSign, waiting: signing, disabled: signing, arrow: true, children: "Sign and continue" })] }) }));
78
+ };
79
+
80
+ export { SignMessage as default };
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,14 @@
1
+ export declare const SignContent: import("styled-components").StyledComponent<"div", any, {}, never>;
2
+ export declare const Subtitle: import("styled-components").StyledComponent<"p", any, {}, never>;
3
+ export declare const MessageBox: import("styled-components").StyledComponent<"div", any, {
4
+ $scroll?: boolean;
5
+ }, never>;
6
+ export declare const DataList: import("styled-components").StyledComponent<"ul", any, {}, never>;
7
+ export declare const DataItem: import("styled-components").StyledComponent<"li", any, {}, never>;
8
+ export declare const DataKey: import("styled-components").StyledComponent<"span", any, {}, never>;
9
+ export declare const ErrorText: import("styled-components").StyledComponent<"div", any, {}, never>;
10
+ export declare const CopyRow: import("styled-components").StyledComponent<"div", any, {}, never>;
11
+ export declare const SuccessWrap: import("styled-components").StyledComponent<"div", any, {}, never>;
12
+ export declare const SuccessCircle: import("styled-components").StyledComponent<"div", any, {}, never>;
13
+ export declare const SuccessTitle: import("styled-components").StyledComponent<"div", any, {}, never>;
14
+ export declare const SignaturePreview: import("styled-components").StyledComponent<"code", any, {}, never>;
@@ -0,0 +1,82 @@
1
+ import styled from '../../../styles/styled/index.js';
2
+
3
+ const SignContent = styled.div `
4
+ display: flex;
5
+ flex-direction: column;
6
+ gap: 16px;
7
+ `;
8
+ const Subtitle = styled.p `
9
+ margin: 0;
10
+ text-align: center;
11
+ font-size: 15px;
12
+ line-height: 1.4;
13
+ color: var(--ck-body-color-muted, #999);
14
+ `;
15
+ const MessageBox = styled.div `
16
+ padding: 16px;
17
+ border-radius: 12px;
18
+ background: var(--ck-body-background-secondary, rgba(0, 0, 0, 0.04));
19
+ color: var(--ck-body-color, #111);
20
+ font-size: 14px;
21
+ line-height: 1.45;
22
+ text-align: left;
23
+ word-break: break-word;
24
+ white-space: pre-wrap;
25
+ ${({ $scroll }) => $scroll && 'max-height: 320px; overflow-y: auto;'}
26
+ `;
27
+ const DataList = styled.ul `
28
+ margin: 0;
29
+ padding-left: 18px;
30
+ list-style: disc;
31
+ `;
32
+ const DataItem = styled.li `
33
+ margin: 2px 0;
34
+ `;
35
+ const DataKey = styled.span `
36
+ color: var(--ck-body-color-muted, #777);
37
+ `;
38
+ const ErrorText = styled.div `
39
+ text-align: center;
40
+ font-size: 13px;
41
+ color: var(--ck-body-color-danger, #e7000b);
42
+ `;
43
+ const CopyRow = styled.div `
44
+ display: flex;
45
+ justify-content: center;
46
+ `;
47
+ const SuccessWrap = styled.div `
48
+ display: flex;
49
+ flex-direction: column;
50
+ align-items: center;
51
+ gap: 12px;
52
+ padding: 12px 0 4px;
53
+ `;
54
+ const SuccessCircle = styled.div `
55
+ display: flex;
56
+ align-items: center;
57
+ justify-content: center;
58
+ width: 56px;
59
+ height: 56px;
60
+ border-radius: 50%;
61
+ color: #fff;
62
+ background: var(--ck-body-color-valid, #16a34a);
63
+ `;
64
+ const SuccessTitle = styled.div `
65
+ font-size: 17px;
66
+ font-weight: 600;
67
+ color: var(--ck-body-color, #111);
68
+ `;
69
+ const SignaturePreview = styled.code `
70
+ display: block;
71
+ max-width: 100%;
72
+ padding: 10px 12px;
73
+ border-radius: 10px;
74
+ background: var(--ck-body-background-secondary, rgba(0, 0, 0, 0.04));
75
+ color: var(--ck-body-color-muted, #777);
76
+ font-size: 12px;
77
+ word-break: break-all;
78
+ text-align: center;
79
+ `;
80
+
81
+ export { CopyRow, DataItem, DataKey, DataList, ErrorText, MessageBox, SignContent, SignaturePreview, Subtitle, SuccessCircle, SuccessTitle, SuccessWrap };
82
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}