@daimo/pay 1.19.8 → 1.19.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/package.json.js +2 -2
- package/build/src/components/Common/AmountInput/AmountInputField.js +6 -15
- package/build/src/components/Common/AmountInput/AmountInputField.js.map +1 -1
- package/build/src/components/Common/AmountInput/index.js +31 -24
- package/build/src/components/Common/AmountInput/index.js.map +1 -1
- package/build/src/components/Common/Modal/index.js +12 -1
- package/build/src/components/Common/Modal/index.js.map +1 -1
- package/build/src/components/Pages/WaitingExternal/index.js +1 -1
- package/build/src/components/Pages/WaitingExternal/index.js.map +1 -1
- package/build/src/hooks/useTokenOptions.js +8 -4
- package/build/src/hooks/useTokenOptions.js.map +1 -1
- package/build/src/utils/format.js +3 -0
- package/build/src/utils/format.js.map +1 -1
- package/package.json +2 -2
package/build/package.json.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "@daimo/pay";
|
|
2
|
-
var version = "1.19.
|
|
2
|
+
var version = "1.19.9";
|
|
3
3
|
var author = "Daimo";
|
|
4
4
|
var homepage = "https://pay.daimo.com";
|
|
5
5
|
var license = "BSD-2-Clause license";
|
|
@@ -31,7 +31,7 @@ var scripts = {
|
|
|
31
31
|
lint: "eslint 'src/**/*.{js,jsx,ts,tsx}' --max-warnings=0"
|
|
32
32
|
};
|
|
33
33
|
var dependencies = {
|
|
34
|
-
"@daimo/pay-common": "1.19.
|
|
34
|
+
"@daimo/pay-common": "1.19.9",
|
|
35
35
|
"@solana/wallet-adapter-base": "^0.9.23",
|
|
36
36
|
"@solana/wallet-adapter-react": "^0.15.35",
|
|
37
37
|
"@solana/web3.js": "^1.95.4",
|
|
@@ -29,19 +29,7 @@ const InputField = styled.input`
|
|
|
29
29
|
min-width: 1ch;
|
|
30
30
|
max-width: 10ch;
|
|
31
31
|
`;
|
|
32
|
-
const
|
|
33
|
-
@keyframes fadeInDown {
|
|
34
|
-
from {
|
|
35
|
-
opacity: 0;
|
|
36
|
-
transform: translateY(-8px);
|
|
37
|
-
}
|
|
38
|
-
to {
|
|
39
|
-
opacity: 1;
|
|
40
|
-
transform: translateY(0);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
animation: fadeInDown 0.3s ease-out forwards;
|
|
32
|
+
const Currency = styled(ModalBody)`
|
|
45
33
|
font-size: ${(props) => props.$small ? "16px" : "24px"};
|
|
46
34
|
`;
|
|
47
35
|
const AmountInputField = ({ value, onChange, currency = "$", onKeyDown }) => {
|
|
@@ -49,8 +37,11 @@ const AmountInputField = ({ value, onChange, currency = "$", onKeyDown }) => {
|
|
|
49
37
|
useEffect(() => {
|
|
50
38
|
inputRef.current?.focus();
|
|
51
39
|
}, [value]);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
inputRef.current?.select();
|
|
42
|
+
}, [currency]);
|
|
52
43
|
return /* @__PURE__ */ jsxs(Container, { children: [
|
|
53
|
-
currency === "$" && /* @__PURE__ */ jsx(
|
|
44
|
+
currency === "$" && /* @__PURE__ */ jsx(Currency, { children: currency }),
|
|
54
45
|
/* @__PURE__ */ jsx(
|
|
55
46
|
InputField,
|
|
56
47
|
{
|
|
@@ -63,7 +54,7 @@ const AmountInputField = ({ value, onChange, currency = "$", onKeyDown }) => {
|
|
|
63
54
|
onKeyDown
|
|
64
55
|
}
|
|
65
56
|
),
|
|
66
|
-
currency !== "$" && /* @__PURE__ */ jsx(
|
|
57
|
+
currency !== "$" && /* @__PURE__ */ jsx(Currency, { $small: true, children: currency })
|
|
67
58
|
] });
|
|
68
59
|
};
|
|
69
60
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmountInputField.js","sources":["../../../../../src/components/Common/AmountInput/AmountInputField.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport styled from \"../../../styles/styled\";\nimport { ModalBody } from \"../Modal/styles\";\n\nconst Container = styled.button`\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n background: transparent;\n`;\n\nconst InputField = styled.input`\n margin: 0;\n padding: 0;\n background: none;\n border: none;\n outline: none;\n font-size: 30px;\n font-weight: var(--ck-modal-h1-font-weight, 600);\n color: var(--ck-body-color);\n width: ${(props) => {\n const length = props.value?.length ?? 0;\n // Placeholder is \"0.00\", 3ch for digits + 0.55ch for decimal point\n if (length === 0) return \"3.55ch\";\n // Reduce width when decimal or commas are present since they're smaller than normal chars\n const numPunctuations = (props.value?.match(/[.,]/g) || []).length;\n const adjustedLength = length - numPunctuations * 0.55;\n return `${Math.min(adjustedLength, 10)}ch`;\n }};\n min-width: 1ch;\n max-width: 10ch;\n`;\n\nconst
|
|
1
|
+
{"version":3,"file":"AmountInputField.js","sources":["../../../../../src/components/Common/AmountInput/AmountInputField.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport styled from \"../../../styles/styled\";\nimport { ModalBody } from \"../Modal/styles\";\n\nconst Container = styled.button`\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n background: transparent;\n`;\n\nconst InputField = styled.input`\n margin: 0;\n padding: 0;\n background: none;\n border: none;\n outline: none;\n font-size: 30px;\n font-weight: var(--ck-modal-h1-font-weight, 600);\n color: var(--ck-body-color);\n width: ${(props) => {\n const length = props.value?.length ?? 0;\n // Placeholder is \"0.00\", 3ch for digits + 0.55ch for decimal point\n if (length === 0) return \"3.55ch\";\n // Reduce width when decimal or commas are present since they're smaller than normal chars\n const numPunctuations = (props.value?.match(/[.,]/g) || []).length;\n const adjustedLength = length - numPunctuations * 0.55;\n return `${Math.min(adjustedLength, 10)}ch`;\n }};\n min-width: 1ch;\n max-width: 10ch;\n`;\n\nconst Currency = styled(ModalBody)<{ $small?: boolean }>`\n font-size: ${(props) => (props.$small ? \"16px\" : \"24px\")};\n`;\n\nconst AmountInputField: React.FC<{\n value: string;\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n currency?: string;\n onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n}> = ({ value, onChange, currency = \"$\", onKeyDown }) => {\n // Focus the input when the component mounts so the user can start typing immediately\n const inputRef = useRef<HTMLInputElement>(null);\n useEffect(() => {\n inputRef.current?.focus();\n }, [value]);\n\n // Select all text when switching between USD and token mode\n useEffect(() => {\n inputRef.current?.select();\n }, [currency]);\n\n return (\n <Container>\n {currency === \"$\" && <Currency>{currency}</Currency>}\n <InputField\n ref={inputRef}\n type=\"text\"\n inputMode=\"decimal\"\n value={value}\n onChange={onChange}\n placeholder=\"0.00\"\n onKeyDown={onKeyDown}\n />\n {currency !== \"$\" && <Currency $small>{currency}</Currency>}\n </Container>\n );\n};\n\nexport default AmountInputField;\n"],"names":[],"mappings":";;;;;AAIA,MAAM,YAAY,MAAO,CAAA,MAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAQzB,MAAM,aAAa,MAAO,CAAA,KAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EASf,CAAC,KAAU,KAAA;AAClB,EAAM,MAAA,MAAA,GAAS,KAAM,CAAA,KAAA,EAAO,MAAU,IAAA,CAAA,CAAA;AAEtC,EAAI,IAAA,MAAA,KAAW,GAAU,OAAA,QAAA,CAAA;AAEzB,EAAA,MAAM,mBAAmB,KAAM,CAAA,KAAA,EAAO,MAAM,OAAO,CAAA,IAAK,EAAI,EAAA,MAAA,CAAA;AAC5D,EAAM,MAAA,cAAA,GAAiB,SAAS,eAAkB,GAAA,IAAA,CAAA;AAClD,EAAA,OAAO,CAAG,EAAA,IAAA,CAAK,GAAI,CAAA,cAAA,EAAgB,EAAE,CAAC,CAAA,EAAA,CAAA,CAAA;AACxC,CAAC,CAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAKH,MAAM,QAAA,GAAW,OAAO,SAAS,CAAA,CAAA;AAAA,aAAA,EAClB,CAAC,KAAA,KAAW,KAAM,CAAA,MAAA,GAAS,SAAS,MAAO,CAAA;AAAA,CAAA,CAAA;AAGpD,MAAA,gBAAA,GAKD,CAAC,EAAE,KAAA,EAAO,UAAU,QAAW,GAAA,GAAA,EAAK,WAAgB,KAAA;AAEvD,EAAM,MAAA,QAAA,GAAW,OAAyB,IAAI,CAAA,CAAA;AAC9C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,QAAA,CAAS,SAAS,KAAM,EAAA,CAAA;AAAA,GAC1B,EAAG,CAAC,KAAK,CAAC,CAAA,CAAA;AAGV,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,QAAA,CAAS,SAAS,MAAO,EAAA,CAAA;AAAA,GAC3B,EAAG,CAAC,QAAQ,CAAC,CAAA,CAAA;AAEb,EAAA,4BACG,SACE,EAAA,EAAA,QAAA,EAAA;AAAA,IAAa,QAAA,KAAA,GAAA,oBAAQ,GAAA,CAAA,QAAA,EAAA,EAAU,QAAS,EAAA,QAAA,EAAA,CAAA;AAAA,oBACzC,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,GAAK,EAAA,QAAA;AAAA,QACL,IAAK,EAAA,MAAA;AAAA,QACL,SAAU,EAAA,SAAA;AAAA,QACV,KAAA;AAAA,QACA,QAAA;AAAA,QACA,WAAY,EAAA,MAAA;AAAA,QACZ,SAAA;AAAA,OAAA;AAAA,KACF;AAAA,IACC,aAAa,GAAO,oBAAA,GAAA,CAAC,QAAS,EAAA,EAAA,MAAA,EAAM,MAAE,QAAS,EAAA,QAAA,EAAA,CAAA;AAAA,GAClD,EAAA,CAAA,CAAA;AAEJ;;;;"}
|
|
@@ -4,7 +4,7 @@ import { usePayContext } from '../../../hooks/usePayContext.js';
|
|
|
4
4
|
import { PageContent, ModalContent, ModalBody } from '../Modal/styles.js';
|
|
5
5
|
import { parseUnits } from 'viem';
|
|
6
6
|
import styled from '../../../styles/styled/index.js';
|
|
7
|
-
import { formatUsd,
|
|
7
|
+
import { formatUsd, roundTokenAmount, roundUsd, USD_DECIMALS, tokenAmountToRoundedUsd, usdToRoundedTokenAmount, roundTokenAmountUnits } from '../../../utils/format.js';
|
|
8
8
|
import { isValidNumber, sanitizeNumber } from '../../../utils/validateInput.js';
|
|
9
9
|
import Button from '../Button/index.js';
|
|
10
10
|
import SwitchButton from '../SwitchButton/index.js';
|
|
@@ -15,14 +15,14 @@ const MultiCurrencySelectAmount = ({ selectedTokenOption, setSelectedTokenOption
|
|
|
15
15
|
const { paymentState, setRoute, triggerResize } = usePayContext();
|
|
16
16
|
const maxUsdLimit = paymentState.getOrderUsdLimit();
|
|
17
17
|
const balanceToken = selectedTokenOption.balance.token;
|
|
18
|
-
const
|
|
19
|
-
${formatUsd(selectedTokenOption.
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
);
|
|
18
|
+
const isUsdStablecoin = balanceToken.fiatISO === "USD";
|
|
19
|
+
const usdBalanceMessage = isUsdStablecoin ? `Balance: ${formatUsd(selectedTokenOption.balance.usd)}` : `Balance: ${formatUsd(selectedTokenOption.balance.usd)} ${balanceToken.symbol}`;
|
|
20
|
+
const tokenBalanceMessage = `Balance: ${roundTokenAmount(selectedTokenOption.balance.amount, balanceToken)} ${balanceToken.symbol}`;
|
|
21
|
+
const getBalanceMessage = (editingUsd) => editingUsd ? usdBalanceMessage : tokenBalanceMessage;
|
|
22
|
+
const [usdStr, setUsdValue] = useState("");
|
|
23
|
+
const [tokenStr, setTokenValue] = useState("");
|
|
24
24
|
const [isEditingUsd, setIsEditingUsd] = useState(true);
|
|
25
|
-
const [message, setMessage] = useState(
|
|
25
|
+
const [message, setMessage] = useState(usdBalanceMessage);
|
|
26
26
|
const [continueDisabled, setContinueDisabled] = useState(true);
|
|
27
27
|
useEffect(() => {
|
|
28
28
|
triggerResize();
|
|
@@ -30,25 +30,32 @@ const MultiCurrencySelectAmount = ({ selectedTokenOption, setSelectedTokenOption
|
|
|
30
30
|
const updateValues = (newUsdValue, newTokenValue, newIsEditingUsd) => {
|
|
31
31
|
const sanitizedUsdValue = sanitizeNumber(newUsdValue);
|
|
32
32
|
const sanitizedTokenValue = sanitizeNumber(newTokenValue);
|
|
33
|
+
const usdNum = Number(sanitizedUsdValue);
|
|
34
|
+
const tokenNum = Number(sanitizedTokenValue);
|
|
35
|
+
const stripTrailingZeros = (val) => val.includes(".") ? val.replace(/\.?0+$/, "") : val;
|
|
33
36
|
setUsdValue(
|
|
34
|
-
newIsEditingUsd ? newUsdValue : roundUsd(
|
|
37
|
+
newIsEditingUsd ? newUsdValue : usdNum > 0 ? roundUsd(usdNum) : ""
|
|
35
38
|
);
|
|
36
39
|
setTokenValue(
|
|
37
|
-
newIsEditingUsd ? roundTokenAmountUnits(
|
|
40
|
+
newIsEditingUsd ? tokenNum > 0 ? stripTrailingZeros(roundTokenAmountUnits(tokenNum, balanceToken)) : "" : newTokenValue
|
|
38
41
|
);
|
|
39
42
|
setIsEditingUsd(newIsEditingUsd);
|
|
40
43
|
setContinueDisabled(
|
|
41
|
-
|
|
44
|
+
usdNum <= 0 || usdNum < selectedTokenOption.minimumRequired.usd || usdNum > selectedTokenOption.balance.usd || usdNum > maxUsdLimit
|
|
42
45
|
);
|
|
43
|
-
|
|
46
|
+
const formatAmount = (usd) => newIsEditingUsd ? formatUsd(usd) : `${usdToRoundedTokenAmount(usd, balanceToken)} ${balanceToken.symbol}`;
|
|
47
|
+
if (usdNum > selectedTokenOption.balance.usd) {
|
|
48
|
+
setMessage(
|
|
49
|
+
`Amount exceeds your balance: ${formatAmount(selectedTokenOption.balance.usd)}`
|
|
50
|
+
);
|
|
51
|
+
} else if (usdNum > maxUsdLimit) {
|
|
52
|
+
setMessage(`Maximum ${formatAmount(maxUsdLimit)}`);
|
|
53
|
+
} else if (usdNum > 0 && usdNum < selectedTokenOption.minimumRequired.usd) {
|
|
44
54
|
setMessage(
|
|
45
|
-
`
|
|
46
|
-
${formatUsd(selectedTokenOption.balance.usd)}`
|
|
55
|
+
`Minimum ${formatAmount(selectedTokenOption.minimumRequired.usd)}`
|
|
47
56
|
);
|
|
48
|
-
} else if (Number(usdValue) > maxUsdLimit) {
|
|
49
|
-
setMessage(`Maximum ${formatUsd(maxUsdLimit)}`);
|
|
50
57
|
} else {
|
|
51
|
-
setMessage(
|
|
58
|
+
setMessage(getBalanceMessage(newIsEditingUsd));
|
|
52
59
|
}
|
|
53
60
|
};
|
|
54
61
|
const handleAmountChange = (e) => {
|
|
@@ -64,12 +71,12 @@ const MultiCurrencySelectAmount = ({ selectedTokenOption, setSelectedTokenOption
|
|
|
64
71
|
updateValues(newUsdValue, newTokenValue, isEditingUsd);
|
|
65
72
|
};
|
|
66
73
|
const handleMax = () => {
|
|
67
|
-
const
|
|
68
|
-
const
|
|
74
|
+
const usdStr2 = roundUsd(Number(selectedTokenOption.balance.usd));
|
|
75
|
+
const tokenStr2 = roundTokenAmount(
|
|
69
76
|
selectedTokenOption.balance.amount,
|
|
70
77
|
balanceToken
|
|
71
78
|
);
|
|
72
|
-
updateValues(
|
|
79
|
+
updateValues(usdStr2, tokenStr2, isEditingUsd);
|
|
73
80
|
};
|
|
74
81
|
const handleKeyDown = (e) => {
|
|
75
82
|
if (e.key === "Enter" && !continueDisabled) {
|
|
@@ -77,10 +84,10 @@ const MultiCurrencySelectAmount = ({ selectedTokenOption, setSelectedTokenOption
|
|
|
77
84
|
}
|
|
78
85
|
};
|
|
79
86
|
const handleSwitchCurrency = () => {
|
|
80
|
-
updateValues(
|
|
87
|
+
updateValues(usdStr, tokenStr, !isEditingUsd);
|
|
81
88
|
};
|
|
82
89
|
const handleContinue = () => {
|
|
83
|
-
const usd = Number(sanitizeNumber(
|
|
90
|
+
const usd = Number(sanitizeNumber(usdStr));
|
|
84
91
|
const amountUnits = usd / balanceToken.usd;
|
|
85
92
|
const amount = parseUnits(amountUnits.toString(), balanceToken.decimals);
|
|
86
93
|
setSelectedTokenOption({
|
|
@@ -106,7 +113,7 @@ const MultiCurrencySelectAmount = ({ selectedTokenOption, setSelectedTokenOption
|
|
|
106
113
|
/* @__PURE__ */ jsx(
|
|
107
114
|
AmountInputField,
|
|
108
115
|
{
|
|
109
|
-
value: isEditingUsd ?
|
|
116
|
+
value: isEditingUsd ? usdStr : tokenStr,
|
|
110
117
|
onChange: handleAmountChange,
|
|
111
118
|
currency: isEditingUsd ? "$" : balanceToken.symbol,
|
|
112
119
|
onKeyDown: handleKeyDown
|
|
@@ -114,7 +121,7 @@ const MultiCurrencySelectAmount = ({ selectedTokenOption, setSelectedTokenOption
|
|
|
114
121
|
),
|
|
115
122
|
/* @__PURE__ */ jsx(MaxButton, { onClick: handleMax, children: "Max" })
|
|
116
123
|
] }),
|
|
117
|
-
balanceToken.fiatISO !== "USD" && /* @__PURE__ */ jsx(SwitchContainer, { children: /* @__PURE__ */ jsx(SwitchButton, { onClick: handleSwitchCurrency, children: /* @__PURE__ */ jsx(SecondaryAmount, { children: isEditingUsd ? `${
|
|
124
|
+
balanceToken.fiatISO !== "USD" && /* @__PURE__ */ jsx(SwitchContainer, { children: /* @__PURE__ */ jsx(SwitchButton, { onClick: handleSwitchCurrency, children: /* @__PURE__ */ jsx(SecondaryAmount, { children: isEditingUsd ? `${tokenStr || "0"} ${balanceToken.symbol}` : `$${usdStr || roundUsd(0)}` }) }) }),
|
|
118
125
|
message && /* @__PURE__ */ jsx(ModalBody, { children: message }),
|
|
119
126
|
/* @__PURE__ */ jsx(Button, { onClick: handleContinue, disabled: continueDisabled, children: "Continue" })
|
|
120
127
|
] })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../src/components/Common/AmountInput/index.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { ROUTES } from \"../../../constants/routes\";\nimport { usePayContext } from \"../../../hooks/usePayContext\";\n\nimport {\n ModalBody,\n ModalContent,\n PageContent,\n} from \"../../Common/Modal/styles\";\n\nimport { WalletPaymentOption } from \"@daimo/pay-common\";\nimport { parseUnits } from \"viem\";\nimport styled from \"../../../styles/styled\";\nimport {\n formatUsd,\n roundTokenAmount,\n roundTokenAmountUnits,\n roundUsd,\n tokenAmountToRoundedUsd,\n USD_DECIMALS,\n usdToRoundedTokenAmount,\n} from \"../../../utils/format\";\nimport { isValidNumber, sanitizeNumber } from \"../../../utils/validateInput\";\nimport Button from \"../../Common/Button\";\nimport SwitchButton from \"../../Common/SwitchButton\";\nimport TokenLogoSpinner from \"../../Spinners/TokenLogoSpinner\";\nimport AmountInputField from \"./AmountInputField\";\n\nconst MultiCurrencySelectAmount: React.FC<{\n selectedTokenOption: WalletPaymentOption;\n setSelectedTokenOption: (option: WalletPaymentOption) => void;\n nextPage: ROUTES;\n}> = ({ selectedTokenOption, setSelectedTokenOption, nextPage }) => {\n const { paymentState, setRoute, triggerResize } = usePayContext();\n const maxUsdLimit = paymentState.getOrderUsdLimit();\n\n const balanceToken = selectedTokenOption.balance.token;\n\n const minimumMessage =\n selectedTokenOption.minimumRequired.usd > 0\n ? `Minimum \n ${formatUsd(selectedTokenOption.minimumRequired.usd, \"up\")}`\n : null;\n\n const [usdValue, setUsdValue] = useState(\"\");\n const [tokenValue, setTokenValue] = useState(\n usdToRoundedTokenAmount(0, balanceToken),\n );\n const [isEditingUsd, setIsEditingUsd] = useState(true);\n const [message, setMessage] = useState<string | null>(minimumMessage);\n const [continueDisabled, setContinueDisabled] = useState(true);\n\n useEffect(() => {\n triggerResize();\n }, [message]); // eslint-disable-line react-hooks/exhaustive-deps\n\n /**\n * Update the editable value and secondary value, taking into account whether\n * the user is currently editing the USD value or the token value.\n */\n const updateValues = (\n newUsdValue: string,\n newTokenValue: string,\n newIsEditingUsd: boolean,\n ) => {\n const sanitizedUsdValue = sanitizeNumber(newUsdValue);\n const sanitizedTokenValue = sanitizeNumber(newTokenValue);\n\n // Update the state. Don't sanitize the value if the user is editing it.\n setUsdValue(\n newIsEditingUsd ? newUsdValue : roundUsd(Number(sanitizedUsdValue)),\n );\n setTokenValue(\n newIsEditingUsd\n ? roundTokenAmountUnits(Number(sanitizedTokenValue), balanceToken)\n : newTokenValue,\n );\n setIsEditingUsd(newIsEditingUsd);\n\n setContinueDisabled(\n Number(sanitizedUsdValue) <= 0 ||\n Number(sanitizedUsdValue) < selectedTokenOption.minimumRequired.usd ||\n Number(sanitizedUsdValue) > selectedTokenOption.balance.usd ||\n Number(sanitizedUsdValue) > maxUsdLimit,\n );\n\n if (Number(sanitizedUsdValue) > selectedTokenOption.balance.usd) {\n setMessage(\n `Amount exceeds your balance: \n ${formatUsd(selectedTokenOption.balance.usd)}`,\n );\n } else if (Number(usdValue) > maxUsdLimit) {\n setMessage(`Maximum ${formatUsd(maxUsdLimit)}`);\n } else {\n setMessage(minimumMessage);\n }\n };\n\n const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n const maxDecimals = isEditingUsd\n ? USD_DECIMALS\n : balanceToken.displayDecimals;\n if (value !== \"\" && !isValidNumber(value, maxDecimals)) return;\n\n const sanitizedValue = sanitizeNumber(value);\n\n const newUsdValue = isEditingUsd\n ? value\n : tokenAmountToRoundedUsd(\n parseUnits(sanitizedValue, balanceToken.decimals),\n balanceToken,\n );\n const newTokenValue = isEditingUsd\n ? usdToRoundedTokenAmount(Number(sanitizedValue), balanceToken)\n : value;\n updateValues(newUsdValue, newTokenValue, isEditingUsd);\n };\n\n const handleMax = () => {\n const usdValue = roundUsd(Number(selectedTokenOption.balance.usd));\n const tokenValue = roundTokenAmount(\n selectedTokenOption.balance.amount,\n balanceToken,\n );\n updateValues(usdValue, tokenValue, isEditingUsd);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && !continueDisabled) {\n handleContinue();\n }\n };\n\n const handleSwitchCurrency = () => {\n updateValues(usdValue, tokenValue, !isEditingUsd);\n };\n\n const handleContinue = () => {\n const usd = Number(sanitizeNumber(usdValue));\n const amountUnits = usd / balanceToken.usd;\n const amount = parseUnits(amountUnits.toString(), balanceToken.decimals);\n setSelectedTokenOption({\n ...selectedTokenOption,\n required: {\n token: balanceToken,\n amount: amount.toString() as `${bigint}`,\n usd,\n },\n });\n paymentState.setChosenUsd(usd);\n setRoute(nextPage, {\n amountUsd: usd,\n amountUnits,\n tokenSymbol: balanceToken.symbol,\n });\n };\n\n return (\n <PageContent>\n <TokenLogoSpinner token={balanceToken} />\n <ModalContent $preserveDisplay={true}>\n <AmountInputContainer>\n {/* Invisible div to balance spacing */}\n <MaxButton style={{ visibility: \"hidden\" }}>Max</MaxButton>\n <AmountInputField\n value={isEditingUsd ? usdValue : tokenValue}\n onChange={handleAmountChange}\n currency={isEditingUsd ? \"$\" : balanceToken.symbol}\n onKeyDown={handleKeyDown}\n />\n <MaxButton onClick={handleMax}>Max</MaxButton>\n </AmountInputContainer>\n\n {balanceToken.fiatISO !== \"USD\" && (\n <SwitchContainer>\n <SwitchButton onClick={handleSwitchCurrency}>\n <SecondaryAmount>\n {isEditingUsd\n ? `${tokenValue} ${balanceToken.symbol}`\n : `$${usdValue}`}\n </SecondaryAmount>\n </SwitchButton>\n </SwitchContainer>\n )}\n\n {message && <ModalBody>{message}</ModalBody>}\n\n <Button onClick={handleContinue} disabled={continueDisabled}>\n Continue\n </Button>\n </ModalContent>\n </PageContent>\n );\n};\n\nconst AmountInputContainer = styled.div`\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n`;\nconst SecondaryAmount = styled.div`\n font-size: 16px;\n font-weight: 400;\n line-height: 21px;\n color: var(--ck-body-color-muted);\n strong {\n font-weight: 500;\n color: var(--ck-body-color);\n }\n`;\nconst MaxButton = styled.button`\n display: inline-block;\n padding: 3px 8px;\n border-radius: var(--ck-primary-button-border-radius);\n font-size: 14px;\n font-weight: 400;\n background: var(\n --ck-secondary-button-background,\n var(--ck-body-background-secondary)\n );\n color: var(--ck-body-color-secondary);\n cursor: pointer;\n`;\nconst SwitchContainer = styled.div`\n display: flex;\n align-items: center;\n justify-content: center;\n`;\n\nexport default MultiCurrencySelectAmount;\n"],"names":["usdValue","tokenValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/components/Common/AmountInput/index.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { ROUTES } from \"../../../constants/routes\";\nimport { usePayContext } from \"../../../hooks/usePayContext\";\n\nimport {\n ModalBody,\n ModalContent,\n PageContent,\n} from \"../../Common/Modal/styles\";\n\nimport { WalletPaymentOption } from \"@daimo/pay-common\";\nimport { parseUnits } from \"viem\";\nimport styled from \"../../../styles/styled\";\nimport {\n formatUsd,\n roundTokenAmount,\n roundTokenAmountUnits,\n roundUsd,\n tokenAmountToRoundedUsd,\n USD_DECIMALS,\n usdToRoundedTokenAmount,\n} from \"../../../utils/format\";\nimport { isValidNumber, sanitizeNumber } from \"../../../utils/validateInput\";\nimport Button from \"../../Common/Button\";\nimport SwitchButton from \"../../Common/SwitchButton\";\nimport TokenLogoSpinner from \"../../Spinners/TokenLogoSpinner\";\nimport AmountInputField from \"./AmountInputField\";\n\nconst MultiCurrencySelectAmount: React.FC<{\n selectedTokenOption: WalletPaymentOption;\n setSelectedTokenOption: (option: WalletPaymentOption) => void;\n nextPage: ROUTES;\n}> = ({ selectedTokenOption, setSelectedTokenOption, nextPage }) => {\n const { paymentState, setRoute, triggerResize } = usePayContext();\n const maxUsdLimit = paymentState.getOrderUsdLimit();\n\n const balanceToken = selectedTokenOption.balance.token;\n\n // Balance messages for USD and token modes\n const isUsdStablecoin = balanceToken.fiatISO === \"USD\";\n const usdBalanceMessage = isUsdStablecoin\n ? `Balance: ${formatUsd(selectedTokenOption.balance.usd)}`\n : `Balance: ${formatUsd(selectedTokenOption.balance.usd)} ${balanceToken.symbol}`;\n const tokenBalanceMessage = `Balance: ${roundTokenAmount(selectedTokenOption.balance.amount, balanceToken)} ${balanceToken.symbol}`;\n\n const getBalanceMessage = (editingUsd: boolean) =>\n editingUsd ? usdBalanceMessage : tokenBalanceMessage;\n\n const [usdStr, setUsdValue] = useState(\"\");\n const [tokenStr, setTokenValue] = useState(\"\");\n const [isEditingUsd, setIsEditingUsd] = useState(true);\n const [message, setMessage] = useState<string | null>(usdBalanceMessage);\n const [continueDisabled, setContinueDisabled] = useState(true);\n\n useEffect(() => {\n triggerResize();\n }, [message]); // eslint-disable-line react-hooks/exhaustive-deps\n\n /**\n * Update the editable value and secondary value, taking into account whether\n * the user is currently editing the USD value or the token value.\n */\n const updateValues = (\n newUsdValue: string,\n newTokenValue: string,\n newIsEditingUsd: boolean,\n ) => {\n const sanitizedUsdValue = sanitizeNumber(newUsdValue);\n const sanitizedTokenValue = sanitizeNumber(newTokenValue);\n const usdNum = Number(sanitizedUsdValue);\n const tokenNum = Number(sanitizedTokenValue);\n\n // Update the state. Don't sanitize the value if the user is editing it.\n // Show empty for zero values so user can start typing immediately.\n // Strip trailing zeros from token values for cleaner display.\n const stripTrailingZeros = (val: string) =>\n val.includes(\".\") ? val.replace(/\\.?0+$/, \"\") : val;\n\n setUsdValue(\n newIsEditingUsd ? newUsdValue : usdNum > 0 ? roundUsd(usdNum) : \"\",\n );\n setTokenValue(\n newIsEditingUsd\n ? tokenNum > 0\n ? stripTrailingZeros(roundTokenAmountUnits(tokenNum, balanceToken))\n : \"\"\n : newTokenValue,\n );\n setIsEditingUsd(newIsEditingUsd);\n\n setContinueDisabled(\n usdNum <= 0 ||\n usdNum < selectedTokenOption.minimumRequired.usd ||\n usdNum > selectedTokenOption.balance.usd ||\n usdNum > maxUsdLimit,\n );\n\n // Format amounts based on current mode (USD or token)\n const formatAmount = (usd: number) =>\n newIsEditingUsd\n ? formatUsd(usd)\n : `${usdToRoundedTokenAmount(usd, balanceToken)} ${balanceToken.symbol}`;\n\n if (usdNum > selectedTokenOption.balance.usd) {\n setMessage(\n `Amount exceeds your balance: ${formatAmount(selectedTokenOption.balance.usd)}`,\n );\n } else if (usdNum > maxUsdLimit) {\n setMessage(`Maximum ${formatAmount(maxUsdLimit)}`);\n } else if (usdNum > 0 && usdNum < selectedTokenOption.minimumRequired.usd) {\n setMessage(\n `Minimum ${formatAmount(selectedTokenOption.minimumRequired.usd)}`,\n );\n } else {\n setMessage(getBalanceMessage(newIsEditingUsd));\n }\n };\n\n const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n const maxDecimals = isEditingUsd\n ? USD_DECIMALS\n : balanceToken.displayDecimals;\n if (value !== \"\" && !isValidNumber(value, maxDecimals)) return;\n\n const sanitizedValue = sanitizeNumber(value);\n\n const newUsdValue = isEditingUsd\n ? value\n : tokenAmountToRoundedUsd(\n parseUnits(sanitizedValue, balanceToken.decimals),\n balanceToken,\n );\n const newTokenValue = isEditingUsd\n ? usdToRoundedTokenAmount(Number(sanitizedValue), balanceToken)\n : value;\n updateValues(newUsdValue, newTokenValue, isEditingUsd);\n };\n\n const handleMax = () => {\n const usdStr = roundUsd(Number(selectedTokenOption.balance.usd));\n const tokenStr = roundTokenAmount(\n selectedTokenOption.balance.amount,\n balanceToken,\n );\n updateValues(usdStr, tokenStr, isEditingUsd);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && !continueDisabled) {\n handleContinue();\n }\n };\n\n const handleSwitchCurrency = () => {\n updateValues(usdStr, tokenStr, !isEditingUsd);\n };\n\n const handleContinue = () => {\n const usd = Number(sanitizeNumber(usdStr));\n const amountUnits = usd / balanceToken.usd;\n const amount = parseUnits(amountUnits.toString(), balanceToken.decimals);\n setSelectedTokenOption({\n ...selectedTokenOption,\n required: {\n token: balanceToken,\n amount: amount.toString() as `${bigint}`,\n usd,\n },\n });\n paymentState.setChosenUsd(usd);\n setRoute(nextPage, {\n amountUsd: usd,\n amountUnits,\n tokenSymbol: balanceToken.symbol,\n });\n };\n\n return (\n <PageContent>\n <TokenLogoSpinner token={balanceToken} />\n <ModalContent $preserveDisplay={true}>\n <AmountInputContainer>\n {/* Invisible div to balance spacing */}\n <MaxButton style={{ visibility: \"hidden\" }}>Max</MaxButton>\n <AmountInputField\n value={isEditingUsd ? usdStr : tokenStr}\n onChange={handleAmountChange}\n currency={isEditingUsd ? \"$\" : balanceToken.symbol}\n onKeyDown={handleKeyDown}\n />\n <MaxButton onClick={handleMax}>Max</MaxButton>\n </AmountInputContainer>\n\n {balanceToken.fiatISO !== \"USD\" && (\n <SwitchContainer>\n <SwitchButton onClick={handleSwitchCurrency}>\n <SecondaryAmount>\n {isEditingUsd\n ? `${tokenStr || \"0\"} ${balanceToken.symbol}`\n : `$${usdStr || roundUsd(0)}`}\n </SecondaryAmount>\n </SwitchButton>\n </SwitchContainer>\n )}\n\n {message && <ModalBody>{message}</ModalBody>}\n\n <Button onClick={handleContinue} disabled={continueDisabled}>\n Continue\n </Button>\n </ModalContent>\n </PageContent>\n );\n};\n\nconst AmountInputContainer = styled.div`\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n`;\n\nconst SecondaryAmount = styled.div`\n font-size: 16px;\n font-weight: 400;\n line-height: 21px;\n color: var(--ck-body-color-muted);\n strong {\n font-weight: 500;\n color: var(--ck-body-color);\n }\n`;\nconst MaxButton = styled.button`\n display: inline-block;\n padding: 3px 8px;\n border-radius: var(--ck-primary-button-border-radius);\n font-size: 14px;\n font-weight: 400;\n background: var(\n --ck-secondary-button-background,\n var(--ck-body-background-secondary)\n );\n color: var(--ck-body-color-secondary);\n cursor: pointer;\n`;\nconst SwitchContainer = styled.div`\n display: flex;\n align-items: center;\n justify-content: center;\n`;\n\nexport default MultiCurrencySelectAmount;\n"],"names":["usdStr","tokenStr"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { useEffect, useState, useCallback
|
|
2
|
+
import { useRef, useEffect, useState, useCallback } from 'react';
|
|
3
3
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
4
4
|
import { ResetContainer } from '../../../styles/index.js';
|
|
5
5
|
import Portal from '../Portal/index.js';
|
|
@@ -179,6 +179,16 @@ const Modal = ({
|
|
|
179
179
|
const rendered = state === "preEnter" || state !== "exiting";
|
|
180
180
|
const currentDepth = routeDepthMap[context.route] ?? 1;
|
|
181
181
|
const prevDepth = usePrevious(currentDepth, currentDepth);
|
|
182
|
+
const isOpeningAnimation = useRef(false);
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
if (open) {
|
|
185
|
+
isOpeningAnimation.current = true;
|
|
186
|
+
const timer = setTimeout(() => {
|
|
187
|
+
isOpeningAnimation.current = false;
|
|
188
|
+
}, 200);
|
|
189
|
+
return () => clearTimeout(timer);
|
|
190
|
+
}
|
|
191
|
+
}, [open]);
|
|
182
192
|
if (!positionInside) useLockBodyScroll(mounted);
|
|
183
193
|
useEffect(() => {
|
|
184
194
|
setOpen(open);
|
|
@@ -217,6 +227,7 @@ const Modal = ({
|
|
|
217
227
|
const { switchChain } = useSwitchChain();
|
|
218
228
|
const ref = useRef(null);
|
|
219
229
|
useEffect(() => {
|
|
230
|
+
if (isOpeningAnimation.current) return;
|
|
220
231
|
if (ref.current) updateBounds(ref.current);
|
|
221
232
|
}, [chain, switchChain, mobile, context.options, context.resize]);
|
|
222
233
|
useEffect(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../src/components/Common/Modal/index.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { AnimatePresence, motion, Variants } from \"framer-motion\";\n\nimport { ResetContainer } from \"../../../styles\";\nimport Portal from \"../Portal\";\n\nimport { flattenChildren, isMobile } from \"../../../utils\";\n\nimport {\n BackButton,\n BackgroundOverlay,\n BoxContainer,\n CloseButton,\n Container,\n ControllerContainer,\n Disclaimer,\n DisclaimerBackground,\n ErrorMessage,\n InfoButton,\n InnerContainer,\n ModalContainer,\n ModalHeading,\n PageContainer,\n PageContents,\n TextWithHr,\n} from \"./styles\";\n\nimport useLockBodyScroll from \"../../../hooks/useLockBodyScroll\";\nimport { usePayContext } from \"../../../hooks/usePayContext\";\n\nimport {\n getChainName,\n shouldShowExternalQRCodeOnDesktop,\n} from \"@daimo/pay-common\";\nimport { useTransition } from \"react-transition-state\";\nimport { useAccount, useSwitchChain } from \"wagmi\";\nimport { AuthIcon } from \"../../../assets/icons\";\nimport { ROUTES } from \"../../../constants/routes\";\nimport { useDaimoPay } from \"../../../hooks/useDaimoPay\";\nimport FocusTrap from \"../../../hooks/useFocusTrap\";\nimport useLocales from \"../../../hooks/useLocales\";\nimport usePrevious from \"../../../hooks/usePrevious\";\nimport { CustomTheme } from \"../../../types\";\nimport { isExternalWallet, useWallet } from \"../../../wallets/useWallets\";\nimport { useThemeContext } from \"../../DaimoPayThemeProvider/DaimoPayThemeProvider\";\nimport FitText from \"../FitText\";\n\n// Map routes to a depth value to drive enter/exit animations.\n// Higher numbers feel \"deeper\" in the flow.\nconst routeDepthMap: Partial<Record<ROUTES, number>> = {\n [ROUTES.SELECT_METHOD]: 0,\n\n [ROUTES.CONNECTORS]: 1,\n [ROUTES.SELECT_EXCHANGE]: 1,\n [ROUTES.SELECT_DEPOSIT_ADDRESS_CHAIN]: 1,\n\n [ROUTES.SELECT_ZKP2P]: 1,\n\n [ROUTES.CONNECT]: 2,\n [ROUTES.SOLANA_CONNECTOR]: 2,\n [ROUTES.MOBILECONNECTORS]: 2,\n [ROUTES.SELECT_WALLET_CHAIN]: 2,\n [ROUTES.SELECT_TOKEN]: 2,\n [ROUTES.SELECT_AMOUNT]: 2,\n [ROUTES.SELECT_EXTERNAL_AMOUNT]: 2,\n [ROUTES.SELECT_DEPOSIT_ADDRESS_AMOUNT]: 2,\n [ROUTES.SELECT_WALLET_AMOUNT]: 2,\n [ROUTES.PAY_WITH_TOKEN]: 2,\n [ROUTES.SOLANA_SELECT_AMOUNT]: 2,\n [ROUTES.SOLANA_PAY_WITH_TOKEN]: 2,\n\n [ROUTES.WAITING_WALLET]: 3,\n [ROUTES.WAITING_EXTERNAL]: 3,\n [ROUTES.WAITING_DEPOSIT_ADDRESS]: 3,\n\n [ROUTES.CONFIRMATION]: 4,\n [ROUTES.ERROR]: 4,\n};\n\nconst ProfileIcon = ({ isSignedIn }: { isSignedIn?: boolean }) => (\n <div style={{ position: \"relative\" }}>\n {isSignedIn ? (\n <AuthIcon\n style={{\n bottom: -1,\n right: -1,\n }}\n />\n ) : (\n <div\n style={{\n zIndex: 2,\n position: \"absolute\",\n top: -2,\n right: -2,\n background: \"#1A88F8\",\n borderRadius: 8,\n boxShadow: \"0 0 0 2px var(--ck-body-background)\",\n width: 8,\n height: 8,\n }}\n />\n )}\n <svg\n aria-hidden=\"true\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{ overflow: \"visible\" }}\n >\n <circle cx=\"10\" cy=\"10\" r=\"9\" stroke=\"currentColor\" strokeWidth=\"2\" />\n <path\n d=\"M16.5 16.775C14.8618 15.0649 12.5552 14 10 14C7.44477 14 5.13825 15.0649 3.5 16.775\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n />\n <circle cx=\"10\" cy=\"8\" r=\"3\" stroke=\"currentColor\" strokeWidth=\"2\" />\n </svg>\n </div>\n);\nconst InfoIcon = ({ ...props }) => (\n <svg\n aria-hidden=\"true\"\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 22 22\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M20 11C20 15.9706 15.9706 20 11 20C6.02944 20 2 15.9706 2 11C2 6.02944 6.02944 2 11 2C15.9706 2 20 6.02944 20 11ZM22 11C22 17.0751 17.0751 22 11 22C4.92487 22 0 17.0751 0 11C0 4.92487 4.92487 0 11 0C17.0751 0 22 4.92487 22 11ZM11.6445 12.7051C11.6445 13.1348 11.3223 13.4678 10.7744 13.4678C10.2266 13.4678 9.92578 13.1885 9.92578 12.6191V12.4795C9.92578 11.4268 10.4951 10.8574 11.2686 10.3203C12.2031 9.67578 12.665 9.32129 12.665 8.59082C12.665 7.76367 12.0205 7.21582 11.043 7.21582C10.3232 7.21582 9.80762 7.57031 9.45312 8.16113C9.38282 8.24242 9.32286 8.32101 9.2667 8.39461C9.04826 8.68087 8.88747 8.8916 8.40039 8.8916C8.0459 8.8916 7.66992 8.62305 7.66992 8.15039C7.66992 7.96777 7.70215 7.7959 7.75586 7.61328C8.05664 6.625 9.27051 5.75488 11.1182 5.75488C12.9336 5.75488 14.5234 6.71094 14.5234 8.50488C14.5234 9.7832 13.7822 10.417 12.7402 11.1045C11.999 11.5986 11.6445 11.9746 11.6445 12.5762V12.7051ZM11.9131 15.5625C11.9131 16.1855 11.376 16.6797 10.7529 16.6797C10.1299 16.6797 9.59277 16.1748 9.59277 15.5625C9.59277 14.9395 10.1191 14.4453 10.7529 14.4453C11.3867 14.4453 11.9131 14.9287 11.9131 15.5625Z\"\n fill=\"currentColor\"\n />\n </svg>\n);\nconst CloseIcon = ({ ...props }) => (\n <motion.svg\n width={14}\n height={14}\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path\n d=\"M1 13L13 1M1 1L13 13\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </motion.svg>\n);\nconst BackIcon = ({ ...props }) => (\n <motion.svg\n width={9}\n height={16}\n viewBox=\"0 0 9 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path\n d=\"M8 1L1 8L8 15\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </motion.svg>\n);\n\nconst contentTransitionDuration = 0.22;\n\nexport const contentVariants: Variants = {\n initial: {\n //willChange: 'transform,opacity',\n zIndex: 2,\n opacity: 0,\n },\n animate: {\n opacity: 1,\n scale: 1,\n transition: {\n duration: contentTransitionDuration * 0.75,\n delay: contentTransitionDuration * 0.25,\n ease: [0.26, 0.08, 0.25, 1],\n },\n },\n exit: {\n zIndex: 1,\n opacity: 0,\n pointerEvents: \"none\",\n position: \"absolute\",\n left: [\"50%\", \"50%\"],\n x: [\"-50%\", \"-50%\"],\n transition: {\n duration: contentTransitionDuration,\n ease: [0.26, 0.08, 0.25, 1],\n },\n },\n};\n\ntype ModalProps = {\n open?: boolean;\n pages: Record<ROUTES, React.ReactNode>;\n pageId: string;\n positionInside?: boolean;\n inline?: boolean;\n onClose?: () => void;\n onBack?: () => void;\n onInfo?: () => void;\n demo?: {\n theme: string;\n mode?: string;\n customTheme: CustomTheme;\n };\n};\nconst Modal: React.FC<ModalProps> = ({\n open,\n pages,\n pageId,\n positionInside,\n inline,\n demo,\n onClose,\n onBack,\n onInfo,\n}) => {\n const context = usePayContext();\n const themeContext = useThemeContext();\n const mobile = isMobile();\n const {\n selectedExternalOption,\n selectedTokenOption,\n selectedSolanaTokenOption,\n selectedDepositAddressOption,\n } = context.paymentState;\n const { order, paymentState } = useDaimoPay();\n\n const { connector } = useAccount();\n // For external wallets (World, MiniPay), use pendingConnectorId\n // For injected wallets, use connector?.id\n const walletId = context.pendingConnectorId || connector?.id || \"\";\n const walletFromConnectors = useWallet(walletId);\n // Fall back to selectedWallet for wallets from walletConfigs (e.g. unique payment options)\n const wallet = walletFromConnectors || context.paymentState.selectedWallet;\n\n const walletInfo = {\n name: wallet?.name,\n shortName: wallet?.shortName ?? wallet?.name,\n icon: wallet?.iconConnector ?? wallet?.icon,\n iconShape: wallet?.iconShape ?? \"circle\",\n iconShouldShrink: wallet?.iconShouldShrink,\n };\n\n const locales = useLocales({\n CONNECTORNAME: walletInfo?.name,\n });\n\n const [state, setOpen] = useTransition({\n timeout: 160,\n preEnter: true,\n mountOnEnter: true,\n unmountOnExit: true,\n });\n const mounted = !(state === \"exited\" || state === \"unmounted\");\n const rendered = state === \"preEnter\" || state !== \"exiting\";\n const currentDepth = routeDepthMap[context.route as ROUTES] ?? 1;\n const prevDepth = usePrevious(currentDepth, currentDepth);\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n if (!positionInside) useLockBodyScroll(mounted);\n\n useEffect(() => {\n setOpen(open);\n if (open) setInTransition(undefined);\n }, [open]);\n\n const [dimensions, setDimensions] = useState<{\n width: string | undefined;\n height: string | undefined;\n }>({\n width: undefined,\n height: undefined,\n });\n const [inTransition, setInTransition] = useState<boolean | undefined>(\n undefined,\n );\n\n // Calculate new content bounds\n const updateBounds = (node: any) => {\n const bounds = {\n width: node?.offsetWidth,\n height: node?.offsetHeight,\n };\n setDimensions({\n width: `${bounds?.width}px`,\n height: `${bounds?.height}px`,\n });\n };\n\n let blockTimeout: ReturnType<typeof setTimeout>;\n const contentRef = useCallback(\n (node: any) => {\n if (!node) return;\n ref.current = node;\n\n // Avoid transition mixups\n setInTransition(inTransition === undefined ? false : true);\n clearTimeout(blockTimeout);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n blockTimeout = setTimeout(() => setInTransition(false), 360);\n\n // Calculate new content bounds\n updateBounds(node);\n },\n [open, inTransition],\n );\n\n // Update layout on chain/network switch to avoid clipping\n const { chain } = useAccount();\n const { switchChain } = useSwitchChain();\n\n const ref = useRef<any>(null);\n useEffect(() => {\n if (ref.current) updateBounds(ref.current);\n }, [chain, switchChain, mobile, context.options, context.resize]);\n\n useEffect(() => {\n if (!mounted) {\n setDimensions({\n width: undefined,\n height: undefined,\n });\n return;\n }\n\n const listener = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && onClose) onClose();\n };\n document.addEventListener(\"keydown\", listener);\n return () => {\n document.removeEventListener(\"keydown\", listener);\n };\n }, [mounted, onClose]);\n\n const dimensionsCSS = {\n \"--height\": dimensions.height,\n \"--width\": dimensions.width,\n } as React.CSSProperties;\n\n // Show \"Scan with phone\" title for wallets with deeplinks (unique payment options)\n const hasDeeplink = wallet && wallet.getDaimoPayDeeplink;\n const shouldShowWalletQRCodeOnDesktop =\n isExternalWallet(wallet) || hasDeeplink;\n\n function getHeading() {\n const payWithString = flattenChildren(locales.payWith).join(\"\");\n switch (context.route) {\n case ROUTES.ABOUT:\n return locales.aboutScreen_heading;\n case ROUTES.CONNECT:\n if (shouldShowWalletQRCodeOnDesktop) {\n return locales.scanWithPhone;\n } else {\n return walletInfo?.name;\n }\n case ROUTES.SELECT_EXCHANGE:\n return locales.selectExchange;\n case ROUTES.SOLANA_CONNECTOR:\n return context.solanaConnector ?? locales.solanaWallet;\n case ROUTES.CONNECTORS:\n return locales.connectorsScreen_heading;\n case ROUTES.MOBILECONNECTORS:\n return locales.mobileConnectorsScreen_heading;\n case ROUTES.ONBOARDING:\n return locales.onboardingScreen_heading;\n case ROUTES.SWITCHNETWORKS:\n return locales.switchNetworkScreen_heading;\n case ROUTES.SELECT_METHOD:\n case ROUTES.SELECT_TOKEN:\n return order?.metadata.intent;\n case ROUTES.SOLANA_PAY_WITH_TOKEN:\n if (!selectedSolanaTokenOption) return undefined;\n return `${payWithString} ${selectedSolanaTokenOption.required.token.symbol}`;\n case ROUTES.WAITING_EXTERNAL:\n if (\n selectedExternalOption &&\n shouldShowExternalQRCodeOnDesktop(selectedExternalOption.id) &&\n !mobile\n ) {\n return locales.scanWithPhone;\n }\n return selectedExternalOption?.cta;\n case ROUTES.SELECT_DEPOSIT_ADDRESS_CHAIN:\n return locales.selectChain;\n case ROUTES.WAITING_DEPOSIT_ADDRESS:\n if (paymentState === \"warning\") return locales.leaveSession;\n if (!selectedDepositAddressOption) return undefined;\n return `${payWithString} ${selectedDepositAddressOption.id}`;\n case ROUTES.SELECT_ZKP2P:\n return locales.selectApp;\n case ROUTES.SELECT_AMOUNT:\n case ROUTES.SELECT_EXTERNAL_AMOUNT:\n case ROUTES.SELECT_DEPOSIT_ADDRESS_AMOUNT:\n case ROUTES.SOLANA_SELECT_AMOUNT:\n case ROUTES.SELECT_WALLET_AMOUNT:\n return locales.selectAmount;\n case ROUTES.PAY_WITH_TOKEN:\n if (selectedTokenOption == null) return undefined;\n\n const chainName = getChainName(\n selectedTokenOption.balance.token.chainId,\n );\n return `${payWithString} ${chainName} ${selectedTokenOption.balance.token.symbol}`;\n case ROUTES.CONFIRMATION:\n return locales.paymentSuccessful;\n case ROUTES.ERROR:\n return locales.error;\n case ROUTES.SELECT_WALLET_CHAIN:\n return locales.selectChain;\n }\n }\n\n const Content = (\n <ResetContainer\n $useTheme={demo?.theme ?? themeContext.theme}\n $useMode={demo?.mode ?? themeContext.mode}\n $customTheme={demo?.customTheme ?? themeContext.customTheme}\n >\n <ModalContainer\n role=\"dialog\"\n style={{\n pointerEvents: rendered ? \"auto\" : \"none\",\n position: positionInside ? \"absolute\" : undefined,\n }}\n >\n {!inline && (\n <BackgroundOverlay\n $active={rendered}\n onClick={onClose}\n $blur={context.options?.overlayBlur}\n />\n )}\n <Container\n style={dimensionsCSS}\n initial={false}\n // transition={{\n // ease: [0.2555, 0.1111, 0.2555, 1.0001],\n // duration: !positionInside && state !== 'entered' ? 0 : 0.24,\n // }}\n >\n <div\n style={{\n pointerEvents: inTransition ? \"all\" : \"none\", // Block interaction while transitioning\n position: \"absolute\",\n top: 0,\n bottom: 0,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"var(--width)\",\n zIndex: 9,\n transition: \"width 200ms ease\",\n }}\n />\n <BoxContainer className={`${rendered && \"active\"}`}>\n <AnimatePresence initial={false}>\n {context.options?.disclaimer &&\n context.route === ROUTES.CONNECTORS && (\n <DisclaimerBackground\n initial={{\n opacity: 0,\n }}\n animate={{\n opacity: 1,\n }}\n exit={{ opacity: 0 }}\n transition={{\n delay: 0,\n duration: 0.2,\n ease: [0.25, 0.1, 0.25, 1.0],\n }}\n >\n <Disclaimer>\n <div>{context.options?.disclaimer}</div>\n </Disclaimer>\n </DisclaimerBackground>\n )}\n </AnimatePresence>\n <AnimatePresence initial={false}>\n {context.errorMessage && (\n <ErrorMessage\n initial={{ y: \"10%\", x: \"-50%\" }}\n animate={{ y: \"-100%\" }}\n exit={{ y: \"100%\" }}\n transition={{ duration: 0.2, ease: \"easeInOut\" }}\n >\n <span>{context.errorMessage}</span>\n <div\n onClick={() => context.displayError(null)}\n style={{\n position: \"absolute\",\n right: 24,\n top: 24,\n cursor: \"pointer\",\n }}\n >\n <CloseIcon />\n </div>\n </ErrorMessage>\n )}\n </AnimatePresence>\n <ControllerContainer>\n {onClose && (\n <CloseButton\n aria-label={flattenChildren(locales.close).toString()}\n onClick={onClose}\n >\n <CloseIcon />\n </CloseButton>\n )}\n <div\n style={{\n position: \"absolute\",\n top: 23,\n left: 20,\n width: 32,\n height: 32,\n }}\n >\n <AnimatePresence>\n {onBack ? (\n <BackButton\n disabled={inTransition}\n aria-label={flattenChildren(locales.back).toString()}\n key=\"backButton\"\n onClick={onBack}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{\n duration: mobile ? 0 : 0.1,\n delay: mobile ? 0.01 : 0,\n }}\n >\n <BackIcon />\n </BackButton>\n ) : (\n onInfo &&\n !context.options?.hideQuestionMarkCTA && (\n <InfoButton\n disabled={inTransition}\n aria-label={flattenChildren(\n locales.moreInformation,\n ).toString()}\n key=\"infoButton\"\n onClick={onInfo}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{\n duration: mobile ? 0 : 0.1,\n delay: mobile ? 0.01 : 0,\n }}\n >\n <InfoIcon />\n </InfoButton>\n )\n )}\n </AnimatePresence>\n </div>\n </ControllerContainer>\n\n <ModalHeading>\n <AnimatePresence>\n <motion.div\n style={{\n position: \"absolute\",\n top: 0,\n bottom: 0,\n left: 52,\n right: 52,\n display: \"flex\",\n //alignItems: 'center',\n justifyContent: \"center\",\n }}\n key={`${context.route}`}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{\n duration: mobile ? 0 : 0.17,\n delay: mobile ? 0.01 : 0,\n }}\n >\n <FitText>{getHeading()}</FitText>\n </motion.div>\n </AnimatePresence>\n </ModalHeading>\n\n <InnerContainer>\n {Object.keys(pages).map((key) => (\n <Page\n key={key}\n open={key === pageId}\n initial={!positionInside && state !== \"entered\"}\n enterAnim={\n key === pageId\n ? currentDepth > prevDepth\n ? \"active-scale-up\"\n : \"active\"\n : \"\"\n }\n exitAnim={\n key !== pageId\n ? currentDepth < prevDepth\n ? \"exit-scale-down\"\n : \"exit\"\n : \"\"\n }\n >\n <PageContents\n key={`inner-${key}`}\n ref={contentRef}\n style={{\n pointerEvents:\n key === pageId && rendered ? \"auto\" : \"none\",\n }}\n >\n {pages[key]}\n </PageContents>\n </Page>\n ))}\n </InnerContainer>\n </BoxContainer>\n </Container>\n </ModalContainer>\n </ResetContainer>\n );\n return (\n <>\n {mounted && (\n <>\n {positionInside ? (\n Content\n ) : (\n <>\n {\n <Portal>\n <FocusTrap>{Content}</FocusTrap>\n </Portal>\n }\n </>\n )}\n </>\n )}\n </>\n );\n};\n\ntype PageProps = {\n children?: React.ReactNode;\n open?: boolean;\n initial: boolean;\n enterAnim?: string;\n exitAnim?: string;\n};\n\nconst Page: React.FC<PageProps> = ({\n children,\n open,\n initial,\n enterAnim,\n exitAnim,\n}) => {\n const [state, setOpen] = useTransition({\n timeout: 400,\n preEnter: true,\n initialEntered: open,\n mountOnEnter: true,\n unmountOnExit: true,\n });\n const mounted = !(state === \"exited\" || state === \"unmounted\");\n const rendered = state === \"preEnter\" || state !== \"exiting\";\n\n useEffect(() => {\n setOpen(open);\n }, [open]);\n\n if (!mounted) return null;\n\n return (\n <PageContainer\n className={`${rendered ? enterAnim : exitAnim}`}\n style={{\n animationDuration: initial ? \"0ms\" : undefined,\n animationDelay: initial ? \"0ms\" : undefined,\n }}\n >\n {children}\n </PageContainer>\n );\n};\n\nexport const OrDivider = ({ children }: { children?: React.ReactNode }) => {\n const locales = useLocales();\n return (\n <TextWithHr>\n <span>{children ?? locales.or}</span>\n </TextWithHr>\n );\n};\n\nexport default Modal;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/components/Common/Modal/index.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { AnimatePresence, motion, Variants } from \"framer-motion\";\n\nimport { ResetContainer } from \"../../../styles\";\nimport Portal from \"../Portal\";\n\nimport { flattenChildren, isMobile } from \"../../../utils\";\n\nimport {\n BackButton,\n BackgroundOverlay,\n BoxContainer,\n CloseButton,\n Container,\n ControllerContainer,\n Disclaimer,\n DisclaimerBackground,\n ErrorMessage,\n InfoButton,\n InnerContainer,\n ModalContainer,\n ModalHeading,\n PageContainer,\n PageContents,\n TextWithHr,\n} from \"./styles\";\n\nimport useLockBodyScroll from \"../../../hooks/useLockBodyScroll\";\nimport { usePayContext } from \"../../../hooks/usePayContext\";\n\nimport {\n getChainName,\n shouldShowExternalQRCodeOnDesktop,\n} from \"@daimo/pay-common\";\nimport { useTransition } from \"react-transition-state\";\nimport { useAccount, useSwitchChain } from \"wagmi\";\nimport { AuthIcon } from \"../../../assets/icons\";\nimport { ROUTES } from \"../../../constants/routes\";\nimport { useDaimoPay } from \"../../../hooks/useDaimoPay\";\nimport FocusTrap from \"../../../hooks/useFocusTrap\";\nimport useLocales from \"../../../hooks/useLocales\";\nimport usePrevious from \"../../../hooks/usePrevious\";\nimport { CustomTheme } from \"../../../types\";\nimport { isExternalWallet, useWallet } from \"../../../wallets/useWallets\";\nimport { useThemeContext } from \"../../DaimoPayThemeProvider/DaimoPayThemeProvider\";\nimport FitText from \"../FitText\";\n\n// Map routes to a depth value to drive enter/exit animations.\n// Higher numbers feel \"deeper\" in the flow.\nconst routeDepthMap: Partial<Record<ROUTES, number>> = {\n [ROUTES.SELECT_METHOD]: 0,\n\n [ROUTES.CONNECTORS]: 1,\n [ROUTES.SELECT_EXCHANGE]: 1,\n [ROUTES.SELECT_DEPOSIT_ADDRESS_CHAIN]: 1,\n\n [ROUTES.SELECT_ZKP2P]: 1,\n\n [ROUTES.CONNECT]: 2,\n [ROUTES.SOLANA_CONNECTOR]: 2,\n [ROUTES.MOBILECONNECTORS]: 2,\n [ROUTES.SELECT_WALLET_CHAIN]: 2,\n [ROUTES.SELECT_TOKEN]: 2,\n [ROUTES.SELECT_AMOUNT]: 2,\n [ROUTES.SELECT_EXTERNAL_AMOUNT]: 2,\n [ROUTES.SELECT_DEPOSIT_ADDRESS_AMOUNT]: 2,\n [ROUTES.SELECT_WALLET_AMOUNT]: 2,\n [ROUTES.PAY_WITH_TOKEN]: 2,\n [ROUTES.SOLANA_SELECT_AMOUNT]: 2,\n [ROUTES.SOLANA_PAY_WITH_TOKEN]: 2,\n\n [ROUTES.WAITING_WALLET]: 3,\n [ROUTES.WAITING_EXTERNAL]: 3,\n [ROUTES.WAITING_DEPOSIT_ADDRESS]: 3,\n\n [ROUTES.CONFIRMATION]: 4,\n [ROUTES.ERROR]: 4,\n};\n\nconst ProfileIcon = ({ isSignedIn }: { isSignedIn?: boolean }) => (\n <div style={{ position: \"relative\" }}>\n {isSignedIn ? (\n <AuthIcon\n style={{\n bottom: -1,\n right: -1,\n }}\n />\n ) : (\n <div\n style={{\n zIndex: 2,\n position: \"absolute\",\n top: -2,\n right: -2,\n background: \"#1A88F8\",\n borderRadius: 8,\n boxShadow: \"0 0 0 2px var(--ck-body-background)\",\n width: 8,\n height: 8,\n }}\n />\n )}\n <svg\n aria-hidden=\"true\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{ overflow: \"visible\" }}\n >\n <circle cx=\"10\" cy=\"10\" r=\"9\" stroke=\"currentColor\" strokeWidth=\"2\" />\n <path\n d=\"M16.5 16.775C14.8618 15.0649 12.5552 14 10 14C7.44477 14 5.13825 15.0649 3.5 16.775\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n />\n <circle cx=\"10\" cy=\"8\" r=\"3\" stroke=\"currentColor\" strokeWidth=\"2\" />\n </svg>\n </div>\n);\nconst InfoIcon = ({ ...props }) => (\n <svg\n aria-hidden=\"true\"\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 22 22\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M20 11C20 15.9706 15.9706 20 11 20C6.02944 20 2 15.9706 2 11C2 6.02944 6.02944 2 11 2C15.9706 2 20 6.02944 20 11ZM22 11C22 17.0751 17.0751 22 11 22C4.92487 22 0 17.0751 0 11C0 4.92487 4.92487 0 11 0C17.0751 0 22 4.92487 22 11ZM11.6445 12.7051C11.6445 13.1348 11.3223 13.4678 10.7744 13.4678C10.2266 13.4678 9.92578 13.1885 9.92578 12.6191V12.4795C9.92578 11.4268 10.4951 10.8574 11.2686 10.3203C12.2031 9.67578 12.665 9.32129 12.665 8.59082C12.665 7.76367 12.0205 7.21582 11.043 7.21582C10.3232 7.21582 9.80762 7.57031 9.45312 8.16113C9.38282 8.24242 9.32286 8.32101 9.2667 8.39461C9.04826 8.68087 8.88747 8.8916 8.40039 8.8916C8.0459 8.8916 7.66992 8.62305 7.66992 8.15039C7.66992 7.96777 7.70215 7.7959 7.75586 7.61328C8.05664 6.625 9.27051 5.75488 11.1182 5.75488C12.9336 5.75488 14.5234 6.71094 14.5234 8.50488C14.5234 9.7832 13.7822 10.417 12.7402 11.1045C11.999 11.5986 11.6445 11.9746 11.6445 12.5762V12.7051ZM11.9131 15.5625C11.9131 16.1855 11.376 16.6797 10.7529 16.6797C10.1299 16.6797 9.59277 16.1748 9.59277 15.5625C9.59277 14.9395 10.1191 14.4453 10.7529 14.4453C11.3867 14.4453 11.9131 14.9287 11.9131 15.5625Z\"\n fill=\"currentColor\"\n />\n </svg>\n);\nconst CloseIcon = ({ ...props }) => (\n <motion.svg\n width={14}\n height={14}\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path\n d=\"M1 13L13 1M1 1L13 13\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </motion.svg>\n);\nconst BackIcon = ({ ...props }) => (\n <motion.svg\n width={9}\n height={16}\n viewBox=\"0 0 9 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path\n d=\"M8 1L1 8L8 15\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </motion.svg>\n);\n\nconst contentTransitionDuration = 0.22;\n\nexport const contentVariants: Variants = {\n initial: {\n //willChange: 'transform,opacity',\n zIndex: 2,\n opacity: 0,\n },\n animate: {\n opacity: 1,\n scale: 1,\n transition: {\n duration: contentTransitionDuration * 0.75,\n delay: contentTransitionDuration * 0.25,\n ease: [0.26, 0.08, 0.25, 1],\n },\n },\n exit: {\n zIndex: 1,\n opacity: 0,\n pointerEvents: \"none\",\n position: \"absolute\",\n left: [\"50%\", \"50%\"],\n x: [\"-50%\", \"-50%\"],\n transition: {\n duration: contentTransitionDuration,\n ease: [0.26, 0.08, 0.25, 1],\n },\n },\n};\n\ntype ModalProps = {\n open?: boolean;\n pages: Record<ROUTES, React.ReactNode>;\n pageId: string;\n positionInside?: boolean;\n inline?: boolean;\n onClose?: () => void;\n onBack?: () => void;\n onInfo?: () => void;\n demo?: {\n theme: string;\n mode?: string;\n customTheme: CustomTheme;\n };\n};\nconst Modal: React.FC<ModalProps> = ({\n open,\n pages,\n pageId,\n positionInside,\n inline,\n demo,\n onClose,\n onBack,\n onInfo,\n}) => {\n const context = usePayContext();\n const themeContext = useThemeContext();\n const mobile = isMobile();\n const {\n selectedExternalOption,\n selectedTokenOption,\n selectedSolanaTokenOption,\n selectedDepositAddressOption,\n } = context.paymentState;\n const { order, paymentState } = useDaimoPay();\n\n const { connector } = useAccount();\n // For external wallets (World, MiniPay), use pendingConnectorId\n // For injected wallets, use connector?.id\n const walletId = context.pendingConnectorId || connector?.id || \"\";\n const walletFromConnectors = useWallet(walletId);\n // Fall back to selectedWallet for wallets from walletConfigs (e.g. unique payment options)\n const wallet = walletFromConnectors || context.paymentState.selectedWallet;\n\n const walletInfo = {\n name: wallet?.name,\n shortName: wallet?.shortName ?? wallet?.name,\n icon: wallet?.iconConnector ?? wallet?.icon,\n iconShape: wallet?.iconShape ?? \"circle\",\n iconShouldShrink: wallet?.iconShouldShrink,\n };\n\n const locales = useLocales({\n CONNECTORNAME: walletInfo?.name,\n });\n\n const [state, setOpen] = useTransition({\n timeout: 160,\n preEnter: true,\n mountOnEnter: true,\n unmountOnExit: true,\n });\n const mounted = !(state === \"exited\" || state === \"unmounted\");\n const rendered = state === \"preEnter\" || state !== \"exiting\";\n const currentDepth = routeDepthMap[context.route as ROUTES] ?? 1;\n const prevDepth = usePrevious(currentDepth, currentDepth);\n\n // Track when modal is in initial opening animation to prevent triggerResize updates\n // This prevents dimension changes mid-animation when OptionsList loads\n const isOpeningAnimation = useRef(false);\n useEffect(() => {\n if (open) {\n isOpeningAnimation.current = true;\n // BoxIn animation is 150ms, wait for it to complete before allowing resizes\n const timer = setTimeout(() => {\n isOpeningAnimation.current = false;\n }, 200);\n return () => clearTimeout(timer);\n }\n }, [open]);\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n if (!positionInside) useLockBodyScroll(mounted);\n\n useEffect(() => {\n setOpen(open);\n if (open) setInTransition(undefined);\n }, [open]);\n\n const [dimensions, setDimensions] = useState<{\n width: string | undefined;\n height: string | undefined;\n }>({\n width: undefined,\n height: undefined,\n });\n const [inTransition, setInTransition] = useState<boolean | undefined>(\n undefined,\n );\n\n // Calculate new content bounds\n const updateBounds = (node: any) => {\n const bounds = {\n width: node?.offsetWidth,\n height: node?.offsetHeight,\n };\n setDimensions({\n width: `${bounds?.width}px`,\n height: `${bounds?.height}px`,\n });\n };\n\n let blockTimeout: ReturnType<typeof setTimeout>;\n const contentRef = useCallback(\n (node: any) => {\n if (!node) return;\n ref.current = node;\n\n // Avoid transition mixups\n setInTransition(inTransition === undefined ? false : true);\n clearTimeout(blockTimeout);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n blockTimeout = setTimeout(() => setInTransition(false), 360);\n\n // Calculate new content bounds (always allowed for route changes)\n updateBounds(node);\n },\n [open, inTransition],\n );\n\n // Update layout on chain/network switch to avoid clipping\n const { chain } = useAccount();\n const { switchChain } = useSwitchChain();\n\n const ref = useRef<any>(null);\n useEffect(() => {\n // Skip triggerResize updates during opening animation to prevent mid-animation dimension changes\n if (isOpeningAnimation.current) return;\n if (ref.current) updateBounds(ref.current);\n }, [chain, switchChain, mobile, context.options, context.resize]);\n\n useEffect(() => {\n if (!mounted) {\n setDimensions({\n width: undefined,\n height: undefined,\n });\n return;\n }\n\n const listener = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && onClose) onClose();\n };\n document.addEventListener(\"keydown\", listener);\n return () => {\n document.removeEventListener(\"keydown\", listener);\n };\n }, [mounted, onClose]);\n\n const dimensionsCSS = {\n \"--height\": dimensions.height,\n \"--width\": dimensions.width,\n } as React.CSSProperties;\n\n // Show \"Scan with phone\" title for wallets with deeplinks (unique payment options)\n const hasDeeplink = wallet && wallet.getDaimoPayDeeplink;\n const shouldShowWalletQRCodeOnDesktop =\n isExternalWallet(wallet) || hasDeeplink;\n\n function getHeading() {\n const payWithString = flattenChildren(locales.payWith).join(\"\");\n switch (context.route) {\n case ROUTES.ABOUT:\n return locales.aboutScreen_heading;\n case ROUTES.CONNECT:\n if (shouldShowWalletQRCodeOnDesktop) {\n return locales.scanWithPhone;\n } else {\n return walletInfo?.name;\n }\n case ROUTES.SELECT_EXCHANGE:\n return locales.selectExchange;\n case ROUTES.SOLANA_CONNECTOR:\n return context.solanaConnector ?? locales.solanaWallet;\n case ROUTES.CONNECTORS:\n return locales.connectorsScreen_heading;\n case ROUTES.MOBILECONNECTORS:\n return locales.mobileConnectorsScreen_heading;\n case ROUTES.ONBOARDING:\n return locales.onboardingScreen_heading;\n case ROUTES.SWITCHNETWORKS:\n return locales.switchNetworkScreen_heading;\n case ROUTES.SELECT_METHOD:\n case ROUTES.SELECT_TOKEN:\n return order?.metadata.intent;\n case ROUTES.SOLANA_PAY_WITH_TOKEN:\n if (!selectedSolanaTokenOption) return undefined;\n return `${payWithString} ${selectedSolanaTokenOption.required.token.symbol}`;\n case ROUTES.WAITING_EXTERNAL:\n if (\n selectedExternalOption &&\n shouldShowExternalQRCodeOnDesktop(selectedExternalOption.id) &&\n !mobile\n ) {\n return locales.scanWithPhone;\n }\n return selectedExternalOption?.cta;\n case ROUTES.SELECT_DEPOSIT_ADDRESS_CHAIN:\n return locales.selectChain;\n case ROUTES.WAITING_DEPOSIT_ADDRESS:\n if (paymentState === \"warning\") return locales.leaveSession;\n if (!selectedDepositAddressOption) return undefined;\n return `${payWithString} ${selectedDepositAddressOption.id}`;\n case ROUTES.SELECT_ZKP2P:\n return locales.selectApp;\n case ROUTES.SELECT_AMOUNT:\n case ROUTES.SELECT_EXTERNAL_AMOUNT:\n case ROUTES.SELECT_DEPOSIT_ADDRESS_AMOUNT:\n case ROUTES.SOLANA_SELECT_AMOUNT:\n case ROUTES.SELECT_WALLET_AMOUNT:\n return locales.selectAmount;\n case ROUTES.PAY_WITH_TOKEN:\n if (selectedTokenOption == null) return undefined;\n\n const chainName = getChainName(\n selectedTokenOption.balance.token.chainId,\n );\n return `${payWithString} ${chainName} ${selectedTokenOption.balance.token.symbol}`;\n case ROUTES.CONFIRMATION:\n return locales.paymentSuccessful;\n case ROUTES.ERROR:\n return locales.error;\n case ROUTES.SELECT_WALLET_CHAIN:\n return locales.selectChain;\n }\n }\n\n const Content = (\n <ResetContainer\n $useTheme={demo?.theme ?? themeContext.theme}\n $useMode={demo?.mode ?? themeContext.mode}\n $customTheme={demo?.customTheme ?? themeContext.customTheme}\n >\n <ModalContainer\n role=\"dialog\"\n style={{\n pointerEvents: rendered ? \"auto\" : \"none\",\n position: positionInside ? \"absolute\" : undefined,\n }}\n >\n {!inline && (\n <BackgroundOverlay\n $active={rendered}\n onClick={onClose}\n $blur={context.options?.overlayBlur}\n />\n )}\n <Container\n style={dimensionsCSS}\n initial={false}\n // transition={{\n // ease: [0.2555, 0.1111, 0.2555, 1.0001],\n // duration: !positionInside && state !== 'entered' ? 0 : 0.24,\n // }}\n >\n <div\n style={{\n pointerEvents: inTransition ? \"all\" : \"none\", // Block interaction while transitioning\n position: \"absolute\",\n top: 0,\n bottom: 0,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"var(--width)\",\n zIndex: 9,\n transition: \"width 200ms ease\",\n }}\n />\n <BoxContainer className={`${rendered && \"active\"}`}>\n <AnimatePresence initial={false}>\n {context.options?.disclaimer &&\n context.route === ROUTES.CONNECTORS && (\n <DisclaimerBackground\n initial={{\n opacity: 0,\n }}\n animate={{\n opacity: 1,\n }}\n exit={{ opacity: 0 }}\n transition={{\n delay: 0,\n duration: 0.2,\n ease: [0.25, 0.1, 0.25, 1.0],\n }}\n >\n <Disclaimer>\n <div>{context.options?.disclaimer}</div>\n </Disclaimer>\n </DisclaimerBackground>\n )}\n </AnimatePresence>\n <AnimatePresence initial={false}>\n {context.errorMessage && (\n <ErrorMessage\n initial={{ y: \"10%\", x: \"-50%\" }}\n animate={{ y: \"-100%\" }}\n exit={{ y: \"100%\" }}\n transition={{ duration: 0.2, ease: \"easeInOut\" }}\n >\n <span>{context.errorMessage}</span>\n <div\n onClick={() => context.displayError(null)}\n style={{\n position: \"absolute\",\n right: 24,\n top: 24,\n cursor: \"pointer\",\n }}\n >\n <CloseIcon />\n </div>\n </ErrorMessage>\n )}\n </AnimatePresence>\n <ControllerContainer>\n {onClose && (\n <CloseButton\n aria-label={flattenChildren(locales.close).toString()}\n onClick={onClose}\n >\n <CloseIcon />\n </CloseButton>\n )}\n <div\n style={{\n position: \"absolute\",\n top: 23,\n left: 20,\n width: 32,\n height: 32,\n }}\n >\n <AnimatePresence>\n {onBack ? (\n <BackButton\n disabled={inTransition}\n aria-label={flattenChildren(locales.back).toString()}\n key=\"backButton\"\n onClick={onBack}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{\n duration: mobile ? 0 : 0.1,\n delay: mobile ? 0.01 : 0,\n }}\n >\n <BackIcon />\n </BackButton>\n ) : (\n onInfo &&\n !context.options?.hideQuestionMarkCTA && (\n <InfoButton\n disabled={inTransition}\n aria-label={flattenChildren(\n locales.moreInformation,\n ).toString()}\n key=\"infoButton\"\n onClick={onInfo}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{\n duration: mobile ? 0 : 0.1,\n delay: mobile ? 0.01 : 0,\n }}\n >\n <InfoIcon />\n </InfoButton>\n )\n )}\n </AnimatePresence>\n </div>\n </ControllerContainer>\n\n <ModalHeading>\n <AnimatePresence>\n <motion.div\n style={{\n position: \"absolute\",\n top: 0,\n bottom: 0,\n left: 52,\n right: 52,\n display: \"flex\",\n //alignItems: 'center',\n justifyContent: \"center\",\n }}\n key={`${context.route}`}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{\n duration: mobile ? 0 : 0.17,\n delay: mobile ? 0.01 : 0,\n }}\n >\n <FitText>{getHeading()}</FitText>\n </motion.div>\n </AnimatePresence>\n </ModalHeading>\n\n <InnerContainer>\n {Object.keys(pages).map((key) => (\n <Page\n key={key}\n open={key === pageId}\n initial={!positionInside && state !== \"entered\"}\n enterAnim={\n key === pageId\n ? currentDepth > prevDepth\n ? \"active-scale-up\"\n : \"active\"\n : \"\"\n }\n exitAnim={\n key !== pageId\n ? currentDepth < prevDepth\n ? \"exit-scale-down\"\n : \"exit\"\n : \"\"\n }\n >\n <PageContents\n key={`inner-${key}`}\n ref={contentRef}\n style={{\n pointerEvents:\n key === pageId && rendered ? \"auto\" : \"none\",\n }}\n >\n {pages[key]}\n </PageContents>\n </Page>\n ))}\n </InnerContainer>\n </BoxContainer>\n </Container>\n </ModalContainer>\n </ResetContainer>\n );\n return (\n <>\n {mounted && (\n <>\n {positionInside ? (\n Content\n ) : (\n <>\n {\n <Portal>\n <FocusTrap>{Content}</FocusTrap>\n </Portal>\n }\n </>\n )}\n </>\n )}\n </>\n );\n};\n\ntype PageProps = {\n children?: React.ReactNode;\n open?: boolean;\n initial: boolean;\n enterAnim?: string;\n exitAnim?: string;\n};\n\nconst Page: React.FC<PageProps> = ({\n children,\n open,\n initial,\n enterAnim,\n exitAnim,\n}) => {\n const [state, setOpen] = useTransition({\n timeout: 400,\n preEnter: true,\n initialEntered: open,\n mountOnEnter: true,\n unmountOnExit: true,\n });\n const mounted = !(state === \"exited\" || state === \"unmounted\");\n const rendered = state === \"preEnter\" || state !== \"exiting\";\n\n useEffect(() => {\n setOpen(open);\n }, [open]);\n\n if (!mounted) return null;\n\n return (\n <PageContainer\n className={`${rendered ? enterAnim : exitAnim}`}\n style={{\n animationDuration: initial ? \"0ms\" : undefined,\n animationDelay: initial ? \"0ms\" : undefined,\n }}\n >\n {children}\n </PageContainer>\n );\n};\n\nexport const OrDivider = ({ children }: { children?: React.ReactNode }) => {\n const locales = useLocales();\n return (\n <TextWithHr>\n <span>{children ?? locales.or}</span>\n </TextWithHr>\n );\n};\n\nexport default Modal;\n"],"names":[],"mappings":"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"}
|
|
@@ -31,7 +31,7 @@ const WaitingExternal = () => {
|
|
|
31
31
|
if (!selectedExternalOption) return;
|
|
32
32
|
payWithExternal(selectedExternalOption.id).then((url) => {
|
|
33
33
|
setExternalURL(url);
|
|
34
|
-
if (!shouldShowExternalQRCodeOnDesktop) {
|
|
34
|
+
if (!shouldShowExternalQRCodeOnDesktop(selectedExternalOption.id)) {
|
|
35
35
|
openExternalWindow(url);
|
|
36
36
|
}
|
|
37
37
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../src/components/Pages/WaitingExternal/index.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { useDaimoPay } from \"../../../hooks/useDaimoPay\";\nimport { usePayContext } from \"../../../hooks/usePayContext\";\n\nimport {\n ModalBody,\n ModalContent,\n ModalH1,\n PageContent,\n} from \"../../Common/Modal/styles\";\n\nimport {\n ExternalPaymentOptions,\n shouldShowExternalQRCodeOnDesktop,\n} from \"@daimo/pay-common\";\nimport { ExternalLinkIcon } from \"../../../assets/icons\";\nimport useIsMobile from \"../../../hooks/useIsMobile\";\nimport useLocales from \"../../../hooks/useLocales\";\nimport styled from \"../../../styles/styled\";\nimport Button from \"../../Common/Button\";\nimport ConnectWithQRCode from \"../../DaimoPayModal/ConnectWithQRCode\";\nimport ExternalPaymentSpinner from \"../../Spinners/ExternalPaymentSpinner\";\n\nconst WaitingExternal: React.FC = () => {\n const context = usePayContext();\n const { triggerResize, paymentState } = context;\n const { isMobile } = useIsMobile();\n const locales = useLocales();\n const { selectedExternalOption, payWithExternal, paymentWaitingMessage } =\n paymentState;\n const { order } = useDaimoPay();\n\n let isCoinbase = false;\n let isBinance = false;\n if (selectedExternalOption) {\n isCoinbase = selectedExternalOption.id === ExternalPaymentOptions.Coinbase;\n isBinance = selectedExternalOption.id === ExternalPaymentOptions.Binance;\n }\n\n const [externalURL, setExternalURL] = useState<string | null>(null);\n const [isRegenerating, setIsRegenerating] = useState(false);\n\n useEffect(() => {\n if (!selectedExternalOption) return;\n payWithExternal(selectedExternalOption.id).then((url) => {\n setExternalURL(url);\n if (!shouldShowExternalQRCodeOnDesktop) {\n openExternalWindow(url);\n }\n });\n }, [selectedExternalOption]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const openExternalWindow = (url: string) => {\n if (!isCoinbase || isMobile) {\n // for non-exchange apps: open in a new tab\n window.open(url, \"_blank\");\n } else {\n // for Coinbase: open in a popup window\n // in portrait mode in the center of the screen\n let width = 500;\n let height = 700;\n const left = Math.max(\n 0,\n Math.floor((window.innerWidth - width) / 2) + window.screenX,\n );\n const top = Math.max(\n 0,\n Math.floor((window.innerHeight - height) / 2) + window.screenY,\n );\n\n window.open(\n url,\n \"popupWindow\",\n `width=${width},height=${height},left=${left},top=${top},scrollbars=yes`,\n );\n }\n };\n\n const regenerateOrder = async () => {\n if (!selectedExternalOption) return;\n\n setIsRegenerating(true);\n setExternalURL(null);\n try {\n payWithExternal(selectedExternalOption.id).then((url) => {\n setExternalURL(url);\n setIsRegenerating(false);\n });\n } catch (error) {\n console.error(\"failed to regenerate order:\", error);\n }\n };\n\n const waitingMessageLength = paymentWaitingMessage?.length;\n\n useEffect(() => {\n triggerResize();\n }, [waitingMessageLength, externalURL]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (!selectedExternalOption) {\n return <PageContent></PageContent>;\n }\n\n return shouldShowExternalQRCodeOnDesktop(selectedExternalOption.id) &&\n !isMobile ? (\n <>\n <ConnectWithQRCode externalUrl={externalURL ?? \"\"} />\n {isBinance && paymentWaitingMessage && !isRegenerating && (\n <RegenerateContainer>\n <RegenerateLink\n as=\"button\"\n onClick={regenerateOrder}\n disabled={isRegenerating}\n >\n <span>\n {locales.notWorking}{\" \"}\n <Underline>{locales.regenerateOrder}</Underline>\n </span>\n </RegenerateLink>\n </RegenerateContainer>\n )}\n </>\n ) : (\n <PageContent>\n <ExternalPaymentSpinner\n logoURI={selectedExternalOption.logoURI}\n logoShape={selectedExternalOption.logoShape}\n />\n <ModalContent style={{ marginLeft: 24, marginRight: 24 }}>\n <ModalH1>{locales.waitingForPayment}</ModalH1>\n {paymentWaitingMessage && (\n <ModalBody style={{ marginTop: 12, marginBottom: 12 }}>\n {paymentWaitingMessage}\n </ModalBody>\n )}\n </ModalContent>\n <Button\n icon={<ExternalLinkIcon />}\n onClick={() => {\n if (externalURL) {\n openExternalWindow(externalURL);\n }\n }}\n >\n {selectedExternalOption.cta}\n </Button>\n {isBinance && paymentWaitingMessage && (\n <RegenerateContainer>\n <RegenerateLink\n as=\"button\"\n onClick={regenerateOrder}\n disabled={isRegenerating}\n >\n <span>\n {isRegenerating ? (\n <>{locales.generatingNewOrder}</>\n ) : (\n <>\n {locales.notWorking}{\" \"}\n <Underline>{locales.regenerateOrder}</Underline>\n </>\n )}\n </span>\n </RegenerateLink>\n </RegenerateContainer>\n )}\n </PageContent>\n );\n};\n\nconst RegenerateContainer = styled.div`\n text-align: center;\n margin-top: 16px;\n margin-bottom: -4px;\n`;\n\nconst RegenerateLink = styled.a`\n appearance: none;\n user-select: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n height: 42px;\n padding: 0 16px;\n border-radius: 6px;\n border: none;\n background: none;\n color: var(--ck-body-color-muted);\n text-decoration-color: var(--ck-body-color-muted);\n font-size: 15px;\n line-height: 18px;\n font-weight: 400;\n cursor: pointer;\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n span {\n opacity: 1;\n transition: opacity 300ms ease;\n }\n`;\n\nconst Underline = styled.span`\n text-underline-offset: 2px;\n text-decoration: underline;\n`;\n\nexport default WaitingExternal;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/components/Pages/WaitingExternal/index.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { useDaimoPay } from \"../../../hooks/useDaimoPay\";\nimport { usePayContext } from \"../../../hooks/usePayContext\";\n\nimport {\n ModalBody,\n ModalContent,\n ModalH1,\n PageContent,\n} from \"../../Common/Modal/styles\";\n\nimport {\n ExternalPaymentOptions,\n shouldShowExternalQRCodeOnDesktop,\n} from \"@daimo/pay-common\";\nimport { ExternalLinkIcon } from \"../../../assets/icons\";\nimport useIsMobile from \"../../../hooks/useIsMobile\";\nimport useLocales from \"../../../hooks/useLocales\";\nimport styled from \"../../../styles/styled\";\nimport Button from \"../../Common/Button\";\nimport ConnectWithQRCode from \"../../DaimoPayModal/ConnectWithQRCode\";\nimport ExternalPaymentSpinner from \"../../Spinners/ExternalPaymentSpinner\";\n\nconst WaitingExternal: React.FC = () => {\n const context = usePayContext();\n const { triggerResize, paymentState } = context;\n const { isMobile } = useIsMobile();\n const locales = useLocales();\n const { selectedExternalOption, payWithExternal, paymentWaitingMessage } =\n paymentState;\n const { order } = useDaimoPay();\n\n let isCoinbase = false;\n let isBinance = false;\n if (selectedExternalOption) {\n isCoinbase = selectedExternalOption.id === ExternalPaymentOptions.Coinbase;\n isBinance = selectedExternalOption.id === ExternalPaymentOptions.Binance;\n }\n\n const [externalURL, setExternalURL] = useState<string | null>(null);\n const [isRegenerating, setIsRegenerating] = useState(false);\n\n useEffect(() => {\n if (!selectedExternalOption) return;\n payWithExternal(selectedExternalOption.id).then((url) => {\n setExternalURL(url);\n if (!shouldShowExternalQRCodeOnDesktop(selectedExternalOption.id)) {\n openExternalWindow(url);\n }\n });\n }, [selectedExternalOption]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const openExternalWindow = (url: string) => {\n if (!isCoinbase || isMobile) {\n // for non-exchange apps: open in a new tab\n window.open(url, \"_blank\");\n } else {\n // for Coinbase: open in a popup window\n // in portrait mode in the center of the screen\n let width = 500;\n let height = 700;\n const left = Math.max(\n 0,\n Math.floor((window.innerWidth - width) / 2) + window.screenX,\n );\n const top = Math.max(\n 0,\n Math.floor((window.innerHeight - height) / 2) + window.screenY,\n );\n\n window.open(\n url,\n \"popupWindow\",\n `width=${width},height=${height},left=${left},top=${top},scrollbars=yes`,\n );\n }\n };\n\n const regenerateOrder = async () => {\n if (!selectedExternalOption) return;\n\n setIsRegenerating(true);\n setExternalURL(null);\n try {\n payWithExternal(selectedExternalOption.id).then((url) => {\n setExternalURL(url);\n setIsRegenerating(false);\n });\n } catch (error) {\n console.error(\"failed to regenerate order:\", error);\n }\n };\n\n const waitingMessageLength = paymentWaitingMessage?.length;\n\n useEffect(() => {\n triggerResize();\n }, [waitingMessageLength, externalURL]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (!selectedExternalOption) {\n return <PageContent></PageContent>;\n }\n\n return shouldShowExternalQRCodeOnDesktop(selectedExternalOption.id) &&\n !isMobile ? (\n <>\n <ConnectWithQRCode externalUrl={externalURL ?? \"\"} />\n {isBinance && paymentWaitingMessage && !isRegenerating && (\n <RegenerateContainer>\n <RegenerateLink\n as=\"button\"\n onClick={regenerateOrder}\n disabled={isRegenerating}\n >\n <span>\n {locales.notWorking}{\" \"}\n <Underline>{locales.regenerateOrder}</Underline>\n </span>\n </RegenerateLink>\n </RegenerateContainer>\n )}\n </>\n ) : (\n <PageContent>\n <ExternalPaymentSpinner\n logoURI={selectedExternalOption.logoURI}\n logoShape={selectedExternalOption.logoShape}\n />\n <ModalContent style={{ marginLeft: 24, marginRight: 24 }}>\n <ModalH1>{locales.waitingForPayment}</ModalH1>\n {paymentWaitingMessage && (\n <ModalBody style={{ marginTop: 12, marginBottom: 12 }}>\n {paymentWaitingMessage}\n </ModalBody>\n )}\n </ModalContent>\n <Button\n icon={<ExternalLinkIcon />}\n onClick={() => {\n if (externalURL) {\n openExternalWindow(externalURL);\n }\n }}\n >\n {selectedExternalOption.cta}\n </Button>\n {isBinance && paymentWaitingMessage && (\n <RegenerateContainer>\n <RegenerateLink\n as=\"button\"\n onClick={regenerateOrder}\n disabled={isRegenerating}\n >\n <span>\n {isRegenerating ? (\n <>{locales.generatingNewOrder}</>\n ) : (\n <>\n {locales.notWorking}{\" \"}\n <Underline>{locales.regenerateOrder}</Underline>\n </>\n )}\n </span>\n </RegenerateLink>\n </RegenerateContainer>\n )}\n </PageContent>\n );\n};\n\nconst RegenerateContainer = styled.div`\n text-align: center;\n margin-top: 16px;\n margin-bottom: -4px;\n`;\n\nconst RegenerateLink = styled.a`\n appearance: none;\n user-select: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n height: 42px;\n padding: 0 16px;\n border-radius: 6px;\n border: none;\n background: none;\n color: var(--ck-body-color-muted);\n text-decoration-color: var(--ck-body-color-muted);\n font-size: 15px;\n line-height: 18px;\n font-weight: 400;\n cursor: pointer;\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n span {\n opacity: 1;\n transition: opacity 300ms ease;\n }\n`;\n\nconst Underline = styled.span`\n text-underline-offset: 2px;\n text-decoration: underline;\n`;\n\nexport default WaitingExternal;\n"],"names":[],"mappings":"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"}
|
|
@@ -62,9 +62,11 @@ function getEvmTokenOptions(options, isDepositFlow, setSelectedTokenOption, setR
|
|
|
62
62
|
const chainName = getChainName(option.balance.token.chainId);
|
|
63
63
|
const titlePrice = isDepositFlow ? formatUsd(option.balance.usd) : roundTokenAmount(option.required.amount, option.required.token);
|
|
64
64
|
const title = `${titlePrice} ${option.balance.token.symbol} ${onString} ${chainName}`;
|
|
65
|
+
const isBelowMinimum = isDepositFlow && option.balance.usd < option.minimumRequired.usd;
|
|
66
|
+
const belowMinimumReason = `Minimum ${formatUsd(option.minimumRequired.usd, "up")}`;
|
|
65
67
|
const balanceStr = `${roundTokenAmount(option.balance.amount, option.balance.token)} ${option.balance.token.symbol}`;
|
|
66
|
-
let subtitle = option.disabledReason ?? `${isDepositFlow ? "" : "Balance: "}${balanceStr}`;
|
|
67
|
-
const disabled = option.disabledReason != null;
|
|
68
|
+
let subtitle = option.disabledReason ?? (isBelowMinimum ? belowMinimumReason : null) ?? `${isDepositFlow ? "" : "Balance: "}${balanceStr}`;
|
|
69
|
+
const disabled = option.disabledReason != null || isBelowMinimum;
|
|
68
70
|
if (nonPassthroughToken != null) {
|
|
69
71
|
const defaultSym = nonPassthroughToken.symbol;
|
|
70
72
|
const optSym = option.balance.token.symbol;
|
|
@@ -110,9 +112,11 @@ function getSolanaTokenOptions(options, isDepositFlow, setSelectedSolanaTokenOpt
|
|
|
110
112
|
return options.map((option) => {
|
|
111
113
|
const titlePrice = isDepositFlow ? formatUsd(option.balance.usd) : roundTokenAmount(option.required.amount, option.required.token);
|
|
112
114
|
const title = `${titlePrice} ${option.balance.token.symbol} ${onString} Solana`;
|
|
115
|
+
const isBelowMinimum = isDepositFlow && option.balance.usd < option.minimumRequired.usd;
|
|
116
|
+
const belowMinimumReason = `Minimum ${formatUsd(option.minimumRequired.usd, "up")}`;
|
|
113
117
|
const balanceStr = `${roundTokenAmount(option.balance.amount, option.balance.token)} ${option.balance.token.symbol}`;
|
|
114
|
-
const subtitle = option.disabledReason ?? `${isDepositFlow ? "" : "Balance: "}${balanceStr}`;
|
|
115
|
-
const disabled = option.disabledReason != null;
|
|
118
|
+
const subtitle = option.disabledReason ?? (isBelowMinimum ? belowMinimumReason : null) ?? `${isDepositFlow ? "" : "Balance: "}${balanceStr}`;
|
|
119
|
+
const disabled = option.disabledReason != null || isBelowMinimum;
|
|
116
120
|
return {
|
|
117
121
|
id: getDaimoTokenKey(option.balance.token),
|
|
118
122
|
sortValue: option.balance.usd,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTokenOptions.js","sources":["../../../src/hooks/useTokenOptions.tsx"],"sourcesContent":["/// Gets token options when paying from a connected wallet. Supports both EVM\n\nimport {\n DaimoPayToken,\n getChainName,\n Token,\n WalletPaymentOption,\n} from \"@daimo/pay-common\";\nimport { Option } from \"../components/Common/OptionsList\";\nimport TokenChainLogo from \"../components/Common/TokenChainLogo\";\nimport { ROUTES } from \"../constants/routes\";\nimport { flattenChildren } from \"../utils\";\nimport { formatUsd, roundTokenAmount } from \"../utils/format\";\nimport { useDaimoPay } from \"./useDaimoPay\";\nimport useLocales from \"./useLocales\";\nimport { usePayContext } from \"./usePayContext\";\n\n/// and Solana tokens. See OptionsList.\nexport function useTokenOptions(mode: \"evm\" | \"solana\" | \"all\"): {\n optionsList: Option[];\n isLoading: boolean;\n} {\n const { setRoute, paymentState } = usePayContext();\n const {\n isDepositFlow,\n walletPaymentOptions,\n solanaPaymentOptions,\n setSelectedTokenOption,\n setSelectedSolanaTokenOption,\n } = paymentState;\n\n // Get translations once and pass down to helpers to avoid violating\n // the Rules-of-Hooks (hooks can only be called inside React components\n // or custom hooks).\n const locales = useLocales();\n const onString = flattenChildren(locales.on).join(\"\");\n\n // HACK: special handling for portfolio deposits\n const pay = useDaimoPay();\n const isPassthrough = !!pay.order?.metadata.payer?.passthroughTokens?.length;\n const nonPassthroughToken = isPassthrough\n ? pay.order?.destFinalCallTokenAmount.token\n : undefined;\n\n let optionsList: Option[] = [];\n let isLoading = false;\n if ([\"evm\", \"all\"].includes(mode)) {\n optionsList.push(\n ...getEvmTokenOptions(\n walletPaymentOptions.options ?? [],\n isDepositFlow,\n setSelectedTokenOption,\n setRoute,\n onString,\n nonPassthroughToken,\n ),\n );\n isLoading ||= walletPaymentOptions.isLoading;\n }\n if ([\"solana\", \"all\"].includes(mode)) {\n optionsList.push(\n ...getSolanaTokenOptions(\n solanaPaymentOptions.options ?? [],\n isDepositFlow,\n setSelectedSolanaTokenOption,\n setRoute,\n onString,\n ),\n );\n isLoading ||= solanaPaymentOptions.isLoading;\n }\n\n optionsList.sort((a, b) => {\n const dDisabled = (a.disabled ? 1 : 0) - (b.disabled ? 1 : 0);\n if (dDisabled !== 0) return dDisabled;\n const dSort = (b.sortValue ?? 0) - (a.sortValue ?? 0);\n return dSort;\n });\n\n return { optionsList, isLoading };\n}\n\nfunction getEvmTokenOptions(\n options: WalletPaymentOption[],\n isDepositFlow: boolean,\n setSelectedTokenOption: (option: WalletPaymentOption) => void,\n setRoute: (route: ROUTES, meta?: any) => void,\n onString: string,\n nonPassthroughToken?: Token,\n) {\n return options.map((option) => {\n const chainName = getChainName(option.balance.token.chainId);\n const titlePrice = isDepositFlow\n ? formatUsd(option.balance.usd)\n : roundTokenAmount(option.required.amount, option.required.token);\n const title = `${titlePrice} ${option.balance.token.symbol} ${onString} ${chainName}`;\n\n const balanceStr = `${roundTokenAmount(option.balance.amount, option.balance.token)} ${option.balance.token.symbol}`;\n let subtitle =\n option.disabledReason ??\n `${isDepositFlow ? \"\" : \"Balance: \"}${balanceStr}`;\n const disabled = option.disabledReason != null;\n\n // HACK: special handling for portfolio deposits\n if (nonPassthroughToken != null) {\n const defaultSym = nonPassthroughToken.symbol;\n const optSym = option.balance.token.symbol;\n if (option.passthroughAddress == null && optSym !== defaultSym) {\n subtitle = `Convert to ${defaultSym}`;\n } else {\n subtitle = `Deposit ${optSym}`;\n }\n }\n const sortValue =\n option.balance.usd + (option.passthroughAddress == null ? 0 : 1e9);\n\n return {\n id: getDaimoTokenKey(option.balance.token),\n sortValue,\n title,\n subtitle,\n icons: [\n <TokenChainLogo\n key={getDaimoTokenKey(option.balance.token)}\n token={option.balance.token}\n />,\n ],\n onClick: () => {\n setSelectedTokenOption(option);\n const meta = {\n event: \"click-token\",\n tokenSymbol: option.balance.token.symbol,\n chainId: option.balance.token.chainId,\n };\n if (isDepositFlow) {\n setRoute(ROUTES.SELECT_AMOUNT, meta);\n } else {\n setRoute(ROUTES.PAY_WITH_TOKEN, meta);\n }\n },\n disabled,\n };\n });\n}\n\nfunction getSolanaTokenOptions(\n options: WalletPaymentOption[],\n isDepositFlow: boolean,\n setSelectedSolanaTokenOption: (option: WalletPaymentOption) => void,\n setRoute: (route: ROUTES, meta?: any) => void,\n onString: string,\n) {\n return options.map((option) => {\n const titlePrice = isDepositFlow\n ? formatUsd(option.balance.usd)\n : roundTokenAmount(option.required.amount, option.required.token);\n const title = `${titlePrice} ${option.balance.token.symbol} ${onString} Solana`;\n const balanceStr = `${roundTokenAmount(option.balance.amount, option.balance.token)} ${option.balance.token.symbol}`;\n const subtitle =\n option.disabledReason ??\n `${isDepositFlow ? \"\" : \"Balance: \"}${balanceStr}`;\n const disabled = option.disabledReason != null;\n\n return {\n id: getDaimoTokenKey(option.balance.token),\n sortValue: option.balance.usd,\n title,\n subtitle,\n icons: [\n <TokenChainLogo\n key={getDaimoTokenKey(option.balance.token)}\n token={option.balance.token}\n />,\n ],\n onClick: () => {\n setSelectedSolanaTokenOption(option);\n const meta = {\n event: \"click-solana-token\",\n tokenSymbol: option.balance.token.symbol,\n chainId: option.balance.token.chainId,\n };\n if (isDepositFlow) {\n setRoute(ROUTES.SOLANA_SELECT_AMOUNT, meta);\n } else {\n setRoute(ROUTES.SOLANA_PAY_WITH_TOKEN, meta);\n }\n },\n disabled,\n };\n });\n}\n\nfunction getDaimoTokenKey(token: DaimoPayToken) {\n return `${token.chainId}-${token.token}`;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useTokenOptions.js","sources":["../../../src/hooks/useTokenOptions.tsx"],"sourcesContent":["/// Gets token options when paying from a connected wallet. Supports both EVM\n\nimport {\n DaimoPayToken,\n getChainName,\n Token,\n WalletPaymentOption,\n} from \"@daimo/pay-common\";\nimport { Option } from \"../components/Common/OptionsList\";\nimport TokenChainLogo from \"../components/Common/TokenChainLogo\";\nimport { ROUTES } from \"../constants/routes\";\nimport { flattenChildren } from \"../utils\";\nimport { formatUsd, roundTokenAmount } from \"../utils/format\";\nimport { useDaimoPay } from \"./useDaimoPay\";\nimport useLocales from \"./useLocales\";\nimport { usePayContext } from \"./usePayContext\";\n\n/// and Solana tokens. See OptionsList.\nexport function useTokenOptions(mode: \"evm\" | \"solana\" | \"all\"): {\n optionsList: Option[];\n isLoading: boolean;\n} {\n const { setRoute, paymentState } = usePayContext();\n const {\n isDepositFlow,\n walletPaymentOptions,\n solanaPaymentOptions,\n setSelectedTokenOption,\n setSelectedSolanaTokenOption,\n } = paymentState;\n\n // Get translations once and pass down to helpers to avoid violating\n // the Rules-of-Hooks (hooks can only be called inside React components\n // or custom hooks).\n const locales = useLocales();\n const onString = flattenChildren(locales.on).join(\"\");\n\n // HACK: special handling for portfolio deposits\n const pay = useDaimoPay();\n const isPassthrough = !!pay.order?.metadata.payer?.passthroughTokens?.length;\n const nonPassthroughToken = isPassthrough\n ? pay.order?.destFinalCallTokenAmount.token\n : undefined;\n\n let optionsList: Option[] = [];\n let isLoading = false;\n if ([\"evm\", \"all\"].includes(mode)) {\n optionsList.push(\n ...getEvmTokenOptions(\n walletPaymentOptions.options ?? [],\n isDepositFlow,\n setSelectedTokenOption,\n setRoute,\n onString,\n nonPassthroughToken,\n ),\n );\n isLoading ||= walletPaymentOptions.isLoading;\n }\n if ([\"solana\", \"all\"].includes(mode)) {\n optionsList.push(\n ...getSolanaTokenOptions(\n solanaPaymentOptions.options ?? [],\n isDepositFlow,\n setSelectedSolanaTokenOption,\n setRoute,\n onString,\n ),\n );\n isLoading ||= solanaPaymentOptions.isLoading;\n }\n\n optionsList.sort((a, b) => {\n const dDisabled = (a.disabled ? 1 : 0) - (b.disabled ? 1 : 0);\n if (dDisabled !== 0) return dDisabled;\n const dSort = (b.sortValue ?? 0) - (a.sortValue ?? 0);\n return dSort;\n });\n\n return { optionsList, isLoading };\n}\n\nfunction getEvmTokenOptions(\n options: WalletPaymentOption[],\n isDepositFlow: boolean,\n setSelectedTokenOption: (option: WalletPaymentOption) => void,\n setRoute: (route: ROUTES, meta?: any) => void,\n onString: string,\n nonPassthroughToken?: Token,\n) {\n return options.map((option) => {\n const chainName = getChainName(option.balance.token.chainId);\n const titlePrice = isDepositFlow\n ? formatUsd(option.balance.usd)\n : roundTokenAmount(option.required.amount, option.required.token);\n const title = `${titlePrice} ${option.balance.token.symbol} ${onString} ${chainName}`;\n\n // In deposit mode, check if balance is under the minimum\n const isBelowMinimum =\n isDepositFlow && option.balance.usd < option.minimumRequired.usd;\n const belowMinimumReason = `Minimum ${formatUsd(option.minimumRequired.usd, \"up\")}`;\n\n const balanceStr = `${roundTokenAmount(option.balance.amount, option.balance.token)} ${option.balance.token.symbol}`;\n\n let subtitle =\n option.disabledReason ??\n (isBelowMinimum ? belowMinimumReason : null) ??\n `${isDepositFlow ? \"\" : \"Balance: \"}${balanceStr}`;\n const disabled = option.disabledReason != null || isBelowMinimum;\n\n // HACK: special handling for portfolio deposits\n if (nonPassthroughToken != null) {\n const defaultSym = nonPassthroughToken.symbol;\n const optSym = option.balance.token.symbol;\n if (option.passthroughAddress == null && optSym !== defaultSym) {\n subtitle = `Convert to ${defaultSym}`;\n } else {\n subtitle = `Deposit ${optSym}`;\n }\n }\n const sortValue =\n option.balance.usd + (option.passthroughAddress == null ? 0 : 1e9);\n\n return {\n id: getDaimoTokenKey(option.balance.token),\n sortValue,\n title,\n subtitle,\n icons: [\n <TokenChainLogo\n key={getDaimoTokenKey(option.balance.token)}\n token={option.balance.token}\n />,\n ],\n onClick: () => {\n setSelectedTokenOption(option);\n const meta = {\n event: \"click-token\",\n tokenSymbol: option.balance.token.symbol,\n chainId: option.balance.token.chainId,\n };\n if (isDepositFlow) {\n setRoute(ROUTES.SELECT_AMOUNT, meta);\n } else {\n setRoute(ROUTES.PAY_WITH_TOKEN, meta);\n }\n },\n disabled,\n };\n });\n}\n\nfunction getSolanaTokenOptions(\n options: WalletPaymentOption[],\n isDepositFlow: boolean,\n setSelectedSolanaTokenOption: (option: WalletPaymentOption) => void,\n setRoute: (route: ROUTES, meta?: any) => void,\n onString: string,\n) {\n return options.map((option) => {\n const titlePrice = isDepositFlow\n ? formatUsd(option.balance.usd)\n : roundTokenAmount(option.required.amount, option.required.token);\n const title = `${titlePrice} ${option.balance.token.symbol} ${onString} Solana`;\n\n // In deposit mode, check if balance is under the minimum\n const isBelowMinimum =\n isDepositFlow && option.balance.usd < option.minimumRequired.usd;\n const belowMinimumReason = `Minimum ${formatUsd(option.minimumRequired.usd, \"up\")}`;\n\n const balanceStr = `${roundTokenAmount(option.balance.amount, option.balance.token)} ${option.balance.token.symbol}`;\n\n const subtitle =\n option.disabledReason ??\n (isBelowMinimum ? belowMinimumReason : null) ??\n `${isDepositFlow ? \"\" : \"Balance: \"}${balanceStr}`;\n const disabled = option.disabledReason != null || isBelowMinimum;\n\n return {\n id: getDaimoTokenKey(option.balance.token),\n sortValue: option.balance.usd,\n title,\n subtitle,\n icons: [\n <TokenChainLogo\n key={getDaimoTokenKey(option.balance.token)}\n token={option.balance.token}\n />,\n ],\n onClick: () => {\n setSelectedSolanaTokenOption(option);\n const meta = {\n event: \"click-solana-token\",\n tokenSymbol: option.balance.token.symbol,\n chainId: option.balance.token.chainId,\n };\n if (isDepositFlow) {\n setRoute(ROUTES.SOLANA_SELECT_AMOUNT, meta);\n } else {\n setRoute(ROUTES.SOLANA_PAY_WITH_TOKEN, meta);\n }\n },\n disabled,\n };\n });\n}\n\nfunction getDaimoTokenKey(token: DaimoPayToken) {\n return `${token.chainId}-${token.token}`;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,9 @@ function roundTokenAmount(amount, token, round = "down") {
|
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
33
|
function roundTokenAmountUnits(amountUnits, token, round = "down") {
|
|
34
|
+
if (amountUnits === 0) {
|
|
35
|
+
return "0";
|
|
36
|
+
}
|
|
34
37
|
return roundDecimals(amountUnits, token.displayDecimals, round);
|
|
35
38
|
}
|
|
36
39
|
function usdToRoundedTokenAmount(usd, token, round = "down") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sources":["../../../src/utils/format.ts"],"sourcesContent":["import { BigIntStr, DaimoPayToken } from \"@daimo/pay-common\";\nimport { formatUnits } from \"viem\";\n\nexport const USD_DECIMALS = 2;\n\n/**\n * Round a number to a given number of decimal places\n *\n * @param round - The rounding strategy to use:\n * - \"up\": Always rounds up to the next decimal place (ceiling)\n * - \"down\": Always rounds down to the previous decimal place (floor)\n * - \"nearest\": Rounds to the nearest decimal place (standard rounding)\n */\nexport function roundDecimals(\n value: number,\n decimals: number,\n round: \"up\" | \"down\" | \"nearest\",\n): string {\n const factor = 10 ** decimals;\n const multiplied = value * factor;\n\n let rounded: number;\n if (round === \"up\") {\n rounded = Math.ceil(multiplied);\n } else if (round === \"down\") {\n rounded = Math.floor(multiplied);\n } else {\n rounded = Math.round(multiplied);\n }\n\n return (rounded / factor).toFixed(decimals);\n}\n\n/**\n * Format a number as a USD amount\n *\n * @param usd - The USD amount to format\n * @param round - The rounding strategy to use (\"up\", \"down\", or \"nearest\")\n * @returns The formatted USD amount\n */\nexport function formatUsd(\n usd: number,\n round: \"up\" | \"down\" | \"nearest\" = \"down\",\n): string {\n return new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }).format(Number(roundUsd(usd, round)));\n}\n\n/**\n * Round a USD amount to `USD_DECIMALS` precision\n */\nexport function roundUsd(\n usd: number,\n round: \"up\" | \"down\" | \"nearest\" = \"down\",\n): string {\n return roundDecimals(usd, USD_DECIMALS, round);\n}\n\n/**\n * Round a token amount to `displayDecimals` precision\n */\nexport function roundTokenAmount(\n amount: bigint | BigIntStr,\n token: DaimoPayToken,\n round: \"up\" | \"down\" | \"nearest\" = \"down\",\n): string {\n return roundDecimals(\n Number(formatUnits(BigInt(amount), token.decimals)),\n token.displayDecimals,\n round,\n );\n}\n\n/**\n * Round a token amount in units to `displayDecimals` precision\n */\nexport function roundTokenAmountUnits(\n amountUnits: number,\n token: DaimoPayToken,\n round: \"up\" | \"down\" | \"nearest\" = \"down\",\n): string {\n return roundDecimals(amountUnits, token.displayDecimals, round);\n}\n\n/**\n * Convert a USD amount to a token amount with `displayDecimals` precision\n *\n * @param usd - The USD amount to convert\n * @param token - The token to convert to\n * @param round - The rounding strategy to use (\"up\", \"down\", or \"nearest\")\n * @returns The token amount\n */\nexport function usdToRoundedTokenAmount(\n usd: number,\n token: DaimoPayToken,\n round: \"up\" | \"down\" | \"nearest\" = \"down\",\n): string {\n return roundTokenAmountUnits(usd / token.usd, token, round);\n}\n\n/**\n * Convert a token amount to a USD amount with `USD_DECIMALS` precision\n *\n * @param amount - The token amount to convert\n * @param token - The token to convert from\n * @param round - The rounding strategy to use (\"up\", \"down\", or \"nearest\")\n * @returns The formatted USD amount\n */\nexport function tokenAmountToRoundedUsd(\n amount: bigint | BigIntStr,\n token: DaimoPayToken,\n round: \"up\" | \"down\" | \"nearest\" = \"nearest\",\n): string {\n const amountUnits = formatUnits(BigInt(amount), token.decimals);\n return roundUsd(Number(amountUnits) * token.usd, round);\n}\n"],"names":[],"mappings":";;AAGO,MAAM,YAAe,GAAA,EAAA;AAUZ,SAAA,aAAA,CACd,KACA,EAAA,QAAA,EACA,KACQ,EAAA;AACR,EAAA,MAAM,SAAS,EAAM,IAAA,QAAA,CAAA;AACrB,EAAA,MAAM,aAAa,KAAQ,GAAA,MAAA,CAAA;AAE3B,EAAI,IAAA,OAAA,CAAA;AACJ,EAAA,IAAI,UAAU,IAAM,EAAA;AAClB,IAAU,OAAA,GAAA,IAAA,CAAK,KAAK,UAAU,CAAA,CAAA;AAAA,GAChC,MAAA,IAAW,UAAU,MAAQ,EAAA;AAC3B,IAAU,OAAA,GAAA,IAAA,CAAK,MAAM,UAAU,CAAA,CAAA;AAAA,GAC1B,MAAA;AACL,IAAU,OAAA,GAAA,IAAA,CAAK,MAAM,UAAU,CAAA,CAAA;AAAA,GACjC;AAEA,EAAQ,OAAA,CAAA,OAAA,GAAU,MAAQ,EAAA,OAAA,CAAQ,QAAQ,CAAA,CAAA;AAC5C,CAAA;AASgB,SAAA,SAAA,CACd,GACA,EAAA,KAAA,GAAmC,MAC3B,EAAA;AACR,EAAO,OAAA,IAAI,IAAK,CAAA,YAAA,CAAa,OAAS,EAAA;AAAA,IACpC,KAAO,EAAA,UAAA;AAAA,IACP,QAAU,EAAA,KAAA;AAAA,GACX,EAAE,MAAO,CAAA,MAAA,CAAO,SAAS,GAAK,EAAA,KAAK,CAAC,CAAC,CAAA,CAAA;AACxC,CAAA;AAKgB,SAAA,QAAA,CACd,GACA,EAAA,KAAA,GAAmC,MAC3B,EAAA;AACR,EAAO,OAAA,aAAA,CAAc,GAAK,EAAA,YAAA,EAAc,KAAK,CAAA,CAAA;AAC/C,CAAA;AAKO,SAAS,gBACd,CAAA,MAAA,EACA,KACA,EAAA,KAAA,GAAmC,MAC3B,EAAA;AACR,EAAO,OAAA,aAAA;AAAA,IACL,OAAO,WAAY,CAAA,MAAA,CAAO,MAAM,CAAG,EAAA,KAAA,CAAM,QAAQ,CAAC,CAAA;AAAA,IAClD,KAAM,CAAA,eAAA;AAAA,IACN,KAAA;AAAA,GACF,CAAA;AACF,CAAA;AAKO,SAAS,qBACd,CAAA,WAAA,EACA,KACA,EAAA,KAAA,GAAmC,MAC3B,EAAA;AACR,EAAA,OAAO,aAAc,CAAA,WAAA,EAAa,KAAM,CAAA,eAAA,EAAiB,KAAK,CAAA,CAAA;AAChE,CAAA;AAUO,SAAS,uBACd,CAAA,GAAA,EACA,KACA,EAAA,KAAA,GAAmC,MAC3B,EAAA;AACR,EAAA,OAAO,qBAAsB,CAAA,GAAA,GAAM,KAAM,CAAA,GAAA,EAAK,OAAO,KAAK,CAAA,CAAA;AAC5D,CAAA;AAUO,SAAS,uBACd,CAAA,MAAA,EACA,KACA,EAAA,KAAA,GAAmC,SAC3B,EAAA;AACR,EAAA,MAAM,cAAc,WAAY,CAAA,MAAA,CAAO,MAAM,CAAA,EAAG,MAAM,QAAQ,CAAA,CAAA;AAC9D,EAAA,OAAO,SAAS,MAAO,CAAA,WAAW,CAAI,GAAA,KAAA,CAAM,KAAK,KAAK,CAAA,CAAA;AACxD;;;;"}
|
|
1
|
+
{"version":3,"file":"format.js","sources":["../../../src/utils/format.ts"],"sourcesContent":["import { BigIntStr, DaimoPayToken } from \"@daimo/pay-common\";\nimport { formatUnits } from \"viem\";\n\nexport const USD_DECIMALS = 2;\n\n/**\n * Round a number to a given number of decimal places\n *\n * @param round - The rounding strategy to use:\n * - \"up\": Always rounds up to the next decimal place (ceiling)\n * - \"down\": Always rounds down to the previous decimal place (floor)\n * - \"nearest\": Rounds to the nearest decimal place (standard rounding)\n */\nexport function roundDecimals(\n value: number,\n decimals: number,\n round: \"up\" | \"down\" | \"nearest\",\n): string {\n const factor = 10 ** decimals;\n const multiplied = value * factor;\n\n let rounded: number;\n if (round === \"up\") {\n rounded = Math.ceil(multiplied);\n } else if (round === \"down\") {\n rounded = Math.floor(multiplied);\n } else {\n rounded = Math.round(multiplied);\n }\n\n return (rounded / factor).toFixed(decimals);\n}\n\n/**\n * Format a number as a USD amount\n *\n * @param usd - The USD amount to format\n * @param round - The rounding strategy to use (\"up\", \"down\", or \"nearest\")\n * @returns The formatted USD amount\n */\nexport function formatUsd(\n usd: number,\n round: \"up\" | \"down\" | \"nearest\" = \"down\",\n): string {\n return new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }).format(Number(roundUsd(usd, round)));\n}\n\n/**\n * Round a USD amount to `USD_DECIMALS` precision\n */\nexport function roundUsd(\n usd: number,\n round: \"up\" | \"down\" | \"nearest\" = \"down\",\n): string {\n return roundDecimals(usd, USD_DECIMALS, round);\n}\n\n/**\n * Round a token amount to `displayDecimals` precision\n */\nexport function roundTokenAmount(\n amount: bigint | BigIntStr,\n token: DaimoPayToken,\n round: \"up\" | \"down\" | \"nearest\" = \"down\",\n): string {\n return roundDecimals(\n Number(formatUnits(BigInt(amount), token.decimals)),\n token.displayDecimals,\n round,\n );\n}\n\n/**\n * Round a token amount in units to `displayDecimals` precision\n */\nexport function roundTokenAmountUnits(\n amountUnits: number,\n token: DaimoPayToken,\n round: \"up\" | \"down\" | \"nearest\" = \"down\",\n): string {\n if (amountUnits === 0) {\n return \"0\";\n }\n return roundDecimals(amountUnits, token.displayDecimals, round);\n}\n\n/**\n * Convert a USD amount to a token amount with `displayDecimals` precision\n *\n * @param usd - The USD amount to convert\n * @param token - The token to convert to\n * @param round - The rounding strategy to use (\"up\", \"down\", or \"nearest\")\n * @returns The token amount\n */\nexport function usdToRoundedTokenAmount(\n usd: number,\n token: DaimoPayToken,\n round: \"up\" | \"down\" | \"nearest\" = \"down\",\n): string {\n return roundTokenAmountUnits(usd / token.usd, token, round);\n}\n\n/**\n * Convert a token amount to a USD amount with `USD_DECIMALS` precision\n *\n * @param amount - The token amount to convert\n * @param token - The token to convert from\n * @param round - The rounding strategy to use (\"up\", \"down\", or \"nearest\")\n * @returns The formatted USD amount\n */\nexport function tokenAmountToRoundedUsd(\n amount: bigint | BigIntStr,\n token: DaimoPayToken,\n round: \"up\" | \"down\" | \"nearest\" = \"nearest\",\n): string {\n const amountUnits = formatUnits(BigInt(amount), token.decimals);\n return roundUsd(Number(amountUnits) * token.usd, round);\n}\n"],"names":[],"mappings":";;AAGO,MAAM,YAAe,GAAA,EAAA;AAUZ,SAAA,aAAA,CACd,KACA,EAAA,QAAA,EACA,KACQ,EAAA;AACR,EAAA,MAAM,SAAS,EAAM,IAAA,QAAA,CAAA;AACrB,EAAA,MAAM,aAAa,KAAQ,GAAA,MAAA,CAAA;AAE3B,EAAI,IAAA,OAAA,CAAA;AACJ,EAAA,IAAI,UAAU,IAAM,EAAA;AAClB,IAAU,OAAA,GAAA,IAAA,CAAK,KAAK,UAAU,CAAA,CAAA;AAAA,GAChC,MAAA,IAAW,UAAU,MAAQ,EAAA;AAC3B,IAAU,OAAA,GAAA,IAAA,CAAK,MAAM,UAAU,CAAA,CAAA;AAAA,GAC1B,MAAA;AACL,IAAU,OAAA,GAAA,IAAA,CAAK,MAAM,UAAU,CAAA,CAAA;AAAA,GACjC;AAEA,EAAQ,OAAA,CAAA,OAAA,GAAU,MAAQ,EAAA,OAAA,CAAQ,QAAQ,CAAA,CAAA;AAC5C,CAAA;AASgB,SAAA,SAAA,CACd,GACA,EAAA,KAAA,GAAmC,MAC3B,EAAA;AACR,EAAO,OAAA,IAAI,IAAK,CAAA,YAAA,CAAa,OAAS,EAAA;AAAA,IACpC,KAAO,EAAA,UAAA;AAAA,IACP,QAAU,EAAA,KAAA;AAAA,GACX,EAAE,MAAO,CAAA,MAAA,CAAO,SAAS,GAAK,EAAA,KAAK,CAAC,CAAC,CAAA,CAAA;AACxC,CAAA;AAKgB,SAAA,QAAA,CACd,GACA,EAAA,KAAA,GAAmC,MAC3B,EAAA;AACR,EAAO,OAAA,aAAA,CAAc,GAAK,EAAA,YAAA,EAAc,KAAK,CAAA,CAAA;AAC/C,CAAA;AAKO,SAAS,gBACd,CAAA,MAAA,EACA,KACA,EAAA,KAAA,GAAmC,MAC3B,EAAA;AACR,EAAO,OAAA,aAAA;AAAA,IACL,OAAO,WAAY,CAAA,MAAA,CAAO,MAAM,CAAG,EAAA,KAAA,CAAM,QAAQ,CAAC,CAAA;AAAA,IAClD,KAAM,CAAA,eAAA;AAAA,IACN,KAAA;AAAA,GACF,CAAA;AACF,CAAA;AAKO,SAAS,qBACd,CAAA,WAAA,EACA,KACA,EAAA,KAAA,GAAmC,MAC3B,EAAA;AACR,EAAA,IAAI,gBAAgB,CAAG,EAAA;AACrB,IAAO,OAAA,GAAA,CAAA;AAAA,GACT;AACA,EAAA,OAAO,aAAc,CAAA,WAAA,EAAa,KAAM,CAAA,eAAA,EAAiB,KAAK,CAAA,CAAA;AAChE,CAAA;AAUO,SAAS,uBACd,CAAA,GAAA,EACA,KACA,EAAA,KAAA,GAAmC,MAC3B,EAAA;AACR,EAAA,OAAO,qBAAsB,CAAA,GAAA,GAAM,KAAM,CAAA,GAAA,EAAK,OAAO,KAAK,CAAA,CAAA;AAC5D,CAAA;AAUO,SAAS,uBACd,CAAA,MAAA,EACA,KACA,EAAA,KAAA,GAAmC,SAC3B,EAAA;AACR,EAAA,MAAM,cAAc,WAAY,CAAA,MAAA,CAAO,MAAM,CAAA,EAAG,MAAM,QAAQ,CAAA,CAAA;AAC9D,EAAA,OAAO,SAAS,MAAO,CAAA,WAAW,CAAI,GAAA,KAAA,CAAM,KAAK,KAAK,CAAA,CAAA;AACxD;;;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daimo/pay",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.19.
|
|
4
|
+
"version": "1.19.9",
|
|
5
5
|
"author": "Daimo",
|
|
6
6
|
"homepage": "https://pay.daimo.com",
|
|
7
7
|
"license": "BSD-2-Clause license",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"lint": "eslint 'src/**/*.{js,jsx,ts,tsx}' --max-warnings=0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@daimo/pay-common": "1.19.
|
|
36
|
+
"@daimo/pay-common": "1.19.9",
|
|
37
37
|
"@solana/wallet-adapter-base": "^0.9.23",
|
|
38
38
|
"@solana/wallet-adapter-react": "^0.15.35",
|
|
39
39
|
"@solana/web3.js": "^1.95.4",
|