@daimo/pay 1.7.2 → 1.7.4
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 +33 -13
- package/build/index.js +204 -110
- package/build/index.js.map +1 -1
- package/package.json +3 -3
package/build/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { ExternalPaymentOptions, assert, assertNotNull, debugJson, supportedChains, ethereum, 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';
|
|
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
4
|
import React, { useState, useEffect, createContext, useCallback, useRef, useLayoutEffect, useMemo, createElement } from 'react';
|
|
5
5
|
import styled$1, { css, keyframes, ThemeProvider } from 'styled-components';
|
|
@@ -7,7 +7,7 @@ import { http, useConfig, useAccountEffect, useWriteContract, useSendTransaction
|
|
|
7
7
|
import { mainnet, base as base$1, polygon, optimism, arbitrum, linea, bsc, sepolia, baseSepolia, worldchain, blast, mantle } from 'wagmi/chains';
|
|
8
8
|
import { safe, injected, coinbaseWallet, walletConnect } from '@wagmi/connectors';
|
|
9
9
|
import { useConnection, useWallet as useWallet$1, ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
|
|
10
|
-
import { hexToBytes, zeroAddress, erc20Abi, getAddress,
|
|
10
|
+
import { hexToBytes, zeroAddress, erc20Abi, getAddress, formatUnits, parseUnits } from 'viem';
|
|
11
11
|
import { VersionedTransaction } from '@solana/web3.js';
|
|
12
12
|
import { createTRPCClient, httpBatchLink } from '@trpc/client';
|
|
13
13
|
import { motion, AnimatePresence, MotionConfig } from 'framer-motion';
|
|
@@ -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.4";
|
|
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.4",
|
|
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",
|
|
@@ -377,7 +377,7 @@ const OtherWallets = ({ ...props }) => {
|
|
|
377
377
|
overflow: "hidden",
|
|
378
378
|
borderRadius: "27.5%",
|
|
379
379
|
};
|
|
380
|
-
return (jsxs("div", { style: column, ...props, children: [jsxs("div", { style: row, children: [jsx("div", { style: cell, children: jsx(
|
|
380
|
+
return (jsxs("div", { style: column, ...props, children: [jsxs("div", { style: row, children: [jsx("div", { style: cell, children: jsx(Zerion, {}) }), jsx("div", { style: cell, children: jsx(WalletConnect, { background: true }) })] }), jsxs("div", { style: row, children: [jsx("div", { style: cell, children: jsx(Family, {}) }), jsx("div", { style: cell, children: jsx(Ledger, {}) })] })] }));
|
|
381
381
|
};
|
|
382
382
|
const Fordefi = ({ ...props }) => (jsxs("svg", { ...props, width: "88", height: "88", viewBox: "0 0 96 96", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxs("g", { clipPath: "url(#clip0_14298_75627)", children: [jsx("path", { d: "M43.5075 62.5508H6V73.5954C6 79.2046 10.5379 83.7515 16.1357 83.7515H32.9997L43.5075 62.5508Z", fill: "#7994FF" }), jsx("path", { d: "M6.00098 39.1016H76.2075L68.0567 55.4841H6.00098V39.1016Z", fill: "#486DFF" }), jsx("path", { d: "M30.6398 12H6.09766V32.0282H89.8447V12H65.3025V26.9577H60.2423V12H35.7001V26.9577H30.6398V12Z", fill: "#5CD1FA" })] }), jsx("defs", { children: jsx("clipPath", { id: "clip0_14298_75627", children: jsx("rect", { width: "84", height: "72", fill: "white", transform: "translate(6 12)" }) }) })] }));
|
|
383
383
|
const SquircleIcon = ({ icon, alt, }) => {
|
|
@@ -580,11 +580,12 @@ const walletConfigs = {
|
|
|
580
580
|
edge: "https://rainbow.me/extension?utm_source=daimopay",
|
|
581
581
|
brave: "https://rainbow.me/extension?utm_source=daimopay",
|
|
582
582
|
},
|
|
583
|
-
showInMobileConnectors:
|
|
583
|
+
showInMobileConnectors: false,
|
|
584
584
|
isWcMobileConnector: false,
|
|
585
585
|
getWalletConnectDeeplink: (uri) => {
|
|
586
|
-
return `
|
|
586
|
+
return `rainbow://wc?uri=${encodeURIComponent(uri)}&connector=daimopay`;
|
|
587
587
|
},
|
|
588
|
+
walletDeepLink: "rainbow://",
|
|
588
589
|
},
|
|
589
590
|
"io.rabby": {
|
|
590
591
|
name: "Rabby Wallet",
|
|
@@ -732,7 +733,7 @@ const walletConfigs = {
|
|
|
732
733
|
getWalletConnectDeeplink: (uri) => {
|
|
733
734
|
return `https://app.zerion.io/wc?uri=${encodeURIComponent(uri)}`;
|
|
734
735
|
},
|
|
735
|
-
showInMobileConnectors:
|
|
736
|
+
showInMobileConnectors: true,
|
|
736
737
|
},
|
|
737
738
|
slope: {
|
|
738
739
|
name: "Slope",
|
|
@@ -838,7 +839,7 @@ function extractWcWalletFromProvider(p, log) {
|
|
|
838
839
|
isWcMobileConnector: true,
|
|
839
840
|
};
|
|
840
841
|
}
|
|
841
|
-
log(`[WCWALLET] name: ${name} wcWallet: ${wallet?.name} isWcMobileConnector: ${wallet?.isWcMobileConnector} provider:
|
|
842
|
+
log(`[WCWALLET] name: ${name} wcWallet: ${wallet?.name} isWcMobileConnector: ${wallet?.isWcMobileConnector} provider: `, p);
|
|
842
843
|
return wallet;
|
|
843
844
|
}
|
|
844
845
|
|
|
@@ -997,7 +998,7 @@ function useOrderUsdLimits({ trpc }) {
|
|
|
997
998
|
return { limits, loading };
|
|
998
999
|
}
|
|
999
1000
|
|
|
1000
|
-
function usePayWithSolanaToken({ trpc, daimoPayOrder, setDaimoPayOrder, createOrHydrate, log, }) {
|
|
1001
|
+
function usePayWithSolanaToken({ trpc, refundAddress, daimoPayOrder, setDaimoPayOrder, createOrHydrate, log, }) {
|
|
1001
1002
|
const { connection } = useConnection();
|
|
1002
1003
|
const wallet = useWallet$1();
|
|
1003
1004
|
const payWithSolanaToken = async (inputToken) => {
|
|
@@ -1006,6 +1007,7 @@ function usePayWithSolanaToken({ trpc, daimoPayOrder, setDaimoPayOrder, createOr
|
|
|
1006
1007
|
const orderId = daimoPayOrder.id;
|
|
1007
1008
|
const { hydratedOrder } = await createOrHydrate({
|
|
1008
1009
|
order: daimoPayOrder,
|
|
1010
|
+
refundAddress,
|
|
1009
1011
|
});
|
|
1010
1012
|
log(`[CHECKOUT] Hydrated order: ${JSON.stringify(hydratedOrder)}, checking out with Solana ${inputToken}`);
|
|
1011
1013
|
const txHash = await (async () => {
|
|
@@ -1040,7 +1042,7 @@ function usePayWithSolanaToken({ trpc, daimoPayOrder, setDaimoPayOrder, createOr
|
|
|
1040
1042
|
return { payWithSolanaToken };
|
|
1041
1043
|
}
|
|
1042
1044
|
|
|
1043
|
-
function usePayWithToken({ trpc, senderAddr, daimoPayOrder, setDaimoPayOrder, createOrHydrate, log, }) {
|
|
1045
|
+
function usePayWithToken({ trpc, senderAddr, refundAddress, daimoPayOrder, setDaimoPayOrder, createOrHydrate, log, }) {
|
|
1044
1046
|
const { writeContractAsync } = useWriteContract();
|
|
1045
1047
|
const { sendTransactionAsync } = useSendTransaction();
|
|
1046
1048
|
/** Commit to a token + amount = initiate payment. */
|
|
@@ -1051,7 +1053,8 @@ function usePayWithToken({ trpc, senderAddr, daimoPayOrder, setDaimoPayOrder, cr
|
|
|
1051
1053
|
const paymentAmount = BigInt(required.amount) + BigInt(fees.amount);
|
|
1052
1054
|
const { hydratedOrder } = await createOrHydrate({
|
|
1053
1055
|
order: daimoPayOrder,
|
|
1054
|
-
|
|
1056
|
+
// Use the developer-provided refund address. Default to the sender.
|
|
1057
|
+
refundAddress: refundAddress ?? senderAddr,
|
|
1055
1058
|
});
|
|
1056
1059
|
log(`[PAY TOKEN] hydrated order: ${JSON.stringify(hydratedOrder)}, paying ${paymentAmount} of token ${required.token.token}`);
|
|
1057
1060
|
setDaimoPayOrder(hydratedOrder);
|
|
@@ -1187,6 +1190,14 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1187
1190
|
// Solana wallet state.
|
|
1188
1191
|
const solanaWallet = useWallet$1();
|
|
1189
1192
|
const solanaPubKey = solanaWallet.publicKey?.toBase58();
|
|
1193
|
+
// TODO: backend should determine whether to show solana payment method
|
|
1194
|
+
const paymentOptions = daimoPayOrder?.metadata.payer?.paymentOptions;
|
|
1195
|
+
// Include by default if paymentOptions not provided. Solana bridging is only
|
|
1196
|
+
// supported on CCTP v1 chains.
|
|
1197
|
+
const showSolanaPaymentMethod = (paymentOptions == null ||
|
|
1198
|
+
paymentOptions.includes(ExternalPaymentOptions.Solana)) &&
|
|
1199
|
+
daimoPayOrder != null &&
|
|
1200
|
+
isCCTPV1Chain(getOrderDestChainId(daimoPayOrder));
|
|
1190
1201
|
// Daimo Pay order state.
|
|
1191
1202
|
const [payParams, setPayParamsState] = useState();
|
|
1192
1203
|
const [paymentWaitingMessage, setPaymentWaitingMessage] = useState();
|
|
@@ -1260,6 +1271,7 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1260
1271
|
const { payWithToken } = usePayWithToken({
|
|
1261
1272
|
trpc,
|
|
1262
1273
|
senderAddr,
|
|
1274
|
+
refundAddress: payParams?.refundAddress,
|
|
1263
1275
|
daimoPayOrder,
|
|
1264
1276
|
setDaimoPayOrder,
|
|
1265
1277
|
createOrHydrate,
|
|
@@ -1267,6 +1279,7 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1267
1279
|
});
|
|
1268
1280
|
const { payWithSolanaToken } = usePayWithSolanaToken({
|
|
1269
1281
|
trpc,
|
|
1282
|
+
refundAddress: payParams?.refundAddress,
|
|
1270
1283
|
daimoPayOrder,
|
|
1271
1284
|
setDaimoPayOrder,
|
|
1272
1285
|
createOrHydrate,
|
|
@@ -1333,11 +1346,11 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1333
1346
|
const setChosenUsd = (usd) => {
|
|
1334
1347
|
assert(!!daimoPayOrder, "[SET CHOSEN USD] daimoPayOrder cannot be null");
|
|
1335
1348
|
const token = daimoPayOrder.destFinalCallTokenAmount.token;
|
|
1336
|
-
const tokenUnits = (usd / token.
|
|
1349
|
+
const tokenUnits = (usd / token.priceFromUsd).toString();
|
|
1337
1350
|
const tokenAmount = parseUnits(tokenUnits, token.decimals);
|
|
1338
1351
|
// TODO: remove amount from destFinalCall, it is redundant with
|
|
1339
1352
|
// destFinalCallTokenAmount. Here, we only modify one and not the other.
|
|
1340
|
-
log(`[CHECKOUT]
|
|
1353
|
+
log(`[CHECKOUT] chose USD amount $${usd} = ${tokenUnits} ${token.symbol}`);
|
|
1341
1354
|
setDaimoPayOrder({
|
|
1342
1355
|
...daimoPayOrder,
|
|
1343
1356
|
destFinalCallTokenAmount: {
|
|
@@ -1394,6 +1407,7 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1394
1407
|
},
|
|
1395
1408
|
externalId: payParams.externalId,
|
|
1396
1409
|
userMetadata: payParams.metadata,
|
|
1410
|
+
refundAddress: payParams.refundAddress,
|
|
1397
1411
|
});
|
|
1398
1412
|
log(`[CHECKOUT] generated preview: ${JSON.stringify(orderPreview)}`);
|
|
1399
1413
|
setDaimoPayOrder(orderPreview);
|
|
@@ -1404,6 +1418,9 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1404
1418
|
setTimeout(() => setOpen(false, { event: "wait-success" }), 1000);
|
|
1405
1419
|
}
|
|
1406
1420
|
};
|
|
1421
|
+
const resetOrder = () => {
|
|
1422
|
+
setDaimoPayOrder(undefined);
|
|
1423
|
+
};
|
|
1407
1424
|
return {
|
|
1408
1425
|
setPayId,
|
|
1409
1426
|
payParams,
|
|
@@ -1418,11 +1435,13 @@ function usePaymentState({ trpc, daimoPayOrder, setDaimoPayOrder, setOpen, log,
|
|
|
1418
1435
|
selectedTokenOption,
|
|
1419
1436
|
selectedSolanaTokenOption,
|
|
1420
1437
|
externalPaymentOptions,
|
|
1438
|
+
showSolanaPaymentMethod,
|
|
1421
1439
|
walletPaymentOptions,
|
|
1422
1440
|
solanaPaymentOptions,
|
|
1423
1441
|
depositAddressOptions,
|
|
1424
1442
|
selectedDepositAddressOption,
|
|
1425
1443
|
getOrderUsdLimit,
|
|
1444
|
+
resetOrder,
|
|
1426
1445
|
setPaymentWaitingMessage,
|
|
1427
1446
|
setSelectedExternalOption,
|
|
1428
1447
|
setSelectedTokenOption,
|
|
@@ -4882,9 +4901,39 @@ const useWallet = (id) => {
|
|
|
4882
4901
|
return null;
|
|
4883
4902
|
return wallet;
|
|
4884
4903
|
};
|
|
4885
|
-
const useWallets = () => {
|
|
4904
|
+
const useWallets = (isMobile) => {
|
|
4886
4905
|
const connectors = useConnectors();
|
|
4887
4906
|
const context = usePayContext();
|
|
4907
|
+
if (isMobile) {
|
|
4908
|
+
const mobileWallets = [];
|
|
4909
|
+
// Add Rainbow first
|
|
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
|
|
4924
|
+
connectors.forEach((connector) => {
|
|
4925
|
+
if (connector.id === "metaMask")
|
|
4926
|
+
return;
|
|
4927
|
+
if (isCoinbaseWalletConnector(connector.id))
|
|
4928
|
+
return;
|
|
4929
|
+
mobileWallets.push({
|
|
4930
|
+
id: connector.id,
|
|
4931
|
+
connector,
|
|
4932
|
+
...walletConfigs[connector.id],
|
|
4933
|
+
});
|
|
4934
|
+
});
|
|
4935
|
+
return mobileWallets;
|
|
4936
|
+
}
|
|
4888
4937
|
const wallets = connectors.map((connector) => {
|
|
4889
4938
|
// use overrides
|
|
4890
4939
|
const walletId = Object.keys(walletConfigs).find(
|
|
@@ -4939,8 +4988,8 @@ const useWallets = () => {
|
|
|
4939
4988
|
self.find((w) => w.id === "farcaster")))
|
|
4940
4989
|
// order by isInstalled injected connectors first
|
|
4941
4990
|
.sort((a, b) => {
|
|
4942
|
-
const AisInstalled = a.isInstalled && isInjectedConnector(a.connector
|
|
4943
|
-
const BisInstalled = b.isInstalled && isInjectedConnector(b.connector
|
|
4991
|
+
const AisInstalled = a.isInstalled && isInjectedConnector(a.connector?.type);
|
|
4992
|
+
const BisInstalled = b.isInstalled && isInjectedConnector(b.connector?.type);
|
|
4944
4993
|
if (AisInstalled && !BisInstalled)
|
|
4945
4994
|
return -1;
|
|
4946
4995
|
if (!AisInstalled && BisInstalled)
|
|
@@ -7241,15 +7290,15 @@ const ConnectorsContainer = styled.div `
|
|
|
7241
7290
|
const ConnectorList = () => {
|
|
7242
7291
|
const context = usePayContext();
|
|
7243
7292
|
const { isMobile } = useIsMobile();
|
|
7244
|
-
const wallets = useWallets();
|
|
7293
|
+
const wallets = useWallets(isMobile);
|
|
7245
7294
|
const { lastConnectorId } = useLastConnector();
|
|
7246
7295
|
const walletsToDisplay = context.options?.hideRecentBadge || lastConnectorId === "walletConnect" // do not hoist walletconnect to top of list
|
|
7247
7296
|
? wallets
|
|
7248
7297
|
: [
|
|
7249
7298
|
// move last used wallet to top of list
|
|
7250
7299
|
// using .filter and spread to avoid mutating original array order with .sort
|
|
7251
|
-
...wallets.filter((wallet) => lastConnectorId === wallet.connector
|
|
7252
|
-
...wallets.filter((wallet) => lastConnectorId !== wallet.connector
|
|
7300
|
+
...wallets.filter((wallet) => lastConnectorId === wallet.connector?.id),
|
|
7301
|
+
...wallets.filter((wallet) => lastConnectorId !== wallet.connector?.id),
|
|
7253
7302
|
];
|
|
7254
7303
|
return (jsxs(ScrollArea, { mobileDirection: "horizontal", children: [walletsToDisplay.length === 0 && (jsx(Alert, { error: true, children: "No connectors found in ConnectKit config." })), walletsToDisplay.length > 0 && (jsx(ConnectorsContainer, { "$mobile": isMobile, "$totalResults": walletsToDisplay.length, children: walletsToDisplay.map((wallet) => (jsx(ConnectorItem, { wallet: wallet, isRecent: wallet.id === lastConnectorId }, wallet.id))) }))] }));
|
|
7255
7304
|
};
|
|
@@ -7266,7 +7315,7 @@ const ConnectorItem = ({ wallet, isRecent, }) => {
|
|
|
7266
7315
|
const redirectToMoreWallets = isMobile && isWalletConnectConnector(wallet.id);
|
|
7267
7316
|
// Safari requires opening popup on user gesture, so we connect immediately here
|
|
7268
7317
|
const shouldConnectImmediately = (detectBrowser() === "safari" || detectBrowser() === "ios") &&
|
|
7269
|
-
isCoinbaseWalletConnector(wallet.connector
|
|
7318
|
+
isCoinbaseWalletConnector(wallet.connector?.id);
|
|
7270
7319
|
if (redirectToMoreWallets || shouldConnectImmediately)
|
|
7271
7320
|
deeplink = undefined; // mobile redirects to more wallets page
|
|
7272
7321
|
return (jsxs(ConnectorButton, { type: "button", as: deeplink ? "a" : undefined, href: deeplink ? deeplink : undefined, disabled: context.route !== ROUTES.CONNECTORS, onClick: deeplink
|
|
@@ -8220,7 +8269,7 @@ const MobileConnectors = () => {
|
|
|
8220
8269
|
// filter out installed wallets
|
|
8221
8270
|
const walletsIdsToDisplay = Object.keys(walletConfigs).filter((walletId) => {
|
|
8222
8271
|
const wallet = walletConfigs[walletId];
|
|
8223
|
-
if (wallets.find((w) => w.connector
|
|
8272
|
+
if (wallets.find((w) => w.connector?.id === walletId))
|
|
8224
8273
|
return false;
|
|
8225
8274
|
if (!wallet.getWalletConnectDeeplink)
|
|
8226
8275
|
return false;
|
|
@@ -9352,7 +9401,7 @@ const ConnectWithInjector = ({ switchConnectMethod, forceState }) => {
|
|
|
9352
9401
|
return (jsx(PageContent, { children: jsxs(Container$4, { children: [jsx(ModalHeading, { children: "Invalid State" }), jsx(ModalContent, { children: jsx(Alert, { children: "No connectors match the id given. This state should never happen." }) })] }) }));
|
|
9353
9402
|
}
|
|
9354
9403
|
// TODO: Make this more generic
|
|
9355
|
-
if (isWalletConnectConnector(wallet?.connector
|
|
9404
|
+
if (isWalletConnectConnector(wallet?.connector?.id)) {
|
|
9356
9405
|
return (jsx(PageContent, { children: jsxs(Container$4, { children: [jsx(ModalHeading, { children: "Invalid State" }), jsx(ModalContent, { children: jsx(Alert, { children: "WalletConnect does not have an injection flow. This state should never happen." }) })] }) }));
|
|
9357
9406
|
}
|
|
9358
9407
|
return (jsx(PageContent, { children: jsxs(Container$4, { children: [jsx(ConnectingContainer, { children: jsxs(ConnectingAnimation, { "$shake": status === states$1.FAILED || status === states$1.REJECTED, "$circle": walletInfo.iconShape === "circle", children: [jsx(AnimatePresence, { children: (status === states$1.FAILED || status === states$1.REJECTED) && (jsx(RetryButton, { "aria-label": "Retry", initial: { opacity: 0, scale: 0.8 }, animate: { opacity: 1, scale: 1 }, exit: { opacity: 0, scale: 0.8 }, whileTap: { scale: 0.9 }, transition: { duration: 0.1 }, onClick: runConnect, children: jsx(RetryIconContainer, { children: jsx(Tooltip, { open: showTryAgainTooltip &&
|
|
@@ -9364,9 +9413,9 @@ const ConnectWithInjector = ({ switchConnectMethod, forceState }) => {
|
|
|
9364
9413
|
transform: "scale(1.14)",
|
|
9365
9414
|
position: "relative",
|
|
9366
9415
|
width: "100%",
|
|
9367
|
-
}, children: walletInfo.icon })) : (jsx(Fragment, { children: walletInfo.icon })), loading: status === states$1.CONNECTING }))] }) }), jsx(ModalContentContainer, { children: jsxs(AnimatePresence, { initial: false, children: [status === states$1.FAILED && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants$1, children: jsxs(ModalContent, { children: [jsxs(ModalH1, { "$error": true, children: [jsx(AlertIcon, {}), locales.injectionScreen_failed_h1] }), jsx(ModalBody, { children: locales.injectionScreen_failed_p })] }) }, states$1.FAILED)), status === states$1.REJECTED && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants$1, children: jsxs(ModalContent, { style: { paddingBottom: 28 }, children: [jsx(ModalH1, { children: locales.injectionScreen_rejected_h1 }), jsx(ModalBody, { children: locales.injectionScreen_rejected_p })] }) }, states$1.REJECTED)), (status === states$1.CONNECTING || status === states$1.EXPIRING) && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants$1, children: jsxs(ModalContent, { style: { paddingBottom: 28 }, children: [jsx(ModalH1, { children: wallet.connector
|
|
9416
|
+
}, children: walletInfo.icon })) : (jsx(Fragment, { children: walletInfo.icon })), loading: status === states$1.CONNECTING }))] }) }), jsx(ModalContentContainer, { children: jsxs(AnimatePresence, { initial: false, children: [status === states$1.FAILED && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants$1, children: jsxs(ModalContent, { children: [jsxs(ModalH1, { "$error": true, children: [jsx(AlertIcon, {}), locales.injectionScreen_failed_h1] }), jsx(ModalBody, { children: locales.injectionScreen_failed_p })] }) }, states$1.FAILED)), status === states$1.REJECTED && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants$1, children: jsxs(ModalContent, { style: { paddingBottom: 28 }, children: [jsx(ModalH1, { children: locales.injectionScreen_rejected_h1 }), jsx(ModalBody, { children: locales.injectionScreen_rejected_p })] }) }, states$1.REJECTED)), (status === states$1.CONNECTING || status === states$1.EXPIRING) && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants$1, children: jsxs(ModalContent, { style: { paddingBottom: 28 }, children: [jsx(ModalH1, { children: wallet.connector?.id === "injected"
|
|
9368
9417
|
? locales.injectionScreen_connecting_injected_h1
|
|
9369
|
-
: locales.injectionScreen_connecting_h1 }), jsx(ModalBody, { children: wallet.connector
|
|
9418
|
+
: locales.injectionScreen_connecting_h1 }), jsx(ModalBody, { children: wallet.connector?.id === "injected"
|
|
9370
9419
|
? locales.injectionScreen_connecting_injected_p
|
|
9371
9420
|
: locales.injectionScreen_connecting_p }), jsxs(Button, { icon: jsx(ExternalLinkIcon, {}), onClick: runConnect, children: ["Connect ", walletInfo.name] })] }) }, states$1.CONNECTING)), status === states$1.CONNECTED && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants$1, children: jsxs(ModalContent, { children: [jsxs(ModalH1, { "$valid": true, children: [jsx(TickIcon, {}), " ", locales.injectionScreen_connected_h1] }), jsx(ModalBody, { children: locales.injectionScreen_connected_p })] }) }, states$1.CONNECTED)), status === states$1.NOTCONNECTED && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants$1, children: jsxs(ModalContent, { children: [jsx(ModalH1, { children: locales.injectionScreen_notconnected_h1 }), jsx(ModalBody, { children: locales.injectionScreen_notconnected_p })] }) }, states$1.NOTCONNECTED)), status === states$1.UNAVAILABLE && (jsx(Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants$1, 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$1.UNAVAILABLE))] }) })] }) }));
|
|
9372
9421
|
};
|
|
@@ -9454,7 +9503,7 @@ const ConnectUsing = () => {
|
|
|
9454
9503
|
useEffect(() => {
|
|
9455
9504
|
// if no provider, change to qrcode
|
|
9456
9505
|
const checkProvider = async () => {
|
|
9457
|
-
const res = await wallet?.connector
|
|
9506
|
+
const res = await wallet?.connector?.getProvider();
|
|
9458
9507
|
if (!res) {
|
|
9459
9508
|
setStatus(states.QRCODE);
|
|
9460
9509
|
setTimeout(context.triggerResize, 10); // delay required here for modal to resize
|
|
@@ -9756,8 +9805,8 @@ const ChainLogoContainer = styled(motion.div) `
|
|
|
9756
9805
|
}
|
|
9757
9806
|
`;
|
|
9758
9807
|
|
|
9759
|
-
const TokenLogoSpinner = ({ token
|
|
9760
|
-
return (jsx(LoadingContainer$2, { children: jsx(AnimationContainer$1, { "$circle": true, children: jsxs(AnimatePresence, { children: [chainToLogo[token.chainId] && (jsx(ChainLogoContainer, { children: chainToLogo[token.chainId] }, "ChainLogoContainer")), jsx(CircleSpinner, { logo: jsx("img", { src: token.logoURI, alt: token.symbol }
|
|
9808
|
+
const TokenLogoSpinner = ({ token }) => {
|
|
9809
|
+
return (jsx(LoadingContainer$2, { children: jsx(AnimationContainer$1, { "$circle": true, children: jsxs(AnimatePresence, { children: [chainToLogo[token.chainId] && (jsx(ChainLogoContainer, { children: chainToLogo[token.chainId] }, "ChainLogoContainer")), jsx(CircleSpinner, { logo: jsx("img", { src: token.logoURI, alt: token.symbol }), loading: false, unavailable: false }, "CircleSpinner")] }) }) }));
|
|
9761
9810
|
};
|
|
9762
9811
|
|
|
9763
9812
|
var PayState$1;
|
|
@@ -9864,12 +9913,12 @@ const PayWithToken = () => {
|
|
|
9864
9913
|
if (selectedTokenOption == null) {
|
|
9865
9914
|
return jsx(PageContent, {});
|
|
9866
9915
|
}
|
|
9867
|
-
return (jsxs(PageContent, { children: [jsx(TokenLogoSpinner, { token: selectedTokenOption.required.token }), jsxs(ModalContent, { style: { paddingBottom: 0 }, "$preserveDisplay": true, children: [jsx(ModalH1, { children: payState }), jsx(PaymentBreakdown, { paymentOption: selectedTokenOption }), payState === PayState$1.RequestingPayment && wcWallet && isMobile && (
|
|
9916
|
+
return (jsxs(PageContent, { children: [jsx(TokenLogoSpinner, { token: selectedTokenOption.required.token }), jsxs(ModalContent, { style: { paddingBottom: 0 }, "$preserveDisplay": true, children: [jsx(ModalH1, { children: payState }), jsx(PaymentBreakdown, { paymentOption: selectedTokenOption }), payState === PayState$1.RequestingPayment && wcWallet && isMobile && (jsx(Button, { icon: jsx(ExternalLinkIcon, {}), onClick: wcWallet.isWcMobileConnector
|
|
9868
9917
|
? () => handleTransfer(selectedTokenOption)
|
|
9869
9918
|
: undefined, href: wcWallet.isWcMobileConnector
|
|
9870
9919
|
? undefined
|
|
9871
9920
|
: wcWallet.walletDeepLink ||
|
|
9872
|
-
wcWallet.getWalletConnectDeeplink?.(""), children:
|
|
9921
|
+
wcWallet.getWalletConnectDeeplink?.(""), children: "Tap Here to Pay" })), payState === PayState$1.RequestCancelled && (jsx(Button, { onClick: () => handleTransfer(selectedTokenOption), children: "Retry Payment" }))] })] }));
|
|
9873
9922
|
};
|
|
9874
9923
|
|
|
9875
9924
|
/**
|
|
@@ -10082,7 +10131,7 @@ const MultiCurrencySelectAmount = ({ selectedTokenOption, setSelectedTokenOption
|
|
|
10082
10131
|
tokenSymbol: balanceToken.symbol,
|
|
10083
10132
|
});
|
|
10084
10133
|
};
|
|
10085
|
-
return (jsxs(PageContent, { children: [jsx(TokenLogoSpinner, { token: balanceToken
|
|
10134
|
+
return (jsxs(PageContent, { children: [jsx(TokenLogoSpinner, { token: balanceToken }), jsxs(ModalContent, { "$preserveDisplay": true, children: [jsxs(AmountInputContainer$2, { children: [jsx(MaxButton, { style: { visibility: "hidden" }, children: "Max" }), jsx(AmountInputField, { value: isEditingUsd ? usdValue : tokenValue, onChange: handleAmountChange, currency: isEditingUsd ? "$" : balanceToken.symbol, onKeyDown: handleKeyDown }), jsx(MaxButton, { onClick: handleMax, children: "Max" })] }), balanceToken.fiatISO !== "USD" && (jsx(SwitchContainer, { children: jsx(SwitchButton, { onClick: handleSwitchCurrency, children: jsx(SecondaryAmount, { children: isEditingUsd
|
|
10086
10135
|
? `${tokenValue} ${balanceToken.symbol}`
|
|
10087
10136
|
: `$${usdValue}` }) }) })), message && jsx(ModalBody, { children: message }), jsx(Button, { onClick: handleContinue, disabled: continueDisabled, children: "Continue" })] })] }));
|
|
10088
10137
|
};
|
|
@@ -10130,13 +10179,13 @@ const SelectAmount = () => {
|
|
|
10130
10179
|
return (jsx(MultiCurrencySelectAmount, { selectedTokenOption: selectedTokenOption, setSelectedTokenOption: setSelectedTokenOption, nextPage: ROUTES.PAY_WITH_TOKEN }));
|
|
10131
10180
|
};
|
|
10132
10181
|
|
|
10133
|
-
const ExternalPaymentSpinner = ({ logoURI, logoShape,
|
|
10182
|
+
const ExternalPaymentSpinner = ({ logoURI, logoShape, }) => {
|
|
10134
10183
|
const optionSpinner = (() => {
|
|
10135
10184
|
if (logoShape === "circle") {
|
|
10136
|
-
return (jsx(CircleSpinner, { logo: jsx("img", { src: logoURI }), loading:
|
|
10185
|
+
return (jsx(CircleSpinner, { logo: jsx("img", { src: logoURI }), loading: false, unavailable: false }));
|
|
10137
10186
|
}
|
|
10138
10187
|
else {
|
|
10139
|
-
return
|
|
10188
|
+
return jsx(SquircleSpinner, { logo: jsx("img", { src: logoURI }), loading: false });
|
|
10140
10189
|
}
|
|
10141
10190
|
})();
|
|
10142
10191
|
return (jsx(LoadingContainer$2, { children: jsx(AnimationContainer$1, { "$circle": logoShape === "circle", children: jsx(AnimatePresence, { children: optionSpinner }) }) }));
|
|
@@ -10182,7 +10231,7 @@ const SelectDepositAddressAmount = () => {
|
|
|
10182
10231
|
paymentState.setChosenUsd(amountUsd);
|
|
10183
10232
|
setRoute(ROUTES.WAITING_DEPOSIT_ADDRESS, { amountUsd });
|
|
10184
10233
|
};
|
|
10185
|
-
return (jsxs(PageContent, { children: [jsx(ExternalPaymentSpinner, { logoURI: selectedDepositAddressOption.logoURI, logoShape: "circle"
|
|
10234
|
+
return (jsxs(PageContent, { children: [jsx(ExternalPaymentSpinner, { logoURI: selectedDepositAddressOption.logoURI, logoShape: "circle" }), jsxs(ModalContent, { "$preserveDisplay": true, children: [jsx(AmountInputContainer$1, { children: jsx(AmountInputField, { value: usdInput, onChange: handleAmountChange, onKeyDown: handleKeyDown }) }), message && jsx(ModalBody, { children: message }), jsx(Button, { onClick: handleContinue, disabled: continueDisabled, children: "Continue" })] })] }));
|
|
10186
10235
|
};
|
|
10187
10236
|
const AmountInputContainer$1 = styled.div `
|
|
10188
10237
|
display: flex;
|
|
@@ -10444,7 +10493,7 @@ const IconStackItem = styled(motion.div) `
|
|
|
10444
10493
|
border-radius: 22.5%;
|
|
10445
10494
|
`;
|
|
10446
10495
|
|
|
10447
|
-
const OptionsContainer = styled
|
|
10496
|
+
const OptionsContainer = styled.div `
|
|
10448
10497
|
width: 100%;
|
|
10449
10498
|
margin-top: 1rem;
|
|
10450
10499
|
`;
|
|
@@ -10593,7 +10642,7 @@ const SelectExternalAmount = () => {
|
|
|
10593
10642
|
paymentState.setChosenUsd(amountUsd);
|
|
10594
10643
|
setRoute(ROUTES.WAITING_EXTERNAL, { amountUsd });
|
|
10595
10644
|
};
|
|
10596
|
-
return (jsxs(PageContent, { children: [jsx(ExternalPaymentSpinner, { logoURI: selectedExternalOption.logoURI, logoShape: selectedExternalOption.logoShape
|
|
10645
|
+
return (jsxs(PageContent, { children: [jsx(ExternalPaymentSpinner, { logoURI: selectedExternalOption.logoURI, logoShape: selectedExternalOption.logoShape }), jsxs(ModalContent, { "$preserveDisplay": true, children: [jsx(AmountInputContainer, { children: jsx(AmountInputField, { value: usdInput, onChange: handleAmountChange, onKeyDown: handleKeyDown }) }), message && jsx(ModalBody, { children: message }), jsx(Button, { onClick: handleContinue, disabled: continueDisabled, children: "Continue" })] })] }));
|
|
10597
10646
|
};
|
|
10598
10647
|
const AmountInputContainer = styled.div `
|
|
10599
10648
|
display: flex;
|
|
@@ -10625,7 +10674,7 @@ function SelectMethod() {
|
|
|
10625
10674
|
const { connected: isSolanaConnected, wallet: solanaWallet, publicKey, } = useWallet$1();
|
|
10626
10675
|
const { setRoute, paymentState, wcWallet, log } = usePayContext();
|
|
10627
10676
|
const { disconnectAsync } = useDisconnect();
|
|
10628
|
-
const { daimoPayOrder, setSelectedExternalOption, externalPaymentOptions, depositAddressOptions, senderEnsName, } = paymentState;
|
|
10677
|
+
const { daimoPayOrder, setSelectedExternalOption, externalPaymentOptions, showSolanaPaymentMethod, depositAddressOptions, senderEnsName, } = paymentState;
|
|
10629
10678
|
const paymentOptions = daimoPayOrder?.metadata.payer?.paymentOptions;
|
|
10630
10679
|
const getConnectedWalletOptions = () => {
|
|
10631
10680
|
const showChainLogo = isEthConnected && isSolanaConnected;
|
|
@@ -10660,7 +10709,7 @@ function SelectMethod() {
|
|
|
10660
10709
|
};
|
|
10661
10710
|
connectedOptions.push(connectedEthWalletOption);
|
|
10662
10711
|
}
|
|
10663
|
-
if (isSolanaConnected &&
|
|
10712
|
+
if (isSolanaConnected && showSolanaPaymentMethod) {
|
|
10664
10713
|
const solWalletDisplayName = getAddressContraction(publicKey?.toBase58() ?? "");
|
|
10665
10714
|
const connectedSolWalletOption = {
|
|
10666
10715
|
id: "connectedSolanaWallet",
|
|
@@ -10685,13 +10734,9 @@ function SelectMethod() {
|
|
|
10685
10734
|
}
|
|
10686
10735
|
return connectedOptions;
|
|
10687
10736
|
};
|
|
10688
|
-
// Solana payment option
|
|
10689
|
-
// Include by default if paymentOptions not provided
|
|
10690
|
-
const includeSolana = paymentOptions == null ||
|
|
10691
|
-
paymentOptions.includes(ExternalPaymentOptions.Solana);
|
|
10692
10737
|
// Deposit address options, e.g. Bitcoin, Tron, Zcash, etc.
|
|
10693
10738
|
// Include by default if paymentOptions not provided
|
|
10694
|
-
const
|
|
10739
|
+
const showDepositAddressMethod = paymentOptions == null ||
|
|
10695
10740
|
paymentOptions.includes(ExternalPaymentOptions.ExternalChains);
|
|
10696
10741
|
const connectedWalletOptions = getConnectedWalletOptions();
|
|
10697
10742
|
const unconnectedWalletOption = {
|
|
@@ -10709,7 +10754,7 @@ function SelectMethod() {
|
|
|
10709
10754
|
options.push(...connectedWalletOptions);
|
|
10710
10755
|
options.push(unconnectedWalletOption);
|
|
10711
10756
|
log(`[SELECT_METHOD] loading: ${externalPaymentOptions.loading}, options: ${JSON.stringify(externalPaymentOptions.options)}`);
|
|
10712
|
-
if (
|
|
10757
|
+
if (showSolanaPaymentMethod) {
|
|
10713
10758
|
const solanaOption = getSolanaOption(isIOS);
|
|
10714
10759
|
if (solanaOption) {
|
|
10715
10760
|
options.push(solanaOption);
|
|
@@ -10733,7 +10778,7 @@ function SelectMethod() {
|
|
|
10733
10778
|
disabled: option.disabled,
|
|
10734
10779
|
subtitle: option.message,
|
|
10735
10780
|
})));
|
|
10736
|
-
if (
|
|
10781
|
+
if (showDepositAddressMethod) {
|
|
10737
10782
|
const depositAddressOption = getDepositAddressOption(depositAddressOptions);
|
|
10738
10783
|
options.push(depositAddressOption);
|
|
10739
10784
|
}
|
|
@@ -10993,7 +11038,7 @@ var PayState;
|
|
|
10993
11038
|
})(PayState || (PayState = {}));
|
|
10994
11039
|
const PayWithSolanaToken = () => {
|
|
10995
11040
|
const { triggerResize, paymentState, setRoute } = usePayContext();
|
|
10996
|
-
const {
|
|
11041
|
+
const { selectedSolanaTokenOption, payWithSolanaToken } = paymentState;
|
|
10997
11042
|
const [payState, setPayState] = useState(PayState.RequestingPayment);
|
|
10998
11043
|
const handleTransfer = async () => {
|
|
10999
11044
|
try {
|
|
@@ -11130,6 +11175,7 @@ const WaitingExternal = () => {
|
|
|
11130
11175
|
const context = usePayContext();
|
|
11131
11176
|
const { triggerResize, paymentState, setRoute } = context;
|
|
11132
11177
|
const trpc = context.trpc;
|
|
11178
|
+
const { isMobile } = useIsMobile();
|
|
11133
11179
|
const { selectedExternalOption, payWithExternal, paymentWaitingMessage, daimoPayOrder, } = paymentState;
|
|
11134
11180
|
const [externalURL, setExternalURL] = useState(null);
|
|
11135
11181
|
useEffect(() => {
|
|
@@ -11155,17 +11201,19 @@ const WaitingExternal = () => {
|
|
|
11155
11201
|
});
|
|
11156
11202
|
}, [selectedExternalOption]);
|
|
11157
11203
|
const openExternalWindow = (url) => {
|
|
11158
|
-
if (
|
|
11159
|
-
//
|
|
11204
|
+
if (isMobile) {
|
|
11205
|
+
// on mobile: open in a new tab
|
|
11206
|
+
window.open(url, "_blank");
|
|
11207
|
+
}
|
|
11208
|
+
else {
|
|
11209
|
+
// on desktop: open in a popup window in
|
|
11210
|
+
// portrait mode in the center of the screen
|
|
11160
11211
|
const width = 500;
|
|
11161
11212
|
const height = 700;
|
|
11162
11213
|
const left = Math.max(0, Math.floor((window.innerWidth - width) / 2) + window.screenX);
|
|
11163
11214
|
const top = Math.max(0, Math.floor((window.innerHeight - height) / 2) + window.screenY);
|
|
11164
11215
|
window.open(url, "popupWindow", `width=${width},height=${height},left=${left},top=${top},scrollbars=yes`);
|
|
11165
11216
|
}
|
|
11166
|
-
else {
|
|
11167
|
-
window.open(url, "_blank");
|
|
11168
|
-
}
|
|
11169
11217
|
};
|
|
11170
11218
|
const waitingMessageLength = paymentWaitingMessage?.length;
|
|
11171
11219
|
useEffect(() => {
|
|
@@ -11185,14 +11233,14 @@ const customThemeDefault = {};
|
|
|
11185
11233
|
const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThemeDefault, lang = "en-US", }) => {
|
|
11186
11234
|
const context = usePayContext();
|
|
11187
11235
|
const paymentState = context.paymentState;
|
|
11188
|
-
const { payParams, generatePreviewOrder, isDepositFlow, setPaymentWaitingMessage, setSelectedExternalOption, setSelectedTokenOption, setSelectedSolanaTokenOption, setSelectedDepositAddressOption, } = paymentState;
|
|
11236
|
+
const { payParams, generatePreviewOrder, isDepositFlow, showSolanaPaymentMethod, setPaymentWaitingMessage, setSelectedExternalOption, setSelectedTokenOption, setSelectedSolanaTokenOption, setSelectedDepositAddressOption, } = paymentState;
|
|
11189
11237
|
const { isConnected: isEthConnected, connector, chain, address, } = useAccount();
|
|
11190
11238
|
const { connected: isSolanaConnected } = useWallet$1();
|
|
11191
11239
|
const { daimoPayOrder } = paymentState;
|
|
11192
11240
|
const paymentOptions = daimoPayOrder?.metadata.payer?.paymentOptions;
|
|
11193
11241
|
// Solana payment option
|
|
11194
11242
|
// Include by default if paymentOptions not provided
|
|
11195
|
-
|
|
11243
|
+
paymentOptions == null ||
|
|
11196
11244
|
paymentOptions.includes(ExternalPaymentOptions.Solana);
|
|
11197
11245
|
const chainIsSupported = useChainIsSupported(chain?.id);
|
|
11198
11246
|
//if chain is unsupported we enforce a "switch chain" prompt
|
|
@@ -11312,34 +11360,42 @@ const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThem
|
|
|
11312
11360
|
}
|
|
11313
11361
|
context.setOpen(false, { event: "click-close" });
|
|
11314
11362
|
}
|
|
11315
|
-
//
|
|
11363
|
+
// If the user has a wallet already connected upon opening the modal, go
|
|
11364
|
+
// straight to the select token screen
|
|
11316
11365
|
useEffect(() => {
|
|
11317
|
-
if (context.open
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
|
|
11366
|
+
if (!context.open)
|
|
11367
|
+
return;
|
|
11368
|
+
if (context.route !== ROUTES.SELECT_METHOD)
|
|
11369
|
+
return;
|
|
11370
|
+
const ethMethodAvailable = context.wcWallet != null || isEthConnected;
|
|
11371
|
+
const solanaMethodAvailable = isSolanaConnected && showSolanaPaymentMethod;
|
|
11372
|
+
// Skip to token selection if exactly one wallet is connected. If both
|
|
11373
|
+
// wallets are connected, stay on the SELECT_METHOD screen to allow the
|
|
11374
|
+
// user to select which wallet to use
|
|
11375
|
+
if (ethMethodAvailable && !solanaMethodAvailable) {
|
|
11376
|
+
context.setRoute(ROUTES.SELECT_TOKEN, {
|
|
11377
|
+
event: "eth_connected_on_open",
|
|
11378
|
+
walletId: connector?.id,
|
|
11379
|
+
chainId: chain?.id,
|
|
11380
|
+
address,
|
|
11381
|
+
});
|
|
11329
11382
|
}
|
|
11330
|
-
else if (
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
includeSolana) {
|
|
11335
|
-
if (context.route === ROUTES.SELECT_METHOD) {
|
|
11336
|
-
context.setRoute(ROUTES.SOLANA_SELECT_TOKEN, {
|
|
11337
|
-
event: "solana_connected_on_open",
|
|
11338
|
-
});
|
|
11339
|
-
}
|
|
11383
|
+
else if (solanaMethodAvailable && !ethMethodAvailable) {
|
|
11384
|
+
context.setRoute(ROUTES.SOLANA_SELECT_TOKEN, {
|
|
11385
|
+
event: "solana_connected_on_open",
|
|
11386
|
+
});
|
|
11340
11387
|
}
|
|
11341
|
-
//
|
|
11342
|
-
|
|
11388
|
+
// Don't include context.route in the dependency array otherwise the user
|
|
11389
|
+
// can't go back from the select token screen to the select method screen
|
|
11390
|
+
}, [
|
|
11391
|
+
context.open,
|
|
11392
|
+
context.wcWallet,
|
|
11393
|
+
isEthConnected,
|
|
11394
|
+
isSolanaConnected,
|
|
11395
|
+
showSolanaPaymentMethod,
|
|
11396
|
+
]);
|
|
11397
|
+
// If we're on the connect page and the user successfully connects their
|
|
11398
|
+
// wallet, go to the select token page
|
|
11343
11399
|
useEffect(() => {
|
|
11344
11400
|
if (context.route === ROUTES.CONNECT ||
|
|
11345
11401
|
context.route === ROUTES.CONNECTORS ||
|
|
@@ -11353,7 +11409,7 @@ const DaimoPayModal = ({ mode = "auto", theme = "auto", customTheme = customThem
|
|
|
11353
11409
|
});
|
|
11354
11410
|
}
|
|
11355
11411
|
}
|
|
11356
|
-
}, [isEthConnected, context.route]);
|
|
11412
|
+
}, [isEthConnected, context.route, connector?.id, chain?.id, address]);
|
|
11357
11413
|
useEffect(() => context.setMode(mode), [mode]);
|
|
11358
11414
|
useEffect(() => context.setTheme(theme), [theme]);
|
|
11359
11415
|
useEffect(() => context.setCustomTheme(customTheme), [customTheme]);
|
|
@@ -11452,18 +11508,43 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11452
11508
|
const [ckMode, setMode] = useState(mode);
|
|
11453
11509
|
const [ckCustomTheme, setCustomTheme] = useState(customTheme ?? {});
|
|
11454
11510
|
const [ckLang, setLang] = useState("en-US");
|
|
11511
|
+
const onOpenRef = useRef();
|
|
11512
|
+
const onCloseRef = useRef();
|
|
11513
|
+
const setOnOpen = useCallback((fn) => {
|
|
11514
|
+
onOpenRef.current = fn;
|
|
11515
|
+
}, []);
|
|
11516
|
+
const setOnClose = useCallback((fn) => {
|
|
11517
|
+
onCloseRef.current = fn;
|
|
11518
|
+
}, []);
|
|
11455
11519
|
const [open, setOpenState] = useState(false);
|
|
11456
|
-
const
|
|
11520
|
+
const [route, setRouteState] = useState(ROUTES.SELECT_METHOD);
|
|
11521
|
+
// Daimo Pay context
|
|
11522
|
+
const [daimoPayOrder, setDaimoPayOrderInner] = useState();
|
|
11523
|
+
const [pendingConnectorId, setPendingConnectorId] = useState(undefined);
|
|
11524
|
+
// Track sessions. Each generates separate intent IDs unless using externalId.
|
|
11525
|
+
const [sessionId] = useState(() => crypto.randomUUID().replaceAll("-", ""));
|
|
11526
|
+
const [solanaConnector, setSolanaConnector] = useState();
|
|
11527
|
+
// Other configuration
|
|
11528
|
+
const [errorMessage, setErrorMessage] = useState("");
|
|
11529
|
+
const [confirmationMessage, setConfirmationMessage] = useState(undefined);
|
|
11530
|
+
const [redirectReturnUrl, setRedirectReturnUrl] = useState(undefined);
|
|
11531
|
+
const log = debugMode ? console.log : () => { };
|
|
11532
|
+
// Connect to the Daimo Pay TRPC API
|
|
11533
|
+
const trpc = useMemo(() => createTrpcClient(payApiUrl, sessionId), [payApiUrl]);
|
|
11534
|
+
const [resize, onResize] = useState(0);
|
|
11535
|
+
const setOpen = useCallback((open, meta) => {
|
|
11457
11536
|
setOpenState(open);
|
|
11458
11537
|
trpc.nav.mutate({
|
|
11459
11538
|
action: open ? "navOpenPay" : "navClosePay",
|
|
11460
11539
|
orderId: daimoPayOrder?.id?.toString(),
|
|
11461
11540
|
data: meta ?? {},
|
|
11462
11541
|
});
|
|
11463
|
-
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
|
|
11542
|
+
if (open)
|
|
11543
|
+
onOpenRef.current?.();
|
|
11544
|
+
else
|
|
11545
|
+
onCloseRef.current?.();
|
|
11546
|
+
}, [trpc, daimoPayOrder?.id]);
|
|
11547
|
+
const setRoute = useCallback((route, data) => {
|
|
11467
11548
|
const action = route.replace("daimoPay", "");
|
|
11468
11549
|
log(`[SET ROUTE] ${action} ${daimoPayOrder?.id} ${debugJson(data ?? {})}`);
|
|
11469
11550
|
trpc.nav.mutate({
|
|
@@ -11472,15 +11553,10 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11472
11553
|
data: data ?? {},
|
|
11473
11554
|
});
|
|
11474
11555
|
setRouteState(route);
|
|
11475
|
-
};
|
|
11476
|
-
const [errorMessage, setErrorMessage] = useState("");
|
|
11477
|
-
const [confirmationMessage, setConfirmationMessage] = useState(undefined);
|
|
11478
|
-
const [redirectReturnUrl, setRedirectReturnUrl] = useState(undefined);
|
|
11479
|
-
const [resize, onResize] = useState(0);
|
|
11480
|
-
const [pendingConnectorId, setPendingConnectorId] = useState(undefined);
|
|
11556
|
+
}, [trpc, daimoPayOrder?.id, log]);
|
|
11481
11557
|
// Include Google Font that is needed for a themes
|
|
11482
11558
|
if (opts.embedGoogleFonts)
|
|
11483
|
-
useThemeFont(
|
|
11559
|
+
useThemeFont(ckTheme);
|
|
11484
11560
|
// Other Configuration
|
|
11485
11561
|
useEffect(() => setTheme(theme), [theme]);
|
|
11486
11562
|
useEffect(() => setLang(opts.language || "en-US"), [opts.language]);
|
|
@@ -11491,31 +11567,30 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11491
11567
|
useEffect(() => {
|
|
11492
11568
|
if (isConnected && opts.enforceSupportedChains && !isChainSupported) {
|
|
11493
11569
|
setOpen(true);
|
|
11494
|
-
|
|
11570
|
+
if (route !== ROUTES.SWITCHNETWORKS)
|
|
11571
|
+
setRoute(ROUTES.SWITCHNETWORKS);
|
|
11495
11572
|
}
|
|
11496
11573
|
}, [isConnected, isChainSupported, chain, route, open]);
|
|
11497
|
-
const log = debugMode ? console.log : () => { };
|
|
11498
|
-
// Track sessions. Each generates separate intent IDs unless using externalId.
|
|
11499
|
-
const [sessionId] = useState(() => crypto.randomUUID().replaceAll("-", ""));
|
|
11500
11574
|
// Single source of truth for the currently-connected wallet is the connector
|
|
11501
11575
|
// exposed by wagmi. See useAccount(). We watch this connector and use it to
|
|
11502
11576
|
// extract the current WalletConnect wallet, if any.
|
|
11503
11577
|
const wcWallet = useExtractWcWallet({ connector, log });
|
|
11504
|
-
// Connect to the Daimo Pay TRPC API
|
|
11505
|
-
const trpc = useMemo(() => createTrpcClient(payApiUrl, sessionId), [payApiUrl]);
|
|
11506
11578
|
// PaymentInfo is a second, inner context object containing a DaimoPayOrder
|
|
11507
11579
|
// plus all associated status and callbacks. In order for useContext() and
|
|
11508
11580
|
// downstream hooks like useDaimoPayStatus() to work correctly, we must set
|
|
11509
11581
|
// set refresh context when payment status changes; done via setDaimoPayOrder.
|
|
11510
|
-
const [daimoPayOrder, setDaimoPayOrderInner] = useState();
|
|
11511
11582
|
const setDaimoPayOrder = useCallback((order) => {
|
|
11512
11583
|
setDaimoPayOrderInner(order);
|
|
11584
|
+
if (order == null) {
|
|
11585
|
+
log(`[PAY] setDaimoPayOrder: reset`);
|
|
11586
|
+
return;
|
|
11587
|
+
}
|
|
11513
11588
|
let extra = `> $${order.destFinalCallTokenAmount.usd.toFixed(2)} to ${order.destFinalCallTokenAmount.token.chainId} ${order.destFinalCall.to}`;
|
|
11514
11589
|
if (order.mode === DaimoPayOrderMode.HYDRATED) {
|
|
11515
11590
|
extra += ` via ${order.intentAddr} ${order.sourceStatus} ${order.intentStatus}`;
|
|
11516
11591
|
}
|
|
11517
11592
|
log(`[PAY] setDaimoPayOrder: ${order.id} ${extra}`);
|
|
11518
|
-
}, [
|
|
11593
|
+
}, [log]);
|
|
11519
11594
|
const paymentState = usePaymentState({
|
|
11520
11595
|
trpc,
|
|
11521
11596
|
daimoPayOrder,
|
|
@@ -11546,7 +11621,6 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11546
11621
|
return () => clearTimeout(timeout);
|
|
11547
11622
|
}, [daimoPayOrder]);
|
|
11548
11623
|
const showPayment = async (modalOptions) => {
|
|
11549
|
-
const { daimoPayOrder } = paymentState;
|
|
11550
11624
|
const id = daimoPayOrder?.id;
|
|
11551
11625
|
log(`[PAY] showing payment ${debugJson({ id, modalOptions })}`);
|
|
11552
11626
|
paymentState.setModalOptions(modalOptions);
|
|
@@ -11572,6 +11646,8 @@ const DaimoPayProviderWithoutSolana = ({ children, theme = "auto", mode = "auto"
|
|
|
11572
11646
|
setCustomTheme,
|
|
11573
11647
|
lang: ckLang,
|
|
11574
11648
|
setLang,
|
|
11649
|
+
setOnOpen,
|
|
11650
|
+
setOnClose,
|
|
11575
11651
|
open,
|
|
11576
11652
|
setOpen,
|
|
11577
11653
|
route,
|
|
@@ -11857,10 +11933,12 @@ function DaimoPayButtonCustom(props) {
|
|
|
11857
11933
|
evmChains: props.evmChains,
|
|
11858
11934
|
externalId: props.externalId,
|
|
11859
11935
|
metadata: props.metadata,
|
|
11936
|
+
refundAddress: props.refundAddress,
|
|
11860
11937
|
}
|
|
11861
11938
|
: null;
|
|
11862
11939
|
let payId = "payId" in props ? props.payId : null;
|
|
11863
11940
|
const { paymentState } = context;
|
|
11941
|
+
// Set the payId or payParams
|
|
11864
11942
|
useEffect(() => {
|
|
11865
11943
|
if (payId != null) {
|
|
11866
11944
|
paymentState.setPayId(payId);
|
|
@@ -11869,18 +11947,30 @@ function DaimoPayButtonCustom(props) {
|
|
|
11869
11947
|
paymentState.setPayParams(payParams);
|
|
11870
11948
|
}
|
|
11871
11949
|
}, [payId, JSON.stringify(payParams || {})]);
|
|
11950
|
+
// Set the confirmation message
|
|
11872
11951
|
const { setConfirmationMessage } = context;
|
|
11873
11952
|
useEffect(() => {
|
|
11874
11953
|
if (props.confirmationMessage) {
|
|
11875
11954
|
setConfirmationMessage(props.confirmationMessage);
|
|
11876
11955
|
}
|
|
11877
11956
|
}, [props.confirmationMessage, setConfirmationMessage]);
|
|
11957
|
+
// Set the redirect return url
|
|
11878
11958
|
const { setRedirectReturnUrl } = context;
|
|
11879
11959
|
useEffect(() => {
|
|
11880
11960
|
if (props.redirectReturnUrl) {
|
|
11881
11961
|
setRedirectReturnUrl(props.redirectReturnUrl);
|
|
11882
11962
|
}
|
|
11883
11963
|
}, [props.redirectReturnUrl, setRedirectReturnUrl]);
|
|
11964
|
+
// Set the onOpen and onClose callbacks
|
|
11965
|
+
const { setOnOpen, setOnClose } = context;
|
|
11966
|
+
useEffect(() => {
|
|
11967
|
+
setOnOpen(props.onOpen);
|
|
11968
|
+
return () => setOnOpen(undefined);
|
|
11969
|
+
}, [props.onOpen, setOnOpen]);
|
|
11970
|
+
useEffect(() => {
|
|
11971
|
+
setOnClose(props.onClose);
|
|
11972
|
+
return () => setOnClose(undefined);
|
|
11973
|
+
}, [props.onClose, setOnClose]);
|
|
11884
11974
|
// Payment events: call these three event handlers.
|
|
11885
11975
|
const { onPaymentStarted, onPaymentCompleted, onPaymentBounced } = props;
|
|
11886
11976
|
const order = paymentState.daimoPayOrder;
|
|
@@ -11896,21 +11986,23 @@ function DaimoPayButtonCustom(props) {
|
|
|
11896
11986
|
};
|
|
11897
11987
|
const hide = () => context.setOpen(false);
|
|
11898
11988
|
// Emit event handlers when payment status changes
|
|
11989
|
+
const sentStart = useRef(false);
|
|
11899
11990
|
useEffect(() => {
|
|
11900
11991
|
if (hydOrder == null)
|
|
11901
11992
|
return;
|
|
11902
11993
|
if (intentStatus === DaimoPayIntentStatus.UNPAID)
|
|
11903
11994
|
return;
|
|
11904
|
-
if (
|
|
11995
|
+
if (!sentStart.current && hydOrder.sourceTokenAmount) {
|
|
11996
|
+
sentStart.current = true;
|
|
11905
11997
|
onPaymentStarted?.({
|
|
11906
11998
|
type: DaimoPayIntentStatus.STARTED,
|
|
11907
11999
|
paymentId: writeDaimoPayOrderID(hydOrder.id),
|
|
11908
|
-
chainId: hydOrder.
|
|
11909
|
-
txHash:
|
|
12000
|
+
chainId: hydOrder.sourceTokenAmount?.token.chainId,
|
|
12001
|
+
txHash: hydOrder.sourceInitiateTxHash ?? null,
|
|
11910
12002
|
payment: getDaimoPayOrderView(hydOrder),
|
|
11911
12003
|
});
|
|
11912
12004
|
}
|
|
11913
|
-
|
|
12005
|
+
if (intentStatus === DaimoPayIntentStatus.COMPLETED ||
|
|
11914
12006
|
intentStatus === DaimoPayIntentStatus.BOUNCED) {
|
|
11915
12007
|
const event = {
|
|
11916
12008
|
type: intentStatus,
|
|
@@ -11926,12 +12018,13 @@ function DaimoPayButtonCustom(props) {
|
|
|
11926
12018
|
onPaymentBounced?.(event);
|
|
11927
12019
|
}
|
|
11928
12020
|
}
|
|
11929
|
-
}, [hydOrder?.id, intentStatus]);
|
|
12021
|
+
}, [hydOrder?.id, intentStatus, hydOrder?.sourceTokenAmount?.token.chainId]);
|
|
12022
|
+
// Open the modal by default if the defaultOpen prop is true
|
|
11930
12023
|
useEffect(() => {
|
|
11931
|
-
if (props.defaultOpen) {
|
|
12024
|
+
if (props.defaultOpen && order != null) {
|
|
11932
12025
|
show();
|
|
11933
12026
|
}
|
|
11934
|
-
}, [order != null]);
|
|
12027
|
+
}, [order != null, props.defaultOpen]);
|
|
11935
12028
|
// Validation
|
|
11936
12029
|
if ((payId == null) == (payParams == null)) {
|
|
11937
12030
|
throw new Error("Must specify either payId or appId, not both");
|
|
@@ -11986,11 +12079,12 @@ function DaimoPayButtonInner({ disabled }) {
|
|
|
11986
12079
|
*/
|
|
11987
12080
|
function useDaimoPayStatus() {
|
|
11988
12081
|
const { paymentState } = usePayContext();
|
|
12082
|
+
const reset = paymentState.resetOrder;
|
|
11989
12083
|
if (!paymentState || !paymentState.daimoPayOrder)
|
|
11990
|
-
return
|
|
12084
|
+
return { reset };
|
|
11991
12085
|
const order = paymentState.daimoPayOrder;
|
|
11992
12086
|
const paymentId = writeDaimoPayOrderID(order.id);
|
|
11993
|
-
return { paymentId, status: order.intentStatus };
|
|
12087
|
+
return { paymentId, status: order.intentStatus, reset };
|
|
11994
12088
|
}
|
|
11995
12089
|
|
|
11996
12090
|
function addressToNumber(address) {
|