UNPKG

@byzantine/vault-sdk

Version:

Byzantine Vault SDK for creating and managing vaults on Ethereum for restaking strategies

116 lines (115 loc) 4.29 kB
"use strict"; /** * Contract Error Handler Utility * * Helper functions to standardize contract error handling across the SDK */ Object.defineProperty(exports, "__esModule", { value: true }); exports.executeContractMethod = executeContractMethod; exports.callContractMethod = callContractMethod; exports.formatContractError = formatContractError; const errorCodeMapping_1 = require("./errorCodeMapping"); /** * Execute a contract method with proper error handling * Uses staticCall to get meaningful errors before executing transaction * * @param contract - Ethers contract instance * @param method - Method name to call * @param args - Arguments to pass to the method * @returns Promise resolving to transaction response */ async function executeContractMethod(contract, method, ...args) { try { // Separate transaction options from method arguments // The last argument might be transaction options if it has transaction properties let methodArgs = args; let txOptions = {}; // Check if the last argument looks like transaction options if (args.length > 0) { const lastArg = args[args.length - 1]; if (lastArg && typeof lastArg === "object" && (lastArg.gasLimit || lastArg.gasPrice || lastArg.value || lastArg.nonce || lastArg.type || lastArg.maxFeePerGas || lastArg.maxPriorityFeePerGas)) { txOptions = lastArg; methodArgs = args.slice(0, -1); } } // First try with staticCall to get a meaningful error (without tx options) await contract[method].staticCall(...methodArgs); // If staticCall succeeds, execute the real transaction with options return await contract[method](...methodArgs, txOptions); } catch (error) { throw formatContractError(method, error); } } /** * Execute a read-only contract method with proper error handling * * @param contract - Ethers contract instance * @param method - Method name to call * @param args - Arguments to pass to the method * @returns Promise resolving to the method's return value */ async function callContractMethod(contract, method, ...args) { try { return await contract[method](...args); } catch (error) { throw formatContractError(method, error); } } /** * Format a contract error into a more meaningful message * * @param method - Contract method name * @param error - Error object * @returns Error with improved message */ function formatContractError(method, error) { // console.log("Going to format contract error", method, error); // console.log("Error revert", error.revert); // console.log("Error reason", error.reason); // console.log("Error message", error.message); // console.log("Error stack", error.stack); // console.log("Error code", error.code); // console.log("Error data", error.data); // console.log("Error error", error.error); // Extract error reason from revert data if available if (error.revert) { const errorName = error.revert.name; const errorArgs = error.revert.args; let argsStr = ""; try { // Format args as string, handling different types argsStr = errorArgs .map((arg) => { if (typeof arg === "bigint") { return arg.toString(); } return arg; }) .join(", "); } catch (e) { argsStr = "unparsable args"; } return new Error(`Contract error: ${errorName}(${argsStr})`); } // If we got a standard reason if (error.reason) { return new Error(`Contract error: ${error.reason}`); } // Check if error has data property and it's in our error mapping if (error.data && errorCodeMapping_1.ErrorCodeMapping[error.data]) { return new Error(`Contract error: ${errorCodeMapping_1.ErrorCodeMapping[error.data]}`); } // For any other error return new Error(`Failed to execute ${method}: ${error.message || "Unknown error"}`); }