@b3dotfun/sdk 0.0.33-alpha.5 → 0.0.33-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ import { components } from "../../../../anyspend/types/api";
2
+ interface InsufficientDepositPaymentProps {
3
+ order: components["schemas"]["Order"];
4
+ srcToken: components["schemas"]["Token"];
5
+ depositDeficit: bigint;
6
+ phantomWalletAddress: string | null;
7
+ txLoading: boolean;
8
+ isSwitchingOrExecuting: boolean;
9
+ onPayment: () => Promise<void>;
10
+ }
11
+ export declare function InsufficientDepositPayment({ order, srcToken, depositDeficit, phantomWalletAddress, txLoading, isSwitchingOrExecuting, onPayment, }: InsufficientDepositPaymentProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ "use client";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.InsufficientDepositPayment = InsufficientDepositPayment;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const anyspend_1 = require("../../../../anyspend");
7
+ const react_1 = require("../../../../global-account/react");
8
+ const utils_1 = require("../../../../shared/utils");
9
+ const chains_1 = require("viem/chains");
10
+ const number_1 = require("../../../../shared/utils/number");
11
+ const react_2 = require("@web3icons/react");
12
+ const lucide_react_1 = require("lucide-react");
13
+ const react_3 = require("motion/react");
14
+ const qrcode_react_1 = require("qrcode.react");
15
+ const sonner_1 = require("sonner");
16
+ function InsufficientDepositPayment({ order, srcToken, depositDeficit, phantomWalletAddress, txLoading, isSwitchingOrExecuting, onPayment, }) {
17
+ const depositDeficitAmount = (0, number_1.formatUnits)(depositDeficit.toString(), srcToken.decimals);
18
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "insufficient-deposit-payment relative flex w-full flex-1 flex-col", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1", children: [(0, jsx_runtime_1.jsx)("span", { className: "insufficient-deposit-payment-text text-as-primary/50", children: "Please send remaining" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex w-full flex-wrap items-center gap-6 sm:justify-between sm:gap-0", children: [(0, jsx_runtime_1.jsx)(react_1.CopyToClipboard, { text: depositDeficitAmount, onCopy: () => {
19
+ sonner_1.toast.success("Copied to clipboard");
20
+ }, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("strong", { className: "border-as-brand text-as-primary border-b-2 pb-1 text-2xl font-semibold sm:text-xl", children: [depositDeficitAmount, " ", srcToken.symbol] }), (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "text-as-primary/50 hover:text-as-primary h-5 w-5 cursor-pointer transition-all duration-200" })] }) }), (0, jsx_runtime_1.jsxs)(react_1.Badge, { variant: "outline", className: "flex h-10 items-center gap-2 px-3 py-1 pr-2 text-sm", children: ["on ", (0, anyspend_1.getChainName)(order.srcChain), (0, jsx_runtime_1.jsx)("img", { src: anyspend_1.ALL_CHAINS[order.srcChain].logoUrl, alt: (0, anyspend_1.getChainName)(order.srcChain), className: (0, utils_1.cn)("h-6 rounded-full", order.srcChain === chains_1.b3.id && "h-5 rounded-none") })] })] }), (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/50 mb-1 mt-2", children: " to the address:" })] }), (0, jsx_runtime_1.jsx)(react_1.CopyToClipboard, { text: order.globalAddress, onCopy: () => {
21
+ sonner_1.toast.success("Copied to clipboard");
22
+ }, children: (0, jsx_runtime_1.jsxs)("div", { className: "payment-address bg-b3-react-background border-b3-react-border hover:border-as-brand group flex cursor-pointer items-center justify-between gap-4 rounded-lg border p-3 px-4 shadow-md transition-all duration-200", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-sm", children: order.globalAddress }), (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "group-hover:text-as-brand text-as-primary/50 h-5 w-5 cursor-pointer transition-all duration-200" })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "payment-buttons mt-4 flex w-full flex-col items-center gap-2", children: [(0, jsx_runtime_1.jsx)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-5/6 max-w-[400px] items-center gap-2 sm:px-0", disabled: txLoading || isSwitchingOrExecuting, onClick: onPayment, children: txLoading ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Transaction Pending", (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "ml-2 h-5 w-5 animate-spin" })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: "whitespace-nowrap pl-4 text-lg md:text-sm", children: order.srcChain === anyspend_1.RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
23
+ ? "Pay from Phantom Wallet"
24
+ : "Pay from Connected Wallet" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] })) }), (0, jsx_runtime_1.jsx)("div", { children: "Or" }), (0, jsx_runtime_1.jsx)(react_3.motion.div, { initial: { opacity: 0, filter: "blur(10px)" }, animate: { opacity: 1, filter: "blur(0px)" }, transition: { duration: 0.5, ease: "easeInOut" }, className: "flex w-full items-center justify-evenly gap-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "qr-code flex flex-col items-center rounded-lg pb-3", children: [(0, jsx_runtime_1.jsx)(qrcode_react_1.QRCodeSVG, { value: (0, anyspend_1.getPaymentUrl)(order.globalAddress, BigInt(depositDeficit), order.srcTokenAddress === anyspend_1.RELAY_ETH_ADDRESS ? srcToken?.symbol || "ETH" : order.srcTokenAddress, order.srcChain, srcToken?.decimals), className: "max-w-[200px]" }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-3 flex items-center justify-center gap-2 text-sm", children: [(0, jsx_runtime_1.jsx)("span", { className: "label-style text-as-brand/70 text-sm", children: "Scan with" }), (0, jsx_runtime_1.jsxs)(react_1.TextLoop, { interval: 3, children: [(0, jsx_runtime_1.jsx)(react_2.WalletMetamask, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_2.WalletCoinbase, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_2.WalletPhantom, { className: "h-5 w-5", variant: "branded" }), (0, jsx_runtime_1.jsx)(react_2.WalletTrust, { className: "h-5 w-5", variant: "branded" })] })] })] }) })] })] }));
25
+ }
@@ -27,6 +27,7 @@ const wagmi_1 = require("wagmi");
27
27
  const Accordion_1 = require("./Accordion");
