@keplr-ewallet/ewallet-sdk-eth
Version:
243 lines • 9.65 kB
JavaScript
import { serializeSignature, serializeTransaction } from "viem";
import { v4 as uuidv4 } from "uuid";
import { hashEthereumMessage, hashEthereumTransaction, hashEthereumTypedData, encodeEthereumSignature, toTransactionSerializable, parseTypedDataDefinition, } from "../utils";
import { getChainIconUrl, SUPPORTED_CHAINS, TESTNET_CHAINS, } from "../chains";
import { standardError } from "../errors";
const signTypeConfig = {
sign_transaction: {
sign_type: "tx",
processModalResult: (data, modalResult) => {
if (data.sign_type !== "tx") {
throw standardError.ethEWallet.invalidSignType({
message: "Sign type should be tx",
});
}
if (!modalResult) {
throw standardError.ethEWallet.invalidMessage({
message: "Make signature result is not present for sign_transaction method",
});
}
if (modalResult.modal_type !== "make_signature") {
throw standardError.ethEWallet.invalidMessage({
message: "Invalid modal result for eth signature",
});
}
if (modalResult.chain_type !== "eth") {
throw standardError.ethEWallet.invalidMessage({
message: "Invalid chain type for eth signature",
});
}
const originalTx = data.payload.data.transaction;
const simulatedTx = modalResult.data.transaction;
const immutableFields = ["type", "to", "value", "data"];
for (const field of immutableFields) {
if (originalTx[field] !== simulatedTx[field]) {
throw standardError.ethEWallet.invalidMessage({
message: `Simulation changed immutable field: ${field}. Original: ${originalTx[field]}, Simulated: ${simulatedTx[field]}`,
});
}
}
return Object.assign(Object.assign({}, data), { payload: Object.assign(Object.assign({}, data.payload), { data: {
transaction: simulatedTx,
} }) });
},
hashMakeSignatureData: (data) => {
if (data.sign_type !== "tx") {
throw standardError.ethEWallet.invalidSignType({
message: "Sign type should be tx",
});
}
const payload = data.payload;
const serializableTx = toTransactionSerializable({
chainId: payload.chain_info.chain_id,
tx: payload.data.transaction,
});
return hashEthereumTransaction(serializableTx);
},
processMakeSignatureResult: (signOutput, data) => {
if (!data) {
throw standardError.ethEWallet.invalidMessage({
message: "Data is required for sign_transaction method",
});
}
if (data.sign_type !== "tx") {
throw standardError.ethEWallet.invalidSignType({
message: "Sign type should be tx",
});
}
const signature = encodeEthereumSignature(signOutput);
const payload = data.payload;
const serializableTx = toTransactionSerializable({
chainId: payload.chain_info.chain_id,
tx: payload.data.transaction,
});
const signedTransaction = serializeTransaction(serializableTx, signature);
return {
type: "signed_transaction",
signedTransaction,
};
},
},
personal_sign: {
sign_type: "arbitrary",
hashMakeSignatureData: (data) => {
if (data.sign_type !== "arbitrary") {
throw standardError.ethEWallet.invalidSignType({
message: "Sign type should be arbitrary",
});
}
return hashEthereumMessage(data.payload.data.message);
},
processMakeSignatureResult: (signOutput) => {
const signature = encodeEthereumSignature(signOutput);
return {
type: "signature",
signature: serializeSignature(signature),
};
},
},
sign_typedData_v4: {
sign_type: "eip712",
hashMakeSignatureData: (data) => {
if (data.sign_type !== "eip712") {
throw standardError.ethEWallet.invalidSignType({
message: "Sign type should be eip712",
});
}
const payloadData = data.payload.data;
if (payloadData.version !== "4") {
throw standardError.ethEWallet.invalidMessage({
message: "Typed data version should be 4 for sign_typedData_v4 method",
});
}
const typedData = parseTypedDataDefinition(payloadData.serialized_typed_data);
return hashEthereumTypedData(typedData);
},
processMakeSignatureResult: (signOutput) => {
const signature = encodeEthereumSignature(signOutput);
return {
type: "signature",
signature: serializeSignature(signature),
};
},
},
};
async function handleSigningFlow(ethEWallet, config, data) {
var _a;
const showModalMsg = {
target: "keplr_ewallet_attached",
msg_type: "show_modal",
payload: {
modal_type: "make_signature",
data,
},
};
const eWallet = ethEWallet.eWallet;
try {
const modalResult = await eWallet.showModal(showModalMsg);
await eWallet.hideModal();
if (!modalResult.approved) {
throw standardError.ethEWallet.userRejectedRequest({
message: (_a = modalResult.reason) !== null && _a !== void 0 ? _a : "User rejected the signature request",
});
}
let processedData = data;
if (config.processModalResult) {
processedData = config.processModalResult(data, modalResult.data);
}
const msgHash = config.hashMakeSignatureData(processedData);
const makeSignatureMsg = {
target: "keplr_ewallet_attached",
msg_type: "make_signature",
payload: {
msg: msgHash,
},
};
const signOutput = await eWallet.makeSignature(makeSignatureMsg);
return config.processMakeSignatureResult(signOutput, processedData);
}
catch (error) {
if (error && typeof error === "object" && "code" in error) {
throw error;
}
throw standardError.ethEWallet.signatureFailed({
message: error instanceof Error ? error.message : String(error),
});
}
}
async function _makeSignature(parameters) {
var _a;
const origin = this.eWallet.origin;
const provider = await this.getEthereumProvider();
const chainId = provider.chainId;
const chainIdNumber = parseInt(chainId, 16);
let chains = SUPPORTED_CHAINS;
if (this.useTestnet) {
chains = [...chains, ...TESTNET_CHAINS];
}
const activeChain = chains.find((chain) => chain.id === chainIdNumber);
if (!activeChain) {
throw standardError.ethEWallet.invalidMessage({
message: "Chain not found in the supported chains",
});
}
const chainInfo = {
chain_id: `eip155:${activeChain.id}`,
chain_name: activeChain.name,
chain_symbol_image_url: getChainIconUrl(activeChain.id),
rpc_url: activeChain.rpcUrls.default.http[0],
block_explorer_url: (_a = activeChain.blockExplorers) === null || _a === void 0 ? void 0 : _a.default.url,
};
const basePayload = {
chain_info: chainInfo,
origin,
signer: parameters.data.address,
request_id: uuidv4(),
};
let signType;
let makeSignatureData;
switch (parameters.type) {
case "sign_transaction": {
signType = "tx";
makeSignatureData = {
chain_type: "eth",
sign_type: signType,
payload: Object.assign(Object.assign({}, basePayload), { data: {
transaction: parameters.data.transaction,
} }),
};
break;
}
case "personal_sign": {
signType = "arbitrary";
makeSignatureData = {
chain_type: "eth",
sign_type: signType,
payload: Object.assign(Object.assign({}, basePayload), { data: {
message: parameters.data.message,
} }),
};
break;
}
case "sign_typedData_v4": {
signType = "eip712";
makeSignatureData = {
chain_type: "eth",
sign_type: signType,
payload: Object.assign(Object.assign({}, basePayload), { data: {
version: "4",
serialized_typed_data: parameters.data.serializedTypedData,
} }),
};
break;
}
default: {
throw standardError.ethEWallet.invalidMessage({
message: `Unknown sign method: ${parameters.type}`,
});
}
}
return await handleSigningFlow(this, signTypeConfig[parameters.type], makeSignatureData);
}
export const makeSignature = _makeSignature;
//# sourceMappingURL=make_signature.js.map