From 66d3e670c40730bc4a5400a6c0e05173c446b740 Mon Sep 17 00:00:00 2001 From: huhuanming Date: Fri, 10 May 2024 11:10:34 +0800 Subject: [PATCH] fix: fix too many vins on nexa (#4559) --- packages/engine/src/vaults/VaultBase.ts | 21 ++++++++ packages/engine/src/vaults/impl/nexa/Vault.ts | 48 +++++++++++++++---- .../engine/src/vaults/impl/nexa/sdk/nexa.ts | 2 + 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/packages/engine/src/vaults/VaultBase.ts b/packages/engine/src/vaults/VaultBase.ts index 07af08d0a54..c8c48e205c2 100644 --- a/packages/engine/src/vaults/VaultBase.ts +++ b/packages/engine/src/vaults/VaultBase.ts @@ -786,6 +786,27 @@ export abstract class VaultBase extends VaultBaseChainOnly { return nextNonce; } + getConfirmedUTXOs( + utxos: T[], + amount: string, + ): T[] { + const confirmedUTXOs = utxos.sort((a, b) => + new BigNumber(b.value).gt(a.value) ? 1 : -1, + ); + let sum = new BigNumber(0); + let i = 0; + for (i = 0; i < confirmedUTXOs.length; i += 1) { + sum = sum.plus(confirmedUTXOs[i].value); + if (sum.gt(amount)) { + break; + } + } + if (sum.lt(amount)) { + return []; + } + return confirmedUTXOs.slice(0, i + 1); + } + validateSendAmount(amount: string, tokenBalance: string, to: string) { return Promise.resolve(true); } diff --git a/packages/engine/src/vaults/impl/nexa/Vault.ts b/packages/engine/src/vaults/impl/nexa/Vault.ts index 56e80c3fec9..8e6c6981688 100644 --- a/packages/engine/src/vaults/impl/nexa/Vault.ts +++ b/packages/engine/src/vaults/impl/nexa/Vault.ts @@ -51,9 +51,14 @@ import type { } from '../../../types/provider'; import type { Token } from '../../../types/token'; import type { KeyringSoftwareBase } from '../../keyring/KeyringSoftwareBase'; -import type { IDecodedTxLegacy, IHistoryTx, ISignedTxPro } from '../../types'; +import type { + IDecodedTxLegacy, + IHistoryTx, + ISignCredentialOptions, + ISignedTxPro, +} from '../../types'; import type { EVMDecodedItem } from '../evm/decoder/types'; -import type { IEncodedTxNexa, INexaTransaction } from './types'; +import type { IEncodedTxNexa, IListUTXO, INexaTransaction } from './types'; export default class Vault extends VaultBase { keyringMap = { @@ -243,13 +248,12 @@ export default class Vault extends VaultBase { ): Promise { const client = await this.getSDKClient(); const fromNexaAddress = transferInfo.from; - const utxos = (await client.getNexaUTXOs(fromNexaAddress)).filter( + const uxtos = (await client.getNexaUTXOs(fromNexaAddress)).filter( (value) => !value.has_token, ); - const network = await this.getNetwork(); return { - inputs: utxos.map((utxo) => ({ + inputs: uxtos.map((utxo) => ({ txId: utxo.outpoint_hash, outputIndex: utxo.tx_pos, satoshis: new BigNumber(utxo.value).toFixed(), @@ -284,15 +288,41 @@ export default class Vault extends VaultBase { return Promise.resolve(encodedTx); } - override buildUnsignedTxFromEncodedTx( + override async buildUnsignedTxFromEncodedTx( encodedTx: IEncodedTxNexa, ): Promise { - return Promise.resolve({ + const client = await this.getSDKClient(); + const network = await this.getNetwork(); + const confirmedUTXOs = this.getConfirmedUTXOs( + encodedTx.inputs.map((input) => ({ + ...input, + value: input.satoshis, + })), + new BigNumber(encodedTx.transferInfo?.amount || 0) + .shiftedBy(network.decimals) + .plus(encodedTx?.gas || 0) + .toFixed(), + ); + + if (confirmedUTXOs.length > client.MAX_TX_NUM_VIN) { + const maximumAmount = confirmedUTXOs + .slice(0, client.MAX_TX_NUM_VIN) + .reduce((acc, cur) => acc.plus(cur.value), new BigNumber(0)); + throw new OneKeyInternalError( + `Too many vins, The maximum amount for this transfer is ${maximumAmount + .shiftedBy(-network.decimals) + .toFixed()} ${network.symbol}.`, + ); + } + encodedTx.inputs = confirmedUTXOs; + return { inputs: [], outputs: [], - payload: { encodedTx }, + payload: { + encodedTx, + }, encodedTx, - }); + }; } override async getTransactionStatuses( diff --git a/packages/engine/src/vaults/impl/nexa/sdk/nexa.ts b/packages/engine/src/vaults/impl/nexa/sdk/nexa.ts index 47dfe6add2c..8b78bb5632f 100644 --- a/packages/engine/src/vaults/impl/nexa/sdk/nexa.ts +++ b/packages/engine/src/vaults/impl/nexa/sdk/nexa.ts @@ -15,6 +15,8 @@ import type { IListUTXO, INexaHistoryItem, INexaTransaction } from '../types'; export class Nexa extends SimpleClient { readonly rpc: WebSocketRequest; + readonly MAX_TX_NUM_VIN = 256; + constructor( url: string, readonly defaultFinality: 'optimistic' | 'final' = 'optimistic',