28
28
  const ConnectWalletPayment_1 = __importDefault(require("./ConnectWalletPayment"));
29
29
  const CryptoPaymentMethod_1 = require("./CryptoPaymentMethod");
30
+ const InsufficientDepositPayment_1 = require("./InsufficientDepositPayment");
30
31
  const OrderDetailsCollapsible_1 = require("./OrderDetailsCollapsible");
31
32
  const PaymentVendorUI_1 = __importDefault(require("./PaymentVendorUI"));
32
33
  const TransferCryptoDetails_1 = require("./TransferCryptoDetails");
@@ -159,22 +160,37 @@ exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ mode = "modal",
159
160
  : undefined;
160
161
  return roundTokenAmount(formattedSrcAmount);
161
162
  }, [order.srcAmount, srcToken]);
163
+ // Calculate deposit amounts - moved here to be used in useCallback hooks
164
+ const depositedAmount = (0, react_4.useMemo)(() => {
165
+ return depositTxs ? depositTxs.reduce((acc, curr) => acc + BigInt(curr.amount), BigInt(0)) : BigInt(0);
166
+ }, [depositTxs]);
167
+ const depositDeficit = (0, react_4.useMemo)(() => {
168
+ return BigInt(order.srcAmount) - depositedAmount;
169
+ }, [order.srcAmount, depositedAmount]);
170
+ const depositEnoughAmount = (0, react_4.useMemo)(() => {
171
+ return depositDeficit <= BigInt(0);
172
+ }, [depositDeficit]);
173
+ const formattedDepositDeficit = (0, react_4.useMemo)(() => {
174
+ return (0, number_1.formatTokenAmount)(BigInt(depositDeficit), srcToken.decimals);
175
+ }, [depositDeficit, srcToken.decimals]);
162
176
  // Unified payment handler for both EOA and AA wallets
163
177
  const handleUnifiedPaymentProcess = (0, react_4.useCallback)(async () => {
164
178
  let txData;
165
179
  let value;
166
180
  let to;
181
+ // Use the existing depositDeficit calculation to determine amount to send
182
+ const amountToSend = depositDeficit > BigInt(0) ? depositDeficit : BigInt(order.srcAmount);
167
183
  if ((0, anyspend_1.isNativeToken)(order.srcTokenAddress)) {
168
184
  // Native token transfer
169
185
  to = order.globalAddress;
170
- value = BigInt(order.srcAmount);
186
+ value = amountToSend;
171
187
  }
172
188
  else {
173
189
  // ERC20 token transfer - encode the transfer function call using proper ABI
174
190
  txData = (0, viem_1.encodeFunctionData)({
175
191
  abi: viem_1.erc20Abi,
176
192
  functionName: "transfer",
177
- args: [order.globalAddress, BigInt(order.srcAmount)],
193
+ args: [order.globalAddress, amountToSend],
178
194
  });
179
195
  to = order.srcTokenAddress;
180
196
  value = BigInt(0);
@@ -183,12 +199,14 @@ exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ mode = "modal",
183
199
  if (txHash) {
184
200
  setTxHash(txHash);
185
201
  }
186
- }, [order, switchChainAndExecuteWithEOA]);
202
+ }, [order, switchChainAndExecuteWithEOA, depositDeficit]);
187
203
  // Main payment handler that triggers chain switch and payment
