@daimo/pay 1.7.4 → 1.7.5
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 +8 -10
- package/build/index.js +116 -117
- package/build/index.js.map +1 -1
- package/package.json +3 -2
package/build/index.d.ts
CHANGED
|
@@ -68,6 +68,7 @@ type DaimoPayContextOptions = {
|
|
|
68
68
|
/** Modal UI options, set on the pay button triggering that modal. */
|
|
69
69
|
type DaimoPayModalOptions = {
|
|
70
70
|
closeOnSuccess?: boolean;
|
|
71
|
+
resetOnSuccess?: boolean;
|
|
71
72
|
};
|
|
72
73
|
/** Additional payment options. Onchain payments are always enabled. */
|
|
73
74
|
type PaymentOption = "Daimo" | "Coinbase" | "Binance" | "RampNetwork" | "Solana" | "ExternalChains" | "Lemon";
|
|
@@ -256,6 +257,8 @@ type PayButtonCommonProps = PayButtonPaymentProps & {
|
|
|
256
257
|
closeOnSuccess?: boolean;
|
|
257
258
|
/** Open the modal by default. */
|
|
258
259
|
defaultOpen?: boolean;
|
|
260
|
+
/** Reset the payment after a successful payment. */
|
|
261
|
+
resetOnSuccess?: boolean;
|
|
259
262
|
/** Custom message to display on confirmation page. */
|
|
260
263
|
confirmationMessage?: string;
|
|
261
264
|
/** Redirect URL to return to the app. E.g. after Coinbase, Binance, RampNetwork. */
|
|
@@ -303,10 +306,9 @@ declare namespace DaimoPayButtonCustom {
|
|
|
303
306
|
* to the payment's configured refund address on the destination chain.
|
|
304
307
|
*/
|
|
305
308
|
declare function useDaimoPayStatus(): {
|
|
306
|
-
paymentId
|
|
307
|
-
status
|
|
308
|
-
|
|
309
|
-
};
|
|
309
|
+
paymentId: string;
|
|
310
|
+
status: DaimoPayIntentStatus;
|
|
311
|
+
} | undefined;
|
|
310
312
|
|
|
311
313
|
/** Icon for an EVM chain, given chain ID. No ID shows a loading spinner. */
|
|
312
314
|
declare const Chain: React$1.FC<{
|
|
@@ -479,8 +481,6 @@ interface PaymentState {
|
|
|
479
481
|
resetOrder: () => void;
|
|
480
482
|
daimoPayOrder: DaimoPayOrder | undefined;
|
|
481
483
|
isDepositFlow: boolean;
|
|
482
|
-
modalOptions: DaimoPayModalOptions;
|
|
483
|
-
setModalOptions: (modalOptions: DaimoPayModalOptions) => void;
|
|
484
484
|
paymentWaitingMessage: string | undefined;
|
|
485
485
|
externalPaymentOptions: ReturnType<typeof useExternalPaymentOptions>;
|
|
486
486
|
showSolanaPaymentMethod: boolean;
|
|
@@ -503,10 +503,6 @@ interface PaymentState {
|
|
|
503
503
|
payWithDepositAddress: (option: DepositAddressPaymentOptions) => Promise<DepositAddressPaymentOptionData | null>;
|
|
504
504
|
payWithSolanaToken: (inputToken: SolanaPublicKey) => Promise<string | undefined>;
|
|
505
505
|
refreshOrder: () => Promise<void>;
|
|
506
|
-
onSuccess: (args: {
|
|
507
|
-
txHash: string;
|
|
508
|
-
txURL?: string;
|
|
509
|
-
}) => void;
|
|
510
506
|
senderEnsName: string | undefined;
|
|
511
507
|
}
|
|
512
508
|
|
|
@@ -555,6 +551,8 @@ type PayContextValue = {
|
|
|
555
551
|
paymentState: PaymentState;
|
|
556
552
|
/** TRPC API client. Internal use only. */
|
|
557
553
|
trpc: any;
|
|
554
|
+
/** Callback to call when the payment is successful. */
|
|
555
|
+
onSuccess: () => void;
|
|
558
556
|
/** Custom message to display on confirmation page. */
|
|
559
557
|
confirmationMessage?: string;
|
|
560
558
|
setConfirmationMessage: React$1.Dispatch<React$1.SetStateAction<string | undefined>>;
|
package/build/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { ExternalPaymentOptions, assert, assertNotNull, debugJson, supportedChains, ethereum, isCCTPV1Chain, getOrderDestChainId, readDaimoPayOrderID, getChainName, arbitrum as arbitrum$1, base as base$2, blast as blast$1, bsc as bsc$1, linea as linea$1, mantle as mantle$1, optimism as optimism$1, polygon as polygon$1, worldchain as worldchain$1, getAddressContraction, writeDaimoPayOrderID, DaimoPayOrderMode, DaimoPayOrderStatusDest, getChainExplorerTxUrl, DaimoPayIntentStatus, retryBackoff, DaimoPayOrderStatusSource, getDaimoPayOrderView } from '@daimo/pay-common';
|
|
3
3
|
import { Buffer } from 'buffer';
|
|
4
|
-
import React, { useState, useEffect, createContext,
|
|
4
|
+
import React, { useState, useEffect, createContext, useRef, useCallback, useLayoutEffect, useMemo, createElement } from 'react';
|
|
5
5
|
import styled$1, { css, keyframes, ThemeProvider } from 'styled-components';
|
|
6
6
|
import { http, useConfig, useAccountEffect, useWriteContract, useSendTransaction, useAccount, useEnsName, useConnectors as useConnectors$1, useSwitchChain, useConnect as useConnect$1, useDisconnect, useChainId, WagmiContext, createConfig, useEnsAddress, useEnsAvatar } from 'wagmi';
|
|
7
7
|
import { mainnet, base as base$1, polygon, optimism, arbitrum, linea, bsc, sepolia, baseSepolia, worldchain, blast, mantle } from 'wagmi/chains';
|
|
@@ -22,7 +22,7 @@ import { WalletSignTransactionError, WalletSendTransactionError } from '@solana/
|
|
|
22
22
|
import { normalize } from 'viem/ens';
|
|
23
23
|
|
|
24
24
|
var name = "@daimo/pay";
|
|
25
|
-
var version = "1.7.
|
|
25
|
+
var version = "1.7.5";
|
|
26
26
|
var author = "Daimo";
|
|
27
27
|
var homepage = "https://pay.daimo.com";
|
|
28
28
|
var license = "BSD-2-Clause license";
|
|
@@ -61,7 +61,7 @@ var keywords = [
|
|
|
61
61
|
"crypto"
|
|
62
62
|
];
|
|
63
63
|
var dependencies = {
|
|
64
|
-
"@daimo/pay-common": "1.7.
|
|
64
|
+
"@daimo/pay-common": "1.7.5",
|
|
65
65
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
66
66
|
"@solana/wallet-adapter-base": "^0.9.23",
|
|
67
67
|
"@solana/wallet-adapter-react": "^0.15.35",
|
|
@@ -94,6 +94,7 @@ var devDependencies = {
|
|
|
94
94
|
"@types/react-dom": "^18.2.18",
|
|
95
95
|
"@types/rollup-plugin-peer-deps-external": "^2.2.5",
|
|
96
96
|
"@types/styled-components": "^5.1.25",
|
|
97
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
97
98
|
rollup: "^3.29.5",
|
|
98
99
|
"rollup-plugin-dts": "^6.1.1",
|
|
99
100
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
@@ -244,14 +245,6 @@ const defaultConfig = ({ appName = "Daimo Pay", appIcon, appDescription, appUrl,
|
|
|
244
245
|
return config;
|
|
245
246
|
};
|
|
246
247
|
|
|
247
|
-
/** Determines whether the current wagmi configuration supports a given chain. */
|
|
248
|
-
function useChainIsSupported(chainId) {
|
|
249
|
-
const { chains } = useConfig();
|
|
250
|
-
if (!chainId)
|
|
251
|
-
return false;
|
|
252
|
-
return chains.some((x) => x.id === chainId);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
248
|
/** Returns currently configured wagmi chains. */
|
|
256
249
|
function useChains() {
|
|
257
250
|
const wagmi = useConfig();
|
|
@@ -843,47 +836,6 @@ function extractWcWalletFromProvider(p, log) {
|
|
|
843
836
|
return wallet;
|
|
844
837
|
}
|
|
845
838
|
|
|
846
|
-
function useGoogleFont(font) {
|
|
847
|
-
useEffect(() => {
|
|
848
|
-
if (!font)
|
|
849
|
-
return;
|
|
850
|
-
font = font.replace(/ /g, "+");
|
|
851
|
-
const googleapis = document.createElement("link");
|
|
852
|
-
googleapis.href = `https://fonts.googleapis.com`;
|
|
853
|
-
googleapis.rel = "preconnect";
|
|
854
|
-
const gstatic = document.createElement("link");
|
|
855
|
-
gstatic.href = `https://fonts.gstatic.com`;
|
|
856
|
-
gstatic.rel = "preconnect";
|
|
857
|
-
gstatic.crossOrigin = "true";
|
|
858
|
-
const link = document.createElement("link");
|
|
859
|
-
link.href = `https://fonts.googleapis.com/css2?family=${font}:wght@400;500;600&display=swap`;
|
|
860
|
-
link.rel = "stylesheet";
|
|
861
|
-
document.head.appendChild(googleapis);
|
|
862
|
-
document.head.appendChild(gstatic);
|
|
863
|
-
document.head.appendChild(link);
|
|
864
|
-
return () => {
|
|
865
|
-
try {
|
|
866
|
-
document.head.removeChild(googleapis);
|
|
867
|
-
document.head.removeChild(gstatic);
|
|
868
|
-
document.head.removeChild(link);
|
|
869
|
-
}
|
|
870
|
-
catch { }
|
|
871
|
-
};
|
|
872
|
-
}, [font]);
|
|
873
|
-
}
|
|
874
|
-
// TODO: This could be dynamic if theming wasn't set up as css variables
|
|
875
|
-
function useThemeFont(theme) {
|
|
876
|
-
const themeFonts = {
|
|
877
|
-
web95: "Lato",
|
|
878
|
-
retro: "Nunito",
|
|
879
|
-
midnight: "Inter",
|
|
880
|
-
minimal: "Inter",
|
|
881
|
-
rounded: "Nunito",
|
|
882
|
-
};
|
|
883
|
-
const font = themeFonts[theme] ?? null;
|
|
884
|
-
useGoogleFont(font ?? "");
|
|
885
|
-
}
|
|
886
|
-
|
|
887
839
|
/** Daimo Pay internal context. */
|
|
888
840
|
const usePayContext = () => {
|
|
889
841
|
const context = React.useContext(PayContext);
|
|
@@ -1175,7 +1127,7 @@ function useWalletPaymentOptions({ trpc, address, usdRequired, destChainId, pref
|
|
|
1175
1127
|
};
|
|
1176
1128
|
}
|
|
1177
1129
|
|
|
1178
|
-
function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder,
|
|
1130
|
+
function usePaymentState({ trpc, lockPayParams, daimoPayOrder, setDaimoPayOrder, setRoute, log, redirectReturnUrl, }) {
|
|
1179
1131
|
// Browser state.
|
|
1180
1132
|
const [platform, setPlatform] = useState();
|
|
1181
1133
|
useEffect(() => {
|
|
@@ -1198,12 +1150,14 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1198
1150
|
paymentOptions.includes(ExternalPaymentOptions.Solana)) &&
|
|
1199
1151
|
daimoPayOrder != null &&
|
|
1200
1152
|
isCCTPV1Chain(getOrderDestChainId(daimoPayOrder));
|
|
1201
|
-
//
|
|
1153
|
+
// Refs the survive re-renders and stores any updated param values while
|
|
1154
|
+
// lockPayParams is true
|
|
1155
|
+
const latestPayParamsRef = useRef();
|
|
1156
|
+
const latestPayIdRef = useRef();
|
|
1157
|
+
// Current pay params to do processing off of
|
|
1202
1158
|
const [payParams, setPayParamsState] = useState();
|
|
1203
1159
|
const [paymentWaitingMessage, setPaymentWaitingMessage] = useState();
|
|
1204
1160
|
const [isDepositFlow, setIsDepositFlow] = useState(false);
|
|
1205
|
-
// Payment UI config.
|
|
1206
|
-
const [modalOptions, setModalOptions] = useState({});
|
|
1207
1161
|
// UI state. Selection for external payment (Binance, etc) vs wallet payment.
|
|
1208
1162
|
const externalPaymentOptions = useExternalPaymentOptions({
|
|
1209
1163
|
trpc,
|
|
@@ -1341,7 +1295,7 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1341
1295
|
else {
|
|
1342
1296
|
log(`[CHECKOUT] IGNORING refreshOrder, wrong ID: ${order.id} vs ${daimoPayOrder.id}`);
|
|
1343
1297
|
}
|
|
1344
|
-
}, [daimoPayOrder
|
|
1298
|
+
}, [daimoPayOrder, trpc, setDaimoPayOrder, log]);
|
|
1345
1299
|
/** User picked a different deposit amount. */
|
|
1346
1300
|
const setChosenUsd = (usd) => {
|
|
1347
1301
|
assert(!!daimoPayOrder, "[SET CHOSEN USD] daimoPayOrder cannot be null");
|
|
@@ -1361,7 +1315,8 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1361
1315
|
});
|
|
1362
1316
|
};
|
|
1363
1317
|
const setPayId = useCallback(async (payId) => {
|
|
1364
|
-
|
|
1318
|
+
latestPayIdRef.current = payId;
|
|
1319
|
+
if (lockPayParams || !payId)
|
|
1365
1320
|
return;
|
|
1366
1321
|
const id = readDaimoPayOrderID(payId).toString();
|
|
1367
1322
|
if (daimoPayOrder && BigInt(id) == daimoPayOrder.id) {
|
|
@@ -1375,15 +1330,19 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1375
1330
|
}
|
|
1376
1331
|
log(`[CHECKOUT] setPayId: fetched order: ${JSON.stringify(order)}`);
|
|
1377
1332
|
setDaimoPayOrder(order);
|
|
1378
|
-
}, [daimoPayOrder]);
|
|
1333
|
+
}, [daimoPayOrder, lockPayParams, trpc, log, setDaimoPayOrder]);
|
|
1379
1334
|
/** Called whenever params change. */
|
|
1380
1335
|
const setPayParams = async (payParams) => {
|
|
1336
|
+
latestPayParamsRef.current = payParams;
|
|
1337
|
+
if (lockPayParams)
|
|
1338
|
+
return;
|
|
1381
1339
|
assert(payParams != null, "[SET PAY PARAMS] payParams cannot be null");
|
|
1340
|
+
console.log("[SET PAY PARAMS] setting payParams");
|
|
1382
1341
|
setPayParamsState(payParams);
|
|
1383
1342
|
setIsDepositFlow(payParams.toUnits == null);
|
|
1384
1343
|
generatePreviewOrder(payParams);
|
|
1385
1344
|
};
|
|
1386
|
-
const generatePreviewOrder = async (payParams) => {
|
|
1345
|
+
const generatePreviewOrder = useCallback(async (payParams) => {
|
|
1387
1346
|
// toUnits is undefined if and only if we're in deposit flow.
|
|
1388
1347
|
// Set dummy value for deposit flow, since user can edit the amount.
|
|
1389
1348
|
const toUnits = payParams.toUnits == null ? "0" : payParams.toUnits;
|
|
@@ -1411,16 +1370,28 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1411
1370
|
});
|
|
1412
1371
|
log(`[CHECKOUT] generated preview: ${JSON.stringify(orderPreview)}`);
|
|
1413
1372
|
setDaimoPayOrder(orderPreview);
|
|
1414
|
-
};
|
|
1415
|
-
const
|
|
1416
|
-
|
|
1417
|
-
log(`[CHECKOUT] transaction succeeded, closing: ${txHash} ${txURL}`);
|
|
1418
|
-
setTimeout(() => setOpen(false, { event: "wait-success" }), 1000);
|
|
1419
|
-
}
|
|
1420
|
-
};
|
|
1421
|
-
const resetOrder = () => {
|
|
1373
|
+
}, [trpc, log, setDaimoPayOrder]);
|
|
1374
|
+
const resetOrder = useCallback(() => {
|
|
1375
|
+
// Clear the old order & UI
|
|
1422
1376
|
setDaimoPayOrder(undefined);
|
|
1423
|
-
|
|
1377
|
+
setRoute(ROUTES.SELECT_METHOD);
|
|
1378
|
+
// Prefer an explicit payId, otherwise use the queued payParams
|
|
1379
|
+
if (latestPayIdRef.current) {
|
|
1380
|
+
setPayId(latestPayIdRef.current);
|
|
1381
|
+
latestPayIdRef.current = undefined;
|
|
1382
|
+
}
|
|
1383
|
+
else if (latestPayParamsRef.current) {
|
|
1384
|
+
const p = latestPayParamsRef.current;
|
|
1385
|
+
setPayParamsState(p);
|
|
1386
|
+
generatePreviewOrder(p);
|
|
1387
|
+
}
|
|
1388
|
+
}, [
|
|
1389
|
+
setDaimoPayOrder,
|
|
1390
|
+
setRoute,
|
|
1391
|
+
setPayId,
|
|
1392
|
+
setPayParamsState,
|
|
1393
|
+
generatePreviewOrder,
|
|
1394
|
+
]);
|
|
1424
1395
|
return {
|
|
1425
1396
|
setPayId,
|
|
1426
1397
|
payParams,
|
|
@@ -1428,8 +1399,6 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1428
1399
|
generatePreviewOrder,
|
|
1429
1400
|
daimoPayOrder,
|
|
1430
1401
|
isDepositFlow,
|
|
1431
|
-
modalOptions,
|
|
1432
|
-
setModalOptions,
|
|
1433
1402
|
paymentWaitingMessage,
|
|
1434
1403
|
selectedExternalOption,
|
|
1435
1404
|
selectedTokenOption,
|
|
@@ -1453,7 +1422,6 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1453
1422
|
payWithDepositAddress,
|
|
1454
1423
|
payWithSolanaToken,
|
|
1455
1424
|
refreshOrder,
|
|
1456
|
-
onSuccess,
|
|
1457
1425
|
senderEnsName: senderEnsName ?? undefined,
|
|
1458
1426
|
};
|
|
1459
1427
|
}
|
|
@@ -6889,6 +6857,14 @@ function useWalletConnectUri({ enabled } = {
|
|
|
6889
6857
|
};
|
|
6890
6858
|
}
|
|
6891
6859
|
|
|
6860
|
+
/** Determines whether the current wagmi configuration supports a given chain. */
|
|
6861
|
+
function useChainIsSupported(chainId) {
|
|
6862
|
+
const { chains } = useConfig();
|
|
6863
|
+
if (!chainId)
|
|
6864
|
+
return false;
|
|
6865
|
+
return chains.some((x) => x.id === chainId);
|
|
6866
|
+
}
|
|
6867
|
+
|
|
6892
6868
|
const Web3Context = React.createContext({
|
|
6893
6869
|
connect: {
|
|
6894
6870
|
getUri: () => "",
|
|
@@ -9610,20 +9586,17 @@ const Underline = styled(motion.span) `
|
|
|
9610
9586
|
`;
|
|
9611
9587
|
|
|
9612
9588
|
const Confirmation = () => {
|
|
9613
|
-
const { paymentState, confirmationMessage } = usePayContext();
|
|
9589
|
+
const { paymentState, confirmationMessage, onSuccess } = usePayContext();
|
|
9614
9590
|
const { daimoPayOrder } = paymentState;
|
|
9615
|
-
const { done, txURL } = (() => {
|
|
9591
|
+
const { done, txURL } = useMemo(() => {
|
|
9616
9592
|
if (daimoPayOrder && daimoPayOrder.mode === DaimoPayOrderMode.HYDRATED) {
|
|
9617
|
-
// Frontends are optimistic, assume submits will be successful
|
|
9618
9593
|
const { destStatus } = daimoPayOrder;
|
|
9619
|
-
if (destStatus === DaimoPayOrderStatusDest.
|
|
9620
|
-
destStatus === DaimoPayOrderStatusDest.FAST_FINISHED ||
|
|
9594
|
+
if (destStatus === DaimoPayOrderStatusDest.FAST_FINISHED ||
|
|
9621
9595
|
destStatus === DaimoPayOrderStatusDest.CLAIM_SUCCESSFUL) {
|
|
9622
9596
|
const txHash = daimoPayOrder.destFastFinishTxHash ?? daimoPayOrder.destClaimTxHash;
|
|
9623
|
-
const
|
|
9597
|
+
const destChainId = getOrderDestChainId(daimoPayOrder);
|
|
9624
9598
|
assert(txHash != null, `[CONFIRMATION] dest status: ${destStatus}, but missing txHash`);
|
|
9625
|
-
const txURL = getChainExplorerTxUrl(
|
|
9626
|
-
paymentState.onSuccess({ txHash, txURL });
|
|
9599
|
+
const txURL = getChainExplorerTxUrl(destChainId, txHash);
|
|
9627
9600
|
return {
|
|
9628
9601
|
done: true,
|
|
9629
9602
|
txURL,
|
|
@@ -9634,7 +9607,12 @@ const Confirmation = () => {
|
|
|
9634
9607
|
done: false,
|
|
9635
9608
|
txURL: undefined,
|
|
9636
9609
|
};
|
|
9637
|
-
})
|
|
9610
|
+
}, [daimoPayOrder]);
|
|
9611
|
+
useEffect(() => {
|
|
9612
|
+
if (done) {
|
|
9613
|
+
onSuccess();
|
|
9614
|
+
}
|
|
9615
|
+
}, [done, onSuccess]);
|
|
9638
9616
|
return (jsx(PageContent, { style: {
|
|
9639
9617
|
display: "flex",
|
|
9640
9618
|
justifyContent: "center",
|
|
@@ -9678,8 +9656,6 @@ const Link = styled.a `
|
|
|
9678
9656
|
`;
|
|
9679
9657
|
const SuccessIcon = styled(TickIcon) `
|
|
9680
9658
|
color: var(--ck-body-color-valid);
|
|
9681
|
-
|
|
9682
|
-
transform: scale(0.5);
|
|
9683
9659
|
transition: all 0.2s ease-in-out;
|
|
9684
9660
|
position: absolute;
|
|
9685
9661
|
opacity: ${(props) => (props.$status ? 1 : 0)};
|
|
@@ -9690,7 +9666,6 @@ const Spinner$1 = styled(LoadingCircleIcon) `
|
|
|
9690
9666
|
transition: all 0.2s ease-in-out;
|
|
9691
9667
|
animation: rotateSpinner 400ms linear infinite;
|
|
9692
9668
|
opacity: ${(props) => (props.$status ? 0 : 1)};
|
|
9693
|
-
transform: ${(props) => (props.$status ? "scale(0.5)" : "scale(1)")};
|
|
9694
9669
|
|
|
9695
9670
|
@keyframes rotateSpinner {
|
|
9696
9671
|
0% {
|
|
@@ -11229,9 +11204,9 @@ const WaitingExternal = () => {
|
|
|
11229
11204
|
}, children: selectedExternalOption.cta })] }));
|
|
11230
11205
|
};
|
|
11231
11206
|
|
|
11232
|
-
const
|
|
11233
|
-
const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThemeDefault, lang = "en-US", }) => {
|
|
11207
|
+
const DaimoPayModal = ({ mode, theme, customTheme, lang, }) => {
|
|
11234
11208
|
const context = usePayContext();
|
|
11209
|
+
const { setMode, setTheme, setCustomTheme, setLang } = context;
|
|
11235
11210
|
const paymentState = context.paymentState;
|
|
11236
11211
|
const { payParams, generatePreviewOrder, isDepositFlow, showSolanaPaymentMethod, setPaymentWaitingMessage, setSelectedExternalOption, setSelectedTokenOption, setSelectedSolanaTokenOption, setSelectedDepositAddressOption, } = paymentState;
|
|
11237
11212
|
const { isConnected: isEthConnected, connector, chain, address, } = useAccount();
|
|
@@ -11387,12 +11362,16 @@ const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThem
|
|
|
11387
11362
|
}
|
|
11388
11363
|
// Don't include context.route in the dependency array otherwise the user
|
|
11389
11364
|
// can't go back from the select token screen to the select method screen
|
|
11365
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11390
11366
|
}, [
|
|
11391
11367
|
context.open,
|
|
11392
11368
|
context.wcWallet,
|
|
11393
11369
|
isEthConnected,
|
|
11394
11370
|
isSolanaConnected,
|
|
11395
11371
|
showSolanaPaymentMethod,
|
|
11372
|
+
address,
|
|
11373
|
+
chain?.id,
|
|
11374
|
+
connector?.id,
|
|
11396
11375
|
]);
|
|
11397
11376
|
// If we're on the connect page and the user successfully connects their
|
|
11398
11377
|
// wallet, go to the select token page
|
|
@@ -11409,11 +11388,12 @@ const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThem
|
|
|
11409
11388
|
});
|
|
11410
11389
|
}
|
|
11411
11390
|
}
|
|
11391
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11412
11392
|
}, [isEthConnected, context.route, connector?.id, chain?.id, address]);
|
|
11413
|
-
useEffect(() =>
|
|
11414
|
-
useEffect(() =>
|
|
11415
|
-
useEffect(() =>
|
|
11416
|
-
useEffect(() =>
|
|
11393
|
+
useEffect(() => setMode(mode), [mode, setMode]);
|
|
11394
|
+
useEffect(() => setTheme(theme), [theme, setTheme]);
|
|
11395
|
+
useEffect(() => setCustomTheme(customTheme), [customTheme, setCustomTheme]);
|
|
11396
|
+
useEffect(() => setLang(lang), [lang, setLang]);
|
|
11417
11397
|
/* When pulling data into WalletConnect, it prioritises the og:title tag over the title tag */
|
|
11418
11398
|
useEffect(() => {
|
|
11419
11399
|
const appName = getAppName();
|
|
@@ -11517,7 +11497,10 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11517
11497
|
onCloseRef.current = fn;
|
|
11518
11498
|
}, []);
|
|
11519
11499
|
const [open, setOpenState] = useState(false);
|
|
11500
|
+
const [lockPayParams, setLockPayParams] = useState(false);
|
|
11501
|
+
const [paymentCompleted, setPaymentCompleted] = useState(false);
|
|
11520
11502
|
const [route, setRouteState] = useState(ROUTES.SELECT_METHOD);
|
|
11503
|
+
const [modalOptions, setModalOptions] = useState();
|
|
11521
11504
|
// Daimo Pay context
|
|
11522
11505
|
const [daimoPayOrder, setDaimoPayOrderInner] = useState();
|
|
11523
11506
|
const [pendingConnectorId, setPendingConnectorId] = useState(undefined);
|
|
@@ -11528,22 +11511,46 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11528
11511
|
const [errorMessage, setErrorMessage] = useState("");
|
|
11529
11512
|
const [confirmationMessage, setConfirmationMessage] = useState(undefined);
|
|
11530
11513
|
const [redirectReturnUrl, setRedirectReturnUrl] = useState(undefined);
|
|
11531
|
-
const log = debugMode ? console.log : () => { };
|
|
11514
|
+
const log = useMemo(() => (debugMode ? console.log : () => { }), [debugMode]);
|
|
11532
11515
|
// Connect to the Daimo Pay TRPC API
|
|
11533
|
-
const trpc = useMemo(() => createTrpcClient(payApiUrl, sessionId), [payApiUrl]);
|
|
11516
|
+
const trpc = useMemo(() => createTrpcClient(payApiUrl, sessionId), [payApiUrl, sessionId]);
|
|
11534
11517
|
const [resize, onResize] = useState(0);
|
|
11535
11518
|
const setOpen = useCallback((open, meta) => {
|
|
11536
11519
|
setOpenState(open);
|
|
11520
|
+
// Lock pay params starting from the first time the modal is opened to
|
|
11521
|
+
// prevent the daimo pay order from changing from under the user
|
|
11522
|
+
if (open) {
|
|
11523
|
+
setLockPayParams(true);
|
|
11524
|
+
}
|
|
11525
|
+
// Reset payment state on close if resetOnSuccess is true
|
|
11526
|
+
if (!open && paymentCompleted && modalOptions?.resetOnSuccess) {
|
|
11527
|
+
setPaymentCompleted(false);
|
|
11528
|
+
setLockPayParams(false);
|
|
11529
|
+
paymentState.resetOrder();
|
|
11530
|
+
}
|
|
11531
|
+
// Log the open/close event
|
|
11537
11532
|
trpc.nav.mutate({
|
|
11538
11533
|
action: open ? "navOpenPay" : "navClosePay",
|
|
11539
11534
|
orderId: daimoPayOrder?.id?.toString(),
|
|
11540
11535
|
data: meta ?? {},
|
|
11541
11536
|
});
|
|
11537
|
+
// Run the onOpen and onClose callbacks
|
|
11542
11538
|
if (open)
|
|
11543
11539
|
onOpenRef.current?.();
|
|
11544
11540
|
else
|
|
11545
11541
|
onCloseRef.current?.();
|
|
11546
|
-
},
|
|
11542
|
+
},
|
|
11543
|
+
// We don't have good caching on paymentState, so don't include it as a dep
|
|
11544
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11545
|
+
[trpc, daimoPayOrder?.id, modalOptions?.resetOnSuccess, paymentCompleted]);
|
|
11546
|
+
// Callback when a payment is successfully completed (regardless of whether
|
|
11547
|
+
// the final call succeeded or bounced)
|
|
11548
|
+
const onSuccess = useCallback(() => {
|
|
11549
|
+
if (modalOptions?.closeOnSuccess) {
|
|
11550
|
+
setTimeout(() => setOpen(false, { event: "wait-success" }), 1000);
|
|
11551
|
+
}
|
|
11552
|
+
setPaymentCompleted(true);
|
|
11553
|
+
}, [modalOptions?.closeOnSuccess, setOpen, setPaymentCompleted]);
|
|
11547
11554
|
const setRoute = useCallback((route, data) => {
|
|
11548
11555
|
const action = route.replace("daimoPay", "");
|
|
11549
11556
|
log(`[SET ROUTE] ${action} ${daimoPayOrder?.id} ${debugJson(data ?? {})}`);
|
|
@@ -11554,23 +11561,11 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11554
11561
|
});
|
|
11555
11562
|
setRouteState(route);
|
|
11556
11563
|
}, [trpc, daimoPayOrder?.id, log]);
|
|
11557
|
-
// Include Google Font that is needed for a themes
|
|
11558
|
-
if (opts.embedGoogleFonts)
|
|
11559
|
-
useThemeFont(ckTheme);
|
|
11560
11564
|
// Other Configuration
|
|
11561
11565
|
useEffect(() => setTheme(theme), [theme]);
|
|
11562
11566
|
useEffect(() => setLang(opts.language || "en-US"), [opts.language]);
|
|
11563
11567
|
useEffect(() => setErrorMessage(null), [route, open]);
|
|
11564
|
-
|
|
11565
|
-
const { chain, isConnected, connector } = useAccount();
|
|
11566
|
-
const isChainSupported = useChainIsSupported(chain?.id);
|
|
11567
|
-
useEffect(() => {
|
|
11568
|
-
if (isConnected && opts.enforceSupportedChains && !isChainSupported) {
|
|
11569
|
-
setOpen(true);
|
|
11570
|
-
if (route !== ROUTES.SWITCHNETWORKS)
|
|
11571
|
-
setRoute(ROUTES.SWITCHNETWORKS);
|
|
11572
|
-
}
|
|
11573
|
-
}, [isConnected, isChainSupported, chain, route, open]);
|
|
11568
|
+
const { connector } = useAccount();
|
|
11574
11569
|
// Single source of truth for the currently-connected wallet is the connector
|
|
11575
11570
|
// exposed by wagmi. See useAccount(). We watch this connector and use it to
|
|
11576
11571
|
// extract the current WalletConnect wallet, if any.
|
|
@@ -11593,9 +11588,10 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11593
11588
|
}, [log]);
|
|
11594
11589
|
const paymentState = usePaymentState({
|
|
11595
11590
|
trpc,
|
|
11591
|
+
lockPayParams,
|
|
11596
11592
|
daimoPayOrder,
|
|
11597
11593
|
setDaimoPayOrder,
|
|
11598
|
-
|
|
11594
|
+
setRoute,
|
|
11599
11595
|
log,
|
|
11600
11596
|
redirectReturnUrl,
|
|
11601
11597
|
});
|
|
@@ -11619,11 +11615,13 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11619
11615
|
log(`[PAY] polling in ${intervalMs}ms`);
|
|
11620
11616
|
const timeout = setTimeout(() => retryBackoff("refreshOrder", () => paymentState.refreshOrder()), intervalMs);
|
|
11621
11617
|
return () => clearTimeout(timeout);
|
|
11622
|
-
|
|
11618
|
+
// We don't have good caching on paymentState, so don't include it as a dep
|
|
11619
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11620
|
+
}, [daimoPayOrder, log]);
|
|
11623
11621
|
const showPayment = async (modalOptions) => {
|
|
11624
11622
|
const id = daimoPayOrder?.id;
|
|
11625
11623
|
log(`[PAY] showing payment ${debugJson({ id, modalOptions })}`);
|
|
11626
|
-
|
|
11624
|
+
setModalOptions(modalOptions);
|
|
11627
11625
|
setOpen(true);
|
|
11628
11626
|
if (daimoPayOrder &&
|
|
11629
11627
|
daimoPayOrder.mode === DaimoPayOrderMode.HYDRATED &&
|
|
@@ -11663,6 +11661,7 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11663
11661
|
// Other configuration
|
|
11664
11662
|
options: opts,
|
|
11665
11663
|
errorMessage,
|
|
11664
|
+
onSuccess,
|
|
11666
11665
|
confirmationMessage,
|
|
11667
11666
|
setConfirmationMessage,
|
|
11668
11667
|
redirectReturnUrl,
|
|
@@ -11946,6 +11945,7 @@ function DaimoPayButtonCustom(props) {
|
|
|
11946
11945
|
else if (payParams != null) {
|
|
11947
11946
|
paymentState.setPayParams(payParams);
|
|
11948
11947
|
}
|
|
11948
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11949
11949
|
}, [payId, JSON.stringify(payParams || {})]);
|
|
11950
11950
|
// Set the confirmation message
|
|
11951
11951
|
const { setConfirmationMessage } = context;
|
|
@@ -11977,14 +11977,14 @@ function DaimoPayButtonCustom(props) {
|
|
|
11977
11977
|
const intentStatus = order?.intentStatus;
|
|
11978
11978
|
const hydOrder = order?.mode === DaimoPayOrderMode.HYDRATED ? order : null;
|
|
11979
11979
|
// Functions to show and hide the modal
|
|
11980
|
-
const { children, closeOnSuccess } = props;
|
|
11981
|
-
const
|
|
11982
|
-
const show = () => {
|
|
11980
|
+
const { children, closeOnSuccess, resetOnSuccess } = props;
|
|
11981
|
+
const show = useCallback(() => {
|
|
11983
11982
|
if (paymentState.daimoPayOrder == null)
|
|
11984
11983
|
return;
|
|
11984
|
+
const modalOptions = { closeOnSuccess, resetOnSuccess };
|
|
11985
11985
|
context.showPayment(modalOptions);
|
|
11986
|
-
};
|
|
11987
|
-
const hide = () => context.setOpen(false);
|
|
11986
|
+
}, [context, paymentState.daimoPayOrder, closeOnSuccess, resetOnSuccess]);
|
|
11987
|
+
const hide = useCallback(() => context.setOpen(false), [context]);
|
|
11988
11988
|
// Emit event handlers when payment status changes
|
|
11989
11989
|
const sentStart = useRef(false);
|
|
11990
11990
|
useEffect(() => {
|
|
@@ -12079,12 +12079,11 @@ function DaimoPayButtonInner({ disabled }) {
|
|
|
12079
12079
|
*/
|
|
12080
12080
|
function useDaimoPayStatus() {
|
|
12081
12081
|
const { paymentState } = usePayContext();
|
|
12082
|
-
const reset = paymentState.resetOrder;
|
|
12083
12082
|
if (!paymentState || !paymentState.daimoPayOrder)
|
|
12084
|
-
return
|
|
12083
|
+
return undefined;
|
|
12085
12084
|
const order = paymentState.daimoPayOrder;
|
|
12086
12085
|
const paymentId = writeDaimoPayOrderID(order.id);
|
|
12087
|
-
return { paymentId, status: order.intentStatus
|
|
12086
|
+
return { paymentId, status: order.intentStatus };
|
|
12088
12087
|
}
|
|
12089
12088
|
|
|
12090
12089
|
function addressToNumber(address) {
|