UNPKG

@0xsequence/connect

Version:
169 lines 7.19 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.waitForTransactionReceipt = exports.sendTransactions = void 0; const _0xsequence_1 = require("0xsequence"); const indexer_1 = require("@0xsequence/indexer"); const index_js_1 = require("../constants/index.js"); const helpers_js_1 = require("../utils/helpers.js"); class FeeOptionInsufficientFundsError extends Error { feeOptions; constructor(message, feeOptions) { super(message); this.name = 'FeeOptionInsufficientFundsError'; this.feeOptions = feeOptions; } } const sendTransactions = async ({ chainId, senderAddress, publicClient, walletClient, connector, transactions, indexerClient, transactionConfirmations = index_js_1.TRANSACTION_CONFIRMATIONS_DEFAULT, waitConfirmationForLastTransaction = true }) => { const walletClientChainId = await walletClient.getChainId(); if (walletClientChainId !== chainId) { throw new Error('The Wallet Client is using the wrong network'); } if (publicClient.chain?.id !== chainId) { throw new Error('The Public Client is using the wrong network'); } const sequenceWaaS = connector?.['sequenceWaas']; const isEmbeddedWallet = !!sequenceWaaS; const isSequenceUniversalWallet = !!connector?._wallet?.isSequenceBased; // Sequence WaaS if (isEmbeddedWallet) { // waas connector logic const resp = await sequenceWaaS.feeOptions({ transactions: transactions, network: chainId }); const isSponsored = resp.data.feeOptions.length == 0; let transactionsFeeOption; const transactionsFeeQuote = resp.data.feeQuote; const balances = await indexerClient.getTokenBalancesDetails({ filter: { accountAddresses: [senderAddress], omitNativeBalances: false } }); for (const feeOption of resp.data.feeOptions) { const isNativeToken = feeOption.token.contractAddress == null; if (isNativeToken) { const nativeTokenBalance = balances.nativeBalances?.[0].balance || '0'; if (BigInt(nativeTokenBalance) >= BigInt(feeOption.value)) { transactionsFeeOption = feeOption; break; } } else { const erc20TokenBalance = balances.balances.find(b => (0, helpers_js_1.compareAddress)(b.contractAddress, feeOption.token.contractAddress || '')); const erc20TokenBalanceValue = erc20TokenBalance?.balance || '0'; if (BigInt(erc20TokenBalanceValue) >= BigInt(feeOption.value)) { transactionsFeeOption = feeOption; break; } } } if (!transactionsFeeOption && !isSponsored) { throw new FeeOptionInsufficientFundsError(`Transaction fee option with valid user balance not found: ${resp.data.feeOptions.map(f => f.token.symbol).join(', ')}`, resp.data.feeOptions); } const response = await sequenceWaaS.sendTransaction({ transactions, transactionsFeeOption, transactionsFeeQuote, network: chainId }); if (response.code === 'transactionFailed') { throw new Error(response.data.error); } const txnHash = response.data.txHash; if (waitConfirmationForLastTransaction) { const { txnStatus } = await (0, exports.waitForTransactionReceipt)({ indexerClient, txnHash: txnHash, publicClient, confirmations: transactionConfirmations }); if (txnStatus === indexer_1.TransactionStatus.FAILED) { throw new Error('Transaction failed'); } } return txnHash; // Sequence-Based Connector } else if (isSequenceUniversalWallet) { const wallet = _0xsequence_1.sequence.getWallet(); const signer = wallet.getSigner(); const response = await signer.sendTransaction(transactions); if (waitConfirmationForLastTransaction) { const { txnStatus } = await (0, exports.waitForTransactionReceipt)({ indexerClient, txnHash: response.hash, publicClient, confirmations: transactionConfirmations }); if (txnStatus === indexer_1.TransactionStatus.FAILED) { throw new Error('Transaction failed'); } } return response.hash; // Other connectors (metamask, eip-6963, etc...) } else { let txHash = ''; // We fire the transactions one at a time since the cannot be batched for (const [index, transaction] of transactions.entries()) { const txnHash = await walletClient.sendTransaction({ account: senderAddress, to: transaction.to, value: transaction?.value, data: transaction?.data, chain: undefined }); const isLastTransaction = index === transactions.length - 1; if (!isLastTransaction || (isLastTransaction && waitConfirmationForLastTransaction)) { const { txnStatus } = await (0, exports.waitForTransactionReceipt)({ indexerClient, txnHash, publicClient, confirmations: transactionConfirmations }); if (txnStatus === indexer_1.TransactionStatus.FAILED) { throw new Error('Transaction failed'); } } // The transaction hash of the last transaction is the one that should be returned txHash = txnHash; } return txHash; } }; exports.sendTransactions = sendTransactions; const waitForTransactionReceipt = async ({ indexerClient, txnHash, publicClient, confirmations }) => { const receiptPromise = new Promise(async (resolve, reject) => { await indexerClient.subscribeReceipts({ filter: { txnHash } }, { onMessage: ({ receipt }) => { resolve(receipt); }, onError: () => { reject('Transaction receipt not found'); } }); }); const receipt = await receiptPromise; if (confirmations) { const blockConfirmationPromise = new Promise(resolve => { const unwatch = publicClient.watchBlocks({ onBlock: ({ number: currentBlockNumber }) => { const confirmedBlocknumber = receipt.blockNumber + confirmations; if (currentBlockNumber >= confirmedBlocknumber) { unwatch(); resolve(); } } }); }); await blockConfirmationPromise; } return receipt; }; exports.waitForTransactionReceipt = waitForTransactionReceipt; //# sourceMappingURL=transactions.js.map