@coin-voyage/paykit 2.3.6-beta.1 → 2.4.0-beta.1

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 (67) hide show
  1. package/dist/assets/icons.d.ts +3 -0
  2. package/dist/assets/icons.js +3 -0
  3. package/dist/components/Pages/CardPayment/index.d.ts +1 -0
  4. package/dist/components/Pages/CardPayment/index.js +214 -0
  5. package/dist/components/Pages/Confirmation/index.js +1 -1
  6. package/dist/components/Pages/MobileConnectors/index.js +2 -2
  7. package/dist/components/Pages/PayToAddress/copyable-info.js +1 -1
  8. package/dist/components/Pages/PayToAddress/index.js +2 -2
  9. package/dist/components/Pages/PayWithToken/index.js +5 -4
  10. package/dist/components/Pages/SelectChain/index.js +2 -2
  11. package/dist/components/Pages/SelectMethod/index.js +2 -2
  12. package/dist/components/Pages/SelectPayToAddressChain/index.js +1 -5
  13. package/dist/components/Pages/SelectToken/index.js +3 -3
  14. package/dist/components/contexts/pay/index.d.ts +5 -5
  15. package/dist/components/pay-button/index.js +1 -1
  16. package/dist/components/pay-modal/ConnectWithInjector/index.js +7 -7
  17. package/dist/components/pay-modal/ConnectWithQRCode.js +2 -2
  18. package/dist/components/pay-modal/index.js +6 -6
  19. package/dist/components/ui/BrowserIcon/index.js +1 -1
  20. package/dist/components/ui/ChainSelectList/index.js +1 -1
  21. package/dist/components/ui/ConnectorList/index.js +7 -7
  22. package/dist/components/ui/CountDownTimer/index.js +1 -1
  23. package/dist/components/ui/Modal/ModalPageRenderer.d.ts +3 -3
  24. package/dist/components/ui/Modal/ModalPageRenderer.js +4 -1
  25. package/dist/components/ui/Modal/index.d.ts +3 -3
  26. package/dist/components/ui/Modal/index.js +4 -3
  27. package/dist/components/ui/Modal/styles.js +21 -0
  28. package/dist/components/ui/OrderHeader/index.js +1 -1
  29. package/dist/config/route-config.d.ts +2 -2
  30. package/dist/config/route-config.js +34 -31
  31. package/dist/hooks/useChainOptions.js +3 -3
  32. package/dist/hooks/useDepositAddressQuery.js +5 -1
  33. package/dist/hooks/useMethodOptions.d.ts +1 -0
  34. package/dist/hooks/useMethodOptions.js +85 -26
  35. package/dist/hooks/usePayToAddress.js +1 -1
  36. package/dist/hooks/usePayToAddressChainOptions.d.ts +1 -6
  37. package/dist/hooks/usePayToAddressChainOptions.js +6 -9
  38. package/dist/hooks/usePayToAddressTokens.js +3 -3
  39. package/dist/hooks/usePayWithCard.d.ts +10 -0
  40. package/dist/hooks/usePayWithCard.js +24 -0
  41. package/dist/hooks/usePayWithToken.js +20 -10
  42. package/dist/hooks/usePaymentState.d.ts +6 -6
  43. package/dist/hooks/usePaymentState.js +10 -3
  44. package/dist/hooks/useTokenOptions.js +3 -3
  45. package/dist/hooks/useWalletConnectModal.js +4 -4
  46. package/dist/hooks/useWalletConnectUri.js +2 -2
  47. package/dist/hooks/useWallets.d.ts +1 -1
  48. package/dist/hooks/useWallets.js +8 -6
  49. package/dist/index.d.ts +1 -1
  50. package/dist/index.js +1 -1
  51. package/dist/lib/api/payment-details.js +1 -1
  52. package/dist/lib/config/wallet.d.ts +1 -1
  53. package/dist/lib/config/wallet.js +1 -1
  54. package/dist/providers/paykit-provider.js +140 -123
  55. package/dist/types/payment-details.d.ts +1 -1
  56. package/dist/types/route-config.d.ts +3 -3
  57. package/dist/types/routes.d.ts +16 -16
  58. package/dist/types/routes.js +19 -18
  59. package/dist/types/state.d.ts +2 -2
  60. package/dist/types.d.ts +5 -1
  61. package/package.json +5 -3
  62. package/dist/components/Pages/SwitchNetworks/index.d.ts +0 -2
  63. package/dist/components/Pages/SwitchNetworks/index.js +0 -24
  64. package/dist/hooks/useChainIsSupported.d.ts +0 -2
  65. package/dist/hooks/useChainIsSupported.js +0 -19
  66. package/dist/types/enums.d.ts +0 -4
  67. package/dist/types/enums.js +0 -5
