UNPKG

@renproject/ren

Version:

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

209 lines 9.18 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { crossChainParamsType, } from "@renproject/provider"; import { renExplorerUrls } from "@renproject/provider/rpcUrls"; import { ChainTransactionStatus, ErrorWithCode, eventEmitter, generateTransactionHash, RenJSError, TxStatus, utils, } from "@renproject/utils"; export 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 = () => __awaiter(this, void 0, void 0, function* () { const tx = yield this.provider.queryTx(this.tx.hash, 1); if (tx.txStatus === TxStatus.TxStatusDone || tx.txStatus === TxStatus.TxStatusReverted) { return this._handleDoneTransaction(tx); } else { return this.updateProgress({ response: tx, status: ChainTransactionStatus.Confirming, }); } }); this.submit = () => { const promiEvent = utils.newPromiEvent(this.eventEmitter); (() => __awaiter(this, void 0, void 0, function* () { // Alternate trying to submit and trying to query. const retries = 4; let errorInner; for (let i = 0; i < retries; i++) { try { yield this.provider.submitTx(this.tx, 1); break; } catch (error) { errorInner = error; } try { yield this.provider.queryTx(this.tx.hash, 1); break; } catch (error) { // Ignore error. } if (i === retries - 1) { throw errorInner; } } if (this.progress.status === ChainTransactionStatus.Ready) { return this.updateProgress({ status: 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.newPromiEvent(this.eventEmitter); (() => __awaiter(this, void 0, void 0, function* () { let tx; let existingStatus = undefined; while (true) { try { tx = yield this.provider.queryTx(this.tx.hash, 1); if (tx.txStatus === TxStatus.TxStatusDone || tx.txStatus === TxStatus.TxStatusReverted) { break; } if (tx.txStatus !== existingStatus || !this.progress.response) { try { existingStatus = tx.txStatus; this.updateProgress({ response: tx, status: 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 } } yield utils.sleep(this.config && this.config.networkDelay ? this.config.networkDelay : 15 * utils.sleep.SECONDS); } return yield 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 = (tx) => __awaiter(this, void 0, void 0, function* () { if (tx.tx.out && tx.tx.out.revert && tx.tx.out.revert.length > 0) { const revertMessage = tx.tx.out.revert; this.updateProgress({ status: ChainTransactionStatus.Reverted, revertReason: revertMessage, confirmations: 1, }); throw new ErrorWithCode(`RenVM transaction reverted: ${revertMessage}`, RenJSError.RENVM_TRANSACTION_REVERTED); } if (this.signatureCallback) { yield this.signatureCallback(tx); } return this.updateProgress({ response: tx, status: ChainTransactionStatus.Done, confirmations: 1, }); }); this.provider = provider; this.eventEmitter = eventEmitter(); this.signatureCallback = signatureCallback; this.config = config; this.providerNetwork = providerNetwork; const version = tx.version || "1"; const expectedHash = utils.toURLBase64(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 && renExplorerUrls[this.providerNetwork]; const explorerLink = explorerLinkBase ? `${explorerLinkBase}/#/tx/${this.tx.hash}` : ``; this.progress = { chain: this.chain, status: ChainTransactionStatus.Ready, target: 1, transaction: { chain: this.chain, txid: this.tx.hash, txHash: this.tx.hash, txindex: "0", explorerLink, }, }; } } export class RenVMCrossChainTxSubmitter extends RenVMTxSubmitter { constructor(provider, selector, params, signatureCallback, config = {}, providerNetwork) { super(provider, { selector, in: { t: crossChainParamsType, v: { txid: utils.toURLBase64(params.txid), txindex: params.txindex.toFixed(), amount: params.amount.toFixed(), payload: utils.toURLBase64(params.payload), phash: utils.toURLBase64(params.phash), to: params.to, nonce: utils.toURLBase64(params.nonce), nhash: utils.toURLBase64(params.nhash), gpubkey: utils.toURLBase64(params.gpubkey), ghash: utils.toURLBase64(params.ghash), }, }, }, signatureCallback, config, providerNetwork); } } //# sourceMappingURL=renVMTxSubmitter.js.map