188
204
  const handlePayment = async () => {
189
205
  console.log("Initiating payment process. Target chain:", order.srcChain, "Current chain:", walletClient?.chain?.id);
190
206
  if (order.srcChain === anyspend_1.RELAY_SOLANA_MAINNET_CHAIN_ID) {
191
- await initiatePhantomTransfer(order.srcAmount, order.srcTokenAddress, order.globalAddress);
207
+ // Use the existing depositDeficit calculation to determine amount to send
208
+ const amountToSend = depositDeficit > BigInt(0) ? depositDeficit.toString() : order.srcAmount;
209
+ await initiatePhantomTransfer(amountToSend, order.srcTokenAddress, order.globalAddress);
192
210
  }
193
211
  else {
194
212
  // Use unified payment process for both EOA and AA wallets
@@ -261,12 +279,6 @@ exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ mode = "modal",
261
279
  const formattedActualDstAmount = actualDstAmount
262
280
  ? (0, number_1.formatTokenAmount)(BigInt(actualDstAmount), dstToken.decimals)
263
281
  : undefined;
264
- const depositedAmount = depositTxs
265
- ? depositTxs.reduce((acc, curr) => acc + BigInt(curr.amount), BigInt(0))
266
- : BigInt(0);
267
- const depositDeficit = BigInt(order.srcAmount) - depositedAmount;
268
- const depositEnoughAmount = depositDeficit <= BigInt(0);
269
- const formattedDepositDeficit = (0, number_1.formatTokenAmount)(BigInt(depositDeficit), srcToken.decimals);
270
282
  const { text: statusText, status: statusDisplay } = (0, anyspend_1.getStatusDisplay)(order);
271
283
  const initiatePhantomTransfer = async (amountLamports, tokenAddress, recipientAddress) => {
272
284
  try {
@@ -475,7 +487,7 @@ exports.OrderDetails = (0, react_4.memo)(function OrderDetails({ mode = "modal",
475
487
  ? "Funding Tournament"
476
488
  : "Processing Transaction", chainId: order.srcChain, tx: null, isProcessing: true, delay: 0.5 })) : ((0, jsx_runtime_1.jsx)(TransactionDetails, { title: order.onrampMetadata?.vendor === "stripe-web2"
477
489
  ? `Waiting for payment`
478
- : `Waiting for deposit ${formattedDepositDeficit} ${srcToken.symbol}`, chainId: order.srcChain, tx: null, isProcessing: true, delay: 0.5 }))] }) })] }) })] }));
490
+ : `Waiting for deposit ${formattedDepositDeficit} ${srcToken.symbol}`, chainId: order.srcChain, tx: null, isProcessing: true, delay: 0.5 }))] }) })] }) }), !depositEnoughAmount && order.status !== "expired" && ((0, jsx_runtime_1.jsx)(InsufficientDepositPayment_1.InsufficientDepositPayment, { order: order, srcToken: srcToken, depositDeficit: depositDeficit, phantomWalletAddress: phantomWalletAddress, txLoading: txLoading, isSwitchingOrExecuting: isSwitchingOrExecuting, onPayment: handlePayment }))] }));
479
491
  }
