@celo/connect
Version:
Light Toolkit for connecting with the Celo network
310 lines • 12.2 kB
JavaScript
;
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.inputSignFormatter = exports.inputAddressFormatter = exports.inputAccessListFormatter = exports.parseAccessList = exports.outputBigNumberFormatter = exports.outputLogFormatter = exports.hexToNumber = exports.outputBlockFormatter = exports.outputBlockHeaderFormatter = exports.inputBlockNumberFormatter = exports.inputDefaultBlockNumberFormatter = exports.outputCeloTxReceiptFormatter = exports.outputCeloTxFormatter = exports.inputCeloTxFormatter = void 0;
const address_1 = require("@celo/base/lib/address");
const address_2 = require("@celo/utils/lib/address");
const solidity_1 = require("@celo/utils/lib/solidity");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const utf8_1 = require("utf8");
/**
* Formats the input of a transaction and converts all values to HEX
*/
function inputCeloTxFormatter(tx) {
const { from, chainId, nonce, to, gas, gasPrice, maxFeePerGas, maxPriorityFeePerGas, maxFeeInFeeCurrency, feeCurrency, data, value, accessList, common, chain, hardfork } = tx, rest = __rest(tx, ["from", "chainId", "nonce", "to", "gas", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "maxFeeInFeeCurrency", "feeCurrency", "data", "value", "accessList", "common", "chain", "hardfork"]);
const formattedTX = rest;
formattedTX.from = inputAddressFormatter(from === null || from === void 0 ? void 0 : from.toString());
formattedTX.to = inputAddressFormatter(to);
formattedTX.gas = numberToHex(gas);
formattedTX.value = numberToHex(value === null || value === void 0 ? void 0 : value.toString());
formattedTX.nonce = numberToHex(nonce === null || nonce === void 0 ? void 0 : nonce.toString());
if (feeCurrency) {
formattedTX.feeCurrency = inputAddressFormatter(feeCurrency);
}
if (data && !isHex(data)) {
throw new Error('The data field must be HEX encoded data.');
}
else if (data) {
formattedTX.data = (0, address_1.ensureLeading0x)(data);
}
if (gasPrice) {
formattedTX.gasPrice = numberToHex(gasPrice.toString());
}
if (maxFeePerGas) {
formattedTX.maxFeePerGas = numberToHex(maxFeePerGas.toString());
}
if (maxPriorityFeePerGas) {
formattedTX.maxPriorityFeePerGas = numberToHex(maxPriorityFeePerGas.toString());
}
if (accessList) {
formattedTX.accessList = inputAccessListFormatter(accessList);
}
if (maxFeeInFeeCurrency) {
formattedTX.maxFeeInFeeCurrency = numberToHex(maxFeeInFeeCurrency.toString());
}
return formattedTX;
}
exports.inputCeloTxFormatter = inputCeloTxFormatter;
function outputCeloTxFormatter(tx) {
if (tx.blockNumber !== null) {
tx.blockNumber = hexToNumber(tx.blockNumber);
}
if (tx.transactionIndex !== null) {
tx.transactionIndex = hexToNumber(tx.transactionIndex);
}
tx.nonce = hexToNumber(tx.nonce);
tx.gas = hexToNumber(tx.gas);
tx.value = outputBigNumberFormatter(tx.value);
if (tx.gasPrice) {
tx.gasPrice = outputBigNumberFormatter(tx.gasPrice);
}
if (tx.maxFeePerGas) {
tx.maxFeePerGas = outputBigNumberFormatter(tx.maxFeePerGas);
}
if (tx.maxPriorityFeePerGas) {
tx.maxPriorityFeePerGas = outputBigNumberFormatter(tx.maxPriorityFeePerGas);
}
tx.to =
tx.to && (0, address_2.isValidAddress)(tx.to)
? // tx.to could be `0x0` or `null` while contract creation
(tx.to = (0, address_2.toChecksumAddress)(tx.to))
: null; // set to `null` if invalid address
if (tx.from) {
tx.from = (0, address_2.toChecksumAddress)(tx.from);
}
if (tx.feeCurrency) {
tx.feeCurrency = (0, address_2.toChecksumAddress)(tx.feeCurrency);
}
return tx;
}
exports.outputCeloTxFormatter = outputCeloTxFormatter;
function outputCeloTxReceiptFormatter(receipt) {
if (typeof receipt !== 'object') {
throw new Error('Received receipt is invalid: ' + receipt);
}
if (receipt.blockNumber !== null) {
receipt.blockNumber = hexToNumber(receipt.blockNumber);
}
if (receipt.transactionIndex !== null) {
receipt.transactionIndex = hexToNumber(receipt.transactionIndex);
}
receipt.cumulativeGasUsed = hexToNumber(receipt.cumulativeGasUsed);
receipt.gasUsed = hexToNumber(receipt.gasUsed);
if (Array.isArray(receipt.logs)) {
receipt.logs = receipt.logs.map(outputLogFormatter);
}
if (receipt.contractAddress) {
receipt.contractAddress = (0, address_2.toChecksumAddress)(receipt.contractAddress);
}
if (typeof receipt.status !== 'undefined' && receipt.status !== null) {
receipt.status = Boolean(parseInt((0, address_1.trimLeading0x)(receipt.status), 10));
}
return receipt;
}
exports.outputCeloTxReceiptFormatter = outputCeloTxReceiptFormatter;
function inputDefaultBlockNumberFormatter(blockNumber) {
if (blockNumber == null) {
blockNumber = 'latest';
}
return inputBlockNumberFormatter(blockNumber);
}
exports.inputDefaultBlockNumberFormatter = inputDefaultBlockNumberFormatter;
function inputBlockNumberFormatter(blockNumber) {
if (blockNumber == null) {
return undefined;
}
if (isPredefinedBlockNumber(blockNumber)) {
return blockNumber;
}
if (blockNumber === 'genesis') {
return '0x0';
}
return isHexStrict(blockNumber.toString())
? blockNumber.toString().toLocaleLowerCase()
: numberToHex(blockNumber.toString());
}
exports.inputBlockNumberFormatter = inputBlockNumberFormatter;
// TODO prune after gingerbread hardfork
function outputBlockHeaderFormatter(blockHeader) {
// transform to number
blockHeader.gasLimit = hexToNumber(blockHeader.gasLimit);
blockHeader.gasUsed = hexToNumber(blockHeader.gasUsed);
blockHeader.size = hexToNumber(blockHeader.size);
blockHeader.timestamp = hexToNumber(blockHeader.timestamp);
if (blockHeader.number !== null) {
blockHeader.number = hexToNumber(blockHeader.number);
}
if (blockHeader.miner) {
blockHeader.miner = (0, address_2.toChecksumAddress)(blockHeader.miner);
}
return blockHeader;
}
exports.outputBlockHeaderFormatter = outputBlockHeaderFormatter;
function outputBlockFormatter(block) {
block = outputBlockHeaderFormatter(block);
if (block.difficulty) {
block.difficulty = outputBigNumberFormatter(block.difficulty);
}
if (block.totalDifficulty) {
block.totalDifficulty = outputBigNumberFormatter(block.totalDifficulty);
}
if (Array.isArray(block.transactions)) {
block.transactions.forEach((item) => {
if (typeof item !== 'string' && !(item instanceof String)) {
return outputCeloTxFormatter(item);
}
});
}
return block;
}
exports.outputBlockFormatter = outputBlockFormatter;
function hexToNumber(hex) {
if (hex) {
return new bignumber_js_1.default(hex).toNumber();
}
return undefined;
}
exports.hexToNumber = hexToNumber;
function outputLogFormatter(log) {
// generate a custom log id
if (typeof log.blockHash === 'string' &&
typeof log.transactionHash === 'string' &&
typeof log.logIndex === 'string') {
const shaId = (0, solidity_1.sha3)((0, address_1.trimLeading0x)(log.blockHash) +
(0, address_1.trimLeading0x)(log.transactionHash) +
(0, address_1.trimLeading0x)(log.logIndex));
log.id = 'log_' + (0, address_1.trimLeading0x)(shaId).substring(0, 8);
}
else if (!log.id) {
log.id = null;
}
if (log.blockNumber !== null) {
log.blockNumber = hexToNumber(log.blockNumber);
}
if (log.transactionIndex !== null) {
log.transactionIndex = hexToNumber(log.transactionIndex);
}
if (log.logIndex !== null) {
log.logIndex = hexToNumber(log.logIndex);
}
if (log.address) {
log.address = (0, address_2.toChecksumAddress)(log.address);
}
return log;
}
exports.outputLogFormatter = outputLogFormatter;
function outputBigNumberFormatter(hex) {
return new bignumber_js_1.default(hex).toString(10);
}
exports.outputBigNumberFormatter = outputBigNumberFormatter;
function isHash(value) {
return isHex(value) && value.length === 32;
}
function parseAccessList(accessListRaw) {
const accessList = [];
if (!accessListRaw) {
return accessList;
}
for (const entry of accessListRaw) {
const [address, storageKeys] = entry;
throwIfInvalidAddress(address);
accessList.push({
address,
storageKeys: storageKeys.map((key) => {
if (isHash(key)) {
return key;
}
else {
// same behavior as web3
throw new Error(`Invalid storage key: ${key}`);
}
}),
});
}
return accessList;
}
exports.parseAccessList = parseAccessList;
function throwIfInvalidAddress(address) {
if (!(0, address_2.isValidAddress)(address)) {
throw new Error(`Invalid address: ${address}`);
}
}
function inputAccessListFormatter(accessList) {
if (!accessList || accessList.length === 0) {
return [];
}
return accessList.reduce((acc, { address, storageKeys }) => {
throwIfInvalidAddress(address);
storageKeys.forEach((storageKey) => {
if (storageKey.length - 2 !== 64) {
throw new Error(`Invalid storage key: ${storageKey}`);
}
});
acc.push([address, storageKeys]);
return acc;
}, []);
}
exports.inputAccessListFormatter = inputAccessListFormatter;
function inputAddressFormatter(address) {
if (!address || address === '0x') {
return undefined;
}
if ((0, address_2.isValidAddress)(address)) {
return (0, address_1.ensureLeading0x)(address).toLocaleLowerCase();
}
throw new Error(`Provided address ${address} is invalid, the capitalization checksum test failed`);
}
exports.inputAddressFormatter = inputAddressFormatter;
function inputSignFormatter(data) {
return isHexStrict(data) ? data : utf8ToHex(data);
}
exports.inputSignFormatter = inputSignFormatter;
function utf8ToHex(str) {
str = (0, utf8_1.encode)(str);
let hex = '';
// remove \u0000 padding from either side
str = str.replace(/^(?:\u0000)*/, '');
str = str.split('').reverse().join('');
str = str.replace(/^(?:\u0000)*/, '');
str = str.split('').reverse().join('');
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
// if (code !== 0) {
const n = code.toString(16);
hex += n.length < 2 ? '0' + n : n;
// }
}
return (0, address_1.ensureLeading0x)(hex);
}
function isHex(hex) {
return /^(-0x|0x)?[0-9a-f]*$/i.test(hex);
}
function isHexStrict(hex) {
return /^(-)?0x[0-9a-f]*$/i.test(hex);
}
function numberToHex(value) {
if (value) {
const numberValue = new bignumber_js_1.default(value);
const result = (0, address_1.ensureLeading0x)(new bignumber_js_1.default(value).toString(16));
// Seen in web3, copied just in case
return (numberValue.lt(new bignumber_js_1.default(0)) ? `-${result}` : result);
}
return undefined;
}
function isPredefinedBlockNumber(blockNumber) {
return blockNumber === 'latest' || blockNumber === 'pending' || blockNumber === 'earliest';
}
//# sourceMappingURL=formatter.js.map