You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

submit.js 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. "use strict";
  2. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  3. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  4. return new (P || (P = Promise))(function (resolve, reject) {
  5. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  6. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  7. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  8. step((generator = generator.apply(thisArg, _arguments || [])).next());
  9. });
  10. };
  11. Object.defineProperty(exports, "__esModule", { value: true });
  12. exports.submitAndWait = exports.submit = void 0;
  13. const ripple_binary_codec_1 = require("ripple-binary-codec");
  14. const errors_1 = require("../errors");
  15. const utils_1 = require("../utils");
  16. const LEDGER_CLOSE_TIME = 1000;
  17. function sleep(ms) {
  18. return __awaiter(this, void 0, void 0, function* () {
  19. return new Promise((resolve) => {
  20. setTimeout(resolve, ms);
  21. });
  22. });
  23. }
  24. function submit(transaction, opts) {
  25. return __awaiter(this, void 0, void 0, function* () {
  26. const signedTx = yield getSignedTx(this, transaction, opts);
  27. return submitRequest(this, signedTx, opts === null || opts === void 0 ? void 0 : opts.failHard);
  28. });
  29. }
  30. exports.submit = submit;
  31. function submitAndWait(transaction, opts) {
  32. return __awaiter(this, void 0, void 0, function* () {
  33. const signedTx = yield getSignedTx(this, transaction, opts);
  34. const lastLedger = getLastLedgerSequence(signedTx);
  35. if (lastLedger == null) {
  36. throw new errors_1.ValidationError('Transaction must contain a LastLedgerSequence value for reliable submission.');
  37. }
  38. const response = yield submitRequest(this, signedTx, opts === null || opts === void 0 ? void 0 : opts.failHard);
  39. const txHash = utils_1.hashes.hashSignedTx(signedTx);
  40. return waitForFinalTransactionOutcome(this, txHash, lastLedger, response.result.engine_result);
  41. });
  42. }
  43. exports.submitAndWait = submitAndWait;
  44. function submitRequest(client, signedTransaction, failHard = false) {
  45. return __awaiter(this, void 0, void 0, function* () {
  46. if (!isSigned(signedTransaction)) {
  47. throw new errors_1.ValidationError('Transaction must be signed');
  48. }
  49. const signedTxEncoded = typeof signedTransaction === 'string'
  50. ? signedTransaction
  51. : (0, ripple_binary_codec_1.encode)(signedTransaction);
  52. const request = {
  53. command: 'submit',
  54. tx_blob: signedTxEncoded,
  55. fail_hard: isAccountDelete(signedTransaction) || failHard,
  56. };
  57. return client.request(request);
  58. });
  59. }
  60. function waitForFinalTransactionOutcome(client, txHash, lastLedger, submissionResult) {
  61. return __awaiter(this, void 0, void 0, function* () {
  62. yield sleep(LEDGER_CLOSE_TIME);
  63. const latestLedger = yield client.getLedgerIndex();
  64. if (lastLedger < latestLedger) {
  65. throw new errors_1.XrplError(`The latest ledger sequence ${latestLedger} is greater than the transaction's LastLedgerSequence (${lastLedger}).\n` +
  66. `Preliminary result: ${submissionResult}`);
  67. }
  68. const txResponse = yield client
  69. .request({
  70. command: 'tx',
  71. transaction: txHash,
  72. })
  73. .catch((error) => __awaiter(this, void 0, void 0, function* () {
  74. var _a;
  75. const message = (_a = error === null || error === void 0 ? void 0 : error.data) === null || _a === void 0 ? void 0 : _a.error;
  76. if (message === 'txnNotFound') {
  77. return waitForFinalTransactionOutcome(client, txHash, lastLedger, submissionResult);
  78. }
  79. throw new Error(`${message} \n Preliminary result: ${submissionResult}.\nFull error details: ${String(error)}`);
  80. }));
  81. if (txResponse.result.validated) {
  82. return txResponse;
  83. }
  84. return waitForFinalTransactionOutcome(client, txHash, lastLedger, submissionResult);
  85. });
  86. }
  87. function isSigned(transaction) {
  88. const tx = typeof transaction === 'string' ? (0, ripple_binary_codec_1.decode)(transaction) : transaction;
  89. return (typeof tx !== 'string' &&
  90. (tx.SigningPubKey != null || tx.TxnSignature != null));
  91. }
  92. function getSignedTx(client, transaction, { autofill = true, wallet, } = {}) {
  93. return __awaiter(this, void 0, void 0, function* () {
  94. if (isSigned(transaction)) {
  95. return transaction;
  96. }
  97. if (!wallet) {
  98. throw new errors_1.ValidationError('Wallet must be provided when submitting an unsigned transaction');
  99. }
  100. let tx = typeof transaction === 'string'
  101. ?
  102. (0, ripple_binary_codec_1.decode)(transaction)
  103. : transaction;
  104. if (autofill) {
  105. tx = yield client.autofill(tx);
  106. }
  107. return wallet.sign(tx).tx_blob;
  108. });
  109. }
  110. function getLastLedgerSequence(transaction) {
  111. const tx = typeof transaction === 'string' ? (0, ripple_binary_codec_1.decode)(transaction) : transaction;
  112. return tx.LastLedgerSequence;
  113. }
  114. function isAccountDelete(transaction) {
  115. const tx = typeof transaction === 'string' ? (0, ripple_binary_codec_1.decode)(transaction) : transaction;
  116. return tx.TransactionType === 'AccountDelete';
  117. }
  118. //# sourceMappingURL=submit.js.map