UNPKG

@flarenetwork/flare-stake-tool

Version:
759 lines 31.8 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.buildExportCTx = buildExportCTx; exports.buildImportCTx = buildImportCTx; exports.buildImportPTx = buildImportPTx; exports.buildExportPTx = buildExportPTx; exports.buildAddDelegatorTx = buildAddDelegatorTx; exports.buildAddValidatorTx = buildAddValidatorTx; exports.buildBaseTx = buildBaseTx; exports.buildEvmTx = buildEvmTx; exports.finalizeAndConvertEvmTx = finalizeAndConvertEvmTx; exports.signAndSubmitTx = signAndSubmitTx; exports.submitTxHex = submitTxHex; exports.getStakeTransaction = getStakeTransaction; const utils = __importStar(require("../utils")); const settings = __importStar(require("../settings")); const chain = __importStar(require("./chain")); const pubk = __importStar(require("./pubk")); const bn_js_1 = __importDefault(require("bn.js")); const flarejs_1 = require("@flarenetwork/flarejs"); const tx_1 = require("@ethereumjs/tx"); const rlp_1 = require("@ethereumjs/rlp"); const common_1 = require("@ethereumjs/common"); const context_1 = require("./context"); const TX_WAIT_MS = 15000; const TX_CHECK_MS = 1000; async function buildExportCTx(account, params) { const importFeeReservation = await chain.getPTxDefaultFee(account.network); if (!params.exportFee || params.exportFee.isZero()) { params.exportFee = await _getExportCTxFee(account, params.amount, importFeeReservation); } const unsignedTx = await _getUnsignedExportCTx(account, params.amount, params.exportFee, importFeeReservation); const unsignedTxHex = _unsignedTxToHex(unsignedTx); return { txDetails: { ...params, importFeeReservation, unsignedTxHex, }, unsignedTx, }; } async function _getExportCTxFee(account, amount, importFeeReservation) { const baseFee = await chain.getCTxBaseFee(account.network); const tx = await _getUnsignedExportCTx(account, amount, new bn_js_1.default(0), importFeeReservation); const cost = new bn_js_1.default(flarejs_1.utils.costCorethTx(tx).toString()); return baseFee.mul(cost); } async function _getUnsignedExportCTx(account, amount, exportFee, importFeeReservation) { const context = await (0, context_1.getContext)(account.network); const cAddress = flarejs_1.utils.hexToBuffer(account.cAddress); const pAddress = flarejs_1.utils.bech32ToBytes(account.pAddress); const nonce = await chain.numberOfCTxs(account.network, account.cAddress); return flarejs_1.evm.newExportTx(context, BigInt(amount.add(importFeeReservation).toString()), context.pBlockchainID, cAddress, [pAddress], BigInt(exportFee.toString()), BigInt(nonce)); } async function buildImportCTx(account, params) { if (!params.importFee || params.importFee.isZero()) { params.importFee = await _getImportCTxFee(account); } const unsignedTx = await _getUnsignedImportCTx(account, params.importFee); const amount = await chain.getPCBalance(account.network, account.pAddress); const unsignedTxHex = _unsignedTxToHex(unsignedTx); return { txDetails: { ...params, amount, unsignedTxHex }, unsignedTx, }; } async function _getImportCTxFee(account) { const baseFee = await chain.getCTxBaseFee(account.network); const tx = await _getUnsignedImportCTx(account, new bn_js_1.default(0)); const cost = new bn_js_1.default(flarejs_1.utils.costCorethTx(tx).toString()); return baseFee.mul(cost); } async function _getUnsignedImportCTx(account, importFee) { const context = await (0, context_1.getContext)(account.network); const pAddressString = `C-${account.pAddress.slice(2)}`; const pAddress = flarejs_1.utils.bech32ToBytes(pAddressString); const cAddress = flarejs_1.utils.hexToBuffer(account.cAddress); const evmapi = new flarejs_1.evm.EVMApi(settings.URL[account.network]); const { utxos } = await evmapi.getUTXOs({ addresses: [pAddressString], sourceChain: "P", }); return flarejs_1.evm.newImportTx(context, cAddress, [pAddress], utxos, context.pBlockchainID, BigInt(importFee.toString())); } async function buildImportPTx(account, params) { const context = await (0, context_1.getContext)(account.network); const pvmapi = new flarejs_1.pvm.PVMApi(settings.URL[account.network]); const feeState = await pvmapi.getFeeState(); const pAddressString = account.pAddress; const pAddress = flarejs_1.utils.bech32ToBytes(pAddressString); const { utxos } = await pvmapi.getUTXOs({ addresses: [pAddressString], sourceChain: "C", }); const isEtnaForkActive = await (0, context_1.isEtnaActive)(account.network); let unsignedTx; if (isEtnaForkActive) { unsignedTx = flarejs_1.pvm.e.newImportTx({ feeState, sourceChainId: context.cBlockchainID, utxos, fromAddressesBytes: [pAddress], toAddressesBytes: [pAddress], }, context); } else { unsignedTx = flarejs_1.pvm.newImportTx(context, context.cBlockchainID, utxos, [pAddress], [pAddress]); } const amount = await chain.getCPBalance(account.network, account.pAddress); const importFee = await chain.getPTxDefaultFee(account.network); const unsignedTxHex = _unsignedTxToHex(unsignedTx); return { txDetails: { ...params, amount, importFee, unsignedTxHex, }, unsignedTx, }; } async function buildExportPTx(account, params) { const context = await (0, context_1.getContext)(account.network); const pvmapi = new flarejs_1.pvm.PVMApi(settings.URL[account.network]); const feeState = await pvmapi.getFeeState(); const pAddressString = account.pAddress; const pAddress = flarejs_1.utils.bech32ToBytes(pAddressString); const isEtnaForkActive = await (0, context_1.isEtnaActive)(account.network); const exportFee = await chain.getPTxDefaultFee(account.network); let amount = params.amount; if (!amount || amount.isZero()) { amount = (await chain.getPBalance(account.network, account.pAddress)).sub(exportFee); } if (amount.lte(new bn_js_1.default(0))) { throw new Error("Export amount is smaller than or equal to zero"); } const { utxos } = await pvmapi.getUTXOs({ addresses: [pAddressString] }); const output = flarejs_1.TransferableOutput.fromNative(context.avaxAssetID, BigInt(amount.toString()), [pAddress]); let unsignedTx; if (isEtnaForkActive) { unsignedTx = flarejs_1.pvm.e.newExportTx({ feeState, destinationChainId: context.cBlockchainID, fromAddressesBytes: [pAddress], utxos, outputs: [output], }, context); } else { unsignedTx = flarejs_1.pvm.newExportTx(context, context.cBlockchainID, [pAddress], utxos, [output]); } const unsignedTxHex = _unsignedTxToHex(unsignedTx); return { txDetails: { ...params, exportFee, unsignedTxHex }, unsignedTx, }; } async function buildAddDelegatorTx(account, params) { const context = await (0, context_1.getContext)(account.network); const pvmapi = new flarejs_1.pvm.PVMApi(settings.URL[account.network]); const feeState = await pvmapi.getFeeState(); const pAddressString = account.pAddress; const pAddress = flarejs_1.utils.bech32ToBytes(pAddressString); const { utxos } = await pvmapi.getUTXOs({ addresses: [pAddressString] }); const isEtnaForkActive = await (0, context_1.isEtnaActive)(account.network); let unsignedTx; if (isEtnaForkActive) { unsignedTx = flarejs_1.pvm.e.newAddPermissionlessDelegatorTx({ feeState, utxos, fromAddressesBytes: [pAddress], nodeId: params.nodeId, subnetId: flarejs_1.networkIDs.PrimaryNetworkID.toString(), start: BigInt(params.startTime.toString()), end: BigInt(params.endTime.toString()), weight: BigInt(params.amount.toString()), rewardAddresses: [pAddress], }, context); } else { unsignedTx = flarejs_1.pvm.newAddPermissionlessDelegatorTx(context, utxos, [pAddress], params.nodeId, flarejs_1.networkIDs.PrimaryNetworkID.toString(), BigInt(params.startTime.toString()), BigInt(params.endTime.toString()), BigInt(params.amount.toString()), [pAddress]); } const unsignedTxHex = _unsignedTxToHex(unsignedTx); return { txDetails: { ...params, unsignedTxHex }, unsignedTx, }; } async function buildAddValidatorTx(account, params) { const context = await (0, context_1.getContext)(account.network); const pvmapi = new flarejs_1.pvm.PVMApi(settings.URL[account.network]); const feeState = await pvmapi.getFeeState(); const pAddressString = account.pAddress; const pAddress = flarejs_1.utils.bech32ToBytes(pAddressString); const { utxos } = await pvmapi.getUTXOs({ addresses: [pAddressString] }); const isEtnaForkActive = await (0, context_1.isEtnaActive)(account.network); let unsignedTx; if (isEtnaForkActive) { unsignedTx = flarejs_1.pvm.e.newAddPermissionlessValidatorTx({ feeState, utxos, delegatorRewardsOwner: [pAddress], nodeId: params.nodeId, subnetId: flarejs_1.networkIDs.PrimaryNetworkID.toString(), start: BigInt(params.startTime.toString()), end: BigInt(params.endTime.toString()), weight: BigInt(params.amount.toString()), rewardAddresses: [pAddress], fromAddressesBytes: [pAddress], shares: params.delegationFee, changeAddressesBytes: [pAddress], publicKey: params.popBLSPublicKey, signature: params.popBLSSignature, }, context); } else { unsignedTx = flarejs_1.pvm.newAddPermissionlessValidatorTx(context, utxos, [pAddress], params.nodeId, flarejs_1.networkIDs.PrimaryNetworkID.toString(), BigInt(params.startTime.toString()), BigInt(params.endTime.toString()), BigInt(params.amount.toString()), [pAddress], [pAddress], params.delegationFee, undefined, 1, 0n, params.popBLSPublicKey, params.popBLSSignature); } const unsignedTxHex = _unsignedTxToHex(unsignedTx); return { txDetails: { ...params, unsignedTxHex }, unsignedTx, }; } async function buildBaseTx(account, params) { const context = await (0, context_1.getContext)(account.network); const pvmapi = new flarejs_1.pvm.PVMApi(settings.URL[account.network]); const feeState = await pvmapi.getFeeState(); const pAddressString = account.pAddress; const pAddressBytes = flarejs_1.utils.bech32ToBytes(pAddressString); const { utxos } = await pvmapi.getUTXOs({ addresses: [pAddressString] }); const recipientAddressBytes = flarejs_1.utils.bech32ToBytes(params.recipientAddress); const isEtnaForkActive = await (0, context_1.isEtnaActive)(account.network); let unsignedTx; if (isEtnaForkActive) { unsignedTx = flarejs_1.pvm.e.newBaseTx({ feeState, fromAddressesBytes: [pAddressBytes], utxos, outputs: [flarejs_1.TransferableOutput.fromNative(context.avaxAssetID, BigInt(params.amount), [recipientAddressBytes])], }, context); } else { unsignedTx = flarejs_1.pvm.newBaseTx(context, [pAddressBytes], utxos, [ flarejs_1.TransferableOutput.fromNative(context.avaxAssetID, BigInt(params.amount), [recipientAddressBytes]), ]); } const unsignedTxHex = _unsignedTxToHex(unsignedTx); return { txDetails: { ...params, unsignedTxHex }, unsignedTx, }; } function _unsignedTxToHex(unsignedTx) { return utils.toHex(unsignedTx.toBytes()); } async function buildEvmTx(account, params, evmTx) { const txData = { from: account.cAddress, chainId: BigInt(settings.CHAIN_ID[account.network]), ...evmTx, }; if (!txData.value) { txData.value = BigInt(0); } if (!txData.nonce) { txData.nonce = await chain.numberOfCTxs(account.network, account.cAddress); } if (!txData.maxFeePerGas || !txData.maxPriorityFeePerGas) { const feeEstimate = await chain.estimateEIP1559Fee(account.network); txData.maxFeePerGas = feeEstimate[0]; txData.maxPriorityFeePerGas = feeEstimate[1]; } if (!txData.gasLimit) { const web3 = chain.getWeb3(account.network); const estimatedGasLimit = await web3.eth.estimateGas(txData); txData.gasLimit = (estimatedGasLimit * BigInt(10500)) / BigInt(10000); } let unsignedTx; let unsignedTxHex; if (params.txType === 0) { const common = common_1.Common.custom({ chainId: txData.chainId }); const evmLegacyTx = { from: txData.from, to: Uint8Array.from(utils.toBuffer(txData.to)), data: Uint8Array.from(utils.toBuffer(txData.data ?? "")), value: txData.value, gasLimit: txData.gasLimit, gasPrice: txData.maxFeePerGas - txData.maxPriorityFeePerGas, nonce: txData.nonce, chainId: txData.chainId, }; unsignedTx = tx_1.LegacyTransaction.fromTxData(evmLegacyTx, { common }); unsignedTxHex = utils.toHex(rlp_1.RLP.encode(unsignedTx.getMessageToSign())); } else if (params.txType === 2) { const evmEIP1559Tx = { from: txData.from, to: Uint8Array.from(utils.toBuffer(txData.to)), data: Uint8Array.from(utils.toBuffer(txData.data ?? "")), value: txData.value, gasLimit: txData.gasLimit, maxPriorityFeePerGas: txData.maxPriorityFeePerGas, maxFeePerGas: txData.maxFeePerGas, nonce: txData.nonce, chainId: txData.chainId, }; unsignedTx = tx_1.FeeMarketEIP1559Transaction.fromTxData(evmEIP1559Tx); unsignedTxHex = utils.toHex(unsignedTx.getMessageToSign()); } else { throw new Error("Unsupported transaction type"); } return { txDetails: { ...params, ...txData, unsignedTxHex, isEvmTx: true, }, unsignedTx, }; } async function finalizeAndConvertEvmTx(from, txHex, txType) { const tx = tx_1.TransactionFactory.fromSerializedData(utils.toBuffer(txHex)); let chainId; let accessList; if (tx instanceof tx_1.LegacyTransaction) { if (!tx.v) { throw new Error("Legacy transaction must have v field defined"); } chainId = tx.v; accessList = null; } else if (tx instanceof tx_1.FeeMarketEIP1559Transaction) { chainId = tx.chainId; accessList = tx.accessList; } else { throw new Error("Unsupported EVM transaction type given"); } const network = _getNetworkFromChainId(chainId); const to = utils.toHex(tx.to ? tx.to.toString() : ""); const value = tx.value; const data = utils.toHex(tx.data); const nonce = await chain.numberOfCTxs(network, from); const feeEstimate = await chain.estimateEIP1559Fee(network); const maxFeePerGas = feeEstimate[0]; const maxPriorityFeePerGas = feeEstimate[1]; const web3 = chain.getWeb3(network); const estimatedGasLimit = await web3.eth.estimateGas({ from, to, value, data, nonce, }); const gasLimit = (estimatedGasLimit * BigInt(10500)) / BigInt(10000); let unsignedTxHex; if (txType === 0) { const toArray = Uint8Array.from(utils.toBuffer(to)); const dataArray = Uint8Array.from(utils.toBuffer(data)); const common = common_1.Common.custom({ chainId }); const gasPrice = maxFeePerGas - maxPriorityFeePerGas; const unsignedTx = tx_1.LegacyTransaction.fromTxData({ to: toArray, value, data: dataArray, nonce, gasLimit, gasPrice }, { common }); unsignedTxHex = utils.toHex(rlp_1.RLP.encode(unsignedTx.getMessageToSign())); } else if (txType === 2) { const toArray = Uint8Array.from(utils.toBuffer(to)); const dataArray = Uint8Array.from(utils.toBuffer(data)); const unsignedTx = tx_1.FeeMarketEIP1559Transaction.fromTxData({ chainId, to: toArray, value, data: dataArray, nonce, gasLimit, maxFeePerGas, maxPriorityFeePerGas, accessList, }); unsignedTxHex = utils.toHex(unsignedTx.getMessageToSign()); } else { throw new Error("Unsupported EVM transaction type requested"); } return unsignedTxHex; } async function signAndSubmitTx(unsignedTxData, sign, presubmit) { let unsignedTxHash; const unsignedTx = unsignedTxData.unsignedTx; if (unsignedTx instanceof tx_1.LegacyTransaction) { unsignedTxHash = utils.toHex(unsignedTx.getHashedMessageToSign()); } else if (unsignedTx instanceof tx_1.FeeMarketEIP1559Transaction) { unsignedTxHash = utils.toHex(unsignedTx.getHashedMessageToSign()); } else if (unsignedTx instanceof flarejs_1.UnsignedTx) { unsignedTxHash = utils.toHex((0, flarejs_1.messageHashFromUnsignedTx)(unsignedTx)); } else { throw new Error(`Can't issue transaction of type ${typeof unsignedTx}`); } const signatureResponse = await sign({ ...unsignedTxData.txDetails, unsignedTxHash, }); let id = ""; let submitted = false; const network = unsignedTxData.txDetails.network; const signedTxData = { ...unsignedTxData, signature: "", signedTx: "" }; if (signatureResponse.startsWith("id:")) { // the transaction was not just signed but also submitted to the network id = signatureResponse.slice(3); submitted = true; } else { const signature = utils.toHex(signatureResponse, false); signedTxData.signature = signature; let publicKey = pubk.recoverPublicKeyFromMsg(unsignedTxHash, signature); if (!pubk.equalPublicKey(publicKey, unsignedTxData.txDetails.publicKey)) { if (unsignedTx instanceof flarejs_1.UnsignedTx) { publicKey = pubk.recoverPublicKeyFromEthMsg(utils.toHex(unsignedTxHash, false), signature); if (!pubk.equalPublicKey(publicKey, unsignedTxData.txDetails.publicKey)) { throw new Error("The public key recovered from the (ETH) signature does not match the expected public key"); } } else { throw new Error("The public key recovered from the signature does not match the expected public key"); } } let signedTx; if (unsignedTx instanceof tx_1.LegacyTransaction || unsignedTx instanceof tx_1.FeeMarketEIP1559Transaction) { const expandedSignature = _expandSignature(signature); let tx; if (unsignedTx instanceof tx_1.LegacyTransaction) { let v = expandedSignature.recoveryParam; if (v === 0 || v === 1) { v += 27; } if (v === 27 || v === 28) { v += 8 + 2 * parseInt(settings.CHAIN_ID[network], 16); } tx = tx_1.LegacyTransaction.fromTxData({ ...unsignedTx.toJSON(), v: BigInt(v.toString()), r: BigInt(expandedSignature.r.toString()), s: BigInt(expandedSignature.s.toString()), }); } else { const txData = unsignedTx.toJSON(); delete txData.gasPrice; tx = tx_1.FeeMarketEIP1559Transaction.fromTxData({ ...txData, v: BigInt(expandedSignature.recoveryParam.toString()), r: BigInt(expandedSignature.r.toString()), s: BigInt(expandedSignature.s.toString()), }); } signedTx = tx.serialize(); } else if (unsignedTx instanceof flarejs_1.EVMUnsignedTx) { const compressedPublicKey = pubk.compressPublicKey(Buffer.from("04" + publicKey, "hex")); const expandedSignature = _expandSignature(signature); signTxDbg(unsignedTx, [ { signature: _transformSignature(expandedSignature), publicKey: compressedPublicKey, }, ]); signedTx = unsignedTx.getSignedTx().toBytes(); } else { // unsignedTx instanceof UnsignedTx const compressedPublicKey = pubk.compressPublicKey(Buffer.from("04" + publicKey, "hex")); const expandedSignature = _expandSignature(signature); signTxDbg(unsignedTx, [ { signature: _transformSignature(expandedSignature), // signature: Buffer.from(signature, "hex"), publicKey: compressedPublicKey, }, ]); signedTx = unsignedTx.getSignedTx().toBytes(); } signedTxData.signedTx = utils.toHex(signedTx); const txSummary = { network: signedTxData.txDetails.network, type: signedTxData.txDetails.type, publicKey: signedTxData.txDetails.publicKey, unsignedTx: signedTxData.txDetails.unsignedTxHex, unsignedTxHash: signedTxData.txDetails.unsignedTxHash, signature: signedTxData.signature, signedTx: signedTxData.signedTx, }; if (!presubmit || (await presubmit(txSummary))) { if (unsignedTx instanceof tx_1.LegacyTransaction || unsignedTx instanceof tx_1.FeeMarketEIP1559Transaction) { const web3 = chain.getWeb3(network); id = await _submitEvmTx(web3, signedTxData.signedTx); } else { if (unsignedTx instanceof flarejs_1.EVMUnsignedTx) { const evmapi = new flarejs_1.evm.EVMApi(settings.URL[network]); id = (await evmapi.issueTx({ tx: utils.toHex(flarejs_1.utils.addChecksum(signedTx)), })).txID; } else if (unsignedTx instanceof flarejs_1.UnsignedTx) { const pvmapi = new flarejs_1.pvm.PVMApi(settings.URL[network]); id = (await pvmapi.issueTx({ tx: utils.toHex(flarejs_1.utils.addChecksum(signedTx)), })).txID; } else { throw new Error(`Can not issue transaction of type ${typeof unsignedTx}`); } } submitted = true; } } let status = ""; let confirmed = false; if (submitted) { let result; if (unsignedTx instanceof tx_1.LegacyTransaction || unsignedTx instanceof tx_1.FeeMarketEIP1559Transaction) { result = await _waitForEvmTxConfirmation(chain.getWeb3(network), id); } else if (unsignedTx instanceof flarejs_1.EVMUnsignedTx) { const evmapi = new flarejs_1.evm.EVMApi(settings.URL[network]); result = await _waitForCTxConfirmation(evmapi, id); } else if (unsignedTx instanceof flarejs_1.UnsignedTx) { const pvmapi = new flarejs_1.pvm.PVMApi(settings.URL[network]); result = await _waitForPTxConfirmation(pvmapi, id); } else { throw new Error(`Can not issue transaction of type ${typeof unsignedTx}`); } status = result[0]; confirmed = result[1]; } return { ...signedTxData, id, status, submitted, confirmed }; } function _expandSignature(signature) { let recoveryParam = parseInt(signature.slice(128, 130), 16); if (recoveryParam === 27 || recoveryParam === 28) { recoveryParam -= 27; } return { r: new bn_js_1.default(signature.slice(0, 64), "hex"), s: new bn_js_1.default(signature.slice(64, 128), "hex"), recoveryParam: recoveryParam, }; } async function submitTxHex(txHex) { try { // let ctx = new CTx() // ctx.fromBuffer(utils.toBuffer(txHex) as any) // let network = _getNetworkFromChainId(ctx.getUnsignedTx().getTransaction().getNetworkID()) // const context = await getContext(network) // let avajs = chain.getAvalanche(network) // TODO: obtain network name from ... const evmapi = new flarejs_1.evm.EVMApi(settings.URL["localflare"]); const id = await _submitCTx(evmapi, txHex); const result = await _waitForCTxConfirmation(evmapi, id); const status = result[0]; const confirmed = result[1]; return [id, status, confirmed]; } catch (e) { console.log("Error submitting CTx", e); } try { // let ptx = new PTx() // ptx.fromBuffer(utils.toBuffer(txHex) as any) // let network = _getNetworkFromChainId(ptx.getUnsignedTx().getTransaction().getNetworkID()) // let avajs = chain.getAvalanche(network) const pvmapi = new flarejs_1.pvm.PVMApi(settings.URL["localflare"]); const id = await _submitPTx(pvmapi, txHex); const result = await _waitForPTxConfirmation(pvmapi, id); const status = result[0]; const confirmed = result[1]; return [id, status, confirmed]; } catch (e) { console.log("Error submitting PTx", e); } try { const evmTx = tx_1.TransactionFactory.fromSerializedData(utils.toBuffer(txHex)); let chainId; if (evmTx instanceof tx_1.LegacyTransaction) { if (!evmTx.v) { throw new Error("Legacy transaction must have v field defined"); } chainId = evmTx.v; } else { chainId = evmTx.chainId; } const network = _getNetworkFromChainId(chainId); const web3 = chain.getWeb3(network); const id = await _submitEvmTx(web3, txHex); const result = await _waitForEvmTxConfirmation(web3, id); const status = result[0]; const confirmed = result[1]; return [id, status, confirmed]; } catch (e) { console.log("Error submitting EVM Tx", e); } return null; } async function _submitCTx(evmapi, txHex) { const { txID } = await evmapi.issueTx({ tx: txHex }); return txID; } async function _submitPTx(pvmapi, txHex) { const { txID } = await pvmapi.issueTx({ tx: txHex }); return txID; } async function _submitEvmTx(web3, txHex) { let id = ""; await web3.eth.sendSignedTransaction(txHex).on("transactionHash", (txHash) => { id = txHash; }); return id; } async function _waitForCTxConfirmation(evmapi, txId) { let status = "Unkown"; const start = Date.now(); while (Date.now() - start < TX_WAIT_MS) { status = (await evmapi.getAtomicTxStatus(txId)).status; await utils.sleep(TX_CHECK_MS); // wait regardless of status for added safety if (status === "Accepted" || status === "Rejected") { break; } } const confirmed = status === "Accepted"; return [status, confirmed]; } async function _waitForPTxConfirmation(pvmapi, txId) { let status = "Unkown"; const start = Date.now(); while (Date.now() - start < TX_WAIT_MS) { status = (await pvmapi.getTxStatus({ txID: txId })).status; await utils.sleep(TX_CHECK_MS); // wait regardless of status for added safety if (status === "Committed" || status === "Rejected") { break; } } const confirmed = status === "Committed"; return [status, confirmed]; } async function _waitForEvmTxConfirmation(web3, txId) { let status = "Unkown"; const start = Date.now(); while (Date.now() - start < TX_WAIT_MS) { let receipt; try { receipt = await web3.eth.getTransactionReceipt(txId); } catch (e) { console.log("Error getting transaction receipt", e); } if (receipt) { status = receipt.status === BigInt(1) ? "Confirmed" : "Failed"; break; } await utils.sleep(TX_CHECK_MS); } const confirmed = status === "Confirmed"; return [status, confirmed]; } function _getNetworkFromChainId(chainId) { let network = ""; const chainIdHex = utils.toHex(chainId.toString(16)); for (const entry of Object.entries(settings.CHAIN_ID)) { if (entry[1] === chainIdHex) { network = entry[0]; break; } } if (!network) { throw new Error("Unsupported network"); } return network; } async function getStakeTransaction(network, txId) { const pvmapi = new flarejs_1.pvm.PVMApi(settings.URL[network]); const tx = await pvmapi.getTx({ txID: txId }); switch (tx.unsignedTx._type) { case flarejs_1.TypeSymbols.AddDelegatorTx: return tx.unsignedTx; case flarejs_1.TypeSymbols.AddValidatorTx: return tx.unsignedTx; case flarejs_1.TypeSymbols.AddPermissionlessDelegatorTx: return tx.unsignedTx; case flarejs_1.TypeSymbols.AddPermissionlessValidatorTx: return tx.unsignedTx; default: throw new Error("Not a stake transaction"); } } function _transformSignature(sig) { const recovery = Buffer.alloc(1); recovery.writeUInt8(sig.recoveryParam, 0); const r = Buffer.from(sig.r.toArray("be", 32)); //we have to skip native Buffer class, so this is the way const s = Buffer.from(sig.s.toArray("be", 32)); //we have to skip native Buffer class, so this is the way return Buffer.concat([r, s, recovery], 65); } function signTxDbg(tx, signingData) { for (const data of signingData) { const coordinates = tx.getSigIndicesForPubKey(data.publicKey); if (coordinates) { coordinates.forEach(([index, subIndex]) => { tx.addSignatureAt(data.signature, index, subIndex); }); } } } //# sourceMappingURL=txs.js.map