@@ -2,6 +2,7 @@ import { Injectable, Logger } from '@nestjs/common';
22import { ConfigService } from '@nestjs/config' ;
33import * as StellarSdk from 'stellar-sdk' ;
44import { SorobanService } from '../../../blockchain/soroban/soroban.service' ;
5+ import { TransactionBuilderService } from '../../transaction-builder.service' ;
56import { PoolStats , LIQUIDITY_POOL_CONTRACT_ID_KEY } from '../interfaces/liquidity-pool.interface' ;
67import {
78 ContractNotConfiguredError ,
@@ -20,6 +21,7 @@ export class LiquidityPoolContractClient {
2021
2122 constructor (
2223 private readonly sorobanService : SorobanService ,
24+ private readonly transactionBuilderService : TransactionBuilderService ,
2325 private readonly configService : ConfigService ,
2426 ) {
2527 this . contractId =
@@ -172,23 +174,36 @@ export class LiquidityPoolContractClient {
172174 const sourceKeypair = StellarSdk . Keypair . random ( ) ;
173175 const sourceAccount = new StellarSdk . Account ( sourceKeypair . publicKey ( ) , '0' ) ;
174176
175- const tx = new StellarSdk . TransactionBuilder ( sourceAccount , {
176- fee : StellarSdk . BASE_FEE ,
177- networkPassphrase,
178- } )
179- . addOperation ( contract . call ( 'deposit' , userArg , amountArg ) )
180- . setTimeout ( 300 )
181- . build ( ) ;
182-
183- const simulation = await server . simulateTransaction ( tx ) ;
184-
185- if ( StellarSdk . SorobanRpc . Api . isSimulationError ( simulation ) ) {
186- const errorMsg =
187- ( simulation as StellarSdk . SorobanRpc . Api . SimulateTransactionErrorResponse ) . error ||
188- 'Unknown simulation error' ;
189- this . logger . error ( `deposit simulation failed: ${ errorMsg } ` ) ;
190- throw new ContractSimulationError ( 'deposit' ) ;
191- }
177+ const buildTransaction = ( fee : string ) : StellarSdk . Transaction =>
178+ new StellarSdk . TransactionBuilder ( sourceAccount , {
179+ fee,
180+ networkPassphrase,
181+ } )
182+ . addOperation ( contract . call ( 'deposit' , userArg , amountArg ) )
183+ . setTimeout ( 300 )
184+ . build ( ) ;
185+
186+ const { tx, simulation } = await this . transactionBuilderService . buildWithFeeRetry (
187+ 1 ,
188+ 'deposit transaction' ,
189+ async ( fee ) => {
190+ const tx = buildTransaction ( fee ) ;
191+ const simulation = await server . simulateTransaction ( tx ) ;
192+
193+ if ( StellarSdk . SorobanRpc . Api . isSimulationError ( simulation ) ) {
194+ const errorMsg =
195+ ( simulation as StellarSdk . SorobanRpc . Api . SimulateTransactionErrorResponse ) . error ||
196+ 'Unknown simulation error' ;
197+ if ( this . transactionBuilderService . isInsufficientFeeError ( errorMsg ) ) {
198+ throw new Error ( errorMsg ) ;
199+ }
200+ this . logger . error ( `deposit simulation failed: ${ errorMsg } ` ) ;
201+ throw new ContractSimulationError ( 'deposit' ) ;
202+ }
203+
204+ return { tx, simulation } ;
205+ } ,
206+ ) ;
192207
193208 const assembledTx = StellarSdk . SorobanRpc . assembleTransaction (
194209 tx ,
@@ -224,23 +239,36 @@ export class LiquidityPoolContractClient {
224239 const sourceKeypair = StellarSdk . Keypair . random ( ) ;
225240 const sourceAccount = new StellarSdk . Account ( sourceKeypair . publicKey ( ) , '0' ) ;
226241
227- const tx = new StellarSdk . TransactionBuilder ( sourceAccount , {
228- fee : StellarSdk . BASE_FEE ,
229- networkPassphrase,
230- } )
231- . addOperation ( contract . call ( 'withdraw' , userArg , sharesArg ) )
232- . setTimeout ( 300 )
233- . build ( ) ;
234-
235- const simulation = await server . simulateTransaction ( tx ) ;
236-
237- if ( StellarSdk . SorobanRpc . Api . isSimulationError ( simulation ) ) {
238- const errorMsg =
239- ( simulation as StellarSdk . SorobanRpc . Api . SimulateTransactionErrorResponse ) . error ||
240- 'Unknown simulation error' ;
241- this . logger . error ( `withdraw simulation failed: ${ errorMsg } ` ) ;
242- throw new ContractSimulationError ( 'withdraw' ) ;
243- }
242+ const buildTransaction = ( fee : string ) : StellarSdk . Transaction =>
243+ new StellarSdk . TransactionBuilder ( sourceAccount , {
244+ fee,
245+ networkPassphrase,
246+ } )
247+ . addOperation ( contract . call ( 'withdraw' , userArg , sharesArg ) )
248+ . setTimeout ( 300 )
249+ . build ( ) ;
250+
251+ const { tx, simulation } = await this . transactionBuilderService . buildWithFeeRetry (
252+ 1 ,
253+ 'withdraw transaction' ,
254+ async ( fee ) => {
255+ const tx = buildTransaction ( fee ) ;
256+ const simulation = await server . simulateTransaction ( tx ) ;
257+
258+ if ( StellarSdk . SorobanRpc . Api . isSimulationError ( simulation ) ) {
259+ const errorMsg =
260+ ( simulation as StellarSdk . SorobanRpc . Api . SimulateTransactionErrorResponse ) . error ||
261+ 'Unknown simulation error' ;
262+ if ( this . transactionBuilderService . isInsufficientFeeError ( errorMsg ) ) {
263+ throw new Error ( errorMsg ) ;
264+ }
265+ this . logger . error ( `withdraw simulation failed: ${ errorMsg } ` ) ;
266+ throw new ContractSimulationError ( 'withdraw' ) ;
267+ }
268+
269+ return { tx, simulation } ;
270+ } ,
271+ ) ;
244272
245273 const assembledTx = StellarSdk . SorobanRpc . assembleTransaction (
246274 tx ,
0 commit comments