480
492
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [statusDisplay === "processing" && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: order.onrampMetadata ? ((0, jsx_runtime_1.jsx)(PaymentVendorUI_1.default, { order: order, dstTokenSymbol: dstToken.symbol })) : effectiveCryptoPaymentMethod === CryptoPaymentMethod_1.CryptoPaymentMethodType.CONNECT_WALLET ? ((0, jsx_runtime_1.jsx)(ConnectWalletPayment_1.default, { order: order, onPayment: handlePayment, onCancel: handleBack, txLoading: txLoading, isSwitchingOrExecuting: isSwitchingOrExecuting, phantomWalletAddress: phantomWalletAddress, tournament: tournament, nft: nft })) : effectiveCryptoPaymentMethod === CryptoPaymentMethod_1.CryptoPaymentMethodType.TRANSFER_CRYPTO ? (
481
493
  // Transfer Crypto Payment Method - Show new card-based UI
@@ -0,0 +1,12 @@
1
+ import { components } from "../../../../anyspend/types/api";
2
+ interface InsufficientDepositPaymentProps {
3
+ order: components["schemas"]["Order"];
4
+ srcToken: components["schemas"]["Token"];
5
+ depositDeficit: bigint;
6
+ phantomWalletAddress: string | null;
7
+ txLoading: boolean;
8
+ isSwitchingOrExecuting: boolean;
9
+ onPayment: () => Promise<void>;
10
+ }
11
+ export declare function InsufficientDepositPayment({ order, srcToken, depositDeficit, phantomWalletAddress, txLoading, isSwitchingOrExecuting, onPayment, }: InsufficientDepositPaymentProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,22 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { ALL_CHAINS, getChainName, getPaymentUrl, RELAY_ETH_ADDRESS, RELAY_SOLANA_MAINNET_CHAIN_ID, } from "../../../../anyspend/index.js";
4
+ import { Badge, CopyToClipboard, ShinyButton, TextLoop } from "../../../../global-account/react/index.js";
5
+ import { cn } from "../../../../shared/utils/index.js";
6
+ import { b3 } from "viem/chains";
7
+ import { formatUnits } from "../../../../shared/utils/number.js";
8
+ import { WalletCoinbase, WalletMetamask, WalletPhantom, WalletTrust } from "@web3icons/react";
9
+ import { ChevronRight, Copy, Loader2 } from "lucide-react";
10
+ import { motion } from "motion/react";
11
+ import { QRCodeSVG } from "qrcode.react";
12
+ import { toast } from "sonner";
13
+ export function InsufficientDepositPayment({ order, srcToken, depositDeficit, phantomWalletAddress, txLoading, isSwitchingOrExecuting, onPayment, }) {
14
+ const depositDeficitAmount = formatUnits(depositDeficit.toString(), srcToken.decimals);
15
+ return (_jsxs("div", { className: "insufficient-deposit-payment relative flex w-full flex-1 flex-col", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("span", { className: "insufficient-deposit-payment-text text-as-primary/50", children: "Please send remaining" }), _jsxs("div", { className: "flex w-full flex-wrap items-center gap-6 sm:justify-between sm:gap-0", children: [_jsx(CopyToClipboard, { text: depositDeficitAmount, onCopy: () => {
16
+ toast.success("Copied to clipboard");
17
+ }, children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("strong", { className: "border-as-brand text-as-primary border-b-2 pb-1 text-2xl font-semibold sm:text-xl", children: [depositDeficitAmount, " ", srcToken.symbol] }), _jsx(Copy, { className: "text-as-primary/50 hover:text-as-primary h-5 w-5 cursor-pointer transition-all duration-200" })] }) }), _jsxs(Badge, { variant: "outline", className: "flex h-10 items-center gap-2 px-3 py-1 pr-2 text-sm", children: ["on ", getChainName(order.srcChain), _jsx("img", { src: ALL_CHAINS[order.srcChain].logoUrl, alt: getChainName(order.srcChain), className: cn("h-6 rounded-full", order.srcChain === b3.id && "h-5 rounded-none") })] })] }), _jsx("span", { className: "text-as-primary/50 mb-1 mt-2", children: " to the address:" })] }), _jsx(CopyToClipboard, { text: order.globalAddress, onCopy: () => {
18
+ toast.success("Copied to clipboard");
19
+ }, children: _jsxs("div", { className: "payment-address bg-b3-react-background border-b3-react-border hover:border-as-brand group flex cursor-pointer items-center justify-between gap-4 rounded-lg border p-3 px-4 shadow-md transition-all duration-200", children: [_jsx("div", { className: "text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-sm", children: order.globalAddress }), _jsx(Copy, { className: "group-hover:text-as-brand text-as-primary/50 h-5 w-5 cursor-pointer transition-all duration-200" })] }) }), _jsxs("div", { className: "payment-buttons mt-4 flex w-full flex-col items-center gap-2", children: [_jsx(ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-5/6 max-w-[400px] items-center gap-2 sm:px-0", disabled: txLoading || isSwitchingOrExecuting, onClick: onPayment, children: txLoading ? (_jsxs(_Fragment, { children: ["Transaction Pending", _jsx(Loader2, { className: "ml-2 h-5 w-5 animate-spin" })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "whitespace-nowrap pl-4 text-lg md:text-sm", children: order.srcChain === RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
20
+ ? "Pay from Phantom Wallet"
21
+ : "Pay from Connected Wallet" }), _jsx(ChevronRight, { className: "h-4 w-4" })] })) }), _jsx("div", { children: "Or" }), _jsx(motion.div, { initial: { opacity: 0, filter: "blur(10px)" }, animate: { opacity: 1, filter: "blur(0px)" }, transition: { duration: 0.5, ease: "easeInOut" }, className: "flex w-full items-center justify-evenly gap-4", children: _jsxs("div", { className: "qr-code flex flex-col items-center rounded-lg pb-3", children: [_jsx(QRCodeSVG, { value: getPaymentUrl(order.globalAddress, BigInt(depositDeficit), order.srcTokenAddress === RELAY_ETH_ADDRESS ? srcToken?.symbol || "ETH" : order.srcTokenAddress, order.srcChain, srcToken?.decimals), className: "max-w-[200px]" }), _jsxs("div", { className: "mt-3 flex items-center justify-center gap-2 text-sm", children: [_jsx("span", { className: "label-style text-as-brand/70 text-sm", children: "Scan with" }), _jsxs(TextLoop, { interval: 3, children: [_jsx(WalletMetamask, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletCoinbase, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletPhantom, { className: "h-5 w-5", variant: "branded" }), _jsx(WalletTrust, { className: "h-5 w-5", variant: "branded" })] })] })] }) })] })] }));
22
+ }
@@ -21,6 +21,7 @@ import { useWaitForTransactionReceipt, useWalletClient } from "wagmi";
21
21
  import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./Accordion.js";
22
22
  import ConnectWalletPayment from "./ConnectWalletPayment.js";
23
23
  import { CryptoPaymentMethodType } from "./CryptoPaymentMethod.js";
24
+ import { InsufficientDepositPayment } from "./InsufficientDepositPayment.js";
24
25
  import { OrderDetailsCollapsible } from "./OrderDetailsCollapsible.js";
25
26
  import PaymentVendorUI from "./PaymentVendorUI.js";
26
27
  import { TransferCryptoDetails } from "./TransferCryptoDetails.js";
