@daimo/pay 1.1.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/build/index.d.ts +37 -105
  2. package/build/package.json.js +3 -4
  3. package/build/package.json.js.map +1 -1
  4. package/build/src/assets/icons.js +2 -1
  5. package/build/src/assets/icons.js.map +1 -1
  6. package/build/src/components/Common/AmountInput/AmountInputField.js +59 -0
  7. package/build/src/components/Common/AmountInput/AmountInputField.js.map +1 -0
  8. package/build/src/components/Common/AmountInput/index.js +143 -0
  9. package/build/src/components/Common/AmountInput/index.js.map +1 -0
  10. package/build/src/components/Common/ChainSelectList/index.js +1 -1
  11. package/build/src/components/Common/Modal/index.js +9 -4
  12. package/build/src/components/Common/Modal/index.js.map +1 -1
  13. package/build/src/components/Common/Modal/styles.js +2 -1
  14. package/build/src/components/Common/Modal/styles.js.map +1 -1
  15. package/build/src/components/Common/OptionsList/styles.js +1 -1
  16. package/build/src/components/Common/OrderHeader/index.js +22 -111
  17. package/build/src/components/Common/OrderHeader/index.js.map +1 -1
  18. package/build/src/components/Common/PaymentBreakdown/index.js +48 -0
  19. package/build/src/components/{Pages/WaitingOther → Common/PaymentBreakdown}/index.js.map +1 -1
  20. package/build/src/components/Common/SwitchButton/index.js +39 -0
  21. package/build/src/components/Common/SwitchButton/index.js.map +1 -0
  22. package/build/src/components/Common/TokenChainLogo/index.js +24 -0
  23. package/build/src/components/Common/TokenChainLogo/index.js.map +1 -0
  24. package/build/src/components/DaimoPay.js +7 -2
  25. package/build/src/components/DaimoPay.js.map +1 -1
  26. package/build/src/components/DaimoPayButton/index.js +0 -1
  27. package/build/src/components/DaimoPayButton/index.js.map +1 -1
  28. package/build/src/components/DaimoPayModal/index.js +86 -26
  29. package/build/src/components/DaimoPayModal/index.js.map +1 -1
  30. package/build/src/components/Pages/PayWithToken/index.js +4 -109
  31. package/build/src/components/Pages/PayWithToken/index.js.map +1 -1
  32. package/build/src/components/Pages/SelectAmount/index.js +16 -0
  33. package/build/src/components/Pages/SelectAmount/index.js.map +1 -0
  34. package/build/src/components/Pages/SelectDepositAddressAmount/index.js +60 -0
  35. package/build/src/components/Pages/SelectDepositAddressAmount/index.js.map +1 -0
  36. package/build/src/components/Pages/SelectDepositAddressChain/index.js +7 -2
  37. package/build/src/components/Pages/SelectDepositAddressChain/index.js.map +1 -1
  38. package/build/src/components/Pages/SelectExternalAmount/index.js +62 -0
  39. package/build/src/components/Pages/SelectExternalAmount/index.js.map +1 -0
  40. package/build/src/components/Pages/SelectMethod/index.js +14 -7
  41. package/build/src/components/Pages/SelectMethod/index.js.map +1 -1
  42. package/build/src/components/Pages/SelectToken/index.js +36 -41
  43. package/build/src/components/Pages/SelectToken/index.js.map +1 -1
  44. package/build/src/components/Pages/Solana/ConnectorSolana/index.js +8 -2
  45. package/build/src/components/Pages/Solana/ConnectorSolana/index.js.map +1 -1
  46. package/build/src/components/Pages/Solana/PayWithSolanaToken/index.js +14 -8
  47. package/build/src/components/Pages/Solana/PayWithSolanaToken/index.js.map +1 -1
  48. package/build/src/components/Pages/Solana/SelectSolanaAmount/index.js +16 -0
  49. package/build/src/components/Pages/Solana/SelectSolanaAmount/index.js.map +1 -0
  50. package/build/src/components/Pages/Solana/SelectSolanaToken/index.js +37 -21
  51. package/build/src/components/Pages/Solana/SelectSolanaToken/index.js.map +1 -1
  52. package/build/src/components/Pages/WaitingExternal/index.js +53 -0
  53. package/build/src/components/Pages/WaitingExternal/index.js.map +1 -0
  54. package/build/src/components/Spinners/ExternalPaymentSpinner/index.js +20 -0
  55. package/build/src/components/Spinners/ExternalPaymentSpinner/index.js.map +1 -0
  56. package/build/src/components/Spinners/TokenLogoSpinner/index.js +13 -0
  57. package/build/src/components/Spinners/TokenLogoSpinner/index.js.map +1 -0
  58. package/build/src/components/Spinners/TokenLogoSpinner/styles.js +40 -0
  59. package/build/src/components/Spinners/TokenLogoSpinner/styles.js.map +1 -0
  60. package/build/src/components/Spinners/styles.js +32 -0
  61. package/build/src/components/Spinners/styles.js.map +1 -0
  62. package/build/src/hooks/useDepositAddressOptions.js +8 -5
  63. package/build/src/hooks/useDepositAddressOptions.js.map +1 -1
  64. package/build/src/hooks/useExternalPaymentOptions.js +7 -6
  65. package/build/src/hooks/useExternalPaymentOptions.js.map +1 -1
  66. package/build/src/hooks/useOrderUsdLimits.js +26 -0
  67. package/build/src/hooks/useOrderUsdLimits.js.map +1 -0
  68. package/build/src/hooks/usePaymentState.js +46 -14
  69. package/build/src/hooks/usePaymentState.js.map +1 -1
  70. package/build/src/hooks/useSolanaPaymentOptions.js +7 -5
  71. package/build/src/hooks/useSolanaPaymentOptions.js.map +1 -1
  72. package/build/src/hooks/useWalletPaymentOptions.js +9 -8
  73. package/build/src/hooks/useWalletPaymentOptions.js.map +1 -1
  74. package/build/src/index.js +1 -1
  75. package/build/src/utils/exports.js +4 -1
  76. package/build/src/utils/exports.js.map +1 -1
  77. package/build/src/utils/format.js +83 -0
  78. package/build/src/utils/format.js.map +1 -0
  79. package/build/src/utils/validateInput.js +36 -0
  80. package/build/src/utils/validateInput.js.map +1 -0
  81. package/package.json +3 -4
  82. package/build/src/components/Pages/WaitingOther/index.js +0 -91
