@daimo/pay 1.9.1 → 1.9.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.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { http, useConnectors as useConnectors$1, useAccount, useSwitchChain, useConnect as useConnect$1, useConfig, useDisconnect, useChainId, useAccountEffect, useEnsName, useSendTransaction, useWriteContract, WagmiContext, createConfig, useEnsAddress, useEnsAvatar } from 'wagmi';
2
- import { mainnet, base as base$1, polygon, optimism, arbitrum, linea, bsc, sepolia, baseSepolia, worldchain, blast, mantle } from 'wagmi/chains';
2
+ import { mainnet, base as base$1, polygon, optimism, arbitrum, linea, bsc, sepolia, baseSepolia, worldchain, mantle } from 'wagmi/chains';
3
3
  import { safe, injected, coinbaseWallet, walletConnect } from '@wagmi/connectors';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
- import { DaimoPayIntentStatus, assert, DaimoPayOrderMode, readDaimoPayOrderID, getOrderDestChainId, assertNotNull, getChainName, arbitrum as arbitrum$1, base as base$2, blast as blast$1, bsc as bsc$1, ethereum, linea as linea$1, mantle as mantle$1, optimism as optimism$1, polygon as polygon$1, worldchain as worldchain$1, solana, getAddressContraction, supportedChains, getChainExplorerTxUrl, ExternalPaymentOptions, isCCTPV1Chain, debugJson, DepositAddressPaymentOptions, writeDaimoPayOrderID, getOrderSourceChainId, DaimoPayEventType, getDaimoPayOrderView } from '@daimo/pay-common';
5
+ import { DaimoPayIntentStatus, assert, DaimoPayOrderMode, isHydrated, readDaimoPayOrderID, getOrderDestChainId, assertNotNull, getChainName, arbitrum as arbitrum$1, base as base$2, bsc as bsc$1, ethereum, linea as linea$1, mantle as mantle$1, optimism as optimism$1, polygon as polygon$1, worldchain as worldchain$1, solana, getAddressContraction, supportedChains, getChainExplorerTxUrl, ExternalPaymentOptions, DepositAddressPaymentOptions, ethereumUSDC, polygonUSDC, baseUSDC, arbitrumUSDC, optimismUSDC, isCCTPV1Chain, debugJson, writeDaimoPayOrderID, DaimoPayOrderStatusSource, getOrderSourceChainId, DaimoPayEventType, getDaimoPayOrderView } from '@daimo/pay-common';
6
6
  import { Buffer } from 'buffer';
7
7
  import React, { createContext, useRef, useState, useEffect, useLayoutEffect, useMemo, useContext, useSyncExternalStore, useCallback, createElement } from 'react';
8
8
  import styled$1, { css, keyframes, ThemeProvider } from 'styled-components';
@@ -22,7 +22,7 @@ import { VersionedTransaction } from '@solana/web3.js';
22
22
  import { normalize } from 'viem/ens';
23
23
 
24
24
  var name = "@daimo/pay";
25
- var version = "1.9.1";
25
+ var version = "1.9.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.9.1",
64
+ "@daimo/pay-common": "1.9.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",
@@ -175,7 +175,6 @@ const REQUIRED_CHAINS = [
175
175
  sepolia,
176
176
  baseSepolia,
177
177
  worldchain,
178
- blast,
179
178
  mantle,
180
179
  ];
181
180
  /** Daimo Pay recommended config, for use with wagmi's createConfig(). */
@@ -2164,6 +2163,7 @@ function useLockBodyScroll(initialLocked) {
2164
2163
  return [locked, setLocked];
2165
2164
  }
2166
2165
 
