@b3dotfun/sdk 0.0.48 → 0.0.49

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.
@@ -29,17 +29,15 @@ exports.OrderDetailsCollapsible = (0, react_3.memo)(function OrderDetailsCollaps
29
29
  const finalFormattedExpectedDstAmount = formattedExpectedDstAmount || (0, number_1.formatTokenAmount)(BigInt(expectedDstAmount), dstToken.decimals);
30
30
  return ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("order-details-collapsible bg-as-surface-secondary border-as-border-secondary rounded-xl border px-4 py-2", className), children: showOrderDetails ? ((0, jsx_runtime_1.jsx)(react_2.motion.div, { className: "order-details-expanded w-full", initial: { opacity: 0, y: 20, filter: "blur(10px)" }, animate: { opacity: 1, y: 0, filter: "blur(0px)" }, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, children: (0, jsx_runtime_1.jsxs)("div", { className: "order-details-content flex w-full flex-col items-center gap-3 whitespace-nowrap py-2 text-sm", children: [(0, jsx_runtime_1.jsxs)("div", { className: "order-details-recipient-section flex w-full justify-between gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "order-details-recipient-label text-as-tertiarry", children: "Recipient" }), (0, jsx_runtime_1.jsxs)("div", { className: "order-details-recipient-info flex flex-col items-end gap-1", children: [recipientName && ((0, jsx_runtime_1.jsx)("div", { className: "order-details-recipient-name text-as-primary font-semibold", children: recipientName })), (0, jsx_runtime_1.jsx)(react_1.CopyToClipboard, { text: order.recipientAddress, onCopy: () => {
31
31
  sonner_1.toast.success("Copied recipient address to clipboard");
32
- }, children: (0, jsx_runtime_1.jsxs)("div", { className: "order-details-recipient-address text-as-primary flex items-center gap-2", children: [(0, centerTruncate_1.default)(order.recipientAddress, 10), (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "order-details-recipient-copy-icon text-as-primary/50 hover:text-as-primary h-4 w-4 cursor-pointer transition-all duration-200" })] }) })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-divider divider w-full" }), (0, jsx_runtime_1.jsxs)("div", { className: "order-details-expected-section flex w-full items-center justify-between gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "order-details-expected-label text-as-tertiarry", children: order.type === "swap" || order.type === "mint_nft"
32
+ }, children: (0, jsx_runtime_1.jsxs)("div", { className: "order-details-recipient-address text-as-primary flex items-center gap-2", children: [(0, centerTruncate_1.default)(order.recipientAddress, 10), (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "order-details-recipient-copy-icon text-as-primary/50 hover:text-as-primary h-4 w-4 cursor-pointer transition-all duration-200" })] }) })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-divider divider w-full" }), (0, jsx_runtime_1.jsxs)("div", { className: "order-details-expected-section flex w-full items-center justify-between gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "order-details-expected-label text-as-tertiarry", children: order.type === "swap" || order.type === "mint_nft" || order.type === "hype_duel"
33
33
  ? "Expected to receive"
34
34
  : order.type === "join_tournament"
35
35
  ? "Join tournament"
36
36
  : order.type === "fund_tournament"
37
37
  ? "Fund tournament"
38
- : order.type === "hype_duel"
39
- ? "Deposit HYPE"
40
- : order.type === "custom"
41
- ? order.metadata.action
42
- ? (0, anyspend_1.capitalizeFirstLetter)(order.metadata.action)
43
- : "Contract execution"
44
- : "" }), (0, jsx_runtime_1.jsxs)("div", { className: "order-details-expected-value flex items-end gap-2", children: [order.type === "swap" ? (`~${finalFormattedExpectedDstAmount} ${dstToken.symbol}`) : order.type === "mint_nft" ? ((0, jsx_runtime_1.jsxs)("div", { className: "order-details-nft-info flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("img", { src: nft?.imageUrl, alt: nft?.name || "NFT", className: "order-details-nft-image h-5 w-5" }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-nft-name", children: nft?.name || "NFT" })] })) : order.type === "join_tournament" || order.type === "fund_tournament" ? ((0, jsx_runtime_1.jsxs)("div", { className: "order-details-tournament-info flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("img", { src: tournament?.imageUrl, alt: tournament?.name || "Tournament", className: "order-details-tournament-image h-5 w-5" }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-tournament-name", children: tournament?.name || "Tournament" })] })) : order.type === "hype_duel" ? ((0, jsx_runtime_1.jsx)("div", { className: "order-details-hype-info flex items-center gap-2", children: (0, jsx_runtime_1.jsxs)("div", { className: "order-details-hype-amount", children: [(0, number_1.formatTokenAmount)(BigInt(order.payload.expectedDstAmount), dstToken.decimals), " HYPE"] }) })) : null, (0, jsx_runtime_1.jsxs)("div", { className: "order-details-chain-info text-as-primary/50 flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("span", { className: "order-details-chain-text", children: ["on ", order.dstChain !== chains_1.b3.id && (0, anyspend_1.getChainName)(order.dstChain)] }), (0, jsx_runtime_1.jsx)("img", { src: anyspend_1.ALL_CHAINS[order.dstChain].logoUrl, alt: (0, anyspend_1.getChainName)(order.dstChain), className: (0, utils_1.cn)("order-details-chain-logo h-3", order.dstChain !== chains_1.b3.id && "w-3 rounded-full", order.dstChain === chains_1.b3.id && "h-4") })] })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-divider divider w-full" }), (0, jsx_runtime_1.jsxs)("div", { className: "order-details-id-total-section flex w-full justify-between gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "order-details-id-total-label text-as-tertiarry", children: showTotal ? "Total (included fee)" : "Order ID" }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-id-total-value text-as-primary overflow-hidden text-ellipsis whitespace-nowrap", children: showTotal && totalAmount ? totalAmount : order.id })] })] }) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "order-details-collapsed flex w-full items-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "order-details-collapsed-divider divider w-full" }), (0, jsx_runtime_1.jsx)("button", { className: "order-details-collapsed-button whitespace-nowrap text-sm", onClick: () => setShowOrderDetails(true), children: "Order Details" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "order-details-collapsed-chevron text-as-primary mx-1 h-4 min-h-4 w-4 min-w-4" }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-collapsed-divider divider w-full" })] })) }));
38
+ : order.type === "custom"
39
+ ? order.metadata.action
40
+ ? (0, anyspend_1.capitalizeFirstLetter)(order.metadata.action)
41
+ : "Contract execution"
42
+ : "" }), (0, jsx_runtime_1.jsxs)("div", { className: "order-details-expected-value flex items-end gap-2", children: [order.type === "swap" ? (`~${finalFormattedExpectedDstAmount} ${dstToken.symbol}`) : order.type === "mint_nft" ? ((0, jsx_runtime_1.jsxs)("div", { className: "order-details-nft-info flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("img", { src: nft?.imageUrl, alt: nft?.name || "NFT", className: "order-details-nft-image h-5 w-5" }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-nft-name", children: nft?.name || "NFT" })] })) : order.type === "join_tournament" || order.type === "fund_tournament" ? ((0, jsx_runtime_1.jsxs)("div", { className: "order-details-tournament-info flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("img", { src: tournament?.imageUrl, alt: tournament?.name || "Tournament", className: "order-details-tournament-image h-5 w-5" }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-tournament-name", children: tournament?.name || "Tournament" })] })) : order.type === "hype_duel" ? ((0, jsx_runtime_1.jsx)("div", { className: "order-details-hype-info flex items-center gap-2", children: (0, jsx_runtime_1.jsxs)("div", { className: "order-details-hype-amount", children: [(0, number_1.formatTokenAmount)(BigInt(order.payload.expectedDstAmount), dstToken.decimals), " HYPE"] }) })) : null, (0, jsx_runtime_1.jsxs)("div", { className: "order-details-chain-info text-as-primary/50 flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("span", { className: "order-details-chain-text", children: ["on ", order.dstChain !== chains_1.b3.id && (0, anyspend_1.getChainName)(order.dstChain)] }), (0, jsx_runtime_1.jsx)("img", { src: anyspend_1.ALL_CHAINS[order.dstChain].logoUrl, alt: (0, anyspend_1.getChainName)(order.dstChain), className: (0, utils_1.cn)("order-details-chain-logo h-3", order.dstChain !== chains_1.b3.id && "w-3 rounded-full", order.dstChain === chains_1.b3.id && "h-4") })] })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-divider divider w-full" }), (0, jsx_runtime_1.jsxs)("div", { className: "order-details-id-total-section flex w-full justify-between gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "order-details-id-total-label text-as-tertiarry", children: showTotal ? "Total (included fee)" : "Order ID" }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-id-total-value text-as-primary overflow-hidden text-ellipsis whitespace-nowrap", children: showTotal && totalAmount ? totalAmount : order.id })] })] }) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "order-details-collapsed flex w-full items-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "order-details-collapsed-divider divider w-full" }), (0, jsx_runtime_1.jsx)("button", { className: "order-details-collapsed-button whitespace-nowrap text-sm", onClick: () => setShowOrderDetails(true), children: "Order Details" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "order-details-collapsed-chevron text-as-primary mx-1 h-4 min-h-4 w-4 min-w-4" }), (0, jsx_runtime_1.jsx)("div", { className: "order-details-collapsed-divider divider w-full" })] })) }));
45
43
  });
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TokenBalance = TokenBalance;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const chain_1 = require("../../../../anyspend/utils/chain");
6
+ const token_1 = require("../../../../anyspend/utils/token");
5
7
  const react_1 = require("../../../../global-account/react");
