@particle-network/authkit
Version:
Auth Core provides MPC (Multi-Party Computation)-based threshold signatures.
343 lines (339 loc) • 16.5 kB
JavaScript
"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