enclave-wallet-sdk
Version:
A simple enclave wallet SDK for React applications
564 lines (563 loc) • 28.8 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WalletModal = void 0;
var react_1 = __importStar(require("react"));
var enclavemoney_web_experimental_1 = require("enclavemoney-web-experimental");
var SwapToken_1 = require("./SwapToken");
var Dashboard_1 = require("./Dashboard");
var TransferToken_1 = __importDefault(require("./Transfer/TransferToken"));
var CryptoBalanceContext_1 = require("../context/CryptoBalanceContext");
var ActivityDetails_1 = __importDefault(require("./ActivityDetails"));
var enclaveLogo = "https://firebasestorage.googleapis.com/v0/b/enclave-wallet.appspot.com/o/enclave_black.png?alt=media&token=6e32e0d1-4ef5-44a5-9ba6-339852ba0359";
var StartStep = function (_a) {
var onNext = _a.onNext;
return (react_1.default.createElement(react_1.default.Fragment, null,
react_1.default.createElement("div", { style: { fontSize: 36, marginBottom: 10 } },
react_1.default.createElement("img", { src: "https://firebasestorage.googleapis.com/v0/b/enclave-wallet.appspot.com/o/wallet-sdk%2FpassKey.png?alt=media&token=00244583-8acf-4805-9fb3-c0fd9f103cfa", alt: "passkey Logo", style: { width: 84 } })),
react_1.default.createElement("div", { style: {
color: "#4B5563",
fontSize: 17,
textAlign: "center",
marginBottom: 10,
} }, "Authenticate securely using your device's passkey"),
react_1.default.createElement("button", { style: {
marginTop: 10,
width: "100%",
background: "#3662E3",
color: "white",
fontWeight: 600,
fontSize: 18,
border: "none",
borderRadius: 10,
padding: "14px 0",
cursor: "pointer",
boxShadow: "0 2px 8px rgba(70,100,233,0.10)",
transition: "background 0.2s",
}, onClick: onNext }, "Use my passkey")));
};
var SignupStep = function (_a) {
var username = _a.username, onUsernameChange = _a.onUsernameChange, usernameStatus = _a.usernameStatus, checking = _a.checking, error = _a.error, actionLoading = _a.actionLoading, onLogin = _a.onLogin, onSignup = _a.onSignup;
return (react_1.default.createElement("div", { style: { width: "100%" } },
react_1.default.createElement("label", { style: {
fontWeight: 600,
fontSize: 14,
marginBottom: 6,
display: "block",
} }, "Choose a username"),
react_1.default.createElement("input", { type: "text", value: username, onChange: function (e) { return onUsernameChange(e.target.value); }, placeholder: "Enter username", style: {
width: "100%",
padding: "10px",
borderRadius: 8,
border: "1px solid #ccc",
fontSize: 16,
marginBottom: 8,
}, disabled: actionLoading }),
checking && (react_1.default.createElement("div", { style: { color: "#888", fontSize: 14 } }, "Searching username...")),
usernameStatus === "exists" && (react_1.default.createElement("div", { style: { color: "green", fontSize: 14 } }, "Username found. You can log in.")),
usernameStatus === "not-exists" && (react_1.default.createElement("div", { style: { color: "blue", fontSize: 14 } }, "Username is available. You can sign up.")),
error && react_1.default.createElement("div", { style: { color: "red", fontSize: 14 } }, error),
react_1.default.createElement("button", { style: {
marginTop: 16,
width: "100%",
background: usernameStatus && !checking ? "#4664E9" : "#bfc8e6",
color: "white",
fontWeight: 600,
fontSize: 16,
border: "none",
borderRadius: 10,
padding: "14px 0",
cursor: usernameStatus && !checking ? "pointer" : "not-allowed",
boxShadow: "0 2px 8px rgba(70,100,233,0.10)",
transition: "background 0.2s",
}, disabled: !usernameStatus || checking || actionLoading, onClick: function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(usernameStatus === "exists")) return [3 /*break*/, 2];
return [4 /*yield*/, onLogin()];
case 1:
_a.sent();
return [3 /*break*/, 4];
case 2:
if (!(usernameStatus === "not-exists")) return [3 /*break*/, 4];
return [4 /*yield*/, onSignup()];
case 3:
_a.sent();
_a.label = 4;
case 4: return [2 /*return*/];
}
});
}); } }, checking
? "Searching username..."
: actionLoading
? usernameStatus === "exists"
? "Logging in..."
: "Signing up..."
: usernameStatus === "exists"
? "Login"
: usernameStatus === "not-exists"
? "Sign Up"
: "Continue")));
};
var WalletModalContent = function (_a) {
var _b;
var isOpen = _a.isOpen, onClose = _a.onClose, walletSDKKey = _a.walletSDKKey, swapParams = _a.swapParams;
var _c = (0, react_1.useState)("start"), step = _c[0], setStep = _c[1];
var _d = (0, react_1.useState)(""), username = _d[0], setUsername = _d[1];
var _e = (0, react_1.useState)(false), checking = _e[0], setChecking = _e[1];
var _f = (0, react_1.useState)(null), usernameStatus = _f[0], setUsernameStatus = _f[1];
var _g = (0, react_1.useState)(null), error = _g[0], setError = _g[1];
var _h = (0, react_1.useState)(false), actionLoading = _h[0], setActionLoading = _h[1];
var _j = (0, react_1.useState)(null), result = _j[0], setResult = _j[1];
var _k = (0, react_1.useState)(null), balance = _k[0], setBalance = _k[1];
var _l = (0, react_1.useState)(false), showSwap = _l[0], setShowSwap = _l[1];
var _m = (0, react_1.useState)(false), showTransfer = _m[0], setShowTransfer = _m[1];
var debounceRef = (0, react_1.useRef)(null);
var _o = (0, CryptoBalanceContext_1.useCryptoBalance)(), cryptoBalance = _o.cryptoBalance, refreshBalance = _o.refreshBalance;
var _p = (0, react_1.useState)(null), combinedBalance = _p[0], setCombinedBalance = _p[1];
var _q = (0, CryptoBalanceContext_1.useCryptoBalance)(), showActivity = _q.showActivity, setShowActivity = _q.setShowActivity, activity = _q.activity, setActivity = _q.setActivity, setLoading = _q.setLoading;
var enclave = new enclavemoney_web_experimental_1.Enclave(walletSDKKey);
(0, react_1.useEffect)(function () {
if (isOpen) {
var saved = localStorage.getItem("enclave_wallet_login");
if (saved) {
var parsed = JSON.parse(saved);
setResult(parsed.result);
setBalance(parsed.balance);
// Trigger immediate balance refresh when modal opens with existing session
refreshBalance();
}
}
}, [isOpen, swapParams]);
(0, react_1.useEffect)(function () {
if (result) {
localStorage.setItem("enclave_wallet_login", JSON.stringify({ result: result, balance: balance }));
setLoading(true);
}
}, [result, balance]);
(0, react_1.useEffect)(function () {
if (swapParams) {
setShowSwap(true);
}
if (result && swapParams && cryptoBalance) {
setCombinedBalance({
data: __spreadArray(__spreadArray(__spreadArray([], (cryptoBalance.data.some(function (token) {
return token.chainIds.some(function (chain) {
return chain.address.toLowerCase() ===
swapParams.fromToken.tokenAddress.toLowerCase() &&
chain.chainId === swapParams.fromToken.chainId;
});
})
? []
: [swapParams.fromToken]), true), (cryptoBalance.data.some(function (token) {
return token.chainIds.some(function (chain) {
return chain.address.toLowerCase() ===
swapParams.toToken.tokenAddress.toLowerCase() &&
chain.chainId === swapParams.toToken.chainId;
});
})
? []
: [swapParams.toToken]), true), cryptoBalance.data, true),
});
}
if (!swapParams && cryptoBalance) {
setCombinedBalance(cryptoBalance);
}
}, [result, swapParams, cryptoBalance]);
var handleUsernameChange = function (value) {
setUsername(value);
setUsernameStatus(null);
setError(null);
if (debounceRef.current)
clearTimeout(debounceRef.current);
if (!value)
return;
setChecking(true);
debounceRef.current = setTimeout(function () {
checkUserName(value);
}, 500);
};
var checkUserName = function (username) { return __awaiter(void 0, void 0, void 0, function () {
var resp, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
setChecking(true);
setError(null);
_a.label = 1;
case 1:
_a.trys.push([1, 3, 4, 5]);
return [4 /*yield*/, enclave.checkUserName(username)];
case 2:
resp = _a.sent();
if (resp.value === true) {
setUsernameStatus("exists");
}
else if (resp.value === false) {
setUsernameStatus("not-exists");
}
else {
setUsernameStatus(null);
}
return [3 /*break*/, 5];
case 3:
e_1 = _a.sent();
setError("Error checking username");
setUsernameStatus(null);
return [3 /*break*/, 5];
case 4:
setChecking(false);
return [7 /*endfinally*/];
case 5: return [2 /*return*/];
}
});
}); };
var signInAccount = function () { return __awaiter(void 0, void 0, void 0, function () {
var resp, attResp, error_1, verificationResp, sdkInstance, balanceData, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
setActionLoading(true);
setError(null);
_a.label = 1;
case 1:
_a.trys.push([1, 13, 14, 15]);
return [4 /*yield*/, enclave.getPasskeyAccountRegisteredOptions(username)];
case 2:
resp = _a.sent();
attResp = void 0;
_a.label = 3;
case 3:
_a.trys.push([3, 5, , 6]);
return [4 /*yield*/, enclave.startPasskeyAccountAuthentication(resp)];
case 4:
attResp = _a.sent();
return [3 /*break*/, 6];
case 5:
error_1 = _a.sent();
throw error_1;
case 6: return [4 /*yield*/, enclave.submitPasskeyAccountRegisteredResponse({
username: username,
attResp: attResp,
})];
case 7:
verificationResp = _a.sent();
if (!verificationResp) return [3 /*break*/, 11];
if (!verificationResp.error) return [3 /*break*/, 8];
setError(verificationResp.message);
return [3 /*break*/, 10];
case 8:
setResult(verificationResp);
sdkInstance = window.__walletSDKInstance;
if (!sdkInstance) return [3 /*break*/, 10];
return [4 /*yield*/, sdkInstance.getUserCryptoBalance()];
case 9:
balanceData = _a.sent();
setBalance(balanceData);
sdkInstance.setUserSession({
result: verificationResp,
balance: balanceData,
});
_a.label = 10;
case 10: return [3 /*break*/, 12];
case 11:
setError("Login failed");
_a.label = 12;
case 12: return [3 /*break*/, 15];
case 13:
e_2 = _a.sent();
setError(e_2.message || "Login failed");
return [3 /*break*/, 15];
case 14:
setActionLoading(false);
return [7 /*endfinally*/];
case 15: return [2 /*return*/];
}
});
}); };
var createAccount = function () { return __awaiter(void 0, void 0, void 0, function () {
var resp, attResp, error_2, verificationResp, sdkInstance, balanceData, e_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
setActionLoading(true);
setError(null);
_a.label = 1;
case 1:
_a.trys.push([1, 13, 14, 15]);
return [4 /*yield*/, enclave.getPasskeyAccountRegistrationOptions(username)];
case 2:
resp = _a.sent();
attResp = void 0;
_a.label = 3;
case 3:
_a.trys.push([3, 5, , 6]);
return [4 /*yield*/, enclave.startPasskeyAccountRegistration(resp)];
case 4:
attResp = _a.sent();
return [3 /*break*/, 6];
case 5:
error_2 = _a.sent();
throw error_2;
case 6: return [4 /*yield*/, enclave.submitPasskeyAccountRegistrationResponse({
username: username,
attResp: attResp,
})];
case 7:
verificationResp = _a.sent();
if (!verificationResp) return [3 /*break*/, 11];
if (!verificationResp.error) return [3 /*break*/, 8];
setError(verificationResp.message);
return [3 /*break*/, 10];
case 8:
setResult(verificationResp);
sdkInstance = window.__walletSDKInstance;
if (!sdkInstance) return [3 /*break*/, 10];
return [4 /*yield*/, sdkInstance.getUserCryptoBalance()];
case 9:
balanceData = _a.sent();
setBalance(balanceData);
sdkInstance.setUserSession({
result: verificationResp,
balance: balanceData,
});
_a.label = 10;
case 10: return [3 /*break*/, 12];
case 11:
setError("Signup failed");
_a.label = 12;
case 12: return [3 /*break*/, 15];
case 13:
e_3 = _a.sent();
setError(e_3.message || "Signup failed");
return [3 /*break*/, 15];
case 14:
setActionLoading(false);
return [7 /*endfinally*/];
case 15: return [2 /*return*/];
}
});
}); };
var handleLogout = function () {
setResult(null);
setUsername("");
setUsernameStatus(null);
setError(null);
setStep("start");
localStorage.removeItem("enclave_wallet_login");
};
var getMatchingTokenFromCryptoBalance = function (tokenAddress, chainId) {
return cryptoBalance === null || cryptoBalance === void 0 ? void 0 : cryptoBalance.data.find(function (token) {
return token.chainIds.some(function (chain) {
return chain.address.toLowerCase() === tokenAddress.toLowerCase() &&
chain.chainId === chainId;
});
});
};
var formatTokenForSwap = function (matchingToken, chainId) {
var _a;
if (!matchingToken)
return undefined;
var matchingChain = matchingToken.chainIds.find(function (chain) { return chain.chainId === chainId; });
if (!matchingChain)
return undefined;
return {
symbol: matchingToken.symbol,
name: matchingToken.name,
icon: matchingToken.logoURI,
address: matchingChain.address,
chainId: matchingChain.chainId,
chainIds: matchingToken.chainIds,
decimals: matchingToken.decimals,
balance: matchingChain.balance,
amount: (_a = matchingToken.amount) === null || _a === void 0 ? void 0 : _a.toString(),
};
};
var getInitialFromToken = function () {
if (!(swapParams === null || swapParams === void 0 ? void 0 : swapParams.fromToken))
return undefined;
var matchingToken = getMatchingTokenFromCryptoBalance(swapParams.fromToken.tokenAddress, swapParams.fromToken.chainId);
return formatTokenForSwap(matchingToken, swapParams.fromToken.chainId);
};
var getInitialToToken = function () {
if (!(swapParams === null || swapParams === void 0 ? void 0 : swapParams.toToken))
return undefined;
var matchingToken = getMatchingTokenFromCryptoBalance(swapParams.toToken.tokenAddress, swapParams.toToken.chainId);
console.log(matchingToken, "matchingToken", swapParams.toToken, cryptoBalance, "cryptoBalance");
return formatTokenForSwap(matchingToken, swapParams.toToken.chainId);
};
if (!isOpen)
return null;
return (react_1.default.createElement("div", { style: {
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: "rgba(0, 0, 0, 0.5)",
display: "flex",
justifyContent: "center",
alignItems: "center",
zIndex: 1000,
}, onClick: onClose },
react_1.default.createElement("div", { style: {
backgroundColor: "white",
maxHeight: "95vh",
overflowY: "auto",
padding: "32px 24px 24px 24px",
borderRadius: "20px",
minWidth: "440px",
color: "#222",
boxShadow: "0 4px 24px rgba(0,0,0,0.10)",
position: "relative",
fontFamily: "Inter, sans-serif",
}, onClick: function (e) { return e.stopPropagation(); } },
!result && (react_1.default.createElement("div", null,
react_1.default.createElement("div", { style: {
display: "flex",
justifyContent: "center",
marginBottom: 16,
} },
react_1.default.createElement("img", { src: enclaveLogo, alt: "Enclave Logo", style: { height: 48, objectFit: "contain" } })),
react_1.default.createElement("button", { onClick: onClose, style: {
position: "absolute",
top: 18,
right: 18,
background: "none",
border: "none",
fontSize: 22,
cursor: "pointer",
color: "#888",
}, "aria-label": "Close" }, "\u00D7"))),
!result && (react_1.default.createElement("h2", { style: {
fontSize: 26,
fontWeight: 700,
margin: 0,
textAlign: "center",
} }, "Log In or Sign Up")),
!result && (react_1.default.createElement("p", { style: {
color: "#6B7280",
fontSize: 16,
margin: "10px 0 24px 0",
textAlign: "center",
} }, "Sign into your wallet with one click")),
!result && (react_1.default.createElement("div", { style: {
background: "#F6F8FE",
borderRadius: 16,
padding: "24px 16px 20px 16px",
flexDirection: "column",
alignItems: "center",
marginBottom: 24,
display: showSwap ? "none" : "flex",
} },
step === "start" && !result && (react_1.default.createElement(StartStep, { onNext: function () { return setStep("signup"); } })),
step === "signup" && !result && (react_1.default.createElement(SignupStep, { username: username, onUsernameChange: handleUsernameChange, usernameStatus: usernameStatus, checking: checking, error: error, actionLoading: actionLoading, onLogin: signInAccount, onSignup: createAccount })))),
showSwap && !showTransfer && (react_1.default.createElement(SwapToken_1.SwapToken, { onBack: function () {
setShowSwap(false);
if (swapParams) {
onClose();
}
}, walletSDKKey: walletSDKKey, combinedBalance: combinedBalance, initialFromToken: cryptoBalance && getInitialFromToken(), initialToToken: cryptoBalance && getInitialToToken(), initialAmount: ((_b = swapParams === null || swapParams === void 0 ? void 0 : swapParams.fromToken) === null || _b === void 0 ? void 0 : _b.amount) || "" })),
showTransfer && (react_1.default.createElement(TransferToken_1.default, { onBack: function () { return setShowTransfer(false); }, onClose: function () { return setShowTransfer(false); }, walletSdkKey: walletSDKKey, username: (result === null || result === void 0 ? void 0 : result.username) || "" })),
result &&
!showSwap &&
!swapParams &&
!showTransfer &&
!showActivity && (react_1.default.createElement(Dashboard_1.Dashboard, { result: result, onLogout: handleLogout, onShowSwap: function () { return setShowSwap(true); }, onShowTransfer: function () { return setShowTransfer(true); }, sdkKey: walletSDKKey })),
showActivity && (react_1.default.createElement(ActivityDetails_1.default, { onBack: function () { return setShowActivity(false); }, activity: activity })),
react_1.default.createElement("div", { style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
gap: 8,
} },
react_1.default.createElement("span", { style: { fontSize: 12, color: "#B4B4B6" } }, "Secured by"),
react_1.default.createElement("img", { src: "https://firebasestorage.googleapis.com/v0/b/enclave-wallet.appspot.com/o/wallet-sdk%2FLogoNameGray.png?alt=media&token=10a251a9-3dc9-441f-bf41-d4e60704cc33", alt: "Enclave text Logo", style: { width: 84 } })))));
};
var WalletModal = function (props) {
return (react_1.default.createElement(CryptoBalanceContext_1.CryptoBalanceProvider, { walletSDKKey: props.walletSDKKey },
react_1.default.createElement(WalletModalContent, __assign({}, props))));
};
exports.WalletModal = WalletModal;