6
8
  const viem_1 = require("viem");
7
9
  function TokenBalance({ token, walletAddress, onChangeInput, }) {
@@ -12,9 +14,24 @@ function TokenBalance({ token, walletAddress, onChangeInput, }) {
12
14
  const handlePercentageClick = (percentage) => {
13
15
  if (!rawBalance)
14
16
  return;
15
- // Calculate the amount based on percentage of balance
16
- // Multiply first, then divide to avoid BigInt truncation
17
- const amount = percentage === 100 ? rawBalance : (rawBalance * BigInt(percentage)) / BigInt(100);
17
+ let amount;
18
+ if (percentage === 100) {
19
+ // For MAX button on native tokens, reserve gas for the transaction
20
+ if ((0, token_1.isNativeToken)(token.address)) {
21
+ const gasReserve = (0, chain_1.getNativeRequired)(token.chainId);
22
+ // Ensure we don't go negative
23
+ amount = rawBalance > gasReserve ? rawBalance - gasReserve : BigInt(0);
24
+ }
25
+ else {
26
+ // For ERC20 tokens, use full balance
27
+ amount = rawBalance;
28
+ }
29
+ }
30
+ else {
31
+ // Calculate the amount based on percentage of balance
32
+ // Multiply first, then divide to avoid BigInt truncation
33
+ amount = (rawBalance * BigInt(percentage)) / BigInt(100);
34
+ }
18
35
  onChangeInput((0, viem_1.formatUnits)(amount, token.decimals));
19
36
  };
20
37
  return ((0, jsx_runtime_1.jsx)("div", { className: "flex h-7 items-center justify-end gap-1", children: !isLoading && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary/50 inline-flex rounded-lg text-sm", children: rawBalance ? `Balance: ${formattedBalance}` : `Balance: 0` }), !!rawBalance && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("button", { onClick: () => handlePercentageClick(100), className: "text-as-primary/50 bg-as-on-surface-2 hover:bg-as-on-surface-3 inline-flex cursor-pointer rounded-lg px-2 py-1 text-xs transition-colors", children: "MAX" }) }))] })) }, `balance-${token.address}-${token.chainId}`));
@@ -13,13 +13,13 @@ export interface IBaseChain {
13
13
  canDepositNative: boolean;
14
14
  defaultToken: components["schemas"]["Token"];
15
15
  nativeToken: components["schemas"]["Token"];
16
+ coingeckoName: string | null;
16
17
  }
17
18
  export interface IEVMChain extends IBaseChain {
18
19
  type: ChainType.EVM;
19
20
  viem: Chain;
20
21
  pollingInterval: number;
21
22
  zapperEnum?: string;
22
- coingeckoName?: string;
23
23
  }
24
24
  export interface ISolanaChain extends IBaseChain {
25
25
  type: ChainType.SOLANA;
@@ -18,6 +18,7 @@ export declare function isMainnet(chainId: number): boolean;
18
18
  export declare function isTestnet(chainId: number): boolean;
19
19
  export declare function getDefaultToken(chainId: number): components["schemas"]["Token"];
20
20
  export declare function getChainName(chainId: number): string;
21
+ export declare function getCoingeckoName(chainId: number): string | null;
21
22
  export declare function getPaymentUrl(address: string, amount: bigint, currency: string, chainId: number, decimals?: number): string;
22
23
  export declare function getExplorerTxUrl(chainId: number, txHash: string): string;
23
24
  export declare function getExplorerAddressUrl(chainId: number, address: string): string;
@@ -15,6 +15,7 @@ exports.isMainnet = isMainnet;
15
15
  exports.isTestnet = isTestnet;
16
16
  exports.getDefaultToken = getDefaultToken;
17
17
  exports.getChainName = getChainName;
18
+ exports.getCoingeckoName = getCoingeckoName;
18
19
  exports.getPaymentUrl = getPaymentUrl;
19
20
  exports.getExplorerTxUrl = getExplorerTxUrl;
20
21
  exports.getExplorerAddressUrl = getExplorerAddressUrl;
@@ -150,6 +151,20 @@ exports.EVM_MAINNET = {
150
151
  zapperEnum: "B3_MAINNET",
151
152
  coingeckoName: "b3",
152
153
  },
154
+ [chains_1.abstract.id]: {
155
+ id: chains_1.abstract.id,
156
+ name: chains_1.abstract.name,
157
+ logoUrl: "https://assets.relay.link/icons/square/2741/light.png",
158
+ type: chain_1.ChainType.EVM,
159
+ nativeRequired: (0, viem_1.parseEther)("0.0001"),
160
+ canDepositNative: true,
161
+ defaultToken: (0, token_1.getEthToken)(chains_1.abstract.id),
162
+ nativeToken: (0, token_1.getEthToken)(chains_1.abstract.id),
163
+ viem: getCustomEvmChain(chains_1.abstract, "https://cosmopolitan-nameless-mountain.abstract-mainnet.quiknode.pro/863853304b986b582bdacf625ce3350397c560f8/"),
164
+ pollingInterval: 3000, // 3 seconds for Abstract
165
+ zapperEnum: "B3_MAINNET",
166
+ coingeckoName: "b3",
167
+ },
153
168
  };
154
169
  exports.EVM_TESTNET = {
155
170
  [chains_1.sepolia.id]: {
@@ -163,6 +178,7 @@ exports.EVM_TESTNET = {
163
178
  nativeToken: (0, token_1.getEthToken)(chains_1.sepolia.id),
164
179
  viem: chains_1.sepolia,
165
180
  pollingInterval: 1000, // 1 second for Sepolia
181
+ coingeckoName: "sepolia-testnet",
166
182
  },
167
183
  [chains_1.baseSepolia.id]: {
168
184
  id: chains_1.baseSepolia.id,
@@ -175,6 +191,7 @@ exports.EVM_TESTNET = {
175
191
  nativeToken: (0, token_1.getEthToken)(chains_1.baseSepolia.id),
176
192
  viem: chains_1.baseSepolia,
177
193
  pollingInterval: 1000, // 1 second for Base Sepolia
194
+ coingeckoName: null,
178
195
  },
179
196
  [chains_1.b3Sepolia.id]: {
180
197
  id: chains_1.b3Sepolia.id,
@@ -187,6 +204,7 @@ exports.EVM_TESTNET = {
187
204
  nativeToken: (0, token_1.getEthToken)(chains_1.b3Sepolia.id),
188
205
  viem: chains_1.b3Sepolia,
189
206
  pollingInterval: 1000, // 1 second for B3 Sepolia
207
+ coingeckoName: null,
190
208
  },
191
209
  // [b4testnet.id]: {
192
210
  // id: b4testnet.id,
@@ -206,6 +224,7 @@ exports.SOLANA_MAINNET = {
206
224
  canDepositNative: true,
207
225
  defaultToken: (0, token_1.getSolanaToken)(),
208
226
  nativeToken: (0, token_1.getSolanaToken)(),
227
+ coingeckoName: "solana",
209
228
  };
210
229
  exports.EVM_CHAINS = { ...exports.EVM_MAINNET, ...exports.EVM_TESTNET };
211
230
  exports.SOLANA_CHAINS = { [constants_1.RELAY_SOLANA_MAINNET_CHAIN_ID]: exports.SOLANA_MAINNET };
@@ -260,6 +279,10 @@ function getChainName(chainId) {
260
279
  (0, invariant_1.default)(exports.ALL_CHAINS[chainId], `Chain ${chainId} is not supported`);
261
280
  return exports.EVM_CHAINS[chainId] ? exports.EVM_CHAINS[chainId].viem.name : "Solana";
262
281
  }
282
+ function getCoingeckoName(chainId) {
283
+ (0, invariant_1.default)(exports.ALL_CHAINS[chainId], `Chain ${chainId} is not supported`);
284
+ return exports.ALL_CHAINS[chainId].coingeckoName;
285
+ }
263
286
  function getPaymentUrl(address, amount, currency, chainId, decimals) {
264
287
  // Get chain type to determine URL format
265
288
  const chainType = getChainType(chainId);
@@ -23,17 +23,15 @@ export const OrderDetailsCollapsible = memo(function OrderDetailsCollapsible({ o
23
23
  const finalFormattedExpectedDstAmount = formattedExpectedDstAmount || formatTokenAmount(BigInt(expectedDstAmount), dstToken.decimals);
24
24
  return (_jsx("div", { className: cn("order-details-collapsible bg-as-surface-secondary border-as-border-secondary rounded-xl border px-4 py-2", className), children: showOrderDetails ? (_jsx(motion.div, { className: "order-details-expanded w-full", initial: { opacity: 0, y: 20, filter: "blur(10px)" }, animate: { opacity: 1, y: 0, filter: "blur(0px)" }, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, children: _jsxs("div", { className: "order-details-content flex w-full flex-col items-center gap-3 whitespace-nowrap py-2 text-sm", children: [_jsxs("div", { className: "order-details-recipient-section flex w-full justify-between gap-4", children: [_jsx("div", { className: "order-details-recipient-label text-as-tertiarry", children: "Recipient" }), _jsxs("div", { className: "order-details-recipient-info flex flex-col items-end gap-1", children: [recipientName && (_jsx("div", { className: "order-details-recipient-name text-as-primary font-semibold", children: recipientName })), _jsx(CopyToClipboard, { text: order.recipientAddress, onCopy: () => {
25
25
  toast.success("Copied recipient address to clipboard");
26
- }, children: _jsxs("div", { className: "order-details-recipient-address text-as-primary flex items-center gap-2", children: [centerTruncate(order.recipientAddress, 10), _jsx(Copy, { className: "order-details-recipient-copy-icon text-as-primary/50 hover:text-as-primary h-4 w-4 cursor-pointer transition-all duration-200" })] }) })] })] }), _jsx("div", { className: "order-details-divider divider w-full" }), _jsxs("div", { className: "order-details-expected-section flex w-full items-center justify-between gap-2", children: [_jsx("div", { className: "order-details-expected-label text-as-tertiarry", children: order.type === "swap" || order.type === "mint_nft"
26
+ }, children: _jsxs("div", { className: "order-details-recipient-address text-as-primary flex items-center gap-2", children: [centerTruncate(order.recipientAddress, 10), _jsx(Copy, { className: "order-details-recipient-copy-icon text-as-primary/50 hover:text-as-primary h-4 w-4 cursor-pointer transition-all duration-200" })] }) })] })] }), _jsx("div", { className: "order-details-divider divider w-full" }), _jsxs("div", { className: "order-details-expected-section flex w-full items-center justify-between gap-2", children: [_jsx("div", { className: "order-details-expected-label text-as-tertiarry", children: order.type === "swap" || order.type === "mint_nft" || order.type === "hype_duel"
27
27
  ? "Expected to receive"
28
28
  : order.type === "join_tournament"
29
29
  ? "Join tournament"
30
30
  : order.type === "fund_tournament"
31
31
  ? "Fund tournament"
32
- : order.type === "hype_duel"
33
- ? "Deposit HYPE"
34
- : order.type === "custom"
35
- ? order.metadata.action
36
- ? capitalizeFirstLetter(order.metadata.action)
37
- : "Contract execution"
38
- : "" }), _jsxs("div", { className: "order-details-expected-value flex items-end gap-2", children: [order.type === "swap" ? (`~${finalFormattedExpectedDstAmount} ${dstToken.symbol}`) : order.type === "mint_nft" ? (_jsxs("div", { className: "order-details-nft-info flex items-center gap-2", children: [_jsx("img", { src: nft?.imageUrl, alt: nft?.name || "NFT", className: "order-details-nft-image h-5 w-5" }), _jsx("div", { className: "order-details-nft-name", children: nft?.name || "NFT" })] })) : order.type === "join_tournament" || order.type === "fund_tournament" ? (_jsxs("div", { className: "order-details-tournament-info flex items-center gap-2", children: [_jsx("img", { src: tournament?.imageUrl, alt: tournament?.name || "Tournament", className: "order-details-tournament-image h-5 w-5" }), _jsx("div", { className: "order-details-tournament-name", children: tournament?.name || "Tournament" })] })) : order.type === "hype_duel" ? (_jsx("div", { className: "order-details-hype-info flex items-center gap-2", children: _jsxs("div", { className: "order-details-hype-amount", children: [formatTokenAmount(BigInt(order.payload.expectedDstAmount), dstToken.decimals), " HYPE"] }) })) : null, _jsxs("div", { className: "order-details-chain-info text-as-primary/50 flex items-center gap-2", children: [_jsxs("span", { className: "order-details-chain-text", children: ["on ", order.dstChain !== b3.id && getChainName(order.dstChain)] }), _jsx("img", { src: ALL_CHAINS[order.dstChain].logoUrl, alt: getChainName(order.dstChain), className: cn("order-details-chain-logo h-3", order.dstChain !== b3.id && "w-3 rounded-full", order.dstChain === b3.id && "h-4") })] })] })] }), _jsx("div", { className: "order-details-divider divider w-full" }), _jsxs("div", { className: "order-details-id-total-section flex w-full justify-between gap-4", children: [_jsx("div", { className: "order-details-id-total-label text-as-tertiarry", children: showTotal ? "Total (included fee)" : "Order ID" }), _jsx("div", { className: "order-details-id-total-value text-as-primary overflow-hidden text-ellipsis whitespace-nowrap", children: showTotal && totalAmount ? totalAmount : order.id })] })] }) })) : (_jsxs("div", { className: "order-details-collapsed flex w-full items-center", children: [_jsx("div", { className: "order-details-collapsed-divider divider w-full" }), _jsx("button", { className: "order-details-collapsed-button whitespace-nowrap text-sm", onClick: () => setShowOrderDetails(true), children: "Order Details" }), _jsx(ChevronDown, { className: "order-details-collapsed-chevron text-as-primary mx-1 h-4 min-h-4 w-4 min-w-4" }), _jsx("div", { className: "order-details-collapsed-divider divider w-full" })] })) }));
32
+ : order.type === "custom"
33
+ ? order.metadata.action
34
+ ? capitalizeFirstLetter(order.metadata.action)
35
+ : "Contract execution"
36
+ : "" }), _jsxs("div", { className: "order-details-expected-value flex items-end gap-2", children: [order.type === "swap" ? (`~${finalFormattedExpectedDstAmount} ${dstToken.symbol}`) : order.type === "mint_nft" ? (_jsxs("div", { className: "order-details-nft-info flex items-center gap-2", children: [_jsx("img", { src: nft?.imageUrl, alt: nft?.name || "NFT", className: "order-details-nft-image h-5 w-5" }), _jsx("div", { className: "order-details-nft-name", children: nft?.name || "NFT" })] })) : order.type === "join_tournament" || order.type === "fund_tournament" ? (_jsxs("div", { className: "order-details-tournament-info flex items-center gap-2", children: [_jsx("img", { src: tournament?.imageUrl, alt: tournament?.name || "Tournament", className: "order-details-tournament-image h-5 w-5" }), _jsx("div", { className: "order-details-tournament-name", children: tournament?.name || "Tournament" })] })) : order.type === "hype_duel" ? (_jsx("div", { className: "order-details-hype-info flex items-center gap-2", children: _jsxs("div", { className: "order-details-hype-amount", children: [formatTokenAmount(BigInt(order.payload.expectedDstAmount), dstToken.decimals), " HYPE"] }) })) : null, _jsxs("div", { className: "order-details-chain-info text-as-primary/50 flex items-center gap-2", children: [_jsxs("span", { className: "order-details-chain-text", children: ["on ", order.dstChain !== b3.id && getChainName(order.dstChain)] }), _jsx("img", { src: ALL_CHAINS[order.dstChain].logoUrl, alt: getChainName(order.dstChain), className: cn("order-details-chain-logo h-3", order.dstChain !== b3.id && "w-3 rounded-full", order.dstChain === b3.id && "h-4") })] })] })] }), _jsx("div", { className: "order-details-divider divider w-full" }), _jsxs("div", { className: "order-details-id-total-section flex w-full justify-between gap-4", children: [_jsx("div", { className: "order-details-id-total-label text-as-tertiarry", children: showTotal ? "Total (included fee)" : "Order ID" }), _jsx("div", { className: "order-details-id-total-value text-as-primary overflow-hidden text-ellipsis whitespace-nowrap", children: showTotal && totalAmount ? totalAmount : order.id })] })] }) })) : (_jsxs("div", { className: "order-details-collapsed flex w-full items-center", children: [_jsx("div", { className: "order-details-collapsed-divider divider w-full" }), _jsx("button", { className: "order-details-collapsed-button whitespace-nowrap text-sm", onClick: () => setShowOrderDetails(true), children: "Order Details" }), _jsx(ChevronDown, { className: "order-details-collapsed-chevron text-as-primary mx-1 h-4 min-h-4 w-4 min-w-4" }), _jsx("div", { className: "order-details-collapsed-divider divider w-full" })] })) }));
39
37
  });
