@coin-voyage/paykit 2.4.5-beta.2 → 2.4.5-beta.3
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/components/Pages/CardPayment/index.d.ts +5 -0
- package/dist/components/Pages/CardPayment/index.js +100 -91
- package/dist/components/Pages/MobileConnectors/index.js +2 -1
- package/dist/hooks/useChainOptions.js +1 -1
- package/dist/hooks/usePaymentState.js +2 -3
- package/dist/hooks/useWallets.js +3 -2
- package/package.json +6 -6
|
@@ -1 +1,6 @@
|
|
|
1
1
|
export default function CardPayment(): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare const CryptoElements: ({ stripeOnramp, children }: {
|
|
3
|
+
stripeOnramp: any;
|
|
4
|
+
children: any;
|
|
5
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export declare const useStripeOnramp: () => any;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { getFiatPaymentData } from "@coin-voyage/shared/payment";
|
|
3
3
|
import { PayOrderMode, PayOrderStatus } from "@coin-voyage/shared/types";
|
|
4
|
-
import { loadStripeOnramp } from "@stripe/crypto/pure";
|
|
5
4
|
import { useQuery } from "@tanstack/react-query";
|
|
6
|
-
import {
|
|
5
|
+
import { createContext, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
7
6
|
import { AlertIcon } from "../../../assets/icons";
|
|
8
7
|
import useLocales from "../../../hooks/useLocales";
|
|
9
8
|
import styled from "../../../styles/styled";
|
|
@@ -66,29 +65,34 @@ function StatusCard({ title, body, actionLabel, onAction, loading = false, warni
|
|
|
66
65
|
}, 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] }));
|
|
67
66
|
}
|
|
68
67
|
function StripeOnrampCheckout({ paymentData }) {
|
|
69
|
-
const {
|
|
70
|
-
const { data: stripeOnramp, isLoading, error, refetch } = useStripeOnramp(paymentData.stripe_publishable_key)
|
|
71
|
-
const refreshOrderRef = useLatestRef(paymentState.refreshOrder);
|
|
68
|
+
const { mode, triggerResize } = usePayContext();
|
|
69
|
+
//const { data: stripeOnramp, isLoading, error, refetch } = useStripeOnramp(paymentData.stripe_publishable_key)
|
|
72
70
|
const refreshDebounceRef = useRef(null);
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
const appearance = useMemo(() => {
|
|
72
|
+
return {
|
|
73
|
+
theme: mode === "dark" ? "night" : "stripe",
|
|
74
|
+
variables: {
|
|
75
|
+
colorBackground: "var(--ck-body-background-secondary)",
|
|
76
|
+
},
|
|
77
|
+
};
|
|
76
78
|
}, [mode]);
|
|
77
|
-
const handleSessionUpdate = useCallback(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
},
|
|
79
|
+
// const handleSessionUpdate = useCallback(
|
|
80
|
+
// (status: OnrampSessionStatus) => {
|
|
81
|
+
// if (status === lastStatusRef.current) return
|
|
82
|
+
// lastStatusRef.current = status
|
|
83
|
+
// const shouldRefresh = status === "fulfillment_complete" || status === "rejected"
|
|
84
|
+
// if (!shouldRefresh) {
|
|
85
|
+
// return
|
|
86
|
+
// }
|
|
87
|
+
// if (refreshDebounceRef.current) {
|
|
88
|
+
// window.clearTimeout(refreshDebounceRef.current)
|
|
89
|
+
// }
|
|
90
|
+
// refreshDebounceRef.current = window.setTimeout(() => {
|
|
91
|
+
// void refreshOrderRef.current()
|
|
92
|
+
// }, 500)
|
|
93
|
+
// },
|
|
94
|
+
// [refreshOrderRef]
|
|
95
|
+
// )
|
|
92
96
|
useEffect(() => {
|
|
93
97
|
return () => {
|
|
94
98
|
if (refreshDebounceRef.current) {
|
|
@@ -96,44 +100,46 @@ function StripeOnrampCheckout({ paymentData }) {
|
|
|
96
100
|
}
|
|
97
101
|
};
|
|
98
102
|
}, []);
|
|
99
|
-
if (error) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
// if (error) {
|
|
104
|
+
// return (
|
|
105
|
+
// <StatusCard
|
|
106
|
+
// warning
|
|
107
|
+
// title="Stripe unavailable"
|
|
108
|
+
// body={error.message}
|
|
109
|
+
// actionLabel="Try again"
|
|
110
|
+
// onAction={() => {
|
|
111
|
+
// void refetch()
|
|
112
|
+
// }}
|
|
113
|
+
// />
|
|
114
|
+
// )
|
|
115
|
+
// }
|
|
116
|
+
return (_jsx(OnrampShell, { children: paymentData.client_secret ? (_jsx(OnrampElement, { id: "onramp-element", clientSecret: paymentData.client_secret, appearance: appearance, onReady: triggerResize })) : (_jsx(OnrampOverlay, { children: _jsx(Spinner, {}) })) }));
|
|
105
117
|
}
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
const
|
|
118
|
+
function OnrampElement({ clientSecret, appearance, onReady, onChange, ...props }) {
|
|
119
|
+
const stripeOnramp = useStripeOnramp();
|
|
120
|
+
const onrampElementRef = useRef(null);
|
|
121
|
+
const [session, setSession] = useState();
|
|
122
|
+
const appearanceJSON = JSON.stringify(appearance);
|
|
110
123
|
useEffect(() => {
|
|
111
|
-
const
|
|
112
|
-
if (
|
|
113
|
-
|
|
124
|
+
const containerRef = onrampElementRef.current;
|
|
125
|
+
if (containerRef) {
|
|
126
|
+
// NB: ideally we want to be able to hot swap/update onramp iframe
|
|
127
|
+
// This currently results a flash if one needs to mint a new session when they need to update fixed transaction details
|
|
128
|
+
containerRef.innerHTML = "";
|
|
129
|
+
if (clientSecret && stripeOnramp) {
|
|
130
|
+
setSession(stripeOnramp
|
|
131
|
+
.createSession({
|
|
132
|
+
clientSecret,
|
|
133
|
+
appearance: appearanceJSON ? JSON.parse(appearanceJSON) : {},
|
|
134
|
+
})
|
|
135
|
+
.mount(containerRef));
|
|
136
|
+
}
|
|
114
137
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const handleUiLoaded = () => {
|
|
121
|
-
onUiLoadedRef.current?.();
|
|
122
|
-
};
|
|
123
|
-
const handleSessionUpdated = (event) => {
|
|
124
|
-
onSessionUpdateRef.current?.(event.payload.session.status);
|
|
125
|
-
};
|
|
126
|
-
session.addEventListener("onramp_ui_loaded", handleUiLoaded);
|
|
127
|
-
session.addEventListener("onramp_session_updated", handleSessionUpdated);
|
|
128
|
-
session.mount(mountNode);
|
|
129
|
-
return () => {
|
|
130
|
-
session.removeEventListener("onramp_ui_loaded", handleUiLoaded);
|
|
131
|
-
session.removeEventListener("onramp_session_updated", handleSessionUpdated);
|
|
132
|
-
mountNode.replaceChildren();
|
|
133
|
-
};
|
|
134
|
-
}, [clientSecret, onSessionUpdateRef, onUiLoadedRef, stripeOnramp, theme]);
|
|
135
|
-
return _jsx(OnrampMount, { ref: mountNodeRef });
|
|
136
|
-
});
|
|
138
|
+
}, [appearanceJSON, clientSecret, stripeOnramp]);
|
|
139
|
+
useOnrampSessionListener("onramp_ui_loaded", session, onReady);
|
|
140
|
+
useOnrampSessionListener("onramp_session_updated", session, onChange);
|
|
141
|
+
return _jsx("div", { ...props, ref: onrampElementRef });
|
|
142
|
+
}
|
|
137
143
|
function useCardPaymentData() {
|
|
138
144
|
const { paymentState } = usePayContext();
|
|
139
145
|
const { payOrder, payWithCard } = paymentState;
|
|
@@ -163,41 +169,44 @@ function useCardPaymentData() {
|
|
|
163
169
|
data: paymentData ?? query.data,
|
|
164
170
|
};
|
|
165
171
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
throw new Error("Stripe Onramp is only available in the browser.");
|
|
172
|
+
// ReactContext to simplify access of StripeOnramp object
|
|
173
|
+
const CryptoElementsContext = createContext(null);
|
|
174
|
+
CryptoElementsContext.displayName = "CryptoElementsContext";
|
|
175
|
+
export const CryptoElements = ({ stripeOnramp, children }) => {
|
|
176
|
+
const [ctx, setContext] = useState(() => ({
|
|
177
|
+
onramp: null,
|
|
178
|
+
}));
|
|
179
|
+
useEffect(() => {
|
|
180
|
+
let isMounted = true;
|
|
181
|
+
Promise.resolve(stripeOnramp).then((onramp) => {
|
|
182
|
+
if (onramp && isMounted) {
|
|
183
|
+
setContext((ctx) => (ctx.onramp ? ctx : { onramp }));
|
|
179
184
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
function useLatestRef(value) {
|
|
195
|
-
const ref = useRef(value);
|
|
185
|
+
});
|
|
186
|
+
return () => {
|
|
187
|
+
isMounted = false;
|
|
188
|
+
};
|
|
189
|
+
}, [stripeOnramp]);
|
|
190
|
+
return _jsx(CryptoElementsContext.Provider, { value: ctx, children: children });
|
|
191
|
+
};
|
|
192
|
+
// React hook to get StripeOnramp from context
|
|
193
|
+
export const useStripeOnramp = () => {
|
|
194
|
+
const context = useContext(CryptoElementsContext);
|
|
195
|
+
return context?.onramp;
|
|
196
|
+
};
|
|
197
|
+
// React element to render Onramp UI
|
|
198
|
+
const useOnrampSessionListener = (type, session, callback) => {
|
|
196
199
|
useEffect(() => {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
if (session && callback) {
|
|
201
|
+
const listener = (e) => callback(e.payload);
|
|
202
|
+
session.addEventListener(type, listener);
|
|
203
|
+
return () => {
|
|
204
|
+
session.removeEventListener(type, listener);
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return () => { };
|
|
208
|
+
}, [session, callback, type]);
|
|
209
|
+
};
|
|
201
210
|
const OnrampShell = styled.div `
|
|
202
211
|
position: relative;
|
|
203
212
|
min-height: 480px;
|
|
@@ -12,6 +12,7 @@ import { ModalContent, PageContent } from "../../ui/Modal/styles";
|
|
|
12
12
|
import { ScrollArea } from "../../ui/ScrollArea";
|
|
13
13
|
import { Spinner } from "../../ui/Spinner";
|
|
14
14
|
import { Container, WalletIcon, WalletItem, WalletLabel, WalletList } from "./styles";
|
|
15
|
+
import { getConnectorId } from "@coin-voyage/crypto/utils";
|
|
15
16
|
const MoreIcon = (_jsx("svg", { width: "60", height: "60", viewBox: "0 0 60 60", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M30 42V19M19 30.5H42", stroke: "var(--ck-body-color-muted)", strokeWidth: "3", strokeLinecap: "round" }) }));
|
|
16
17
|
export default function MobileConnectors() {
|
|
17
18
|
const { paymentState } = usePayContext();
|
|
@@ -29,7 +30,7 @@ export default function MobileConnectors() {
|
|
|
29
30
|
// check if wallet is supports currentChainType
|
|
30
31
|
if (connectorChainType && wallet.chainTypes && !wallet.chainTypes.includes(connectorChainType))
|
|
31
32
|
return false;
|
|
32
|
-
if (wallets.find((w) => w.connectors.find((c) => c.connector
|
|
33
|
+
if (wallets.find((w) => w.connectors.find((c) => getConnectorId(c.connector) === walletId)))
|
|
33
34
|
return false;
|
|
34
35
|
return true;
|
|
35
36
|
}) ?? [];
|
|
@@ -3,7 +3,7 @@ import { useConfig as useBigmiConfig } from "@bigmi/react";
|
|
|
3
3
|
import { Arbitrum, Base, Bitcoin, Ethereum, Solana, Sui } from "@coin-voyage/shared/chain";
|
|
4
4
|
import { ChainType, PayOrderMode } from "@coin-voyage/shared/types";
|
|
5
5
|
import { truncateAddress, truncateENSName } from "@coin-voyage/shared/utils";
|
|
6
|
-
import { useWallets } from "@mysten/dapp-kit";
|
|
6
|
+
import { useWallets } from "@mysten/dapp-kit-react";
|
|
7
7
|
import { useWallet } from "@solana/wallet-adapter-react";
|
|
8
8
|
import { useCallback, useMemo } from "react";
|
|
9
9
|
import { useConfig as useWagmiConfig } from "wagmi";
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { useAccount } from "@coin-voyage/crypto/hooks";
|
|
1
|
+
import { useAccount, useSuiNSName } from "@coin-voyage/crypto/hooks";
|
|
2
2
|
import { zPayOrder } from "@coin-voyage/shared/schemas";
|
|
3
3
|
import { ChainType, PayOrderMode, } from "@coin-voyage/shared/types";
|
|
4
|
-
import { useResolveSuiNSName } from "@mysten/dapp-kit";
|
|
5
4
|
import { useCallback, useRef, useState } from "react";
|
|
6
5
|
import { mainnet } from "viem/chains";
|
|
7
6
|
import { useEnsName } from "wagmi";
|
|
@@ -21,7 +20,7 @@ export function usePaymentState({ payOrder, setPayOrder, setRoute, log, }) {
|
|
|
21
20
|
selectedWallet,
|
|
22
21
|
chainType: connectorChainType,
|
|
23
22
|
});
|
|
24
|
-
const { data: suiEnsName } =
|
|
23
|
+
const { data: suiEnsName } = useSuiNSName(senderAccount.address, {
|
|
25
24
|
enabled: !!senderAccount.address && senderAccount.chainType === ChainType.SUI && senderAccount.isConnected,
|
|
26
25
|
});
|
|
27
26
|
const { data: evmEnsName } = useEnsName({
|
package/dist/hooks/useWallets.js
CHANGED
|
@@ -3,6 +3,7 @@ import { useInstalledWallets } from "@coin-voyage/crypto/hooks";
|
|
|
3
3
|
import usePayContext from "../components/contexts/pay";
|
|
4
4
|
import { walletConfigs } from "../lib/config/wallet";
|
|
5
5
|
import { isInjectedConnector } from "../utils";
|
|
6
|
+
import { getConnectorId } from "@coin-voyage/crypto/utils";
|
|
6
7
|
export const useWallets = () => {
|
|
7
8
|
const { paymentState } = usePayContext();
|
|
8
9
|
const installedWallets = useInstalledWallets(paymentState.connectorChainType);
|
|
@@ -54,8 +55,8 @@ export const useWallets = () => {
|
|
|
54
55
|
self.find((w) => w.id === "io.metamask" || w.id === "io.metamask.mobile")))
|
|
55
56
|
// order by isInstalled injected connectors first
|
|
56
57
|
.sort((a, b) => {
|
|
57
|
-
const AisInstalled = a.isInstalled && isInjectedConnector(a.connectors[0].connector
|
|
58
|
-
const BisInstalled = b.isInstalled && isInjectedConnector(b.connectors[0].connector
|
|
58
|
+
const AisInstalled = a.isInstalled && isInjectedConnector(getConnectorId(a.connectors[0].connector));
|
|
59
|
+
const BisInstalled = b.isInstalled && isInjectedConnector(getConnectorId(b.connectors[0].connector));
|
|
59
60
|
if (AisInstalled && !BisInstalled)
|
|
60
61
|
return -1;
|
|
61
62
|
if (!AisInstalled && BisInstalled)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coin-voyage/paykit",
|
|
3
3
|
"description": "Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.",
|
|
4
|
-
"version": "2.4.5-beta.
|
|
4
|
+
"version": "2.4.5-beta.3",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"author": "Lars <lars@coinvoyage.io>",
|
|
@@ -57,11 +57,11 @@
|
|
|
57
57
|
"react-transition-state": "^1.1.4",
|
|
58
58
|
"react-use-measure": "^2.1.1",
|
|
59
59
|
"@stripe/stripe-js": "8.10.0",
|
|
60
|
-
"@stripe/crypto": "
|
|
60
|
+
"@stripe/crypto": "1.0.2",
|
|
61
61
|
"styled-components": "^5.3.11",
|
|
62
62
|
"uuid": "13.0.0",
|
|
63
|
-
"@coin-voyage/
|
|
64
|
-
"@coin-voyage/
|
|
63
|
+
"@coin-voyage/crypto": "2.4.5-beta.1",
|
|
64
|
+
"@coin-voyage/shared": "2.4.5-beta.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/qrcode": "1.5.5",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"typescript-plugin-styled-components": "^3.0.0"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|
|
73
|
-
"@bigmi/react": "^0.
|
|
74
|
-
"@mysten/dapp-kit": "^0.
|
|
73
|
+
"@bigmi/react": "^0.8.0",
|
|
74
|
+
"@mysten/dapp-kit-react": "^2.0.3",
|
|
75
75
|
"@solana/wallet-adapter-react": "^0.15.39",
|
|
76
76
|
"@tanstack/react-query": "^5.90.6",
|
|
77
77
|
"react": "^18 || ^19",
|