UNPKG

@daimo/pay

Version:

Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.

186 lines (183 loc) 6.09 kB
import { ExternalPaymentOptions, supportedChains } from '@daimo/pay-common'; import { useState, useMemo, useEffect } from 'react'; import { inferTopLevelFromArray } from '../constants/paymentOptions.js'; const DEFAULT_EXTERNAL_PAYMENT_OPTIONS = Object.values( ExternalPaymentOptions ).filter( (opt) => opt !== ExternalPaymentOptions.AllAddresses && opt !== ExternalPaymentOptions.AllPaymentApps ); function usePaymentOptions({ trpc, appId, orderId, isDepositFlow, usdRequired, solanaPubKey, ethWalletAddress, platform, // For filtering/preferences from order metadata filterIds, preferredChains, preferredTokens, evmChains, destChainId, passthroughTokens, destAddress, log }) { const [externalOptions, setExternalOptions] = useState(/* @__PURE__ */ new Map()); const [walletOptions, setWalletOptions] = useState(null); const [solanaOptions, setSolanaOptions] = useState(null); const [depositOptions, setDepositOptions] = useState([]); const [parsedConfig, setParsedConfig] = useState({ walletOrder: [] }); const [loading, setLoading] = useState(false); const memoizedPreferredChains = useMemo( () => preferredChains, // eslint-disable-next-line react-hooks/exhaustive-deps [JSON.stringify(preferredChains)] ); const memoizedPreferredTokens = useMemo( () => preferredTokens, // eslint-disable-next-line react-hooks/exhaustive-deps [JSON.stringify(preferredTokens)] ); const memoizedEvmChains = useMemo( () => evmChains, // eslint-disable-next-line react-hooks/exhaustive-deps [JSON.stringify(evmChains)] ); const memoizedFilterIds = useMemo( () => filterIds, // eslint-disable-next-line react-hooks/exhaustive-deps [JSON.stringify(filterIds)] ); useEffect(() => { const fetchPaymentOptions = async () => { if (!platform) return; if (!appId && !orderId) return; if (!isDepositFlow && !orderId && !usdRequired) return; setLoading(true); try { const result = await trpc.getPaymentOptionsV1.query({ appId, orderId: orderId?.toString(), platform, ethWalletAddress, preferredChains: memoizedPreferredChains, preferredTokens: memoizedPreferredTokens, evmChains: memoizedEvmChains, destChainId, solanaPubKey, usdRequired, isDepositFlow }); let walletOrder = []; if (memoizedFilterIds) { const nestedArray = memoizedFilterIds.find( (opt) => Array.isArray(opt) ); if (nestedArray && Array.isArray(nestedArray)) { walletOrder = nestedArray; } } setParsedConfig({ walletOrder }); const flatFilterIds = memoizedFilterIds ? memoizedFilterIds.flatMap( (opt) => Array.isArray(opt) ? inferTopLevelFromArray(opt) ?? "AllWallets" : opt ) : null; const enabledExtPaymentOptions = flatFilterIds || DEFAULT_EXTERNAL_PAYMENT_OPTIONS; const hasAllPaymentApps = enabledExtPaymentOptions.includes( ExternalPaymentOptions.AllPaymentApps ); const hasAllExchanges = enabledExtPaymentOptions.includes( ExternalPaymentOptions.AllExchanges ); const filteredExternal = result.externalOptions.filter( (option) => enabledExtPaymentOptions.includes(option.id) || hasAllPaymentApps && option.optionType === "zkp2p" || hasAllExchanges && option.optionType === "exchange" ); const optionsByType = /* @__PURE__ */ new Map(); filteredExternal.forEach((option) => { const { optionType } = option; if (!optionsByType.has(optionType)) { optionsByType.set(optionType, []); } optionsByType.get(optionType).push(option); }); setExternalOptions(optionsByType); if (result.walletOptions.length > 0) { const isSupported = (o) => supportedChains.some((c) => c.chainId === o.balance.token.chainId); const filtered = result.walletOptions.filter(isSupported); if (filtered.length < result.walletOptions.length) { log( `[WALLET]: skipping ${result.walletOptions.length - filtered.length} unsupported-chain balances` ); } if (destAddress) { addPassthroughTokens(filtered, passthroughTokens, destAddress); } setWalletOptions(filtered); } else { setWalletOptions(ethWalletAddress ? [] : null); } setSolanaOptions(solanaPubKey ? result.solanaOptions : null); setDepositOptions(result.depositAddressOptions); } catch (error) { console.error("[usePaymentOptions] error:", error); } finally { setLoading(false); } }; fetchPaymentOptions(); }, [ trpc, appId, orderId, isDepositFlow, usdRequired, solanaPubKey, ethWalletAddress, platform, memoizedPreferredChains, memoizedPreferredTokens, memoizedEvmChains, memoizedFilterIds, destChainId, destAddress, passthroughTokens, log ]); return { externalPaymentOptions: { options: externalOptions, loading, parsedConfig }, walletPaymentOptions: { options: walletOptions, isLoading: loading }, solanaPaymentOptions: { options: solanaOptions, isLoading: loading }, depositAddressOptions: { options: depositOptions, loading } }; } function addPassthroughTokens(options, passthroughTokens, passthroughAddress) { if (passthroughTokens == null) return; for (const option of options) { const tok = option.balance.token; if (option.disabledReason != null) continue; const found = passthroughTokens.find( (t) => t.address === tok.token && t.chain == tok.chainId ); if (found == null) continue; option.passthroughAddress = passthroughAddress; } } export { addPassthroughTokens, usePaymentOptions }; //# sourceMappingURL=usePaymentOptions.js.map