UNPKG

@flarenetwork/flare-stake-tool

Version:
484 lines 18 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.toBuffer = toBuffer; exports.toHex = toHex; exports.isHex = isHex; exports.isZeroHex = isZeroHex; exports.isEqualHex = isEqualHex; exports.toCB58 = toCB58; exports.flrToGwei = flrToGwei; exports.weiToFlr = weiToFlr; exports.gweiToFlr = gweiToFlr; exports.gweiToWei = gweiToWei; exports.weiToGwei = weiToGwei; exports.weiToGweiCeil = weiToGweiCeil; exports.dateToDateTimeLocalString = dateToDateTimeLocalString; exports.timestamp = timestamp; exports.dateToDateTimeString = dateToDateTimeString; exports.adjustStartTime = adjustStartTime; exports.adjustStartTimeForDefi = adjustStartTimeForDefi; exports.waitWhile = waitWhile; exports.sleep = sleep; exports.saveToFile = saveToFile; exports.copyToClipboard = copyToClipboard; exports.privateKeyToEncodedPublicKey = privateKeyToEncodedPublicKey; exports.privateKeyToPublicKey = privateKeyToPublicKey; exports.decodePublicKey = decodePublicKey; exports.compressPublicKey = compressPublicKey; exports.publicKeyToBech32AddressBuffer = publicKeyToBech32AddressBuffer; exports.publicKeyToBech32AddressString = publicKeyToBech32AddressString; exports.publicKeyToEthereumAddressString = publicKeyToEthereumAddressString; exports.validatePublicKey = validatePublicKey; exports.recoverMessageSigner = recoverMessageSigner; exports.recoverTransactionSigner = recoverTransactionSigner; exports.recoverPublicKey = recoverPublicKey; exports.sleepms = sleepms; exports.unPrefix0x = unPrefix0x; exports.prefix0x = prefix0x; exports.decimalToInteger = decimalToInteger; exports.integerToDecimal = integerToDecimal; exports.toBN = toBN; exports.initCtxJson = initCtxJson; exports.saveUnsignedTxJson = saveUnsignedTxJson; exports.readUnsignedTxJson = readUnsignedTxJson; exports.readSignedTxJson = readSignedTxJson; exports.addFlagForSentSignedTx = addFlagForSentSignedTx; exports.isAlreadySentToChain = isAlreadySentToChain; exports.waitFinalize = waitFinalize; const bn_js_1 = __importDefault(require("bn.js")); const web3_utils_1 = require("web3-utils"); const base_1 = require("@scure/base"); function toBuffer(value) { if (Buffer.isBuffer(value)) { return value; } else { return Buffer.from(toHex(value, false), 'hex'); } } function toHex(value, prefix0x = true) { let hex; if (!value) { value = '0'; } if (typeof value === 'string') { if (isHex(value)) { hex = value; } else { hex = toHex(base_1.base58.decode(value), prefix0x); } } else if (typeof value === 'number') { hex = value.toString(16); } else if (Buffer.isBuffer(value)) { hex = value.toString('hex'); } else if (value instanceof Uint8Array || Array.isArray(value)) { hex = Buffer.from(value).toString('hex'); } else { throw new Error('The given value cannot be converted to hex'); } if (hex.startsWith('0x')) { return prefix0x ? hex : hex.substring(2); } else { return prefix0x ? `0x${hex}` : hex; } } function isHex(value) { return /^(0x)?[A-F0-9]+$/i.test(value); } function isZeroHex(value) { return /^0x0+$/.test(value); } function isEqualHex(value1, value2) { return (isHex(value1) && isHex(value2) && toHex(value1).toLowerCase() === toHex(value2).toLowerCase()); } function toCB58(value) { return base_1.base58.encode(value); } function flrToGwei(flrValue) { return new bn_js_1.default((0, web3_utils_1.toWei)(flrValue, 'ether')).div(new bn_js_1.default(1e9)); } function weiToFlr(weiValue) { return (0, web3_utils_1.fromWei)(weiValue, 'ether'); } function gweiToFlr(gweiValue, thousandsSeparator = false) { let value = (0, web3_utils_1.fromWei)(new bn_js_1.default(gweiValue).mul(new bn_js_1.default(1e9)).toString(), 'ether'); if (thousandsSeparator) { value = parseFloat(value).toLocaleString(); } return value; } function gweiToWei(gweiValue) { return (gweiValue instanceof bn_js_1.default ? gweiValue : new bn_js_1.default(gweiValue.toString())).mul(new bn_js_1.default(1e9)); } function weiToGwei(weiValue) { return (weiValue instanceof bn_js_1.default ? weiValue : new bn_js_1.default(weiValue.toString())).divRound(new bn_js_1.default(1e9)); } function weiToGweiCeil(weiValue) { let weiValueBN = weiValue instanceof bn_js_1.default ? weiValue : new bn_js_1.default(weiValue.toString()); let dm = weiValueBN.divmod(new bn_js_1.default(1e9)); return dm.mod.isZero() ? dm.div : dm.div.iaddn(1); } function dateToDateTimeLocalString(date) { return new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000).toISOString().slice(0, -1); } function timestamp() { return dateToDateTimeLocalString(new Date()).replace(/[-:.]+/g, '_'); } function dateToDateTimeString(date) { return date.toLocaleString(); } function adjustStartTime(startTime) { return Number(startTime) || Math.round(Date.now() / 1000); } function adjustStartTimeForDefi(startTime) { return Number(startTime) || 1; } async function waitWhile(condition, timeoutMs, delayMs) { let start = Date.now(); while (Date.now() - start < timeoutMs) { if (await condition()) { break; } await sleep(delayMs); } } async function sleep(ms) { await new Promise((resolve) => setTimeout(resolve, ms)); } function saveToFile(text, filename) { let file = new Blob([text], { type: 'text/plain' }); let a = document.createElement('a'); let url = URL.createObjectURL(file); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); setTimeout(function () { document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 0); } async function copyToClipboard(text) { let result = await navigator.permissions.query({ name: 'clipboard-write' }); if (result.state === 'granted' || result.state === 'prompt') { await navigator.clipboard.writeText(text); } } const fs_1 = __importDefault(require("fs")); const ethutil = __importStar(require("ethereumjs-util")); const elliptic = __importStar(require("elliptic")); const bech32_1 = require("bech32"); const forDefi_1 = require("./constants/forDefi"); ////////////////////////////////////////////////////////////////////////////////////////// // public keys and bech32 addresses const ec = new elliptic.ec('secp256k1'); function privateKeyToEncodedPublicKey(privateKey, compress = true) { const keyPair = ec.keyFromPrivate(privateKey); return keyPair.getPublic().encode('hex', compress); } function privateKeyToPublicKey(privateKey) { const keyPair = ec.keyFromPrivate(privateKey).getPublic(); const x = keyPair.getX().toBuffer(undefined, 32); const y = keyPair.getY().toBuffer(undefined, 32); return [x, y]; } function decodePublicKey(publicKey) { publicKey = unPrefix0x(publicKey); if (publicKey.length == 128) { publicKey = '04' + publicKey; } const keyPair = ec.keyFromPublic(publicKey, 'hex').getPublic(); const x = keyPair.getX().toBuffer(undefined, 32); const y = keyPair.getY().toBuffer(undefined, 32); return [x, y]; } function compressPublicKey(x, y) { return Buffer.from(ec .keyFromPublic({ x: x.toString('hex'), y: y.toString('hex') }) .getPublic() .encode('hex', true), 'hex'); } function publicKeyToBech32AddressBuffer(x, y) { const compressed = compressPublicKey(x, y); return ethutil.ripemd160(ethutil.sha256(compressed), false); } function publicKeyToBech32AddressString(publicKey, hrp) { const [pubX, pubY] = decodePublicKey(publicKey); const addressBuffer = publicKeyToBech32AddressBuffer(pubX, pubY); return `${bech32_1.bech32.encode(hrp, bech32_1.bech32.toWords(addressBuffer))}`; } function publicKeyToEthereumAddressString(publicKey) { const [pubX, pubY] = decodePublicKey(publicKey); const decompressedPubk = Buffer.concat([pubX, pubY]); const ethAddress = ethutil.publicToAddress(decompressedPubk); return prefix0x(ethAddress.toString('hex')); } function validatePublicKey(publicKey) { try { decodePublicKey(publicKey); return true; } catch (error) { console.error('Invalid public key:', error); return false; } } ///////////////////////////////////////////////////////////////////////////////////////// // signatures function recoverMessageSigner(message, signature) { const messageHash = ethutil.hashPersonalMessage(message); return recoverTransactionSigner(messageHash, signature); } function recoverTransactionSigner(message, signature) { let split = ethutil.fromRpcSig(signature); let publicKey = ethutil.ecrecover(message, split.v, split.r, split.s); let signer = ethutil.pubToAddress(publicKey).toString('hex'); return signer; } function recoverPublicKey(message, signature) { const split = ethutil.fromRpcSig(signature); return ethutil.ecrecover(message, split.v, split.r, split.s); } //export function expandSignature(signature: string): EcdsaSignature { // let recoveryParam = parseInt(signature.slice(128, 130), 16); // if (recoveryParam === 27 || recoveryParam === 28) recoveryParam -= 27; // return { // r: new BN(signature.slice(0, 64), "hex"), // s: new BN(signature.slice(64, 128), "hex"), // recoveryParam: recoveryParam, // }; //} ////////////////////////////////////////////////////////////////////////////////////////// // general helper functions async function sleepms(milliseconds) { await new Promise((resolve) => { setTimeout(resolve, milliseconds); }); } function unPrefix0x(tx) { if (!tx) { return '0x0'; } return tx.startsWith('0x') ? tx.slice(2) : tx; } function prefix0x(hexString) { if (!hexString) { return '0x0'; } return hexString.startsWith('0x') ? hexString : '0x' + unPrefix0x(hexString); } function decimalToInteger(dec, offset) { let ret = dec; if (ret.includes('.')) { const split = ret.split('.'); ret = split[0] + split[1].slice(0, offset).padEnd(offset, '0'); } else { ret = ret + '0'.repeat(offset); } return ret; } function integerToDecimal(int, offset) { if (int === '0') { return '0'; } int = int.padStart(offset, '0'); const part1 = int.slice(0, -offset) || '0'; const part2 = int.slice(-offset).replace(/0+$/, ''); return part1 + (part2 === '' ? '' : '.' + part2); } //export function parseRelativeTime(time: string): string { // // assume time starts with now+ // return UnixNow() // .add(new BN(time.split("+")[1])) // .toString(); //} function toBN(num) { return num ? new bn_js_1.default(num) : undefined; } //////////////////////////////////////////////////////////////////////////////////////////// //// key and unsigned/signed transaction storage // function initCtxJson(contextFile) { if (fs_1.default.existsSync('ctx.json')) { throw new Error('ctx.json already exists'); } fs_1.default.writeFileSync('ctx.json', JSON.stringify(contextFile, null, 2)); } function saveUnsignedTxJson(unsignedTxJson, id, dir) { if (dir === undefined) { dir = `${forDefi_1.forDefiDirectory}/${forDefi_1.forDefiUnsignedTxnDirectory}`; } fs_1.default.mkdirSync(dir, { recursive: true }); const fname = `${dir}/${id}.unsignedTx.json`; if (fs_1.default.existsSync(fname)) { throw new Error(`unsignedTx file ${fname} already exists`); } const forDefiHash = Buffer.from(unsignedTxJson.signatureRequests[0].message, 'hex').toString('base64'); const unsignedTxJsonForDefi = { ...unsignedTxJson, forDefiHash: forDefiHash, }; const serialization = JSON.stringify(unsignedTxJsonForDefi, null, 2); fs_1.default.writeFileSync(fname, serialization); return forDefiHash; } function readUnsignedTxJson(id) { const fname = `${forDefi_1.forDefiDirectory}/${forDefi_1.forDefiUnsignedTxnDirectory}/${id}.unsignedTx.json`; if (!fs_1.default.existsSync(fname)) { throw new Error(`unsignedTx file ${fname} does not exist`); } const serialization = fs_1.default.readFileSync(fname, 'utf-8').toString(); return JSON.parse(serialization); } function readSignedTxJson(id) { const fname = `${forDefi_1.forDefiDirectory}/${forDefi_1.forDefiSignedTxnDirectory}/${id}.signedTx.json`; if (!fs_1.default.existsSync(fname)) { throw new Error(`signedTx file ${fname} does not exist`); } const serialization = fs_1.default.readFileSync(fname).toString(); const resp = JSON.parse(serialization); if (!resp.signature) { throw new Error(`unsignedTx file ${fname} does not contain signature`); } return resp; } /** * @description Adds a flag to the signed txn to indicate it has been submitted to the blockchain * @param {string} id Transaction Id used to create the transaction file */ function addFlagForSentSignedTx(id) { const fname = `${forDefi_1.forDefiDirectory}/${forDefi_1.forDefiSignedTxnDirectory}/${id}.signedTx.json`; if (!fs_1.default.existsSync(fname)) { throw new Error(`signedTx file ${fname} does not exist`); } const serialization = fs_1.default.readFileSync(fname).toString(); const txObj = JSON.parse(serialization); txObj.isSentToChain = true; fs_1.default.writeFileSync(`${forDefi_1.forDefiDirectory}/${forDefi_1.forDefiSignedTxnDirectory}/${id}.signedTx.json`, JSON.stringify(txObj), "utf8"); } /** * @description Checks whether the transaction has already been submitted to the blockchain * @param {string} id Transaction Id used to create the transaction file * @returns {boolean} */ function isAlreadySentToChain(id) { const fname = `${forDefi_1.forDefiDirectory}/${forDefi_1.forDefiSignedTxnDirectory}/${id}.signedTx.json`; if (!fs_1.default.existsSync(fname)) { return false; } const serialization = fs_1.default.readFileSync(fname).toString(); const txObj = JSON.parse(serialization); return !!txObj.isSentToChain; } ////////////////////////////////////////////////////////////////////////////////////////// // limiting delegation number //function countpAddressInDelegation( // validators: any[], // pAddressBech32: string, //): { count: number; validatorNodeIds: string[] } { // let count = 0; // const validatorNodeIds = []; // for (const item of validators) { // if (item.delegators) { // for (const delegator of item.delegators) { // for (const addr of delegator.rewardOwner.addresses) { // if (addr.toLowerCase() === pAddressBech32.toLowerCase()) { // count++; // validatorNodeIds.push(item.nodeID.toLowerCase()); // } // } // } // } // } // return { count, validatorNodeIds }; //} ///** // * @description Count number of p-chain address used for delegation // * @param {Context} ctx context file // * @returns number of times p address used in current validators delegation list // */ //export async function delegationAddressCount(ctx: Context) { // const current = await ctx.pchain.getCurrentValidators(); // const pending = await ctx.pchain.getPendingValidators(); // const pendingValidtaor = JSON.parse(JSON.stringify(pending)); // const pCurrent = JSON.parse(JSON.stringify(current)); // const currentDelegationDetails = countpAddressInDelegation( // pCurrent.validators, // ctx.pAddressBech32!, // ); // const pendingDelegationDetails = countpAddressInDelegation( // pendingValidtaor.validators, // ctx.pAddressBech32!, // ); // return { // count: currentDelegationDetails.count + pendingDelegationDetails.count, // validatorNodeId: [ // ...currentDelegationDetails.validatorNodeIds, // ...pendingDelegationDetails.validatorNodeIds, // ], // }; //} // //////////////////////////////////////////////////////////////////////////////////////////// //// finalization // async function waitFinalize(ctx, prms) { if (!ctx.web3 || !ctx.cAddressHex) { throw new Error('Web3 or contract address is not initialized in the context'); } const txcount1 = await ctx.web3.eth.getTransactionCount(ctx.cAddressHex); const resp = await prms; while ((await ctx.web3.eth.getTransactionCount(ctx.cAddressHex)) == txcount1) { await sleepms(1000); } return resp; } //# sourceMappingURL=utils.js.map