@coin-voyage/paykit 2.3.6-beta.0 → 2.3.6-beta.2
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/dist/assets/icons.d.ts +3 -0
- package/dist/assets/icons.js +3 -0
- package/dist/components/Pages/CardPayment/index.d.ts +1 -0
- package/dist/components/Pages/CardPayment/index.js +214 -0
- package/dist/components/Pages/MobileConnectors/index.js +2 -2
- package/dist/components/Pages/PayToAddress/index.js +2 -2
- package/dist/components/Pages/PayWithToken/index.js +3 -3
- package/dist/components/Pages/SelectChain/index.js +2 -2
- package/dist/components/Pages/SelectMethod/index.js +2 -2
- package/dist/components/Pages/SelectToken/index.js +3 -3
- package/dist/components/contexts/pay/index.d.ts +3 -3
- package/dist/components/pay-button/index.js +1 -1
- package/dist/components/pay-modal/ConnectWithInjector/index.js +2 -2
- package/dist/components/pay-modal/ConnectWithQRCode.js +2 -2
- package/dist/components/pay-modal/index.js +5 -5
- package/dist/components/ui/ConnectorList/index.js +6 -6
- package/dist/components/ui/Modal/ModalPageRenderer.d.ts +3 -3
- package/dist/components/ui/Modal/ModalPageRenderer.js +4 -1
- package/dist/components/ui/Modal/index.d.ts +3 -3
- package/dist/components/ui/Modal/index.js +2 -2
- package/dist/components/ui/Modal/styles.js +21 -0
- package/dist/config/route-config.d.ts +2 -2
- package/dist/config/route-config.js +34 -26
- package/dist/hooks/useChainOptions.js +2 -2
- package/dist/hooks/useDepositAddressQuery.js +5 -1
- package/dist/hooks/useMethodOptions.d.ts +1 -0
- package/dist/hooks/useMethodOptions.js +85 -26
- package/dist/hooks/usePayToAddressChainOptions.js +2 -2
- package/dist/hooks/usePayToAddressTokens.js +2 -2
- package/dist/hooks/usePayWithCard.d.ts +10 -0
- package/dist/hooks/usePayWithCard.js +24 -0
- package/dist/hooks/usePayWithToken.js +19 -10
- package/dist/hooks/usePaymentLifecycle.js +3 -1
- package/dist/hooks/usePaymentState.d.ts +4 -4
- package/dist/hooks/usePaymentState.js +9 -2
- package/dist/hooks/useTokenOptions.js +2 -2
- package/dist/hooks/useWalletConnectModal.js +2 -2
- package/dist/hooks/useWalletConnectUri.js +2 -2
- package/dist/providers/paykit-provider.js +139 -122
- package/dist/types/route-config.d.ts +3 -3
- package/dist/types/routes.d.ts +17 -16
- package/dist/types/routes.js +20 -18
- package/dist/types/state.d.ts +2 -2
- package/dist/types.d.ts +4 -0
- package/package.json +5 -3
- package/dist/types/enums.d.ts +0 -4
- package/dist/types/enums.js +0 -5
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { getChainName } from "@coin-voyage/shared/common";
|
|
3
3
|
import About from "../components/Pages/About";
|
|
4
|
+
import CardPayment from "../components/Pages/CardPayment";
|
|
4
5
|
import Confirmation from "../components/Pages/Confirmation";
|
|
5
6
|
import Connectors from "../components/Pages/Connectors";
|
|
6
7
|
import DownloadApp from "../components/Pages/DownloadApp";
|
|
@@ -15,92 +16,99 @@ import SelectPayToAddressToken from "../components/Pages/SelectPayToAddressToken
|
|
|
15
16
|
import SelectToken from "../components/Pages/SelectToken";
|
|
16
17
|
import SwitchNetworks from "../components/Pages/SwitchNetworks";
|
|
17
18
|
import ConnectUsing from "../components/pay-modal/ConnectUsing";
|
|
18
|
-
import {
|
|
19
|
+
import { ROUTE } from "../types/routes";
|
|
19
20
|
export const routeConfig = {
|
|
20
|
-
[
|
|
21
|
+
[ROUTE.SELECT_METHOD]: {
|
|
21
22
|
component: _jsx(SelectMethod, {}),
|
|
22
23
|
heading: (ctx) => ctx.locales.selectMethodScreen_heading,
|
|
23
24
|
showBackButton: false,
|
|
24
25
|
},
|
|
26
|
+
[ROUTE.CARD_PAYMENT]: {
|
|
27
|
+
component: _jsx(CardPayment, {}),
|
|
28
|
+
heading: () => "Pay with Card",
|
|
29
|
+
onBack: (actions) => {
|
|
30
|
+
actions.setRoute(ROUTE.SELECT_METHOD);
|
|
31
|
+
},
|
|
32
|
+
},
|
|
25
33
|
// Pay to address routes
|
|
26
|
-
[
|
|
34
|
+
[ROUTE.ADDRESS_CHAIN_SELECT]: {
|
|
27
35
|
component: _jsx(SelectPayToAddressChain, {}),
|
|
28
36
|
heading: (ctx) => ctx.locales.selectPayToAddressChainScreen_heading,
|
|
29
37
|
onBack: (actions) => {
|
|
30
|
-
actions.setRoute(
|
|
38
|
+
actions.setRoute(ROUTE.SELECT_METHOD);
|
|
31
39
|
},
|
|
32
40
|
},
|
|
33
|
-
[
|
|
41
|
+
[ROUTE.ADDRESS_TOKEN_SELECT]: {
|
|
34
42
|
component: _jsx(SelectPayToAddressToken, {}),
|
|
35
43
|
heading: (ctx) => ctx.locales.selectPayToAddressTokenScreen_heading,
|
|
36
44
|
onBack: (actions) => {
|
|
37
45
|
actions.setPayToAddressChain(undefined);
|
|
38
|
-
actions.setRoute(
|
|
46
|
+
actions.setRoute(ROUTE.ADDRESS_CHAIN_SELECT);
|
|
39
47
|
},
|
|
40
48
|
},
|
|
41
|
-
[
|
|
49
|
+
[ROUTE.PAY_TO_ADDRESS]: {
|
|
42
50
|
component: _jsx(PayToAddress, {}),
|
|
43
51
|
heading: (ctx) => ctx.locales.payToAddressWaitingScreen_heading,
|
|
44
52
|
onBack: (actions) => {
|
|
45
53
|
actions.setPayToAddressCurrency(undefined);
|
|
46
|
-
actions.setRoute(
|
|
54
|
+
actions.setRoute(ROUTE.ADDRESS_TOKEN_SELECT);
|
|
47
55
|
},
|
|
48
56
|
},
|
|
49
57
|
// Pay with token routes
|
|
50
|
-
[
|
|
58
|
+
[ROUTE.WALLET_CHAIN_SELECT]: {
|
|
51
59
|
component: _jsx(SelectChain, {}),
|
|
52
60
|
heading: (ctx) => ctx.locales.selectChainScreen_heading,
|
|
53
61
|
onBack: (actions) => {
|
|
54
|
-
actions.setRoute(
|
|
62
|
+
actions.setRoute(ROUTE.SELECT_METHOD);
|
|
55
63
|
},
|
|
56
64
|
},
|
|
57
|
-
[
|
|
65
|
+
[ROUTE.WALLET_TOKEN_SELECT]: {
|
|
58
66
|
component: _jsx(SelectToken, {}),
|
|
59
67
|
heading: (ctx) => ctx.locales.selectTokenScreen_heading,
|
|
60
68
|
onBack: (actions) => {
|
|
61
69
|
actions.setConnectorChainType(undefined);
|
|
62
|
-
actions.setRoute(
|
|
70
|
+
actions.setRoute(ROUTE.WALLET_CHAIN_SELECT);
|
|
63
71
|
},
|
|
64
72
|
},
|
|
65
|
-
[
|
|
73
|
+
[ROUTE.WALLET_PAYMENT]: {
|
|
66
74
|
component: _jsx(PayWithToken, {}),
|
|
67
75
|
heading: (ctx) => ctx.selectedCurrencyOption
|
|
68
76
|
? `Pay with ${ctx.selectedCurrencyOption.ticker} on ${getChainName(ctx.selectedCurrencyOption.chain_id)}`
|
|
69
77
|
: undefined,
|
|
70
78
|
onBack: (actions) => {
|
|
71
79
|
actions.setSelectedCurrencyOption(undefined);
|
|
72
|
-
actions.setRoute(
|
|
80
|
+
actions.setRoute(ROUTE.WALLET_TOKEN_SELECT);
|
|
73
81
|
},
|
|
74
82
|
},
|
|
75
|
-
[
|
|
83
|
+
[ROUTE.CONFIRMATION]: {
|
|
76
84
|
component: _jsx(Confirmation, {}),
|
|
77
85
|
heading: (ctx) => ctx.locales.confirmationScreen_heading,
|
|
78
86
|
showBackButton: false,
|
|
79
87
|
showInfoButton: false,
|
|
80
88
|
},
|
|
81
|
-
[
|
|
89
|
+
[ROUTE.ONBOARDING]: {
|
|
82
90
|
component: _jsx(Onboarding, {}),
|
|
83
91
|
heading: (ctx) => ctx.locales.onboardingScreen_heading,
|
|
84
|
-
onBack:
|
|
92
|
+
onBack: ROUTE.SELECT_METHOD,
|
|
85
93
|
},
|
|
86
|
-
[
|
|
94
|
+
[ROUTE.ABOUT]: {
|
|
87
95
|
component: _jsx(About, {}),
|
|
88
96
|
heading: (ctx) => ctx.locales.aboutScreen_heading,
|
|
89
97
|
},
|
|
90
|
-
[
|
|
98
|
+
[ROUTE.CONNECTORS]: {
|
|
91
99
|
component: _jsx(Connectors, {}),
|
|
92
100
|
heading: (ctx) => ctx.locales.connectorsScreen_heading,
|
|
93
101
|
depth: 0,
|
|
94
102
|
onBack: (actions) => {
|
|
95
103
|
actions.setConnectorChainType(undefined);
|
|
96
|
-
actions.setRoute(
|
|
104
|
+
actions.setRoute(ROUTE.SELECT_METHOD);
|
|
97
105
|
},
|
|
98
106
|
},
|
|
99
|
-
[
|
|
107
|
+
[ROUTE.MOBILECONNECTORS]: {
|
|
100
108
|
component: _jsx(MobileConnectors, {}),
|
|
101
109
|
heading: (ctx) => ctx.locales.connectorsScreen_heading,
|
|
102
110
|
},
|
|
103
|
-
[
|
|
111
|
+
[ROUTE.CONNECT]: {
|
|
104
112
|
component: _jsx(ConnectUsing, {}),
|
|
105
113
|
heading: (ctx) => {
|
|
106
114
|
if (ctx.shouldUseQrcode) {
|
|
@@ -110,15 +118,15 @@ export const routeConfig = {
|
|
|
110
118
|
}
|
|
111
119
|
return ctx.walletName;
|
|
112
120
|
},
|
|
113
|
-
onBack:
|
|
121
|
+
onBack: ROUTE.CONNECTORS,
|
|
114
122
|
},
|
|
115
|
-
[
|
|
123
|
+
[ROUTE.DOWNLOAD]: {
|
|
116
124
|
component: _jsx(DownloadApp, {}),
|
|
117
125
|
heading: (ctx) => ctx.locales.downloadAppScreen_heading,
|
|
118
126
|
depth: 2,
|
|
119
|
-
onBack:
|
|
127
|
+
onBack: ROUTE.CONNECT,
|
|
120
128
|
},
|
|
121
|
-
[
|
|
129
|
+
[ROUTE.SWITCHNETWORKS]: {
|
|
122
130
|
component: _jsx(SwitchNetworks, {}),
|
|
123
131
|
heading: (ctx) => ctx.locales.switchNetworkScreen_heading,
|
|
124
132
|
},
|
|
@@ -10,7 +10,7 @@ import Logos from "../assets/chains";
|
|
|
10
10
|
import { MetaMask } from "../assets/logos";
|
|
11
11
|
import usePayContext from "../components/contexts/pay";
|
|
12
12
|
import { SquircleIcon } from "../components/ui/Icon";
|
|
13
|
-
import {
|
|
13
|
+
import { ROUTE } from "../types/routes";
|
|
14
14
|
function getTitle(subject, isDeposit) {
|
|
15
15
|
return `${isDeposit ? "Deposit from" : "Pay on"} ${subject}`;
|
|
16
16
|
}
|
|
@@ -29,7 +29,7 @@ export function useChainOptions({ account, mode, onClick }) {
|
|
|
29
29
|
: "wallet", [paymentState.senderEnsName, account.address]);
|
|
30
30
|
const handleConnectedWalletClick = useCallback(() => {
|
|
31
31
|
paymentState.setConnectorChainType(account.chainType);
|
|
32
|
-
setRoute(
|
|
32
|
+
setRoute(ROUTE.WALLET_TOKEN_SELECT);
|
|
33
33
|
}, [paymentState, account.chainType, setRoute]);
|
|
34
34
|
const connectedWalletIcon = useMemo(() => {
|
|
35
35
|
return account.connector?.icon
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getDepositAddress } from "@coin-voyage/shared/common";
|
|
1
2
|
import { useQuery } from "@tanstack/react-query";
|
|
2
3
|
import usePayContext from "../components/contexts/pay";
|
|
3
4
|
export function useDepositAddressQuery({ enabled }) {
|
|
@@ -22,9 +23,12 @@ export function useDepositAddressQuery({ enabled }) {
|
|
|
22
23
|
});
|
|
23
24
|
if (!response)
|
|
24
25
|
throw new Error("no-response");
|
|
26
|
+
const depositAddress = getDepositAddress(response.data);
|
|
27
|
+
if (!depositAddress)
|
|
28
|
+
throw new Error("Deposit address is unavailable for this pay order");
|
|
25
29
|
return {
|
|
26
30
|
...currency,
|
|
27
|
-
depositAddress
|
|
31
|
+
depositAddress,
|
|
28
32
|
amount: response.data.src.total.ui_amount.toString(),
|
|
29
33
|
ticker: response.data.src.ticker,
|
|
30
34
|
expirationS: Math.floor(new Date(response.data.expires_at).getTime() / 1000),
|
|
@@ -1,40 +1,99 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { PayOrderMode } from "@coin-voyage/shared/types";
|
|
2
|
+
import { PaymentMethod, PayOrderMode } from "@coin-voyage/shared/types";
|
|
3
|
+
import { useQuery } from "@tanstack/react-query";
|
|
4
|
+
import { useMemo } from "react";
|
|
3
5
|
import ChainLogos from "../assets/chains";
|
|
6
|
+
import { CreditCardIcon } from "../assets/icons";
|
|
4
7
|
import Logos from "../assets/logos";
|
|
8
|
+
import { useBackendApi } from "../components/contexts/api";
|
|
5
9
|
import usePayContext from "../components/contexts/pay";
|
|
6
|
-
import {
|
|
7
|
-
import { ROUTES } from "../types/routes";
|
|
10
|
+
import { ROUTE } from "../types/routes";
|
|
8
11
|
function getTitle(subject, isDeposit) {
|
|
9
12
|
return `${isDeposit ? "Deposit" : "Pay"} ${subject}`;
|
|
10
13
|
}
|
|
11
14
|
export function useMethodOptions({ mode, onClick }) {
|
|
12
|
-
const
|
|
13
|
-
const {
|
|
15
|
+
const api = useBackendApi();
|
|
16
|
+
const { setRoute, paymentState, options: contextOptions } = usePayContext();
|
|
17
|
+
const { payOrder, setPaymentMethod } = paymentState;
|
|
14
18
|
const isDeposit = mode === PayOrderMode.DEPOSIT;
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
const shouldCheckCardAvailability = contextOptions?.experimentalFeatures?.cardPayments === true;
|
|
20
|
+
const { data: paymentMethods, isLoading } = useQuery({
|
|
21
|
+
queryKey: ["payment-methods", payOrder?.id],
|
|
22
|
+
enabled: shouldCheckCardAvailability && Boolean(payOrder?.id),
|
|
23
|
+
retry: false,
|
|
24
|
+
refetchOnWindowFocus: false,
|
|
25
|
+
queryFn: async () => {
|
|
26
|
+
if (!payOrder?.id) {
|
|
27
|
+
throw new Error("Missing pay order");
|
|
28
|
+
}
|
|
29
|
+
const response = await api.getPayOrderPaymentMethods(payOrder.id);
|
|
30
|
+
if (response.error || !response.data) {
|
|
31
|
+
throw new Error(response.error?.message ?? "Unable to load payment methods");
|
|
32
|
+
}
|
|
33
|
+
return response.data;
|
|
26
34
|
},
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
});
|
|
36
|
+
const options = useMemo(() => {
|
|
37
|
+
const nextOptions = [
|
|
38
|
+
{
|
|
39
|
+
id: PaymentMethod.WALLET,
|
|
40
|
+
title: getTitle("with Wallet", isDeposit),
|
|
41
|
+
iconShape: "squircle",
|
|
42
|
+
icons: [_jsx(Logos.MetaMask, {}, "metamask"), _jsx(Logos.Rainbow, {}, "rainbow"), _jsx(Logos.Phantom, {}, "phantom")],
|
|
43
|
+
onClick: () => {
|
|
44
|
+
setPaymentMethod(PaymentMethod.WALLET);
|
|
45
|
+
setRoute(ROUTE.WALLET_CHAIN_SELECT);
|
|
46
|
+
onClick();
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: PaymentMethod.DEPOSIT_ADDRESS,
|
|
51
|
+
title: getTitle("to Address", isDeposit),
|
|
52
|
+
iconShape: "circle",
|
|
53
|
+
icons: [
|
|
54
|
+
_jsx(ChainLogos.Ethereum, {}, "ethereum"),
|
|
55
|
+
_jsx(ChainLogos.Base, {}, "base"),
|
|
56
|
+
_jsx(ChainLogos.Arbitrum, {}, "arbitrum"),
|
|
57
|
+
],
|
|
58
|
+
onClick: () => {
|
|
59
|
+
setPaymentMethod(PaymentMethod.DEPOSIT_ADDRESS);
|
|
60
|
+
setRoute(ROUTE.ADDRESS_CHAIN_SELECT);
|
|
61
|
+
onClick();
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
if (!shouldCheckCardAvailability) {
|
|
66
|
+
return nextOptions;
|
|
67
|
+
}
|
|
68
|
+
const cardMethod = paymentMethods?.methods.find((m) => m.method === PaymentMethod.CARD);
|
|
69
|
+
if (!cardMethod) {
|
|
70
|
+
return nextOptions;
|
|
71
|
+
}
|
|
72
|
+
nextOptions.push({
|
|
73
|
+
id: PaymentMethod.CARD,
|
|
74
|
+
title: getTitle("with Card", isDeposit),
|
|
75
|
+
subtitle: !cardMethod.available
|
|
76
|
+
? (cardMethod.reason ?? formatMinimumAmount(cardMethod.minimum_amount))
|
|
77
|
+
: undefined,
|
|
78
|
+
disabled: !cardMethod.available,
|
|
79
|
+
iconShape: "squircle",
|
|
80
|
+
icons: [_jsx(CreditCardIcon, {}, "stripe")],
|
|
32
81
|
onClick: () => {
|
|
33
|
-
|
|
34
|
-
|
|
82
|
+
if (!cardMethod.available) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
setPaymentMethod(PaymentMethod.CARD);
|
|
86
|
+
setRoute(ROUTE.CARD_PAYMENT);
|
|
35
87
|
onClick();
|
|
36
88
|
},
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
89
|
+
});
|
|
90
|
+
return nextOptions;
|
|
91
|
+
}, [isDeposit, onClick, paymentMethods?.methods, setPaymentMethod, setRoute, shouldCheckCardAvailability]);
|
|
92
|
+
return { options, isLoading };
|
|
93
|
+
}
|
|
94
|
+
function formatMinimumAmount(minimumAmount) {
|
|
95
|
+
if (!minimumAmount) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
return `Minimum ${minimumAmount.amount} ${minimumAmount.unit}`;
|
|
40
99
|
}
|
|
@@ -5,7 +5,7 @@ import { useQuery } from "@tanstack/react-query";
|
|
|
5
5
|
import { useMemo } from "react";
|
|
6
6
|
import usePayContext from "../components/contexts/pay";
|
|
7
7
|
import { SquircleIcon } from "../components/ui/Icon";
|
|
8
|
-
import {
|
|
8
|
+
import { ROUTE } from "../types/routes";
|
|
9
9
|
const BTC_MIN_USD_AMOUNT = 15;
|
|
10
10
|
const TOKEN_LIST_QUERY_KEY = ["token-list"];
|
|
11
11
|
export function usePayToAddressChainOptions({ fiatAmount }) {
|
|
@@ -23,7 +23,7 @@ export function usePayToAddressChainOptions({ fiatAmount }) {
|
|
|
23
23
|
icons: [_jsx(SquircleIcon, { icon: chain.logoURI, alt: chain.name }, chain.chainId)],
|
|
24
24
|
onClick: () => {
|
|
25
25
|
setPayToAddressChain(chain.chainId);
|
|
26
|
-
setRoute(
|
|
26
|
+
setRoute(ROUTE.ADDRESS_TOKEN_SELECT);
|
|
27
27
|
},
|
|
28
28
|
disabled: chain.chainId === ChainId.BTC && typeof fiatAmount === "number" && fiatAmount < BTC_MIN_USD_AMOUNT,
|
|
29
29
|
})), [chains, fiatAmount, setPayToAddressChain, setRoute]);
|
|
@@ -4,7 +4,7 @@ import { useQuery } from "@tanstack/react-query";
|
|
|
4
4
|
import { useMemo } from "react";
|
|
5
5
|
import usePayContext from "../components/contexts/pay";
|
|
6
6
|
import { SquircleIcon } from "../components/ui/Icon";
|
|
7
|
-
import {
|
|
7
|
+
import { ROUTE } from "../types/routes";
|
|
8
8
|
const TOKEN_LIST_QUERY_KEY = ["token-list"];
|
|
9
9
|
export function usePayToAddressTokens() {
|
|
10
10
|
const { paymentState, setRoute } = usePayContext();
|
|
@@ -29,7 +29,7 @@ export function usePayToAddressTokens() {
|
|
|
29
29
|
onClick: () => {
|
|
30
30
|
const currency = tokenToCurrency(token);
|
|
31
31
|
setPayToAddressCurrency(currency);
|
|
32
|
-
setRoute(
|
|
32
|
+
setRoute(ROUTE.PAY_TO_ADDRESS);
|
|
33
33
|
},
|
|
34
34
|
})), [tokens, setPayToAddressCurrency, setRoute]);
|
|
35
35
|
return { options, isLoading };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type PaymentDetails, type PayOrder } from "@coin-voyage/shared/types";
|
|
2
|
+
interface PayWithCardParams {
|
|
3
|
+
payOrder: PayOrder | undefined;
|
|
4
|
+
setPayOrder: (order: PayOrder) => void;
|
|
5
|
+
log: (message: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function usePayWithCard({ payOrder, setPayOrder, log }: PayWithCardParams): {
|
|
8
|
+
payWithCard: () => Promise<PaymentDetails>;
|
|
9
|
+
};
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { assert } from "@coin-voyage/shared/common";
|
|
2
|
+
import { PaymentRail } from "@coin-voyage/shared/types";
|
|
3
|
+
import { useBackendApi } from "../components/contexts/api";
|
|
4
|
+
import { fetchPaymentDetails } from "../lib/api/payment-details";
|
|
5
|
+
export function usePayWithCard({ payOrder, setPayOrder, log }) {
|
|
6
|
+
const api = useBackendApi();
|
|
7
|
+
const payWithCard = async () => {
|
|
8
|
+
assert(payOrder != undefined, "PayOrder is required");
|
|
9
|
+
const params = {
|
|
10
|
+
payorder_id: payOrder.id,
|
|
11
|
+
payment_rail: PaymentRail.FIAT,
|
|
12
|
+
};
|
|
13
|
+
// const paymentDetails = stub as unknown as PaymentDetails
|
|
14
|
+
const paymentDetails = await fetchPaymentDetails(api, params, payOrder);
|
|
15
|
+
log(`[PAY-WITH-CARD] Created Stripe onramp session: ${JSON.stringify(paymentDetails)}`);
|
|
16
|
+
setPayOrder({
|
|
17
|
+
...payOrder,
|
|
18
|
+
payment: paymentDetails.data,
|
|
19
|
+
status: paymentDetails.status,
|
|
20
|
+
});
|
|
21
|
+
return paymentDetails;
|
|
22
|
+
};
|
|
23
|
+
return { payWithCard };
|
|
24
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { usePrepareTransaction } from "@coin-voyage/crypto/hooks";
|
|
2
|
-
import { assert } from "@coin-voyage/shared/common";
|
|
2
|
+
import { assert, getDepositAddress, getWalletPaymentData } from "@coin-voyage/shared/common";
|
|
3
3
|
import { useBackendApi } from "../components/contexts/api";
|
|
4
4
|
import { fetchPaymentDetails } from "../lib/api/payment-details";
|
|
5
5
|
export function usePayFromWallet({ senderAddr, payOrder, setPayOrder, chainType, log }) {
|
|
@@ -23,15 +23,24 @@ export function usePayFromWallet({ senderAddr, payOrder, setPayOrder, chainType,
|
|
|
23
23
|
const paymentData = paymentDetails.data;
|
|
24
24
|
log(`[PAY-WITH-TOKEN] Final Quote for Order: ${JSON.stringify(paymentDetails)}, params: ${JSON.stringify(params)}`);
|
|
25
25
|
try {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
:
|
|
34
|
-
|
|
26
|
+
const walletPaymentData = getWalletPaymentData(paymentData);
|
|
27
|
+
const depositAddress = getDepositAddress(paymentData);
|
|
28
|
+
assert(Boolean(walletPaymentData || depositAddress), "Payment step is missing executable wallet data");
|
|
29
|
+
const txHash = walletPaymentData
|
|
30
|
+
? await actions.execute({
|
|
31
|
+
from: senderAddr,
|
|
32
|
+
chainId: paymentData.src.chain_id,
|
|
33
|
+
paymentData: walletPaymentData,
|
|
34
|
+
})
|
|
35
|
+
: await actions.execute({
|
|
36
|
+
amount: BigInt(paymentData.src.currency_amount.raw_amount),
|
|
37
|
+
from: senderAddr,
|
|
38
|
+
to: depositAddress,
|
|
39
|
+
chainId: paymentData.src.chain_id,
|
|
40
|
+
token: paymentData.src.address
|
|
41
|
+
? { address: paymentData.src.address, decimals: paymentData.src.decimals }
|
|
42
|
+
: undefined,
|
|
43
|
+
});
|
|
35
44
|
setPayOrder({
|
|
36
45
|
...payOrder,
|
|
37
46
|
deposit_tx_hash: txHash,
|
|
@@ -56,7 +56,7 @@ export function usePaymentLifecycle(order, handlers) {
|
|
|
56
56
|
status: order.status,
|
|
57
57
|
metadata: order.metadata,
|
|
58
58
|
refund_address: order.payment.refund_address,
|
|
59
|
-
refund_tx_hash: order.refund_tx_hash ?? "",
|
|
59
|
+
refund_tx_hash: order.payment.refund_tx_hash ?? "",
|
|
60
60
|
});
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
@@ -66,6 +66,8 @@ export function usePaymentLifecycle(order, handlers) {
|
|
|
66
66
|
status: order.status,
|
|
67
67
|
metadata: order.metadata,
|
|
68
68
|
payment_data: order.payment,
|
|
69
|
+
source_tx_hash: order.payment.source_tx_hash ?? "",
|
|
70
|
+
destination_tx_hash: order.payment.destination_tx_hash ?? "",
|
|
69
71
|
});
|
|
70
72
|
}, [order, isFinalized, onPaymentCompleted, onPaymentBounced]);
|
|
71
73
|
return { isStarted, isFinalized, order };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { WalletProps } from "@coin-voyage/crypto/types/wallet";
|
|
2
|
-
import { ChainId, ChainType, Currency, CurrencyBase, type PayOrder } from "@coin-voyage/shared/types";
|
|
2
|
+
import { ChainId, ChainType, Currency, CurrencyBase, PaymentMethod, type PayOrder } from "@coin-voyage/shared/types";
|
|
3
3
|
import { PaymentDetails, PayOrderParams } from "@coin-voyage/shared/types/api";
|
|
4
|
-
import {
|
|
5
|
-
import { ROUTES } from "../types/routes";
|
|
4
|
+
import { ROUTE } from "../types/routes";
|
|
6
5
|
import { CurrencyAndQuoteID } from "../types/state";
|
|
7
6
|
import { usePayOrderQuotes } from "./usePayOrderQuotes";
|
|
8
7
|
/** Loads a PayOrder + manages the corresponding modal. */
|
|
@@ -22,6 +21,7 @@ export interface PaymentState {
|
|
|
22
21
|
selectedCurrencyOption: CurrencyAndQuoteID | undefined;
|
|
23
22
|
setSelectedCurrencyOption: (option: CurrencyAndQuoteID | undefined) => void;
|
|
24
23
|
payFromWallet: (currency: CurrencyAndQuoteID) => Promise<string | undefined>;
|
|
24
|
+
payWithCard: () => Promise<PaymentDetails>;
|
|
25
25
|
payToAddress: (currency: CurrencyBase) => Promise<PaymentDetails | undefined>;
|
|
26
26
|
refreshOrder: () => Promise<void>;
|
|
27
27
|
senderEnsName: string | undefined;
|
|
@@ -33,6 +33,6 @@ export interface PaymentState {
|
|
|
33
33
|
export declare function usePaymentState({ payOrder, setPayOrder, setRoute, log, }: {
|
|
34
34
|
payOrder: PayOrder | undefined;
|
|
35
35
|
setPayOrder: (o: PayOrder) => void;
|
|
36
|
-
setRoute: React.Dispatch<React.SetStateAction<
|
|
36
|
+
setRoute: React.Dispatch<React.SetStateAction<ROUTE>>;
|
|
37
37
|
log: (...args: unknown[]) => void;
|
|
38
38
|
}): PaymentState;
|
|
@@ -6,9 +6,10 @@ import { useCallback, useState } from "react";
|
|
|
6
6
|
import { mainnet } from "viem/chains";
|
|
7
7
|
import { useEnsName } from "wagmi";
|
|
8
8
|
import { useBackendApi } from "../components/contexts/api";
|
|
9
|
-
import {
|
|
9
|
+
import { ROUTE } from "../types/routes";
|
|
10
10
|
import { usePayOrderQuotes } from "./usePayOrderQuotes";
|
|
11
11
|
import { usePayToAddress } from "./usePayToAddress";
|
|
12
|
+
import { usePayWithCard } from "./usePayWithCard";
|
|
12
13
|
import { usePayFromWallet } from "./usePayWithToken";
|
|
13
14
|
export function usePaymentState({ payOrder, setPayOrder, setRoute, log, }) {
|
|
14
15
|
const api = useBackendApi();
|
|
@@ -49,6 +50,11 @@ export function usePaymentState({ payOrder, setPayOrder, setRoute, log, }) {
|
|
|
49
50
|
setPayOrder,
|
|
50
51
|
log,
|
|
51
52
|
});
|
|
53
|
+
const { payWithCard } = usePayWithCard({
|
|
54
|
+
payOrder,
|
|
55
|
+
setPayOrder,
|
|
56
|
+
log,
|
|
57
|
+
});
|
|
52
58
|
const fetchPayOrder = useCallback(async (id) => {
|
|
53
59
|
const { data: order, error } = await api.getPayOrder(id);
|
|
54
60
|
if (!order || error) {
|
|
@@ -130,7 +136,7 @@ export function usePaymentState({ payOrder, setPayOrder, setRoute, log, }) {
|
|
|
130
136
|
setSelectedCurrencyOption(undefined);
|
|
131
137
|
setConnectorChainType(undefined);
|
|
132
138
|
setSelectedWallet(undefined);
|
|
133
|
-
setRoute(
|
|
139
|
+
setRoute(ROUTE.SELECT_METHOD);
|
|
134
140
|
}, [setRoute]);
|
|
135
141
|
return {
|
|
136
142
|
setPayId: setPayOrderId,
|
|
@@ -148,6 +154,7 @@ export function usePaymentState({ payOrder, setPayOrder, setRoute, log, }) {
|
|
|
148
154
|
setSelectedCurrencyOption,
|
|
149
155
|
payOrderQuotes,
|
|
150
156
|
payFromWallet,
|
|
157
|
+
payWithCard,
|
|
151
158
|
payToAddress,
|
|
152
159
|
refreshOrder,
|
|
153
160
|
senderEnsName: evmEnsName ?? suiEnsName ?? undefined,
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { getChainName } from "@coin-voyage/shared/common";
|
|
3
3
|
import usePayContext from "../components/contexts/pay";
|
|
4
4
|
import TokenChainLogo from "../components/ui/TokenChainLogo";
|
|
5
|
-
import {
|
|
5
|
+
import { ROUTE } from "../types/routes";
|
|
6
6
|
export function useTokenOptions(disabled) {
|
|
7
7
|
const { paymentState, setRoute } = usePayContext();
|
|
8
8
|
const { setSelectedCurrencyOption, payOrderQuotes } = paymentState;
|
|
@@ -37,7 +37,7 @@ export function useTokenOptions(disabled) {
|
|
|
37
37
|
],
|
|
38
38
|
onClick: () => {
|
|
39
39
|
setSelectedCurrencyOption(quote);
|
|
40
|
-
setRoute(
|
|
40
|
+
setRoute(ROUTE.WALLET_PAYMENT);
|
|
41
41
|
},
|
|
42
42
|
};
|
|
43
43
|
}) ?? []);
|
|
@@ -6,7 +6,7 @@ import { useWallet } from "@solana/wallet-adapter-react";
|
|
|
6
6
|
import { useState } from "react";
|
|
7
7
|
import { useConnect as wagmiUseConnect } from "wagmi";
|
|
8
8
|
import usePayContext from "../components/contexts/pay";
|
|
9
|
-
import {
|
|
9
|
+
import { ROUTE } from "../types/routes";
|
|
10
10
|
import { isWalletConnectConnector } from "../utils";
|
|
11
11
|
export function useWalletConnectModal() {
|
|
12
12
|
const { log, setRoute, paymentState } = usePayContext();
|
|
@@ -15,7 +15,7 @@ export function useWalletConnectModal() {
|
|
|
15
15
|
const { connect } = useUniversalConnect({
|
|
16
16
|
onSuccess: (_, variables) => {
|
|
17
17
|
if (variables?.connector) {
|
|
18
|
-
setRoute(
|
|
18
|
+
setRoute(ROUTE.WALLET_TOKEN_SELECT);
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
onError: (error) => {
|
|
@@ -2,7 +2,7 @@ import { useAccount, useUniversalConnect } from "@coin-voyage/crypto/hooks";
|
|
|
2
2
|
import { ChainType } from "@coin-voyage/shared/types";
|
|
3
3
|
import { useEffect, useRef, useState } from "react";
|
|
4
4
|
import usePayContext from "../components/contexts/pay";
|
|
5
|
-
import {
|
|
5
|
+
import { ROUTE } from "../types/routes";
|
|
6
6
|
import { useWallets } from "./useWallets";
|
|
7
7
|
export function useWalletConnectUri({ enabled } = { enabled: true }) {
|
|
8
8
|
const { log, setRoute, paymentState } = usePayContext();
|
|
@@ -19,7 +19,7 @@ export function useWalletConnectUri({ enabled } = { enabled: true }) {
|
|
|
19
19
|
onError: (err) => log("WC Connect Error", err),
|
|
20
20
|
onSuccess: () => {
|
|
21
21
|
setUri(undefined);
|
|
22
|
-
setRoute(
|
|
22
|
+
setRoute(ROUTE.WALLET_TOKEN_SELECT);
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
25
|
const isConnectingRef = useRef(false);
|