UNPKG

@celo-tools/celo-ethers-wrapper

Version:

A minimal wrapper to make Ethers.JS compatible with the Celo network.

434 lines 36.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseCeloTransaction = exports.serializeCeloTransaction = exports.getTxType = exports.celoTransactionFields = exports.celoAllowedTransactionKeys = exports.TxTypeToPrefix = void 0; const ethers_1 = require("ethers"); const utils_1 = require("./transaction/utils"); const consts_1 = require("../consts"); var TxTypeToPrefix; (function (TxTypeToPrefix) { TxTypeToPrefix[TxTypeToPrefix["cip64"] = 123] = "cip64"; TxTypeToPrefix[TxTypeToPrefix["cip66"] = 122] = "cip66"; TxTypeToPrefix[TxTypeToPrefix["eip1559"] = 2] = "eip1559"; })(TxTypeToPrefix || (exports.TxTypeToPrefix = TxTypeToPrefix = {})); exports.celoAllowedTransactionKeys = { type: true, chainId: true, data: true, gasLimit: true, gasPrice: true, nonce: true, to: true, value: true, feeCurrency: true, maxFeePerGas: true, maxPriorityFeePerGas: true, accessList: true, maxFeeInFeeCurrency: true, }; exports.celoTransactionFields = { nonce: { maxLength: 32, numeric: true }, gasPrice: { maxLength: 32, numeric: true }, gasLimit: { maxLength: 32, numeric: true }, feeCurrency: { length: 20 }, to: { length: 20 }, value: { maxLength: 32, numeric: true }, data: {}, maxFeePerGas: { maxLength: 32, numeric: true }, maxPriorityFeePerGas: { maxLength: 32, numeric: true }, maxFeeInFeeCurrency: { maxLength: 32, numeric: true }, }; function formatCeloField(name, value) { const fieldInfo = exports.celoTransactionFields[name]; const options = {}; if (!value || value === "0x") return value; if (fieldInfo.numeric) { options.hexPad = "left"; value = value ? (0, ethers_1.toBeHex)(value, fieldInfo.maxLength) : "0x"; } else { value = (0, ethers_1.hexlify)(value); } let _value = (0, ethers_1.toBeArray)(value); // Fixed-width field if (fieldInfo.length && _value.length !== fieldInfo.length && _value.length > 0) { (0, ethers_1.assertArgument)(false, "invalid length for " + name, "transaction:" + name, _value); } // Variable-width (with a maximum) if (fieldInfo.maxLength) { _value = (0, ethers_1.toBeArray)((0, ethers_1.stripZerosLeft)(_value)); if (_value.length > fieldInfo.maxLength) { (0, ethers_1.assertArgument)(false, "invalid length for " + name, "transaction:" + name, _value); } } return (0, ethers_1.hexlify)(_value); } function getTxType(tx) { if (tx.gasPrice) { return ""; } if ((0, utils_1.isCIP66)(tx)) { return TxTypeToPrefix.cip66; } if ((0, utils_1.isCIP64)(tx)) { return TxTypeToPrefix.cip64; } return TxTypeToPrefix.eip1559; } exports.getTxType = getTxType; function prepareEncodeTx(tx, signature) { let raw = []; switch (tx.type) { case TxTypeToPrefix.cip66: // https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0066.md // 0x7a || rlp([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, feeCurrency, maxFeeInFeeCurrency, signatureYParity, signatureR, signatureS]). raw = [ (0, ethers_1.toBeHex)(tx.chainId), (0, ethers_1.toBeHex)(tx.nonce), tx.maxPriorityFeePerGas ? (0, ethers_1.toBeHex)(tx.maxPriorityFeePerGas) : "0x", tx.maxFeePerGas ? (0, ethers_1.toBeHex)(tx.maxFeePerGas) : "0x", tx.gasLimit ? (0, ethers_1.toBeHex)(tx.gasLimit) : "0x", tx.to || "0x", tx.value ? (0, ethers_1.toBeHex)(tx.value) : "0x", tx.data || "0x", formatAccessList(tx.accessList || []), tx.feeCurrency || "0x", tx.maxFeeInFeeCurrency ? (0, ethers_1.toBeHex)(tx.maxFeeInFeeCurrency) : "0x", ]; break; case TxTypeToPrefix.cip64: // https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md // 0x7b || rlp([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, feeCurrency, signatureYParity, signatureR, signatureS]). raw = [ (0, ethers_1.toBeHex)(tx.chainId), (0, ethers_1.toBeHex)(tx.nonce), tx.maxPriorityFeePerGas ? (0, ethers_1.toBeHex)(tx.maxPriorityFeePerGas) : "0x", tx.maxFeePerGas ? (0, ethers_1.toBeHex)(tx.maxFeePerGas) : "0x", tx.gasLimit ? (0, ethers_1.toBeHex)(tx.gasLimit) : "0x", tx.to || "0x", tx.value ? (0, ethers_1.toBeHex)(tx.value) : "0x", tx.data || "0x", formatAccessList(tx.accessList || []), tx.feeCurrency || "0x", ]; break; case TxTypeToPrefix.eip1559: // https://eips.ethereum.org/EIPS/eip-1559 // 0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s]). raw = [ (0, ethers_1.toBeHex)(tx.chainId), (0, ethers_1.toBeHex)(tx.nonce), tx.maxPriorityFeePerGas ? (0, ethers_1.toBeHex)(tx.maxPriorityFeePerGas) : "0x", tx.maxFeePerGas ? (0, ethers_1.toBeHex)(tx.maxFeePerGas) : "0x", tx.gasLimit ? (0, ethers_1.toBeHex)(tx.gasLimit) : "0x", tx.to || "0x", tx.value ? (0, ethers_1.toBeHex)(tx.value) : "0x", tx.data || "0x", formatAccessList(tx.accessList || []), ]; break; default: // Type 0 Ethereum legacy transaction: // rlp([nonce, gasprice, gaslimit, recipient, amount, data, v, r, s]) raw = [ (0, ethers_1.toBeHex)(tx.nonce), tx.gasPrice ? (0, ethers_1.toBeHex)(tx.gasPrice) : "0x", tx.gasLimit ? (0, ethers_1.toBeHex)(tx.gasLimit) : "0x", tx.to || "0x", tx.value ? (0, ethers_1.toBeHex)(tx.value) : "0x", tx.data || "0x", ]; if (!signature) { raw.push(...[(0, ethers_1.toBeHex)(tx.chainId), "0x", "0x"]); } break; } if (signature) { raw.push(...[ // NOTE: Somehow geth cannot parse `0x00` because it's dumb signature.v ? (0, ethers_1.toBeHex)(signature.v) : "0x", (0, ethers_1.stripZerosLeft)((0, ethers_1.getBytes)(signature.r)), (0, ethers_1.stripZerosLeft)((0, ethers_1.getBytes)(signature.s)), ]); } return raw; } // Almost identical to https://github.com/ethers-io/ethers.js/blob/master/packages/transactions/src.ts/index.ts#L85 // Need to override to use the celo tx prop whitelists above function serializeCeloTransaction(transaction, signature) { Object.keys(transaction).forEach((property) => { if (!(property in exports.celoAllowedTransactionKeys)) { (0, ethers_1.assertArgument)(false, "unknown property", "serializeCeloTransaction", property); } }); const txArgs = {}; Object.entries(transaction).forEach(([fieldName, fieldValue]) => { if (fieldName in exports.celoTransactionFields) { // @ts-expect-error txArgs[fieldName] = formatCeloField(fieldName, fieldValue); } else if (fieldName === 'accessList') { txArgs[fieldName] = fieldValue; } }); let chainId = 0; if (transaction.chainId != null) { // A chainId was provided; if non-zero we'll use EIP-155 chainId = parseInt(transaction.chainId.toString(16), 16); if (typeof chainId !== "number") { (0, ethers_1.assertArgument)(false, "invalid transaction.chainId", "transaction", transaction); } } else if (signature && !(0, ethers_1.isBytesLike)(signature) && signature.v && (0, ethers_1.getNumber)(signature.v) > 28) { // No chainId provided, but the signature is signing with EIP-155; derive chainId chainId = Math.floor(((0, ethers_1.getNumber)(signature.v) - consts_1.EIP155_NUMBER) / 2); } // We have an EIP-155 transaction (chainId was specified and non-zero) if (chainId !== 0) { txArgs["chainId"] = (0, ethers_1.toBeHex)(chainId); // @TODO: hexValue? } // Requesting an unsigned transation // @ts-ignore const type = getTxType(txArgs); // @ts-expect-error txArgs.type = type; if (!signature) { // @ts-expect-error const raw = prepareEncodeTx(txArgs); const encoded = (0, ethers_1.encodeRlp)(raw); return type ? (0, utils_1.concatHex)([(0, ethers_1.toBeHex)(type), encoded]) : encoded; } // The splitSignature will ensure the transaction has a recoveryParam in the // case that the signTransaction function only adds a v. const sig = ethers_1.Signature.from(signature); let v; if (txArgs.type) { // cip64, eip-1559 v = sig.v - consts_1.Y_PARITY_EIP_2098; } else { // celo-legacy v = consts_1.Y_PARITY_EIP_2098 + sig.yParity; if (chainId !== 0) { v += chainId * 2 + consts_1.EIGHT; // If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it! if (sig.v > consts_1.Y_PARITY_EIP_2098 + 1 && sig.v !== v) { (0, ethers_1.assertArgument)(false, "transaction.chainId/signature.v mismatch", "signature", signature); } } else if (sig.v !== v) { (0, ethers_1.assertArgument)(false, "transaction.chainId/signature.v mismatch", "signature", signature); } } // @ts-expect-error const raw = prepareEncodeTx(txArgs, { ...sig.toJSON(), v }); const encoded = (0, ethers_1.encodeRlp)(raw); return type ? (0, utils_1.concatHex)([(0, ethers_1.toBeHex)(type), encoded]) : encoded; } exports.serializeCeloTransaction = serializeCeloTransaction; // Based on https://github.com/ethers-io/ethers.js/blob/0234cfbbef76b7f7a53efe4c434cc6d8892bf404/packages/transactions/src.ts/index.ts#L165 // Need to override to use the celo tx prop whitelists above function parseCeloTransaction(rawTransaction) { const [type, transaction] = splitTypeAndRawTx(rawTransaction); let tx; switch (type) { case TxTypeToPrefix.cip66: tx = { type: TxTypeToPrefix.cip66, chainId: handleNumber(transaction[0]), nonce: handleNumber(transaction[1]), maxPriorityFeePerGas: handleBigInt(transaction[2]), maxFeePerGas: handleBigInt(transaction[3]), gasLimit: handleBigInt(transaction[4]), to: handleAddress(transaction[5]), value: handleBigInt(transaction[6]), data: transaction[7], accessList: handleAccessList(transaction[8]), feeCurrency: handleAddress(transaction[9]), maxFeeInFeeCurrency: handleBigInt(transaction[10]), }; break; case TxTypeToPrefix.cip64: tx = { type: TxTypeToPrefix.cip64, chainId: handleNumber(transaction[0]), nonce: handleNumber(transaction[1]), maxPriorityFeePerGas: handleBigInt(transaction[2]), maxFeePerGas: handleBigInt(transaction[3]), gasLimit: handleBigInt(transaction[4]), to: handleAddress(transaction[5]), value: handleBigInt(transaction[6]), data: transaction[7], accessList: handleAccessList(transaction[8]), feeCurrency: handleAddress(transaction[9]), }; break; case TxTypeToPrefix.eip1559: // untested tx = { type: TxTypeToPrefix.eip1559, chainId: handleNumber(transaction[0]), nonce: handleNumber(transaction[1]), maxPriorityFeePerGas: handleBigInt(transaction[2]), maxFeePerGas: handleBigInt(transaction[3]), gasLimit: handleBigInt(transaction[4]), to: handleAddress(transaction[5]), value: handleBigInt(transaction[6]), data: transaction[7], accessList: handleAccessList(transaction[8]), }; break; default: /** * Type 0 Ethereum legacy transaction: * RLP([nonce, gasprice, gaslimit, recipient, amount, data, chaindId, 0, 0]) */ tx = { nonce: handleNumber(transaction[0]), gasPrice: handleBigInt(transaction[1]), gasLimit: handleBigInt(transaction[2]), to: handleAddress(transaction[3]), value: handleBigInt(transaction[4]), data: transaction[5], chainId: handleBigInt(transaction[6]), }; break; } // Legacy unsigned transaction if (!isSigned(type, transaction)) { return tx; } let v; try { v = handleNumber(transaction.at(-3)); } catch (error) { console.log(error); return tx; } const r = (0, ethers_1.zeroPadValue)(transaction.at(-2), 32); const s = (0, ethers_1.zeroPadValue)(transaction.at(-1), 32); // EIP-155 unsigned transaction if (handleBigInt(r) === 0n && handleBigInt(s) === 0n) { if (!type) { tx.chainId = v; v = 0; } } // Signed Transaction else { let recoveryParam = v; if (!type) { // celo-legacy tx.chainId = Math.max(0, Math.floor((v - consts_1.EIP155_NUMBER) / 2)); recoveryParam = v - consts_1.Y_PARITY_EIP_2098; recoveryParam -= tx.chainId * 2 + consts_1.EIGHT; } // NOTE: Serialization needs to happen here because chainId may not populated before const serialized = serializeCeloTransaction(tx); const digest = (0, ethers_1.keccak256)(serialized); try { tx.from = (0, ethers_1.recoverAddress)(digest, { r, s, yParity: recoveryParam, }); } catch (error) { console.log(error); } tx.hash = (0, ethers_1.keccak256)(rawTransaction); } return tx; } exports.parseCeloTransaction = parseCeloTransaction; function handleAddress(value) { if (value === "0x") { return undefined; } try { return (0, ethers_1.getAddress)(value); } catch (error) { return value; } } function handleNumber(value) { if (value === "0x") { return 0; } return (0, ethers_1.getNumber)(value); } function handleBigInt(value) { if (value === "0x") { return 0n; } return (0, ethers_1.getBigInt)(value); } function formatAccessList(value) { return (0, ethers_1.accessListify)(value).map((set) => [set.address, set.storageKeys]); } /* @param value [ [ '0x0000000000000000000000000000000000000000', [ '0x0000000000000000000000000000000000000000000000000000000000000001', '0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe' ] ] ] */ function handleAccessList(value) { if (value === "0x") { return (0, ethers_1.accessListify)([]); } return (0, ethers_1.accessListify)(value); } const baseTxLengths = { [TxTypeToPrefix.cip64]: { unsigned: 10, signed: 13 }, [TxTypeToPrefix.cip66]: { unsigned: 11, signed: 14 }, [TxTypeToPrefix.eip1559]: { unsigned: 9, signed: 12 }, /** * Unsigned: RLP([nonce, gasprice, gaslimit, recipient, amount, data, chaindId, 0, 0]) * Signed: RLP([nonce, gasprice, gaslimit, recipient, amount, data, v, r, s]) * Source: https://github.com/celo-org/txtypes?tab=readme-ov-file#legacy-transactions */ "ethereum-legacy": { unsigned: 9, signed: 9 }, }; function isSigned(type, transaction) { if (type) { const { signed } = baseTxLengths[type]; return transaction.length === signed; } const r = transaction.at(-2) || "0x"; const s = transaction.at(-1) || "0x"; return r !== "0x" && s !== "0x"; } function isCorrectLength(type, transaction) { const { unsigned } = baseTxLengths[type || "ethereum-legacy"]; return transaction.length === unsigned || isSigned(type, transaction); } function splitTypeAndRawTx(rawTransaction) { let rawStr = rawTransaction.toString(); let type; for (const _type of [TxTypeToPrefix.cip64, TxTypeToPrefix.cip66, TxTypeToPrefix.eip1559]) { const prefix = (0, ethers_1.toBeHex)(_type); if (rawStr.startsWith(prefix)) { rawStr = `0x${rawStr.slice(prefix.length)}`; type = _type; break; } } const transaction = (0, ethers_1.decodeRlp)(rawStr); if (!isCorrectLength(type, transaction)) { (0, ethers_1.assertArgument)(false, "invalid raw transaction", "{type, rawTransaction}", { type: type, rawTransaction, }); } return [type, transaction]; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBeUJnQjtBQUNoQiwrQ0FBa0U7QUFDbEUsc0NBQW9FO0FBNEJwRSxJQUFZLGNBSVg7QUFKRCxXQUFZLGNBQWM7SUFDeEIsdURBQVksQ0FBQTtJQUNaLHVEQUFZLENBQUE7SUFDWix5REFBYyxDQUFBO0FBQ2hCLENBQUMsRUFKVyxjQUFjLDhCQUFkLGNBQWMsUUFJekI7QUFRWSxRQUFBLDBCQUEwQixHQUFHO0lBQ3hDLElBQUksRUFBRSxJQUFJO0lBQ1YsT0FBTyxFQUFFLElBQUk7SUFDYixJQUFJLEVBQUUsSUFBSTtJQUNWLFFBQVEsRUFBRSxJQUFJO0lBQ2QsUUFBUSxFQUFFLElBQUk7SUFDZCxLQUFLLEVBQUUsSUFBSTtJQUNYLEVBQUUsRUFBRSxJQUFJO0lBQ1IsS0FBSyxFQUFFLElBQUk7SUFDWCxXQUFXLEVBQUUsSUFBSTtJQUNqQixZQUFZLEVBQUUsSUFBSTtJQUNsQixvQkFBb0IsRUFBRSxJQUFJO0lBQzFCLFVBQVUsRUFBRSxJQUFJO0lBQ2hCLG1CQUFtQixFQUFFLElBQUk7Q0FDakIsQ0FBQztBQXFCRSxRQUFBLHFCQUFxQixHQUFpQztJQUNqRSxLQUFLLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQVc7SUFDaEQsUUFBUSxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFXO0lBQ25ELFFBQVEsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBVztJQUNuRCxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFXO0lBQ3BDLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQVc7SUFDM0IsS0FBSyxFQUFFLEVBQUUsU0FB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