@daimo/pay 1.7.4 → 1.7.6
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 +143 -133
- 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.6";
|
|
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.6",
|
|
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();
|
|
@@ -543,6 +536,7 @@ const walletConfigs = {
|
|
|
543
536
|
},
|
|
544
537
|
"metaMask, metaMask-io, io.metamask, io.metamask.mobile, metaMaskSDK": {
|
|
545
538
|
name: "MetaMask",
|
|
539
|
+
shortName: "MetaMask",
|
|
546
540
|
icon: jsx(Logos$1.MetaMask, {}),
|
|
547
541
|
iconConnector: jsx(Logos$1.MetaMask, {}),
|
|
548
542
|
iconShouldShrink: true,
|
|
@@ -843,47 +837,6 @@ function extractWcWalletFromProvider(p, log) {
|
|
|
843
837
|
return wallet;
|
|
844
838
|
}
|
|
845
839
|
|
|
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
840
|
/** Daimo Pay internal context. */
|
|
888
841
|
const usePayContext = () => {
|
|
889
842
|
const context = React.useContext(PayContext);
|
|
@@ -1175,7 +1128,7 @@ function useWalletPaymentOptions({ trpc, address, usdRequired, destChainId, pref
|
|
|
1175
1128
|
};
|
|
1176
1129
|
}
|
|
1177
1130
|
|
|
1178
|
-
function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder,
|
|
1131
|
+
function usePaymentState({ trpc, lockPayParams, daimoPayOrder, setDaimoPayOrder, setRoute, log, redirectReturnUrl, }) {
|
|
1179
1132
|
// Browser state.
|
|
1180
1133
|
const [platform, setPlatform] = useState();
|
|
1181
1134
|
useEffect(() => {
|
|
@@ -1198,12 +1151,14 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1198
1151
|
paymentOptions.includes(ExternalPaymentOptions.Solana)) &&
|
|
1199
1152
|
daimoPayOrder != null &&
|
|
1200
1153
|
isCCTPV1Chain(getOrderDestChainId(daimoPayOrder));
|
|
1201
|
-
//
|
|
1154
|
+
// Refs the survive re-renders and stores any updated param values while
|
|
1155
|
+
// lockPayParams is true
|
|
1156
|
+
const latestPayParamsRef = useRef();
|
|
1157
|
+
const latestPayIdRef = useRef();
|
|
1158
|
+
// Current pay params to do processing off of
|
|
1202
1159
|
const [payParams, setPayParamsState] = useState();
|
|
1203
1160
|
const [paymentWaitingMessage, setPaymentWaitingMessage] = useState();
|
|
1204
1161
|
const [isDepositFlow, setIsDepositFlow] = useState(false);
|
|
1205
|
-
// Payment UI config.
|
|
1206
|
-
const [modalOptions, setModalOptions] = useState({});
|
|
1207
1162
|
// UI state. Selection for external payment (Binance, etc) vs wallet payment.
|
|
1208
1163
|
const externalPaymentOptions = useExternalPaymentOptions({
|
|
1209
1164
|
trpc,
|
|
@@ -1341,7 +1296,7 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1341
1296
|
else {
|
|
1342
1297
|
log(`[CHECKOUT] IGNORING refreshOrder, wrong ID: ${order.id} vs ${daimoPayOrder.id}`);
|
|
1343
1298
|
}
|
|
1344
|
-
}, [daimoPayOrder
|
|
1299
|
+
}, [daimoPayOrder, trpc, setDaimoPayOrder, log]);
|
|
1345
1300
|
/** User picked a different deposit amount. */
|
|
1346
1301
|
const setChosenUsd = (usd) => {
|
|
1347
1302
|
assert(!!daimoPayOrder, "[SET CHOSEN USD] daimoPayOrder cannot be null");
|
|
@@ -1361,7 +1316,8 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1361
1316
|
});
|
|
1362
1317
|
};
|
|
1363
1318
|
const setPayId = useCallback(async (payId) => {
|
|
1364
|
-
|
|
1319
|
+
latestPayIdRef.current = payId;
|
|
1320
|
+
if (lockPayParams || !payId)
|
|
1365
1321
|
return;
|
|
1366
1322
|
const id = readDaimoPayOrderID(payId).toString();
|
|
1367
1323
|
if (daimoPayOrder && BigInt(id) == daimoPayOrder.id) {
|
|
@@ -1375,15 +1331,19 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1375
1331
|
}
|
|
1376
1332
|
log(`[CHECKOUT] setPayId: fetched order: ${JSON.stringify(order)}`);
|
|
1377
1333
|
setDaimoPayOrder(order);
|
|
1378
|
-
}, [daimoPayOrder]);
|
|
1334
|
+
}, [daimoPayOrder, lockPayParams, trpc, log, setDaimoPayOrder]);
|
|
1379
1335
|
/** Called whenever params change. */
|
|
1380
1336
|
const setPayParams = async (payParams) => {
|
|
1337
|
+
latestPayParamsRef.current = payParams;
|
|
1338
|
+
if (lockPayParams)
|
|
1339
|
+
return;
|
|
1381
1340
|
assert(payParams != null, "[SET PAY PARAMS] payParams cannot be null");
|
|
1341
|
+
console.log("[SET PAY PARAMS] setting payParams");
|
|
1382
1342
|
setPayParamsState(payParams);
|
|
1383
1343
|
setIsDepositFlow(payParams.toUnits == null);
|
|
1384
1344
|
generatePreviewOrder(payParams);
|
|
1385
1345
|
};
|
|
1386
|
-
const generatePreviewOrder = async (payParams) => {
|
|
1346
|
+
const generatePreviewOrder = useCallback(async (payParams) => {
|
|
1387
1347
|
// toUnits is undefined if and only if we're in deposit flow.
|
|
1388
1348
|
// Set dummy value for deposit flow, since user can edit the amount.
|
|
1389
1349
|
const toUnits = payParams.toUnits == null ? "0" : payParams.toUnits;
|
|
@@ -1411,16 +1371,28 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1411
1371
|
});
|
|
1412
1372
|
log(`[CHECKOUT] generated preview: ${JSON.stringify(orderPreview)}`);
|
|
1413
1373
|
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 = () => {
|
|
1374
|
+
}, [trpc, log, setDaimoPayOrder]);
|
|
1375
|
+
const resetOrder = useCallback(() => {
|
|
1376
|
+
// Clear the old order & UI
|
|
1422
1377
|
setDaimoPayOrder(undefined);
|
|
1423
|
-
|
|
1378
|
+
setRoute(ROUTES.SELECT_METHOD);
|
|
1379
|
+
// Prefer an explicit payId, otherwise use the queued payParams
|
|
1380
|
+
if (latestPayIdRef.current) {
|
|
1381
|
+
setPayId(latestPayIdRef.current);
|
|
1382
|
+
latestPayIdRef.current = undefined;
|
|
1383
|
+
}
|
|
1384
|
+
else if (latestPayParamsRef.current) {
|
|
1385
|
+
const p = latestPayParamsRef.current;
|
|
1386
|
+
setPayParamsState(p);
|
|
1387
|
+
generatePreviewOrder(p);
|
|
1388
|
+
}
|
|
1389
|
+
}, [
|
|
1390
|
+
setDaimoPayOrder,
|
|
1391
|
+
setRoute,
|
|
1392
|
+
setPayId,
|
|
1393
|
+
setPayParamsState,
|
|
1394
|
+
generatePreviewOrder,
|
|
1395
|
+
]);
|
|
1424
1396
|
return {
|
|
1425
1397
|
setPayId,
|
|
1426
1398
|
payParams,
|
|
@@ -1428,8 +1400,6 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1428
1400
|
generatePreviewOrder,
|
|
1429
1401
|
daimoPayOrder,
|
|
1430
1402
|
isDepositFlow,
|
|
1431
|
-
modalOptions,
|
|
1432
|
-
setModalOptions,
|
|
1433
1403
|
paymentWaitingMessage,
|
|
1434
1404
|
selectedExternalOption,
|
|
1435
1405
|
selectedTokenOption,
|
|
@@ -1453,7 +1423,6 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1453
1423
|
payWithDepositAddress,
|
|
1454
1424
|
payWithSolanaToken,
|
|
1455
1425
|
refreshOrder,
|
|
1456
|
-
onSuccess,
|
|
1457
1426
|
senderEnsName: senderEnsName ?? undefined,
|
|
1458
1427
|
};
|
|
1459
1428
|
}
|
|
@@ -4906,32 +4875,42 @@ const useWallets = (isMobile) => {
|
|
|
4906
4875
|
const context = usePayContext();
|
|
4907
4876
|
if (isMobile) {
|
|
4908
4877
|
const mobileWallets = [];
|
|
4909
|
-
// Add
|
|
4910
|
-
mobileWallets.push({
|
|
4911
|
-
id: "me.rainbow",
|
|
4912
|
-
...walletConfigs["me.rainbow"],
|
|
4913
|
-
});
|
|
4914
|
-
// Add MetaMask second
|
|
4915
|
-
const metaMaskConnector = connectors.find((c) => c.id === "metaMask");
|
|
4916
|
-
if (metaMaskConnector) {
|
|
4917
|
-
mobileWallets.push({
|
|
4918
|
-
id: metaMaskConnector.id,
|
|
4919
|
-
connector: metaMaskConnector,
|
|
4920
|
-
...walletConfigs["metaMask, metaMask-io, io.metamask, io.metamask.mobile, metaMaskSDK"],
|
|
4921
|
-
});
|
|
4922
|
-
}
|
|
4923
|
-
// Add WalletConnect and other wallets
|
|
4878
|
+
// Add injected wallet (if any) first
|
|
4924
4879
|
connectors.forEach((connector) => {
|
|
4925
4880
|
if (connector.id === "metaMask")
|
|
4926
4881
|
return;
|
|
4882
|
+
if (connector.id === "walletConnect")
|
|
4883
|
+
return;
|
|
4927
4884
|
if (isCoinbaseWalletConnector(connector.id))
|
|
4928
4885
|
return;
|
|
4929
4886
|
mobileWallets.push({
|
|
4930
4887
|
id: connector.id,
|
|
4931
4888
|
connector,
|
|
4932
|
-
|
|
4889
|
+
shortName: connector.name,
|
|
4890
|
+
iconConnector: jsx("img", { src: connector.icon, alt: connector.name }),
|
|
4891
|
+
iconShape: "squircle",
|
|
4933
4892
|
});
|
|
4934
4893
|
});
|
|
4894
|
+
function addIfNotPresent(idList) {
|
|
4895
|
+
if (mobileWallets.find((w) => idList.includes(w.id)))
|
|
4896
|
+
return;
|
|
4897
|
+
const wallet = assertNotNull(walletConfigs[idList], () => `missing ${idList}`);
|
|
4898
|
+
mobileWallets.push({
|
|
4899
|
+
id: idList,
|
|
4900
|
+
...wallet,
|
|
4901
|
+
});
|
|
4902
|
+
}
|
|
4903
|
+
addIfNotPresent("me.rainbow");
|
|
4904
|
+
addIfNotPresent("metaMask, metaMask-io, io.metamask, io.metamask.mobile, metaMaskSDK");
|
|
4905
|
+
// Add WalletConnect last
|
|
4906
|
+
const walletConnectConnector = connectors.find((c) => c.id === "walletConnect");
|
|
4907
|
+
if (walletConnectConnector) {
|
|
4908
|
+
mobileWallets.push({
|
|
4909
|
+
id: walletConnectConnector.id,
|
|
4910
|
+
connector: walletConnectConnector,
|
|
4911
|
+
...walletConfigs[walletConnectConnector.id],
|
|
4912
|
+
});
|
|
4913
|
+
}
|
|
4935
4914
|
return mobileWallets;
|
|
4936
4915
|
}
|
|
4937
4916
|
const wallets = connectors.map((connector) => {
|
|
@@ -6889,6 +6868,14 @@ function useWalletConnectUri({ enabled } = {
|
|
|
6889
6868
|
};
|
|
6890
6869
|
}
|
|
6891
6870
|
|
|
6871
|
+
/** Determines whether the current wagmi configuration supports a given chain. */
|
|
6872
|
+
function useChainIsSupported(chainId) {
|
|
6873
|
+
const { chains } = useConfig();
|
|
6874
|
+
if (!chainId)
|
|
6875
|
+
return false;
|
|
6876
|
+
return chains.some((x) => x.id === chainId);
|
|
6877
|
+
}
|
|
6878
|
+
|
|
6892
6879
|
const Web3Context = React.createContext({
|
|
6893
6880
|
connect: {
|
|
6894
6881
|
getUri: () => "",
|
|
@@ -9610,20 +9597,17 @@ const Underline = styled(motion.span) `
|
|
|
9610
9597
|
`;
|
|
9611
9598
|
|
|
9612
9599
|
const Confirmation = () => {
|
|
9613
|
-
const { paymentState, confirmationMessage } = usePayContext();
|
|
9600
|
+
const { paymentState, confirmationMessage, onSuccess } = usePayContext();
|
|
9614
9601
|
const { daimoPayOrder } = paymentState;
|
|
9615
|
-
const { done, txURL } = (() => {
|
|
9602
|
+
const { done, txURL } = useMemo(() => {
|
|
9616
9603
|
if (daimoPayOrder && daimoPayOrder.mode === DaimoPayOrderMode.HYDRATED) {
|
|
9617
|
-
// Frontends are optimistic, assume submits will be successful
|
|
9618
9604
|
const { destStatus } = daimoPayOrder;
|
|
9619
|
-
if (destStatus === DaimoPayOrderStatusDest.
|
|
9620
|
-
destStatus === DaimoPayOrderStatusDest.FAST_FINISHED ||
|
|
9605
|
+
if (destStatus === DaimoPayOrderStatusDest.FAST_FINISHED ||
|
|
9621
9606
|
destStatus === DaimoPayOrderStatusDest.CLAIM_SUCCESSFUL) {
|
|
9622
9607
|
const txHash = daimoPayOrder.destFastFinishTxHash ?? daimoPayOrder.destClaimTxHash;
|
|
9623
|
-
const
|
|
9608
|
+
const destChainId = getOrderDestChainId(daimoPayOrder);
|
|
9624
9609
|
assert(txHash != null, `[CONFIRMATION] dest status: ${destStatus}, but missing txHash`);
|
|
9625
|
-
const txURL = getChainExplorerTxUrl(
|
|
9626
|
-
paymentState.onSuccess({ txHash, txURL });
|
|
9610
|
+
const txURL = getChainExplorerTxUrl(destChainId, txHash);
|
|
9627
9611
|
return {
|
|
9628
9612
|
done: true,
|
|
9629
9613
|
txURL,
|
|
@@ -9634,7 +9618,12 @@ const Confirmation = () => {
|
|
|
9634
9618
|
done: false,
|
|
9635
9619
|
txURL: undefined,
|
|
9636
9620
|
};
|
|
9637
|
-
})
|
|
9621
|
+
}, [daimoPayOrder]);
|
|
9622
|
+
useEffect(() => {
|
|
9623
|
+
if (done) {
|
|
9624
|
+
onSuccess();
|
|
9625
|
+
}
|
|
9626
|
+
}, [done, onSuccess]);
|
|
9638
9627
|
return (jsx(PageContent, { style: {
|
|
9639
9628
|
display: "flex",
|
|
9640
9629
|
justifyContent: "center",
|
|
@@ -9678,8 +9667,6 @@ const Link = styled.a `
|
|
|
9678
9667
|
`;
|
|
9679
9668
|
const SuccessIcon = styled(TickIcon) `
|
|
9680
9669
|
color: var(--ck-body-color-valid);
|
|
9681
|
-
|
|
9682
|
-
transform: scale(0.5);
|
|
9683
9670
|
transition: all 0.2s ease-in-out;
|
|
9684
9671
|
position: absolute;
|
|
9685
9672
|
opacity: ${(props) => (props.$status ? 1 : 0)};
|
|
@@ -9690,7 +9677,6 @@ const Spinner$1 = styled(LoadingCircleIcon) `
|
|
|
9690
9677
|
transition: all 0.2s ease-in-out;
|
|
9691
9678
|
animation: rotateSpinner 400ms linear infinite;
|
|
9692
9679
|
opacity: ${(props) => (props.$status ? 0 : 1)};
|
|
9693
|
-
transform: ${(props) => (props.$status ? "scale(0.5)" : "scale(1)")};
|
|
9694
9680
|
|
|
9695
9681
|
@keyframes rotateSpinner {
|
|
9696
9682
|
0% {
|
|
@@ -11229,9 +11215,9 @@ const WaitingExternal = () => {
|
|
|
11229
11215
|
}, children: selectedExternalOption.cta })] }));
|
|
11230
11216
|
};
|
|
11231
11217
|
|
|
11232
|
-
const
|
|
11233
|
-
const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThemeDefault, lang = "en-US", }) => {
|
|
11218
|
+
const DaimoPayModal = ({ mode, theme, customTheme, lang, }) => {
|
|
11234
11219
|
const context = usePayContext();
|
|
11220
|
+
const { setMode, setTheme, setCustomTheme, setLang } = context;
|
|
11235
11221
|
const paymentState = context.paymentState;
|
|
11236
11222
|
const { payParams, generatePreviewOrder, isDepositFlow, showSolanaPaymentMethod, setPaymentWaitingMessage, setSelectedExternalOption, setSelectedTokenOption, setSelectedSolanaTokenOption, setSelectedDepositAddressOption, } = paymentState;
|
|
11237
11223
|
const { isConnected: isEthConnected, connector, chain, address, } = useAccount();
|
|
@@ -11387,12 +11373,16 @@ const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThem
|
|
|
11387
11373
|
}
|
|
11388
11374
|
// Don't include context.route in the dependency array otherwise the user
|
|
11389
11375
|
// can't go back from the select token screen to the select method screen
|
|
11376
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11390
11377
|
}, [
|
|
11391
11378
|
context.open,
|
|
11392
11379
|
context.wcWallet,
|
|
11393
11380
|
isEthConnected,
|
|
11394
11381
|
isSolanaConnected,
|
|
11395
11382
|
showSolanaPaymentMethod,
|
|
11383
|
+
address,
|
|
11384
|
+
chain?.id,
|
|
11385
|
+
connector?.id,
|
|
11396
11386
|
]);
|
|
11397
11387
|
// If we're on the connect page and the user successfully connects their
|
|
11398
11388
|
// wallet, go to the select token page
|
|
@@ -11409,11 +11399,12 @@ const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThem
|
|
|
11409
11399
|
});
|
|
11410
11400
|
}
|
|
11411
11401
|
}
|
|
11402
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11412
11403
|
}, [isEthConnected, context.route, connector?.id, chain?.id, address]);
|
|
11413
|
-
useEffect(() =>
|
|
11414
|
-
useEffect(() =>
|
|
11415
|
-
useEffect(() =>
|
|
11416
|
-
useEffect(() =>
|
|
11404
|
+
useEffect(() => setMode(mode), [mode, setMode]);
|
|
11405
|
+
useEffect(() => setTheme(theme), [theme, setTheme]);
|
|
11406
|
+
useEffect(() => setCustomTheme(customTheme), [customTheme, setCustomTheme]);
|
|
11407
|
+
useEffect(() => setLang(lang), [lang, setLang]);
|
|
11417
11408
|
/* When pulling data into WalletConnect, it prioritises the og:title tag over the title tag */
|
|
11418
11409
|
useEffect(() => {
|
|
11419
11410
|
const appName = getAppName();
|
|
@@ -11517,7 +11508,10 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11517
11508
|
onCloseRef.current = fn;
|
|
11518
11509
|
}, []);
|
|
11519
11510
|
const [open, setOpenState] = useState(false);
|
|
11511
|
+
const [lockPayParams, setLockPayParams] = useState(false);
|
|
11512
|
+
const [paymentCompleted, setPaymentCompleted] = useState(false);
|
|
11520
11513
|
const [route, setRouteState] = useState(ROUTES.SELECT_METHOD);
|
|
11514
|
+
const [modalOptions, setModalOptions] = useState();
|
|
11521
11515
|
// Daimo Pay context
|
|
11522
11516
|
const [daimoPayOrder, setDaimoPayOrderInner] = useState();
|
|
11523
11517
|
const [pendingConnectorId, setPendingConnectorId] = useState(undefined);
|
|
@@ -11528,22 +11522,46 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11528
11522
|
const [errorMessage, setErrorMessage] = useState("");
|
|
11529
11523
|
const [confirmationMessage, setConfirmationMessage] = useState(undefined);
|
|
11530
11524
|
const [redirectReturnUrl, setRedirectReturnUrl] = useState(undefined);
|
|
11531
|
-
const log = debugMode ? console.log : () => { };
|
|
11525
|
+
const log = useMemo(() => (debugMode ? console.log : () => { }), [debugMode]);
|
|
11532
11526
|
// Connect to the Daimo Pay TRPC API
|
|
11533
|
-
const trpc = useMemo(() => createTrpcClient(payApiUrl, sessionId), [payApiUrl]);
|
|
11527
|
+
const trpc = useMemo(() => createTrpcClient(payApiUrl, sessionId), [payApiUrl, sessionId]);
|
|
11534
11528
|
const [resize, onResize] = useState(0);
|
|
11535
11529
|
const setOpen = useCallback((open, meta) => {
|
|
11536
11530
|
setOpenState(open);
|
|
11531
|
+
// Lock pay params starting from the first time the modal is opened to
|
|
11532
|
+
// prevent the daimo pay order from changing from under the user
|
|
11533
|
+
if (open) {
|
|
11534
|
+
setLockPayParams(true);
|
|
11535
|
+
}
|
|
11536
|
+
// Reset payment state on close if resetOnSuccess is true
|
|
11537
|
+
if (!open && paymentCompleted && modalOptions?.resetOnSuccess) {
|
|
11538
|
+
setPaymentCompleted(false);
|
|
11539
|
+
setLockPayParams(false);
|
|
11540
|
+
paymentState.resetOrder();
|
|
11541
|
+
}
|
|
11542
|
+
// Log the open/close event
|
|
11537
11543
|
trpc.nav.mutate({
|
|
11538
11544
|
action: open ? "navOpenPay" : "navClosePay",
|
|
11539
11545
|
orderId: daimoPayOrder?.id?.toString(),
|
|
11540
11546
|
data: meta ?? {},
|
|
11541
11547
|
});
|
|
11548
|
+
// Run the onOpen and onClose callbacks
|
|
11542
11549
|
if (open)
|
|
11543
11550
|
onOpenRef.current?.();
|
|
11544
11551
|
else
|
|
11545
11552
|
onCloseRef.current?.();
|
|
11546
|
-
},
|
|
11553
|
+
},
|
|
11554
|
+
// We don't have good caching on paymentState, so don't include it as a dep
|
|
11555
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11556
|
+
[trpc, daimoPayOrder?.id, modalOptions?.resetOnSuccess, paymentCompleted]);
|
|
11557
|
+
// Callback when a payment is successfully completed (regardless of whether
|
|
11558
|
+
// the final call succeeded or bounced)
|
|
11559
|
+
const onSuccess = useCallback(() => {
|
|
11560
|
+
if (modalOptions?.closeOnSuccess) {
|
|
11561
|
+
setTimeout(() => setOpen(false, { event: "wait-success" }), 1000);
|
|
11562
|
+
}
|
|
11563
|
+
setPaymentCompleted(true);
|
|
11564
|
+
}, [modalOptions?.closeOnSuccess, setOpen, setPaymentCompleted]);
|
|
11547
11565
|
const setRoute = useCallback((route, data) => {
|
|
11548
11566
|
const action = route.replace("daimoPay", "");
|
|
11549
11567
|
log(`[SET ROUTE] ${action} ${daimoPayOrder?.id} ${debugJson(data ?? {})}`);
|
|
@@ -11554,23 +11572,11 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11554
11572
|
});
|
|
11555
11573
|
setRouteState(route);
|
|
11556
11574
|
}, [trpc, daimoPayOrder?.id, log]);
|
|
11557
|
-
// Include Google Font that is needed for a themes
|
|
11558
|
-
if (opts.embedGoogleFonts)
|
|
11559
|
-
useThemeFont(ckTheme);
|
|
11560
11575
|
// Other Configuration
|
|
11561
11576
|
useEffect(() => setTheme(theme), [theme]);
|
|
11562
11577
|
useEffect(() => setLang(opts.language || "en-US"), [opts.language]);
|
|
11563
11578
|
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]);
|
|
11579
|
+
const { connector } = useAccount();
|
|
11574
11580
|
// Single source of truth for the currently-connected wallet is the connector
|
|
11575
11581
|
// exposed by wagmi. See useAccount(). We watch this connector and use it to
|
|
11576
11582
|
// extract the current WalletConnect wallet, if any.
|
|
@@ -11593,9 +11599,10 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11593
11599
|
}, [log]);
|
|
11594
11600
|
const paymentState = usePaymentState({
|
|
11595
11601
|
trpc,
|
|
11602
|
+
lockPayParams,
|
|
11596
11603
|
daimoPayOrder,
|
|
11597
11604
|
setDaimoPayOrder,
|
|
11598
|
-
|
|
11605
|
+
setRoute,
|
|
11599
11606
|
log,
|
|
11600
11607
|
redirectReturnUrl,
|
|
11601
11608
|
});
|
|
@@ -11619,11 +11626,13 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11619
11626
|
log(`[PAY] polling in ${intervalMs}ms`);
|
|
11620
11627
|
const timeout = setTimeout(() => retryBackoff("refreshOrder", () => paymentState.refreshOrder()), intervalMs);
|
|
11621
11628
|
return () => clearTimeout(timeout);
|
|
11622
|
-
|
|
11629
|
+
// We don't have good caching on paymentState, so don't include it as a dep
|
|
11630
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11631
|
+
}, [daimoPayOrder, log]);
|
|
11623
11632
|
const showPayment = async (modalOptions) => {
|
|
11624
11633
|
const id = daimoPayOrder?.id;
|
|
11625
11634
|
log(`[PAY] showing payment ${debugJson({ id, modalOptions })}`);
|
|
11626
|
-
|
|
11635
|
+
setModalOptions(modalOptions);
|
|
11627
11636
|
setOpen(true);
|
|
11628
11637
|
if (daimoPayOrder &&
|
|
11629
11638
|
daimoPayOrder.mode === DaimoPayOrderMode.HYDRATED &&
|
|
@@ -11663,6 +11672,7 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11663
11672
|
// Other configuration
|
|
11664
11673
|
options: opts,
|
|
11665
11674
|
errorMessage,
|
|
11675
|
+
onSuccess,
|
|
11666
11676
|
confirmationMessage,
|
|
11667
11677
|
setConfirmationMessage,
|
|
11668
11678
|
redirectReturnUrl,
|
|
@@ -11946,6 +11956,7 @@ function DaimoPayButtonCustom(props) {
|
|
|
11946
11956
|
else if (payParams != null) {
|
|
11947
11957
|
paymentState.setPayParams(payParams);
|
|
11948
11958
|
}
|
|
11959
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11949
11960
|
}, [payId, JSON.stringify(payParams || {})]);
|
|
11950
11961
|
// Set the confirmation message
|
|
11951
11962
|
const { setConfirmationMessage } = context;
|
|
@@ -11977,14 +11988,14 @@ function DaimoPayButtonCustom(props) {
|
|
|
11977
11988
|
const intentStatus = order?.intentStatus;
|
|
11978
11989
|
const hydOrder = order?.mode === DaimoPayOrderMode.HYDRATED ? order : null;
|
|
11979
11990
|
// Functions to show and hide the modal
|
|
11980
|
-
const { children, closeOnSuccess } = props;
|
|
11981
|
-
const
|
|
11982
|
-
const show = () => {
|
|
11991
|
+
const { children, closeOnSuccess, resetOnSuccess } = props;
|
|
11992
|
+
const show = useCallback(() => {
|
|
11983
11993
|
if (paymentState.daimoPayOrder == null)
|
|
11984
11994
|
return;
|
|
11995
|
+
const modalOptions = { closeOnSuccess, resetOnSuccess };
|
|
11985
11996
|
context.showPayment(modalOptions);
|
|
11986
|
-
};
|
|
11987
|
-
const hide = () => context.setOpen(false);
|
|
11997
|
+
}, [context, paymentState.daimoPayOrder, closeOnSuccess, resetOnSuccess]);
|
|
11998
|
+
const hide = useCallback(() => context.setOpen(false), [context]);
|
|
11988
11999
|
// Emit event handlers when payment status changes
|
|
11989
12000
|
const sentStart = useRef(false);
|
|
11990
12001
|
useEffect(() => {
|
|
@@ -12079,12 +12090,11 @@ function DaimoPayButtonInner({ disabled }) {
|
|
|
12079
12090
|
*/
|
|
12080
12091
|
function useDaimoPayStatus() {
|
|
12081
12092
|
const { paymentState } = usePayContext();
|
|
12082
|
-
const reset = paymentState.resetOrder;
|
|
12083
12093
|
if (!paymentState || !paymentState.daimoPayOrder)
|
|
12084
|
-
return
|
|
12094
|
+
return undefined;
|
|
12085
12095
|
const order = paymentState.daimoPayOrder;
|
|
12086
12096
|
const paymentId = writeDaimoPayOrderID(order.id);
|
|
12087
|
-
return { paymentId, status: order.intentStatus
|
|
12097
|
+
return { paymentId, status: order.intentStatus };
|
|
12088
12098
|
}
|
|
12089
12099
|
|
|
12090
12100
|
function addressToNumber(address) {
|