@@ -153,22 +154,37 @@ export const OrderDetails = memo(function OrderDetails({ mode = "modal", order,
153
154
  : undefined;
154
155
  return roundTokenAmount(formattedSrcAmount);
155
156
  }, [order.srcAmount, srcToken]);
157
+ // Calculate deposit amounts - moved here to be used in useCallback hooks
158
+ const depositedAmount = useMemo(() => {
159
+ return depositTxs ? depositTxs.reduce((acc, curr) => acc + BigInt(curr.amount), BigInt(0)) : BigInt(0);
160
+ }, [depositTxs]);
161
+ const depositDeficit = useMemo(() => {
162
+ return BigInt(order.srcAmount) - depositedAmount;
163
+ }, [order.srcAmount, depositedAmount]);
164
+ const depositEnoughAmount = useMemo(() => {
165
+ return depositDeficit <= BigInt(0);
166
+ }, [depositDeficit]);
167
+ const formattedDepositDeficit = useMemo(() => {
168
+ return formatTokenAmount(BigInt(depositDeficit), srcToken.decimals);
169
+ }, [depositDeficit, srcToken.decimals]);
156
170
  // Unified payment handler for both EOA and AA wallets
157
171
  const handleUnifiedPaymentProcess = useCallback(async () => {
158
172
  let txData;
159
173
  let value;
160
174
  let to;
175
+ // Use the existing depositDeficit calculation to determine amount to send
176
+ const amountToSend = depositDeficit > BigInt(0) ? depositDeficit : BigInt(order.srcAmount);
161
177
  if (isNativeToken(order.srcTokenAddress)) {
162
178
  // Native token transfer
163
179
  to = order.globalAddress;
164
- value = BigInt(order.srcAmount);
180
+ value = amountToSend;
165
181
  }
166
182
  else {
167
183
  // ERC20 token transfer - encode the transfer function call using proper ABI
168
184
  txData = encodeFunctionData({
169
185
  abi: erc20Abi,
170
186
  functionName: "transfer",
171
- args: [order.globalAddress, BigInt(order.srcAmount)],
187
+ args: [order.globalAddress, amountToSend],
172
188
  });
173
189
  to = order.srcTokenAddress;
174
190
  value = BigInt(0);
@@ -177,12 +193,14 @@ export const OrderDetails = memo(function OrderDetails({ mode = "modal", order,
177
193
  if (txHash) {
178
194
  setTxHash(txHash);
179
195
  }
180
- }, [order, switchChainAndExecuteWithEOA]);
196
+ }, [order, switchChainAndExecuteWithEOA, depositDeficit]);
181
197
  // Main payment handler that triggers chain switch and payment
182
198
  const handlePayment = async () => {
183
199
  console.log("Initiating payment process. Target chain:", order.srcChain, "Current chain:", walletClient?.chain?.id);
184
200
  if (order.srcChain === RELAY_SOLANA_MAINNET_CHAIN_ID) {
185
- await initiatePhantomTransfer(order.srcAmount, order.srcTokenAddress, order.globalAddress);
201
+ // Use the existing depositDeficit calculation to determine amount to send
202
+ const amountToSend = depositDeficit > BigInt(0) ? depositDeficit.toString() : order.srcAmount;
203
+ await initiatePhantomTransfer(amountToSend, order.srcTokenAddress, order.globalAddress);
186
204
  }
187
205
  else {
188
206
  // Use unified payment process for both EOA and AA wallets
@@ -255,12 +273,6 @@ export const OrderDetails = memo(function OrderDetails({ mode = "modal", order,
255
273
  const formattedActualDstAmount = actualDstAmount
256
274
  ? formatTokenAmount(BigInt(actualDstAmount), dstToken.decimals)
257
275
  : undefined;
258
- const depositedAmount = depositTxs
259
- ? depositTxs.reduce((acc, curr) => acc + BigInt(curr.amount), BigInt(0))
260
- : BigInt(0);
261
- const depositDeficit = BigInt(order.srcAmount) - depositedAmount;
262
- const depositEnoughAmount = depositDeficit <= BigInt(0);
263
- const formattedDepositDeficit = formatTokenAmount(BigInt(depositDeficit), srcToken.decimals);
264
276
  const { text: statusText, status: statusDisplay } = getStatusDisplay(order);
265
277
  const initiatePhantomTransfer = async (amountLamports, tokenAddress, recipientAddress) => {
266
278
  try {
@@ -469,7 +481,7 @@ export const OrderDetails = memo(function OrderDetails({ mode = "modal", order,
469
481
  ? "Funding Tournament"
470
482
  : "Processing Transaction", chainId: order.srcChain, tx: null, isProcessing: true, delay: 0.5 })) : (_jsx(TransactionDetails, { title: order.onrampMetadata?.vendor === "stripe-web2"
471
483
  ? `Waiting for payment`
472
- : `Waiting for deposit ${formattedDepositDeficit} ${srcToken.symbol}`, chainId: order.srcChain, tx: null, isProcessing: true, delay: 0.5 }))] }) })] }) })] }));
484
+ : `Waiting for deposit ${formattedDepositDeficit} ${srcToken.symbol}`, chainId: order.srcChain, tx: null, isProcessing: true, delay: 0.5 }))] }) })] }) }), !depositEnoughAmount && order.status !== "expired" && (_jsx(InsufficientDepositPayment, { order: order, srcToken: srcToken, depositDeficit: depositDeficit, phantomWalletAddress: phantomWalletAddress, txLoading: txLoading, isSwitchingOrExecuting: isSwitchingOrExecuting, onPayment: handlePayment }))] }));
473
485
  }
