UNPKG

@particle-network/authkit

Version:

Auth Core provides MPC (Multi-Party Computation)-based threshold signatures.

343 lines (339 loc) 16.5 kB
"use client"; import { icon_copy_default, info_sign_default, menu_default, usePaymentPassword } from "./chunk-B7MBFVT5.mjs"; import { useError } from "./chunk-BV57KN2B.mjs"; import "./chunk-C3QCRACD.mjs"; import { power_footer_default } from "./chunk-PPCDDBBD.mjs"; import { AuthError, formatTokenAmount, getChainDisplayName, isTelegramWebApp, shortString, useAuthCoreModal, useCustomNavigate, useEvents, useMessage_default, useModalOptions, useParticleAuth, useTranslation } from "./chunk-H5PUG6U3.mjs"; import "./chunk-55PCA22M.mjs"; // src/pages/sign/components/info-sign.tsx import { RecordType } from "@particle-network/analytics"; import { SolanaEnhancedMethod, SolanaRpcMethod, analyticsRecord, getChainIcon, isNeedRestoreWallet, particleAuth, syncUserInfo } from "@particle-network/auth-core"; import { Button, Modal, Tabs } from "antd"; import base58 from "bs58"; import React, { useEffect, useMemo, useState } from "react"; import CopyToClipboard from "react-copy-to-clipboard"; // src/utils/solana-utils.ts var SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"; var solana = { async findAssociatedTokenAddress(walletAddress, tokenMintAddress) { const { PublicKey } = await import("@solana/web3.js"); const TOKEN_PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); return PublicKey.findProgramAddressSync( [ new PublicKey(walletAddress).toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), new PublicKey(tokenMintAddress).toBuffer() ], new PublicKey(SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID) )[0]; } }; var solana_utils_default = solana; // src/pages/sign/components/info-sign.tsx function InfoSign(props) { const { method, param, chainId, loginAuthorizationSign } = props; const { t } = useTranslation(); const navigate = useCustomNavigate(); const { setPaymentVerify, userInfo, setPaymentPassword } = useParticleAuth(); const { events } = useEvents(); const { modalOptions } = useModalOptions(); const { authCoreModal } = useAuthCoreModal(); const { errorHandle } = useError(); const [loading, setLoading] = useState(false); const message = useMessage_default(); const [transactionInfo, setTransactionInfo] = useState(); const [nftChanges, setNftChanges] = useState(); const [tokenChanges, setTokenChanges] = useState(); const [headerTitle, setHeaderTitle] = useState(""); const [headerDes, setHeaderDes] = useState(""); const { hasSetPaymentPassword, showSetPaymentPasswordOrConfirm } = usePaymentPassword(); const chain = useMemo(() => { return { id: chainId || particleAuth.solana.chainId, name: "Solana" }; }, []); const shortAddress = useMemo(() => { const address = particleAuth.solana.selectedAddress; return shortString(address); }, []); useEffect(() => { syncUserInfo().catch((e) => console.log("syncUserInfo", e)); if (isNeedRestoreWallet()) { navigate("account/master-password/verify" /* MasterPasswordVerify */); } }, [navigate]); const loadsecurityAccounts = () => { syncUserInfo().then(() => { approveSign(); }).catch((error) => { var _a; setLoading(false); message.error((_a = error.message) != null ? _a : "Sign Error"); }); }; const finallyHandle = (result, error) => { events.emit("signResponse" /* SignResponse */, { result, error }); }; async function asyncFilter(predicate, arr) { if (!arr) { return []; } const results = await Promise.all(arr.map(predicate)); return arr.filter((_v, index) => results[index]); } const approveSign = async () => { var _a, _b; if (!method) return; analyticsRecord({ record_type: RecordType.PAGE_SIGN_CONFIRM_BUTTON_CLICK }); if ((_a = userInfo == null ? void 0 : userInfo.security_account) == null ? void 0 : _a.has_set_payment_password) { setPaymentVerify({ visible: true, onVerifyCompleted: approveSignImpl }); } else if (method === SolanaRpcMethod.signAndSendTransaction || method === SolanaRpcMethod.signTransaction || method === SolanaRpcMethod.signAllTransactions || ((_b = modalOptions == null ? void 0 : modalOptions.promptSettingConfig) == null ? void 0 : _b.promptPaymentPasswordSettingWhenSign) === 3 /* everyAndNotSkip */) { showSetPaymentPasswordOrConfirm(approveSignImpl); } else { approveSignImpl(); } }; const approveSignImpl = async () => { var _a; if (!method) return; setLoading(true); let signed; try { if (method === SolanaRpcMethod.signMessage) { const { signature } = await particleAuth.solana.signMessage(param); signed = signature; } else if (method === SolanaRpcMethod.signAndSendTransaction) { const { signature } = await particleAuth.solana.signAndSendTransaction( param, chain.id ); signed = signature; } else if (method === SolanaRpcMethod.signTransaction) { signed = await particleAuth.solana.signTransaction(param, chain.id); } else if (method === SolanaRpcMethod.signAllTransactions) { signed = await particleAuth.solana.signAllTransactions( param, chain.id ); } else { throw new Error("Unknown method"); } analyticsRecord({ record_type: RecordType.PAGE_SIGN_CONFIRM_BUTTON_CLICK_SUCCESS }); } catch (e) { console.error("approveSignImpl error", method, e); analyticsRecord({ record_type: RecordType.PAGE_SIGN_CONFIRM_BUTTON_CLICK_FAILURE }); if ((e == null ? void 0 : e.error_code) === 50103 && !((_a = userInfo == null ? void 0 : userInfo.security_account) == null ? void 0 : _a.has_set_payment_password)) { loadsecurityAccounts(); } else if ((e == null ? void 0 : e.message) === "Local Key not found" || (e == null ? void 0 : e.message) === "Master password decryption error") { navigate("account/master-password/verify" /* MasterPasswordVerify */); } else { errorHandle(e); } } finally { setLoading(false); } if (signed) { if (method === SolanaRpcMethod.signMessage && loginAuthorizationSign) { events.emit("loginSuccess" /* LoginSuccess */, { ...userInfo, authorization: { message: base58.encode(param), signature: signed } }); } else { finallyHandle(signed); } } }; const cancelSign = () => { if (loading) { return; } if (loginAuthorizationSign) { events.emit("loginSuccess" /* LoginSuccess */, userInfo); } else { finallyHandle(void 0, AuthError.userRejectedRequest()); } }; useEffect(() => { if (method === SolanaRpcMethod.signMessage) { setHeaderTitle(t("sign.signature_message")); setHeaderDes(t("sign.signature_title")); } else if (method === SolanaRpcMethod.signAndSendTransaction) { setHeaderTitle(t("sign.send_transaction")); setHeaderDes(t("sign.approve_and").format(getChainDisplayName(chain))); const serializeTx = param.serialize({ requireAllSignatures: false, verifySignatures: false }); deserializeTransaction([base58.encode(serializeTx)]); } else if (method === SolanaRpcMethod.signTransaction) { setHeaderTitle(t("sign.sign_transaction")); setHeaderDes(t("sign.sign_but")); const serializeTx = param.serialize({ requireAllSignatures: false, verifySignatures: false }); deserializeTransaction([base58.encode(serializeTx)]); } else if (method === SolanaRpcMethod.signAllTransactions) { setHeaderTitle(t("sign.sign_transaction")); setHeaderDes(t("sign.sign_but")); const serializeTxs = param.map( (tx) => base58.encode( tx.serialize({ requireAllSignatures: false, verifySignatures: false }) ) ); deserializeTransaction(serializeTxs); } else { throw new Error("Unknown method"); } }, [param, t]); useEffect(() => { particleAuth.solana.connect(); }, []); const deserializeTransaction = (messages) => { particleAuth.solana.request({ chainId: chain.id, method: SolanaEnhancedMethod.enhancedDeserializeTransaction, params: messages }).then((result) => { var _a, _b; setTransactionInfo(result); asyncFilter(async (info) => { const associatedTokenAddress = await solana_utils_default.findAssociatedTokenAddress( particleAuth.solana.selectedAddress, info.mint ); return info.associatedTokenAddress === associatedTokenAddress.toBase58(); }, (_a = result == null ? void 0 : result.estimatedChanges) == null ? void 0 : _a.nfts).then((results) => { console.log("NFTChanges", results.length); setNftChanges(results); }); asyncFilter(async (info) => { const associatedTokenAddress = await solana_utils_default.findAssociatedTokenAddress( particleAuth.solana.selectedAddress, info.mint ); return info.associatedTokenAddress === associatedTokenAddress.toBase58(); }, (_b = result == null ? void 0 : result.estimatedChanges) == null ? void 0 : _b.tokens).then((results) => { console.log("TokenChanges", results.length); setTokenChanges(results); }); }).catch((error) => { var _a; console.log("deserializeTransaction error", error); Modal.error({ title: (_a = error.message) != null ? _a : "Deserialize Transaction Error", okCancel: true, cancelText: t("common.cancel"), okText: t("common.retry"), wrapClassName: "auth-core-modal-error", getContainer: () => { return authCoreModal.rootBody; }, onOk: () => { deserializeTransaction(messages); } }); }); }; const signMessage = () => { const textDecoder = new TextDecoder(); const decodedString = textDecoder.decode(param); return /* @__PURE__ */ React.createElement("div", { className: "sign-message" }, /* @__PURE__ */ React.createElement("div", { className: "message" + (hasSetPaymentPassword ? "" : " no-password-tip") }, /* @__PURE__ */ React.createElement("div", { className: "pre-wrap personal-message" }, decodedString))); }; const signTransaction = () => { var _a; return /* @__PURE__ */ React.createElement( Tabs, { defaultActiveKey: "1", items: [ { label: t("sign.details"), key: "1", children: /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "balance-change" }, /* @__PURE__ */ React.createElement("div", { className: "title" }, t("sign.estimated_balance_change")), /* @__PURE__ */ React.createElement("div", { className: "change-body" }, (_a = transactionInfo == null ? void 0 : transactionInfo.estimatedChanges) == null ? void 0 : _a.sols.filter((info) => { var _a2, _b; return info.address === ((_b = (_a2 = particleAuth) == null ? void 0 : _a2.solana) == null ? void 0 : _b.selectedAddress); }).map((info, index) => { return /* @__PURE__ */ React.createElement("div", { className: "change-title", key: `sol-change-${index}` }, "SOL", /* @__PURE__ */ React.createElement("div", { className: "change-val", style: info.lamportsChange < 0 ? { color: "#ea4335" } : {} }, info.lamportsChange < 0 ? "" : "+", formatTokenAmount(info.lamportsChange, 9))); }), nftChanges == null ? void 0 : nftChanges.map((info, index) => { return /* @__PURE__ */ React.createElement("div", { className: "change-title", key: `nft-change-${index}` }, info.name ? info.name : "Unknown NFT", /* @__PURE__ */ React.createElement("div", { className: "change-val", style: info.amountChange < 0 ? { color: "#ea4335" } : {} }, info.amountChange < 0 ? "" : "+", info.amountChange)); }), tokenChanges == null ? void 0 : tokenChanges.map((info, index) => { return /* @__PURE__ */ React.createElement("div", { className: "change-title", key: `token-change-${index}` }, info.name ? info.name : "Unknown Token", /* @__PURE__ */ React.createElement("div", { className: "change-val", style: info.amountChange < 0 ? { color: "#ea4335" } : {} }, info.amountChange < 0 ? "" : "+", formatTokenAmount(info.amountChange, info.decimals))); }))), /* @__PURE__ */ React.createElement("div", { className: "net-fee solana" }, /* @__PURE__ */ React.createElement("div", { className: "title" }, t("sign.network_fee"), transactionInfo && /* @__PURE__ */ React.createElement("div", { className: "fee-val" }, formatTokenAmount(transactionInfo.estimatedLamportsFee, 9), " SOL")))) }, { label: t("sign.data"), key: "2", children: /* @__PURE__ */ React.createElement("div", null, transactionInfo == null ? void 0 : transactionInfo.instructions.map((instruction, index) => { return /* @__PURE__ */ React.createElement("div", { className: "inner-instruction", key: `instruction-${index}` }, /* @__PURE__ */ React.createElement("div", { className: "inner-content" }, /* @__PURE__ */ React.createElement("div", { className: "content-item" }, /* @__PURE__ */ React.createElement("div", { className: "item" }, /* @__PURE__ */ React.createElement("div", { className: "item-0" }, "#", index + 1, " - ", t(`program.${instruction.type}`)), /* @__PURE__ */ React.createElement("div", { className: "item-1 mt10" }, t("sign.program_id"), /* @__PURE__ */ React.createElement("span", null, shortString(instruction.programId))), /* @__PURE__ */ React.createElement("div", { className: "item-1 mt15" }, t("sign.data"), /* @__PURE__ */ React.createElement("span", null, shortString(instruction.data))))))); })) } ] } ); }; return /* @__PURE__ */ React.createElement("div", { className: "info-sign" }, /* @__PURE__ */ React.createElement("style", null, info_sign_default), !hasSetPaymentPassword && /* @__PURE__ */ React.createElement("div", { className: "has-payment-password", "data-telegram": isTelegramWebApp() }, /* @__PURE__ */ React.createElement("div", { className: "has-payment-password-icon" }), /* @__PURE__ */ React.createElement("div", { className: "has-payment-password-tip" }, t("account.waring_tip1")), /* @__PURE__ */ React.createElement("div", { className: "has-payment-password-set", onClick: setPaymentPassword }, t("account.set"))), /* @__PURE__ */ React.createElement("div", { className: "scroll-part" + (hasSetPaymentPassword ? "" : " no-password-tip") }, /* @__PURE__ */ React.createElement(menu_default, { userInfo, transactionInfo }), /* @__PURE__ */ React.createElement("div", { className: "info-request" }, headerTitle), /* @__PURE__ */ React.createElement("div", { className: "info-title" }, /* @__PURE__ */ React.createElement("img", { src: getChainIcon(chain), alt: "" }), getChainDisplayName(chain)), /* @__PURE__ */ React.createElement( CopyToClipboard, { text: particleAuth.solana.selectedAddress, onCopy: () => message.success(t("new.copied_to")) }, /* @__PURE__ */ React.createElement("div", { className: "info-address" }, shortAddress, /* @__PURE__ */ React.createElement("div", { className: "copy-icon" }, /* @__PURE__ */ React.createElement(icon_copy_default, null))) ), /* @__PURE__ */ React.createElement("div", { className: "info-des" }, headerDes), /* @__PURE__ */ React.createElement("div", { className: "apart-line" }), method === SolanaRpcMethod.signMessage && signMessage(), method !== SolanaRpcMethod.signMessage && signTransaction()), /* @__PURE__ */ React.createElement("div", { className: "btn-box" }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Button, { className: "btn-cancel", onClick: cancelSign }, t("common.cancel")), /* @__PURE__ */ React.createElement(Button, { className: "btn-approve", onClick: approveSign, loading }, t("common.confirm"))), /* @__PURE__ */ React.createElement(power_footer_default, null))); } var info_sign_default2 = InfoSign; export { info_sign_default2 as default }; //# sourceMappingURL=info-sign-FF2R27ZX.mjs.map