diff --git a/src/common/constants/api.constant.ts b/src/common/constants/api.constant.ts index f08643f3..9cdc7ab7 100644 --- a/src/common/constants/api.constant.ts +++ b/src/common/constants/api.constant.ts @@ -15,6 +15,7 @@ export const URL_CONSTANTS = { CHANGE_SEQ: 'change-seq', DELETE_TX: 'delete', GET_ADDRESS_SIMULATE: 'simulate/address', + GET_NEXT_SEQUENCE: 'next-seq', SIMULATE_TX: 'simulate', broadcasting: 'broadcasting', signing: 'signing', diff --git a/src/modules/multisig-transaction/dto/request/get-next-seq-query.req.ts b/src/modules/multisig-transaction/dto/request/get-next-seq-query.req.ts new file mode 100644 index 00000000..81a5d7d1 --- /dev/null +++ b/src/modules/multisig-transaction/dto/request/get-next-seq-query.req.ts @@ -0,0 +1,13 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Type } from 'class-transformer'; +import { IsNumber } from 'class-validator'; + +export class GetNextSeqQueryDto { + @IsNumber() + @ApiProperty({ + description: 'Safe Id', + example: 1, + }) + @Type(() => Number) + safeId: number; +} diff --git a/src/modules/multisig-transaction/dto/request/index.ts b/src/modules/multisig-transaction/dto/request/index.ts index 2a3c23c8..7eac0d5b 100644 --- a/src/modules/multisig-transaction/dto/request/index.ts +++ b/src/modules/multisig-transaction/dto/request/index.ts @@ -9,3 +9,4 @@ export * from './get-tx-query.req'; export * from './get-simulate.req'; export * from './get-simulate-query.req'; export * from './delete-tx.req'; +export * from './get-next-seq-query.req'; diff --git a/src/modules/multisig-transaction/multisig-transaction.controller.ts b/src/modules/multisig-transaction/multisig-transaction.controller.ts index 710645bc..ecbd442f 100644 --- a/src/modules/multisig-transaction/multisig-transaction.controller.ts +++ b/src/modules/multisig-transaction/multisig-transaction.controller.ts @@ -31,6 +31,7 @@ import { ConfirmTransactionRequestDto, CreateTransactionRequestDto, GetAllTransactionsRequestDto, + GetNextSeqQueryDto, GetSimulateAddressQueryDto, GetTxDetailQueryDto, RejectTransactionRequestDto, @@ -136,6 +137,18 @@ export class MultisigTransactionController { return this.multisigTransactionService.getTransactionDetail(query); } + + + @CommonGet({ + url: URL_CONSTANTS.GET_NEXT_SEQUENCE, + summary: 'Get simulate addresses', + description: 'Get simulate addresses', + }) + async getNextSeq(@Query() request: GetNextSeqQueryDto) { + this.logger.log('========== Get next sequence =========='); + return this.multisigTransactionService.getNextSequence(request.safeId); + } + @CommonGet({ url: URL_CONSTANTS.GET_ADDRESS_SIMULATE, summary: 'Get simulate addresses', diff --git a/src/modules/multisig-transaction/multisig-transaction.processor.ts b/src/modules/multisig-transaction/multisig-transaction.processor.ts index a9d4e868..2a5c5c79 100644 --- a/src/modules/multisig-transaction/multisig-transaction.processor.ts +++ b/src/modules/multisig-transaction/multisig-transaction.processor.ts @@ -32,7 +32,7 @@ export class MultisigTxProcessor { private readonly chainRepos: ChainRepository, private readonly multisigConfirmRepos: MultisigConfirmRepository, private readonly safeRepo: SafeRepository, - ) {} + ) { } @Process('send-tx') async handleTranscode(job: Job) { @@ -87,14 +87,17 @@ export class MultisigTxProcessor { ): Promise { const queueSequences = await this.multisigRepo.findSequenceInQueue(safeId); - let nextSeq = currentSequence; - for (const seq of queueSequences) { - if (seq !== nextSeq) { + let estimateSeq = currentSequence; + for (const inQueueSeq of queueSequences) { + if (inQueueSeq < estimateSeq) { + // skip invalid queue tx + } else if (inQueueSeq === estimateSeq) { + estimateSeq += 1 + } else { break; } - nextSeq += 1; } - return nextSeq.toString(); + return estimateSeq.toString(); } async makeTx( @@ -129,19 +132,19 @@ export class MultisigTxProcessor { const executeTransaction = chain.chainId.startsWith('evmos') || chain.chainId.startsWith('canto') ? this.ethermintHelper.makeMultisignedTxEthermint( - safePubkey, - Number(multisigTransaction.sequence), - sendFee, - encodedBodyBytes, - addressSignatureMap, - ) + safePubkey, + Number(multisigTransaction.sequence), + sendFee, + encodedBodyBytes, + addressSignatureMap, + ) : makeMultisignedTx( - safePubkey, - Number(multisigTransaction.sequence), - sendFee, - encodedBodyBytes, - addressSignatureMap, - ); + safePubkey, + Number(multisigTransaction.sequence), + sendFee, + encodedBodyBytes, + addressSignatureMap, + ); const encodeTransaction = Uint8Array.from( TxRaw.encode(executeTransaction).finish(), diff --git a/src/modules/multisig-transaction/multisig-transaction.service.ts b/src/modules/multisig-transaction/multisig-transaction.service.ts index 4f57f17f..a02c9f71 100644 --- a/src/modules/multisig-transaction/multisig-transaction.service.ts +++ b/src/modules/multisig-transaction/multisig-transaction.service.ts @@ -92,6 +92,24 @@ export class MultisigTransactionService { this.useHoroscope = /^true$/i.test(this.configService.get('USE_HOROSCOPE')); } + async getNextSequence(safeId: number) { + + const safe = await this.safeRepos.getSafeById(safeId); + // get chain info + const chain = await this.chainRepos.findChain(safe.internalChainId); + + // get safe account info + const { sequence } = await this.indexerV2.getAccount( + chain.chainId, + safe.safeAddress, + ); + + const nextSequence = await this.calculateNextSeq(safeId, sequence) + return { + nextSequence + } + } + async createMultisigTransaction( request: CreateTransactionRequestDto, ): Promise> { @@ -166,17 +184,17 @@ export class MultisigTransactionService { // check balance await (contractAddress ? this.indexerV2.checkCw20Balance( - safe.safeAddress, - contractAddress, - amount, - chain.chainId, - ) + safe.safeAddress, + contractAddress, + amount, + chain.chainId, + ) : this.indexerV2.checkTokenBalance( - safe.safeAddress, - amount, - denom, - chain.chainId, - )); + safe.safeAddress, + amount, + denom, + chain.chainId, + )); } if (this.useHoroscope && contractAddress) { @@ -879,19 +897,19 @@ export class MultisigTransactionService { const executeTransaction = chainInfo.coinDecimals === 18 ? this.ethermintHelper.makeMultisignedTxEthermint( - safePubkey, - Number(multisigTransaction.sequence), - sendFee, - encodedBodyBytes, - addressSignatureMap, - ) + safePubkey, + Number(multisigTransaction.sequence), + sendFee, + encodedBodyBytes, + addressSignatureMap, + ) : makeMultisignedTx( - safePubkey, - Number(multisigTransaction.sequence), - sendFee, - encodedBodyBytes, - addressSignatureMap, - ); + safePubkey, + Number(multisigTransaction.sequence), + sendFee, + encodedBodyBytes, + addressSignatureMap, + ); const encodeTransaction = Uint8Array.from( TxRaw.encode(executeTransaction).finish(), @@ -984,13 +1002,16 @@ export class MultisigTransactionService { const queueSequences = await this.multisigTransactionRepos.findSequenceInQueue(safeId); - let nextSeq = currentSequence; - for (const seq of queueSequences) { - if (seq !== nextSeq) { + let estimateSeq = currentSequence; + for (const inQueueSeq of queueSequences) { + if (inQueueSeq < estimateSeq) { + // skip invalid queue tx + } else if (inQueueSeq === estimateSeq) { + estimateSeq += 1 + } else { break; } - nextSeq += 1; } - return nextSeq.toString(); + return estimateSeq.toString(); } }