2166
+ const WarningIcon = () => (jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", className: "size-6", width: "16", height: "16", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" }) }));
2167
2167
  const ExternalLinkIcon = ({ ...props }) => (jsxs("svg", { "aria-hidden": "true", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", style: {
2168
2168
  left: 0,
2169
2169
  top: 0,
@@ -2392,8 +2392,8 @@ function reduceUnhydrated(state, event) {
2392
2392
  }
2393
2393
  function reducePaymentUnpaid(state, event) {
2394
2394
  switch (event.type) {
2395
- case "payment_started":
2396
- return { type: "payment_started", order: state.order };
2395
+ case "order_refreshed":
2396
+ return reduceOrderRefreshed(state, event.order);
2397
2397
  case "error":
2398
2398
  return {
2399
2399
  type: "error",
@@ -2408,14 +2408,8 @@ function reducePaymentUnpaid(state, event) {
2408
2408
  }
2409
2409
  function reducePaymentStarted(state, event) {
2410
2410
  switch (event.type) {
2411
- case "order_refreshed": {
2412
- assert(event.order.mode === DaimoPayOrderMode.HYDRATED, `[PAYMENT_REDUCER] order ${event.order.id} is ${event.order.intentStatus} but not hydrated`);
2413
- return { type: "payment_started", order: event.order };
2414
- }
2415
- case "dest_processed":
2416
- return event.order.intentStatus === DaimoPayIntentStatus.COMPLETED
2417
- ? { type: "payment_completed", order: event.order }
2418
- : { type: "payment_bounced", order: event.order };
2411
+ case "order_refreshed":
2412
+ return reduceOrderRefreshed(state, event.order);
2419
2413
  case "error":
2420
2414
  return {
2421
2415
  type: "error",
@@ -2428,6 +2422,21 @@ function reducePaymentStarted(state, event) {
2428
2422
  return state;
2429
2423
  }
2430
2424
  }
2425
+ function reduceOrderRefreshed(state, order) {
2426
+ assert(isHydrated(order), `[PAYMENT_REDUCER] unhydrated`);
2427
+ switch (order.intentStatus) {
2428
+ case DaimoPayIntentStatus.UNPAID:
2429
+ return { type: "payment_unpaid", order };
2430
+ case DaimoPayIntentStatus.STARTED:
2431
+ return { type: "payment_started", order };
2432
+ case DaimoPayIntentStatus.COMPLETED:
2433
+ return { type: "payment_completed", order };
2434
+ case DaimoPayIntentStatus.BOUNCED:
2435
+ return { type: "payment_bounced", order };
2436
+ default:
2437
+ return state;
2438
+ }
2439
+ }
2431
2440
  function reduceTerminal(state, event) {
2432
2441
  switch (event.type) {
2433
2442
  case "reset":
@@ -2461,10 +2470,9 @@ function waitForPaymentState(store, predicate) {
2461
2470
  * Will poll the given function at the specified interval. Stops when the
2462
2471
  * returned handle is invoked.
2463
2472
  */
2464
- function startPolling({ key, intervalMs, pollFn, onResult, onError, maxErrors = 5, log = console.log, }) {
2473
+ function startPolling({ key, intervalMs, pollFn, onResult, onError, log = console.log, }) {
2465
2474
  let active = true;
2466
2475
  let timer;
2467
- let errorCount = 0;
2468
2476
  const stop = () => {
2469
2477
  active = false;
2470
2478
  clearTimeout(timer);
@@ -2476,7 +2484,6 @@ function startPolling({ key, intervalMs, pollFn, onResult, onError, maxErrors =
2476
2484
  const res = await pollFn();
2477
2485
  if (!active)
2478
2486
  return;
2479
- errorCount = 0;
2480
2487
  log(`[POLL] ${key} success`);
2481
2488
  onResult(res);
2482
2489
  }
@@ -2485,11 +2492,6 @@ function startPolling({ key, intervalMs, pollFn, onResult, onError, maxErrors =
2485
2492
  return;
2486
2493
  log(`[POLL] ${key} error: ${e}`);
2487
2494
  onError(e);
2488
- errorCount++;
2489
- if (errorCount >= maxErrors) {
2490
- log(`[POLL] ${key} reached max errors (${maxErrors}), giving up`);
2491
- return stop();
2492
- }
2493
2495
  }
2494
2496
  timer = setTimeout(tick, intervalMs);
2495
2497
  };
@@ -2527,7 +2529,7 @@ function attachPaymentEffectHandlers(store, trpc, log) {
2527
2529
  if (prev.type !== next.type) {
2528
2530
  // Start watching for source payment
2529
2531
  if (next.type === "payment_unpaid") {
2530
- pollFindSourcePayment(store, trpc, next.order.id);
2532
+ pollFindPayments(store, trpc, next.order.id);
2531
2533
  }
2532
2534
  // Refresh the order to watch for destination processing
2533
2535
  if (next.type === "payment_started") {
@@ -2591,22 +2593,19 @@ function attachPaymentEffectHandlers(store, trpc, log) {
2591
2593
  };
2592
2594
  return cleanup;
2593
2595
  }
2594
- async function pollFindSourcePayment(store, trpc, orderId) {
2596
+ async function pollFindPayments(store, trpc, orderId) {
2595
2597
  const key = `${PollerType.FIND_SOURCE_PAYMENT}:${orderId}`;
2596
2598
  const stopPolling = startPolling({
2597
2599
  key,
2598
2600
  intervalMs: 1_000,
2599
- pollFn: () => trpc.findSourcePayment.query({ orderId: orderId.toString() }),
2600
- onResult: (found) => {
2601
+ pollFn: () => trpc.findOrderPayments.query({ orderId: orderId.toString() }),
2602
+ onResult: (order) => {
2601
2603
  const state = store.getState();
2602
- // Check that we're still in the payment_unpaid state
2603
2604
  if (state.type !== "payment_unpaid") {
2604
2605
  stopPolling();
2606
+ return;
2605
2607
  }
2606
- else if (found) {
2607
- stopPolling();
2608
- store.dispatch({ type: "payment_started", order: state.order });
2609
- }
2608
+ store.dispatch({ type: "order_refreshed", order });
2610
2609
  },
2611
2610
  onError: () => { },
2612
2611
  });
@@ -2621,16 +2620,12 @@ async function pollRefreshOrder(store, trpc, orderId) {
2621
2620
  onResult: (res) => {
2622
2621
  const state = store.getState();
2623
2622
  // Check that we're still in the payment_started state
2624
- if (state.type !== "payment_started")
2623
+ if (state.type !== "payment_started") {
2624
+ stopPolling();
2625
2625
  return;
2626
+ }
2626
2627
  const order = res.order;
2627
2628
  store.dispatch({ type: "order_refreshed", order });
2628
- if (order.intentStatus === "payment_completed" ||
2629
- order.intentStatus === "payment_bounced") {
2630
- assert(order.mode === DaimoPayOrderMode.HYDRATED, `[PAYMENT_EFFECTS] order ${order.id} is ${order.intentStatus} but not hydrated`);
2631
- store.dispatch({ type: "dest_processed", order });
2632
- stopPolling();
2633
- }
2634
2629
  },
2635
2630
  onError: () => { },
2636
2631
  });
@@ -2739,7 +2734,7 @@ async function runHydratePayIdEffects(store, trpc, prev, event) {
2739
2734
  async function runPayEthereumSourceEffects(store, trpc, prev, event) {
2740
2735
  const orderId = prev.order.id;
2741
2736
  try {
2742
- await trpc.processSourcePayment.mutate({
2737
+ const order = await trpc.processSourcePayment.mutate({
2743
2738
  orderId: orderId.toString(),
2744
2739
  sourceInitiateTxHash: event.paymentTxHash,
2745
2740
  sourceChainId: event.sourceChainId,
@@ -2747,8 +2742,7 @@ async function runPayEthereumSourceEffects(store, trpc, prev, event) {
2747
2742
  sourceToken: event.sourceToken,
2748
2743
  sourceAmount: event.sourceAmount.toString(),
2749
2744
  });
2750
- // TODO: Update order state with updated txHash
2751
- store.dispatch({ type: "payment_started", order: prev.order });
2745
+ store.dispatch({ type: "order_refreshed", order });
2752
2746
  }
2753
2747
  catch (e) {
2754
2748
  store.dispatch({ type: "error", order: prev.order, message: e.message });
@@ -2757,13 +2751,12 @@ async function runPayEthereumSourceEffects(store, trpc, prev, event) {
2757
2751
  async function runPaySolanaSourceEffects(store, trpc, prev, event) {
2758
2752
  const orderId = prev.order.id;
2759
2753
  try {
2760
- await trpc.processSolanaSourcePayment.mutate({
2754
+ const order = await trpc.processSolanaSourcePayment.mutate({
2761
2755
  orderId: orderId.toString(),
2762
2756
  startIntentTxHash: event.paymentTxHash,
2763
2757
  token: event.sourceToken,
2764
2758
  });
2765
- // TODO: Update order state with updated txHash
2766
- store.dispatch({ type: "payment_started", order: prev.order });
2759
+ store.dispatch({ type: "order_refreshed", order });
2767
2760
  }
2768
2761
  catch (e) {
2769
2762
  store.dispatch({ type: "error", order: prev.order, message: e.message });
@@ -7333,12 +7326,33 @@ const Base = ({ testnet, ...props }) => (jsx("svg", { ...props, width: "44", hei
7333
7326
  }, children: jsx("path", { d: "M21.9756 36C29.721 36 36 29.732 36 22C36 14.268 29.721 8 21.9756 8C14.6271 8 8.59871 13.6419 8 20.8232H26.5371V23.1768H8C8.59871 30.3581 14.6271 36 21.9756 36Z", fill: "white" }) }));
7334
7327
  const Linea = ({ testnet, ...props }) => (jsxs("svg", { ...props, width: "44", height: "44", viewBox: "0 0 200 200", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("path", { d: "M200 0H0V200H200V0Z", fill: "#121212" }), jsx("mask", { id: "mask0_267_10", style: { maskType: "luminance" }, maskUnits: "userSpaceOnUse", x: "50", y: "48", width: "100", height: "104", children: jsx("path", { d: "M149.541 48H50V151.977H149.541V48Z", fill: "white" }) }), jsxs("g", { mask: "url(#mask0_267_10)", children: [jsx("path", { d: "M132.669 151.977H50V64.8721H68.9147V135.096H132.669V151.968V151.977Z", fill: "white" }), jsx("path", { d: "M132.669 81.7441C141.987 81.7441 149.541 74.1902 149.541 64.8721C149.541 55.5539 141.987 48 132.669 48C123.35 48 115.797 55.5539 115.797 64.8721C115.797 74.1902 123.35 81.7441 132.669 81.7441Z", fill: "white" })] })] }));
7335
7328
  const Worldchain = ({ testnet, ...props }) => (jsxs("svg", { ...props, "aria-hidden": "true", width: "44", height: "44", viewBox: "0 0 400 400", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("path", { d: "M0 0 C132 0 264 0 400 0 C400 132 400 264 400 400 C268 400 136 400 0 400 C0 268 0 136 0 0 Z ", fill: "#FEFEFE", transform: "translate(0,0)" }), jsx("path", { d: "M0 0 C0.70403961 0.0012085 1.40807922 0.00241699 2.13345337 0.00366211 C37.34271908 0.16721508 68.5105973 14.80090333 93.17163086 39.68505859 C98.62984305 45.41558542 103.09177892 51.78200535 107.4375 58.375 C108.159375 59.4475 108.88125 60.52 109.625 61.625 C122.08220864 80.87704972 127.84793078 103.26191133 127.75 126.0625 C127.74850952 126.72419189 127.74701904 127.38588379 127.7454834 128.06762695 C127.70436084 138.22551322 127.07498098 147.56085403 124.4375 157.375 C124.14746094 158.56480469 123.85742188 159.75460938 123.55859375 160.98046875 C117.33294616 184.86715846 102.42700827 208.48904018 83.4375 224.375 C82.7775 224.375 82.1175 224.375 81.4375 224.375 C81.4375 225.035 81.4375 225.695 81.4375 226.375 C79.55168751 227.86844182 77.6802053 229.22460868 75.6875 230.5625 C75.09767334 230.96251221 74.50784668 231.36252441 73.90014648 231.7746582 C45.33982467 250.94089101 10.69801357 259.36417248 -23.53125 253.31640625 C-58.32294327 245.96067382 -87.68703658 225.97193245 -107.32177734 196.33154297 C-113.84308531 186.04784324 -119.21618764 175.09939589 -122.5625 163.375 C-122.75714844 162.7032373 -122.95179687 162.03147461 -123.15234375 161.33935547 C-126.29298989 150.01096274 -126.95426502 138.7553544 -127 127.0625 C-127.0061734 126.39534973 -127.0123468 125.72819946 -127.01870728 125.04083252 C-127.22210042 90.87814217 -112.10569979 60.09763142 -88.5625 35.9375 C-73.41024939 20.79283974 -54.8893351 10.80975271 -34.5625 4.375 C-33.52222656 4.04242188 -32.48195313 3.70984375 -31.41015625 3.3671875 C-20.96204118 0.67295275 -10.76743051 -0.03432509 0 0 Z ", fill: "#030303", transform: "translate(199.5625,72.625)" }), jsx("path", { d: "M0 0 C11.55 0 23.1 0 35 0 C37.475 7.425 37.475 7.425 40 15 C49.21380616 33.94914853 62.0370052 48.14330377 82.26171875 55.140625 C83.16535156 55.42421875 84.06898438 55.7078125 85 56 C86.03415543 56.34114838 87.06831085 56.68229675 88.13380432 57.03378296 C92.4151578 58.10375381 96.2112859 58.30653699 100.59741211 58.31884766 C101.84252563 58.33391609 101.84252563 58.33391609 103.11279297 58.34928894 C105.83430337 58.37997941 108.55571605 58.39711649 111.27734375 58.4140625 C113.17306857 58.43278554 115.06878515 58.45235979 116.9644928 58.4727478 C121.93741998 58.52395501 126.91037415 58.56364168 131.88342285 58.60089111 C136.96466688 58.64100246 142.04579976 58.69206221 147.12695312 58.7421875 C157.08455721 58.83881161 167.04222421 58.92325948 177 59 C176.06240625 60.11818809 175.12128368 61.23341782 174.17871094 62.34741211 C173.39315826 63.27945717 173.39315826 63.27945717 172.59173584 64.23033142 C162.58148353 75.35958323 147.85650103 82.10162688 134 87 C132.87980469 87.41765625 131.75960937 87.8353125 130.60546875 88.265625 C112.47396566 93.94296445 87.79207496 93.59729315 70 87 C68.77410156 86.5875 67.54820312 86.175 66.28515625 85.75 C40.7576163 76.74144211 20.58906247 57.52681738 8.6484375 33.45703125 C3.51705369 22.69571686 0 12.06068152 0 0 Z ", fill: "#FAFAFA", transform: "translate(98,212)" }), jsx("path", { d: "M0 0 C0.99128906 0.26683594 1.98257813 0.53367187 3.00390625 0.80859375 C20.02205338 5.90723969 35.38784974 15.53622797 48 28 C48 28.33 48 28.66 48 29 C46.99569946 29.00142502 45.99139893 29.00285004 44.95666504 29.00431824 C35.42537052 29.02109205 25.89449728 29.06417913 16.36342621 29.13209057 C11.46504263 29.16617258 6.56696472 29.19144103 1.66845703 29.19555664 C-3.07161547 29.19988029 -7.81100063 29.22867466 -12.55085754 29.27343178 C-14.34621658 29.28627824 -16.14165841 29.29076089 -17.9370575 29.28615379 C-39.57125354 29.2436265 -58.64662622 35.40002391 -74.56494141 50.54882812 C-85.14790619 61.25062171 -89.66973578 73.56885506 -93 88 C-104.88 88 -116.76 88 -129 88 C-129 64.08086196 -115.40828709 41.63583644 -99 25 C-72.65926108 0.43663887 -35.01441399 -9.99793527 0 0 Z ", fill: "#FBFBFB", transform: "translate(227,100)" }), jsx("path", { d: "M0 0 C1.43530815 -0.00043808 1.43530815 -0.00043808 2.89961243 -0.00088501 C6.04327657 0.00050157 9.18669983 0.01603116 12.33032227 0.03173828 C14.51750051 0.0354708 16.70468044 0.03831664 18.89186096 0.04031372 C24.63427386 0.04793137 30.37658477 0.06756384 36.11895752 0.08972168 C41.98432028 0.11022036 47.8496996 0.11932403 53.71508789 0.12939453 C65.21317945 0.15081148 76.71119548 0.18492487 88.20922852 0.22705078 C89.01417532 1.6299547 89.81343075 3.03612493 90.61035156 4.44360352 C91.05606003 5.22630112 91.50176849 6.00899872 91.96098328 6.81541443 C93.86879215 10.50134175 94.96928018 14.29024711 96.02172852 18.28955078 C96.34560547 19.41586914 96.34560547 19.41586914 96.67602539 20.56494141 C98.11972655 25.86767867 98.20922852 29.34376842 98.20922852 35.22705078 C50.68922852 35.22705078 3.16922852 35.22705078 -45.79077148 35.22705078 C-41.98207673 22.53140161 -35.92269341 12.61991806 -24.31030273 5.76220703 C-16.09258333 1.47307966 -9.18687217 -0.07412284 0 0 Z ", fill: "#FDFDFD", transform: "translate(203.790771484375,152.77294921875)" }), jsx("path", { d: "M0 0 C47.52 0 95.04 0 144 0 C142.84140283 13.90316605 142.84140283 13.90316605 140.6875 20.3125 C140.48705078 20.96283203 140.28660156 21.61316406 140.08007812 22.28320312 C138.58431084 26.91869244 136.43289036 30.78177675 134 35 C121.42969934 35.09296032 108.85948139 35.16389686 96.2889061 35.20724869 C90.45094348 35.22806258 84.61321724 35.25626666 78.77539062 35.30175781 C73.1343582 35.34543695 67.49355217 35.36918365 61.85236359 35.37950897 C59.70752655 35.38686085 57.56270095 35.40121672 55.41796112 35.42292023 C38.21797933 35.58994386 24.82919001 34.23919899 11.77734375 21.8984375 C5.69643497 15.465177 1.74000471 8.70002355 0 0 Z ", fill: "#FDFDFD", transform: "translate(158,212)" }), jsx("path", { d: "M0 0 C47.52 0 95.04 0 144 0 C144 0.33 144 0.66 144 1 C143.27516733 1.00238835 142.55033466 1.00477671 141.80353737 1.00723743 C124.18601629 1.0663125 106.5686429 1.14181412 88.95127296 1.23571491 C80.43172058 1.28072596 71.91221049 1.32012822 63.39257812 1.34643555 C55.96891368 1.3693728 48.5453825 1.40272254 41.12182367 1.44870156 C37.1892239 1.47269179 33.25675658 1.49138239 29.32408524 1.49761391 C25.62550831 1.50363876 21.92727054 1.52354315 18.22881889 1.55427551 C16.21821404 1.56731688 14.2075301 1.56547871 12.19688416 1.5632782 C11.00773911 1.57581635 9.81859406 1.58835449 8.59341431 1.60127258 C7.55547541 1.60588155 6.51753651 1.61049051 5.44814491 1.61523914 C4.64025709 1.74221023 3.83236927 1.86918131 3 2 C2.01 3.485 2.01 3.485 1 5 C0.67 3.35 0.34 1.7 0 0 Z ", fill: "#DDDDDD", transform: "translate(158,212)" }), jsx("path", { d: "M0 0 C0.66 0.66 1.32 1.32 2 2 C-0.97 5.3 -3.94 8.6 -7 12 C-7.66 11.01 -8.32 10.02 -9 9 C-8.01 8.34 -7.02 7.68 -6 7 C-4.78715124 3.94570927 -4.78715124 3.94570927 -4 1 C-3.01 1 -2.02 1 -1 1 C-0.67 0.67 -0.34 0.34 0 0 Z ", fill: "#090909", transform: "translate(126,124)" }), jsx("path", { d: "M0 0 C-0.99 1.485 -0.99 1.485 -2 3 C-3.9453125 3.29296875 -3.9453125 3.29296875 -6.125 3.1875 C-7.40375 3.125625 -8.6825 3.06375 -10 3 C-10 2.01 -10 1.02 -10 0 C-2.25 -1.125 -2.25 -1.125 0 0 Z ", fill: "#121212", transform: "translate(182,75)" }), jsx("path", { d: "M0 0 C0.66 0.33 1.32 0.66 2 1 C0.515 2.485 0.515 2.485 -1 4 C-0.67 4.66 -0.34 5.32 0 6 C-2.31 5.67 -4.62 5.34 -7 5 C-2.25 1.125 -2.25 1.125 0 0 Z ", fill: "#181818", transform: "translate(171,136)" }), jsx("path", { d: "M0 0 C4 4.5 4 4.5 4 9 C3.34 8.67 2.68 8.34 2 8 C2 6.68 2 5.36 2 4 C0.68 3.34 -0.64 2.68 -2 2 C-1.34 2 -0.68 2 0 2 C0 1.34 0 0.68 0 0 Z ", fill: "#E6E6E6", transform: "translate(90,265)" }), jsx("path", { d: "M0 0 C-1.39332574 3.36720387 -2.9789286 4.9859524 -6 7 C-6.33 6.01 -6.66 5.02 -7 4 C-2.25 0 -2.25 0 0 0 Z ", fill: "#1A1A1A", transform: "translate(124,129)" })] }));
7336
- const Blast = ({ testnet, ...props }) => (jsxs("svg", { ...props, "aria-hidden": "true", width: "44", height: "44", viewBox: "0 0 128 128", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("path", { d: "M0 0 C42.24 0 84.48 0 128 0 C128 42.24 128 84.48 128 128 C85.76 128 43.52 128 0 128 C0 85.76 0 43.52 0 0 Z ", fill: "#FBFB02", transform: "translate(0,0)" }), jsx("path", { d: "M0 0 C1.29626816 -0.00432541 2.59253632 -0.00865082 3.92808533 -0.0131073 C6.65588944 -0.01887515 9.38206966 -0.00018386 12.10961914 0.03686523 C15.58233542 0.08239403 19.05191484 0.06972176 22.5246973 0.03905773 C25.87091674 0.01684949 29.21626874 0.04154386 32.5625 0.0625 C34.41440697 0.0489875 34.41440697 0.0489875 36.3037262 0.03520203 C44.24833063 0.18576309 49.15483387 1.67114298 55.21484375 6.89453125 C54.95700697 8.90565812 54.59904373 10.90367679 54.21484375 12.89453125 C54.10011719 13.61769531 53.98539062 14.34085938 53.8671875 15.0859375 C52.92855388 19.19506689 52.06398095 21.28119581 48.5703125 23.8046875 C45.82568204 25.29503241 43.08020729 26.65400884 40.21484375 27.89453125 C40.21484375 28.55453125 40.21484375 29.21453125 40.21484375 29.89453125 C42.17632249 31.28391202 44.17650951 32.62057235 46.21484375 33.89453125 C45.70230165 40.94198511 44.80867926 47.70762156 39.26782227 52.62109375 C28.09200342 59.30025375 15.01841579 57.53817431 2.46484375 57.26953125 C0.01435568 57.23939433 -2.43616809 57.21202513 -4.88671875 57.1875 C-10.85365094 57.12180305 -16.81923525 57.02175013 -22.78515625 56.89453125 C-15.80058377 33.54211776 -15.80058377 33.54211776 -13.03515625 24.70703125 C-12.74511719 23.75634766 -12.45507812 22.80566406 -12.15625 21.82617188 C-11.87394531 20.92705078 -11.59164062 20.02792969 -11.30078125 19.1015625 C-11.05618164 18.31241455 -10.81158203 17.5232666 -10.55957031 16.71020508 C-9.78515625 14.89453125 -9.78515625 14.89453125 -7.78515625 13.89453125 C-5.14515625 15.87453125 -2.50515625 17.85453125 0.21484375 19.89453125 C-1.81250285 28.89397227 -4.65412522 37.12764436 -7.78515625 45.89453125 C5.41484375 45.89453125 18.61484375 45.89453125 32.21484375 45.89453125 C33.69984375 40.44953125 33.69984375 40.44953125 35.21484375 34.89453125 C35.54484375 33.90453125 35.87484375 32.91453125 36.21484375 31.89453125 C26.97484375 31.89453125 17.73484375 31.89453125 8.21484375 31.89453125 C8.87484375 29.25453125 9.53484375 26.61453125 10.21484375 23.89453125 C19.78484375 23.89453125 29.35484375 23.89453125 39.21484375 23.89453125 C40.20484375 20.26453125 41.19484375 16.63453125 42.21484375 12.89453125 C19.11484375 12.56453125 -3.98515625 12.23453125 -27.78515625 11.89453125 C-18.85278804 2.96216304 -12.73867052 -0.17886377 0 0 Z ", fill: "#000000", transform: "translate(49.78515625,36.10546875)" })] }));
7329
+ // const Blast = ({ testnet, ...props }: { testnet?: boolean }) => (
7330
+ // <svg
7331
+ // {...props}
7332
+ // aria-hidden="true"
7333
+ // width="44"
7334
+ // height="44"
7335
+ // viewBox="0 0 128 128"
7336
+ // fill="none"
7337
+ // xmlns="http://www.w3.org/2000/svg"
7338
+ // >
7339
+ // <path
7340
+ // d="M0 0 C42.24 0 84.48 0 128 0 C128 42.24 128 84.48 128 128 C85.76 128 43.52 128 0 128 C0 85.76 0 43.52 0 0 Z "
7341
+ // fill="#FBFB02"
7342
+ // transform="translate(0,0)"
7343
+ // />
7344
+ // <path
7345
+ // d="M0 0 C1.29626816 -0.00432541 2.59253632 -0.00865082 3.92808533 -0.0131073 C6.65588944 -0.01887515 9.38206966 -0.00018386 12.10961914 0.03686523 C15.58233542 0.08239403 19.05191484 0.06972176 22.5246973 0.03905773 C25.87091674 0.01684949 29.21626874 0.04154386 32.5625 0.0625 C34.41440697 0.0489875 34.41440697 0.0489875 36.3037262 0.03520203 C44.24833063 0.18576309 49.15483387 1.67114298 55.21484375 6.89453125 C54.95700697 8.90565812 54.59904373 10.90367679 54.21484375 12.89453125 C54.10011719 13.61769531 53.98539062 14.34085938 53.8671875 15.0859375 C52.92855388 19.19506689 52.06398095 21.28119581 48.5703125 23.8046875 C45.82568204 25.29503241 43.08020729 26.65400884 40.21484375 27.89453125 C40.21484375 28.55453125 40.21484375 29.21453125 40.21484375 29.89453125 C42.17632249 31.28391202 44.17650951 32.62057235 46.21484375 33.89453125 C45.70230165 40.94198511 44.80867926 47.70762156 39.26782227 52.62109375 C28.09200342 59.30025375 15.01841579 57.53817431 2.46484375 57.26953125 C0.01435568 57.23939433 -2.43616809 57.21202513 -4.88671875 57.1875 C-10.85365094 57.12180305 -16.81923525 57.02175013 -22.78515625 56.89453125 C-15.80058377 33.54211776 -15.80058377 33.54211776 -13.03515625 24.70703125 C-12.74511719 23.75634766 -12.45507812 22.80566406 -12.15625 21.82617188 C-11.87394531 20.92705078 -11.59164062 20.02792969 -11.30078125 19.1015625 C-11.05618164 18.31241455 -10.81158203 17.5232666 -10.55957031 16.71020508 C-9.78515625 14.89453125 -9.78515625 14.89453125 -7.78515625 13.89453125 C-5.14515625 15.87453125 -2.50515625 17.85453125 0.21484375 19.89453125 C-1.81250285 28.89397227 -4.65412522 37.12764436 -7.78515625 45.89453125 C5.41484375 45.89453125 18.61484375 45.89453125 32.21484375 45.89453125 C33.69984375 40.44953125 33.69984375 40.44953125 35.21484375 34.89453125 C35.54484375 33.90453125 35.87484375 32.91453125 36.21484375 31.89453125 C26.97484375 31.89453125 17.73484375 31.89453125 8.21484375 31.89453125 C8.87484375 29.25453125 9.53484375 26.61453125 10.21484375 23.89453125 C19.78484375 23.89453125 29.35484375 23.89453125 39.21484375 23.89453125 C40.20484375 20.26453125 41.19484375 16.63453125 42.21484375 12.89453125 C19.11484375 12.56453125 -3.98515625 12.23453125 -27.78515625 11.89453125 C-18.85278804 2.96216304 -12.73867052 -0.17886377 0 0 Z "
7346
+ // fill="#000000"
7347
+ // transform="translate(49.78515625,36.10546875)"
7348
+ // />
7349
+ // </svg>
7350
+ // );
7337
7351
  const Mantle = ({ testnet, ...props }) => (jsxs("svg", { ...props, "aria-hidden": "true", width: "44", height: "44", viewBox: "0 0 311 311", xmlns: "http://www.w3.org/2000/svg", children: [jsx("style", { children: ".st0{fill:#fff}" }), jsx("path", { d: "M0 0h314v311H0z" }), jsx("path", { d: "M155.5 289.1v-45.7c-4.6 0-9.3-.4-13.9-1.1l-7.2 45.1c7 1.2 14.1 1.7 21.1 1.7zm21-1.6c7-1.1 13.9-2.7 20.6-4.9L183 239.1c-4.4 1.4-9 2.5-13.6 3.2l7.1 45.2zm-62.6-4.9 14.1-43.4c-4.4-1.4-8.7-3.2-12.9-5.3l-20.8 40.7c6.3 3.1 12.9 5.8 19.6 8zm102.7-8c6.3-3.2 12.3-6.9 18-11l-27-36.9c-3.7 2.7-7.7 5.2-11.9 7.2l20.9 40.7zM76.3 263.5l27-36.9c-3.7-2.7-7.3-5.7-10.6-9l-32.4 32.3c5 4.9 10.4 9.5 16 13.6zm174.2-13.4.3-.3c5-4.9 9.6-10.3 13.7-15.9l-37-26.9c-2.7 3.7-5.8 7.3-9 10.5l-.5.5 15.6 14.7 16.9 17.4zM46.6 233.8l37-26.9c-2.7-3.7-5.2-7.7-7.3-11.8l-40.8 20.7c3.2 6.3 6.9 12.3 11.1 18zm228.9-17.9c3.2-6.2 5.9-12.8 8.1-19.5l-43.6-14c-1.4 4.4-3.2 8.7-5.3 12.8l40.8 20.7zM27.4 196.4 71 182.3c-1.4-4.4-2.5-8.9-3.2-13.5l-45.3 7.1c1.1 6.9 2.8 13.8 4.9 20.5zM288.5 176c1.1-6.9 1.7-14 1.7-21h-45.8c0 4.6-.4 9.3-1.1 13.9l45.2 7.1zM66.7 154.9c0-4.6.4-9.3 1.1-13.9l-45.3-7.1c-1.1 6.9-1.6 14-1.7 21h45.9zm176.6-13.8 45.3-7.1c-1.1-6.9-2.7-13.8-4.9-20.5l-43.6 14c1.4 4.5 2.5 9 3.2 13.6zM71 127.5c1.4-4.4 3.2-8.7 5.3-12.8L35.5 94c-3.2 6.2-5.9 12.8-8.1 19.5l43.6 14zm163.8-12.7 40.9-20.7c-3.2-6.3-6.9-12.3-11.1-18L227.5 103c2.7 3.7 5.2 7.7 7.3 11.8zM83.6 102.9c2.7-3.7 5.8-7.3 9.1-10.6l.1-.1-32.4-32.3-.1.1c-5 5-9.6 10.3-13.7 16l37 26.9zm134.9-10.4 9.8-9.9 22.5-22.4-.1-.1c-5-4.9-10.3-9.5-15.9-13.6l-27 36.9c3.7 2.7 7.3 5.7 10.5 9l.2.1zm-115.1-9.3c3.7-2.7 7.7-5.1 11.9-7.2L94.5 35.3c-6.3 3.2-12.3 6.9-18 11l26.9 36.9zm92.6-7.1 20.9-40.7c-6.3-3.2-12.8-5.9-19.5-8.1l-14.2 43.4c4.3 1.5 8.6 3.3 12.8 5.4zm-67.8-5.4c4.4-1.4 9-2.5 13.6-3.2l-7.1-45.1c-6.9 1.1-13.9 2.7-20.6 4.9l14.1 43.4zm41.3-3.2 7.2-45.1c-6.9-1.1-14-1.7-21-1.7v45.7c4.6 0 9.3.4 13.8 1.1z", className: "st0" }), jsx("path", { d: "M155.5 245.5v-45.9c-3.9 0-7.7-.5-11.5-1.5l-12 44.3c7.7 2 15.6 3.1 23.5 3.1zm23.5-3.1c7.7-2 15-5 21.9-9l-23.2-39.7c-3.3 1.9-6.9 3.4-10.6 4.4l11.9 44.3zm-68.8-9 23.2-39.7c-3.3-1.9-6.4-4.3-9.2-7l-.4-.4-14.6 15.3-18 17.3.3.3c5.6 5.5 11.9 10.3 18.7 14.2zm109.4-14.2c5.6-5.6 10.5-11.8 14.4-18.6l-40.1-23c-1.9 3.3-4.3 6.3-7.1 9.1l32.8 32.5zM77 200.5l40.1-22.9c-1.9-3.3-3.4-6.8-4.4-10.5L68 178.9c2 7.5 5.1 14.8 9 21.6zM243.1 179c2-7.6 3.1-15.4 3.1-23.2h-46.3c0 3.8-.5 7.7-1.5 11.4l44.7 11.8zm-131.8-23.3c0-3.8.5-7.7 1.5-11.4L68 132.5c-2 7.6-3.1 15.4-3.1 23.2h46.4zm87-11.3 44.8-11.8c-2-7.6-5.1-14.9-9-21.7L194 133.8c1.8 3.4 3.3 6.9 4.3 10.6zm-81.1-10.6c1.9-3.2 4.2-6.3 7-9l.1-.1-16.6-16.4L91.8 92l-.3.3c-5.6 5.5-10.4 11.8-14.4 18.5l40.1 23zm-9.5-25.5.2.2-.2-.2zm79.1 16.5 16.4-16.3L220 92.7l-.4-.4C214 86.7 207.7 82 200.9 78l-23.2 39.7c3.3 1.9 6.3 4.2 9.1 6.9v.2zm-53.4-7.1c3.3-1.9 6.9-3.4 10.6-4.4L132.2 69c-7.7 2-15 5-21.9 9l23.1 39.7zm33.6-4.3 12-44.3c-7.6-2-15.5-3.1-23.4-3.1v45.9c3.8 0 7.7.5 11.4 1.5z", className: "st0" })] }));
7338
7352
  const chainToLogo = {
7339
7353
  [arbitrum$1.chainId]: jsx(Arbitrum, {}),
7340
7354
  [base$2.chainId]: jsx(Base, {}),
7341
- [blast$1.chainId]: jsx(Blast, {}),
7355
+ // [blast.chainId]: <Blast />,
7342
7356
  [bsc$1.chainId]: jsx(BinanceSmartChain, {}),
7343
7357
  [ethereum.chainId]: jsx(Ethereum, {}),
7344
7358
  [linea$1.chainId]: jsx(Linea, {}),
@@ -7676,7 +7690,7 @@ const QRPlaceholder = styled(motion.div) `
7676
7690
  content: "";
7677
7691
  position: absolute;
7678
7692
  inset: 0;
7679
- transform: scale(1.5) rotate(45deg);
7693
+ transform: scale(1.7) rotate(45deg);
7680
7694
  background-image: linear-gradient(
7681
7695
  90deg,
7682
7696
  rgba(255, 255, 255, 0) 50%,
@@ -7719,16 +7733,6 @@ const LogoIcon = styled(motion.div) `
7719
7733
  : css `
7720
7734
  width: 28%;
7721
7735
  height: 28%;
7722
- border-radius: 17px;
7723
- &:before {
7724
- pointer-events: none;
7725
- z-index: 2;
7726
- content: "";
7727
- position: absolute;
7728
- inset: 0;
7729
- border-radius: inherit;
7730
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.02);
7731
- }
7732
7736
  `}
7733
7737
  `;
7734
7738
 
@@ -8013,6 +8017,7 @@ const WalletItem = styled.button `
8013
8017
  text-align: center;
8014
8018
  transition: opacity 100ms ease;
8015
8019
  opacity: ${(props) => (props.$waiting ? 0.4 : 1)};
8020
+ background: transparent;
8016
8021
  `;
8017
8022
  const WalletIcon = styled.div `
8018
8023
  z-index: 9;
@@ -10250,9 +10255,10 @@ const SelectDepositAddressAmount = () => {
10250
10255
  const { paymentState, setRoute, triggerResize } = usePayContext();
10251
10256
  const { selectedDepositAddressOption } = paymentState;
10252
10257
  const maxUsdLimit = paymentState.getOrderUsdLimit();
10253
- // const minimumMessage = `Minimum ${formatUsd(MIN_USD_VALUE, "up")}`;
10258
+ const minUsd = selectedDepositAddressOption?.minimumUsd ?? 0;
10259
+ const minimumMessage = `Minimum ${formatUsd(minUsd, "up")}`;
10254
10260
  const [usdInput, setUsdInput] = useState("");
10255
- const [message, setMessage] = useState("");
10261
+ const [message, setMessage] = useState(minimumMessage);
10256
10262
  const [continueDisabled, setContinueDisabled] = useState(true);
10257
10263
  useEffect(() => {
10258
10264
  triggerResize();
@@ -10269,7 +10275,7 @@ const SelectDepositAddressAmount = () => {
10269
10275
  setMessage(`Maximum ${formatUsd(maxUsdLimit)}`);
10270
10276
  }
10271
10277
  else {
10272
- setMessage("");
10278
+ setMessage(minimumMessage);
10273
10279
  }
10274
10280
  const usd = Number(sanitizeNumber(value));
10275
10281
  setContinueDisabled(usd <= 0 || usd > maxUsdLimit);
@@ -10592,6 +10598,8 @@ function SelectAnotherMethodButton() {
10592
10598
 
10593
10599
  const SelectDepositAddressChain = () => {
10594
10600
  const { setRoute, paymentState } = usePayContext();
10601
+ const pay = useDaimoPay();
10602
+ const { order } = pay;
10595
10603
  const { isDepositFlow, setSelectedDepositAddressOption, depositAddressOptions, } = paymentState;
10596
10604
  return (jsxs(PageContent, { children: [jsx(OrderHeader, { minified: true }), !depositAddressOptions.loading &&
10597
10605
  depositAddressOptions.options?.length === 0 && (jsxs(ModalContent, { style: {
@@ -10605,6 +10613,9 @@ const SelectDepositAddressChain = () => {
10605
10613
  id: option.id,
10606
10614
  title: option.id,
10607
10615
  icons: [option.logoURI],
10616
+ disabled: option.minimumUsd > 0 &&
10617
+ order?.mode === DaimoPayOrderMode.HYDRATED &&
10618
+ order.usdValue < option.minimumUsd,
10608
10619
  onClick: () => {
10609
10620
  setSelectedDepositAddressOption(option);
10610
10621
  const meta = { event: "click-option", option: option.id };
@@ -10812,6 +10823,8 @@ function SelectMethod() {
10812
10823
  },
10813
10824
  });
10814
10825
  }
10826
+ // Order disabled to bottom
10827
+ options.sort((a, b) => (a.disabled ? 1 : 0) - (b.disabled ? 1 : 0));
10815
10828
  return (jsxs(PageContent, { children: [jsx(OrderHeader, {}), jsx(OptionsList, { requiredSkeletons: isMobile ? 4 : 3, isLoading: externalPaymentOptions.loading, options: externalPaymentOptions.loading ? [] : options }), jsx(PoweredByFooter, {})] }));
10816
10829
  }
10817
10830
  // Get 3 icons, skipping the one that is already connected
@@ -10869,21 +10882,53 @@ function getDepositAddressOption(setRoute) {
10869
10882
  };
10870
10883
  }
10871
10884
 
10872
- const TokenChainLogo = ({ token }) => {
10873
- return (jsxs(TokenChainContainer, { children: [jsx("img", { src: token.logoURI, alt: token.symbol, style: { borderRadius: 9999 } }), jsx(ChainContainer$1, { children: chainToLogo[token.chainId] })] }));
10885
+ const TokenChainLogo = ({ token, size = 32, offset = 0, }) => {
10886
+ const chainLogoSize = Math.round((size * 30) / 64);
10887
+ return (jsxs(TokenChainContainer, { "$size": size, children: [jsx(TokenImage, { src: token.logoURI, alt: token.symbol, "$size": size }), jsx(ChainContainer$1, { "$size": chainLogoSize, "$offset": offset, children: chainToLogo[token.chainId] })] }));
10874
10888
  };
10875
10889
  const TokenChainContainer = styled(motion.div) `
10876
- width: 100%;
10877
- height: 100%;
10890
+ position: relative;
10891
+ width: ${(props) => props.$size}px;
10892
+ height: ${(props) => props.$size}px;
10893
+ display: flex;
10894
+ align-items: center;
10895
+ justify-content: center;
10896
+ `;
10897
+ const TokenImage = styled.img `
10898
+ width: ${(props) => props.$size}px;
10899
+ height: ${(props) => props.$size}px;
10900
+ border-radius: 50%;
10901
+ object-fit: cover;
10902
+ transition: transform 0.2s ease;
10903
+
10904
+ ${(props) => props.$showBorder &&
10905
+ `
10906
+ border: 2px solid var(--ck-body-background, #fff);
10907
+ `}
10878
10908
  `;
10879
10909
  const ChainContainer$1 = styled(motion.div) `
10880
10910
  position: absolute;
10881
- width: 16px;
10882
- height: 16px;
10883
- border-radius: 9999px;
10884
- overflow: hidden;
10911
+ width: ${(props) => props.$size}px;
10912
+ height: ${(props) => props.$size}px;
10913
+ min-width: ${(props) => props.$size}px;
10914
+ min-height: ${(props) => props.$size}px;
10885
10915
  bottom: 0px;
10886
- right: 0px;
10916
+ right: ${(props) => props.$offset}px;
10917
+ border-radius: 50%;
10918
+ aspect-ratio: 1 / 1;
10919
+ overflow: hidden;
10920
+ background: ${(props) => props.$showBorder ? "var(--ck-body-background, #fff)" : "transparent"};
10921
+ display: flex;
10922
+ align-items: center;
10923
+ justify-content: center;
10924
+ flex-shrink: 0;
10925
+
10926
+ svg {
10927
+ width: 100%;
10928
+ height: 100%;
10929
+ border-radius: 50%;
10930
+ flex-shrink: 0;
10931
+ }
10887
10932
  `;
10888
10933
 
10889
10934
  /// and Solana tokens. See OptionsList.
@@ -11281,7 +11326,8 @@ const CircleTimer = ({ total, size = 24, stroke = 3, currentTime, onTimeChange,
11281
11326
  return () => clearInterval(id);
11282
11327
  }, [target, onTimeChange]);
11283
11328
  const ratio = Math.round((left * 100) / total); // 0-100
11284
- const radius = Math.round((size - stroke) / 2); // integer radius
11329
+ // Ensure stroke stays within viewBox: use floor to be conservative
11330
+ const radius = Math.floor((size - stroke) / 2);
11285
11331
  const circumference = Math.round((2 * 314 * radius) / 100); // 2πr, π≈3.14
11286
11332
  const dashoffset = Math.round((circumference * (100 - ratio)) / 100);
11287
11333
  // colour transition: green → orange → red
@@ -11304,47 +11350,132 @@ function WaitingDepositAddress() {
11304
11350
  const context = usePayContext();
11305
11351
  const { triggerResize, paymentState } = context;
11306
11352
  const { payWithDepositAddress, selectedDepositAddressOption } = paymentState;
11307
- const [details, setDetails] = useState();
11353
+ const { order } = useDaimoPay();
11354
+ const [depAddr, setDepAddr] = useState();
11308
11355
  const [failed, setFailed] = useState(false);
11356
+ // If we selected a deposit address option, generate the address...
11309
11357
  const generateDepositAddress = () => {
11310
- if (!selectedDepositAddressOption)
11311
- return;
11312
- payWithDepositAddress(selectedDepositAddressOption.id).then((details) => {
11313
- if (!details)
11314
- setFailed(true);
11315
- else
11316
- setDetails(details);
11317
- });
11358
+ if (selectedDepositAddressOption == null) {
11359
+ if (order == null || !isHydrated(order))
11360
+ return;
11361
+ if (order.sourceTokenAmount == null)
11362
+ return;
11363
+ // Pay underpaid order
11364
+ const taPaid = order.sourceTokenAmount;
11365
+ const usdPaid = taPaid.usd; // TODO: get usdPaid directly from the order
11366
+ const usdToPay = Math.max(order.usdValue - usdPaid, 0.01);
11367
+ const dispDecimals = taPaid.token.displayDecimals;
11368
+ const unitsToPay = (usdToPay / taPaid.token.usd).toFixed(dispDecimals);
11369
+ const unitsPaid = (Number(taPaid.amount) /
11370
+ 10 ** taPaid.token.decimals).toFixed(dispDecimals);
11371
+ // Hack to always show a <= 60 minute countdown
11372
+ let expirationS = (order.createdAt ?? 0) + 59.5 * 60;
11373
+ if (order.expirationTs != null &&
11374
+ Number(order.expirationTs) < expirationS) {
11375
+ expirationS = Number(order.expirationTs);
11376
+ }
11377
+ setDepAddr({
11378
+ address: order.intentAddr,
11379
+ amount: unitsToPay,
11380
+ underpayment: { unitsPaid, coin: taPaid.token.symbol },
11381
+ coins: `${taPaid.token.symbol} on ${getChainName(taPaid.token.chainId)}`,
11382
+ expirationS: expirationS,
11383
+ uri: order.intentAddr,
11384
+ displayToken: taPaid.token,
11385
+ logoURI: "", // Not needed for underpaid orders
11386
+ });
11387
+ }
11388
+ else {
11389
+ payWithDepositAddress(selectedDepositAddressOption.id).then((details) => {
11390
+ if (details) {
11391
+ setDepAddr({
11392
+ address: details.address,
11393
+ amount: details.amount,
11394
+ coins: details.suffix,
11395
+ expirationS: details.expirationS,
11396
+ uri: details.uri,
11397
+ displayToken: getDisplayToken(selectedDepositAddressOption),
11398
+ logoURI: selectedDepositAddressOption.logoURI,
11399
+ });
11400
+ }
11401
+ else {
11402
+ setFailed(true);
11403
+ }
11404
+ });
11405
+ }
11318
11406
  };
11319
- // TODO: load payment status, show underpayment
11320
11407
  // eslint-disable-next-line react-hooks/exhaustive-deps
11321
11408
  useEffect(generateDepositAddress, [selectedDepositAddressOption]);
11322
11409
  // eslint-disable-next-line react-hooks/exhaustive-deps
11323
- useEffect(triggerResize, [details]);
11324
- return (jsx(PageContent, { children: selectedDepositAddressOption == null ? null : failed ? (jsx(DepositFailed, { meta: selectedDepositAddressOption })) : (jsx(DepositAddressInfo, { meta: selectedDepositAddressOption, details: details, refresh: generateDepositAddress })) }));
11410
+ useEffect(triggerResize, [depAddr, failed]);
11411
+ return (jsx(PageContent, { children: failed ? (selectedDepositAddressOption && (jsx(DepositFailed, { name: selectedDepositAddressOption.id }))) : (jsx(DepositAddressInfo, { depAddr: depAddr, refresh: generateDepositAddress, triggerResize: triggerResize })) }));
11325
11412
  }
11326
- function DepositAddressInfo({ meta, details, refresh, }) {
11413
+ function DepositAddressInfo({ depAddr, refresh, triggerResize, }) {
11327
11414
  const { isMobile } = useIsMobile();
11328
- const [remainingS, totalS] = useCountdown(details?.expirationS);
11329
- const isExpired = details?.expirationS != null && remainingS === 0;
11330
- return (jsxs(ModalContent, { children: [isExpired ? (jsx(LogoWrap, { children: jsx(Button, { onClick: refresh, style: { width: 128 }, children: "Refresh" }) })) : isMobile ? (jsx(LogoWrap, { children: jsx("img", { src: meta.logoURI, width: "64px", height: "64px" }) })) : (jsx(QRWrap, { children: jsx(CustomQRCode, { value: details?.uri, contentPadding: 24, size: 200, image: jsx("img", { src: meta.logoURI, width: "100%", height: "100%" }) }) })), jsx(CopyableInfo, { meta: meta, details: details, remainingS: remainingS, totalS: totalS })] }));
11415
+ const [remainingS, totalS] = useCountdown(depAddr?.expirationS);
11416
+ const isExpired = depAddr?.expirationS != null && remainingS === 0;
11417
+ // eslint-disable-next-line react-hooks/exhaustive-deps
11418
+ useEffect(triggerResize, [isExpired]);
11419
+ const logoOffset = isMobile ? 4 : 0;
11420
+ const logoElement = depAddr?.displayToken ? (jsx(TokenChainLogo, { token: depAddr.displayToken, size: 64, offset: logoOffset })) : (jsx("img", { src: depAddr?.logoURI, width: "64px", height: "64px" }));
11421
+ return (jsxs(ModalContent, { children: [isExpired ? (jsx(LogoRow, { children: jsx(Button, { onClick: refresh, style: { width: 128 }, children: "Refresh" }) })) : isMobile ? (jsx(LogoRow, { children: jsx(LogoWrap, { children: logoElement }) })) : (jsx(QRWrap, { children: jsx(CustomQRCode, { value: depAddr?.uri, contentPadding: 24, size: 200, image: logoElement }) })), jsx(CopyableInfo, { depAddr: depAddr, remainingS: remainingS, totalS: totalS })] }));
11422
+ }
11423
+ function getDisplayToken(meta) {
11424
+ switch (meta.id) {
11425
+ case DepositAddressPaymentOptions.OP_MAINNET:
11426
+ return optimismUSDC;
11427
+ case DepositAddressPaymentOptions.ARBITRUM:
11428
+ return arbitrumUSDC;
11429
+ case DepositAddressPaymentOptions.BASE:
11430
+ return baseUSDC;
11431
+ case DepositAddressPaymentOptions.POLYGON:
11432
+ return polygonUSDC;
11433
+ case DepositAddressPaymentOptions.ETH_L1:
11434
+ return ethereumUSDC;
11435
+ default:
11436
+ return null;
11437
+ }
11331
11438
  }
11332
11439
  const LogoWrap = styled.div `
11440
+ position: relative;
11441
+ width: 64px;
11442
+ height: 64px;
11443
+ `;
11444
+ const LogoRow = styled.div `
11333
11445
  padding: 32px 0;
11334
11446
  height: 128px;
11335
11447
  display: flex;
11336
11448
  align-items: center;
11449
+ gap: 8px;
11337
11450
  justify-content: center;
11338
11451
  `;
11339
11452
  const QRWrap = styled.div `
11340
11453
  margin: 0 auto;
11341
11454
  width: 280px;
11342
11455
  `;
11343
- function CopyableInfo({ meta, details, remainingS, totalS, }) {
11344
- const currencies = details?.suffix;
11345
- const isExpired = details?.expirationS != null && remainingS === 0;
11346
- return (jsxs(CopyableInfoWrapper, { children: [jsx(CopyRowOrThrobber, { title: "Send Exactly", value: details?.amount, smallText: currencies, disabled: isExpired }), jsx(CopyRowOrThrobber, { title: "Receiving Address", value: details?.address, valueText: details && getAddressContraction(details.address), disabled: isExpired }), jsx(CountdownWrap, { children: jsx(CountdownTimer, { remainingS: remainingS, totalS: totalS }) })] }));
11456
+ function CopyableInfo({ depAddr, remainingS, totalS, }) {
11457
+ const underpayment = depAddr?.underpayment;
11458
+ const isExpired = depAddr?.expirationS != null && remainingS === 0;
11459
+ return (jsxs(CopyableInfoWrapper, { children: [underpayment && jsx(UnderpaymentInfo, { underpayment: underpayment }), jsx(CopyRowOrThrobber, { title: "Send Exactly", value: depAddr?.amount, smallText: depAddr?.coins, disabled: isExpired }), jsx(CopyRowOrThrobber, { title: "Receiving Address", value: depAddr?.address, valueText: depAddr?.address && getAddressContraction(depAddr.address), disabled: isExpired }), jsx(CountdownWrap, { children: jsx(CountdownTimer, { remainingS: remainingS, totalS: totalS }) })] }));
11347
11460
  }
11461
+ function UnderpaymentInfo({ underpayment }) {
11462
+ return (jsxs(UnderpaymentWrapper, { children: [jsxs(UnderpaymentHeader, { children: [jsx(WarningIcon, {}), jsxs("span", { children: ["Received ", underpayment.unitsPaid, " ", underpayment.coin] })] }), jsx(SmallText, { children: "Finish by sending the extra amount below." })] }));
11463
+ }
11464
+ const UnderpaymentWrapper = styled.div `
11465
+ background: var(--ck-body-background-tertiary);
11466
+ border-radius: 8px;
11467
+ padding: 16px;
11468
+ margin: 0 4px 16px 4px;
11469
+ margin-bottom: 16px;
11470
+ `;
11471
+ const UnderpaymentHeader = styled.div `
11472
+ font-weight: 500;
11473
+ display: flex;
11474
+ justify-content: center;
11475
+ align-items: flex-end;
11476
+ gap: 8px;
11477
+ margin-bottom: 8px;
11478
+ `;
11348
11479
  const CopyableInfoWrapper = styled.div `
11349
11480
  display: flex;
11350
11481
  flex-direction: column;
@@ -11370,10 +11501,9 @@ function useCountdown(expirationS) {
11370
11501
  return [remainingS, totalS];
11371
11502
  }
11372
11503
  function CountdownTimer({ remainingS, totalS, }) {
11373
- if (totalS == 0)
11374
- return null;
11375
- if (remainingS > 3600)
11376
- return null;
11504
+ if (totalS == 0 || remainingS > 3600) {
11505
+ return jsx(SmallText, { children: "Send only once" });
11506
+ }
11377
11507
  const isExpired = remainingS === 0;
11378
11508
  return (jsx(ModalBody, { children: jsxs(CountdownRow, { children: [jsx(CircleTimer, { total: totalS, currentTime: remainingS, size: 18, stroke: 3 }), jsx("strong", { children: isExpired ? "Expired" : formatTime(remainingS) })] }) }));
11379
11509
  }
@@ -11389,8 +11519,8 @@ const formatTime = (sec) => {
11389
11519
  const s = `${sec % 60}`.padStart(2, "0");
11390
11520
  return `${m}:${s}`;
11391
11521
  };
11392
- function DepositFailed({ meta, }) {
11393
- return (jsxs(ModalContent, { style: { marginLeft: 24, marginRight: 24 }, children: [jsxs(ModalH1, { children: [meta.id, " unavailable"] }), jsxs(ModalBody, { children: ["We're unable to process ", meta.id, " payments at this time. Please select another payment method."] }), jsx(SelectAnotherMethodButton, {})] }));
11522
+ function DepositFailed({ name }) {
11523
+ return (jsxs(ModalContent, { style: { marginLeft: 24, marginRight: 24 }, children: [jsxs(ModalH1, { children: [name, " unavailable"] }), jsxs(ModalBody, { children: ["We're unable to process ", name, " payments at this time. Please select another payment method."] }), jsx(SelectAnotherMethodButton, {})] }));
11394
11524
  }
11395
11525
  const CopyRow = styled.button `
11396
11526
  display: block;
@@ -11399,6 +11529,7 @@ const CopyRow = styled.button `
11399
11529
  padding: 8px 16px;
11400
11530
 
11401
11531
  cursor: pointer;
11532
+ background-color: var(--ck-body-background);
11402
11533
 
11403
11534
  display: flex;
11404
11535
  align-items: center;
@@ -11437,7 +11568,16 @@ const ValueContainer = styled.div `
11437
11568
  `;
11438
11569
  const SmallText = styled.span `
11439
11570
  font-size: 14px;
11440
- color: var(--ck-body-color-muted);
11571
+ color: var(--ck-primary-button-color);
11572
+ `;
11573
+ const ValueText = styled.span `
11574
+ font-size: 14px;
11575
+ font-weight: 600;
11576
+ color: var(--ck-primary-button-color);
11577
+ `;
11578
+ const LabelText = styled(ModalBody) `
11579
+ margin: 0;
11580
+ text-align: left;
11441
11581
  `;
11442
11582
  const pulse = keyframes `
11443
11583
  0% {
@@ -11472,10 +11612,10 @@ function CopyRowOrThrobber({ title, value, valueText, smallText, disabled, }) {
11472
11612
  setTimeout(() => setCopied(false), 1000);
11473
11613
  };
11474
11614
  if (!value) {
11475
- return (jsxs(CopyRow, { children: [jsx(LabelRow, { children: jsx(ModalBody, { style: { margin: 0, textAlign: "left" }, children: title }) }), jsx(MainRow, { children: jsx(Skeleton, {}) })] }));
11615
+ return (jsxs(CopyRow, { children: [jsx(LabelRow, { children: jsx(LabelText, { children: title }) }), jsx(MainRow, { children: jsx(Skeleton, {}) })] }));
11476
11616
  }
11477
11617
  const displayValue = valueText || value;
11478
- return (jsxs(CopyRow, { as: "button", onClick: handleCopy, disabled: disabled, children: [jsxs("div", { children: [jsx(LabelRow, { children: jsx(ModalBody, { style: { margin: 0, textAlign: "left" }, children: title }) }), jsx(MainRow, { children: jsxs(ValueContainer, { children: [jsx("span", { style: { fontWeight: 600 }, children: displayValue }), smallText && jsx(SmallText, { children: smallText })] }) })] }), jsx(CopyIconWrap, { children: jsx(CopyToClipboardIcon, { copied: copied, dark: true }) })] }));
11618
+ return (jsxs(CopyRow, { as: "button", onClick: handleCopy, disabled: disabled, children: [jsxs("div", { children: [jsx(LabelRow, { children: jsx(LabelText, { children: title }) }), jsx(MainRow, { children: jsxs(ValueContainer, { children: [jsx(ValueText, { children: displayValue }), smallText && jsx(SmallText, { children: smallText })] }) })] }), jsx(CopyIconWrap, { children: jsx(CopyToClipboardIcon, { copied: copied, dark: true }) })] }));
11479
11619
  }
11480
11620
  const CopyIconWrap = styled.div `
11481
11621
  --color: var(--ck-copytoclipboard-stroke);
@@ -11893,7 +12033,8 @@ function useDepositAddressOptions({ trpc, usdRequired, mode, }) {
11893
12033
  const DEFAULT_EXTERNAL_PAYMENT_OPTIONS = Object.values(ExternalPaymentOptions).filter((opt) =>
11894
12034
  // Solana and ExternalChains are handled in the SelectMethod component.
11895
12035
  opt !== ExternalPaymentOptions.Solana &&
11896
- opt !== ExternalPaymentOptions.ExternalChains);
12036
+ opt !== ExternalPaymentOptions.ExternalChains &&
12037
+ opt !== ExternalPaymentOptions.Daimo);
11897
12038
  function useExternalPaymentOptions({ trpc, filterIds, platform, usdRequired, mode, }) {
11898
12039
  const [options, setOptions] = useState(new Map());
11899
12040
  const [loading, setLoading] = useState(false);
@@ -12657,13 +12798,22 @@ const DaimoPayUIProvider = ({ children, theme = "auto", mode = "auto", customThe
12657
12798
  }
12658
12799
  };
12659
12800
  // Watch when the order gets paid and navigate to confirmation
12801
+ // ...if underpaid, go to the deposit addr screen, let the user finish paying.
12802
+ const isUnderpaid = pay.order?.mode === DaimoPayOrderMode.HYDRATED &&
12803
+ pay.order.sourceStatus === DaimoPayOrderStatusSource.WAITING_PAYMENT &&
12804
+ pay.order.sourceTokenAmount != null;
12660
12805
  useEffect(() => {
12661
12806
  if (pay.paymentState === "payment_started" ||
12662
12807
  pay.paymentState === "payment_completed" ||
12663
12808
  pay.paymentState === "payment_bounced") {
12664
12809
  setRoute(ROUTES.CONFIRMATION, { event: "payment-started" });
12665
12810
  }
12666
- }, [pay.paymentState, setRoute]);
12811
+ else if (isUnderpaid) {
12812
+ paymentState.setSelectedDepositAddressOption(undefined);
12813
+ setRoute(ROUTES.WAITING_DEPOSIT_ADDRESS);
12814
+ }
12815
+ // eslint-disable-next-line react-hooks/exhaustive-deps
12816
+ }, [pay.paymentState, setRoute, isUnderpaid]);
12667
12817
  const value = {
12668
12818
  theme: ckTheme,
12669
12819
  setTheme,