@@ -1,92 +1,37 @@
1
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { DaimoPayOrderMode } from '@daimo/common';
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
2
  import { motion } from 'framer-motion';
4
- import { useState } from 'react';
5
3
  import { Ethereum, Optimism, Arbitrum, Base, Polygon, Solana } from '../../../assets/chains.js';
6
4
  import { USDC } from '../../../assets/coins.js';
7
5
  import defaultTheme from '../../../constants/defaultTheme.js';
8
6
  import styled from '../../../styles/styled/index.js';
9
- import { usePayContext } from '../../DaimoPay.js';
10
- import Button from '../Button/index.js';
7
+ import { formatUsd } from '../../../utils/format.js';
8
+ import { usePayContext, ROUTES } from '../../DaimoPay.js';
11
9
 
12
10
  /** Shows payment amount. */
13
11
  const OrderHeader = ({ minified = false }) => {
14
- const { paymentState } = usePayContext();
15
- const amountUsd = paymentState.daimoPayOrder?.destFinalCallTokenAmount.usd;
16
- const isEditable = paymentState.daimoPayOrder?.mode === DaimoPayOrderMode.CHOOSE_AMOUNT;
17
- const [editableAmount, setEditableAmount] = useState(amountUsd == null ? "" : amountUsd.toFixed(2));
18
- const [isEditing, setIsEditing] = useState(false);
19
- const handleSave = () => {
20
- if (!isEditing)
21
- return;
22
- paymentState.setChosenUsd(Number(editableAmount));
23
- setIsEditing(false);
24
- };
25
- const handleKeyDown = (e) => {
26
- if (e.key === "Enter" && isEditing) {
27
- handleSave();
28
- }
29
- };
30
- const sanitizeAndSetAmount = (enteredUsd) => {
31
- if (!enteredUsd.match(/^[0-9]*(\.[0-9]{0,2})?$/)) {
32
- return;
12
+ const { paymentState, route } = usePayContext();
13
+ const orderUsd = paymentState.daimoPayOrder?.destFinalCallTokenAmount.usd;
14
+ const titleAmountContent = (() => {
15
+ if (paymentState.isDepositFlow) {
16
+ return route === ROUTES.SELECT_TOKEN ||
17
+ route === ROUTES.SOLANA_SELECT_TOKEN ? (
18
+ // TODO: make this match `ModalH1` font size for mobile
19
+ jsx("span", { style: { fontSize: "19px", lineHeight: "22px" }, children: "Your balances" })) : null;
33
20
  }
34
- const [digitsBeforeDecimal, digitsAfterDecimal] = (() => {
35
- if (enteredUsd.includes("."))
36
- return enteredUsd.split(".");
37
- else
38
- return [enteredUsd, ""];
39
- })();
40
- if (digitsBeforeDecimal.length > 5 || digitsAfterDecimal.length > 2) {
41
- return;
21
+ else {
22
+ return orderUsd != null ? (jsx("span", { children: formatUsd(orderUsd, "nearest") })) : null;
42
23
  }
43
- setEditableAmount(enteredUsd);
44
- };
45
- const titleAmountContent = (() => {
46
- const buttonStyles = (() => {
47
- if (minified)
48
- return {
49
- height: "24px",
50
- width: "42px",
51
- lineHeight: "12px",
52
- borderRadius: "6px",
53
- fontSize: "14px",
54
- };
55
- else
56
- return {
57
- height: "30px",
58
- width: "54px",
59
- lineHeight: "16px",
60
- borderRadius: "8px",
61
- fontSize: "20px",
62
- };
63
- })();
64
- return (jsxs(Fragment, { children: [isEditable && !minified && (jsx("div", { style: { width: buttonStyles.width, height: buttonStyles.height } })), !isEditing && amountUsd != null && (jsx("span", { children: new Intl.NumberFormat("en-US", {
65
- style: "currency",
66
- currency: "USD",
67
- }).format(amountUsd) })), isEditing && (jsxs("div", { style: { display: "flex" }, children: ["$", jsx(InputUnderlineField, { value: editableAmount, onChange: (e) => sanitizeAndSetAmount(e.target.value), onBlur: (e) => {
68
- if (!e.relatedTarget) {
69
- setIsEditing(false);
70
- }
71
- }, onKeyDown: handleKeyDown })] })), isEditable && (jsx(Button, { variant: "primary", onClick: () => {
72
- if (isEditing)
73
- handleSave();
74
- else
75
- setIsEditing(true);
76
- }, style: {
77
- width: buttonStyles.width,
78
- height: buttonStyles.height,
79
- lineHeight: buttonStyles.lineHeight,
80
- borderRadius: buttonStyles.borderRadius,
81
- fontSize: buttonStyles.fontSize,
82
- margin: 0,
83
- }, children: isEditing ? "Save" : "Edit" }))] }));
84
24
  })();
85
25
  if (minified) {
86
- return (jsxs(MinifiedContainer, { children: [jsx(MinifiedTitleAmount, { children: titleAmountContent }), jsx(CoinLogos, { "$size": 32 })] }));
26
+ if (titleAmountContent != null) {
27
+ return (jsxs(MinifiedContainer, { children: [jsx(MinifiedTitleAmount, { children: titleAmountContent }), jsx(CoinLogos, { "$size": 32 })] }));
28
+ }
29
+ else {
30
+ return (jsxs(MinifiedContainer, { children: [jsx(CoinLogos, {}), jsx(Subtitle, { children: "1000+ tokens accepted" })] }));
31
+ }
87
32
  }
88
33
  else {
89
- return (jsxs(Fragment, { children: [jsx(TitleAmount, { children: titleAmountContent }), jsxs(AnyChainAnyCoinContainer, { children: [jsx(CoinLogos, {}), jsx(Subtitle, { children: "1000+ tokens accepted" })] })] }));
34
+ return (jsxs(Fragment, { children: [titleAmountContent && jsx(TitleAmount, { children: titleAmountContent }), jsxs(AnyChainAnyCoinContainer, { children: [jsx(CoinLogos, {}), jsx(Subtitle, { children: "1000+ tokens accepted" })] })] }));
90
35
  }
91
36
  };
92
37
  function CoinLogos({ $size = 24 }) {
@@ -102,42 +47,8 @@ function CoinLogos({ $size = 24 }) {
102
47
  const logoBlock = (element, index) => (jsx(LogoContainer, { "$marginLeft": index !== 0 ? -($size / 3) : 0, "$zIndex": logos.length - index, "$size": $size, transition: { duration: 0.5, ease: [0.175, 0.885, 0.32, 0.98] }, children: element }, index));
103
48
  return (jsx(Logos, { children: logos.map((element, index) => logoBlock(element, index)) }));
104
49
  }
105
- function InputUnderlineField({ value, onChange, onBlur, onKeyDown, }) {
106
- // subtract width for decimal point if necessary
107
- const width = value.length - 0.5 * (value.includes(".") ? 1 : 0) + "ch";
108
- const selectAll = (e) => {
109
- // When entering edit mode, select the amount for quicker editing
110
- setTimeout(() => e.target.select(), 100);
111
- };
112
- return (jsxs("div", { style: { width: "auto", position: "relative" }, children: [jsx(InputField, { "$width": width, type: "text", pattern: "\\d*.\\d{2}", value: value, onChange: onChange, onBlur: onBlur, onFocus: selectAll, onKeyDown: onKeyDown, autoFocus: true }), jsx(Underline, {})] }));
113
- }
114
- const InputField = styled(motion.input) `
115
- box-sizing: border-box;
116
- background-color: transparent;
117
- outline: none;
118
- width: ${(props) => props.$width || "5ch"};
119
- line-height: inherit;
120
- font-size: inherit;
121
- font-weight: inherit;
122
- color: inherit;
123
- border: none;
124
- padding: 0;
125
- &:focus {
126
- box-sizing: border-box;
127
- outline: none;
128
- border: none;
129
- }
130
- `;
131
- const Underline = styled(motion.div) `
132
- position: absolute;
133
- bottom: 0;
134
- left: 0;
135
- width: 100%;
136
- height: 2px;
137
- background-color: var(--ck-body-color-muted);
138
- `;
139
50
  const TitleAmount = styled(motion.h1) `
140
- margin: 0;
51
+ margin-bottom: 24px;
141
52
  padding: 0;
142
53
  line-height: 66px;
143
54
  font-size: 64px;
@@ -187,7 +98,7 @@ const AnyChainAnyCoinContainer = styled(motion.div) `
187
98
  justify-content: center;
188
99
  text-align: center;
189
100
  gap: 8px;
190
- margin: 24px 0;
101
+ margin-bottom: 24px;
191
102
  `;
192
103
  const LogoContainer = styled(motion.div) `
193
104
  display: block;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,48 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import defaultTheme from '../../../constants/defaultTheme.js';
3
+ import styled from '../../../styles/styled/index.js';
4
+ import { ModalBody } from '../Modal/styles.js';
5
+
6
+ const PaymentBreakdown = ({ paymentOption }) => {
7
+ const totalUsd = paymentOption.required.usd;
8
+ const feesUsd = paymentOption.fees.usd;
9
+ const subtotalUsd = totalUsd - feesUsd;
10
+ return (jsxs(FeesContainer, { children: [feesUsd > 0 && (jsxs(FeeRow, { children: [jsx(ModalBody, { children: "Subtotal" }), jsxs(ModalBody, { children: ["$", subtotalUsd.toFixed(2)] })] })), jsxs(FeeRow, { children: [jsx(ModalBody, { children: "Fees" }), feesUsd === 0 ? (jsx(Badge, { children: "Free" })) : (jsxs(ModalBody, { children: ["$", feesUsd.toFixed(2)] }))] }), jsxs(FeeRow, { style: { marginTop: 8 }, children: [jsx(ModalBody, { style: { fontWeight: 600 }, children: "Total" }), jsxs(ModalBody, { style: { fontWeight: 600 }, children: ["$", totalUsd.toFixed(2)] })] })] }));
11
+ };
12
+ const FeesContainer = styled.div `
13
+ display: flex;
14
+ flex-direction: column;
15
+ align-items: center;
16
+ width: 100%;
17
+ gap: 4px;
18
+ margin: 16px 0;
19
+
20
+ @media only screen and (max-width: ${defaultTheme.mobileWidth}px) {
21
+ & ${ModalBody} {
22
+ margin: 0 !important;
23
+ max-width: 100% !important;
24
+ text-align: left !important;
25
+ }
26
+ }
27
+ `;
28
+ const FeeRow = styled.div `
29
+ display: flex;
30
+ justify-content: space-between;
31
+ align-items: center;
32
+ width: 50%;
33
+ `;
34
+ const Badge = styled.span `
35
+ display: inline-block;
36
+ padding: 3px 8px;
37
+ border-radius: var(--ck-primary-button-border-radius);
38
+ font-size: 14px;
39
+ font-weight: 400;
40
+ background: var(
41
+ --ck-secondary-button-background,
42
+ var(--ck-body-background-secondary)
43
+ );
44
+ color: var(--ck-body-color-muted);
45
+ `;
46
+
47
+ export { PaymentBreakdown as default };
48
+ //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,39 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useState } from 'react';
3
+ import { SwitchIcon } from '../../../assets/icons.js';
4
+ import styled from '../../../styles/styled/index.js';
5
+
6
+ const Container = styled.button `
7
+ display: flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ gap: 4px;
11
+ cursor: pointer;
12
+ width: fit-content;
13
+ `;
14
+ const IconWrapper = styled.div `
15
+ opacity: ${({ $isFlipped }) => ($isFlipped ? 1 : 1)};
16
+ transform: scaleY(${({ $isFlipped }) => ($isFlipped ? -1 : 1)});
17
+ transition: all 0.2s ease-in-out;
18
+
19
+ &.fade {
20
+ opacity: 0;
21
+ transform: scaleY(0);
22
+ }
23
+ `;
24
+ const SwitchButton = ({ onClick, children }) => {
25
+ const [isFlipped, setIsFlipped] = useState(false);
26
+ const [isFading, setIsFading] = useState(false);
27
+ const handleClick = () => {
28
+ setIsFading(true);
29
+ setTimeout(() => {
30
+ setIsFlipped(!isFlipped);
31
+ setIsFading(false);
32
+ }, 150); // Match the transition duration
33
+ onClick();
34
+ };
35
+ return (jsxs(Container, { onClick: handleClick, children: [jsx(IconWrapper, { "$isFlipped": isFlipped, className: isFading ? "fade" : "", children: jsx(SwitchIcon, {}) }), children] }));
36
+ };
37
+
38
+ export { SwitchButton as default };
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,24 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { motion } from 'framer-motion';
3
+ import styled from 'styled-components';
4
+ import { chainToLogo } from '../../../assets/chains.js';
5
+
6
+ const TokenChainLogo = ({ token }) => {
7
+ return (jsxs(TokenChainContainer, { children: [jsx("img", { src: token.logoURI, alt: token.symbol, style: { borderRadius: 9999 } }), jsx(ChainContainer, { children: chainToLogo[token.chainId] })] }));
8
+ };
9
+ const TokenChainContainer = styled(motion.div) `
10
+ width: 100%;
11
+ height: 100%;
12
+ `;
13
+ const ChainContainer = styled(motion.div) `
14
+ position: absolute;
15
+ width: 16px;
16
+ height: 16px;
17
+ border-radius: 9999px;
18
+ overflow: hidden;
19
+ bottom: 0px;
20
+ right: 0px;
21
+ `;
22
+
23
+ export { TokenChainLogo as default };
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -20,7 +20,10 @@ var ROUTES;
20
20
  (function (ROUTES) {
21
21
  ROUTES["SELECT_METHOD"] = "daimoPaySelectMethod";
22
22
  ROUTES["SELECT_TOKEN"] = "daimoPaySelectToken";
23
- ROUTES["WAITING_OTHER"] = "daimoPayWaitingOther";
23
+ ROUTES["SELECT_AMOUNT"] = "daimoPaySelectAmount";
24
+ ROUTES["SELECT_EXTERNAL_AMOUNT"] = "daimoPaySelectExternalAmount";
25
+ ROUTES["SELECT_DEPOSIT_ADDRESS_AMOUNT"] = "daimoPaySelectDepositAddressAmount";
26
+ ROUTES["WAITING_EXTERNAL"] = "daimoPayWaitingExternal";
24
27
  ROUTES["SELECT_DEPOSIT_ADDRESS_CHAIN"] = "daimoPaySelectDepositAddressChain";
25
28
  ROUTES["WAITING_DEPOSIT_ADDRESS"] = "daimoPayWaitingDepositAddress";
26
29
  ROUTES["PAY_WITH_TOKEN"] = "daimoPayPayWithToken";
@@ -28,6 +31,7 @@ var ROUTES;
28
31
  ROUTES["SOLANA_CONNECT"] = "daimoPaySolanaConnect";
29
32
  ROUTES["SOLANA_CONNECTOR"] = "daimoPaySolanaConnector";
30
33
  ROUTES["SOLANA_SELECT_TOKEN"] = "daimoPaySolanaSelectToken";
34
+ ROUTES["SOLANA_SELECT_AMOUNT"] = "daimoPaySolanaSelectAmount";
31
35
  ROUTES["SOLANA_PAY_WITH_TOKEN"] = "daimoPaySolanaPayWithToken";
32
36
  // Unused routes. Kept to minimize connectkit merge conflicts.
33
37
  ROUTES["ONBOARDING"] = "onboarding";
@@ -157,7 +161,8 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
157
161
  return;
158
162
  }
159
163
  log(`[PAY] polling in ${intervalMs}ms`);
160
- setTimeout(() => retryBackoff("refreshOrder", () => paymentState.refreshOrder()), intervalMs);
164
+ const timeout = setTimeout(() => retryBackoff("refreshOrder", () => paymentState.refreshOrder()), intervalMs);
165
+ return () => clearTimeout(timeout);
161
166
  }, [daimoPayOrder]);
162
167
  const showPayment = async (modalOptions) => {
163
168
  const { daimoPayOrder } = paymentState;
@@ -1 +1 @@
1
- {"version":3,"file":"DaimoPay.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"DaimoPay.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -30,7 +30,6 @@ function DaimoPayButtonCustom(props) {
30
30
  toToken: props.toToken,
31
31
  toUnits: props.toUnits,
32
32
  toCallData: props.toCallData,
33
- isAmountEditable: props.amountEditable ?? false,
34
33
  intent: props.intent,
35
34
  paymentOptions: props.paymentOptions,
36
35
  preferredChains: props.preferredChains,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -10,25 +10,31 @@ import MobileConnectors from '../Pages/MobileConnectors/index.js';
10
10
  import Introduction from '../Pages/Onboarding/index.js';
11
11
  import SwitchNetworks from '../Pages/SwitchNetworks/index.js';
12
12
  import ConnectUsing from './ConnectUsing.js';
13
+ import assert from 'assert';
13
14
  import { getAppName } from '../../defaultConfig.js';
14
15
  import { useChainIsSupported } from '../../hooks/useChainIsSupported.js';
15
16
  import { DaimoPayThemeProvider } from '../DaimoPayThemeProvider/DaimoPayThemeProvider.js';
16
17
  import Confirmation from '../Pages/Confirmation/index.js';
17
18
  import PayWithToken from '../Pages/PayWithToken/index.js';
19
+ import SelectAmount from '../Pages/SelectAmount/index.js';
20
+ import SelectDepositAddressAmount from '../Pages/SelectDepositAddressAmount/index.js';
18
21
  import SelectDepositAddressChain from '../Pages/SelectDepositAddressChain/index.js';
22
+ import SelectExternalAmount from '../Pages/SelectExternalAmount/index.js';
19
23
  import SelectMethod from '../Pages/SelectMethod/index.js';
20
24
  import SelectToken from '../Pages/SelectToken/index.js';
21
25
  import ConnectSolana$1 from '../Pages/Solana/ConnectorSolana/index.js';
22
26
  import ConnectSolana from '../Pages/Solana/ConnectSolana/index.js';
23
27
  import PayWithSolanaToken from '../Pages/Solana/PayWithSolanaToken/index.js';
28
+ import SelectSolanaAmount from '../Pages/Solana/SelectSolanaAmount/index.js';
24
29
  import SelectSolanaToken from '../Pages/Solana/SelectSolanaToken/index.js';
25
30
  import WaitingDepositAddress from '../Pages/WaitingDepositAddress/index.js';
26
- import WaitingOther from '../Pages/WaitingOther/index.js';
31
+ import WaitingExternal from '../Pages/WaitingExternal/index.js';
27
32
 
28
33
  const customThemeDefault = {};
29
34
  const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThemeDefault, lang = "en-US", }) => {
30
35
  const context = usePayContext();
31
- const { setSelectedExternalOption, setSelectedTokenOption, setSelectedDepositAddressOption, setSelectedSolanaTokenOption, } = context.paymentState;
36
+ const paymentState = context.paymentState;
37
+ const { payParams, generatePreviewOrder, isDepositFlow, setPaymentWaitingMessage, setSelectedExternalOption, setSelectedTokenOption, setSelectedSolanaTokenOption, setSelectedDepositAddressOption, } = paymentState;
32
38
  const { isConnected, chain } = useAccount();
33
39
  const chainIsSupported = useChainIsSupported(chain?.id);
34
40
  //if chain is unsupported we enforce a "switch chain" prompt
@@ -48,50 +54,104 @@ const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThem
48
54
  else if (context.route === ROUTES.SELECT_TOKEN) {
49
55
  context.setRoute(ROUTES.SELECT_METHOD);
50
56
  }
51
- else if (context.route === ROUTES.WAITING_OTHER) {
57
+ else if (context.route === ROUTES.SELECT_AMOUNT) {
58
+ setSelectedTokenOption(undefined);
59
+ context.setRoute(ROUTES.SELECT_TOKEN);
60
+ }
61
+ else if (context.route === ROUTES.SELECT_EXTERNAL_AMOUNT) {
52
62
  setSelectedExternalOption(undefined);
53
63
  context.setRoute(ROUTES.SELECT_METHOD);
54
64
  }
65
+ else if (context.route === ROUTES.SELECT_DEPOSIT_ADDRESS_AMOUNT) {
66
+ setSelectedDepositAddressOption(undefined);
67
+ context.setRoute(ROUTES.SELECT_DEPOSIT_ADDRESS_CHAIN);
68
+ }
69
+ else if (context.route === ROUTES.WAITING_EXTERNAL) {
70
+ setPaymentWaitingMessage(undefined);
71
+ if (isDepositFlow) {
72
+ assert(payParams != null, "payParams cannot be null in deposit flow");
73
+ generatePreviewOrder(payParams);
74
+ context.setRoute(ROUTES.SELECT_EXTERNAL_AMOUNT);
75
+ }
76
+ else {
77
+ setSelectedExternalOption(undefined);
78
+ context.setRoute(ROUTES.SELECT_METHOD);
79
+ }
80
+ }
55
81
  else if (context.route === ROUTES.PAY_WITH_TOKEN) {
56
- setSelectedTokenOption(undefined);
57
- context.setRoute(ROUTES.SELECT_TOKEN);
82
+ if (isDepositFlow) {
83
+ assert(payParams != null, "payParams cannot be null in deposit flow");
84
+ generatePreviewOrder(payParams);
85
+ context.setRoute(ROUTES.SELECT_AMOUNT);
86
+ }
87
+ else {
88
+ setSelectedTokenOption(undefined);
89
+ context.setRoute(ROUTES.SELECT_TOKEN);
90
+ }
58
91
  }
59
92
  else if (context.route === ROUTES.ONBOARDING) {
60
93
  context.setRoute(ROUTES.CONNECTORS);
61
94
  }
62
95
  else if (context.route === ROUTES.WAITING_DEPOSIT_ADDRESS) {
63
- setSelectedDepositAddressOption(undefined);
64
- context.setRoute(ROUTES.SELECT_DEPOSIT_ADDRESS_CHAIN);
96
+ if (isDepositFlow) {
97
+ assert(payParams != null, "payParams cannot be null in deposit flow");
98
+ generatePreviewOrder(payParams);
99
+ context.setRoute(ROUTES.SELECT_DEPOSIT_ADDRESS_AMOUNT);
100
+ }
101
+ else {
102
+ setSelectedDepositAddressOption(undefined);
103
+ context.setRoute(ROUTES.SELECT_DEPOSIT_ADDRESS_CHAIN);
104
+ }
65
105
  }
66
- else if (context.route === ROUTES.SOLANA_PAY_WITH_TOKEN) {
106
+ else if (context.route === ROUTES.SOLANA_SELECT_AMOUNT) {
67
107
  setSelectedSolanaTokenOption(undefined);
68
108
  context.setRoute(ROUTES.SOLANA_SELECT_TOKEN);
69
109
  }
110
+ else if (context.route === ROUTES.SOLANA_PAY_WITH_TOKEN) {
111
+ if (isDepositFlow) {
112
+ assert(payParams != null, "payParams cannot be null in deposit flow");
113
+ generatePreviewOrder(payParams);
114
+ context.setRoute(ROUTES.SOLANA_SELECT_AMOUNT);
115
+ }
116
+ else {
117
+ setSelectedSolanaTokenOption(undefined);
118
+ context.setRoute(ROUTES.SOLANA_SELECT_TOKEN);
119
+ }
120
+ }
70
121
  else {
71
122
  context.setRoute(ROUTES.SELECT_METHOD);
72
123
  }
73
124
  };
74
125
  const pages = {
75
- daimoPaySelectMethod: jsx(SelectMethod, {}),
76
- daimoPaySelectToken: jsx(SelectToken, {}),
77
- daimoPayWaitingOther: jsx(WaitingOther, {}),
78
- daimoPaySelectDepositAddressChain: jsx(SelectDepositAddressChain, {}),
79
- daimoPayWaitingDepositAddress: jsx(WaitingDepositAddress, {}),
80
- daimoPayConfirmation: jsx(Confirmation, {}),
81
- daimoPayPayWithToken: jsx(PayWithToken, {}),
82
- daimoPaySolanaConnect: jsx(ConnectSolana, {}),
83
- daimoPaySolanaConnector: jsx(ConnectSolana$1, {}),
84
- daimoPaySolanaSelectToken: jsx(SelectSolanaToken, {}),
85
- daimoPaySolanaPayWithToken: jsx(PayWithSolanaToken, {}),
86
- onboarding: jsx(Introduction, {}),
87
- about: jsx(About, {}),
88
- download: jsx(DownloadApp, {}),
89
- connectors: jsx(Wallets, {}),
90
- mobileConnectors: jsx(MobileConnectors, {}),
91
- connect: jsx(ConnectUsing, {}),
92
- switchNetworks: jsx(SwitchNetworks, {}),
126
+ [ROUTES.SELECT_METHOD]: jsx(SelectMethod, {}),
127
+ [ROUTES.SELECT_TOKEN]: jsx(SelectToken, {}),
128
+ [ROUTES.SELECT_AMOUNT]: jsx(SelectAmount, {}),
129
+ [ROUTES.SELECT_EXTERNAL_AMOUNT]: jsx(SelectExternalAmount, {}),
130
+ [ROUTES.SELECT_DEPOSIT_ADDRESS_AMOUNT]: jsx(SelectDepositAddressAmount, {}),
131
+ [ROUTES.WAITING_EXTERNAL]: jsx(WaitingExternal, {}),
132
+ [ROUTES.SELECT_DEPOSIT_ADDRESS_CHAIN]: jsx(SelectDepositAddressChain, {}),
133
+ [ROUTES.WAITING_DEPOSIT_ADDRESS]: jsx(WaitingDepositAddress, {}),
134
+ [ROUTES.CONFIRMATION]: jsx(Confirmation, {}),
135
+ [ROUTES.PAY_WITH_TOKEN]: jsx(PayWithToken, {}),
136
+ [ROUTES.SOLANA_CONNECT]: jsx(ConnectSolana, {}),
137
+ [ROUTES.SOLANA_CONNECTOR]: jsx(ConnectSolana$1, {}),
138
+ [ROUTES.SOLANA_SELECT_TOKEN]: jsx(SelectSolanaToken, {}),
139
+ [ROUTES.SOLANA_SELECT_AMOUNT]: jsx(SelectSolanaAmount, {}),
140
+ [ROUTES.SOLANA_PAY_WITH_TOKEN]: jsx(PayWithSolanaToken, {}),
141
+ // Unused routes. Kept to minimize connectkit merge conflicts.
142
+ [ROUTES.ONBOARDING]: jsx(Introduction, {}),
143
+ [ROUTES.ABOUT]: jsx(About, {}),
144
+ [ROUTES.DOWNLOAD]: jsx(DownloadApp, {}),
145
+ [ROUTES.CONNECTORS]: jsx(Wallets, {}),
146
+ [ROUTES.MOBILECONNECTORS]: jsx(MobileConnectors, {}),
147
+ [ROUTES.CONNECT]: jsx(ConnectUsing, {}),
148
+ [ROUTES.SWITCHNETWORKS]: jsx(SwitchNetworks, {}),
93
149
  };
94
150
  function hide() {
151
+ if (isDepositFlow) {
152
+ assert(payParams != null, "payParams cannot be null in deposit flow");
153
+ generatePreviewOrder(payParams);
154
+ }
95
155
  context.setOpen(false);
96
156
  }
97
157
  useEffect(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,15 +1,11 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { useState, useEffect } from 'react';
3
3
  import { usePayContext, ROUTES } from '../../DaimoPay.js';
4
- import { ModalBody, PageContent, ModalContent, ModalH1 } from '../../Common/Modal/styles.js';
5
- import { motion, AnimatePresence } from 'framer-motion';
6
- import { css } from 'styled-components';
4
+ import { PageContent, ModalContent, ModalH1 } from '../../Common/Modal/styles.js';
7
5
  import { useChainId, useSwitchChain } from 'wagmi';
8
- import { chainToLogo } from '../../../assets/chains.js';
9
- import defaultTheme from '../../../constants/defaultTheme.js';
10
- import styled from '../../../styles/styled/index.js';
11
6
  import Button from '../../Common/Button/index.js';
12
- import CircleSpinner from '../../Spinners/CircleSpinner/index.js';
7
+ import PaymentBreakdown from '../../Common/PaymentBreakdown/index.js';
8
+ import TokenLogoSpinner from '../../Spinners/TokenLogoSpinner/index.js';
13
9
 
14
10
  var PayState;
15
11
  (function (PayState) {
@@ -96,109 +92,8 @@ const PayWithToken = () => {
96
92
  useEffect(() => {
97
93
  triggerResize();
98
94
  }, [payState]);
99
- return (jsxs(PageContent, { children: [jsx(LoadingContainer, { children: jsx(AnimationContainer, { "$circle": true, children: jsxs(AnimatePresence, { children: [jsx(ChainLogoContainer, { children: selectedTokenOption &&
100
- chainToLogo[selectedTokenOption.required.token.chainId] }, "ChainLogoContainer"), jsx(CircleSpinner, { logo: jsx("img", { src: selectedTokenOption?.required.token.logoURI, alt: selectedTokenOption?.required.token.symbol }, selectedTokenOption?.required.token.logoURI), loading: true, unavailable: false }, "CircleSpinner")] }) }) }), jsxs(ModalContent, { style: { paddingBottom: 0 }, children: [jsx(ModalH1, { children: payState }), selectedTokenOption && (jsx(PaymentDetails, { selectedTokenOption: selectedTokenOption })), payState === PayState.RequestCancelled && (jsx(Button, { onClick: () => selectedTokenOption ? handleTransfer(selectedTokenOption) : null, children: "Retry Payment" }))] })] }));
95
+ return (jsxs(PageContent, { children: [selectedTokenOption && (jsx(TokenLogoSpinner, { token: selectedTokenOption.required.token })), jsxs(ModalContent, { style: { paddingBottom: 0 }, "$preserveDisplay": true, children: [jsx(ModalH1, { children: payState }), selectedTokenOption && (jsx(PaymentBreakdown, { paymentOption: selectedTokenOption })), payState === PayState.RequestCancelled && (jsx(Button, { onClick: () => selectedTokenOption ? handleTransfer(selectedTokenOption) : null, children: "Retry Payment" }))] })] }));
101
96
  };
102
- const PaymentDetails = ({ selectedTokenOption, }) => {
103
- const totalUsd = selectedTokenOption.required.usd;
104
- const feesUsd = selectedTokenOption.fees.usd;
105
- const subtotalUsd = totalUsd - feesUsd;
106
- return (jsxs(FeesContainer, { children: [feesUsd > 0 && (jsxs(FeeRow, { children: [jsx(ModalBody, { children: "Subtotal" }), jsxs(ModalBody, { children: ["$", subtotalUsd.toFixed(2)] })] })), jsxs(FeeRow, { children: [jsx(ModalBody, { children: "Fees" }), feesUsd === 0 ? (jsx(Badge, { children: "Free" })) : (jsxs(ModalBody, { children: ["$", feesUsd.toFixed(2)] }))] }), jsxs(FeeRow, { style: { marginTop: 8 }, children: [jsx(ModalBody, { style: { fontWeight: 600 }, children: "Total" }), jsxs(ModalBody, { style: { fontWeight: 600 }, children: ["$", totalUsd.toFixed(2)] })] })] }));
107
- };
108
- const LoadingContainer = styled(motion.div) `
109
- display: flex;
110
- align-items: center;
111
- justify-content: center;
112
- margin: 10px auto 16px;
113
- height: 120px;
114
- `;
115
- const AnimationContainer = styled(motion.div) `
116
- user-select: none;
117
- position: relative;
118
- --spinner-error-opacity: 0;
119
- &:before {
120
- content: "";
121
- position: absolute;
122
- inset: 1px;
123
- opacity: 0;
124
- background: var(--ck-body-color-danger);
125
- ${(props) => props.$circle &&
126
- css `
127
- inset: -5px;
128
- border-radius: 50%;
129
- background: none;
130
- box-shadow: inset 0 0 0 3.5px var(--ck-body-color-danger);
131
- `}
132
- }
133
- `;
134
- const ChainLogoContainer = styled(motion.div) `
135
- z-index: 10;
136
- position: absolute;
137
- right: 2px;
138
- bottom: 2px;
139
- padding: 0;
140
- display: flex;
141
- align-items: center;
142
- justify-content: center;
143
- width: 32px;
144
- height: 32px;
145
- border-radius: 16px;
146
- overflow: hidden;
147
-
148
- color: var(--ck-body-background);
149
- transition: color 200ms ease;
150
-
151
- &:before {
152
- z-index: 5;
153
- content: "";
154
- position: absolute;
155
- inset: 0;
156
- opacity: 0;
157
- transition: opacity 200ms ease;
158
- background: var(--ck-body-color);
159
- }
160
-
161
- svg {
162
- display: block;
163
- position: relative;
164
- width: 100%;
165
- height: 100%;
166
- }
167
- `;
168
- const FeesContainer = styled.div `
169
- display: flex;
170
- flex-direction: column;
171
- align-items: center;
172
- width: 100%;
173
- gap: 4px;
174
- margin: 16px 0;
175
-
176
- @media only screen and (max-width: ${defaultTheme.mobileWidth}px) {
177
- & ${ModalBody} {
178
- margin: 0 !important;
179
- max-width: 100% !important;
180
- text-align: left !important;
181
- }
182
- }
183
- `;
184
- const FeeRow = styled.div `
185
- display: flex;
186
- justify-content: space-between;
187
- align-items: center;
188
- width: 50%;
189
- `;
190
- const Badge = styled.span `
191
- display: inline-block;
192
- padding: 3px 8px;
193
- border-radius: var(--ck-primary-button-border-radius);
194
- font-size: 14px;
195
- font-weight: 400;
196
- background: var(
197
- --ck-secondary-button-background,
198
- var(--ck-body-background-secondary)
199
- );
200
- color: var(--ck-body-color-muted);
201
- `;
202
97
 
203
98
  export { PayWithToken as default };
204
99
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}