@fireblocks/fireblocks-web3-provider
Version:
EIP-1193 Compatible Ethereum provider for Fireblocks
563 lines • 29.7 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FireblocksWeb3Provider = void 0;
const util_1 = __importDefault(require("util"));
const fireblocks_sdk_1 = require("fireblocks-sdk");
const utils_1 = require("./utils");
const fs_1 = require("fs");
const types_1 = require("./types");
const fireblocks_sdk_2 = require("fireblocks-sdk");
const units_1 = require("@ethersproject/units");
const constants_1 = require("./constants");
const ethers = __importStar(require("ethers"));
const factories_1 = require("./contracts/factories");
const https_proxy_agent_1 = require("https-proxy-agent");
const jsonRpcUtils_1 = require("./jsonRpcUtils");
const package_json_1 = require("../package.json");
const debug_1 = __importDefault(require("debug"));
const HttpProvider = require("web3-providers-http");
const logTransactionStatusChange = (0, debug_1.default)(constants_1.DEBUG_NAMESPACE_TX_STATUS_CHANGES);
const logEnhancedErrorHandling = (0, debug_1.default)(constants_1.DEBUG_NAMESPACE_ENHANCED_ERROR_HANDLING);
const logRequestsAndResponses = (0, debug_1.default)(constants_1.DEBUG_NAMESPACE_REQUESTS_AND_RESPONSES);
class FireblocksWeb3Provider extends HttpProvider {
constructor(config) {
var _a, _b, _c;
if (config.assetId && !config.rpcUrl) {
throw Error(`If you supply an assetId, you must also supply an rpcUrl`);
}
const asset = config.assetId ? {
assetId: config.assetId,
rpcUrl: config.rpcUrl,
} : (0, utils_1.getAssetByChain)(config.chainId);
if (!asset && !config.rpcUrl) {
throw Error(`Unsupported chain id: ${config.chainId}.\nSupported chains ids: ${Object.keys(types_1.ChainId).join(', ')}\nIf you're using a private blockchain, you can specify the blockchain's Fireblocks Asset ID via the "assetId" config param.`);
}
const debugNamespaces = [process.env.DEBUG || ''];
if (config.logTransactionStatusChanges) {
debugNamespaces.push(constants_1.DEBUG_NAMESPACE_TX_STATUS_CHANGES);
}
if (config.enhancedErrorHandling || config.enhancedErrorHandling == undefined) {
debugNamespaces.push(constants_1.DEBUG_NAMESPACE_ENHANCED_ERROR_HANDLING);
}
if (config.logRequestsAndResponses) {
debugNamespaces.push(constants_1.DEBUG_NAMESPACE_REQUESTS_AND_RESPONSES);
}
debug_1.default.enable(debugNamespaces.join(','));
const headers = [];
if (config.rpcUrl && config.rpcUrl.includes("@") && config.rpcUrl.includes(":")) {
const [creds, url] = config.rpcUrl.replace("https://", "").replace("http://", "").split("@");
config.rpcUrl = `${config.rpcUrl.startsWith("https") ? "https://" : "http://"}${url}`;
headers.push({
name: "Authorization",
value: Buffer.from(creds).toString('base64')
});
}
super(config.rpcUrl || asset.rpcUrl);
this.headers = [];
this.accounts = {};
this.gaslessGasTankVaultAddress = '';
this.whitelisted = {};
this.requestCounter = 0;
this.config = config;
this.headers = headers;
if (config.proxyPath) {
const proxyAgent = new https_proxy_agent_1.HttpsProxyAgent(config.proxyPath);
this.agent = {
http: proxyAgent,
https: proxyAgent
};
}
this.fireblocksApiClient = new fireblocks_sdk_1.FireblocksSDK(this.parsePrivateKey(config.privateKey), config.apiKey, config.apiBaseUrl || types_1.ApiBaseUrl.Production, undefined, {
userAgent: this.getUserAgent(),
httpsAgent: (_a = this === null || this === void 0 ? void 0 : this.agent) === null || _a === void 0 ? void 0 : _a.https
});
this.feeLevel = config.fallbackFeeLevel || fireblocks_sdk_1.FeeLevel.MEDIUM;
this.note = (_b = config.note) !== null && _b !== void 0 ? _b : 'Created by Fireblocks Web3 Provider';
this.externalTxId = config.externalTxId;
this.gaslessGasTankVaultId = config.gaslessGasTankVaultId;
this.vaultAccountIds = this.parseVaultAccountIds(config.vaultAccountIds);
this.pollingInterval = config.pollingInterval || 1000;
this.oneTimeAddressesEnabled = (_c = config.oneTimeAddressesEnabled) !== null && _c !== void 0 ? _c : true;
this.chainId = config.chainId;
this.assetId = asset === null || asset === void 0 ? void 0 : asset.assetId;
this.assetAndChainIdPopulatedPromise = (0, utils_1.promiseToFunction)(async () => { if (!this.chainId)
return await this.populateAssetAndChainId(); });
this.accountsPopulatedPromise = (0, utils_1.promiseToFunction)(async () => { return await this.populateAccounts(); });
this.whitelistedPopulatedPromise = (0, utils_1.promiseToFunction)(async () => { if (!this.oneTimeAddressesEnabled)
return await this.populateWhitelisted(); });
this.gaslessGasTankAddressPopulatedPromise = (0, utils_1.promiseToFunction)(async () => { if (this.gaslessGasTankVaultId)
return await this.populateGaslessGasTankAddress(); });
}
parsePrivateKey(privateKey) {
if (!privateKey) {
throw Error(`privateKey is required in the fireblocks-web3-provider config`);
}
if (!privateKey.trim().startsWith('-----BEGIN')) {
return (0, fs_1.readFileSync)(privateKey, 'utf8');
}
else {
return privateKey;
}
}
async populateGaslessGasTankAddress() {
await this.assetAndChainIdPopulatedPromise();
const depositAddresses = await this.fireblocksApiClient.getPaginatedAddresses(this.gaslessGasTankVaultId.toString(), this.assetId);
if (depositAddresses.addresses.length === 0) {
throw Error(`Gasless gas tank vault not found (vault id: ${this.gaslessGasTankVaultId})`);
}
this.gaslessGasTankVaultAddress = depositAddresses.addresses[0].address;
this.accounts[this.gaslessGasTankVaultId] = this.gaslessGasTankVaultAddress;
}
parseVaultAccountIds(vaultAccountIds) {
if (typeof vaultAccountIds == 'number') {
return [vaultAccountIds];
}
else if (typeof vaultAccountIds == 'string') {
return vaultAccountIds.split(',').map(x => parseInt(x));
}
else if (Array.isArray(vaultAccountIds)) {
return vaultAccountIds.map(x => parseInt(x.toString()));
}
else {
return vaultAccountIds;
}
}
getUserAgent() {
let userAgent = `fireblocks-web3-provider/${package_json_1.version}`;
if (this.config.userAgent) {
userAgent = `${this.config.userAgent} ${userAgent}`;
}
return userAgent;
}
async getVaultAccounts() {
await this.assetAndChainIdPopulatedPromise();
return (await this.fireblocksApiClient.getVaultAccountsWithPageInfo({
assetId: this.assetId,
orderBy: "ASC",
limit: 20,
})).accounts
.filter((x) => x.assets.some((a) => a.id == this.assetId))
.map((x) => parseInt(x.id));
}
// Called by the constructor in case rpcUrl is provided, and chainId not
async populateAssetAndChainId() {
const chainId = (await util_1.default.promisify(super.send).bind(this)((0, jsonRpcUtils_1.formatJsonRpcRequest)('eth_chainId', []))).result;
this.chainId = Number(chainId);
if (!this.assetId) {
const asset = (0, utils_1.getAssetByChain)(Number(chainId));
if (!asset) {
throw this.createError({ message: `Unsupported chain id: ${chainId}.\nSupported chains ids: ${Object.keys(types_1.ChainId).join(', ')}\nIf you're using a private blockchain, you can specify the blockchain's Fireblocks Asset ID via the "assetId" config param.` });
}
this.assetId = asset.assetId;
}
}
async populateAccounts() {
if (Object.keys(this.accounts).length > 0) {
throw this.createError({ message: "Accounts already populated" });
}
if (!this.vaultAccountIds) {
this.vaultAccountIds = await this.getVaultAccounts();
}
await this.assetAndChainIdPopulatedPromise();
for (const vaultAccountId of this.vaultAccountIds) {
let depositAddresses;
try {
depositAddresses = await this.fireblocksApiClient.getPaginatedAddresses(vaultAccountId.toString(), this.assetId);
}
catch (error) {
throw this.createFireblocksError(error);
}
if (this.config.vaultAccountIds && depositAddresses.addresses.length == 0) {
throw this.createError({ message: `No ${this.assetId} asset wallet found for vault account with id ${vaultAccountId}` });
}
if (depositAddresses.addresses.length) {
this.accounts[vaultAccountId] = depositAddresses.addresses[0].address;
}
}
}
createFireblocksError(e) {
var _a, _b, _c, _d, _e, _f, _g;
const code = ((_a = e === null || e === void 0 ? void 0 : e.response) === null || _a === void 0 ? void 0 : _a.status) == 401 ? 4100 : undefined;
let message = ((_c = (_b = e === null || e === void 0 ? void 0 : e.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.message) || (e === null || e === void 0 ? void 0 : e.message) || 'Unknown error';
message = `Fireblocks SDK Error: ${message}`;
message = ((_e = (_d = e === null || e === void 0 ? void 0 : e.response) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.code) ? `${message} (Error code: ${e.response.data.code})` : message;
message = ((_g = (_f = e === null || e === void 0 ? void 0 : e.response) === null || _f === void 0 ? void 0 : _f.headers) === null || _g === void 0 ? void 0 : _g['x-request-id']) ? `${message} (Request ID: ${e.response.headers['x-request-id']})` : message;
return this.createError({ message, code });
}
async getWhitelistedWallets(walletsPromise, type, assetId) {
return (await walletsPromise).map((x) => {
var _a;
return ({
type,
id: x.id,
name: x.name,
address: (_a = x.assets.find((a) => a.id == assetId)) === null || _a === void 0 ? void 0 : _a.address,
});
}).filter((x) => x.address);
}
async populateWhitelisted() {
if (Object.keys(this.whitelisted).length > 0) {
throw this.createError({ message: "Whitelisted already populated" });
}
await this.assetAndChainIdPopulatedPromise();
const [externalWallets, internalWallets, contractWallets] = await Promise.all([
this.getWhitelistedWallets(this.fireblocksApiClient.getExternalWallets(), fireblocks_sdk_2.PeerType.EXTERNAL_WALLET, this.assetId),
this.getWhitelistedWallets(this.fireblocksApiClient.getInternalWallets(), fireblocks_sdk_2.PeerType.INTERNAL_WALLET, this.assetId),
this.getWhitelistedWallets(this.fireblocksApiClient.getContractWallets(), fireblocks_sdk_2.PeerType.EXTERNAL_WALLET, this.assetId),
]);
await this.accountsPopulatedPromise();
const vaultWallets = Object.entries(this.accounts).map(([id, address]) => ({
type: fireblocks_sdk_2.PeerType.VAULT_ACCOUNT,
id,
address,
}));
const whitelistedList = [...externalWallets, ...internalWallets, ...contractWallets, ...vaultWallets];
this.whitelisted = whitelistedList.reduce((wl, x) => {
wl[x.address.toLowerCase()] = { type: x.type, id: x.id, name: x.name };
return wl;
}, {});
}
async initialized() {
await Promise.all([
this.assetAndChainIdPopulatedPromise(),
this.accountsPopulatedPromise(),
this.whitelistedPopulatedPromise(),
this.gaslessGasTankAddressPopulatedPromise(),
]);
}
send(payload, callback) {
(async () => {
var _a, _b, _c, _d, _e, _f;
let result;
let error = null;
const requestNumber = ++this.requestCounter;
try {
logRequestsAndResponses(`Request #${requestNumber}: method=${payload.method} params=${JSON.stringify(payload.params, undefined, 4)}`);
if (((_b = (_a = payload === null || payload === void 0 ? void 0 : payload.params) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.input) && !((_d = (_c = payload === null || payload === void 0 ? void 0 : payload.params) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.data)) {
payload.params[0].data = (_e = payload.params) === null || _e === void 0 ? void 0 : _e[0].input;
(_f = payload.params) === null || _f === void 0 ? true : delete _f[0].input;
}
switch (payload.method) {
case "eth_requestAccounts":
case "eth_accounts":
await this.accountsPopulatedPromise();
await this.gaslessGasTankAddressPopulatedPromise();
result = Object.values(this.accounts)
.filter((addr) => addr.toLowerCase() != this.gaslessGasTankVaultAddress.toLowerCase());
break;
case "eth_sendTransaction":
await this.gaslessGasTankAddressPopulatedPromise();
try {
if (this.gaslessGasTankVaultId != undefined && payload.params[0].from.toLowerCase() != this.gaslessGasTankVaultAddress.toLowerCase()) {
result = this.createGaslessTransaction(payload.params[0]);
}
else {
result = await this.createContractCall(payload.params[0]);
}
}
catch (error) {
logEnhancedErrorHandling(`Simulate the failed transaction on Tenderly: ${this.createTenderlySimulationLink(payload.params[0])}`);
throw error;
}
break;
case "personal_sign":
case "eth_sign":
result = await this.createPersonalSign(payload.params[1], payload.params[0], fireblocks_sdk_2.TransactionOperation.TYPED_MESSAGE, types_1.RawMessageType.ETH_MESSAGE);
break;
case "eth_signTypedData":
case "eth_signTypedData_v1":
case "eth_signTypedData_v3":
case "eth_signTypedData_v4":
result = await this.createPersonalSign(payload.params[0], payload.params[1], fireblocks_sdk_2.TransactionOperation.TYPED_MESSAGE, types_1.RawMessageType.EIP712);
break;
case "eth_signTypedData_v2":
case "eth_signTransaction":
throw this.createError({
message: `JSON-RPC method (${payload.method}) is not implemented in FireblocksWeb3Provider`,
code: 4200,
payload,
});
default:
const jsonRpcResponse = await util_1.default.promisify(super.send).bind(this)(payload);
if (jsonRpcResponse.error) {
if (payload.method == 'eth_estimateGas') {
logEnhancedErrorHandling(`Simulate the failed transaction on Tenderly: ${this.createTenderlySimulationLink(payload.params[0])}`);
}
throw this.createError({
message: jsonRpcResponse.error.message,
code: jsonRpcResponse.error.code,
data: jsonRpcResponse.error.data,
payload,
});
}
result = jsonRpcResponse.result;
}
}
catch (e) {
error = e;
}
if (error) {
logRequestsAndResponses(`Error #${requestNumber}: ${error}`);
}
else {
logRequestsAndResponses(`Response #${requestNumber}: ${JSON.stringify(result, undefined, 4)}`);
}
callback(error, (0, jsonRpcUtils_1.formatJsonRpcResult)(payload.id, result));
})();
}
createTenderlySimulationLink(tx) {
const searchParams = new URLSearchParams(JSON.parse(JSON.stringify(Object.assign(Object.assign({}, tx), { to: undefined, contractAddress: tx.to, data: undefined, rawFunctionInput: tx.data || '0x', network: this.chainId, gasPrice: tx.gasPrice ? Number(tx.gasPrice) : undefined, gas: tx.gas ? Number(tx.gas) : undefined }))));
if (!searchParams.get('gasPrice') && tx.maxFeePerGas) {
searchParams.set('gasPrice', String(Number(tx.maxFeePerGas)));
}
return `https://dashboard.tenderly.co/simulator/new?${searchParams.toString()}`;
}
createError(errorData) {
const error = new Error(errorData.message);
error.code = errorData.code || -32603;
error.data = errorData.data;
error.payload = errorData.payload;
// We do this to avoid including this function in the stack trace
if (Error.captureStackTrace !== undefined) {
Error.captureStackTrace(error, this.createError);
}
return error;
}
sendAsync(payload, callback) {
this.send(payload, callback);
}
async request(args) {
return (await util_1.default.promisify(this.send).bind(this)((0, jsonRpcUtils_1.formatJsonRpcRequest)(args.method, args.params))).result;
}
getDestination(address) {
if (this.oneTimeAddressesEnabled) {
return {
type: fireblocks_sdk_2.PeerType.ONE_TIME_ADDRESS,
oneTimeAddress: {
address: address || "0x0" // 0x0 for contract creation transactions
}
};
}
else {
if (!address || address == "0x0") {
throw this.createError({ message: "Contract deployment is currently not available without enabling one-time addresses" });
}
const whitelistedDestination = this.whitelisted[address.toLowerCase()];
if (!whitelistedDestination) {
throw this.createError({ message: `Address ${address} is not whitelisted. Whitelisted addresses: ${JSON.stringify(this.whitelisted, undefined, 4)}` });
}
return {
type: whitelistedDestination.type,
id: whitelistedDestination.id,
};
}
}
getVaultAccountIdAndValidateExistence(address, errorMessage = "Account not found: ") {
const vaultAccountId = this.getVaultAccountId(address);
if (isNaN(vaultAccountId)) {
throw this.createError({
message: `${errorMessage}${address}.
${!this.config.vaultAccountIds ? "vaultAccountIds was not provided in the configuration. When that happens, the provider loads the first 20 vault accounts found. It is advised to explicitly pass the required vaultAccountIds in the configuration to the provider." : `vaultAccountIds provided in the configuration: ${this.vaultAccountIds.join(", ")}`}.
Available addresses: ${Object.values(this.accounts).join(', ')}.`
});
}
return vaultAccountId;
}
async createGaslessTransaction(transaction) {
await this.initialized();
if (transaction.chainId && Number(transaction.chainId) != Number(this.chainId)) {
throw new Error(`Chain ID of the transaction (${transaction.chainId}) does not match the chain ID of the FireblocksWeb3Provider (${this.chainId})`);
}
if (!transaction.from) {
throw new Error(`Transaction sent with no "from" field`);
}
const { data, from, to } = transaction;
const ethersProvider = new ethers.BrowserProvider(this);
const NativeMetaTransactionContract = factories_1.NativeMetaTransaction__factory.connect(to, await ethersProvider.getSigner(this.gaslessGasTankVaultAddress));
const nonce = Number(await NativeMetaTransactionContract.getNonce(from));
const name = await NativeMetaTransactionContract.name();
const version = await NativeMetaTransactionContract.ERC712_VERSION();
const req = {
nonce,
from: from,
functionSignature: data,
};
const domain = {
name,
version,
// @ts-ignore
salt: ethers.utils.hexZeroPad(this.chainId, 32),
verifyingContract: to,
};
const types = {
MetaTransaction: [
{ name: 'nonce', type: 'uint256' },
{ name: 'from', type: 'address' },
{ name: 'functionSignature', type: 'bytes' },
],
};
const signature = ethers.Signature.from(await (await ethersProvider.getSigner(from)).signTypedData(domain, types, req));
const relayedTx = await NativeMetaTransactionContract.executeMetaTransaction(from, data, signature.r, signature.s, signature.v);
return relayedTx.hash;
}
async createContractCall(transaction) {
var _a;
await this.initialized();
if (transaction.chainId && Number(transaction.chainId) != Number(this.chainId)) {
throw this.createError({ message: `Chain ID of the transaction (${transaction.chainId}) does not match the chain ID of the FireblocksWeb3Provider (${this.chainId})` });
}
if (!transaction.from) {
throw this.createError({ message: `Transaction sent with no "from" field` });
}
const vaultAccountId = this.getVaultAccountIdAndValidateExistence(transaction.from, `Transaction sent from an unsupported address: `);
const { gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas } = transaction;
const fee = (0, units_1.formatUnits)(gasPrice || 0, "gwei");
const maxFee = (0, units_1.formatUnits)(maxFeePerGas || 0, "gwei");
const priorityFee = (0, units_1.formatUnits)(maxPriorityFeePerGas || 0, "gwei");
// if both are provided prefer eip 1559 fees
const isEip1559Fees = (Boolean(maxFee) && Boolean(maxPriorityFeePerGas) && Boolean(gas));
const isLegacyFees = (Boolean(gasPrice) && Boolean(gas)) && !isEip1559Fees;
const transactionArguments = {
operation: transaction.data ? fireblocks_sdk_2.TransactionOperation.CONTRACT_CALL : fireblocks_sdk_2.TransactionOperation.TRANSFER,
assetId: this.assetId,
source: {
type: fireblocks_sdk_2.PeerType.VAULT_ACCOUNT,
id: vaultAccountId.toString(),
},
fee: isLegacyFees ? fee : undefined,
maxFee: isEip1559Fees ? maxFee : undefined,
priorityFee: isEip1559Fees ? priorityFee : undefined,
gasLimit: (isEip1559Fees || isLegacyFees) ? Number(gas).toString(10) : undefined,
feeLevel: (isEip1559Fees || isLegacyFees) ? undefined : this.feeLevel,
destination: this.getDestination(transaction.to),
note: this.note,
externalTxId: !this.externalTxId ? undefined : (typeof this.externalTxId == 'function' ? this.externalTxId() : this.externalTxId),
amount: (0, units_1.formatEther)(((_a = transaction.value) === null || _a === void 0 ? void 0 : _a.toString()) || "0"),
extraParameters: transaction.data ? {
contractCallData: transaction.data
} : undefined,
};
const createTransactionResponse = await this.createTransaction(transactionArguments);
return createTransactionResponse.txHash;
}
async createPersonalSign(address, content, operation, type) {
await this.initialized();
const vaultAccountId = this.getVaultAccountIdAndValidateExistence(address, `Signature request from an unsupported address: `);
let finalContent = content;
if (type === types_1.RawMessageType.EIP712) {
if (typeof content !== 'object') {
finalContent = JSON.parse(content);
}
else {
finalContent = content;
}
}
else if (finalContent.startsWith("0x")) {
finalContent = finalContent.substring(2);
}
let message;
if (operation === fireblocks_sdk_2.TransactionOperation.TYPED_MESSAGE) {
message = {
content: finalContent,
index: 0,
type: type,
};
}
else {
message = {
content: finalContent
};
}
const transactionArguments = {
operation: operation,
assetId: this.assetId,
source: {
type: fireblocks_sdk_2.PeerType.VAULT_ACCOUNT,
id: vaultAccountId.toString(),
},
note: this.note,
externalTxId: !this.externalTxId ? undefined : (typeof this.externalTxId == 'function' ? this.externalTxId() : this.externalTxId),
extraParameters: {
rawMessageData: {
messages: [message]
}
}
};
const txInfo = await this.createTransaction(transactionArguments);
const sig = txInfo.signedMessages[0].signature;
const v = 27 + sig.v;
return "0x" + sig.r + sig.s + v.toString(16);
}
async createTransaction(transactionArguments) {
const { id } = await this.fireblocksApiClient.createTransaction(transactionArguments);
let txInfo;
let currentStatus = fireblocks_sdk_1.TransactionStatus.SUBMITTED;
while (!constants_1.FINAL_TRANSACTION_STATES.includes(currentStatus)) {
try {
txInfo = await this.fireblocksApiClient.getTransactionById(id);
if (currentStatus != txInfo.status) {
logTransactionStatusChange(`Fireblocks transaction ${txInfo.id} changed status from ${currentStatus} to ${txInfo.status} ${txInfo.subStatus ? `(${txInfo.subStatus})` : ''}`);
}
currentStatus = txInfo.status;
}
catch (err) {
console.error(this.createFireblocksError(err));
}
await new Promise(r => setTimeout(r, this.pollingInterval));
}
if (!constants_1.FINAL_SUCCESSFUL_TRANSACTION_STATES.includes(currentStatus)) {
throw this.createError({ message: `Fireblocks transaction ${txInfo.id || ''} was not completed successfully. Final Status: ${currentStatus} ${(txInfo === null || txInfo === void 0 ? void 0 : txInfo.subStatus) ? `(${txInfo === null || txInfo === void 0 ? void 0 : txInfo.subStatus})` : ''}` });
}
return txInfo;
}
getVaultAccountId(address) {
var _a;
return parseInt(((_a = Object.entries(this.accounts).find(([id, addr]) => addr.toLowerCase() === address.toLowerCase())) === null || _a === void 0 ? void 0 : _a[0]) || '');
}
setExternalTxId(externalTxId) {
this.externalTxId = externalTxId;
}
toAxiosProxyConfig(path) {
const proxyUrl = new URL(path);
if (proxyUrl.pathname != '/') {
throw 'Proxy with path is not supported by axios';
}
return {
protocol: proxyUrl.protocol.replace(':', ''),
host: proxyUrl.hostname,
port: parseInt(proxyUrl.port),
auth: proxyUrl.username ? {
username: proxyUrl.username,
password: proxyUrl.password
} : undefined
};
}
}
exports.FireblocksWeb3Provider = FireblocksWeb3Provider;
//# sourceMappingURL=provider.js.map