@daimo/pay 1.3.3 → 1.4.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.
- package/build/index.d.ts +20 -5
- package/build/package.json.js +3 -3
- package/build/src/components/Common/PaymentBreakdown/index.js +2 -2
- package/build/src/components/Common/PoweredByFooter/index.js +4 -1
- package/build/src/components/Common/PoweredByFooter/index.js.map +1 -1
- package/build/src/components/DaimoPay.js +4 -0
- package/build/src/components/DaimoPay.js.map +1 -1
- package/build/src/components/DaimoPayButton/index.js +7 -0
- package/build/src/components/DaimoPayButton/index.js.map +1 -1
- package/build/src/components/DaimoPayModal/ConnectWithInjector/index.js +2 -2
- package/build/src/components/Pages/PayWithToken/index.js +2 -2
- package/build/src/components/Pages/SelectMethod/index.js +40 -26
- package/build/src/components/Pages/SelectMethod/index.js.map +1 -1
- package/build/src/components/Pages/WaitingExternal/index.js +1 -1
- package/build/src/hooks/useExternalPaymentOptions.js +1 -0
- package/build/src/hooks/useExternalPaymentOptions.js.map +1 -1
- package/build/src/hooks/usePayWithSolanaToken.js +1 -2
- package/build/src/hooks/usePayWithSolanaToken.js.map +1 -1
- package/build/src/hooks/usePayWithToken.js +15 -13
- package/build/src/hooks/usePayWithToken.js.map +1 -1
- package/build/src/hooks/usePaymentState.js +5 -3
- package/build/src/hooks/usePaymentState.js.map +1 -1
- package/build/src/hooks/useWalletPaymentOptions.js +2 -1
- package/build/src/hooks/useWalletPaymentOptions.js.map +1 -1
- package/build/src/utils/supportUrl.js +10 -11
- package/build/src/utils/supportUrl.js.map +1 -1
- package/package.json +3 -3
package/build/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React$1, { ReactNode } from 'react';
|
|
2
2
|
export { version } from '../package.json';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
-
import { DaimoPayOrderMode, DepositAddressPaymentOptionMetadata, PlatformType, ExternalPaymentOptionMetadata, WalletPaymentOption, DaimoPayOrder,
|
|
4
|
+
import { DaimoPayOrderMode, DepositAddressPaymentOptionMetadata, PlatformType, ExternalPaymentOptionMetadata, WalletPaymentOption, DaimoPayOrder, ExternalPaymentOptions, DepositAddressPaymentOptions, DepositAddressPaymentOptionData, SolanaPublicKey, DaimoPayUserMetadata, PaymentStartedEvent, PaymentCompletedEvent, PaymentBouncedEvent, DaimoPayIntentStatus, DaimoPayOrderView } from '@daimo/common';
|
|
5
5
|
import { Address, Hex } from 'viem';
|
|
6
6
|
import { AppRouter } from '@daimo/pay-api';
|
|
7
7
|
import { CreateTRPCClient } from '@trpc/client';
|
|
@@ -70,7 +70,7 @@ type DaimoPayModalOptions = {
|
|
|
70
70
|
closeOnSuccess?: boolean;
|
|
71
71
|
};
|
|
72
72
|
/** Additional payment options. Onchain payments are always enabled. */
|
|
73
|
-
type PaymentOption = "Daimo" | "Coinbase" | "Binance" | "RampNetwork";
|
|
73
|
+
type PaymentOption = "Daimo" | "Coinbase" | "Binance" | "RampNetwork" | "Solana" | "ExternalChains";
|
|
74
74
|
|
|
75
75
|
type types_d_All = All;
|
|
76
76
|
type types_d_CustomAvatarProps = CustomAvatarProps;
|
|
@@ -127,7 +127,7 @@ declare function useSolanaPaymentOptions({ trpc, address, usdRequired, isDeposit
|
|
|
127
127
|
};
|
|
128
128
|
|
|
129
129
|
/** Wallet payment options. User picks one. */
|
|
130
|
-
declare function useWalletPaymentOptions({ trpc, address, usdRequired, destChainId, preferredChains, preferredTokens, isDepositFlow, log, }: {
|
|
130
|
+
declare function useWalletPaymentOptions({ trpc, address, usdRequired, destChainId, preferredChains, preferredTokens, evmChains, isDepositFlow, log, }: {
|
|
131
131
|
trpc: TrpcClient;
|
|
132
132
|
address: string | undefined;
|
|
133
133
|
usdRequired: number | undefined;
|
|
@@ -137,6 +137,7 @@ declare function useWalletPaymentOptions({ trpc, address, usdRequired, destChain
|
|
|
137
137
|
chain: number;
|
|
138
138
|
address: string;
|
|
139
139
|
}[] | undefined;
|
|
140
|
+
evmChains: number[] | undefined;
|
|
140
141
|
isDepositFlow: boolean;
|
|
141
142
|
log: (msg: string) => void;
|
|
142
143
|
}): {
|
|
@@ -172,6 +173,8 @@ interface PayParams {
|
|
|
172
173
|
chain: number;
|
|
173
174
|
address: Address;
|
|
174
175
|
}[];
|
|
176
|
+
/** Only allow payments on these EVM chains. */
|
|
177
|
+
evmChains?: number[];
|
|
175
178
|
/** External ID. E.g. a correlation ID. */
|
|
176
179
|
externalId?: string;
|
|
177
180
|
/** Developer metadata. E.g. correlation ID. */
|
|
@@ -203,7 +206,7 @@ interface PaymentState {
|
|
|
203
206
|
setSelectedSolanaTokenOption: (option: WalletPaymentOption | undefined) => void;
|
|
204
207
|
setSelectedDepositAddressOption: (option: DepositAddressPaymentOptionMetadata | undefined) => void;
|
|
205
208
|
setChosenUsd: (usd: number) => void;
|
|
206
|
-
payWithToken: (
|
|
209
|
+
payWithToken: (walletOption: WalletPaymentOption) => Promise<void>;
|
|
207
210
|
payWithExternal: (option: ExternalPaymentOptions) => Promise<string>;
|
|
208
211
|
payWithDepositAddress: (option: DepositAddressPaymentOptions) => Promise<DepositAddressPaymentOptionData | null>;
|
|
209
212
|
payWithSolanaToken: (inputToken: SolanaPublicKey) => Promise<string | undefined>;
|
|
@@ -284,6 +287,9 @@ type ContextValue = {
|
|
|
284
287
|
/** Custom message to display on confirmation page. */
|
|
285
288
|
confirmationMessage?: string;
|
|
286
289
|
setConfirmationMessage: React$1.Dispatch<React$1.SetStateAction<string | undefined>>;
|
|
290
|
+
/** Redirect URL to return to the app. E.g. after Coinbase, Binance, RampNetwork. */
|
|
291
|
+
redirectReturnUrl?: string;
|
|
292
|
+
setRedirectReturnUrl: React$1.Dispatch<React$1.SetStateAction<string | undefined>>;
|
|
287
293
|
} & useConnectCallbackProps;
|
|
288
294
|
/** Meant for internal use. This will be non-exported in a future SDK version. */
|
|
289
295
|
declare const Context: React$1.Context<ContextValue | null>;
|
|
@@ -372,6 +378,10 @@ type PayButtonPaymentProps = {
|
|
|
372
378
|
chain: number;
|
|
373
379
|
address: Address;
|
|
374
380
|
}[];
|
|
381
|
+
/**
|
|
382
|
+
* Only allow payments on these EVM chains.
|
|
383
|
+
*/
|
|
384
|
+
evmChains?: number[];
|
|
375
385
|
/**
|
|
376
386
|
* External ID. E.g. a correlation ID.
|
|
377
387
|
*/
|
|
@@ -397,6 +407,8 @@ type PayButtonCommonProps = PayButtonPaymentProps & {
|
|
|
397
407
|
defaultOpen?: boolean;
|
|
398
408
|
/** Custom message to display on confirmation page. */
|
|
399
409
|
confirmationMessage?: string;
|
|
410
|
+
/** Redirect URL to return to the app. E.g. after Coinbase, Binance, RampNetwork. */
|
|
411
|
+
redirectReturnUrl?: string;
|
|
400
412
|
};
|
|
401
413
|
type DaimoPayButtonProps = PayButtonCommonProps & {
|
|
402
414
|
/** Light mode, dark mode, or auto. */
|
|
@@ -461,4 +473,7 @@ declare const daimoPayVersion: string;
|
|
|
461
473
|
/** Chain ids supported by Daimo Pay. */
|
|
462
474
|
declare const supportedChainIds: Set<number>;
|
|
463
475
|
|
|
464
|
-
|
|
476
|
+
type DaimoPayment = DaimoPayOrderView;
|
|
477
|
+
type DaimoPayEvent = PaymentStartedEvent | PaymentCompletedEvent | PaymentBouncedEvent;
|
|
478
|
+
|
|
479
|
+
export { Avatar, Chain as ChainIcon, DaimoPayButton, type DaimoPayButtonCustomProps, type DaimoPayButtonProps, Context as DaimoPayContext, type DaimoPayEvent, DaimoPayProvider, type DaimoPayment, types_d as Types, daimoPayVersion, defaultConfig as getDefaultConfig, supportedChainIds, useDaimoPayStatus, usePayContext, wallets };
|
package/build/package.json.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "@daimo/pay";
|
|
2
|
-
var version = "1.
|
|
2
|
+
var version = "1.4.0";
|
|
3
3
|
var author = "Daimo";
|
|
4
4
|
var homepage = "https://pay.daimo.com";
|
|
5
5
|
var license = "BSD-2-Clause license";
|
|
@@ -38,8 +38,8 @@ var keywords = [
|
|
|
38
38
|
"crypto"
|
|
39
39
|
];
|
|
40
40
|
var dependencies = {
|
|
41
|
-
"@daimo/common": "1.3.
|
|
42
|
-
"@daimo/contract": "1.3.
|
|
41
|
+
"@daimo/common": "1.3.4",
|
|
42
|
+
"@daimo/contract": "1.3.4",
|
|
43
43
|
"@solana/wallet-adapter-base": "^0.9.23",
|
|
44
44
|
"@solana/wallet-adapter-react": "^0.15.35",
|
|
45
45
|
"@solana/web3.js": "^1.95.4",
|
|
@@ -4,9 +4,9 @@ import styled from '../../../styles/styled/index.js';
|
|
|
4
4
|
import { ModalBody } from '../Modal/styles.js';
|
|
5
5
|
|
|
6
6
|
const PaymentBreakdown = ({ paymentOption }) => {
|
|
7
|
-
const
|
|
7
|
+
const subtotalUsd = paymentOption.required.usd;
|
|
8
8
|
const feesUsd = paymentOption.fees.usd;
|
|
9
|
-
const
|
|
9
|
+
const totalUsd = subtotalUsd + feesUsd;
|
|
10
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
11
|
};
|
|
12
12
|
const FeesContainer = styled.div `
|
|
@@ -4,6 +4,7 @@ import { useState, useEffect } from 'react';
|
|
|
4
4
|
import { keyframes } from 'styled-components';
|
|
5
5
|
import CrepeIcon from '../../../assets/crepe.js';
|
|
6
6
|
import styled from '../../../styles/styled/index.js';
|
|
7
|
+
import { daimoPayVersion } from '../../../utils/exports.js';
|
|
7
8
|
|
|
8
9
|
const PoweredByFooter = ({ supportUrl } = {}) => {
|
|
9
10
|
const [supportVisible, setSupportVisible] = useState(false);
|
|
@@ -17,7 +18,9 @@ const PoweredByFooter = ({ supportUrl } = {}) => {
|
|
|
17
18
|
return () => clearTimeout(timer);
|
|
18
19
|
}, []);
|
|
19
20
|
return (jsx(Container, { children: jsxs(TextButton, { onClick: () => {
|
|
20
|
-
window.open(supportVisible
|
|
21
|
+
window.open(supportVisible
|
|
22
|
+
? supportUrl
|
|
23
|
+
: `https://pay.daimo.com?ref=paykit-v${daimoPayVersion}`, "_blank");
|
|
21
24
|
}, className: supportVisible ? "support" : "", children: [!supportVisible && jsx(CrepeIcon, {}), jsx("span", { children: supportVisible ? (jsxs(Fragment, { children: ["Need help? ", jsx(Underline, { children: "Contact support" })] })) : (jsx(Fragment, { children: "Powered by Daimo Pay" })) })] }) }));
|
|
22
25
|
};
|
|
23
26
|
const Container = styled(motion.div) `
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -129,6 +129,7 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
129
129
|
};
|
|
130
130
|
const [errorMessage, setErrorMessage] = useState("");
|
|
131
131
|
const [confirmationMessage, setConfirmationMessage] = useState(undefined);
|
|
132
|
+
const [redirectReturnUrl, setRedirectReturnUrl] = useState(undefined);
|
|
132
133
|
const [resize, onResize] = useState(0);
|
|
133
134
|
// Include Google Font that is needed for a themes
|
|
134
135
|
if (opts.embedGoogleFonts)
|
|
@@ -170,6 +171,7 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
170
171
|
setDaimoPayOrder,
|
|
171
172
|
setOpen,
|
|
172
173
|
log,
|
|
174
|
+
redirectReturnUrl,
|
|
173
175
|
});
|
|
174
176
|
// When a payment is in progress, poll for status updates. Do this regardless
|
|
175
177
|
// of whether the modal is still being displayed for useDaimoPayStatus().
|
|
@@ -235,6 +237,8 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
235
237
|
errorMessage,
|
|
236
238
|
confirmationMessage,
|
|
237
239
|
setConfirmationMessage,
|
|
240
|
+
redirectReturnUrl,
|
|
241
|
+
setRedirectReturnUrl,
|
|
238
242
|
debugMode,
|
|
239
243
|
log,
|
|
240
244
|
displayError: (message, code) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DaimoPay.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DaimoPay.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -34,6 +34,7 @@ function DaimoPayButtonCustom(props) {
|
|
|
34
34
|
paymentOptions: props.paymentOptions,
|
|
35
35
|
preferredChains: props.preferredChains,
|
|
36
36
|
preferredTokens: props.preferredTokens,
|
|
37
|
+
evmChains: props.evmChains,
|
|
37
38
|
externalId: props.externalId,
|
|
38
39
|
metadata: props.metadata,
|
|
39
40
|
}
|
|
@@ -54,6 +55,12 @@ function DaimoPayButtonCustom(props) {
|
|
|
54
55
|
setConfirmationMessage(props.confirmationMessage);
|
|
55
56
|
}
|
|
56
57
|
}, [props.confirmationMessage, setConfirmationMessage]);
|
|
58
|
+
const { setRedirectReturnUrl } = context;
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (props.redirectReturnUrl) {
|
|
61
|
+
setRedirectReturnUrl(props.redirectReturnUrl);
|
|
62
|
+
}
|
|
63
|
+
}, [props.redirectReturnUrl, setRedirectReturnUrl]);
|
|
57
64
|
// Payment events: call these three event handlers.
|
|
58
65
|
const { onPaymentStarted, onPaymentCompleted, onPaymentBounced } = props;
|
|
59
66
|
const order = paymentState.daimoPayOrder;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -7,7 +7,7 @@ import Button from '../../Common/Button/index.js';
|
|
|
7
7
|
import { PageContent, ModalHeading, ModalContent, ModalContentContainer, ModalH1, ModalBody } from '../../Common/Modal/styles.js';
|
|
8
8
|
import Tooltip from '../../Common/Tooltip/index.js';
|
|
9
9
|
import SquircleSpinner from '../../Spinners/SquircleSpinner/index.js';
|
|
10
|
-
import { RetryIconCircle, AlertIcon, TickIcon } from '../../../assets/icons.js';
|
|
10
|
+
import { RetryIconCircle, AlertIcon, ExternalLinkIcon, TickIcon } from '../../../assets/icons.js';
|
|
11
11
|
import { useConnect } from '../../../hooks/useConnect.js';
|
|
12
12
|
import useLocales from '../../../hooks/useLocales.js';
|
|
13
13
|
import { detectBrowser, isWalletConnectConnector } from '../../../utils/index.js';
|
|
@@ -195,7 +195,7 @@ const ConnectWithInjector = ({ switchConnectMethod, forceState }) => {
|
|
|
195
195
|
? locales.injectionScreen_connecting_injected_h1
|
|
196
196
|
: locales.injectionScreen_connecting_h1 }), jsx(ModalBody, { children: wallet.connector.id === "injected"
|
|
197
197
|
? locales.injectionScreen_connecting_injected_p
|
|
198
|
-
: locales.injectionScreen_connecting_p })] }) }, states.CONNECTING)), status === states.CONNECTED && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: jsxs(ModalContent, { children: [jsxs(ModalH1, { "$valid": true, children: [jsx(TickIcon, {}), " ", locales.injectionScreen_connected_h1] }), jsx(ModalBody, { children: locales.injectionScreen_connected_p })] }) }, states.CONNECTED)), status === states.NOTCONNECTED && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: jsxs(ModalContent, { children: [jsx(ModalH1, { children: locales.injectionScreen_notconnected_h1 }), jsx(ModalBody, { children: locales.injectionScreen_notconnected_p })] }) }, states.NOTCONNECTED)), status === states.UNAVAILABLE && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: !extensionUrl ? (jsxs(Fragment, { children: [jsxs(ModalContent, { style: { paddingBottom: 12 }, children: [jsx(ModalH1, { children: locales.injectionScreen_unavailable_h1 }), jsx(ModalBody, { children: locales.injectionScreen_unavailable_p })] }), !wallet.isInstalled && suggestedExtension && (jsxs(Button, { href: suggestedExtension?.url, icon: jsx(BrowserIcon, { browser: suggestedExtension?.name }), children: ["Install on ", suggestedExtension?.label] }))] })) : (jsxs(Fragment, { children: [jsxs(ModalContent, { style: { paddingBottom: 18 }, children: [jsx(ModalH1, { children: locales.injectionScreen_install_h1 }), jsx(ModalBody, { children: locales.injectionScreen_install_p })] }), !wallet.isInstalled && extensionUrl && (jsx(Button, { href: extensionUrl, icon: jsx(BrowserIcon, {}), children: locales.installTheExtension }))] })) }, states.UNAVAILABLE))] }) })] }) }));
|
|
198
|
+
: locales.injectionScreen_connecting_p }), jsxs(Button, { icon: jsx(ExternalLinkIcon, {}), onClick: runConnect, children: ["Connect ", walletInfo.name] })] }) }, states.CONNECTING)), status === states.CONNECTED && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: jsxs(ModalContent, { children: [jsxs(ModalH1, { "$valid": true, children: [jsx(TickIcon, {}), " ", locales.injectionScreen_connected_h1] }), jsx(ModalBody, { children: locales.injectionScreen_connected_p })] }) }, states.CONNECTED)), status === states.NOTCONNECTED && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: jsxs(ModalContent, { children: [jsx(ModalH1, { children: locales.injectionScreen_notconnected_h1 }), jsx(ModalBody, { children: locales.injectionScreen_notconnected_p })] }) }, states.NOTCONNECTED)), status === states.UNAVAILABLE && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: !extensionUrl ? (jsxs(Fragment, { children: [jsxs(ModalContent, { style: { paddingBottom: 12 }, children: [jsx(ModalH1, { children: locales.injectionScreen_unavailable_h1 }), jsx(ModalBody, { children: locales.injectionScreen_unavailable_p })] }), !wallet.isInstalled && suggestedExtension && (jsxs(Button, { href: suggestedExtension?.url, icon: jsx(BrowserIcon, { browser: suggestedExtension?.name }), children: ["Install on ", suggestedExtension?.label] }))] })) : (jsxs(Fragment, { children: [jsxs(ModalContent, { style: { paddingBottom: 18 }, children: [jsx(ModalH1, { children: locales.injectionScreen_install_h1 }), jsx(ModalBody, { children: locales.injectionScreen_install_p })] }), !wallet.isInstalled && extensionUrl && (jsx(Button, { href: extensionUrl, icon: jsx(BrowserIcon, {}), children: locales.installTheExtension }))] })) }, states.UNAVAILABLE))] }) })] }) }));
|
|
199
199
|
};
|
|
200
200
|
|
|
201
201
|
export { ConnectWithInjector as default, states };
|
|
@@ -50,7 +50,7 @@ const PayWithToken = () => {
|
|
|
50
50
|
}
|
|
51
51
|
setPayState(PayState.RequestingPayment);
|
|
52
52
|
try {
|
|
53
|
-
await payWithToken(option
|
|
53
|
+
await payWithToken(option);
|
|
54
54
|
setPayState(PayState.RequestSuccessful);
|
|
55
55
|
setTimeout(() => {
|
|
56
56
|
setRoute(ROUTES.CONFIRMATION, { event: "wait-pay-with-token" });
|
|
@@ -64,7 +64,7 @@ const PayWithToken = () => {
|
|
|
64
64
|
const switchSuccessful = await trySwitchingChain(option, true);
|
|
65
65
|
if (switchSuccessful) {
|
|
66
66
|
try {
|
|
67
|
-
await payWithToken(option
|
|
67
|
+
await payWithToken(option);
|
|
68
68
|
return; // Payment successful after switching chain
|
|
69
69
|
}
|
|
70
70
|
catch (retryError) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { usePayContext, ROUTES } from '../../DaimoPay.js';
|
|
3
3
|
import { PageContent } from '../../Common/Modal/styles.js';
|
|
4
|
-
import { getAddressContraction } from '@daimo/common';
|
|
4
|
+
import { getAddressContraction, ExternalPaymentOptions } from '@daimo/common';
|
|
5
5
|
import { useWallet } from '@solana/wallet-adapter-react';
|
|
6
6
|
import { useAccount, useDisconnect } from 'wagmi';
|
|
7
7
|
import { Solana, Bitcoin, Tron, Zcash } from '../../../assets/chains.js';
|
|
@@ -67,8 +67,9 @@ const SelectMethod = () => {
|
|
|
67
67
|
const { address, chain, isConnected, connector } = useAccount();
|
|
68
68
|
const { disconnectAsync } = useDisconnect();
|
|
69
69
|
const { setRoute, paymentState, log } = usePayContext();
|
|
70
|
-
const { setSelectedExternalOption, externalPaymentOptions, depositAddressOptions, senderEnsName, } = paymentState;
|
|
70
|
+
const { daimoPayOrder, setSelectedExternalOption, externalPaymentOptions, depositAddressOptions, senderEnsName, } = paymentState;
|
|
71
71
|
const displayName = senderEnsName ?? (address ? getAddressContraction(address) : "wallet");
|
|
72
|
+
const paymentOptions = daimoPayOrder?.metadata.payer?.paymentOptions;
|
|
72
73
|
const connectedWalletOption = isConnected
|
|
73
74
|
? {
|
|
74
75
|
id: "connectedWallet",
|
|
@@ -97,30 +98,43 @@ const SelectMethod = () => {
|
|
|
97
98
|
? [connectedWalletOption, unconnectedWalletOption]
|
|
98
99
|
: [unconnectedWalletOption];
|
|
99
100
|
log(`[SELECT_METHOD] loading: ${externalPaymentOptions.loading}, options: ${JSON.stringify(externalPaymentOptions.options)}`);
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
101
|
+
const options = [...walletOptions];
|
|
102
|
+
// Solana payment option
|
|
103
|
+
// Include by default if paymentOptions not provided
|
|
104
|
+
const includeSolana = paymentOptions == null ||
|
|
105
|
+
paymentOptions.includes(ExternalPaymentOptions.Solana);
|
|
106
|
+
if (includeSolana) {
|
|
107
|
+
const solanaOption = getSolanaOption();
|
|
108
|
+
if (solanaOption) {
|
|
109
|
+
options.push(solanaOption);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// External payment options, e.g. Binance, Coinbase, etc.
|
|
113
|
+
options.push(...(externalPaymentOptions.options ?? []).map((option) => ({
|
|
114
|
+
id: option.id,
|
|
115
|
+
title: option.cta,
|
|
116
|
+
icons: [option.logoURI],
|
|
117
|
+
onClick: () => {
|
|
118
|
+
setSelectedExternalOption(option);
|
|
119
|
+
const meta = { event: "click-option", option: option.id };
|
|
120
|
+
if (paymentState.isDepositFlow) {
|
|
121
|
+
setRoute(ROUTES.SELECT_EXTERNAL_AMOUNT, meta);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
setRoute(ROUTES.WAITING_EXTERNAL, meta);
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
disabled: option.disabled,
|
|
128
|
+
subtitle: option.message,
|
|
129
|
+
})));
|
|
130
|
+
// Deposit address options, e.g. Bitcoin, Tron, Zcash, etc.
|
|
131
|
+
// Include by default if paymentOptions not provided
|
|
132
|
+
const includeDepositAddressOption = paymentOptions == null ||
|
|
133
|
+
paymentOptions.includes(ExternalPaymentOptions.ExternalChains);
|
|
134
|
+
if (includeDepositAddressOption) {
|
|
135
|
+
const depositAddressOption = getDepositAddressOption(depositAddressOptions);
|
|
136
|
+
options.push(depositAddressOption);
|
|
137
|
+
}
|
|
124
138
|
return (jsxs(PageContent, { children: [jsx(OrderHeader, {}), jsx(OptionsList, { requiredSkeletons: isMobile ? 4 : 3, isLoading: externalPaymentOptions.loading, options: externalPaymentOptions.loading ? [] : options }), jsx(PoweredByFooter, {})] }));
|
|
125
139
|
};
|
|
126
140
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -46,7 +46,7 @@ const WaitingExternal = () => {
|
|
|
46
46
|
return (jsxs(PageContent, { children: [jsx(ExternalPaymentSpinner, { logoURI: selectedExternalOption.logoURI, logoShape: selectedExternalOption.logoShape }), jsxs(ModalContent, { style: { marginLeft: 24, marginRight: 24 }, children: [jsx(ModalH1, { children: "Waiting for Payment" }), paymentWaitingMessage && (jsx(ModalBody, { style: { marginTop: 12, marginBottom: 12 }, children: paymentWaitingMessage }))] }), jsx(Button, { icon: jsx(ExternalLinkIcon, {}), onClick: () => {
|
|
47
47
|
if (externalURL)
|
|
48
48
|
window.open(externalURL, "_blank");
|
|
49
|
-
}, children:
|
|
49
|
+
}, children: selectedExternalOption.cta })] }));
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
export { WaitingExternal as default };
|
|
@@ -6,6 +6,7 @@ const DEFAULT_EXTERNAL_PAYMENT_OPTIONS = [
|
|
|
6
6
|
ExternalPaymentOptions.Binance,
|
|
7
7
|
ExternalPaymentOptions.Daimo,
|
|
8
8
|
ExternalPaymentOptions.RampNetwork,
|
|
9
|
+
// Solana and ExternalChains are handled in the SelectMethod component.
|
|
9
10
|
];
|
|
10
11
|
function useExternalPaymentOptions({ trpc, filterIds, platform, usdRequired, mode, }) {
|
|
11
12
|
const [options, setOptions] = useState([]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useExternalPaymentOptions.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useExternalPaymentOptions.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -3,13 +3,12 @@ import { useConnection, useWallet } from '@solana/wallet-adapter-react';
|
|
|
3
3
|
import { VersionedTransaction } from '@solana/web3.js';
|
|
4
4
|
import { hexToBytes } from 'viem';
|
|
5
5
|
|
|
6
|
-
function usePayWithSolanaToken({ trpc, daimoPayOrder, setDaimoPayOrder, createOrHydrate,
|
|
6
|
+
function usePayWithSolanaToken({ trpc, daimoPayOrder, setDaimoPayOrder, createOrHydrate, log, }) {
|
|
7
7
|
const { connection } = useConnection();
|
|
8
8
|
const wallet = useWallet();
|
|
9
9
|
const payWithSolanaToken = async (inputToken) => {
|
|
10
10
|
assert(!!wallet.publicKey, "[PAY SOLANA] No wallet connected");
|
|
11
11
|
assert(!!daimoPayOrder, "[PAY SOLANA] daimoPayOrder cannot be null");
|
|
12
|
-
assert(!!platform, "[PAY SOLANA] platform cannot be null");
|
|
13
12
|
const orderId = daimoPayOrder.id;
|
|
14
13
|
const { hydratedOrder } = await createOrHydrate({
|
|
15
14
|
order: daimoPayOrder,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePayWithSolanaToken.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"usePayWithSolanaToken.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,39 +1,41 @@
|
|
|
1
|
-
import { assert, assertNotNull } from '@daimo/common';
|
|
1
|
+
import { assert, debugJson, assertNotNull } from '@daimo/common';
|
|
2
2
|
import { zeroAddress, erc20Abi, getAddress } from 'viem';
|
|
3
3
|
import { useWriteContract, useSendTransaction } from 'wagmi';
|
|
4
4
|
|
|
5
|
-
function usePayWithToken({ trpc, senderAddr, daimoPayOrder, setDaimoPayOrder, createOrHydrate,
|
|
5
|
+
function usePayWithToken({ trpc, senderAddr, daimoPayOrder, setDaimoPayOrder, createOrHydrate, log, }) {
|
|
6
6
|
const { writeContractAsync } = useWriteContract();
|
|
7
7
|
const { sendTransactionAsync } = useSendTransaction();
|
|
8
8
|
/** Commit to a token + amount = initiate payment. */
|
|
9
|
-
const payWithToken = async (
|
|
9
|
+
const payWithToken = async (walletOption) => {
|
|
10
10
|
assert(!!daimoPayOrder, "[PAY TOKEN] daimoPayOrder cannot be null");
|
|
11
|
-
|
|
11
|
+
const { required, fees } = walletOption;
|
|
12
|
+
assert(required.token.token === fees.token.token, `[PAY TOKEN] required token ${debugJson(required)} does not match fees token ${debugJson(fees)}`);
|
|
13
|
+
const paymentAmount = BigInt(required.amount) + BigInt(fees.amount);
|
|
12
14
|
const { hydratedOrder } = await createOrHydrate({
|
|
13
15
|
order: daimoPayOrder,
|
|
14
16
|
refundAddress: senderAddr,
|
|
15
17
|
});
|
|
16
|
-
log(`[
|
|
18
|
+
log(`[PAY TOKEN] hydrated order: ${JSON.stringify(hydratedOrder)}, paying ${paymentAmount} of token ${required.token.token}`);
|
|
17
19
|
setDaimoPayOrder(hydratedOrder);
|
|
18
20
|
const txHash = await (async () => {
|
|
19
21
|
try {
|
|
20
|
-
if (
|
|
22
|
+
if (required.token.token === zeroAddress) {
|
|
21
23
|
return await sendTransactionAsync({
|
|
22
24
|
to: hydratedOrder.intentAddr,
|
|
23
|
-
value:
|
|
25
|
+
value: paymentAmount,
|
|
24
26
|
});
|
|
25
27
|
}
|
|
26
28
|
else {
|
|
27
29
|
return await writeContractAsync({
|
|
28
30
|
abi: erc20Abi,
|
|
29
|
-
address: getAddress(
|
|
31
|
+
address: getAddress(required.token.token),
|
|
30
32
|
functionName: "transfer",
|
|
31
|
-
args: [hydratedOrder.intentAddr,
|
|
33
|
+
args: [hydratedOrder.intentAddr, paymentAmount],
|
|
32
34
|
});
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
catch (e) {
|
|
36
|
-
console.error(`[
|
|
38
|
+
console.error(`[PAY TOKEN] error sending token: ${e}`);
|
|
37
39
|
throw e;
|
|
38
40
|
}
|
|
39
41
|
})();
|
|
@@ -41,10 +43,10 @@ function usePayWithToken({ trpc, senderAddr, daimoPayOrder, setDaimoPayOrder, cr
|
|
|
41
43
|
await trpc.processSourcePayment.mutate({
|
|
42
44
|
orderId: daimoPayOrder.id.toString(),
|
|
43
45
|
sourceInitiateTxHash: txHash,
|
|
44
|
-
sourceChainId:
|
|
46
|
+
sourceChainId: required.token.chainId,
|
|
45
47
|
sourceFulfillerAddr: assertNotNull(senderAddr, `[PAY TOKEN] senderAddr cannot be null on order ${daimoPayOrder.id}`),
|
|
46
|
-
sourceToken:
|
|
47
|
-
sourceAmount:
|
|
48
|
+
sourceToken: required.token.token,
|
|
49
|
+
sourceAmount: paymentAmount.toString(),
|
|
48
50
|
});
|
|
49
51
|
// TODO: update order immediately, do not wait for polling.
|
|
50
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePayWithToken.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"usePayWithToken.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -13,7 +13,7 @@ import { usePayWithToken } from './usePayWithToken.js';
|
|
|
13
13
|
import { useSolanaPaymentOptions } from './useSolanaPaymentOptions.js';
|
|
14
14
|
import { useWalletPaymentOptions } from './useWalletPaymentOptions.js';
|
|
15
15
|
|
|
16
|
-
function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log, }) {
|
|
16
|
+
function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log, redirectReturnUrl, }) {
|
|
17
17
|
// Browser state.
|
|
18
18
|
const [platform, setPlatform] = useState();
|
|
19
19
|
useEffect(() => {
|
|
@@ -49,6 +49,7 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
49
49
|
destChainId: daimoPayOrder?.destFinalCallTokenAmount.token.chainId,
|
|
50
50
|
preferredChains: daimoPayOrder?.metadata.payer?.preferredChains,
|
|
51
51
|
preferredTokens: daimoPayOrder?.metadata.payer?.preferredTokens,
|
|
52
|
+
evmChains: daimoPayOrder?.metadata.payer?.evmChains,
|
|
52
53
|
isDepositFlow,
|
|
53
54
|
log,
|
|
54
55
|
});
|
|
@@ -75,6 +76,7 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
75
76
|
platform,
|
|
76
77
|
refundAddress,
|
|
77
78
|
externalPaymentOption,
|
|
79
|
+
redirectReturnUrl,
|
|
78
80
|
});
|
|
79
81
|
}
|
|
80
82
|
log(`[CREATE/HYDRATE] creating+hydrating new order ${order.id}`);
|
|
@@ -93,6 +95,7 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
93
95
|
platform,
|
|
94
96
|
refundAddress,
|
|
95
97
|
externalPaymentOption,
|
|
98
|
+
redirectReturnUrl,
|
|
96
99
|
});
|
|
97
100
|
};
|
|
98
101
|
const { payWithToken } = usePayWithToken({
|
|
@@ -101,7 +104,6 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
101
104
|
daimoPayOrder,
|
|
102
105
|
setDaimoPayOrder,
|
|
103
106
|
createOrHydrate,
|
|
104
|
-
platform,
|
|
105
107
|
log,
|
|
106
108
|
});
|
|
107
109
|
const { payWithSolanaToken } = usePayWithSolanaToken({
|
|
@@ -109,7 +111,6 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
109
111
|
daimoPayOrder,
|
|
110
112
|
setDaimoPayOrder,
|
|
111
113
|
createOrHydrate,
|
|
112
|
-
platform,
|
|
113
114
|
log,
|
|
114
115
|
});
|
|
115
116
|
const [selectedExternalOption, setSelectedExternalOption] = useState();
|
|
@@ -229,6 +230,7 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
229
230
|
paymentOptions: payParams.paymentOptions,
|
|
230
231
|
preferredChains: payParams.preferredChains,
|
|
231
232
|
preferredTokens: payParams.preferredTokens,
|
|
233
|
+
evmChains: payParams.evmChains,
|
|
232
234
|
},
|
|
233
235
|
},
|
|
234
236
|
externalId: payParams.externalId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePaymentState.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"usePaymentState.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -2,7 +2,7 @@ import { useState, useEffect } from 'react';
|
|
|
2
2
|
import { supportedChainIds } from '../utils/exports.js';
|
|
3
3
|
|
|
4
4
|
/** Wallet payment options. User picks one. */
|
|
5
|
-
function useWalletPaymentOptions({ trpc, address, usdRequired, destChainId, preferredChains, preferredTokens, isDepositFlow, log, }) {
|
|
5
|
+
function useWalletPaymentOptions({ trpc, address, usdRequired, destChainId, preferredChains, preferredTokens, evmChains, isDepositFlow, log, }) {
|
|
6
6
|
const [options, setOptions] = useState(null);
|
|
7
7
|
const [isLoading, setIsLoading] = useState(false);
|
|
8
8
|
useEffect(() => {
|
|
@@ -19,6 +19,7 @@ function useWalletPaymentOptions({ trpc, address, usdRequired, destChainId, pref
|
|
|
19
19
|
destChainId,
|
|
20
20
|
preferredChains,
|
|
21
21
|
preferredTokens,
|
|
22
|
+
evmChains,
|
|
22
23
|
});
|
|
23
24
|
// Filter out chains we don't support yet.
|
|
24
25
|
const isSupported = (o) => supportedChainIds.has(o.balance.token.chainId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWalletPaymentOptions.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useWalletPaymentOptions.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { writeDaimoPayOrderID } from '@daimo/common';
|
|
2
|
+
import { daimoPayVersion } from './exports.js';
|
|
2
3
|
|
|
3
4
|
function getSupportUrl(daimoPayOrder, screen) {
|
|
4
|
-
const
|
|
5
|
+
const payId = daimoPayOrder == null ? null : writeDaimoPayOrderID(daimoPayOrder.id);
|
|
5
6
|
const email = "support@daimo.com";
|
|
6
|
-
const subject = `Support
|
|
7
|
-
let body =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
body
|
|
14
|
-
const mailtoUrl = `mailto:${email}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
|
15
|
-
return mailtoUrl;
|
|
7
|
+
const subject = `Support${payId ? ` #${payId}` : ""}`;
|
|
8
|
+
let body = [
|
|
9
|
+
`Transaction: ${screen}`,
|
|
10
|
+
`Version: ${daimoPayVersion}`,
|
|
11
|
+
``,
|
|
12
|
+
`Tell us how we can help`,
|
|
13
|
+
].join("\n");
|
|
14
|
+
return `mailto:${email}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
export { getSupportUrl };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supportUrl.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"supportUrl.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daimo/pay",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.0",
|
|
5
5
|
"author": "Daimo",
|
|
6
6
|
"homepage": "https://pay.daimo.com",
|
|
7
7
|
"license": "BSD-2-Clause license",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"crypto"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@daimo/common": "1.3.
|
|
44
|
-
"@daimo/contract": "1.3.
|
|
43
|
+
"@daimo/common": "1.3.4",
|
|
44
|
+
"@daimo/contract": "1.3.4",
|
|
45
45
|
"@solana/wallet-adapter-base": "^0.9.23",
|
|
46
46
|
"@solana/wallet-adapter-react": "^0.15.35",
|
|
47
47
|
"@solana/web3.js": "^1.95.4",
|