UNPKG

@drift-labs/sdk

Version:
104 lines (103 loc) 5.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getTransactionError = exports.getTransactionErrorFromTxSig = exports.throwTransactionError = void 0; const web3_js_1 = require("@solana/web3.js"); const config_1 = require("../config"); /** * The new getTransaction method expects a Finality type instead of a Commitment type. The only options for Finality are 'confirmed' and 'finalized'. * @param commitment * @returns */ const commitmentToFinality = (commitment) => { switch (commitment) { case 'confirmed': return 'confirmed'; case 'finalized': return 'finalized'; default: throw new Error(`Invalid commitment when reporting transaction error. The commitment must be 'confirmed' or 'finalized' but was given '${commitment}'. If you're using this commitment for a specific reason, you may need to roll your own logic here.`); } }; const getTransactionResult = async (txSig, connection, commitment) => { const finality = commitmentToFinality(commitment || connection.commitment || config_1.DEFAULT_CONFIRMATION_OPTS.commitment); return await connection.getTransaction(txSig, { maxSupportedTransactionVersion: 0, commitment: finality, }); }; const getTransactionResultWithRetry = async (txSig, connection, commitment) => { const start = Date.now(); const retryTimeout = 3000; // Timeout after 3 seconds const retryInterval = 800; // Retry with 800ms interval const retryCount = 3; // Retry 3 times let currentCount = 0; let transactionResult = await getTransactionResult(txSig, connection, commitment); // Retry 3 times or until timeout as long as we don't have a result yet while (!transactionResult && Date.now() - start < retryTimeout && currentCount < retryCount) { // Sleep for 1 second :: Do this first so that we don't run the first loop immediately after the initial fetch above await new Promise((resolve) => setTimeout(resolve, retryInterval)); transactionResult = await getTransactionResult(txSig, connection, commitment); currentCount++; } return transactionResult; }; /** * THROWS if there is an error * * Should only be used for a txSig that is confirmed has an error. There is a race-condition where sometimes the transaction is not instantly available to fetch after the confirmation has already failed with an error, so this method has retry logic which we don't want to do wastefully. This method will throw a generic error if it can't get the transaction result after a retry period. * @param txSig * @param connection * @returns */ const throwTransactionError = async (txSig, connection, commitment) => { const err = await (0, exports.getTransactionErrorFromTxSig)(txSig, connection, commitment); if (err) { throw err; } return; }; exports.throwTransactionError = throwTransactionError; /** * RETURNS an error if there is one * * Should only be used for a txSig that is confirmed has an error. There is a race-condition where sometimes the transaction is not instantly available to fetch after the confirmation has already failed with an error, so this method has retry logic which we don't want to do wastefully. This method will throw a generic error if it can't get the transaction result after a retry period. * @param txSig * @param connection * @returns */ const getTransactionErrorFromTxSig = async (txSig, connection, commitment) => { var _a; const transactionResult = await getTransactionResultWithRetry(txSig, connection, commitment); if (!transactionResult) { // Throw a generic error because we couldn't get the transaction result for the given txSig return new web3_js_1.SendTransactionError({ action: 'send', signature: txSig, transactionMessage: `Transaction Failed`, }); } if (!((_a = transactionResult === null || transactionResult === void 0 ? void 0 : transactionResult.meta) === null || _a === void 0 ? void 0 : _a.err)) { // Assume that the transaction was successful and we are here erroneously because we have a result with no error return; } return (0, exports.getTransactionError)(transactionResult); }; exports.getTransactionErrorFromTxSig = getTransactionErrorFromTxSig; const getTransactionError = (transactionResult) => { var _a, _b, _c, _d, _e, _f; if (!((_a = transactionResult === null || transactionResult === void 0 ? void 0 : transactionResult.meta) === null || _a === void 0 ? void 0 : _a.err)) { return; } const logs = (_c = (_b = transactionResult === null || transactionResult === void 0 ? void 0 : transactionResult.meta) === null || _b === void 0 ? void 0 : _b.logMessages) !== null && _c !== void 0 ? _c : ['No logs']; const lastLog = logs[logs.length - 1]; const friendlyMessage = (_d = lastLog === null || lastLog === void 0 ? void 0 : lastLog.match(/(failed:) (.+)/)) === null || _d === void 0 ? void 0 : _d[2]; return new web3_js_1.SendTransactionError({ action: 'send', signature: (_f = (_e = transactionResult === null || transactionResult === void 0 ? void 0 : transactionResult.transaction) === null || _e === void 0 ? void 0 : _e.signatures) === null || _f === void 0 ? void 0 : _f[0], transactionMessage: `Transaction Failed${friendlyMessage ? `: ${friendlyMessage}` : ''}`, logs, }); }; exports.getTransactionError = getTransactionError;