UNPKG

@enclavemoney/enclave-wallet-sdk

Version:

A simple enclave wallet SDK for React applications

366 lines (365 loc) 20.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var react_1 = __importStar(require("react")); var lucide_react_1 = require("lucide-react"); var Spinner_1 = __importDefault(require("./ui/Spinner")); var services_1 = require("../services/services"); var TokenLogo_1 = require("./ui/TokenLogo"); var WalletProvider_1 = require("./WalletProvider"); var styles = "\n .hide-scrollbar::-webkit-scrollbar {\n display: none;\n }\n"; var TokenSelector = function (_a) { var title = _a.title, tokens = _a.tokens, onTokenSelect = _a.onTokenSelect, onBack = _a.onBack, _b = _a.isLoading, isLoading = _b === void 0 ? false : _b, tokenFilter = _a.tokenFilter, _c = _a.inSwap, inSwap = _c === void 0 ? false : _c, apiKey = _a.apiKey; var _d = (0, react_1.useState)(""), searchQuery = _d[0], setSearchQuery = _d[1]; var _e = (0, react_1.useState)(false), isSearching = _e[0], setIsSearching = _e[1]; var _f = (0, react_1.useState)([]), searchResults = _f[0], setSearchResults = _f[1]; var _g = (0, react_1.useState)(""), debouncedQuery = _g[0], setDebouncedQuery = _g[1]; var cryptoBalance = (0, WalletProvider_1.useWallet)().cryptoBalance; // Get user balance tokens var userBalanceTokens = (cryptoBalance === null || cryptoBalance === void 0 ? void 0 : cryptoBalance.data) || []; // Debounce search query (0, react_1.useEffect)(function () { var timer = setTimeout(function () { setDebouncedQuery(searchQuery); }, 300); // 300ms delay return function () { return clearTimeout(timer); }; }, [searchQuery]); // Perform search when debounced query changes (0, react_1.useEffect)(function () { var performSearch = function () { return __awaiter(void 0, void 0, void 0, function () { var result, mappedTokens, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!debouncedQuery) { setSearchResults([]); return [2 /*return*/]; } setIsSearching(true); _a.label = 1; case 1: _a.trys.push([1, 3, 4, 5]); return [4 /*yield*/, (0, services_1.searchTokensByQuery)(debouncedQuery, apiKey)]; case 2: result = _a.sent(); if ((result === null || result === void 0 ? void 0 : result.success) && result.data) { mappedTokens = result.data.map(function (token) { var _a, _b, _c, _d, _e; return ({ symbol: token.symbol, name: token.name, icon: token.logoURI, logoURI: token.logoURI, address: ((_b = (_a = token.chainIds) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.address) || "", chainId: ((_d = (_c = token.chainIds) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.chainId) || 0, decimals: token.decimals, balance: undefined, amount: (_e = token.amount) === null || _e === void 0 ? void 0 : _e.toString(), chainIds: token.chainIds, price: token.price, priceUsd: token.priceUsd, }); }); setSearchResults(mappedTokens); } return [3 /*break*/, 5]; case 3: error_1 = _a.sent(); console.error("Error searching tokens:", error_1); return [3 /*break*/, 5]; case 4: setIsSearching(false); return [7 /*endfinally*/]; case 5: return [2 /*return*/]; } }); }); }; performSearch(); }, [debouncedQuery, apiKey]); // Filter user balance tokens based on search query var filteredUserTokens = (0, react_1.useMemo)(function () { if (!userBalanceTokens || userBalanceTokens.length === 0) return []; var filtered = userBalanceTokens; // Apply search filter if (searchQuery) { var query_1 = searchQuery.toLowerCase(); filtered = filtered.filter(function (token) { return token.name.toLowerCase().includes(query_1) || token.symbol.toLowerCase().includes(query_1) || (token.address && token.address.toLowerCase().includes(query_1)); }); } // Apply token filter if provided if (tokenFilter && tokenFilter.length > 0) { filtered = filtered.filter(function (token) { return tokenFilter.includes(token.symbol); }); } // Sort by valueUsd in descending order filtered = filtered.sort(function (a, b) { var valueA = a.valueUsd || 0; var valueB = b.valueUsd || 0; return valueB - valueA; }); return filtered; }, [userBalanceTokens, searchQuery, tokenFilter]); // Filter all tokens based on search query and exclude user balance tokens var filteredTokens = (0, react_1.useMemo)(function () { // If there's a search query and search results, show those instead if (debouncedQuery && searchResults.length > 0) { return searchResults; } var filtered = tokens; // Remove tokens that are already in user balances if (userBalanceTokens && userBalanceTokens.length > 0) { var userTokenKeys_1 = new Set(userBalanceTokens.flatMap(function (userToken) { var _a, _b; return ((_a = userToken.chainIds) === null || _a === void 0 ? void 0 : _a.map(function (chain) { return "".concat(chain.address.toLowerCase(), "-").concat(chain.chainId); })) || ["".concat((_b = userToken.address) === null || _b === void 0 ? void 0 : _b.toLowerCase(), "-").concat(userToken.chainId)]; })); filtered = filtered.filter(function (token) { var tokenKey = "".concat(token.address.toLowerCase(), "-").concat(token.chainId); return !userTokenKeys_1.has(tokenKey); }); } // Apply token filter if provided if (tokenFilter && tokenFilter.length > 0) { filtered = filtered.filter(function (token) { return tokenFilter.includes(token.symbol); }); } // Apply search filter if (searchQuery) { var query_2 = searchQuery.toLowerCase(); filtered = filtered.filter(function (token) { return token.name.toLowerCase().includes(query_2) || token.symbol.toLowerCase().includes(query_2) || (token.address && token.address.toLowerCase().includes(query_2)); }); } return filtered; }, [ tokens, userBalanceTokens, searchQuery, tokenFilter, debouncedQuery, searchResults, ]); // Helper function to render token rows var renderTokenRow = function (token, idx, isLastInSection, showBalance) { if (showBalance === void 0) { showBalance = false; } return (react_1.default.createElement("div", { key: "".concat(token.symbol, "-").concat(idx), style: { display: "flex", alignItems: "center", padding: "14px 0", borderBottom: !isLastInSection ? "1px solid #E9EAEB" : "none", cursor: "pointer", transition: "background 0.1s", }, onClick: function () { return onTokenSelect(token); } }, react_1.default.createElement(TokenLogo_1.TokenLogo, { logoURI: token.logoURI || token.icon, symbol: token.symbol, name: token.name, size: 36, style: { marginRight: 12 } }), react_1.default.createElement("div", { style: { flexGrow: 1 } }, react_1.default.createElement("div", { style: { fontWeight: 600 } }, token.name), react_1.default.createElement("div", { style: { color: "#666", fontSize: 12 } }, token.symbol)), showBalance && token.balance && (react_1.default.createElement("div", { style: { textAlign: "right" } }, token.valueUsd && (react_1.default.createElement("div", { style: { fontWeight: 600, fontSize: 16 } }, "$", (function () { var valueUsd = parseFloat(String((token === null || token === void 0 ? void 0 : token.valueUsd) || "0")); if (valueUsd > 0 && valueUsd < 0.0001) { return "<0.0001"; } return valueUsd.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2, }); })())), react_1.default.createElement("div", { style: { fontWeight: 400, fontSize: 12, color: "#666" } }, (function () { var amount = parseFloat((token === null || token === void 0 ? void 0 : token.amount) || "0"); if (amount > 0 && amount < 0.0001) { return "<0.0001"; } return amount.toLocaleString(undefined, { maximumFractionDigits: 6, }); })()))))); }; return (react_1.default.createElement(react_1.default.Fragment, null, react_1.default.createElement("style", null, styles), react_1.default.createElement("div", { style: { width: "100%", background: "#fff", borderRadius: 20, fontFamily: "Inter, sans-serif", display: "flex", flexDirection: "column", height: "550px", } }, react_1.default.createElement("div", { style: { display: "flex", alignItems: "center", marginBottom: 18, position: "relative", } }, react_1.default.createElement("button", { onClick: onBack, style: { background: "none", border: "none", fontSize: 22, color: "#222", cursor: "pointer", position: "absolute", left: 0, fontFamily: "Inter, sans-serif", padding: 0, margin: 0, outline: "none", } }, react_1.default.createElement(lucide_react_1.ArrowLeft, { style: { width: 24, height: 24, color: "#717680" } })), react_1.default.createElement("span", { style: { fontWeight: 600, fontSize: 20, width: "100%", textAlign: "center", } }, title)), react_1.default.createElement("div", { style: { position: "relative", marginBottom: 18 } }, isSearching ? (react_1.default.createElement("div", { style: { position: "absolute", left: 14, top: "50%", transform: "translateY(-50%)", } }, react_1.default.createElement(Spinner_1.default, null))) : (react_1.default.createElement(lucide_react_1.Search, { style: { position: "absolute", left: 14, top: "50%", transform: "translateY(-50%)", width: 18, height: 18, color: "#717680", } })), react_1.default.createElement("input", { type: "text", placeholder: "Search name or paste address...", value: searchQuery, onChange: function (e) { return setSearchQuery(e.target.value); }, style: { width: "100%", padding: "10px 14px 10px 40px", borderRadius: 10, border: "1px solid #E0E0E0", backgroundColor: "white", fontSize: 16, color: "#717680", outline: "none", } })), react_1.default.createElement("div", null, react_1.default.createElement("div", { style: { flex: 1, overflowY: "auto", maxHeight: "440px", paddingRight: 8, msOverflowStyle: "none", scrollbarWidth: "none", WebkitOverflowScrolling: "touch", }, className: "hide-scrollbar" }, isLoading || isSearching ? (react_1.default.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "200px", gap: "16px", } }, react_1.default.createElement(Spinner_1.default, null), react_1.default.createElement("span", { style: { color: "#717680", fontSize: 16 } }, isSearching ? "Searching Tokens..." : "Loading Tokens..."))) : filteredTokens.length === 0 && filteredUserTokens.length === 0 && debouncedQuery ? (react_1.default.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "200px", gap: "16px", } }, react_1.default.createElement("span", { style: { color: "#717680", fontSize: 16 } }, "No tokens found"))) : (react_1.default.createElement(react_1.default.Fragment, null, filteredUserTokens && filteredUserTokens.length > 0 && (react_1.default.createElement("div", null, react_1.default.createElement("div", { style: { fontWeight: 600, fontSize: 16, color: "#333", padding: "8px 0", marginBottom: 8, } }, "Your Tokens"), filteredUserTokens.map(function (token, idx) { return renderTokenRow(token, idx, idx === filteredUserTokens.length - 1, true); }))), filteredTokens.length > 0 && (react_1.default.createElement("div", { style: { marginTop: filteredUserTokens && filteredUserTokens.length > 0 ? 16 : 0, } }, react_1.default.createElement("div", { style: { fontWeight: 600, fontSize: 16, color: "#333", padding: "8px 0", marginBottom: 8, } }, filteredUserTokens && filteredUserTokens.length > 0 ? "All Tokens" : "Tokens"), filteredTokens.map(function (token, idx) { return renderTokenRow(token, idx, idx === filteredTokens.length - 1, false); })))))))))); }; exports.default = TokenSelector;