UNPKG

@renproject/ren

Version:

Official Ren JavaScript SDK for bridging crypto assets cross-chain.

205 lines 8.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RenVMCrossChainTxSubmitter = exports.RenVMTxSubmitter = void 0; const provider_1 = require("@renproject/provider"); const rpcUrls_1 = require("@renproject/provider/rpcUrls"); const utils_1 = require("@renproject/utils"); class RenVMTxSubmitter { constructor(provider, tx, signatureCallback, config = {}, providerNetwork) { this.chain = "RenVM"; this.updateProgress = (progress) => { const currentProgress = this.progress; this.progress = Object.assign(Object.assign({}, currentProgress), progress); this.eventEmitter.emit("progress", this.progress); return this.progress; }; this.export = () => { return this.tx; }; this.query = async () => { const tx = await this.provider.queryTx(this.tx.hash, 1); if (tx.txStatus === utils_1.TxStatus.TxStatusDone || tx.txStatus === utils_1.TxStatus.TxStatusReverted) { return this._handleDoneTransaction(tx); } else { return this.updateProgress({ response: tx, status: utils_1.ChainTransactionStatus.Confirming, }); } }; this.submit = () => { const promiEvent = utils_1.utils.newPromiEvent(this.eventEmitter); (async () => { // Alternate trying to submit and trying to query. const retries = 4; let errorInner; for (let i = 0; i < retries; i++) { try { await this.provider.submitTx(this.tx, 1); break; } catch (error) { errorInner = error; } try { await this.provider.queryTx(this.tx.hash, 1); break; } catch (error) { // Ignore error. } if (i === retries - 1) { throw errorInner; } } if (this.progress.status === utils_1.ChainTransactionStatus.Ready) { return this.updateProgress({ status: utils_1.ChainTransactionStatus.Confirming, confirmations: 0, }); } else { return this.progress; } // const response = { // version: parseInt(tx.version), // hash: tx.hash, // selector: tx.selector, // in: unmarshalTypedPackValue(tx.in), // }; })() .then(promiEvent.resolve) .catch(promiEvent.reject); return promiEvent; }; this.setTransaction = () => { return this.progress; }; this.wait = () => { const promiEvent = utils_1.utils.newPromiEvent(this.eventEmitter); (async () => { let tx; let existingStatus = undefined; while (true) { try { tx = await this.provider.queryTx(this.tx.hash, 1); if (tx.txStatus === utils_1.TxStatus.TxStatusDone || tx.txStatus === utils_1.TxStatus.TxStatusReverted) { break; } if (tx.txStatus !== existingStatus || !this.progress.response) { try { existingStatus = tx.txStatus; this.updateProgress({ response: tx, status: utils_1.ChainTransactionStatus.Confirming, confirmations: 0, }); } catch (error) { // Ignore non-critical error. } } } catch (error) { if (error instanceof Error && /(not found)|(not available)/.exec(String((error || {}).message))) { // ignore } else { console.error(error); // TODO: throw unexpected errors } } await utils_1.utils.sleep(this.config && this.config.networkDelay ? this.config.networkDelay : 15 * utils_1.utils.sleep.SECONDS); } return await this._handleDoneTransaction(tx); })() .then(promiEvent.resolve) .catch(promiEvent.reject); return promiEvent; }; /** * Process a complete RenVM transaction, handling checking for a revert * reason and calling the signatureCallback. */ this._handleDoneTransaction = async (tx) => { if (tx.tx.out && tx.tx.out.revert && tx.tx.out.revert.length > 0) { const revertMessage = tx.tx.out.revert; this.updateProgress({ status: utils_1.ChainTransactionStatus.Reverted, revertReason: revertMessage, confirmations: 1, }); throw new utils_1.ErrorWithCode(`RenVM transaction reverted: ${revertMessage}`, utils_1.RenJSError.RENVM_TRANSACTION_REVERTED); } if (this.signatureCallback) { await this.signatureCallback(tx); } return this.updateProgress({ response: tx, status: utils_1.ChainTransactionStatus.Done, confirmations: 1, }); }; this.provider = provider; this.eventEmitter = (0, utils_1.eventEmitter)(); this.signatureCallback = signatureCallback; this.config = config; this.providerNetwork = providerNetwork; const version = tx.version || "1"; const expectedHash = utils_1.utils.toURLBase64((0, utils_1.generateTransactionHash)(version, tx.selector, tx.in)); if (tx.hash && tx.hash !== expectedHash) { throw new Error(`Invalid hash (expected '${expectedHash}', got '${tx.hash}').`); } const hash = tx.hash || expectedHash; this.tx = Object.assign(Object.assign({}, tx), { version, hash }); const explorerLinkBase = this.providerNetwork && rpcUrls_1.renExplorerUrls[this.providerNetwork]; const explorerLink = explorerLinkBase ? `${explorerLinkBase}/#/tx/${this.tx.hash}` : ``; this.progress = { chain: this.chain, status: utils_1.ChainTransactionStatus.Ready, target: 1, transaction: { chain: this.chain, txid: this.tx.hash, txHash: this.tx.hash, txindex: "0", explorerLink, }, }; } } exports.RenVMTxSubmitter = RenVMTxSubmitter; class RenVMCrossChainTxSubmitter extends RenVMTxSubmitter { constructor(provider, selector, params, signatureCallback, config = {}, providerNetwork) { super(provider, { selector, in: { t: provider_1.crossChainParamsType, v: { txid: utils_1.utils.toURLBase64(params.txid), txindex: params.txindex.toFixed(), amount: params.amount.toFixed(), payload: utils_1.utils.toURLBase64(params.payload), phash: utils_1.utils.toURLBase64(params.phash), to: params.to, nonce: utils_1.utils.toURLBase64(params.nonce), nhash: utils_1.utils.toURLBase64(params.nhash), gpubkey: utils_1.utils.toURLBase64(params.gpubkey), ghash: utils_1.utils.toURLBase64(params.ghash), }, }, }, signatureCallback, config, providerNetwork); } } exports.RenVMCrossChainTxSubmitter = RenVMCrossChainTxSubmitter; //# sourceMappingURL=renVMTxSubmitter.js.map