From a2339c3928b5daec911cd5d89dc2a2d5d1a99fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kotol?= Date: Wed, 6 Mar 2024 09:29:14 +0100 Subject: [PATCH] ALL-5473 - Fix Solana confirm transaction with custom retry (#1075) --- package.json | 2 +- .../src/lib/__tests__/solana.tx.spec.ts | 5 ++-- .../src/lib/services/solana.marketplace.ts | 27 +++++++------------ .../solana/src/lib/services/solana.nft.ts | 16 +++++------ .../solana/src/lib/services/solana.spl.ts | 8 +++--- .../solana/src/lib/services/solana.tx.ts | 4 +-- .../solana/src/lib/services/solana.utils.ts | 17 +++++++++++- 7 files changed, 39 insertions(+), 40 deletions(-) diff --git a/package.json b/package.json index 0b645bafbd..926d13b4aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tatumio", - "version": "2.2.56", + "version": "2.2.57", "license": "MIT", "repository": "https://github.com/tatumio/tatum-js", "scripts": { diff --git a/packages/blockchain/solana/src/lib/__tests__/solana.tx.spec.ts b/packages/blockchain/solana/src/lib/__tests__/solana.tx.spec.ts index d629d7af22..5247ea511c 100644 --- a/packages/blockchain/solana/src/lib/__tests__/solana.tx.spec.ts +++ b/packages/blockchain/solana/src/lib/__tests__/solana.tx.spec.ts @@ -6,10 +6,9 @@ import { FEE_PAYER } from '../services/solana.utils' jest.setTimeout(99999) -describe.skip('SolanaSDK - tx', () => { +describe('SolanaSDK - tx', () => { const sdk = TatumSolanaSDK({ apiKey: REPLACE_ME_WITH_TATUM_API_KEY, - provider: 'https://api.devnet.solana.com', }) const mintNFT = async () => { @@ -366,7 +365,7 @@ describe.skip('SolanaSDK - tx', () => { }) }) - describe('External signing', () => { + describe.skip('External signing', () => { it('should send SPL token with fee payer', async () => { const tx = await sdk.spl.send.transferSignedTransaction( { diff --git a/packages/blockchain/solana/src/lib/services/solana.marketplace.ts b/packages/blockchain/solana/src/lib/services/solana.marketplace.ts index b172a32cb4..dacca00e69 100644 --- a/packages/blockchain/solana/src/lib/services/solana.marketplace.ts +++ b/packages/blockchain/solana/src/lib/services/solana.marketplace.ts @@ -238,8 +238,9 @@ export const solanaMarketPlaceService = ( } const signers = [web3.generateKeyPair(params.fromPrivateKey)] + const { txId } = await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) return { - txId: await connection.sendTransaction(transaction, signers), + txId, contractAddress: auctionHouse.toBase58(), feeAccount: feeAccount.toBase58(), treasuryAccount: treasuryAccount.toBase58(), @@ -314,9 +315,7 @@ export const solanaMarketPlaceService = ( } const signers = [web3.generateKeyPair(params.fromPrivateKey)] - return { - txId: await connection.sendTransaction(transaction, signers), - } + return await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) } const formatPrice = async ( @@ -444,9 +443,9 @@ export const solanaMarketPlaceService = ( if (authorityPrivateKey) { signers.push(web3.generateKeyPair(authorityPrivateKey)) } - + const { txId } = await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) return { - txId: await connection.sendTransaction(transaction, signers), + txId, listingId: receipt.toBase58(), } } @@ -803,9 +802,7 @@ export const solanaMarketPlaceService = ( signers.push(web3.generateKeyPair(authorityPrivateKey)) } - return { - txId: await connection.sendTransaction(transaction, signers), - } + return await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) } const cancelSignedTransaction = async ( @@ -894,9 +891,7 @@ export const solanaMarketPlaceService = ( signers.push(web3.generateKeyPair(authorityPrivateKey)) } - return { - txId: await connection.sendTransaction(transaction, signers), - } + return await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) } const withdrawFromTreasurySignedTransaction = async ( @@ -950,9 +945,7 @@ export const solanaMarketPlaceService = ( const signers = [web3.generateKeyPair(fromPrivateKey)] - return { - txId: await connection.sendTransaction(transaction, signers), - } + return await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) } const withdrawFromFeeSignedTransaction = async ( @@ -1004,9 +997,7 @@ export const solanaMarketPlaceService = ( const signers = [web3.generateKeyPair(fromPrivateKey)] - return { - txId: await connection.sendTransaction(transaction, signers), - } + return await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) } return { diff --git a/packages/blockchain/solana/src/lib/services/solana.nft.ts b/packages/blockchain/solana/src/lib/services/solana.nft.ts index 2e352311eb..56b7fc47ab 100644 --- a/packages/blockchain/solana/src/lib/services/solana.nft.ts +++ b/packages/blockchain/solana/src/lib/services/solana.nft.ts @@ -81,9 +81,7 @@ const transferSignedTransaction = async ( } else if (body.feePayerPrivateKey) { signers.push(web3.generateKeyPair(body.feePayerPrivateKey)) } - return { - txId: await connection.sendTransaction(transaction, signers), - } + return await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) } const mintSignedTransaction = async ( @@ -221,8 +219,10 @@ const mintSignedTransaction = async ( } else if (body.feePayerPrivateKey) { signers.push(web3.generateKeyPair(body.feePayerPrivateKey)) } + + const { txId } = await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) return { - txId: await connection.sendTransaction(transaction, [wallet, ...signers]), + txId, nftAddress: mint.publicKey.toBase58(), nftAccountAddress: userTokenAccountAddress.toBase58(), } @@ -277,9 +277,7 @@ const burnSignedTransaction = async ( } else if (body.feePayerPrivateKey) { signers.push(web3.generateKeyPair(body.feePayerPrivateKey)) } - return { - txId: await connection.sendTransaction(transaction, signers), - } + return await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) } const verifySignedTransaction = async ( @@ -327,9 +325,7 @@ const verifySignedTransaction = async ( } else if (body.feePayerPrivateKey) { signers.push(web3.generateKeyPair(body.feePayerPrivateKey)) } - return { - txId: await connection.sendTransaction(transaction, signers), - } + return await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) } export const solanaNftService = (args: { web3: SolanaWeb3 }) => { diff --git a/packages/blockchain/solana/src/lib/services/solana.spl.ts b/packages/blockchain/solana/src/lib/services/solana.spl.ts index b9a7e27c9c..44bbaeec33 100644 --- a/packages/blockchain/solana/src/lib/services/solana.spl.ts +++ b/packages/blockchain/solana/src/lib/services/solana.spl.ts @@ -62,9 +62,7 @@ const transferSignedTransaction = async ( } else if (body.feePayerPrivateKey) { signers.push(web3.generateKeyPair(body.feePayerPrivateKey)) } - return { - txId: await connection.sendTransaction(transaction, signers), - } + return await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) } const deploySignedTransaction = async ( @@ -128,8 +126,10 @@ const deploySignedTransaction = async ( } else if (body.feePayerPrivateKey) { signers.push(web3.generateKeyPair(body.feePayerPrivateKey)) } + + const { txId } = await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) return { - txId: await connection.sendTransaction(transaction, signers), + txId, contractAddress: mint.publicKey.toBase58(), } } diff --git a/packages/blockchain/solana/src/lib/services/solana.tx.ts b/packages/blockchain/solana/src/lib/services/solana.tx.ts index e17d3322d8..b86c1bea47 100644 --- a/packages/blockchain/solana/src/lib/services/solana.tx.ts +++ b/packages/blockchain/solana/src/lib/services/solana.tx.ts @@ -50,9 +50,7 @@ const transferSignedTransaction = async ( signers.push(web3.generateKeyPair(body.feePayerPrivateKey)) } - return { - txId: await connection.sendTransaction(transaction, signers), - } + return await solanaUtils.sendTransactionWithConfirm(connection, transaction, signers) } export const solanaTxService = (args: { web3: SolanaWeb3 }) => { diff --git a/packages/blockchain/solana/src/lib/services/solana.utils.ts b/packages/blockchain/solana/src/lib/services/solana.utils.ts index 653c67c7fe..caac2cd6a5 100644 --- a/packages/blockchain/solana/src/lib/services/solana.utils.ts +++ b/packages/blockchain/solana/src/lib/services/solana.utils.ts @@ -11,7 +11,7 @@ import { } from '@tatumio/api-client' import { SdkErrorCode, WithoutChain } from '@tatumio/shared-abstract-sdk' import { FromPrivateKeyOrSignatureId } from '@tatumio/shared-blockchain-abstract' -import { PublicKey, Signer, Transaction } from '@solana/web3.js' +import { Connection, PublicKey, Signer, Transaction } from '@solana/web3.js' import { SolanaWeb3 } from './solana.web3' import { SolanaSdkError } from '../solana.sdk.errors' import BN from 'bn.js' @@ -108,4 +108,19 @@ export const solanaUtils = { chain: 'SOL', }) }, + sendTransactionWithConfirm: async (connection: Connection, transaction: Transaction, signers: Signer[]) => { + const attempts = 5 + const txId = await connection.sendTransaction(transaction, signers) + for (let attempt = 1; attempt <= attempts; attempt++) { + const confirmedTx = await connection.getTransaction(txId, { commitment: 'confirmed' }) + + if (confirmedTx && !confirmedTx.meta?.err) { + return { txId } + } + await new Promise((r) => setTimeout(r, 500)) + } + throw new Error( + `Transaction not confirmed after ${attempts} attempts, please try to send transaction again.`, + ) + }, }