474
486
  return (_jsxs(_Fragment, { children: [statusDisplay === "processing" && (_jsx(_Fragment, { children: order.onrampMetadata ? (_jsx(PaymentVendorUI, { order: order, dstTokenSymbol: dstToken.symbol })) : effectiveCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ? (_jsx(ConnectWalletPayment, { order: order, onPayment: handlePayment, onCancel: handleBack, txLoading: txLoading, isSwitchingOrExecuting: isSwitchingOrExecuting, phantomWalletAddress: phantomWalletAddress, tournament: tournament, nft: nft })) : effectiveCryptoPaymentMethod === CryptoPaymentMethodType.TRANSFER_CRYPTO ? (
475
487
  // Transfer Crypto Payment Method - Show new card-based UI
@@ -0,0 +1,12 @@
1
+ import { components } from "@b3dotfun/sdk/anyspend/types/api";
2
+ interface InsufficientDepositPaymentProps {
3
+ order: components["schemas"]["Order"];
4
+ srcToken: components["schemas"]["Token"];
5
+ depositDeficit: bigint;
6
+ phantomWalletAddress: string | null;
7
+ txLoading: boolean;
8
+ isSwitchingOrExecuting: boolean;
9
+ onPayment: () => Promise<void>;
10
+ }
11
+ export declare function InsufficientDepositPayment({ order, srcToken, depositDeficit, phantomWalletAddress, txLoading, isSwitchingOrExecuting, onPayment, }: InsufficientDepositPaymentProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.33-alpha.5",
3
+ "version": "0.0.33-alpha.6",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -0,0 +1,144 @@
1
+ "use client";
2
+
3
+ import {
4
+ ALL_CHAINS,
5
+ getChainName,
6
+ getPaymentUrl,
7
+ RELAY_ETH_ADDRESS,
8
+ RELAY_SOLANA_MAINNET_CHAIN_ID,
9
+ } from "@b3dotfun/sdk/anyspend";
10
+ import { components } from "@b3dotfun/sdk/anyspend/types/api";
11
+ import { Badge, CopyToClipboard, ShinyButton, TextLoop } from "@b3dotfun/sdk/global-account/react";
12
+ import { cn } from "@b3dotfun/sdk/shared/utils";
13
+ import { b3 } from "viem/chains";
14
+
15
+ import { formatUnits } from "@b3dotfun/sdk/shared/utils/number";
16
+ import { WalletCoinbase, WalletMetamask, WalletPhantom, WalletTrust } from "@web3icons/react";
17
+ import { ChevronRight, Copy, Loader2 } from "lucide-react";
18
+ import { motion } from "motion/react";
19
+ import { QRCodeSVG } from "qrcode.react";
20
+ import { toast } from "sonner";
21
+
22
+ interface InsufficientDepositPaymentProps {
23
+ order: components["schemas"]["Order"];
24
+ srcToken: components["schemas"]["Token"];
25
+ depositDeficit: bigint;
26
+ phantomWalletAddress: string | null;
27
+ txLoading: boolean;
28
+ isSwitchingOrExecuting: boolean;
29
+ onPayment: () => Promise<void>;
30
+ }
31
+
32
+ export function InsufficientDepositPayment({
33
+ order,
34
+ srcToken,
35
+ depositDeficit,
36
+ phantomWalletAddress,
37
+ txLoading,
38
+ isSwitchingOrExecuting,
39
+ onPayment,
40
+ }: InsufficientDepositPaymentProps) {
41
+ const depositDeficitAmount = formatUnits(depositDeficit.toString(), srcToken.decimals);
42
+ return (
43
+ <div className="insufficient-deposit-payment relative flex w-full flex-1 flex-col">
44
+ <div className="flex flex-col gap-1">
45
+ <span className="insufficient-deposit-payment-text text-as-primary/50">Please send remaining</span>
46
+ <div className="flex w-full flex-wrap items-center gap-6 sm:justify-between sm:gap-0">
47
+ <CopyToClipboard
48
+ text={depositDeficitAmount}
49
+ onCopy={() => {
50
+ toast.success("Copied to clipboard");
51
+ }}
52
+ >
53
+ <div className="flex items-center gap-2">
54
+ <strong className="border-as-brand text-as-primary border-b-2 pb-1 text-2xl font-semibold sm:text-xl">
55
+ {depositDeficitAmount} {srcToken.symbol}
56
+ </strong>
57
+ <Copy className="text-as-primary/50 hover:text-as-primary h-5 w-5 cursor-pointer transition-all duration-200" />
58
+ </div>
59
+ </CopyToClipboard>
60
+
61
+ <Badge variant="outline" className="flex h-10 items-center gap-2 px-3 py-1 pr-2 text-sm">
62
+ on {getChainName(order.srcChain)}
63
+ <img
64
+ src={ALL_CHAINS[order.srcChain].logoUrl}
65
+ alt={getChainName(order.srcChain)}
66
+ className={cn("h-6 rounded-full", order.srcChain === b3.id && "h-5 rounded-none")}
67
+ />
68
+ </Badge>
69
+ </div>
70
+ <span className={"text-as-primary/50 mb-1 mt-2"}> to the address:</span>
71
+ </div>
72
+ <CopyToClipboard
73
+ text={order.globalAddress}
74
+ onCopy={() => {
75
+ toast.success("Copied to clipboard");
76
+ }}
77
+ >
78
+ <div className="payment-address bg-b3-react-background border-b3-react-border hover:border-as-brand group flex cursor-pointer items-center justify-between gap-4 rounded-lg border p-3 px-4 shadow-md transition-all duration-200">
79
+ <div className="text-as-primary overflow-hidden text-ellipsis whitespace-nowrap text-sm">
80
+ {order.globalAddress}
81
+ </div>
82
+ <Copy className="group-hover:text-as-brand text-as-primary/50 h-5 w-5 cursor-pointer transition-all duration-200" />
83
+ </div>
84
+ </CopyToClipboard>
85
+
86
+ <div className="payment-buttons mt-4 flex w-full flex-col items-center gap-2">
87
+ <ShinyButton
88
+ accentColor={"hsl(var(--as-brand))"}
89
+ textColor="text-white"
90
+ className="flex w-5/6 max-w-[400px] items-center gap-2 sm:px-0"
91
+ disabled={txLoading || isSwitchingOrExecuting}
92
+ onClick={onPayment}
93
+ >
94
+ {txLoading ? (
95
+ <>
96
+ Transaction Pending
97
+ <Loader2 className="ml-2 h-5 w-5 animate-spin" />
98
+ </>
99
+ ) : (
100
+ <>
101
+ <span className="whitespace-nowrap pl-4 text-lg md:text-sm">
102
+ {order.srcChain === RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
103
+ ? "Pay from Phantom Wallet"
104
+ : "Pay from Connected Wallet"}
105
+ </span>
106
+ <ChevronRight className="h-4 w-4" />
107
+ </>
108
+ )}
109
+ </ShinyButton>
110
+
111
+ <div>Or</div>
112
+
113
+ <motion.div
114
+ initial={{ opacity: 0, filter: "blur(10px)" }}
115
+ animate={{ opacity: 1, filter: "blur(0px)" }}
116
+ transition={{ duration: 0.5, ease: "easeInOut" }}
117
+ className="flex w-full items-center justify-evenly gap-4"
118
+ >
119
+ <div className="qr-code flex flex-col items-center rounded-lg pb-3">
120
+ <QRCodeSVG
121
+ value={getPaymentUrl(
122
+ order.globalAddress,
123
+ BigInt(depositDeficit),
124
+ order.srcTokenAddress === RELAY_ETH_ADDRESS ? srcToken?.symbol || "ETH" : order.srcTokenAddress,
125
+ order.srcChain,
126
+ srcToken?.decimals,
127
+ )}
128
+ className="max-w-[200px]"
129
+ />
130
+ <div className="mt-3 flex items-center justify-center gap-2 text-sm">
131
+ <span className="label-style text-as-brand/70 text-sm">Scan with</span>
132
+ <TextLoop interval={3}>
133
+ <WalletMetamask className="h-5 w-5" variant="branded" />
134
+ <WalletCoinbase className="h-5 w-5" variant="branded" />
135
+ <WalletPhantom className="h-5 w-5" variant="branded" />
136
+ <WalletTrust className="h-5 w-5" variant="branded" />
137
+ </TextLoop>
138
+ </div>
139
+ </div>
140
+ </motion.div>
141
+ </div>
142
+ </div>
143
+ );
144
+ }
@@ -51,6 +51,7 @@ import { useWaitForTransactionReceipt, useWalletClient } from "wagmi";
51
51
  import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./Accordion";
52
52
  import ConnectWalletPayment from "./ConnectWalletPayment";
53
53
  import { CryptoPaymentMethodType } from "./CryptoPaymentMethod";
54
+ import { InsufficientDepositPayment } from "./InsufficientDepositPayment";
54
55
  import { OrderDetailsCollapsible } from "./OrderDetailsCollapsible";
55
56
  import PaymentVendorUI from "./PaymentVendorUI";
56
57
  import { TransferCryptoDetails } from "./TransferCryptoDetails";
@@ -248,22 +249,42 @@ export const OrderDetails = memo(function OrderDetails({
248
249
  return roundTokenAmount(formattedSrcAmount);
249
250
  }, [order.srcAmount, srcToken]);
250
251
 
252
+ // Calculate deposit amounts - moved here to be used in useCallback hooks
253
+ const depositedAmount = useMemo(() => {
254
+ return depositTxs ? depositTxs.reduce((acc, curr) => acc + BigInt(curr.amount), BigInt(0)) : BigInt(0);
255
+ }, [depositTxs]);
256
+
257
+ const depositDeficit = useMemo(() => {
258
+ return BigInt(order.srcAmount) - depositedAmount;
259
+ }, [order.srcAmount, depositedAmount]);
260
+
261
+ const depositEnoughAmount = useMemo(() => {
262
+ return depositDeficit <= BigInt(0);
263
+ }, [depositDeficit]);
264
+
265
+ const formattedDepositDeficit = useMemo(() => {
266
+ return formatTokenAmount(BigInt(depositDeficit), srcToken.decimals);
267
+ }, [depositDeficit, srcToken.decimals]);
268
+
251
269
  // Unified payment handler for both EOA and AA wallets
252
270
  const handleUnifiedPaymentProcess = useCallback(async () => {
253
271
  let txData: `0x${string}` | undefined;
254
272
  let value: bigint;
255
273
  let to: `0x${string}`;
256
274
 
275
+ // Use the existing depositDeficit calculation to determine amount to send
276
+ const amountToSend = depositDeficit > BigInt(0) ? depositDeficit : BigInt(order.srcAmount);
277
+
257
278
  if (isNativeToken(order.srcTokenAddress)) {
258
279
  // Native token transfer
259
280
  to = order.globalAddress as `0x${string}`;
260
- value = BigInt(order.srcAmount);
281
+ value = amountToSend;
261
282
  } else {
262
283
  // ERC20 token transfer - encode the transfer function call using proper ABI
263
284
  txData = encodeFunctionData({
264
285
  abi: erc20Abi,
265
286
  functionName: "transfer",
266
- args: [order.globalAddress as `0x${string}`, BigInt(order.srcAmount)],
287
+ args: [order.globalAddress as `0x${string}`, amountToSend],
267
288
  });
268
289
  to = order.srcTokenAddress as `0x${string}`;
269
290
  value = BigInt(0);
@@ -274,13 +295,15 @@ export const OrderDetails = memo(function OrderDetails({
274
295
  if (txHash) {
275
296
  setTxHash(txHash as `0x${string}`);
276
297
  }
277
- }, [order, switchChainAndExecuteWithEOA]);
298
+ }, [order, switchChainAndExecuteWithEOA, depositDeficit]);
278
299
 
279
300
  // Main payment handler that triggers chain switch and payment
280
301
  const handlePayment = async () => {
281
302
  console.log("Initiating payment process. Target chain:", order.srcChain, "Current chain:", walletClient?.chain?.id);
282
303
  if (order.srcChain === RELAY_SOLANA_MAINNET_CHAIN_ID) {
283
- await initiatePhantomTransfer(order.srcAmount, order.srcTokenAddress, order.globalAddress);
304
+ // Use the existing depositDeficit calculation to determine amount to send
305
+ const amountToSend = depositDeficit > BigInt(0) ? depositDeficit.toString() : order.srcAmount;
306
+ await initiatePhantomTransfer(amountToSend, order.srcTokenAddress, order.globalAddress);
284
307
  } else {
285
308
  // Use unified payment process for both EOA and AA wallets
286
309
  await handleUnifiedPaymentProcess();
@@ -364,13 +387,6 @@ export const OrderDetails = memo(function OrderDetails({
364
387
  ? formatTokenAmount(BigInt(actualDstAmount), dstToken.decimals)
365
388
  : undefined;
366
389
 
367
- const depositedAmount = depositTxs
368
- ? depositTxs.reduce((acc, curr) => acc + BigInt(curr.amount), BigInt(0))
369
- : BigInt(0);
370
- const depositDeficit = BigInt(order.srcAmount) - depositedAmount;
371
- const depositEnoughAmount = depositDeficit <= BigInt(0);
372
- const formattedDepositDeficit = formatTokenAmount(BigInt(depositDeficit), srcToken.decimals);
373
-
374
390
  const { text: statusText, status: statusDisplay } = getStatusDisplay(order);
375
391
 
376
392
  const initiatePhantomTransfer = async (amountLamports: string, tokenAddress: string, recipientAddress: string) => {
@@ -962,6 +978,19 @@ export const OrderDetails = memo(function OrderDetails({
962
978
  </AccordionItem>
963
979
  </Accordion>
964
980
 
981
+ {/* Show payment UI when deposit is not enough and order is not expired */}
982
+ {!depositEnoughAmount && order.status !== "expired" && (
983
+ <InsufficientDepositPayment
984
+ order={order}
985
+ srcToken={srcToken}
986
+ depositDeficit={depositDeficit}
987
+ phantomWalletAddress={phantomWalletAddress}
988
+ txLoading={txLoading}
989
+ isSwitchingOrExecuting={isSwitchingOrExecuting}
990
+ onPayment={handlePayment}
991
+ />
992
+ )}
993
+
965
994
  {/* <DelayedSupportMessage /> */}
966
995
  </>
967
996
  );