@@ -1,4 +1,6 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { getNativeRequired } from "../../../../anyspend/utils/chain.js";
3
+ import { isNativeToken } from "../../../../anyspend/utils/token.js";
2
4
  import { useTokenBalance } from "../../../../global-account/react/index.js";
3
5
  import { formatUnits } from "viem";
4
6
  export function TokenBalance({ token, walletAddress, onChangeInput, }) {
@@ -9,9 +11,24 @@ export function TokenBalance({ token, walletAddress, onChangeInput, }) {
9
11
  const handlePercentageClick = (percentage) => {
10
12
  if (!rawBalance)
11
13
  return;
12
- // Calculate the amount based on percentage of balance
13
- // Multiply first, then divide to avoid BigInt truncation
14
- const amount = percentage === 100 ? rawBalance : (rawBalance * BigInt(percentage)) / BigInt(100);
14
+ let amount;
15
+ if (percentage === 100) {
16
+ // For MAX button on native tokens, reserve gas for the transaction
17
+ if (isNativeToken(token.address)) {
18
+ const gasReserve = getNativeRequired(token.chainId);
19
+ // Ensure we don't go negative
20
+ amount = rawBalance > gasReserve ? rawBalance - gasReserve : BigInt(0);
21
+ }
22
+ else {
23
+ // For ERC20 tokens, use full balance
24
+ amount = rawBalance;
25
+ }
26
+ }
27
+ else {
28
+ // Calculate the amount based on percentage of balance
29
+ // Multiply first, then divide to avoid BigInt truncation
30
+ amount = (rawBalance * BigInt(percentage)) / BigInt(100);
31
+ }
15
32
  onChangeInput(formatUnits(amount, token.decimals));
16
33
  };
17
34
  return (_jsx("div", { className: "flex h-7 items-center justify-end gap-1", children: !isLoading && (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-as-primary/50 inline-flex rounded-lg text-sm", children: rawBalance ? `Balance: ${formattedBalance}` : `Balance: 0` }), !!rawBalance && (_jsx(_Fragment, { children: _jsx("button", { onClick: () => handlePercentageClick(100), className: "text-as-primary/50 bg-as-on-surface-2 hover:bg-as-on-surface-3 inline-flex cursor-pointer rounded-lg px-2 py-1 text-xs transition-colors", children: "MAX" }) }))] })) }, `balance-${token.address}-${token.chainId}`));
@@ -13,13 +13,13 @@ export interface IBaseChain {
13
13
  canDepositNative: boolean;
14
14
  defaultToken: components["schemas"]["Token"];
15
15
  nativeToken: components["schemas"]["Token"];
16
+ coingeckoName: string | null;
16
17
  }
17
18
  export interface IEVMChain extends IBaseChain {
18
19
  type: ChainType.EVM;
19
20
  viem: Chain;
20
21
  pollingInterval: number;
21
22
  zapperEnum?: string;
22
- coingeckoName?: string;
23
23
  }
24
24
  export interface ISolanaChain extends IBaseChain {
25
25
  type: ChainType.SOLANA;
@@ -18,6 +18,7 @@ export declare function isMainnet(chainId: number): boolean;
18
18
  export declare function isTestnet(chainId: number): boolean;
19
19
  export declare function getDefaultToken(chainId: number): components["schemas"]["Token"];
20
20
  export declare function getChainName(chainId: number): string;
21
+ export declare function getCoingeckoName(chainId: number): string | null;
21
22
  export declare function getPaymentUrl(address: string, amount: bigint, currency: string, chainId: number, decimals?: number): string;
22
23
  export declare function getExplorerTxUrl(chainId: number, txHash: string): string;
23
24
  export declare function getExplorerAddressUrl(chainId: number, address: string): string;
@@ -1,7 +1,7 @@
1
1
  import { RELAY_SOLANA_MAINNET_CHAIN_ID } from "../../anyspend/constants/index.js";
2
2
  import invariant from "invariant";
3
3
  import { createPublicClient, createWalletClient, defineChain, http, parseEther, } from "viem";
4
- import { arbitrum, avalanche, b3, b3Sepolia, base, baseSepolia, bsc, mainnet, optimism, polygon, sepolia, } from "viem/chains";
4
+ import { abstract, arbitrum, avalanche, b3, b3Sepolia, base, baseSepolia, bsc, mainnet, optimism, polygon, sepolia, } from "viem/chains";
5
5
  import { ChainType } from "../types/chain.js";
6
6
  import { getAvaxToken, getBnbToken, getEthToken, getPolToken, getSolanaToken } from "./token.js";
7
7
  function getCustomEvmChain(chain, rpcUrl) {
@@ -127,6 +127,20 @@ export const EVM_MAINNET = {
127
127
  zapperEnum: "B3_MAINNET",
128
128
  coingeckoName: "b3",
129
129
  },
130
+ [abstract.id]: {
131
+ id: abstract.id,
132
+ name: abstract.name,
133
+ logoUrl: "https://assets.relay.link/icons/square/2741/light.png",
134
+ type: ChainType.EVM,
135
+ nativeRequired: parseEther("0.0001"),
136
+ canDepositNative: true,
137
+ defaultToken: getEthToken(abstract.id),
138
+ nativeToken: getEthToken(abstract.id),
139
+ viem: getCustomEvmChain(abstract, "https://cosmopolitan-nameless-mountain.abstract-mainnet.quiknode.pro/863853304b986b582bdacf625ce3350397c560f8/"),
140
+ pollingInterval: 3000, // 3 seconds for Abstract
141
+ zapperEnum: "B3_MAINNET",
142
+ coingeckoName: "b3",
143
+ },
130
144
  };
131
145
  export const EVM_TESTNET = {
132
146
  [sepolia.id]: {
@@ -140,6 +154,7 @@ export const EVM_TESTNET = {
140
154
  nativeToken: getEthToken(sepolia.id),
141
155
  viem: sepolia,
142
156
  pollingInterval: 1000, // 1 second for Sepolia
157
+ coingeckoName: "sepolia-testnet",
143
158
  },
144
159
  [baseSepolia.id]: {
145
160
  id: baseSepolia.id,
@@ -152,6 +167,7 @@ export const EVM_TESTNET = {
152
167
  nativeToken: getEthToken(baseSepolia.id),
153
168
  viem: baseSepolia,
154
169
  pollingInterval: 1000, // 1 second for Base Sepolia
170
+ coingeckoName: null,
155
171
  },
156
172
  [b3Sepolia.id]: {
157
173
  id: b3Sepolia.id,
@@ -164,6 +180,7 @@ export const EVM_TESTNET = {
164
180
  nativeToken: getEthToken(b3Sepolia.id),
165
181
  viem: b3Sepolia,
166
182
  pollingInterval: 1000, // 1 second for B3 Sepolia
183
+ coingeckoName: null,
167
184
  },
168
185
  // [b4testnet.id]: {
169
186
  // id: b4testnet.id,
@@ -183,6 +200,7 @@ export const SOLANA_MAINNET = {
183
200
  canDepositNative: true,
184
201
  defaultToken: getSolanaToken(),
185
202
  nativeToken: getSolanaToken(),
203
+ coingeckoName: "solana",
186
204
  };
187
205
  export const EVM_CHAINS = { ...EVM_MAINNET, ...EVM_TESTNET };
188
206
  export const SOLANA_CHAINS = { [RELAY_SOLANA_MAINNET_CHAIN_ID]: SOLANA_MAINNET };
@@ -237,6 +255,10 @@ export function getChainName(chainId) {
237
255
  invariant(ALL_CHAINS[chainId], `Chain ${chainId} is not supported`);
238
256
  return EVM_CHAINS[chainId] ? EVM_CHAINS[chainId].viem.name : "Solana";
239
257
  }
258
+ export function getCoingeckoName(chainId) {
259
+ invariant(ALL_CHAINS[chainId], `Chain ${chainId} is not supported`);
260
+ return ALL_CHAINS[chainId].coingeckoName;
261
+ }
240
262
  export function getPaymentUrl(address, amount, currency, chainId, decimals) {
241
263
  // Get chain type to determine URL format
242
264
  const chainType = getChainType(chainId);
@@ -13,13 +13,13 @@ export interface IBaseChain {
13
13
  canDepositNative: boolean;
14
14
  defaultToken: components["schemas"]["Token"];
15
15
  nativeToken: components["schemas"]["Token"];
16
+ coingeckoName: string | null;
16
17
  }
17
18
  export interface IEVMChain extends IBaseChain {
18
19
  type: ChainType.EVM;
19
20
  viem: Chain;
20
21
  pollingInterval: number;
21
22
  zapperEnum?: string;
22
- coingeckoName?: string;
23
23
  }
24
24
  export interface ISolanaChain extends IBaseChain {
25
25
  type: ChainType.SOLANA;
@@ -18,6 +18,7 @@ export declare function isMainnet(chainId: number): boolean;
18
18
  export declare function isTestnet(chainId: number): boolean;
19
19
  export declare function getDefaultToken(chainId: number): components["schemas"]["Token"];
20
20
  export declare function getChainName(chainId: number): string;
21
+ export declare function getCoingeckoName(chainId: number): string | null;
21
22
  export declare function getPaymentUrl(address: string, amount: bigint, currency: string, chainId: number, decimals?: number): string;
22
23
  export declare function getExplorerTxUrl(chainId: number, txHash: string): string;
23
24
  export declare function getExplorerAddressUrl(chainId: number, address: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.48",
3
+ "version": "0.0.49",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -95,19 +95,17 @@ export const OrderDetailsCollapsible = memo(function OrderDetailsCollapsible({
95
95
  {/* Expected Amount/Action Section */}
96
96
  <div className="order-details-expected-section flex w-full items-center justify-between gap-2">
97
97
  <div className="order-details-expected-label text-as-tertiarry">
98
- {order.type === "swap" || order.type === "mint_nft"
98
+ {order.type === "swap" || order.type === "mint_nft" || order.type === "hype_duel"
99
99
  ? "Expected to receive"
100
100
  : order.type === "join_tournament"
101
101
  ? "Join tournament"
102
102
  : order.type === "fund_tournament"
103
103
  ? "Fund tournament"
104
- : order.type === "hype_duel"
105
- ? "Deposit HYPE"
106
- : order.type === "custom"
107
- ? order.metadata.action
108
- ? capitalizeFirstLetter(order.metadata.action)
109
- : "Contract execution"
110
- : ""}
104
+ : order.type === "custom"
105
+ ? order.metadata.action
106
+ ? capitalizeFirstLetter(order.metadata.action)
107
+ : "Contract execution"
108
+ : ""}
111
109
  </div>
112
110
 
113
111
  <div className="order-details-expected-value flex items-end gap-2">
@@ -1,4 +1,6 @@
1
1
  import { components } from "@b3dotfun/sdk/anyspend/types/api";
2
+ import { getNativeRequired } from "@b3dotfun/sdk/anyspend/utils/chain";
3
+ import { isNativeToken } from "@b3dotfun/sdk/anyspend/utils/token";
2
4
  import { useTokenBalance } from "@b3dotfun/sdk/global-account/react";
3
5
  import { formatUnits } from "viem";
4
6
 
@@ -19,9 +21,23 @@ export function TokenBalance({
19
21
  const handlePercentageClick = (percentage: number) => {
20
22
  if (!rawBalance) return;
21
23
 
22
- // Calculate the amount based on percentage of balance
23
- // Multiply first, then divide to avoid BigInt truncation
24
- const amount = percentage === 100 ? rawBalance : (rawBalance * BigInt(percentage)) / BigInt(100);
24
+ let amount: bigint;
25
+
26
+ if (percentage === 100) {
27
+ // For MAX button on native tokens, reserve gas for the transaction
28
+ if (isNativeToken(token.address)) {
29
+ const gasReserve = getNativeRequired(token.chainId);
30
+ // Ensure we don't go negative
31
+ amount = rawBalance > gasReserve ? rawBalance - gasReserve : BigInt(0);
32
+ } else {
33
+ // For ERC20 tokens, use full balance
34
+ amount = rawBalance;
35
+ }
36
+ } else {
37
+ // Calculate the amount based on percentage of balance
38
+ // Multiply first, then divide to avoid BigInt truncation
39
+ amount = (rawBalance * BigInt(percentage)) / BigInt(100);
40
+ }
25
41
 
26
42
  onChangeInput(formatUnits(amount, token.decimals));
27
43
  };
@@ -15,6 +15,7 @@ export interface IBaseChain {
15
15
  canDepositNative: boolean;
16
16
  defaultToken: components["schemas"]["Token"];
17
17
  nativeToken: components["schemas"]["Token"];
18
+ coingeckoName: string | null;
18
19
  }
19
20
 
20
21
  export interface IEVMChain extends IBaseChain {
@@ -22,7 +23,6 @@ export interface IEVMChain extends IBaseChain {
22
23
  viem: Chain;
23
24
  pollingInterval: number;
24
25
  zapperEnum?: string;
25
- coingeckoName?: string;
26
26
  }
27
27
 
28
28
  export interface ISolanaChain extends IBaseChain {
@@ -14,6 +14,7 @@ import {
14
14
  WalletClient,
15
15
  } from "viem";
16
16
  import {
17
+ abstract,
17
18
  arbitrum,
18
19
  avalanche,
19
20
  b3,
@@ -172,6 +173,23 @@ export const EVM_MAINNET: Record<number, IEVMChain> = {
172
173
  zapperEnum: "B3_MAINNET",
173
174
  coingeckoName: "b3",
174
175
  },
176
+ [abstract.id]: {
177
+ id: abstract.id,
178
+ name: abstract.name,
179
+ logoUrl: "https://assets.relay.link/icons/square/2741/light.png",
180
+ type: ChainType.EVM,
181
+ nativeRequired: parseEther("0.0001"),
182
+ canDepositNative: true,
183
+ defaultToken: getEthToken(abstract.id),
184
+ nativeToken: getEthToken(abstract.id),
185
+ viem: getCustomEvmChain(
186
+ abstract,
187
+ "https://cosmopolitan-nameless-mountain.abstract-mainnet.quiknode.pro/863853304b986b582bdacf625ce3350397c560f8/",
188
+ ),
189
+ pollingInterval: 3000, // 3 seconds for Abstract
190
+ zapperEnum: "B3_MAINNET",
191
+ coingeckoName: "b3",
192
+ },
175
193
  };
176
194
 
177
195
  export const EVM_TESTNET: Record<number, IEVMChain> = {
@@ -186,6 +204,7 @@ export const EVM_TESTNET: Record<number, IEVMChain> = {
186
204
  nativeToken: getEthToken(sepolia.id),
187
205
  viem: sepolia,
188
206
  pollingInterval: 1000, // 1 second for Sepolia
207
+ coingeckoName: "sepolia-testnet",
189
208
  },
190
209
  [baseSepolia.id]: {
191
210
  id: baseSepolia.id,
@@ -198,6 +217,7 @@ export const EVM_TESTNET: Record<number, IEVMChain> = {
198
217
  nativeToken: getEthToken(baseSepolia.id),
199
218
  viem: baseSepolia,
200
219
  pollingInterval: 1000, // 1 second for Base Sepolia
220
+ coingeckoName: null,
201
221
  },
202
222
  [b3Sepolia.id]: {
203
223
  id: b3Sepolia.id,
@@ -210,6 +230,7 @@ export const EVM_TESTNET: Record<number, IEVMChain> = {
210
230
  nativeToken: getEthToken(b3Sepolia.id),
211
231
  viem: b3Sepolia,
212
232
  pollingInterval: 1000, // 1 second for B3 Sepolia
233
+ coingeckoName: null,
213
234
  },
214
235
  // [b4testnet.id]: {
215
236
  // id: b4testnet.id,
@@ -230,6 +251,7 @@ export const SOLANA_MAINNET: ISolanaChain = {
230
251
  canDepositNative: true,
231
252
  defaultToken: getSolanaToken(),
232
253
  nativeToken: getSolanaToken(),
254
+ coingeckoName: "solana",
233
255
  };
234
256
 
235
257
  export const EVM_CHAINS: Record<number, IEVMChain> = { ...EVM_MAINNET, ...EVM_TESTNET };
@@ -301,6 +323,11 @@ export function getChainName(chainId: number): string {
301
323
  return EVM_CHAINS[chainId] ? EVM_CHAINS[chainId].viem.name : "Solana";
302
324
  }
303
325
 
326
+ export function getCoingeckoName(chainId: number): string | null {
327
+ invariant(ALL_CHAINS[chainId], `Chain ${chainId} is not supported`);
328
+ return ALL_CHAINS[chainId].coingeckoName;
329
+ }
330
+
304
331
  export function getPaymentUrl(address: string, amount: bigint, currency: string, chainId: number, decimals?: number) {
305
332
  // Get chain type to determine URL format
306
333
  const chainType = getChainType(chainId);