@@ -28,3 +28,6 @@ export declare const AuthIcon: ({ ...props }: {
28
28
  export declare const ErrorIcon: ({ ...props }: {
29
29
  [x: string]: any;
30
30
  }) => import("react/jsx-runtime").JSX.Element;
31
+ export declare const CreditCardIcon: ({ ...props }: {
32
+ [x: string]: any;
33
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -41,3 +41,6 @@ export const AuthIcon = ({ ...props }) => (_jsx("div", { ...props, style: {
41
41
  export const ErrorIcon = ({ ...props }) => {
42
42
  return (_jsx("svg", { "aria-hidden": "true", width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M9 18C13.9706 18 18 13.9706 18 9C18 4.02944 13.9706 0 9 0C4.02944 0 0 4.02944 0 9C0 13.9706 4.02944 18 9 18ZM6.70711 5.29289C6.31658 4.90237 5.68342 4.90237 5.29289 5.29289C4.90237 5.68342 4.90237 6.31658 5.29289 6.70711L7.58579 9L5.29289 11.2929C4.90237 11.6834 4.90237 12.3166 5.29289 12.7071C5.68342 13.0976 6.31658 13.0976 6.70711 12.7071L9 10.4142L11.2929 12.7071C11.6834 13.0976 12.3166 13.0976 12.7071 12.7071C13.0976 12.3166 13.0976 11.6834 12.7071 11.2929L10.4142 9L12.7071 6.70711C13.0976 6.31658 13.0976 5.68342 12.7071 5.29289C12.3166 4.90237 11.6834 4.90237 11.2929 5.29289L9 7.58579L6.70711 5.29289Z", fill: "currentColor" }) }));
43
43
  };
44
+ export const CreditCardIcon = ({ ...props }) => {
45
+ return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: [_jsx("rect", { width: "20", height: "14", x: "2", y: "5", rx: "2" }), _jsx("line", { x1: "2", x2: "22", y1: "10", y2: "10" })] }));
46
+ };
@@ -0,0 +1 @@
1
+ export default function CardPayment(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,214 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { getFiatPaymentData } from "@coin-voyage/shared/payment";
3
+ import { PayOrderMode, PayOrderStatus } from "@coin-voyage/shared/types";
4
+ import { loadStripeOnramp } from "@stripe/crypto/pure";
5
+ import { useQuery } from "@tanstack/react-query";
6
+ import { useCallback, useEffect, useMemo, useRef } from "react";
7
+ import { AlertIcon } from "../../../assets/icons";
8
+ import useLocales from "../../../hooks/useLocales";
9
+ import styled from "../../../styles/styled";
10
+ import { ROUTE } from "../../../types/routes";
11
+ import usePayContext from "../../contexts/pay";
12
+ import Button from "../../ui/Button";
13
+ import { ModalBody, ModalContent, ModalH1, PageContent } from "../../ui/Modal/styles";
14
+ import { OrderHeader } from "../../ui/OrderHeader";
15
+ import PoweredByFooter from "../../ui/PoweredByFooter";
16
+ import { Spinner } from "../../ui/Spinner";
17
+ export default function CardPayment() {
18
+ const { triggerResize } = usePayContext();
19
+ const { data, isLoading, error, refetch } = useCardPaymentData();
20
+ useEffect(() => {
21
+ triggerResize();
22
+ }, [triggerResize, isLoading, data?.session_id, data?.client_secret, error]);
23
+ return (_jsxs(PageContent, { children: [_jsx(OrderHeader, { minified: true }), _jsx(CardPaymentContent, { paymentData: data, isLoading: isLoading, error: error instanceof Error ? error : null, onRetry: () => {
24
+ void refetch();
25
+ } }), _jsx(PoweredByFooter, {})] }));
26
+ }
27
+ function CardPaymentContent({ paymentData, isLoading, error, onRetry, }) {
28
+ const locales = useLocales();
29
+ const { paymentState, setRoute } = usePayContext();
30
+ const { payOrder } = paymentState;
31
+ if (!payOrder) {
32
+ return (_jsx(StatusCard, { title: locales.selectPayToAddressWaitingScreen_unavailable_h1, body: "We couldn't load this card payment.", actionLabel: locales.back, onAction: () => setRoute(ROUTE.SELECT_METHOD) }));
33
+ }
34
+ if (payOrder.status === PayOrderStatus.EXPIRED) {
35
+ return _jsx(ExpiredCardPayment, {});
36
+ }
37
+ if (isLoading) {
38
+ return _jsx(StatusCard, { loading: true, title: locales.requesting_payment_h1, body: "Preparing secure Stripe checkout..." });
39
+ }
40
+ if (error || !paymentData) {
41
+ return (_jsx(StatusCard, { warning: true, title: locales.selectPayToAddressWaitingScreen_unavailable_h1, body: error?.message ?? "We couldn't start the Stripe checkout for this order.", actionLabel: locales.tryAgain, onAction: onRetry }));
42
+ }
43
+ return _jsx(StripeOnrampCheckout, { paymentData: paymentData });
44
+ }
45
+ function ExpiredCardPayment() {
46
+ const locales = useLocales();
47
+ const { paymentState, setRoute } = usePayContext();
48
+ const isDeposit = paymentState.payOrder?.mode === PayOrderMode.DEPOSIT;
49
+ return (_jsx(StatusCard, { warning: true, title: locales.payWithTokenScreen_expired_h1, body: locales.payWithTokenScreen_expired_p, actionLabel: isDeposit ? locales.refresh : locales.selectTokenScreen_selectAnotherMethod, onAction: () => {
50
+ if (isDeposit) {
51
+ void paymentState.copyDepositPayOrder();
52
+ return;
53
+ }
54
+ setRoute(ROUTE.SELECT_METHOD);
55
+ } }));
56
+ }
57
+ function StatusCard({ title, body, actionLabel, onAction, loading = false, warning = false, }) {
58
+ return (_jsxs(ModalContent, { "$center": true, style: {
59
+ marginLeft: 24,
60
+ marginRight: 24,
61
+ paddingTop: 24,
62
+ paddingBottom: 24,
63
+ }, children: [loading ? _jsx(Spinner, {}) : warning ? _jsx(AlertIcon, {}) : null, _jsx(ModalH1, { "$warning": warning, children: title }), _jsx(ModalBody, { children: body }), actionLabel && onAction ? (_jsx(ActionRow, { children: _jsx(Button, { onClick: onAction, children: actionLabel }) })) : null] }));
64
+ }
65
+ function StripeOnrampCheckout({ paymentData }) {
66
+ const { paymentState, mode, triggerResize } = usePayContext();
67
+ const { data: stripeOnramp, isLoading, error, refetch } = useStripeOnramp(paymentData.stripe_publishable_key);
68
+ const refreshOrderRef = useLatestRef(paymentState.refreshOrder);
69
+ const refreshDebounceRef = useRef(null);
70
+ const theme = useMemo(() => {
71
+ return mode === "dark" ? "dark" : "light";
72
+ }, [mode]);
73
+ const handleSessionUpdate = useCallback((status) => {
74
+ if (status === "initialized") {
75
+ return;
76
+ }
77
+ if (refreshDebounceRef.current) {
78
+ window.clearTimeout(refreshDebounceRef.current);
79
+ }
80
+ refreshDebounceRef.current = window.setTimeout(() => {
81
+ void refreshOrderRef.current();
82
+ }, 500);
83
+ }, [refreshOrderRef]);
84
+ useEffect(() => {
85
+ return () => {
86
+ if (refreshDebounceRef.current) {
87
+ window.clearTimeout(refreshDebounceRef.current);
88
+ }
89
+ };
90
+ }, []);
91
+ if (error) {
92
+ return (_jsx(StatusCard, { warning: true, title: "Stripe unavailable", body: error.message, actionLabel: "Try again", onAction: () => {
93
+ void refetch();
94
+ } }));
95
+ }
96
+ return (_jsxs(OnrampShell, { children: [isLoading ? (_jsx(OnrampOverlay, { children: _jsx(Spinner, {}) })) : null, stripeOnramp ? (_jsx(OnrampSession, { stripeOnramp: stripeOnramp, clientSecret: paymentData.client_secret, theme: theme, onUiLoaded: triggerResize, onSessionUpdate: handleSessionUpdate }, paymentData.client_secret)) : null] }));
97
+ }
98
+ function OnrampSession({ stripeOnramp, clientSecret, theme, onUiLoaded, onSessionUpdate, }) {
99
+ const mountNodeRef = useRef(null);
100
+ useEffect(() => {
101
+ const mountNode = mountNodeRef.current;
102
+ if (!mountNode) {
103
+ return;
104
+ }
105
+ mountNode.replaceChildren();
106
+ const session = stripeOnramp.createSession({
107
+ clientSecret,
108
+ appearance: theme ? { theme } : undefined,
109
+ });
110
+ const handleUiLoaded = () => {
111
+ onUiLoaded?.();
112
+ };
113
+ const handleSessionUpdated = (event) => {
114
+ onSessionUpdate?.(event.payload.session.status);
115
+ };
116
+ session.addEventListener("onramp_ui_loaded", handleUiLoaded);
117
+ session.addEventListener("onramp_session_updated", handleSessionUpdated);
118
+ session.mount(mountNode);
119
+ return () => {
120
+ session.removeEventListener("onramp_ui_loaded", handleUiLoaded);
121
+ session.removeEventListener("onramp_session_updated", handleSessionUpdated);
122
+ mountNode.replaceChildren();
123
+ };
124
+ }, [clientSecret, onSessionUpdate, onUiLoaded, stripeOnramp, theme]);
125
+ return _jsx(OnrampMount, { ref: mountNodeRef });
126
+ }
127
+ function useCardPaymentData() {
128
+ const { paymentState } = usePayContext();
129
+ const { payOrder, payWithCard } = paymentState;
130
+ const paymentData = getFiatPaymentData(payOrder?.payment);
131
+ const query = useQuery({
132
+ queryKey: ["card-payment", payOrder?.id, paymentData?.session_id ?? null, paymentData?.client_secret ?? null],
133
+ enabled: Boolean(payOrder?.id) && !paymentData,
134
+ retry: false,
135
+ refetchOnWindowFocus: false,
136
+ queryFn: async () => {
137
+ if (!payOrder) {
138
+ throw new Error("Missing pay order");
139
+ }
140
+ if (paymentData) {
141
+ return paymentData;
142
+ }
143
+ const paymentDetails = await payWithCard();
144
+ const fiatPaymentData = getFiatPaymentData(paymentDetails.data);
145
+ if (!fiatPaymentData) {
146
+ throw new Error("Stripe onramp session is unavailable for this pay order");
147
+ }
148
+ return fiatPaymentData;
149
+ },
150
+ });
151
+ return {
152
+ ...query,
153
+ data: paymentData ?? query.data,
154
+ };
155
+ }
156
+ function useStripeOnramp(publishableKey) {
157
+ return useQuery({
158
+ queryKey: ["stripe-onramp", publishableKey],
159
+ enabled: Boolean(publishableKey),
160
+ staleTime: Infinity,
161
+ retry: false,
162
+ queryFn: async () => {
163
+ if (!publishableKey) {
164
+ throw new Error("Missing Stripe publishable key.");
165
+ }
166
+ const instance = await getStripeOnrampPromise(publishableKey);
167
+ if (!instance) {
168
+ throw new Error("Stripe Onramp is only available in the browser.");
169
+ }
170
+ return instance;
171
+ },
172
+ });
173
+ }
174
+ const stripeOnrampPromiseCache = new Map();
175
+ function getStripeOnrampPromise(publishableKey) {
176
+ const cached = stripeOnrampPromiseCache.get(publishableKey);
177
+ if (cached) {
178
+ return cached;
179
+ }
180
+ const nextPromise = loadStripeOnramp(publishableKey);
181
+ stripeOnrampPromiseCache.set(publishableKey, nextPromise);
182
+ return nextPromise;
183
+ }
184
+ function useLatestRef(value) {
185
+ const ref = useRef(value);
186
+ useEffect(() => {
187
+ ref.current = value;
188
+ }, [value]);
189
+ return ref;
190
+ }
191
+ const OnrampShell = styled.div `
192
+ position: relative;
193
+ min-height: 480px;
194
+ border-radius: 10px;
195
+ overflow: hidden;
196
+ background: var(--ck-body-background-secondary);
197
+ border: 1px solid var(--ck-body-divider-secondary, var(--ck-body-divider));
198
+ `;
199
+ const OnrampMount = styled.div `
200
+ min-height: 480px;
201
+ `;
202
+ const OnrampOverlay = styled.div `
203
+ position: absolute;
204
+ inset: 0;
205
+ z-index: 1;
206
+ display: flex;
207
+ align-items: center;
208
+ justify-content: center;
209
+ background: color-mix(in srgb, var(--ck-body-background) 88%, transparent);
210
+ `;
211
+ const ActionRow = styled.div `
212
+ width: 100%;
213
+ margin-top: 8px;
214
+ `;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { getChainExplorerTxUrl } from "@coin-voyage/shared/common";
2
+ import { getChainExplorerTxUrl } from "@coin-voyage/shared/chain";
3
3
  import { PayOrderMode, PayOrderStatus } from "@coin-voyage/shared/types";
4
4
  import { useEffect, useMemo } from "react";
5
5
  import { ExternalLinkIcon } from "../../../assets/icons";
@@ -6,7 +6,7 @@ import { useWalletConnectModal } from "../../../hooks/useWalletConnectModal";
6
6
  import { useWalletConnectUri } from "../../../hooks/useWalletConnectUri";
7
7
  import { useWallets } from "../../../hooks/useWallets";
8
8
  import { walletConfigs } from "../../../lib/config/wallet";
9
- import { ROUTES } from "../../../types/routes";
9
+ import { ROUTE } from "../../../types/routes";
10
10
  import usePayContext from "../../contexts/pay";
11
11
  import { ModalContent, PageContent } from "../../ui/Modal/styles";
12
12
  import { ScrollArea } from "../../ui/ScrollArea";
@@ -44,7 +44,7 @@ export default function MobileConnectors() {
44
44
  chainType: connectorChainType,
45
45
  open: true,
46
46
  walletId,
47
- route: ROUTES.CONNECTORS,
47
+ route: ROUTE.CONNECTORS,
48
48
  }))}`;
49
49
  }
50
50
  const uri = wallet.getWalletDeeplink?.(URI, connectorChainType);
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { truncateAddress } from "@coin-voyage/shared/common";
2
+ import { truncateAddress } from "@coin-voyage/shared/utils";
3
3
  import useLocales from "../../../hooks/useLocales";
4
4
  import { CopyRowOrThrobber } from "../../ui/CopyableInfo";
5
5
  import { CountdownTimer } from "../../ui/CountDownTimer";
@@ -5,7 +5,7 @@ import { AlertIcon } from "../../../assets/icons";
5
5
  import { useCountdown } from "../../../hooks/useCountdown";
6
6
  import { useDepositAddressQuery } from "../../../hooks/useDepositAddressQuery";
7
7
  import useLocales from "../../../hooks/useLocales";
8
- import { ROUTES } from "../../../types/routes";
8
+ import { ROUTE } from "../../../types/routes";
9
9
  import usePayContext from "../../contexts/pay";
10
10
  import Button from "../../ui/Button";
11
11
  import CustomQRCode from "../../ui/CustomQRCode";
@@ -66,7 +66,7 @@ function DepositFailed() {
66
66
  const onSelectAnotherMethod = useCallback(() => {
67
67
  setPayToAddressChain(undefined);
68
68
  setPayToAddressCurrency(undefined);
69
- setRoute(ROUTES.SELECT_PAY_TO_ADDRESS_CHAIN);
69
+ setRoute(ROUTE.ADDRESS_CHAIN_SELECT);
70
70
  }, [setRoute, setPayToAddressChain, setPayToAddressCurrency]);
71
71
  return (_jsxs(ModalContent, { "$center": true, style: {
72
72
  marginLeft: 24,
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useAccount } from "@coin-voyage/crypto/hooks";
3
- import { assert, getChainTypeByChainId } from "@coin-voyage/shared/common";
3
+ import { getChainTypeByChainId } from "@coin-voyage/shared/chain";
4
4
  import { ChainType, PayOrderMode, PayOrderStatus } from "@coin-voyage/shared/types";
5
+ import { assert } from "@coin-voyage/shared/utils";
5
6
  import { AnimatePresence, motion } from "framer-motion";
6
7
  import { useCallback, useEffect, useMemo, useState } from "react";
7
8
  import { useChainId, useSwitchChain } from "wagmi";
@@ -9,7 +10,7 @@ import { chainToLogo } from "../../../assets/chains";
9
10
  import { AlertIcon, RetryIconCircle } from "../../../assets/icons";
10
11
  import useLocales from "../../../hooks/useLocales";
11
12
  import styled from "../../../styles/styled";
12
- import { ROUTES } from "../../../types/routes";
13
+ import { ROUTE } from "../../../types/routes";
13
14
  import usePayContext from "../../contexts/pay";
14
15
  import { RetryButton, RetryIconContainer } from "../../pay-modal/ConnectWithInjector/styles";
15
16
  import CircleSpinner from "../../spinners/CircleSpinner";
@@ -74,7 +75,7 @@ export default function PayWithToken() {
74
75
  try {
75
76
  await executePayment(token);
76
77
  setPayState(PayState.RequestSuccessful);
77
- setTimeout(() => setRoute(ROUTES.CONFIRMATION), 200);
78
+ setTimeout(() => setRoute(ROUTE.CONFIRMATION), 200);
78
79
  }
79
80
  catch (e) {
80
81
  if (e?.name === "ConnectorChainMismatchError") {
@@ -103,7 +104,7 @@ export default function PayWithToken() {
103
104
  const onRetry = () => {
104
105
  if (isExpired && isDeposit) {
105
106
  paymentState.copyDepositPayOrder();
106
- setRoute(ROUTES.SELECT_TOKEN);
107
+ setRoute(ROUTE.WALLET_TOKEN_SELECT);
107
108
  }
108
109
  else if (selectedCurrencyOption) {
109
110
  handleTransfer(selectedCurrencyOption);
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useAccount, useAccountDisconnect } from "@coin-voyage/crypto/hooks";
3
3
  import { useIsMobile } from "@coin-voyage/shared/hooks";
4
4
  import { useChainOptions } from "../../../hooks/useChainOptions";
5
- import { ROUTES } from "../../../types/routes";
5
+ import { ROUTE } from "../../../types/routes";
6
6
  import usePayContext from "../../contexts/pay";
7
7
  import { PageContent } from "../../ui/Modal/styles";
8
8
  import OptionsList from "../../ui/OptionsList";
@@ -19,7 +19,7 @@ export default function SelectChain() {
19
19
  const handleClick = (chainType) => {
20
20
  disconnect(account);
21
21
  paymentState.setConnectorChainType(chainType);
22
- setRoute(ROUTES.CONNECTORS);
22
+ setRoute(ROUTE.CONNECTORS);
23
23
  };
24
24
  const { options } = useChainOptions({
25
25
  account,
@@ -18,9 +18,9 @@ export default function SelectMethod() {
18
18
  const handleClick = () => {
19
19
  disconnect(account);
20
20
  };
21
- const { options } = useMethodOptions({
21
+ const { options, isLoading } = useMethodOptions({
22
22
  mode: paymentState.payOrder?.mode,
23
23
  onClick: handleClick,
24
24
  });
25
- return (_jsxs(PageContent, { children: [_jsx(OrderHeader, {}), _jsx(OptionsList, { requiredSkeletons: isMobile ? 3 : 4, options: options }), _jsx(PoweredByFooter, {})] }));
25
+ return (_jsxs(PageContent, { children: [_jsx(OrderHeader, {}), _jsx(OptionsList, { requiredSkeletons: 3, options: options, isLoading: isLoading }), _jsx(PoweredByFooter, {})] }));
26
26
  }
@@ -1,14 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import usePayContext from "../../contexts/pay";
3
2
  import { PageContent } from "../../ui/Modal/styles";
4
3
  import { OrderHeader } from "../../ui/OrderHeader";
5
4
  import OptionsList from "../../ui/OptionsList";
6
5
  import PoweredByFooter from "../../ui/PoweredByFooter";
7
6
  import { usePayToAddressChainOptions } from "../../../hooks/usePayToAddressChainOptions";
8
7
  export default function SelectPayToAddressChain() {
9
- const { paymentState } = usePayContext();
10
- const { payOrder } = paymentState;
11
- const fiatAmount = payOrder?.fulfillment.amount.value_usd;
12
- const { options, isLoading } = usePayToAddressChainOptions({ fiatAmount });
8
+ const { options, isLoading } = usePayToAddressChainOptions();
13
9
  return (_jsxs(PageContent, { children: [_jsx(OrderHeader, { minified: true }), _jsx(OptionsList, { isLoading: isLoading, requiredSkeletons: 4, options: options }), _jsx(PoweredByFooter, {})] }));
14
10
  }
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { ROUTES } from "../../../types/routes";
2
+ import { ROUTE } from "../../../types/routes";
3
3
  import { ModalBody, ModalContent, ModalH1, PageContent } from "../../ui/Modal/styles";
4
4
  import { useAccount } from "@coin-voyage/crypto/hooks";
5
5
  import { useCallback } from "react";
@@ -12,7 +12,7 @@ import SelectAnotherMethod from "../../ui/SelectAnotherMethod";
12
12
  export default function SelectToken() {
13
13
  const locales = useLocales();
14
14
  const { paymentState, allowedWallets, setRoute } = usePayContext();
15
- const { payOrderQuotes, selectedWallet, connectorChainType, setConnectorChainType, setSelectedCurrencyOption, } = paymentState;
15
+ const { payOrderQuotes, selectedWallet, connectorChainType, setConnectorChainType, setSelectedCurrencyOption } = paymentState;
16
16
  const { account } = useAccount({
17
17
  selectedWallet,
18
18
  chainType: connectorChainType,
@@ -23,7 +23,7 @@ export default function SelectToken() {
23
23
  const onSelectAnotherMethod = useCallback(() => {
24
24
  setConnectorChainType(undefined);
25
25
  setSelectedCurrencyOption(undefined);
26
- setRoute(ROUTES.SELECT_CHAIN);
26
+ setRoute(ROUTE.WALLET_CHAIN_SELECT);
27
27
  }, [setConnectorChainType, setSelectedCurrencyOption, setRoute]);
28
28
  return (_jsxs(PageContent, { children: [_jsx(OrderHeader, { minified: true, showConnectedWallet: true }), walletDisabled ? (_jsxs(ModalContent, { "$center": true, style: {
29
29
  paddingTop: 16,
@@ -1,9 +1,9 @@
1
- import { useConnectCallbackProps } from "@coin-voyage/crypto/hooks/use-connect-callback";
2
- import { WalletPermission } from "@coin-voyage/crypto/types/wallet";
1
+ import { useConnectCallbackProps } from "@coin-voyage/crypto/hooks";
2
+ import { WalletPermission } from "@coin-voyage/crypto/types";
3
3
  import React from "react";
4
4
  import type { PaymentState } from "../../../hooks/usePaymentState";
5
5
  import type { CustomTheme, Languages, Mode, PayKitOptions, PayModalOptions, Theme } from "../../../types";
6
- import type { ROUTES } from "../../../types/routes";
6
+ import type { ROUTE } from "../../../types/routes";
7
7
  export type PayContextValue = {
8
8
  theme: Theme;
9
9
  setTheme: React.Dispatch<React.SetStateAction<Theme>>;
@@ -18,8 +18,8 @@ export type PayContextValue = {
18
18
  open: boolean;
19
19
  setOpen: (open: boolean) => void;
20
20
  onSuccess: () => void;
21
- route: string;
22
- setRoute: React.Dispatch<React.SetStateAction<ROUTES>>;
21
+ route: ROUTE;
22
+ setRoute: React.Dispatch<React.SetStateAction<ROUTE>>;
23
23
  errorMessage: string | React.ReactNode | null;
24
24
  debugMode?: boolean;
25
25
  log: (...props: any) => void;
@@ -41,7 +41,7 @@ function PayButtonCustom(props) {
41
41
  },
42
42
  metadata: props.metadata,
43
43
  };
44
- }, [props]);
44
+ }, [hasDepositParams, props]);
45
45
  const payId = hasPayId ? props.payId : null;
46
46
  usePaymentLifecycle(order, {
47
47
  onPaymentStarted,
@@ -4,15 +4,15 @@ import { useCallback, useEffect, useRef, useState } from "react";
4
4
  import { ConnectingContainer, Container, Content, RetryButton, RetryIconContainer } from "./styles";
5
5
  import Alert from "../../ui/Alert";
6
6
  import Button from "../../ui/Button";
7
- import { ModalBody, ModalContent, ModalContentContainer, ModalH1, ModalHeading, PageContent, } from "../../ui/Modal/styles";
7
+ import { ModalBody, ModalContent, ModalContentContainer, ModalH1, PageContent } from "../../ui/Modal/styles";
8
8
  import Tooltip from "../../ui/Tooltip";
9
9
  import SquircleSpinner from "../../spinners/SquircleSpinner";
10
10
  import { useUniversalConnect } from "@coin-voyage/crypto/hooks";
11
- import { getConnectorId } from "@coin-voyage/crypto/lib/utils/connector";
12
- import { detectBrowser } from "@coin-voyage/shared/common";
11
+ import { getConnectorId } from "@coin-voyage/crypto/utils";
12
+ import { detectBrowser } from "@coin-voyage/shared/utils";
13
13
  import { AlertIcon, RetryIconCircle, TickIcon } from "../../../assets/icons";
14
14
  import useLocales from "../../../hooks/useLocales";
15
- import { ROUTES } from "../../../types/routes";
15
+ import { ROUTE } from "../../../types/routes";
16
16
  import { isInjectedConnector, isWalletConnectConnector } from "../../../utils";
17
17
  import usePayContext from "../../contexts/pay";
18
18
  import CircleSpinner from "../../spinners/CircleSpinner";
@@ -101,7 +101,7 @@ export default function ConnectWithInjector({ forceState }) {
101
101
  onSuccess(_, variables) {
102
102
  if (variables?.connector) {
103
103
  setStatus(states.CONNECTED);
104
- setRoute(ROUTES.SELECT_TOKEN);
104
+ setRoute(ROUTE.WALLET_TOKEN_SELECT);
105
105
  }
106
106
  },
107
107
  });
@@ -153,14 +153,14 @@ export default function ConnectWithInjector({ forceState }) {
153
153
  return () => clearTimeout(timeoutId);
154
154
  }, [status, runConnect]);
155
155
  if (!wallet) {
156
- return (_jsx(PageContent, { children: _jsxs(Container, { children: [_jsx(ModalHeading, { children: "Invalid State" }), _jsx(ModalContent, { children: _jsx(Alert, { children: "No connectors match the id given. This state should never happen." }) })] }) }));
156
+ return (_jsx(PageContent, { children: _jsx(Container, { children: _jsxs(ModalContent, { children: [_jsx(ModalH1, { "$error": true, children: "Invalid State" }), _jsx(Alert, { children: "No connectors match the id given. This state should never happen." })] }) }) }));
157
157
  }
158
158
  const connectorId = getConnectorId(wallet.connectors[0].connector);
159
159
  const isWalletConnect = isWalletConnectConnector(connectorId);
160
160
  const isInjected = isInjectedConnector(connectorId);
161
161
  // TODO: Make this more generic
162
162
  if (isWalletConnect) {
163
- return (_jsx(PageContent, { children: _jsxs(Container, { children: [_jsx(ModalHeading, { children: "Invalid State" }), _jsx(ModalContent, { children: _jsx(Alert, { children: "WalletConnect does not have an injection flow. This state should never happen." }) })] }) }));
163
+ return (_jsx(PageContent, { children: _jsx(Container, { children: _jsxs(ModalContent, { children: [_jsx(ModalH1, { "$error": true, children: "Invalid State" }), _jsx(Alert, { children: "WalletConnect does not have an injection flow. This state should never happen." })] }) }) }));
164
164
  }
165
165
  return (_jsx(PageContent, { children: _jsxs(Container, { children: [_jsx(ConnectingContainer, { children: _jsxs(AnimationContainer, { "$shake": status === states.FAILED || status === states.REJECTED, "$circle": walletInfo.iconShape === "circle", children: [_jsx(AnimatePresence, { children: (status === states.FAILED || status === states.REJECTED) && (_jsx(RetryButton, { "aria-label": "Retry", initial: { opacity: 0, scale: 0.8 }, animate: { opacity: 1, scale: 1 }, exit: { opacity: 0, scale: 0.8 }, whileTap: { scale: 0.9 }, transition: { duration: 0.1 }, onClick: runConnect, children: _jsx(RetryIconContainer, { children: _jsx(Tooltip, { open: showTryAgainTooltip && (status === states.FAILED || status === states.REJECTED), message: locales.tryAgainQuestion, xOffset: -6, children: _jsx(RetryIconCircle, {}) }) }) })) }), walletInfo.iconShape === "circle" ? (_jsx(CircleSpinner, { logo: status === states.UNAVAILABLE ? (_jsx("div", { style: {
166
166
  transform: "scale(1.14)",
@@ -5,7 +5,7 @@ import ScanIconWithLogos from "../../assets/scan-icon-with-logos";
5
5
  import useLocales from "../../hooks/useLocales";
6
6
  import { useWalletConnectModal } from "../../hooks/useWalletConnectModal";
7
7
  import { useWalletConnectUri } from "../../hooks/useWalletConnectUri";
8
- import { ROUTES } from "../../types/routes";
8
+ import { ROUTE } from "../../types/routes";
9
9
  import { isWalletConnectConnector } from "../../utils";
10
10
  import usePayContext from "../contexts/pay";
11
11
  import Button from "../ui/Button";
@@ -34,6 +34,6 @@ export default function ConnectWithQRCode() {
34
34
  justifyContent: "center",
35
35
  gap: 14,
36
36
  }, children: [context.options?.walletConnectCTA !== "modal" && (_jsx(CopyToClipboard, { variant: "button", text: uri, children: context.options?.walletConnectCTA === "link" ? locales.copyToClipboard : locales.copyCode })), context.options?.walletConnectCTA !== "link" && (_jsx(Button, { icon: _jsx(ExternalLinkIcon, {}), onClick: openW3M, disabled: isOpenW3M, waiting: isOpenW3M, children: context.options?.walletConnectCTA === "modal" ? locales.useWalletConnectModal : locales.useModal }))] })), hasApps && (_jsx(_Fragment, { children: _jsx(Button, { onClick: () => {
37
- context.setRoute(ROUTES.DOWNLOAD);
37
+ context.setRoute(ROUTE.DOWNLOAD);
38
38
  }, download: true, children: locales.getWalletName }) }))] }));
39
39
  }
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { getChainTypeName } from "@coin-voyage/shared/common";
2
+ import { getChainTypeName } from "@coin-voyage/shared/chain";
3
3
  import { useCallback, useMemo } from "react";
4
4
  import { routeConfig } from "../../config/route-config";
5
5
  import useLocales from "../../hooks/useLocales";
6
6
  import { ThemeProvider } from "../../providers/theme/provider";
7
- import { ROUTES } from "../../types/routes";
7
+ import { ROUTE } from "../../types/routes";
8
8
  import { isWalletConnectConnector } from "../../utils";
9
9
  import usePayContext from "../contexts/pay";
10
10
  import Modal from "../ui/Modal";
@@ -54,12 +54,12 @@ export function PayModal() {
54
54
  clearUserSelection();
55
55
  return;
56
56
  }
57
- if (typeof config.onBack === "string") {
58
- setRoute(config.onBack);
57
+ if (typeof config.onBack === "function") {
58
+ config.onBack(actions);
59
59
  }
60
60
  else {
61
- config.onBack(actions);
61
+ setRoute(config.onBack);
62
62
  }
63
63
  }, [config, actions, setRoute, clearUserSelection]);
64
- return (_jsx(ThemeProvider, { theme: theme, customTheme: customTheme, mode: mode, children: _jsx(Modal, { pages: pages, pageId: route, heading: heading, depth: depth, onClose: () => setOpen(false), onInfo: showInfoButton ? () => setRoute(ROUTES.ABOUT) : undefined, onBack: showBackButton ? onBack : undefined }) }));
64
+ return (_jsx(ThemeProvider, { theme: theme, customTheme: customTheme, mode: mode, children: _jsx(Modal, { pages: pages, pageId: route, heading: heading, depth: depth, onClose: () => setOpen(false), onInfo: showInfoButton ? () => setRoute(ROUTE.ABOUT) : undefined, onBack: showBackButton ? onBack : undefined }) }));
65
65
  }
@@ -1,6 +1,6 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
2
  import React from "react";
3
- import { detectBrowser } from "@coin-voyage/shared/common";
3
+ import { detectBrowser } from "@coin-voyage/shared/utils";
4
4
  import { BrowserIconContainer } from "./styles";
5
5
  import browsers from "../../../assets/browsers";
6
6
  const BrowserIcon = React.forwardRef(({ browser }, _ref) => {
@@ -5,7 +5,7 @@ import Alert from "../Alert";
5
5
  import { ChainButton, ChainButtonBg, ChainButtonContainer, ChainButtonStatus, ChainButtons, ChainIcon, ChainLogoContainer, ChainLogoSpinner, SwitchNetworksContainer, } from "./styles";
6
6
  import { AnimatePresence, motion } from "framer-motion";
7
7
  import { isCoinbaseWalletConnector } from "../../../utils";
8
- import { isMobile } from "@coin-voyage/shared/common";
8
+ import { isMobile } from "@coin-voyage/shared/utils";
9
9
  import ChainIcons from "../../../assets/chains";
10
10
  import useLocales from "../../../hooks/useLocales";
11
11
  import { chainConfigs } from "../../../lib/config/chain";
@@ -1,12 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ROUTES } from "../../../types/routes";
2
+ import { ROUTE } from "../../../types/routes";
3
3
  import { ConnectorButton, ConnectorIcon, ConnectorLabel, ConnectorsContainer, RecentlyUsedTag } from "./styles";
4
4
  import Alert from "../Alert";
5
5
  import { ScrollArea } from "../ScrollArea";
6
6
  import { useLastConnector, useUniversalConnect } from "@coin-voyage/crypto/hooks";
7
- import { isWalletInstalled } from "@coin-voyage/crypto/lib/utils/is-wallet-installed";
7
+ import { isWalletInstalled } from "@coin-voyage/crypto/utils";
8
+ import { detectBrowser } from "@coin-voyage/shared/utils";
8
9
  import { useIsMobile } from "@coin-voyage/shared/hooks";
9
- import { detectBrowser } from "@coin-voyage/shared/common";
10
10
  import { useCallback, useMemo } from "react";
11
11
  import useLocales from "../../../hooks/useLocales";
12
12
  import { useWalletConnectUri } from "../../../hooks/useWalletConnectUri";
@@ -48,7 +48,7 @@ const ConnectorItem = ({ wallet, isRecent, walletConnectURI, }) => {
48
48
  const { connect } = useUniversalConnect({
49
49
  onSuccess: (_, variables) => {
50
50
  if (variables?.connector) {
51
- setRoute(ROUTES.SELECT_TOKEN);
51
+ setRoute(ROUTE.WALLET_TOKEN_SELECT);
52
52
  }
53
53
  },
54
54
  onError: (error) => {
@@ -82,7 +82,7 @@ const ConnectorItem = ({ wallet, isRecent, walletConnectURI, }) => {
82
82
  if (deeplink)
83
83
  return;
84
84
  if (redirectToMoreWallets) {
85
- setRoute(ROUTES.MOBILECONNECTORS);
85
+ setRoute(ROUTE.MOBILECONNECTORS);
86
86
  return;
87
87
  }
88
88
  if (shouldConnectImmediately) {
@@ -92,7 +92,7 @@ const ConnectorItem = ({ wallet, isRecent, walletConnectURI, }) => {
92
92
  connect({ walletConnector });
93
93
  }
94
94
  paymentState.setSelectedWallet(wallet);
95
- setRoute(ROUTES.CONNECT);
95
+ setRoute(ROUTE.CONNECT);
96
96
  }, [deeplink, redirectToMoreWallets, shouldConnectImmediately, wallet, paymentState, setRoute, connect]);
97
- return (_jsxs(ConnectorButton, { type: "button", as: deeplink ? "a" : undefined, href: deeplink, disabled: route !== ROUTES.CONNECTORS, onClick: handleClick, children: [_jsx(ConnectorIcon, { "data-small": wallet.iconShouldShrink, "data-shape": wallet.iconShape, children: wallet.iconConnector ?? wallet.icon }), _jsxs(ConnectorLabel, { children: [isMobile ? (wallet.shortName ?? wallet.name) : wallet.name, !options?.hideRecentBadge && isRecent && _jsx(RecentlyUsedTag, { children: locales.recent })] })] }));
97
+ return (_jsxs(ConnectorButton, { type: "button", as: deeplink ? "a" : undefined, href: deeplink, disabled: route !== ROUTE.CONNECTORS, onClick: handleClick, children: [_jsx(ConnectorIcon, { "data-small": wallet.iconShouldShrink, "data-shape": wallet.iconShape, children: wallet.iconConnector ?? wallet.icon }), _jsxs(ConnectorLabel, { children: [isMobile ? (wallet.shortName ?? wallet.name) : wallet.name, !options?.hideRecentBadge && isRecent && _jsx(RecentlyUsedTag, { children: locales.recent })] })] }));
98
98
  };
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { formatTime } from "@coin-voyage/shared/common";
2
+ import { formatTime } from "@coin-voyage/shared/utils";
3
3
  import useLocales from "../../../hooks/useLocales";
4
4
  import CircleTimer from "../CircleTimer";
5
5
  import { ModalBody } from "../Modal/styles";
@@ -1,8 +1,8 @@
1
1
  import type React from "react";
2
- import { ROUTES } from "../../../types/routes";
2
+ import { ROUTE } from "../../../types/routes";
3
3
  type ModalPageRendererProps = {
4
- pages: Record<ROUTES, React.ReactNode>;
5
- pageId: string;
4
+ pages: Record<ROUTE, React.ReactNode>;
5
+ pageId: ROUTE;
6
6
  currentDepth: number;
7
7
  prevDepth: number;
8
8
  positionInside?: boolean;
@@ -3,7 +3,10 @@ import { useEffect } from "react";
3
3
  import { useTransition } from "react-transition-state";
4
4
  import { InnerContainer, PageContainer, PageContents } from "./styles";
5
5
  export function ModalPageRenderer({ pages, pageId, currentDepth, prevDepth, positionInside, transitionState, contentRef, rendered, }) {
6
- return (_jsx(InnerContainer, { children: Object.keys(pages).map((key) => (_jsx(Page, { open: key === pageId, initial: !positionInside && transitionState !== "entered", enterAnim: key === pageId && currentDepth > prevDepth ? "active-scale-up" : "active", exitAnim: key !== pageId && currentDepth < prevDepth ? "exit-scale-down" : "exit", children: _jsx(PageContents, { ref: contentRef, style: { pointerEvents: key === pageId && rendered ? "auto" : "none" }, children: pages[key] }, `inner-${key}`) }, key))) }));
6
+ return (_jsx(InnerContainer, { children: Object.keys(pages).map((key) => {
7
+ const routeKey = Number(key);
8
+ return (_jsx(Page, { open: routeKey === pageId, initial: !positionInside && transitionState !== "entered", enterAnim: routeKey === pageId && currentDepth > prevDepth ? "active-scale-up" : "active", exitAnim: routeKey !== pageId && currentDepth < prevDepth ? "exit-scale-down" : "exit", children: _jsx(PageContents, { ref: contentRef, style: { pointerEvents: routeKey === pageId && rendered ? "auto" : "none" }, children: pages[routeKey] }, `inner-${routeKey}`) }, routeKey));
9
+ }) }));
7
10
  }
8
11
  const Page = ({ children, open, initial, enterAnim, exitAnim }) => {
9
12
  const [state, setOpen] = useTransition({