From eb73726637419859ccb0f98eb915415b93a72a8d Mon Sep 17 00:00:00 2001 From: ByteZhang Date: Fri, 19 Apr 2024 19:53:34 +0800 Subject: [PATCH] fix: sudt transafer --- .../engine/src/vaults/impl/nervos/Vault.ts | 23 +++++++- .../src/vaults/impl/nervos/types/TokenInfo.ts | 8 +-- .../src/vaults/impl/nervos/utils/xudt.ts | 53 +++++++++++++------ .../src/views/Send/modals/PreSendAmount.tsx | 6 +-- 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/packages/engine/src/vaults/impl/nervos/Vault.ts b/packages/engine/src/vaults/impl/nervos/Vault.ts index 1ba398a2c2d..0566e77471f 100644 --- a/packages/engine/src/vaults/impl/nervos/Vault.ts +++ b/packages/engine/src/vaults/impl/nervos/Vault.ts @@ -285,6 +285,7 @@ export default class Vault extends VaultBase { txSkeleton = await xUDTTransafer( txSkeleton, from, + token, tokenAddress, to, BI.from(amountValue), @@ -453,6 +454,7 @@ export default class Vault extends VaultBase { .isGreaterThan(new BigNumber(1.5 * 100000000)) ) { debugLogger.common.error('Fee is too high, transaction: ', txs); + throw new OneKeyInternalError('Fee is too high'); } @@ -752,11 +754,24 @@ export default class Vault extends VaultBase { config: Config; tokenAddress: string; }) { - const token = await this.engine.ensureTokenInDB( + const tokenDb = await this.engine.ensureTokenInDB( this.networkId, tokenAddress, ); + let token: PartialTokenInfo | undefined; + if (tokenDb) { + token = { + symbol: tokenDb.symbol, + name: tokenDb.name, + decimals: tokenDb.decimals, + }; + } + + if (!token) { + token = await getTokenInfo(tokenAddress, config); + } + if (!token) { return []; } @@ -1019,7 +1034,13 @@ export default class Vault extends VaultBase { config, tokenAddress, }); + + if (actions.length === 0 && tokenActions.length === 0) { + return await Promise.resolve(null); + } + actions = [...actions, ...tokenActions]; + if (tokenActions.length > 0) { existsToken = true; } diff --git a/packages/engine/src/vaults/impl/nervos/types/TokenInfo.ts b/packages/engine/src/vaults/impl/nervos/types/TokenInfo.ts index c3b1946745b..960747183ee 100644 --- a/packages/engine/src/vaults/impl/nervos/types/TokenInfo.ts +++ b/packages/engine/src/vaults/impl/nervos/types/TokenInfo.ts @@ -1,7 +1,9 @@ export type XUDTInfoResponse = { - id: string; - type: string; - attributes: XUDTAttributes; + data: { + id: string; + type: string; + attributes: XUDTAttributes; + }; }; export type XUDTAttributes = { diff --git a/packages/engine/src/vaults/impl/nervos/utils/xudt.ts b/packages/engine/src/vaults/impl/nervos/utils/xudt.ts index 3beab3d3966..89e5299259b 100644 --- a/packages/engine/src/vaults/impl/nervos/utils/xudt.ts +++ b/packages/engine/src/vaults/impl/nervos/utils/xudt.ts @@ -10,10 +10,16 @@ import { minimalCellCapacityCompatible, parseAddress, } from '@ckb-lumos/helpers'; -import axios from 'axios'; +import BigNumber from 'bignumber.js'; +import fetch from 'cross-fetch'; import { List, Set } from 'immutable'; -import { getFiatEndpoint } from '../../../../endpoint'; +import type { Token as IToken } from '@onekeyhq/engine/src/types/token'; + +import { + MinimumTransferBalanceRequiredForSendingAssetError, + OneKeyValidatorError, +} from '../../../../errors'; import { addCellDep } from './script'; @@ -55,6 +61,7 @@ export function packAmount(amount: BIish): HexString { export async function transfer( txSkeleton: TransactionSkeletonType, fromAddress: Address, + token: IToken, xudtToken: Token, toAddress: Address | null | undefined, amount: BIish, @@ -215,6 +222,9 @@ export async function transfer( let _totalCapacity = BI.from(0); let _totalAmount = BI.from(0); + let _totalTokenCapacity = BI.from(0); + let _requiresExtraNativeToken = BI.from(0); + let done = false; for (const { cellCollector } of cellCollectorInfos) { for await (const inputCell of cellCollector.collect()) { @@ -264,6 +274,9 @@ export async function transfer( _totalCapacity = _totalCapacity.add(inputCapacity); _totalAmount = _totalAmount.add(inputAmount); + if (inputCell.cellOutput.type?.args === xudtToken) { + _totalTokenCapacity = _totalTokenCapacity.add(inputCapacity); + } const requiresAmount = _amount; @@ -277,6 +290,7 @@ export async function transfer( minimalCellCapacityCompatible(changeCellWithoutXudt), ); + _requiresExtraNativeToken = targetCapacity.sub(_totalTokenCapacity); if ( _totalCapacity.gt(targetCapacity) && _totalAmount.gte(requiresAmount) @@ -290,8 +304,14 @@ export async function transfer( } } - if (changeAmount.lt(0) || changeCapacity.lt(0)) { - throw new Error('Not enough capacity or amount in from infos!'); + if (!done || changeAmount.lt(0) || changeCapacity.lt(0)) { + throw new MinimumTransferBalanceRequiredForSendingAssetError( + `${new BigNumber(amount.toString()) + .shiftedBy(-token.decimals) + .toString()} ${token.symbol}`, + _requiresExtraNativeToken.div(10 ** 8).toString(), + 'CKB', + ); } const minimalChangeCellWithoutSudtCapacity = BI.from( @@ -350,8 +370,8 @@ export async function getTokenInfo( const scriptHash = utils.computeScriptHash(xudtScript); try { - const response = await axios.get( - `${getFiatEndpoint()}/nervos/xudts/${scriptHash}`, + const response = await fetch( + `https://mainnet-api.explorer.nervos.org/api/v1/xudts/${scriptHash}`, { headers: { 'Content-Type': 'application/vnd.api+json', @@ -360,15 +380,18 @@ export async function getTokenInfo( }, ); - if ( - response.data.attributes.type_script.args.toLowerCase() === - token.toLowerCase() - ) { - return { - name: response.data.attributes.full_name, - symbol: response.data.attributes.symbol, - decimals: parseInt(response.data.attributes.decimal), - }; + if (response.status === 200) { + const res = JSON.parse(await response.text()) as XUDTInfoResponse; + if ( + res.data.attributes.type_script.args.toLowerCase() === + token.toLowerCase() + ) { + return { + name: res.data.attributes.full_name, + symbol: res.data.attributes.symbol, + decimals: parseInt(res.data.attributes.decimal), + }; + } } } catch (error) { // ignore diff --git a/packages/kit/src/views/Send/modals/PreSendAmount.tsx b/packages/kit/src/views/Send/modals/PreSendAmount.tsx index 996bae1d1bb..eee69d4ef65 100644 --- a/packages/kit/src/views/Send/modals/PreSendAmount.tsx +++ b/packages/kit/src/views/Send/modals/PreSendAmount.tsx @@ -41,6 +41,7 @@ import { useTokenBalanceWithoutFrozen, } from '../../../hooks/useOverview'; import { useFrozenBalance, useSingleToken } from '../../../hooks/useTokens'; +import { deviceUtils } from '../../../utils/hardware'; import { wait } from '../../../utils/helper'; import { showAccountBalanceDetailsOverlay, @@ -440,10 +441,7 @@ function PreSendAmount() { { type: 'error' }, ); } else { - ToastManager.show( - { title: typeof e === 'string' ? e : (e as Error).message }, - { type: 'error' }, - ); + deviceUtils.showErrorToast(e); } } finally { setIsLoading(false);