diff --git a/package.json b/package.json index 429a12194d..e3cbe767f7 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "ncp": "2.0.0", "prettier": "2.8.8", "ts-jest": "29.2.0", + "ts-node": "^10.9.2", "typescript": "5.3.3", "wait-on": "7.0.1" }, @@ -66,7 +67,15 @@ "@types/react": "18.2.45", "react-i18next": ">=11.16.4", "react-refresh": "0.14.0", - "node-fetch": "2.6.13" + "node-fetch": "2.6.13", + "@ckb-lumos/ckb-indexer": "0.23.0", + "@ckb-lumos/base": "0.23.0", + "@ckb-lumos/bi": "0.23.0", + "@ckb-lumos/codec": "0.23.0", + "@ckb-lumos/common-scripts": "0.23.0", + "@ckb-lumos/config-manager": "0.23.0", + "@ckb-lumos/lumos": "0.23.0", + "@ckb-lumos/rpc": "0.23.0" }, "volta": { "node": "20.10.0" diff --git a/packages/neuron-ui/.storybook/main.ts b/packages/neuron-ui/.storybook/main.ts index 3cf0dbf366..a8bbc1d2bc 100644 --- a/packages/neuron-ui/.storybook/main.ts +++ b/packages/neuron-ui/.storybook/main.ts @@ -12,6 +12,11 @@ export default { options: {}, }, webpackFinal: config => { + config.resolve.fallback = { + fs: false, + crypto: false, + buffer: false, + } config.resolve.alias = { ...config.resolve.alias, electron: require.resolve('./electron'), diff --git a/packages/neuron-ui/config-overrides.js b/packages/neuron-ui/config-overrides.js index 6222691d70..8ffe287136 100644 --- a/packages/neuron-ui/config-overrides.js +++ b/packages/neuron-ui/config-overrides.js @@ -4,6 +4,10 @@ const path = require('path') module.exports = function override(config) { const webpackConfig = { ...config } webpackConfig.resolve.alias.electron = path.join(__dirname, 'src/electron-modules') - webpackConfig.resolve.fallback = { fs: false } + webpackConfig.resolve.fallback = { + fs: false, + crypto: false, + buffer: false, + } return webpackConfig } diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json index c832d47fd1..633abb7d55 100644 --- a/packages/neuron-ui/package.json +++ b/packages/neuron-ui/package.json @@ -50,14 +50,15 @@ "last 2 chrome versions" ], "dependencies": { - "@ckb-lumos/bi": "0.21.1", - "@ckb-lumos/rpc": "0.21.1", - "@ckb-lumos/base": "0.21.1", - "@ckb-lumos/codec": "0.21.1", - "@ckb-lumos/hd": "0.21.1", - "@ckb-lumos/helpers": "0.21.1", - "@ckb-lumos/config-manager": "0.21.1", - "@ckb-lumos/common-scripts": "0.21.1", + "@ckb-lumos/lumos": "0.23.0", + "@ckb-lumos/bi": "0.23.0", + "@ckb-lumos/rpc": "0.23.0", + "@ckb-lumos/base": "0.23.0", + "@ckb-lumos/codec": "0.23.0", + "@ckb-lumos/hd": "0.23.0", + "@ckb-lumos/helpers": "0.23.0", + "@ckb-lumos/config-manager": "0.23.0", + "@ckb-lumos/common-scripts": "0.23.0", "canvg": "2.0.0", "i18next": "23.7.11", "immer": "9.0.21", diff --git a/packages/neuron-ui/src/components/CellInfoDialog/index.tsx b/packages/neuron-ui/src/components/CellInfoDialog/index.tsx index e75da3363a..df5cdad484 100644 --- a/packages/neuron-ui/src/components/CellInfoDialog/index.tsx +++ b/packages/neuron-ui/src/components/CellInfoDialog/index.tsx @@ -4,7 +4,7 @@ import { calculateUsedCapacity, getExplorerUrl, shannonToCKBFormatter, truncateM import { useTranslation } from 'react-i18next' import Tabs from 'widgets/Tabs' import { type TFunction } from 'i18next' -import { Script } from '@ckb-lumos/base' +import { Script } from '@ckb-lumos/lumos' import Switch from 'widgets/Switch' import { Copy, ExplorerIcon } from 'widgets/Icons/icon' import Alert from 'widgets/Alert' diff --git a/packages/neuron-ui/src/components/CellManagement/cellManagement.module.scss b/packages/neuron-ui/src/components/CellManagement/cellManagement.module.scss index a142528c7e..a36bad6e1e 100644 --- a/packages/neuron-ui/src/components/CellManagement/cellManagement.module.scss +++ b/packages/neuron-ui/src/components/CellManagement/cellManagement.module.scss @@ -53,7 +53,7 @@ .actions { display: flex; gap: 16px; - & > svg { + & svg { cursor: pointer; &[data-disabled='true'] { cursor: not-allowed; diff --git a/packages/neuron-ui/src/components/CellManagement/hooks.ts b/packages/neuron-ui/src/components/CellManagement/hooks.ts index 1823cc98c0..4977cc6ced 100644 --- a/packages/neuron-ui/src/components/CellManagement/hooks.ts +++ b/packages/neuron-ui/src/components/CellManagement/hooks.ts @@ -18,7 +18,8 @@ import { ErrorCode, LockScriptCategory, RoutePath, TypeScriptCategory, isSuccess import { SortType } from 'widgets/Table' const cellTypeOrder: Record = { - [TypeScriptCategory.SUDT]: 1, + [TypeScriptCategory.SUDT]: 0, + [TypeScriptCategory.XUDT]: 1, [TypeScriptCategory.NFT]: 2, [TypeScriptCategory.Spore]: 3, [TypeScriptCategory.Unknown]: 4, @@ -47,6 +48,9 @@ const getLockStatusAndReason = (item: State.LiveCellWithLocalInfo) => { case TypeScriptCategory.DAO: lockedReason = { key: 'cell-manage.locked-reason.NFT-SUDT-DAO', params: { type: 'Nervos DAO' } } break + case TypeScriptCategory.XUDT: + lockedReason = { key: 'cell-manage.locked-reason.NFT-SUDT-DAO', params: { type: 'XUDT' } } + break case TypeScriptCategory.Unknown: lockedReason = { key: 'cell-manage.locked-reason.Unknown' } break @@ -82,6 +86,7 @@ const getCellType = (item: State.LiveCellWithLocalInfo) => { switch (item.typeScriptType) { case TypeScriptCategory.NFT: case TypeScriptCategory.SUDT: + case TypeScriptCategory.XUDT: case TypeScriptCategory.Spore: case TypeScriptCategory.Unknown: return item.typeScriptType diff --git a/packages/neuron-ui/src/components/CellManagement/index.tsx b/packages/neuron-ui/src/components/CellManagement/index.tsx index 186e884d6a..7fbb4860bc 100644 --- a/packages/neuron-ui/src/components/CellManagement/index.tsx +++ b/packages/neuron-ui/src/components/CellManagement/index.tsx @@ -23,7 +23,7 @@ import { TFunction } from 'i18next' import TextField from 'widgets/TextField' import { useSearchParams } from 'react-router-dom' import CellInfoDialog from 'components/CellInfoDialog' -import { computeScriptHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash } from '@ckb-lumos/lumos/utils' import Hardware from 'widgets/Icons/Hardware.png' import Button from 'widgets/Button' import Alert from 'widgets/Alert' @@ -193,7 +193,7 @@ const getColumns = ({ @@ -202,7 +202,7 @@ const getColumns = ({ diff --git a/packages/neuron-ui/src/components/HistoryDetailPage/index.tsx b/packages/neuron-ui/src/components/HistoryDetailPage/index.tsx index 8d6f553ec5..8db87ebf76 100644 --- a/packages/neuron-ui/src/components/HistoryDetailPage/index.tsx +++ b/packages/neuron-ui/src/components/HistoryDetailPage/index.tsx @@ -3,7 +3,7 @@ import { useNavigate, useParams } from 'react-router-dom' import { useTranslation } from 'react-i18next' import { calculateUnlockDaoMaximumWithdraw, getTransaction } from 'services/remote' import { showPageNotice, transactionState, useDispatch, useState as useGlobalState } from 'states' -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import PageContainer from 'components/PageContainer' import LockInfoDialog from 'components/LockInfoDialog' import ScriptTag from 'components/ScriptTag' diff --git a/packages/neuron-ui/src/components/LockInfoDialog/index.tsx b/packages/neuron-ui/src/components/LockInfoDialog/index.tsx index 7e747e18c8..2242042484 100644 --- a/packages/neuron-ui/src/components/LockInfoDialog/index.tsx +++ b/packages/neuron-ui/src/components/LockInfoDialog/index.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next' import React, { useRef } from 'react' -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import Dialog from 'widgets/Dialog' import { useCopy, useDialog, scriptToAddress } from 'utils' import { Copy } from 'widgets/Icons/icon' diff --git a/packages/neuron-ui/src/components/MultisigAddress/hooks.ts b/packages/neuron-ui/src/components/MultisigAddress/hooks.ts index d5a431f22c..9c3b55bca4 100644 --- a/packages/neuron-ui/src/components/MultisigAddress/hooks.ts +++ b/packages/neuron-ui/src/components/MultisigAddress/hooks.ts @@ -15,7 +15,7 @@ import { OfflineSignJSON, getMultisigSyncProgress, } from 'services/remote' -import { computeScriptHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash } from '@ckb-lumos/lumos/utils' export const useSearch = (clearSelected: () => void, onFilterConfig: (searchKey: string) => void) => { const [keywords, setKeywords] = useState('') diff --git a/packages/neuron-ui/src/components/NervosDAO/hooks.ts b/packages/neuron-ui/src/components/NervosDAO/hooks.ts index 93498cadf1..e0e900c72c 100644 --- a/packages/neuron-ui/src/components/NervosDAO/hooks.ts +++ b/packages/neuron-ui/src/components/NervosDAO/hooks.ts @@ -3,12 +3,12 @@ import { AppActions, StateAction } from 'states/stateProvider/reducer' import { updateNervosDaoData, clearNervosDaoData } from 'states/stateProvider/actionCreators' import { NavigateFunction } from 'react-router-dom' -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import { calculateAPC, CONSTANTS, isSuccessResponse, RoutePath } from 'utils' import { rpc, getHeader } from 'services/chain' import { generateDaoWithdrawTx, generateDaoClaimTx } from 'services/remote' -import { calculateMaximumWithdrawCompatible } from '@ckb-lumos/common-scripts/lib/dao' +import { calculateMaximumWithdrawCompatible } from '@ckb-lumos/lumos/common-scripts/dao' const { MILLISECONDS_IN_YEAR, MEDIUM_FEE_RATE } = CONSTANTS @@ -337,7 +337,7 @@ export const useUpdateDepositEpochList = ({ useEffect(() => { if (connectionStatus === 'online') { getBlockHashes(records.map(v => v.depositOutPoint?.txHash).filter(v => !!v) as string[]).then( - (depositBlockHashes: { txHash: string; blockHash: string | null }[]) => { + (depositBlockHashes: { txHash: string; blockHash: string | undefined }[]) => { const recordKeyIdx: string[] = [] const batchParams: ['getHeader', string][] = [] records.forEach(record => { diff --git a/packages/neuron-ui/src/components/NervosDAODetail/CellsCard/index.tsx b/packages/neuron-ui/src/components/NervosDAODetail/CellsCard/index.tsx index bb8af67050..d22f3f49ee 100644 --- a/packages/neuron-ui/src/components/NervosDAODetail/CellsCard/index.tsx +++ b/packages/neuron-ui/src/components/NervosDAODetail/CellsCard/index.tsx @@ -1,6 +1,6 @@ import React, { FC, useMemo, useState } from 'react' import Tabs, { VariantProps } from 'widgets/Tabs' -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import { clsx, localNumberFormatter, shannonToCKBFormatter, scriptToAddress, isMainnet as isMainnetUtils } from 'utils' import { useTranslation } from 'react-i18next' import { onEnter } from 'utils/inputDevice' diff --git a/packages/neuron-ui/src/components/NervosDAORecord/hooks.ts b/packages/neuron-ui/src/components/NervosDAORecord/hooks.ts index 784a90bc98..a3531451cd 100644 --- a/packages/neuron-ui/src/components/NervosDAORecord/hooks.ts +++ b/packages/neuron-ui/src/components/NervosDAORecord/hooks.ts @@ -1,7 +1,7 @@ import { useEffect } from 'react' import { getHeader } from 'services/chain' import { calculateAPC, CONSTANTS } from 'utils' -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' const { MILLISECONDS_IN_YEAR } = CONSTANTS diff --git a/packages/neuron-ui/src/components/SUDTAccountList/index.tsx b/packages/neuron-ui/src/components/SUDTAccountList/index.tsx index fa4f6972ef..b961ca079d 100644 --- a/packages/neuron-ui/src/components/SUDTAccountList/index.tsx +++ b/packages/neuron-ui/src/components/SUDTAccountList/index.tsx @@ -24,6 +24,7 @@ import { isSuccessResponse, useIsInsufficientToCreateSUDTAccount, useOnGenerateNewAccountTransaction, + UDTType, } from 'utils' import { getSUDTAccountList, updateSUDTAccount } from 'services/remote' @@ -48,7 +49,11 @@ const SUDTAccountList = () => { const [keyword, setKeyword] = useState('') const [dialog, setDialog] = useState<{ id: string; action: 'create' | 'update' } | null>(null) const [isLoaded, setIsLoaded] = useState(false) - const [insufficient, setInsufficient] = useState({ [AccountType.CKB]: false, [AccountType.SUDT]: false }) + const [insufficient, setInsufficient] = useState({ + [AccountType.CKB]: false, + [AccountType.SUDT]: false, + [AccountType.XUDT]: false, + }) const isMainnet = isMainnetUtil(networks, networkID) const [receiveData, setReceiveData] = useState(null) @@ -178,6 +183,7 @@ const SUDTAccountList = () => { tokenName: accountToUpdate.tokenName || DEFAULT_SUDT_FIELDS.tokenName, symbol: accountToUpdate.symbol || DEFAULT_SUDT_FIELDS.symbol, isCKB: accountToUpdate.tokenId === DEFAULT_SUDT_FIELDS.CKBTokenId, + udtType: accountToUpdate.udtType, onSubmit: (info: Omit) => { const params: any = { id: accountToUpdate.accountId } Object.keys(info).forEach(key => { @@ -208,7 +214,7 @@ const SUDTAccountList = () => { : undefined const handleCreateAccount = useCallback( - (info: TokenInfo) => { + (info: TokenInfo & { udtType?: UDTType }) => { createAccount(info, () => { setNotice(t('s-udt.create-account-success')) }) diff --git a/packages/neuron-ui/src/components/SUDTCreateDialog/index.tsx b/packages/neuron-ui/src/components/SUDTCreateDialog/index.tsx index fa9c5a0b19..c4710b31c8 100644 --- a/packages/neuron-ui/src/components/SUDTCreateDialog/index.tsx +++ b/packages/neuron-ui/src/components/SUDTCreateDialog/index.tsx @@ -10,13 +10,15 @@ import { isSuccessResponse, useSUDTAccountInfoErrors, useFetchTokenInfoList, - useOpenSUDTTokenUrl, + useOpenUDTTokenUrl, + UDTType, } from 'utils' import { DEFAULT_SUDT_FIELDS } from 'utils/const' import styles from './sUDTCreateDialog.module.scss' export enum AccountType { SUDT = 'sudt', + XUDT = 'xudt', CKB = 'ckb', } @@ -33,10 +35,10 @@ export interface TokenInfo extends BasicInfo { export interface SUDTCreateDialogProps extends TokenInfo { isMainnet: boolean - onSubmit: (info: TokenInfo) => void + onSubmit: (info: TokenInfo & { udtType?: UDTType }) => void onCancel: () => void existingAccountNames?: string[] - insufficient?: { [AccountType.CKB]: boolean; [AccountType.SUDT]: boolean } + insufficient?: { [P in AccountType]: boolean } } enum DialogSection { @@ -49,6 +51,10 @@ const accountTypes: { key: AccountType; label: string }[] = [ key: AccountType.SUDT, label: 's-udt.create-dialog.sudt-account', }, + { + key: AccountType.XUDT, + label: 's-udt.create-dialog.xudt-account', + }, { key: AccountType.CKB, label: 's-udt.create-dialog.ckb-account', @@ -121,13 +127,18 @@ const SUDTCreateDialog = ({ onSubmit, onCancel, existingAccountNames = [], - insufficient = { [AccountType.CKB]: false, [AccountType.SUDT]: false }, + insufficient = { [AccountType.CKB]: false, [AccountType.SUDT]: false, [AccountType.XUDT]: false }, isMainnet, }: Partial> & Pick) => { const [t] = useTranslation() const [info, dispatch] = useReducer(reducer, { accountName, tokenId, tokenName, symbol, decimal }) - const [accountType, setAccountType] = useState([AccountType.SUDT, AccountType.CKB].find(at => !insufficient[at])) + const [accountType, setAccountType] = useState( + [AccountType.SUDT, AccountType.CKB, AccountType.XUDT].find(at => !insufficient[at]) + ) + const isUDT = accountType === AccountType.SUDT || accountType === AccountType.XUDT + // eslint-disable-next-line no-nested-ternary + const udtType = isUDT ? (accountType === AccountType.SUDT ? UDTType.SUDT : UDTType.XUDT) : undefined const [step, setStep] = useState(DialogSection.Account) const tokenInfoList = useFetchTokenInfoList() @@ -135,9 +146,10 @@ const SUDTCreateDialog = ({ const tokenErrors = useSUDTAccountInfoErrors({ info, - isCKB: AccountType.CKB === accountType, + isCKB: !isUDT, existingAccountNames, t, + udtType, }) const isAccountNameReady = info.accountName.trim() && !tokenErrors.accountName && accountType @@ -190,7 +202,7 @@ const SUDTCreateDialog = ({ } case DialogSection.Token: { if (isTokenReady) { - onSubmit({ ...info, accountName: info.accountName.trim(), tokenName: info.tokenName.trim() }) + onSubmit({ ...info, udtType, accountName: info.accountName.trim(), tokenName: info.tokenName.trim() }) } break } @@ -216,7 +228,7 @@ const SUDTCreateDialog = ({ } } } - const openSUDTTokenUrl = useOpenSUDTTokenUrl(info.tokenId, isMainnet) + const openSUDTTokenUrl = useOpenUDTTokenUrl(info.tokenId, udtType, isMainnet) return ( ))} - {accountType === AccountType.SUDT && !tokenErrors.tokenId && info.tokenId && ( + {isUDT && !tokenErrors.tokenId && info.tokenId && ( )} diff --git a/packages/neuron-ui/src/components/ScriptTag/index.tsx b/packages/neuron-ui/src/components/ScriptTag/index.tsx index b93b91ae40..a6ddd7f0e5 100644 --- a/packages/neuron-ui/src/components/ScriptTag/index.tsx +++ b/packages/neuron-ui/src/components/ScriptTag/index.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import { MultiSigLockInfo, LocktimeLockInfo, diff --git a/packages/neuron-ui/src/components/Send/hooks.ts b/packages/neuron-ui/src/components/Send/hooks.ts index f631045253..14f77fb349 100644 --- a/packages/neuron-ui/src/components/Send/hooks.ts +++ b/packages/neuron-ui/src/components/Send/hooks.ts @@ -1,6 +1,6 @@ import React, { useState, useCallback, useEffect, useMemo } from 'react' import { TFunction } from 'i18next' -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import { AppActions, StateDispatch } from 'states/stateProvider/reducer' import { generateTx, generateSendingAllTx } from 'services/remote/wallets' import { ControllerResponse, SuccessFromController } from 'services/remote/remoteApiWrapper' diff --git a/packages/neuron-ui/src/components/SpecialAssetList/hooks.ts b/packages/neuron-ui/src/components/SpecialAssetList/hooks.ts index 206ea8ceb1..d1ff65cc43 100644 --- a/packages/neuron-ui/src/components/SpecialAssetList/hooks.ts +++ b/packages/neuron-ui/src/components/SpecialAssetList/hooks.ts @@ -1,6 +1,6 @@ import React, { useCallback, useEffect } from 'react' -import { number, bytes } from '@ckb-lumos/codec' -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { bytes, Uint64LE } from '@ckb-lumos/lumos/codec' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import { getSUDTAccountList } from 'services/remote' import { NeuronWalletActions, useDispatch } from 'states' import { @@ -145,7 +145,7 @@ export const useSpecialAssetColumnInfo = ({ switch (assetInfo.lock) { case PresetScript.Locktime: { - const targetEpochInfo = epochParser(bytes.hexify(number.Uint64LE.pack(`0x${lock.args.slice(-16)}`))) + const targetEpochInfo = epochParser(bytes.hexify(Uint64LE.pack(`0x${lock.args.slice(-16)}`))) const currentEpochInfo = epochParser(epoch) const targetEpochFraction = Number(targetEpochInfo.length) > 0 ? Number(targetEpochInfo.index) / Number(targetEpochInfo.length) : 1 @@ -180,13 +180,6 @@ export const useSpecialAssetColumnInfo = ({ } break } - case PresetScript.SUDT: { - status = 'user-defined-token' - const tokenInfo = tokenInfoList.find(info => info.tokenID === type?.args) - const amountInfo = getSUDTAmount({ tokenInfo, data }) - amount = amountInfo.amount - break - } default: { // ignore } @@ -220,6 +213,14 @@ export const useSpecialAssetColumnInfo = ({ amount = t('special-assets.unknown-asset') break } + case PresetScript.XUDT: + case PresetScript.SUDT: { + status = 'user-defined-token' + const tokenInfo = tokenInfoList.find(info => info.tokenID === type?.args) + const amountInfo = getSUDTAmount({ tokenInfo, data }) + amount = amountInfo.amount + break + } default: { break } @@ -235,6 +236,7 @@ export const useSpecialAssetColumnInfo = ({ epochsInfo, isSpore, sporeClusterInfo, + udtType: assetInfo.type, } }, [epoch, bestKnownBlockTimestamp, tokenInfoList, t] diff --git a/packages/neuron-ui/src/components/SpecialAssetList/index.tsx b/packages/neuron-ui/src/components/SpecialAssetList/index.tsx index 171aa745cb..7f4c5eb6b9 100644 --- a/packages/neuron-ui/src/components/SpecialAssetList/index.tsx +++ b/packages/neuron-ui/src/components/SpecialAssetList/index.tsx @@ -238,6 +238,7 @@ const SpecialAssetList = () => { symbol: (accountToClaim.account.symbol || foundTokenInfo?.symbol) ?? '', decimal: (accountToClaim.account.decimal || foundTokenInfo?.decimal) ?? '', isCKB: false, + udtType: accountToClaim.account.udtType, onSubmit: (info: Omit) => { const params: any = accountToClaim?.account || {} Object.keys(info).forEach(key => { @@ -371,6 +372,12 @@ const SpecialAssetList = () => { } break } + default: { + // ignore + } + } + switch (cell.customizedAssetInfo.type) { + case PresetScript.XUDT: case PresetScript.SUDT: { setMigrateCell(cell) const findTokenInfo = tokenInfoList.find(info => info.tokenID === cell.type?.args) @@ -379,9 +386,8 @@ const SpecialAssetList = () => { setIsMigrateDialogOpen(true) break } - default: { - // ignore - } + default: + break } }, [cells, id, dispatch, setAccountToClaim, navigate, setIsMigrateDialogOpen, tokenInfoList, handleActionSuccess] @@ -437,8 +443,15 @@ const SpecialAssetList = () => { customizedAssetInfo, } = item - const { status, targetTime, isLockedCheque, isNFTTransferable, isNFTClassOrIssuer, epochsInfo } = - handleGetSpecialAssetColumnInfo(item) + const { + status, + targetTime, + isLockedCheque, + isNFTTransferable, + isNFTClassOrIssuer, + epochsInfo, + udtType, + } = handleGetSpecialAssetColumnInfo(item) if (isNFTClassOrIssuer || (customizedAssetInfo.type === NFTType.NFT && !isNFTTransferable)) { return ( @@ -458,22 +471,15 @@ const SpecialAssetList = () => { ['user-defined-asset', 'locked-asset', 'user-defined-token'].includes(status) || isLockedCheque if (showTip) { - if (customizedAssetInfo.lock !== PresetScript.Cheque || isLockedCheque) { - tip = t(`special-assets.${status}-tooltip`, { - epochs: epochsInfo?.target.toFixed(2), - year: targetTime ? new Date(targetTime).getFullYear() : '', - month: targetTime ? new Date(targetTime).getMonth() + 1 : '', - day: targetTime ? new Date(targetTime).getDate() : '', - hour: targetTime ? new Date(targetTime).getHours() : '', - minute: targetTime ? new Date(targetTime).getMinutes() : '', - }) - } - if (status === 'user-defined-token') { - tip = t('special-assets.user-defined-asset-tooltip') - } - if (status === 'user-defined-token') { - tip = t('special-assets.user-defined-token-tooltip') - } + tip = t(`special-assets.${status}-tooltip`, { + udtType, + epochs: epochsInfo?.target.toFixed(2), + year: targetTime ? new Date(targetTime).getFullYear() : '', + month: targetTime ? new Date(targetTime).getMonth() + 1 : '', + day: targetTime ? new Date(targetTime).getDate() : '', + hour: targetTime ? new Date(targetTime).getHours() : '', + minute: targetTime ? new Date(targetTime).getMinutes() : '', + }) } const btnDisabled = @@ -490,7 +496,7 @@ const SpecialAssetList = () => { data-idx={index} data-status={status} type="primary" - label={t(`special-assets.${status}`)} + label={t(`special-assets.${status}`, { udtType })} className={styles.actionBtn} onClick={handleAction} disabled={!!btnDisabled} diff --git a/packages/neuron-ui/src/components/TransactionType/index.tsx b/packages/neuron-ui/src/components/TransactionType/index.tsx index 59ed2b91ab..068702b92f 100644 --- a/packages/neuron-ui/src/components/TransactionType/index.tsx +++ b/packages/neuron-ui/src/components/TransactionType/index.tsx @@ -74,7 +74,7 @@ const TransactionType = ({ i18nKey: `overview.${item.type}SUDT`, components: [ , diff --git a/packages/neuron-ui/src/components/WithdrawDialog/index.tsx b/packages/neuron-ui/src/components/WithdrawDialog/index.tsx index 7d83c98df8..02a0756012 100644 --- a/packages/neuron-ui/src/components/WithdrawDialog/index.tsx +++ b/packages/neuron-ui/src/components/WithdrawDialog/index.tsx @@ -5,7 +5,7 @@ import { CONSTANTS, shannonToCKBFormatter, localNumberFormatter, useCalculateEpo import { getTransaction, getHeader } from 'services/chain' import Dialog from 'widgets/Dialog' import { Attention } from 'widgets/Icons/icon' -import { calculateMaximumWithdrawCompatible } from '@ckb-lumos/common-scripts/lib/dao' +import { calculateMaximumWithdrawCompatible } from '@ckb-lumos/lumos/common-scripts/dao' import styles from './withdrawDialog.module.scss' const { WITHDRAW_EPOCHS } = CONSTANTS diff --git a/packages/neuron-ui/src/locales/en.json b/packages/neuron-ui/src/locales/en.json index db85a72669..a500247b60 100644 --- a/packages/neuron-ui/src/locales/en.json +++ b/packages/neuron-ui/src/locales/en.json @@ -516,10 +516,10 @@ "title": "Create Asset Account" }, "send-sudt": { - "title": "Send sUDT" + "title": "Send UDT" }, "transfer-to-sudt": { - "title": "Send to sUDT account" + "title": "Send to UDT account" }, "send-ckb-asset": { "title": "Send CKB" @@ -528,7 +528,7 @@ "title": "Send CKB" }, "send-acp-sudt-to-new-cell": { - "title": "Send sUDT" + "title": "Send UDT" }, "send-acp-ckb-to-new-cell": { "title": "Send CKB" @@ -960,7 +960,7 @@ "locked-asset": "Locked", "locked-asset-tooltip": "Lock parameter is {{epochs}} epochs, estimated release date is {{year}}-{{month}}-{{day}}(according to the actual running block height, there may be some time variances in locktime).", "withdraw-asset-tooltip": "Estimate release time is {{year}}-{{month}}-{{day}} {{hour}}:{{minute}}(according to the actual running block height).", - "user-defined-token-tooltip": "Migrate sUDT asset to a sUDT Asset Account", + "user-defined-token-tooltip": "Migrate {{udtType}} asset to a {{udtType}} Asset Account", "claim-asset": "Claim", "withdraw-asset": "Withdraw", "view-details": "View Details", @@ -971,14 +971,14 @@ "transfer-nft": "Send", "user-defined-token": "Migrate", "transfer-nft-success": "Transfer of assets successful", - "migrate-sudt-success": "Conversion to new sUDT asset account successful", - "send-sudt-success": "Transfer to sUDT account successful", + "migrate-sudt-success": "Conversion to new {{udtType}} asset account successful", + "send-sudt-success": "Transfer to {{udtType}} account successful", "unlock-success": "Asset claimed, go to transaction history for details", "withdraw-cheque-success": "Asset withdrawn, go to transaction history for details", "claim-cheque-success": "Asset claimed, go to transaction history for details" }, "migrate-sudt": { - "title": "Migrate to a sUDT Asset Account", + "title": "Migrate to a {{udtType}} Asset Account", "choose-title": "Migration mode", "next": "Next", "back": "Back", @@ -986,14 +986,14 @@ "input-symbol": "Please input symbol", "input-decimal": "Please input decimal", "turn-into-new-account": { - "title": "Turn into a new sUDT Asset Account", - "sub-title": "Turn the sUDT Asset into a new sUDT Account, occupies at least 142 CKBytes", + "title": "Turn into a new {{udtType}} Asset Account", + "sub-title": "Turn the {{udtType}} Asset into a new {{udtType}} Account, occupies at least 142 CKBytes", "cancel": "Cancel", "confirm": "Confirm" }, "transfer-to-exist-account": { - "title": "Transfer to a sUDT Asset Account", - "sub-title": "Transfer all sUDT balance to an existing sUDT Account, please make sure the target account is alive" + "title": "Transfer to a {{udtType}} Asset Account", + "sub-title": "Transfer all {{udtType}} balance to an existing {{udtType}} Account, please make sure the target account is alive" }, "cancel": "Cancel", "confirm": "Confirm", @@ -1019,6 +1019,7 @@ "select-account-type": "Select account type", "account-name": "Account Name", "sudt-account": "sUDT Account", + "xudt-account": "xUDT Account", "delete-failed": "Failed to delete the multisig config, reason for failure: {{reason}}", "ckb-account": "CKB Account", "set-token-info": "Set Token Info", @@ -1040,7 +1041,7 @@ "decimal": "Please input decimal" }, "placeholder": { - "token-id": "Token ID is the Args of the sUDT Type Script, which is the same as the lock hash of the token issuer." + "token-id": "Token ID is the Args of the {{udtType}} Type Script, which is the same as the lock hash of the token issuer." } }, "send": { diff --git a/packages/neuron-ui/src/locales/es.json b/packages/neuron-ui/src/locales/es.json index 6e2fd2f7cc..94b69501d7 100644 --- a/packages/neuron-ui/src/locales/es.json +++ b/packages/neuron-ui/src/locales/es.json @@ -499,10 +499,10 @@ "title": "Crear Cuenta de Activos" }, "send-sudt": { - "title": "Enviar sUDT" + "title": "Enviar UDT" }, "transfer-to-sudt": { - "title": "Enviar a cuenta sUDT" + "title": "Enviar a cuenta UDT" }, "send-ckb-asset": { "title": "Enviar CKB" @@ -511,7 +511,7 @@ "title": "Enviar CKB" }, "send-acp-sudt-to-new-cell": { - "title": "Enviar sUDT" + "title": "Enviar UDT" }, "send-acp-ckb-to-new-cell": { "title": "Enviar CKB" @@ -943,7 +943,7 @@ "locked-asset": "Bloqueado", "locked-asset-tooltip": "El parámetro de bloqueo es de {{epochs}} épocas, la fecha de lanzamiento estimada es {{year}}-{{month}}-{{day}} (según la altura del bloque en ejecución real, pueden haber algunas variaciones de tiempo en el tiempo de bloqueo).", "withdraw-asset-tooltip": "Hora estimada de lanzamiento es {{year}}-{{month}}-{{day}} {{hour}}:{{minute}} (según la altura del bloque en ejecución real).", - "user-defined-token-tooltip": "Migre el activo sUDT a una cuenta de activos sUDT", + "user-defined-token-tooltip": "Migre el activo {{udtType}} a una cuenta de activos {{udtType}}", "claim-asset": "Reclamar", "withdraw-asset": "Retirar", "view-details": "Ver detalles", @@ -954,14 +954,14 @@ "transfer-nft": "Enviar", "user-defined-token": "Migrar", "transfer-nft-success": "Transferencia de activos exitosa", - "migrate-sudt-success": "Conversión a nueva cuenta de activo sUDT exitosa", - "send-sudt-success": "Transferencia exitosa a la cuenta de activo sUDT", + "migrate-sudt-success": "Conversión a nueva cuenta de activo {{udtType}} exitosa", + "send-sudt-success": "Transferencia exitosa a la cuenta de activo {{udtType}}", "unlock-success": "Activo reclamado. Vaya al historial de transacciones para obtener más detalles.", "withdraw-cheque-success": "El activo fue retirado. Vaya al historial de transacciones para obtener más detalles.", "claim-cheque-success": "Activo reclamado. Vaya al historial de transacciones para obtener más detalles." }, "migrate-sudt": { - "title": "Migrar a una cuenta de activo sUDT", + "title": "Migrar a una cuenta de activo {{udtType}}", "choose-title": "Modo de migración", "next": "Siguiente", "back": "Atrás", @@ -969,14 +969,14 @@ "input-symbol": "Por favor ingrese el símbolo", "input-decimal": "Por favor ingrese el decimal", "turn-into-new-account": { - "title": "Conviértalo en una nueva cuenta de activo sUDT", - "sub-title": "Convierta el activo sUDT en una nueva cuenta sUDT, ocupa al menos 142 CKbytes.", + "title": "Conviértalo en una nueva cuenta de activo {{udtType}}", + "sub-title": "Convierta el activo {{udtType}} en una nueva cuenta {{udtType}}, ocupa al menos 142 CKbytes.", "cancel": "Cancelar", "confirm": "Confirmar" }, "transfer-to-exist-account": { - "title": "Transferir a una cuenta de activo sUDT", - "sub-title": "Transfiera todo el saldo sUDT a una cuenta sUDT existente. Asegúrese de que la cuenta objetivo esté activa." + "title": "Transferir a una cuenta de activo {{udtType}}", + "sub-title": "Transfiera todo el saldo {{udtType}} a una cuenta {{udtType}} existente. Asegúrese de que la cuenta objetivo esté activa." }, "cancel": "Cancelar", "confirm": "Confirmar", @@ -1002,6 +1002,7 @@ "select-account-type": "Seleccione el tipo de cuenta", "account-name": "Nombre de la cuenta", "sudt-account": "Cuenta de activos sUDT", + "xudt-account": "Cuenta de activos xUDT", "delete-failed": "No se pudo eliminar la configuración multifirma, el motivo del fallo: {{reason}}", "ckb-account": "Cuenta CKB", "set-token-info": "Establecer información del token", @@ -1023,7 +1024,7 @@ "decimal": "Ingrese el decimal" }, "placeholder": { - "token-id": "El ID del token es el Args del sUDT Type Script, que es el mismo que el hash de bloqueo del emisor del token." + "token-id": "El ID del token es el Args del {{udtType}} Type Script, que es el mismo que el hash de bloqueo del emisor del token." } }, "send": { diff --git a/packages/neuron-ui/src/locales/fr.json b/packages/neuron-ui/src/locales/fr.json index ec0df27270..39b46403ba 100644 --- a/packages/neuron-ui/src/locales/fr.json +++ b/packages/neuron-ui/src/locales/fr.json @@ -506,10 +506,10 @@ "title": "Créer un compte d'actif" }, "send-sudt": { - "title": "Envoyer sUDT" + "title": "Envoyer UDT" }, "transfer-to-sudt": { - "title": "Envoyer vers le compte sUDT" + "title": "Envoyer vers le compte UDT" }, "send-ckb-asset": { "title": "Envoyer CKB" @@ -518,7 +518,7 @@ "title": "Envoyer CKB" }, "send-acp-sudt-to-new-cell": { - "title": "Envoyer sUDT" + "title": "Envoyer UDT" }, "send-acp-ckb-to-new-cell": { "title": "Envoyer CKB" @@ -950,7 +950,7 @@ "locked-asset": "Verrouillé", "locked-asset-tooltip": "Le paramètre de verrouillage est de {{epochs}} époques, la date de libération estimée est le {{year}}-{{month}}-{{day}} (selon la hauteur de bloc réelle en cours d'exécution, il peut y avoir des variances de temps dans le verrouillage).", "withdraw-asset-tooltip": "L'heure de libération estimée est le {{year}}-{{month}}-{{day}} à {{hour}}:{{minute}} (selon la hauteur de bloc réelle en cours d'exécution).", - "user-defined-token-tooltip": "Migrer l'actif sUDT vers un compte d'actif sUDT", + "user-defined-token-tooltip": "Migrer l'actif {{udtType}} vers un compte d'actif {{udtType}}", "claim-asset": "Réclamation", "withdraw-asset": "Retrait", "view-details": "Voir les détails", @@ -961,14 +961,14 @@ "transfer-nft": "Envoyer", "user-defined-token": "Migrer", "transfer-nft-success": "Transfert d'actifs réussi", - "migrate-sudt-success": "Conversion en nouveau compte d'actif sUDT réussie", - "send-sudt-success": "Transfert vers le compte sUDT réussi", + "migrate-sudt-success": "Conversion en nouveau compte d'actif {{udtType}} réussie", + "send-sudt-success": "Transfert vers le compte {{udtType}} réussi", "unlock-success": "Actif réclamé, consultez l'historique des transactions pour plus de détails", "withdraw-cheque-success": "Actif retiré, consultez l'historique des transactions pour plus de détails", "claim-cheque-success": "Actif réclamé, consultez l'historique des transactions pour plus de détails" }, "migrate-sudt": { - "title": "Migrer vers un compte d'actif sUDT", + "title": "Migrer vers un compte d'actif {{udtType}}", "choose-title": "Mode de migration", "next": "Suivant", "back": "Retour", @@ -976,14 +976,14 @@ "input-symbol": "Veuillez saisir le symbole", "input-decimal": "Veuillez saisir la décimale", "turn-into-new-account": { - "title": "Transformez en un nouveau compte d'actif sUDT", - "sub-title": "Transformez l'actif sUDT en un nouveau compte sUDT, occupe au moins 142 CKBytes", + "title": "Transformez en un nouveau compte d'actif {{udtType}}", + "sub-title": "Transformez l'actif {{udtType}} en un nouveau compte {{udtType}}, occupe au moins 142 CKBytes", "cancel": "Annuler", "confirm": "Confirmer" }, "transfer-to-exist-account": { - "title": "Transférer vers un compte d'actif sUDT", - "sub-title": "Transférez tout le solde sUDT vers un compte sUDT existant, assurez-vous que le compte cible est actif" + "title": "Transférer vers un compte d'actif {{udtType}}", + "sub-title": "Transférez tout le solde {{udtType}} vers un compte {{udtType}} existant, assurez-vous que le compte cible est actif" }, "cancel": "Annuler", "confirm": "Confirmer", @@ -1009,6 +1009,7 @@ "select-account-type": "Sélectionner le type de compte", "account-name": "Nom du compte", "sudt-account": "Compte sUDT", + "xudt-account": "Compte xUDT", "delete-failed": "Échec de la suppression de la configuration multisig, raison de l'échec : {{reason}}", "ckb-account": "Compte CKB", "set-token-info": "Définir les informations du token", @@ -1030,7 +1031,7 @@ "decimal": "Veuillez saisir la décimale" }, "placeholder": { - "token-id": "L'ID du token est l'argument du script de type sUDT, qui est identique au hachage de verrouillage de l'émetteur du token." + "token-id": "L'ID du token est l'argument du script de type {{udtType}}, qui est identique au hachage de verrouillage de l'émetteur du token." } }, "send": { diff --git a/packages/neuron-ui/src/locales/zh-tw.json b/packages/neuron-ui/src/locales/zh-tw.json index 0bb1ea2f02..491f51fad9 100644 --- a/packages/neuron-ui/src/locales/zh-tw.json +++ b/packages/neuron-ui/src/locales/zh-tw.json @@ -510,10 +510,10 @@ "title": "創建資產賬戶" }, "send-sudt": { - "title": "發起 sUDT 交易" + "title": "發起 UDT 交易" }, "transfer-to-sudt": { - "title": "發起 sUDT 交易" + "title": "發起 UDT 交易" }, "send-ckb-asset": { "title": "發起 CKB 交易" @@ -522,7 +522,7 @@ "title": "發起 CKB 交易" }, "send-acp-sudt-to-new-cell": { - "title": "發起 sUDT 交易" + "title": "發起 UDT 交易" }, "send-acp-ckb-to-new-cell": { "title": "發起 CKB 交易" @@ -954,7 +954,7 @@ "locked-asset": "已鎖定", "locked-asset-tooltip": "鎖定參數為 {{epochs}} epochs, 預計解鎖時間為 {{year}}年{{month}}月{{day}}日(鎖定時間根據區塊鏈實際運行情況會有一定的誤差)。", "withdraw-asset-tooltip": "預計解鎖時間為 {{year}}年{{month}}月{{day}}日 {{hour}}時{{minute}}分(根據區塊鏈實際運行情況會有一定的誤差)。", - "user-defined-token-tooltip": "將 sUDT 資產轉移到 sUDT 賬戶", + "user-defined-token-tooltip": "將 {{udtType}} 資產轉移到 {{udtType}} 賬戶", "claim-asset": "領取", "withdraw-asset": "撤回", "view-details": "查看詳情", @@ -965,14 +965,14 @@ "transfer-nft": "轉讓", "user-defined-token": "遷移", "transfer-nft-success": "轉讓資產成功", - "migrate-sudt-success": "轉換成新的 sUDT 資產帳戶成功", - "send-sudt-success": "轉入 sUDT 帳戶成功", + "migrate-sudt-success": "轉換成新的 {{udtType}} 資產帳戶成功", + "send-sudt-success": "轉入 {{udtType}} 帳戶成功", "unlock-success": "資產已領取,可前往交易歷史查看詳情", "withdraw-cheque-success": "資產已撤回,可前往交易歷史查看詳情", "claim-cheque-success": "資產已領取,可前往交易歷史查看詳情" }, "migrate-sudt": { - "title": "遷移至 sUDT 資產賬戶", + "title": "遷移至 {{udtType}} 資產賬戶", "choose-title": "選擇遷移方式", "next": "下一步", "back": "上一步", @@ -980,14 +980,14 @@ "input-symbol": "請輸入簡稱", "input-decimal": "請輸入小數位", "turn-into-new-account": { - "title": "轉換成新的 sUDT 資產賬戶", - "sub-title": "將 sUDT 資產轉換成 sUDT 資產賬戶, 至少占用 142 CKBytes", + "title": "轉換成新的 {{udtType}} 資產賬戶", + "sub-title": "將 {{udtType}} 資產轉換成 {{udtType}} 資產賬戶, 至少占用 142 CKBytes", "cancel": "取消", "confirm": "確認" }, "transfer-to-exist-account": { - "title": "轉入 sUDT 賬戶", - "sub-title": "將全部 sUDT 余額轉入已存在的 sUDT 資產賬戶, 請確保目標賬戶存在" + "title": "轉入 {{udtType}} 賬戶", + "sub-title": "將全部 {{udtType}} 余額轉入已存在的 {{udtType}} 資產賬戶, 請確保目標賬戶存在" }, "cancel": "取消", "confirm": "確認", @@ -1013,6 +1013,7 @@ "select-account-type": "選擇帳戶類型", "account-name": "賬戶名稱", "sudt-account": "sUDT 賬戶", + "xudt-account": "xUDT 賬戶", "ckb-account": "CKB 賬戶", "set-token-info": "設置代幣信息", "token-id": "代幣ID", @@ -1033,7 +1034,7 @@ "decimal": "請輸入小數位" }, "placeholder": { - "token-id": "代幣 ID 即 sUDT Type Script 的 Args,等同於該 token 發行者的 lock hash。" + "token-id": "代幣 ID 即 {{udtType}} Type Script 的 Args,等同於該 token 發行者的 lock hash。" } }, "send": { diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json index 9481f370b7..ec23a10763 100644 --- a/packages/neuron-ui/src/locales/zh.json +++ b/packages/neuron-ui/src/locales/zh.json @@ -509,10 +509,10 @@ "title": "创建资产账户" }, "send-sudt": { - "title": "发起 sUDT 交易" + "title": "发起 UDT 交易" }, "transfer-to-sudt": { - "title": "转入 sUDT 账户" + "title": "转入 UDT 账户" }, "send-ckb-asset": { "title": "发起 CKB 交易" @@ -521,7 +521,7 @@ "title": "发起 CKB 交易" }, "send-acp-sudt-to-new-cell": { - "title": "发起 sUDT 交易" + "title": "发起 UDT 交易" }, "send-acp-ckb-to-new-cell": { "title": "发起 CKB 交易" @@ -953,7 +953,7 @@ "locked-asset": "已锁定", "locked-asset-tooltip": "锁定参数为 {{epochs}} epochs, 预计解锁时间为 {{year}}年{{month}}月{{day}}日(锁定时间根据区块链实际运行情况会有一定的误差)。", "withdraw-asset-tooltip": "预计解锁时间为 {{year}}年{{month}}月{{day}}日 {{hour}}时{{minute}}分(根据区块链实际运行情况会有一定的误差)。", - "user-defined-token-tooltip": "将 sUDT 资产转移到 sUDT 账户", + "user-defined-token-tooltip": "将 {{udtType}} 资产转移到 {{udtType}} 账户", "claim-asset": "领取", "withdraw-asset": "撤回", "view-details": "查看详情", @@ -964,14 +964,14 @@ "transfer-nft": "转让", "user-defined-token": "迁移", "transfer-nft-success": "转让资产成功", - "migrate-sudt-success": "转换成新的 sUDT 资产账户成功", - "send-sudt-success": "转入 sUDT 账户成功", + "migrate-sudt-success": "转换成新的 {{udtType}} 资产账户成功", + "send-sudt-success": "转入 {{udtType}} 账户成功", "unlock-success": "资产已领取,可前往交易历史查看详情", "withdraw-cheque-success": "资产已撤回,可前往交易历史查看详情", "claim-cheque-success": "资产已领取,可前往交易历史查看详情" }, "migrate-sudt": { - "title": "迁移至 sUDT 资产账户", + "title": "迁移至 {{udtType}} 资产账户", "choose-title": "选择迁移方式", "next": "下一步", "back": "上一步", @@ -979,14 +979,14 @@ "input-symbol": "请输入简称", "input-decimal": "请输入小数位", "turn-into-new-account": { - "title": "转换成新的 sUDT 资产账户", - "sub-title": "将 sUDT 资产转换成 sUDT 资产账户, 至少占用 142 CKBytes", + "title": "转换成新的 {{udtType}} 资产账户", + "sub-title": "将 {{udtType}} 资产转换成 {{udtType}} 资产账户, 至少占用 142 CKBytes", "cancel": "取消", "confirm": "确认" }, "transfer-to-exist-account": { - "title": "转入 sUDT 账户", - "sub-title": "将全部 sUDT 余额转入已存在的 sUDT 资产账户, 请确保目标账户存在" + "title": "转入 {{udtType}} 账户", + "sub-title": "将全部 {{udtType}} 余额转入已存在的 {{udtType}} 资产账户, 请确保目标账户存在" }, "cancel": "取消", "confirm": "确认", @@ -1012,6 +1012,7 @@ "select-account-type": "选择账户类型", "account-name": "账户名称", "sudt-account": "sUDT 账户", + "xudt-account": "xUDT 账户", "ckb-account": "CKB 账户", "set-token-info": "设置代币信息", "token-id": "代币ID", @@ -1032,7 +1033,7 @@ "decimal": "请输入小数位" }, "placeholder": { - "token-id": "代币 ID 即 sUDT Type Script 的 Args,等同于该 token 发行者的 lock hash。" + "token-id": "代币 ID 即 {{udtType}} Type Script 的 Args,等同于该 token 发行者的 lock hash。" } }, "send": { diff --git a/packages/neuron-ui/src/services/chain.ts b/packages/neuron-ui/src/services/chain.ts index 31dac003db..f4e1fdb59e 100644 --- a/packages/neuron-ui/src/services/chain.ts +++ b/packages/neuron-ui/src/services/chain.ts @@ -1,6 +1,6 @@ -import { CKBRPC } from '@ckb-lumos/rpc' +import { RPC } from '@ckb-lumos/lumos' -export const rpc = new CKBRPC('') +export const rpc = new RPC('') export const { getHeader, getBlockchainInfo, getTipHeader, getHeaderByNumber, getFeeRateStatistics, getTransaction } = rpc diff --git a/packages/neuron-ui/src/services/remote/sudt.ts b/packages/neuron-ui/src/services/remote/sudt.ts index 0faf64622c..3b78e253a8 100644 --- a/packages/neuron-ui/src/services/remote/sudt.ts +++ b/packages/neuron-ui/src/services/remote/sudt.ts @@ -1,3 +1,4 @@ +import { UDTType } from 'utils' import { remoteApi } from './remoteApiWrapper' export const getAnyoneCanPayScript = remoteApi('get-anyone-can-pay-script') @@ -21,9 +22,10 @@ export const generateSUDTTransaction = remoteApi( - 'get-hold-sudt-cell-capacity' -) +export const getHoldSUDTCellCapacity = remoteApi< + { address: string; tokenID: string; udtType?: UDTType }, + string | undefined +>('get-hold-sudt-cell-capacity') export const sendSUDTTransaction = remoteApi('send-to-anyone-can-pay') @@ -33,9 +35,4 @@ export const getSUDTTokenInfo = remoteApi('get-sudt-type-script-hash') - export const generateSudtMigrateAcpTx = remoteApi('generate-sudt-migrate-acp-tx') diff --git a/packages/neuron-ui/src/states/stateProvider/reducer.ts b/packages/neuron-ui/src/states/stateProvider/reducer.ts index 801a9fe30c..23995000a3 100644 --- a/packages/neuron-ui/src/states/stateProvider/reducer.ts +++ b/packages/neuron-ui/src/states/stateProvider/reducer.ts @@ -1,4 +1,4 @@ -import type { OutPoint } from '@ckb-lumos/base' +import type { OutPoint } from '@ckb-lumos/lumos' import produce, { Draft } from 'immer' import { OfflineSignJSON } from 'services/remote' import initStates from 'states/init' @@ -234,7 +234,7 @@ export const reducer = produce((state: Draft, action: state.sUDTAccounts = action.payload .filter(account => account.id !== undefined) .sort(sortAccounts) - .map(({ id, accountName, tokenName, symbol, tokenID, balance: accountBalance, address, decimal }) => ({ + .map(({ id, accountName, tokenName, symbol, tokenID, balance: accountBalance, address, decimal, udtType }) => ({ accountId: id!.toString(), accountName, tokenName, @@ -243,6 +243,7 @@ export const reducer = produce((state: Draft, action: address, decimal, tokenId: tokenID, + udtType, })) break } diff --git a/packages/neuron-ui/src/stories/SUDTCreateDialog.stories.tsx b/packages/neuron-ui/src/stories/SUDTCreateDialog.stories.tsx index 744a73dc7c..887c65fc41 100644 --- a/packages/neuron-ui/src/stories/SUDTCreateDialog.stories.tsx +++ b/packages/neuron-ui/src/stories/SUDTCreateDialog.stories.tsx @@ -20,9 +20,9 @@ const baseProps = { } const propsList: { [name: string]: SUDTCreateDialogProps } = { Basic: baseProps, - InsufficientForSUDT: { ...baseProps, insufficient: { ckb: false, sudt: true } }, - InsufficientForCKB: { ...baseProps, insufficient: { ckb: true, sudt: false } }, - InsufficientForCKBAndSUDT: { ...baseProps, insufficient: { ckb: true, sudt: true } }, + InsufficientForSUDT: { ...baseProps, insufficient: { ckb: false, sudt: true, xudt: true } }, + InsufficientForCKB: { ...baseProps, insufficient: { ckb: true, sudt: false, xudt: false } }, + InsufficientForCKBAndSUDT: { ...baseProps, insufficient: { ckb: true, sudt: true, xudt: true } }, } const meta: Meta = { diff --git a/packages/neuron-ui/src/stories/ScriptTag.stories.tsx b/packages/neuron-ui/src/stories/ScriptTag.stories.tsx index ec88624ea6..15ac80146a 100644 --- a/packages/neuron-ui/src/stories/ScriptTag.stories.tsx +++ b/packages/neuron-ui/src/stories/ScriptTag.stories.tsx @@ -1,7 +1,7 @@ import { Meta, StoryObj } from '@storybook/react' import { withRouter } from 'storybook-addon-react-router-v6' import { action } from '@storybook/addon-actions' -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import ScriptTag from 'components/ScriptTag' const scripts: Record = { diff --git a/packages/neuron-ui/src/tests/getMultisigSignStatus/index.test.ts b/packages/neuron-ui/src/tests/getMultisigSignStatus/index.test.ts index 71ad89f736..eab3d73406 100644 --- a/packages/neuron-ui/src/tests/getMultisigSignStatus/index.test.ts +++ b/packages/neuron-ui/src/tests/getMultisigSignStatus/index.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from '@jest/globals' import { MultisigConfig } from 'services/remote' import { addressToScript, getMultisigSignStatus } from 'utils' -import { computeScriptHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash } from '@ckb-lumos/lumos/utils' const addresses = [ 'ckt1qyqwh5hmt8j59njztrfz6z0s9wug3nv5qysqrnfm2h', diff --git a/packages/neuron-ui/src/types/App/index.d.ts b/packages/neuron-ui/src/types/App/index.d.ts index 2a237caef5..649cf62493 100644 --- a/packages/neuron-ui/src/types/App/index.d.ts +++ b/packages/neuron-ui/src/types/App/index.d.ts @@ -132,6 +132,11 @@ declare namespace State { amendHash?: string } + enum UDTType { + SUDT = 'sUDT', + XUDT = 'xUDT', + } + interface SUDTAccount { accountId: string accountName?: string @@ -141,6 +146,7 @@ declare namespace State { tokenId: string address: string decimal: string + udtType?: UDTType } type GlobalAlertDialog = { @@ -364,6 +370,7 @@ declare namespace State { NFTClass = 'NFTClass', NFTIssuer = 'NFTIssuer', SUDT = 'SUDT', + XUDT = 'XUDT', Spore = 'Spore', Unknown = 'Unknown', } @@ -382,7 +389,7 @@ declare namespace State { } interface LiveCellWithLocalInfo extends LiveCellWithLocalInfoAPI { lockedReason?: { key: string; params?: Record } - cellType?: 'CKB' | 'SUDT' | 'NFT' | 'Spore' | 'Unknown' + cellType?: 'CKB' | 'SUDT' | 'XUDT' | 'NFT' | 'Spore' | 'Unknown' } interface UpdateLiveCellLocalInfo { diff --git a/packages/neuron-ui/src/types/Controller/index.d.ts b/packages/neuron-ui/src/types/Controller/index.d.ts index 83d7cab827..5737d4f79c 100644 --- a/packages/neuron-ui/src/types/Controller/index.d.ts +++ b/packages/neuron-ui/src/types/Controller/index.d.ts @@ -1,4 +1,9 @@ declare namespace Controller { + enum UDTType { + SUDT = 'sUDT', + XUDT = 'xUDT', + } + interface RequestOpenInExplorerParams { key: string type: 'transaction' @@ -217,6 +222,7 @@ declare namespace Controller { balance: string blake160: string address: string + udtType?: UDTType } namespace GetSUDTAccount { @@ -244,6 +250,7 @@ declare namespace Controller { symbol: string decimal: string feeRate: string + udtType?: UDTType } interface Response { assetAccount: any @@ -254,7 +261,7 @@ declare namespace Controller { namespace SendCreateSUDTAccountTransaction { interface Params { walletID: string - assetAccount: Pick + assetAccount: Pick tx: any password?: string } @@ -385,9 +392,9 @@ declare namespace Controller { } namespace GenerateClaimChequeTransaction { - type AssetAccount = Record< - 'accountName' | 'balance' | 'blake160' | 'decimal' | 'symbol' | 'tokenID' | 'tokenName', - string + type AssetAccount = Pick< + SUDTAccount, + 'accountName' | 'balance' | 'blake160' | 'decimal' | 'symbol' | 'tokenID' | 'tokenName' | 'udtType' > interface Params { diff --git a/packages/neuron-ui/src/utils/calculateUsedCapacity.ts b/packages/neuron-ui/src/utils/calculateUsedCapacity.ts index 2832513763..e7653fd7f9 100644 --- a/packages/neuron-ui/src/utils/calculateUsedCapacity.ts +++ b/packages/neuron-ui/src/utils/calculateUsedCapacity.ts @@ -1,4 +1,4 @@ -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' const CODE_HASH_LENGTH = 32 const HASH_TYPE_LENGTH = 1 diff --git a/packages/neuron-ui/src/utils/const.ts b/packages/neuron-ui/src/utils/const.ts index 2dda7ff4d3..02dc639675 100644 --- a/packages/neuron-ui/src/utils/const.ts +++ b/packages/neuron-ui/src/utils/const.ts @@ -20,6 +20,7 @@ export const MAINNET_CLIENT_LIST = [FULL_NODE_MAINNET, LIGHT_CLIENT_MAINNET] export const MIN_DEPOSIT_AMOUNT = 102 export const TOKEN_ID_LENGTH = 66 +export const XUDT_TOKEN_ID_LENGTH = 68 export const SHANNON_CKB_RATIO = 1e8 diff --git a/packages/neuron-ui/src/utils/enums.ts b/packages/neuron-ui/src/utils/enums.ts index 23c0b96b6f..2ae3a13711 100644 --- a/packages/neuron-ui/src/utils/enums.ts +++ b/packages/neuron-ui/src/utils/enums.ts @@ -126,6 +126,7 @@ export enum PresetScript { Locktime = 'SingleMultiSign', Cheque = 'Cheque', SUDT = 'SUDT', + XUDT = 'XUDT', } export enum CompensationPeriod { @@ -241,6 +242,12 @@ export enum TypeScriptCategory { NFTClass = 'NFTClass', NFTIssuer = 'NFTIssuer', SUDT = 'SUDT', + XUDT = 'XUDT', Spore = 'Spore', Unknown = 'Unknown', } + +export enum UDTType { + SUDT = 'sUDT', + XUDT = 'xUDT', +} diff --git a/packages/neuron-ui/src/utils/formatters.ts b/packages/neuron-ui/src/utils/formatters.ts index 55273b9a7f..982d821a5e 100644 --- a/packages/neuron-ui/src/utils/formatters.ts +++ b/packages/neuron-ui/src/utils/formatters.ts @@ -1,10 +1,11 @@ -import { molecule } from '@ckb-lumos/codec' -import { blockchain } from '@ckb-lumos/base' -import { formatUnit, ckbDecimals } from '@ckb-lumos/bi' +import { table, blockchain } from '@ckb-lumos/lumos/codec' +import { formatUnit } from '@ckb-lumos/lumos/utils' import { TFunction } from 'i18next' import { FailureFromController } from 'services/remote/remoteApiWrapper' import { CapacityUnit } from './enums' +const CKB_DECIMALS = 8 + const base = 10e9 const numberParser = (value: string, exchange: string) => { if (Number.isNaN(+value)) { @@ -112,7 +113,7 @@ export const shannonToCKBFormatter = (shannon: string, showPositiveSign?: boolea return new Intl.NumberFormat('en-US', { useGrouping: showCommaSeparator, signDisplay: showPositiveSign && +shannon > 0 ? 'always' : 'auto', - maximumFractionDigits: ckbDecimals, + maximumFractionDigits: CKB_DECIMALS, }).format(formatUnit(BigInt(shannon ?? '0'), 'ckb') as any) } @@ -259,7 +260,7 @@ type FormatterOptions = { args: string; data?: string; clusterName?: string; tru export const sporeFormatter = ({ args, data, clusterName, truncate }: FormatterOptions) => { let format = 'Spore' - const SporeData = molecule.table( + const SporeData = table( { contentType: blockchain.Bytes, content: blockchain.Bytes, diff --git a/packages/neuron-ui/src/utils/getLockSupportShortAddress.ts b/packages/neuron-ui/src/utils/getLockSupportShortAddress.ts index 0247eb8364..82b5ac806f 100644 --- a/packages/neuron-ui/src/utils/getLockSupportShortAddress.ts +++ b/packages/neuron-ui/src/utils/getLockSupportShortAddress.ts @@ -1,4 +1,4 @@ -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import { AnyoneCanPayLockInfoOnAggron, AnyoneCanPayLockInfoOnLina, DefaultLockInfo, MultiSigLockInfo } from './enums' const getLockSupportShortAddress = (lock: CKBComponents.Script) => { diff --git a/packages/neuron-ui/src/utils/getMultisigSignStatus.ts b/packages/neuron-ui/src/utils/getMultisigSignStatus.ts index 1f351ba59a..91dfe57cc6 100644 --- a/packages/neuron-ui/src/utils/getMultisigSignStatus.ts +++ b/packages/neuron-ui/src/utils/getMultisigSignStatus.ts @@ -1,5 +1,5 @@ import { addressToScript } from 'utils' -import { computeScriptHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash } from '@ckb-lumos/lumos/utils' import { MultisigConfig } from 'services/remote' export const getMultisigSignStatus = ({ diff --git a/packages/neuron-ui/src/utils/hooks/createSUDTAccount.ts b/packages/neuron-ui/src/utils/hooks/createSUDTAccount.ts index 3eb7e94b15..6efb93673c 100644 --- a/packages/neuron-ui/src/utils/hooks/createSUDTAccount.ts +++ b/packages/neuron-ui/src/utils/hooks/createSUDTAccount.ts @@ -3,15 +3,12 @@ import { TFunction } from 'i18next' import { useEffect, useCallback } from 'react' import { AccountType, TokenInfo } from 'components/SUDTCreateDialog' import { AppActions, StateAction } from 'states' -import { - generateCreateSUDTAccountTransaction, - openExternal, - getSUDTTypeScriptHash, - invokeShowErrorMessage, -} from 'services/remote' +import { generateCreateSUDTAccountTransaction, openExternal, invokeShowErrorMessage } from 'services/remote' import { getExplorerUrl } from 'utils' +import { predefined } from '@ckb-lumos/config-manager' +import { utils } from '@ckb-lumos/base' import useGetCountDownAndFeeRateStats from './useGetCountDownAndFeeRateStats' -import { ErrorCode } from '../enums' +import { ErrorCode, UDTType } from '../enums' import { isSuccessResponse } from '../is' import { MIN_CKB_REQUIRED_BY_CKB_SUDT, @@ -46,6 +43,7 @@ export const useIsInsufficientToCreateSUDTAccount = ({ symbol: DEFAULT_SUDT_FIELDS.symbol, decimal: '0', feeRate: `${suggestFeeRate}`, + udtType: UDTType.SUDT, } return generateCreateSUDTAccountTransaction(params).catch(() => false) } @@ -77,6 +75,7 @@ export const useIsInsufficientToCreateSUDTAccount = ({ setInsufficient({ [AccountType.CKB]: insufficientToCreateCKBAccount, [AccountType.SUDT]: insufficientToCreateSUDTAccount, + [AccountType.XUDT]: insufficientToCreateSUDTAccount, }) }) }, [walletId, balance, setInsufficient, suggestFeeRate]) @@ -94,7 +93,10 @@ export const useOnGenerateNewAccountTransaction = ({ t: TFunction }) => useCallback( - ({ tokenId, tokenName, accountName, symbol, decimal }: TokenInfo, onSuccess?: () => void) => { + ( + { tokenId, tokenName, accountName, symbol, decimal, udtType }: TokenInfo & { udtType?: UDTType }, + onSuccess?: () => void + ) => { return generateCreateSUDTAccountTransaction({ walletID: walletId, tokenID: tokenId, @@ -103,6 +105,7 @@ export const useOnGenerateNewAccountTransaction = ({ symbol, decimal, feeRate: `${MEDIUM_FEE_RATE}`, + udtType, }) .then(res => { if (isSuccessResponse(res)) { @@ -131,15 +134,18 @@ export const useOnGenerateNewAccountTransaction = ({ [onGenerated, walletId, dispatch, t] ) -export const useOpenSUDTTokenUrl = (tokenID: string, isMainnet?: boolean) => +export const useOpenUDTTokenUrl = (tokenID: string, udtType?: UDTType, isMainnet?: boolean) => useCallback(() => { - if (tokenID) { - getSUDTTypeScriptHash({ tokenID }).then(res => { - if (isSuccessResponse(res) && res.result) { - openExternal(`${getExplorerUrl(isMainnet)}/sudt/${res.result}`) - } + if (tokenID && udtType) { + const { SUDT, XUDT } = isMainnet ? predefined.LINA.SCRIPTS : predefined.AGGRON4.SCRIPTS + const udtScript = udtType === UDTType.SUDT ? SUDT : XUDT + const scriptHash = utils.computeScriptHash({ + codeHash: udtScript.CODE_HASH, + hashType: udtScript.HASH_TYPE, + args: tokenID, }) + openExternal(`${getExplorerUrl(isMainnet)}/${udtType === UDTType.SUDT ? 'sudt' : 'xudt'}/${scriptHash}`) } }, [isMainnet, tokenID]) -export default { useIsInsufficientToCreateSUDTAccount, useOnGenerateNewAccountTransaction, useOpenSUDTTokenUrl } +export default { useIsInsufficientToCreateSUDTAccount, useOnGenerateNewAccountTransaction, useOpenUDTTokenUrl } diff --git a/packages/neuron-ui/src/utils/hooks/index.ts b/packages/neuron-ui/src/utils/hooks/index.ts index 9496c06422..82a29776f7 100644 --- a/packages/neuron-ui/src/utils/hooks/index.ts +++ b/packages/neuron-ui/src/utils/hooks/index.ts @@ -13,7 +13,7 @@ import { showPageNotice, useDispatch, } from 'states' -import { epochParser, isReadyByVersion, calculateClaimEpochValue, CONSTANTS, isSuccessResponse } from 'utils' +import { epochParser, isReadyByVersion, calculateClaimEpochValue, CONSTANTS, isSuccessResponse, UDTType } from 'utils' import { validateTokenId, validateAssetAccountName, @@ -282,6 +282,7 @@ export const useSUDTAccountInfoErrors = ({ existingAccountNames, isCKB, t, + udtType, }: { info: { accountName: string @@ -294,6 +295,7 @@ export const useSUDTAccountInfoErrors = ({ existingAccountNames: string[] isCKB: boolean t: TFunction + udtType?: UDTType }) => useMemo(() => { const tokenErrors = { @@ -311,7 +313,7 @@ export const useSUDTAccountInfoErrors = ({ validator: validateAssetAccountName, }, symbol: { params: { symbol, isCKB }, validator: validateSymbol }, - tokenId: { params: { tokenId, isCKB }, validator: validateTokenId }, + tokenId: { params: { tokenId, isCKB, udtType }, validator: validateTokenId }, tokenName: { params: { tokenName, isCKB }, validator: validateTokenName }, decimal: { params: { decimal }, validator: validateDecimal }, balance: { params: { balance }, validator: typeof balance === 'undefined' ? () => {} : validateDecimal }, diff --git a/packages/neuron-ui/src/utils/is.ts b/packages/neuron-ui/src/utils/is.ts index 5a82900882..1e53b008b2 100644 --- a/packages/neuron-ui/src/utils/is.ts +++ b/packages/neuron-ui/src/utils/is.ts @@ -7,7 +7,10 @@ import { AnyoneCanPayLockInfoOnLina, PwAcpLockInfoOnMainNet, PwAcpLockInfoOnTestNet, + UDTType, } from 'utils/enums' +import { type Script } from '@ckb-lumos/base' +import { predefined } from '@ckb-lumos/config-manager' import { MAINNET_CLIENT_LIST } from './const' export const isMainnet = (networks: Readonly, networkID: string) => { @@ -62,3 +65,28 @@ export const isAnyoneCanPayAddress = (address: string, isMainnetAddress: boolean return false } } + +// Add string type to recognize the return type of API from https://github.com/nervosnetwork/neuron/blob/v0.116.2/packages/neuron-wallet/src/models/chain/output.ts#L20 +// TODO, make the UDT code hash globally configurable to ensure it can test with the devnet +export const getUdtType = (type: Script | string | null) => { + if (type === null) return undefined + if (typeof type === 'string') { + switch (type) { + case UDTType.SUDT: + case UDTType.XUDT: + return type + default: + return undefined + } + } + switch (type.codeHash) { + case predefined.AGGRON4.SCRIPTS.SUDT.CODE_HASH: + case predefined.LINA.SCRIPTS.SUDT.CODE_HASH: + return UDTType.SUDT + case predefined.AGGRON4.SCRIPTS.XUDT.CODE_HASH: + case predefined.LINA.SCRIPTS.XUDT.CODE_HASH: + return UDTType.XUDT + default: + return undefined + } +} diff --git a/packages/neuron-ui/src/utils/multisig.ts b/packages/neuron-ui/src/utils/multisig.ts index a59c6998c6..232acc6a00 100644 --- a/packages/neuron-ui/src/utils/multisig.ts +++ b/packages/neuron-ui/src/utils/multisig.ts @@ -1,4 +1,4 @@ -import { ckbHash } from '@ckb-lumos/base/lib/utils' +import { ckbHash } from '@ckb-lumos/lumos/utils' import { scriptToAddress } from 'utils' import { MultiSigLockInfo } from './enums' import { MAX_M_N_NUMBER } from './const' diff --git a/packages/neuron-ui/src/utils/outPointTransform.ts b/packages/neuron-ui/src/utils/outPointTransform.ts index e659458bcf..8a098c4a0b 100644 --- a/packages/neuron-ui/src/utils/outPointTransform.ts +++ b/packages/neuron-ui/src/utils/outPointTransform.ts @@ -1,4 +1,4 @@ -import { type CKBComponents } from '@ckb-lumos/rpc/lib/types/api' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' export const outPointToStr = (value: CKBComponents.OutPoint): string => { return `${value.txHash}_${value.index}` diff --git a/packages/neuron-ui/src/utils/parsers.ts b/packages/neuron-ui/src/utils/parsers.ts index 10dfafaba8..06b3b05671 100644 --- a/packages/neuron-ui/src/utils/parsers.ts +++ b/packages/neuron-ui/src/utils/parsers.ts @@ -1,5 +1,5 @@ -import { since } from '@ckb-lumos/base' -import { number, bytes } from '@ckb-lumos/codec' +import { since } from '@ckb-lumos/lumos' +import { bytes, Uint128LE, Uint64LE } from '@ckb-lumos/lumos/codec' import { MILLISECONDS, PAGE_SIZE } from './const' export const listParams = (search: string) => { @@ -45,7 +45,7 @@ export const toUint128Le = (hexString: string) => { s = s.slice(0, 34) } - return bytes.hexify(number.Uint128LE.pack(s)) + return bytes.hexify(Uint128LE.pack(s)) } export const getLockTimestamp = ({ @@ -57,7 +57,7 @@ export const getLockTimestamp = ({ epoch: string bestKnownBlockTimestamp: number }) => { - const targetEpochInfo = epochParser(bytes.hexify(number.Uint64LE.pack(`0x${lockArgs.slice(-16)}`))) + const targetEpochInfo = epochParser(bytes.hexify(Uint64LE.pack(`0x${lockArgs.slice(-16)}`))) const currentEpochInfo = epochParser(epoch) const targetEpochFraction = Number(targetEpochInfo.length) > 0 ? Number(targetEpochInfo.index) / Number(targetEpochInfo.length) : 1 diff --git a/packages/neuron-ui/src/utils/scriptAndAddress.ts b/packages/neuron-ui/src/utils/scriptAndAddress.ts index acea450b72..dfc0965bcc 100644 --- a/packages/neuron-ui/src/utils/scriptAndAddress.ts +++ b/packages/neuron-ui/src/utils/scriptAndAddress.ts @@ -1,8 +1,7 @@ -import { type Script } from '@ckb-lumos/base' -import { predefined } from '@ckb-lumos/config-manager' -import { encodeToAddress, parseAddress, generateAddress } from '@ckb-lumos/helpers' - -const { LINA: MAINNET, AGGRON4: TESTNET } = predefined +import { type Script } from '@ckb-lumos/lumos' +import { MAINNET, TESTNET } from '@ckb-lumos/lumos/config' +import { encodeToAddress, parseAddress } from '@ckb-lumos/lumos/helpers' +import { generateAddress } from '@ckb-lumos/helpers' const CONFIGS = { [MAINNET.PREFIX]: MAINNET, diff --git a/packages/neuron-ui/src/utils/validators/capacity.ts b/packages/neuron-ui/src/utils/validators/capacity.ts index d91c15cee1..0d5420bd47 100644 --- a/packages/neuron-ui/src/utils/validators/capacity.ts +++ b/packages/neuron-ui/src/utils/validators/capacity.ts @@ -1,6 +1,6 @@ import { CKBToShannonFormatter } from 'utils/formatters' import { CapacityTooSmallException } from 'exceptions' -import { bytes as byteUtils } from '@ckb-lumos/codec' +import { bytes as byteUtils } from '@ckb-lumos/lumos/codec' import { addressToScript } from 'utils' export const validateCapacity = (item: State.Output) => { diff --git a/packages/neuron-ui/src/utils/validators/tokenId.ts b/packages/neuron-ui/src/utils/validators/tokenId.ts index dfd64c96d7..7bdb5fed1a 100644 --- a/packages/neuron-ui/src/utils/validators/tokenId.ts +++ b/packages/neuron-ui/src/utils/validators/tokenId.ts @@ -1,14 +1,17 @@ -import { DEFAULT_SUDT_FIELDS, TOKEN_ID_LENGTH } from 'utils/const' +import { DEFAULT_SUDT_FIELDS, TOKEN_ID_LENGTH, XUDT_TOKEN_ID_LENGTH } from 'utils/const' import { FieldRequiredException, FieldInvalidException } from 'exceptions' +import { UDTType } from 'utils/enums' export const validateTokenId = ({ tokenId, isCKB = false, required = false, + udtType, }: { tokenId: string isCKB: boolean required: boolean + udtType?: UDTType }) => { if (!tokenId) { if (required) { @@ -22,7 +25,9 @@ export const validateTokenId = ({ return true } - if (!isCKB && tokenId.startsWith('0x') && tokenId.length === TOKEN_ID_LENGTH && !Number.isNaN(+tokenId)) { + const tokenLength = udtType === UDTType.SUDT ? [TOKEN_ID_LENGTH] : [TOKEN_ID_LENGTH, XUDT_TOKEN_ID_LENGTH] + + if (!isCKB && tokenId.startsWith('0x') && tokenLength.includes(tokenId.length) && !Number.isNaN(+tokenId)) { return true } diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json index f6af151e56..7ca3b1b10a 100644 --- a/packages/neuron-wallet/package.json +++ b/packages/neuron-wallet/package.json @@ -42,15 +42,11 @@ ] }, "dependencies": { - "@ckb-lumos/base": "0.21.1", - "@ckb-lumos/bi": "0.21.1", - "@ckb-lumos/ckb-indexer": "0.21.1", - "@ckb-lumos/codec": "0.21.1", - "@ckb-lumos/common-scripts": "0.21.1", - "@ckb-lumos/config-manager": "0.21.1", - "@ckb-lumos/hd": "0.21.1", - "@ckb-lumos/helpers": "0.21.1", - "@ckb-lumos/rpc": "0.21.1", + "@ckb-lumos/base": "0.23.0", + "@ckb-lumos/ckb-indexer": "0.23.0", + "@ckb-lumos/helpers": "0.23.0", + "@ckb-lumos/rpc": "0.23.0", + "@ckb-lumos/lumos": "0.23.0", "@iarna/toml": "2.2.5", "@ledgerhq/hw-transport-node-hid": "6.27.22", "@spore-sdk/core": "0.1.0", diff --git a/packages/neuron-wallet/src/block-sync-renderer/index.ts b/packages/neuron-wallet/src/block-sync-renderer/index.ts index 892c676618..e62a772353 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/index.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/index.ts @@ -9,7 +9,8 @@ import DataUpdateSubject from '../models/subjects/data-update' import AddressCreatedSubject from '../models/subjects/address-created-subject' import WalletDeletedSubject from '../models/subjects/wallet-deleted-subject' import TxDbChangedSubject from '../models/subjects/tx-db-changed-subject' -import { type Cell, type QueryOptions } from '@ckb-lumos/base' +import { type QueryOptions } from '@ckb-lumos/base' +import { type Cell } from '@ckb-lumos/lumos' import { WorkerMessage, StartParams, QueryIndexerParams } from './task' import logger from '../utils/logger' import CommonUtils from '../utils/common' diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/full-synchronizer.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/full-synchronizer.ts index eecace1ccf..7682cdbd6c 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/full-synchronizer.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/full-synchronizer.ts @@ -1,4 +1,4 @@ -import { Tip } from '@ckb-lumos/base' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import logger from '../../utils/logger' import CommonUtils from '../../utils/common' import RpcService from '../../services/rpc-service' @@ -15,7 +15,7 @@ export default class FullSynchronizer extends Synchronizer { this.rpcService = new RpcService(nodeUrl, nodeType) } - private async synchronize(indexerTipBlock: Tip) { + private async synchronize(indexerTipBlock: CKBComponents.Tip) { if (!indexerTipBlock) { return } diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts index b3401f6626..99f29b49e4 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts @@ -6,7 +6,7 @@ import RpcService from '../../services/rpc-service' import TransactionWithStatus from '../../models/chain/transaction-with-status' import SyncInfoEntity from '../../database/chain/entities/sync-info' import { getConnection } from '../../database/chain/connection' -import { TransactionCollector, CellCollector, Indexer as CkbIndexer } from '@ckb-lumos/ckb-indexer' +import { TransactionCollector, Indexer as CkbIndexer, CellCollector } from '@ckb-lumos/ckb-indexer' export default class IndexerCacheService { private addressMetas: AddressMeta[] @@ -194,7 +194,7 @@ export default class IndexerCacheService { const txsWithStatus: TransactionWithStatus[] = [] const fetchBlockDetailsQueue = queue(async (hash: string) => { const txWithStatus = await this.rpcService.getTransaction(hash) - if (!txWithStatus) { + if (!txWithStatus?.transaction) { return } const blockHeader = await this.rpcService.getHeader(txWithStatus!.txStatus.blockHash!) diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/light-synchronizer.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/light-synchronizer.ts index fe89dabefb..aafa963859 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/light-synchronizer.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/light-synchronizer.ts @@ -1,28 +1,27 @@ -import type { HexString, Script, TransactionWithStatus } from '@ckb-lumos/base' +import type { HexString, Script } from '@ckb-lumos/lumos' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import logger from '../../utils/logger' import { Address } from '../../models/address' import AddressMeta from '../../database/address/meta' import { scheduler } from 'timers/promises' import SyncProgressService from '../../services/sync-progress' import { Synchronizer } from './synchronizer' -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import { FetchTransactionReturnType, LightRPC, LightScriptFilter } from '../../utils/ckb-rpc' import Multisig from '../../services/multisig' import SyncProgress, { SyncAddressType } from '../../database/chain/entities/sync-progress' import WalletService from '../../services/wallets' import AssetAccountInfo from '../../models/asset-account-info' import { DepType } from '../../models/chain/cell-dep' -import { molecule } from '@ckb-lumos/codec' -import { blockchain } from '@ckb-lumos/base' -import type { Base } from '@ckb-lumos/rpc/lib/Base' -import { BI } from '@ckb-lumos/bi' +import { vector, blockchain } from '@ckb-lumos/lumos/codec' +import type { Base } from '@ckb-lumos/lumos/rpc' +import { BI } from '@ckb-lumos/lumos' import IndexerCacheService from './indexer-cache-service' -import { ScriptType } from '@ckb-lumos/ckb-indexer/lib/type' import { scriptToAddress } from '../../utils/scriptAndAddress' import NetworksService from '../../services/networks' import { getConnection } from '../../database/chain/connection' -const unpackGroup = molecule.vector(blockchain.OutPoint) +const unpackGroup = vector(blockchain.OutPoint) const THRESHOLD_BLOCK_NUMBER_IN_DIFF_WALLET = 100_000 export default class LightSynchronizer extends Synchronizer { @@ -43,6 +42,7 @@ export default class LightSynchronizer extends Synchronizer { const fetchCellDeps = [ assetAccountInfo.anyoneCanPayCellDep, assetAccountInfo.sudtCellDep, + assetAccountInfo.xudtCellDep, assetAccountInfo.getNftClassInfo().cellDep, assetAccountInfo.getNftInfo().cellDep, assetAccountInfo.getNftIssuerInfo().cellDep, @@ -101,7 +101,7 @@ export default class LightSynchronizer extends Synchronizer { }: { script: Script blockRange: [HexString, HexString] - scriptType: ScriptType + scriptType: CKBComponents.ScriptType }) { const res = [] let lastCursor: HexString | undefined = undefined @@ -293,7 +293,9 @@ export default class LightSynchronizer extends Synchronizer { private async fetchPreviousOutputs(txHashes: string[]) { const transactions = await this.lightRpc - .createBatchRequest<'getTransaction', string[], TransactionWithStatus[]>(txHashes.map(v => ['getTransaction', v])) + .createBatchRequest<'getTransaction', string[], CKBComponents.TransactionWithStatus[]>( + txHashes.map(v => ['getTransaction', v]) + ) .exec() const previousTxHashes = new Set() transactions @@ -335,7 +337,9 @@ export default class LightSynchronizer extends Synchronizer { private async checkTxExist(txHashes: string[]) { const transactions = await this.lightRpc - .createBatchRequest<'getTransaction', string[], TransactionWithStatus[]>(txHashes.map(v => ['getTransaction', v])) + .createBatchRequest<'getTransaction', string[], CKBComponents.TransactionWithStatus[]>( + txHashes.map(v => ['getTransaction', v]) + ) .exec() return transactions.every(v => !!v.transaction) } diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts index 8eb2b923f3..890cbac985 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts @@ -133,8 +133,8 @@ export default class Queue { for (let index = 0; index < txsWithStatus.length; index++) { if (txsWithStatus[index]?.transaction) { const tx = Transaction.fromSDK(txsWithStatus[index].transaction) - tx.blockHash = txsWithStatus[index].txStatus.blockHash! - blockHashes.push(tx.blockHash) + tx.blockHash = txsWithStatus[index].txStatus.blockHash + blockHashes.push(tx.blockHash!) txs.push(tx) } else { if ((txsWithStatus[index].txStatus as any) === 'rejected') { @@ -144,7 +144,7 @@ export default class Queue { } } const headers = await rpc - .createBatchRequest<'getHeader', string[], CKBComponents.BlockHeader[]>(blockHashes.map(v => ['getHeader', v])) + .createBatchRequest<'getHeader', string[], CKBComponents.BlockHeader[]>(blockHashes.map(v => ['getHeader', v!])) .exec() headers.forEach((blockHeader: CKBComponents.BlockHeader, idx: number) => { if (blockHeader) { @@ -231,7 +231,7 @@ export default class Queue { } await TransactionPersistor.saveFetchTx(tx, this.#lockArgsSet) for (const info of anyoneCanPayInfos) { - await AssetAccountService.checkAndSaveAssetAccountWhenSync(info.tokenID, info.blake160) + await AssetAccountService.checkAndSaveAssetAccountWhenSync(info.tokenID, info.blake160, info.udtType) } await this.#checkAndGenerateAddressesByTx(tx) diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/tx-address-finder.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/tx-address-finder.ts index 200aaeded3..8cb87fffd7 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/tx-address-finder.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/tx-address-finder.ts @@ -6,10 +6,13 @@ import OutPoint from '../../models/chain/out-point' import Transaction from '../../models/chain/transaction' import SystemScriptInfo from '../../models/system-script-info' import { getConnection } from '../../database/chain/connection' +import { UDTType } from '../../utils/const' +import AssetAccountInfo from '../../models/asset-account-info' export interface AnyoneCanPayInfo { tokenID: string blake160: string + udtType?: UDTType } // Search for all addresses related to a transaction. These addresses include: @@ -47,6 +50,7 @@ export default class TxAddressFinder { let shouldSync = false // const anyoneCanPayBlake160s: string[] = [] const anyoneCanPayInfos: AnyoneCanPayInfo[] = [] + const assetAccountInfo = new AssetAccountInfo() const outputs: Output[] = this.tx .outputs!.map((output, index) => { if (SystemScriptInfo.isMultiSignScript(output.lock)) { @@ -62,6 +66,11 @@ export default class TxAddressFinder { anyoneCanPayInfos.push({ blake160: output.lock.args, tokenID: output.type?.args || 'CKBytes', + udtType: output.type + ? assetAccountInfo.isSudtScript(output.type) + ? UDTType.SUDT + : UDTType.XUDT + : undefined, }) } if (this.lockHashes.has(output.lockHash!)) { @@ -86,6 +95,7 @@ export default class TxAddressFinder { const anyoneCanPayInfos: AnyoneCanPayInfo[] = [] const inputs = this.tx.inputs!.filter(i => i.previousOutput !== null) const isMainnet = NetworksService.getInstance().isMainnet() + const assetAccountInfo = new AssetAccountInfo() let shouldSync = false for (const input of inputs) { @@ -100,6 +110,11 @@ export default class TxAddressFinder { anyoneCanPayInfos.push({ blake160: output.lockArgs, tokenID: output.typeArgs || 'CKBytes', + udtType: output.typeScript() + ? assetAccountInfo.isSudtScript(output.typeScript()!) + ? UDTType.SUDT + : UDTType.XUDT + : undefined, }) } if (output && this.lockHashes.has(output.lockHash)) { diff --git a/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts b/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts index 1a2532559b..3d996b3cf7 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts @@ -7,6 +7,7 @@ import TransactionWithStatus from '../models/chain/transaction-with-status' import logger from '../utils/logger' import { getConnection } from '../database/chain/connection' import { interval } from 'rxjs' +import TxStatus from '../models/chain/tx-status' type TransactionDetail = { hash: string @@ -18,7 +19,8 @@ type TransactionDetail = { const getTransactionStatus = async (hash: string) => { const network = NetworksService.getInstance().getCurrent() const rpcService = new RpcService(network.remote, network.type) - const txWithStatus: TransactionWithStatus | undefined = await rpcService.getTransaction(hash) + const txWithStatus: TransactionWithStatus | undefined | { transaction: null; txStatus: TxStatus } = + await rpcService.getTransaction(hash) if (!txWithStatus) { return { tx: txWithStatus, @@ -33,6 +35,13 @@ const getTransactionStatus = async (hash: string) => { blockHash: txWithStatus.txStatus.blockHash, } } + if (txWithStatus.txStatus.isRejected()) { + return { + tx: null, + status: TransactionStatus.Rejected, + blockHash: null, + } + } return { tx: txWithStatus.transaction, status: TransactionStatus.Pending, @@ -41,16 +50,16 @@ const getTransactionStatus = async (hash: string) => { } const trackingStatus = async () => { - const pendingTransactions = await FailedTransaction.pendings() + const pendingOrFailedTransactions = await FailedTransaction.pendingOrFaileds() await FailedTransaction.processAmendFailedTxs() - if (!pendingTransactions.length) { + if (!pendingOrFailedTransactions.length) { return } - const pendingHashes = pendingTransactions.map(tx => tx.hash) + const pendingOrFailedHashes = pendingOrFailedTransactions.map(tx => tx.hash) const txs = await Promise.all( - pendingHashes.map(async hash => { + pendingOrFailedHashes.map(async hash => { try { const txWithStatus = await getTransactionStatus(hash) return { @@ -65,17 +74,18 @@ const trackingStatus = async () => { }) ) - const failedTxs = txs.filter( - (tx): tx is TransactionDetail & { status: TransactionStatus.Failed } => tx?.status === TransactionStatus.Failed - ) - const successTxs = txs.filter( - (tx): tx is TransactionDetail & { status: TransactionStatus.Success } => tx?.status === TransactionStatus.Success - ) + const failedTxs = txs.filter((tx): tx is TransactionDetail => tx?.status === TransactionStatus.Failed) + const successTxs = txs.filter((tx): tx is TransactionDetail => tx?.status === TransactionStatus.Success) + const rejectedTxs = txs.filter((tx): tx is TransactionDetail => tx?.status === TransactionStatus.Rejected) if (failedTxs.length) { await FailedTransaction.updateFailedTxs(failedTxs.map(tx => tx.hash)) } + if (rejectedTxs.length) { + await FailedTransaction.deleteFailedTxs(rejectedTxs.map(tx => tx.hash)) + } + if (successTxs.length > 0) { const network = NetworksService.getInstance().getCurrent() const rpcService = new RpcService(network.remote, network.type) diff --git a/packages/neuron-wallet/src/controllers/anyone-can-pay.ts b/packages/neuron-wallet/src/controllers/anyone-can-pay.ts index df092470bf..9848f808ea 100644 --- a/packages/neuron-wallet/src/controllers/anyone-can-pay.ts +++ b/packages/neuron-wallet/src/controllers/anyone-can-pay.ts @@ -1,7 +1,7 @@ import AssetAccountInfo from '../models/asset-account-info' import Transaction from '../models/chain/transaction' import { ServiceHasNoResponse } from '../exceptions' -import { ResponseCode } from '../utils/const' +import { ResponseCode, UDTType } from '../utils/const' import AnyoneCanPayService from '../services/anyone-can-pay' import TransactionSender from '../services/transaction-sender' import { set as setDescription } from '../services/tx/transaction-description' @@ -49,10 +49,11 @@ export default class AnyoneCanPayController { public async getHoldSudtCellCapacity( receiveAddress: string, - tokenID: string + tokenID: string, + udtType?: UDTType ): Promise> { const lockScript = AddressParser.parse(receiveAddress) - const extraCKB = await AnyoneCanPayService.getHoldSUDTCellCapacity(lockScript, tokenID) + const extraCKB = await AnyoneCanPayService.getHoldSUDTCellCapacity(lockScript, tokenID, udtType) return { status: ResponseCode.Success, result: extraCKB, diff --git a/packages/neuron-wallet/src/controllers/api.ts b/packages/neuron-wallet/src/controllers/api.ts index 7f5b8b6aed..d60b6325af 100644 --- a/packages/neuron-wallet/src/controllers/api.ts +++ b/packages/neuron-wallet/src/controllers/api.ts @@ -24,7 +24,7 @@ import { ConnectionStatusSubject } from '../models/subjects/node' import NetworksService from '../services/networks' import WalletsService from '../services/wallets' import SettingsService, { Locale } from '../services/settings' -import { ResponseCode } from '../utils/const' +import { ResponseCode, UDTType } from '../utils/const' import { clean as cleanChain } from '../database/chain' import WalletsController from '../controllers/wallets' import TransactionsController from '../controllers/transactions' @@ -64,7 +64,7 @@ import DataUpdateSubject from '../models/subjects/data-update' import CellManagement from './cell-management' import { UpdateCellLocalInfo } from '../database/chain/entities/cell-local-info' import { CKBLightRunner } from '../services/light-runner' -import { OutPoint } from '@ckb-lumos/base' +import { type OutPoint } from '@ckb-lumos/lumos' import { updateApplicationMenu } from './app/menu' export type Command = 'export-xpubkey' | 'import-xpubkey' | 'delete-wallet' | 'backup-wallet' @@ -801,9 +801,12 @@ export default class ApiController { return this.#anyoneCanPayController.generateTx(params) }) - handle('get-hold-sudt-cell-capacity', async (_, params: { address: string; tokenID: string }) => { - return this.#anyoneCanPayController.getHoldSudtCellCapacity(params.address, params.tokenID) - }) + handle( + 'get-hold-sudt-cell-capacity', + async (_, params: { address: string; tokenID: string; udtType?: UDTType }) => { + return this.#anyoneCanPayController.getHoldSudtCellCapacity(params.address, params.tokenID, params.udtType) + } + ) handle('send-to-anyone-can-pay', async (_, params: SendAnyoneCanPayTxParams) => { return this.#anyoneCanPayController.sendTx(params) @@ -817,10 +820,6 @@ export default class ApiController { return this.#sudtController.getSUDTTokenInfo(params) }) - handle('get-sudt-type-script-hash', async (_, params: { tokenID: string }) => { - return this.#sudtController.getSUDTTypeScriptHash(params) - }) - handle('generate-destroy-asset-account-tx', async (_, params: { walletID: string; id: number }) => { return this.#assetAccountController.destroyAssetAccount(params) }) diff --git a/packages/neuron-wallet/src/controllers/asset-account.ts b/packages/neuron-wallet/src/controllers/asset-account.ts index 1469996125..1fefd3e22e 100644 --- a/packages/neuron-wallet/src/controllers/asset-account.ts +++ b/packages/neuron-wallet/src/controllers/asset-account.ts @@ -3,7 +3,7 @@ import AssetAccount from '../models/asset-account' import Transaction from '../models/chain/transaction' import AssetAccountService from '../services/asset-account-service' import { ServiceHasNoResponse } from '../exceptions' -import { ResponseCode } from '../utils/const' +import { ResponseCode, UDTType } from '../utils/const' import NetworksService from '../services/networks' import AssetAccountInfo from '../models/asset-account-info' import TransactionSender from '../services/transaction-sender' @@ -22,6 +22,7 @@ export interface GenerateCreateAssetAccountTxParams { decimal: string feeRate: string fee: string + udtType?: UDTType } export interface SendCreateAssetAccountTxParams { @@ -137,16 +138,7 @@ export default class AssetAccountController { tx: Transaction }> > { - const result = await AssetAccountService.generateCreateTx( - params.walletID, - params.tokenID, - params.symbol, - params.accountName, - params.tokenName, - params.decimal, - params.feeRate, - params.fee - ) + const result = await AssetAccountService.generateCreateTx(params) if (!result) { throw new ServiceHasNoResponse('AssetAccount') diff --git a/packages/neuron-wallet/src/controllers/cell-management.ts b/packages/neuron-wallet/src/controllers/cell-management.ts index 9bf158a65f..1ad6b37cb1 100644 --- a/packages/neuron-wallet/src/controllers/cell-management.ts +++ b/packages/neuron-wallet/src/controllers/cell-management.ts @@ -1,4 +1,4 @@ -import type { OutPoint as OutPointSDK, Script } from '@ckb-lumos/base' +import type { OutPoint as OutPointSDK, Script } from '@ckb-lumos/lumos' import CellLocalInfo, { UpdateCellLocalInfo } from '../database/chain/entities/cell-local-info' import Output from '../models/chain/output' import CellsService, { LockScriptCategory, TypeScriptCategory } from '../services/cells' diff --git a/packages/neuron-wallet/src/controllers/dao.ts b/packages/neuron-wallet/src/controllers/dao.ts index 2dccf9e798..37e30447ad 100644 --- a/packages/neuron-wallet/src/controllers/dao.ts +++ b/packages/neuron-wallet/src/controllers/dao.ts @@ -1,4 +1,4 @@ -import { type OutPoint as OutPointSDK } from '@ckb-lumos/base' +import { type OutPoint as OutPointSDK } from '@ckb-lumos/lumos' import { ServiceHasNoResponse, IsRequired } from '../exceptions' import { ResponseCode } from '../utils/const' import CellsService from '../services/cells' diff --git a/packages/neuron-wallet/src/controllers/hardware.ts b/packages/neuron-wallet/src/controllers/hardware.ts index e8e9aa0cfa..563fe58c89 100644 --- a/packages/neuron-wallet/src/controllers/hardware.ts +++ b/packages/neuron-wallet/src/controllers/hardware.ts @@ -2,7 +2,7 @@ import { DeviceInfo, ExtendedPublicKey, PublicKey } from '../services/hardware/c import { ResponseCode } from '../utils/const' import HardwareWalletService from '../services/hardware' import { connectDeviceFailed } from '../exceptions' -import { AccountExtendedPublicKey } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' export default class HardwareController { public async connectDevice(deviceInfo: DeviceInfo): Promise> { @@ -50,7 +50,7 @@ export default class HardwareController { public async getPublicKey(): Promise> { const device = HardwareWalletService.getInstance().getCurrent()! - const defaultPath = AccountExtendedPublicKey.ckbAccountPath + const defaultPath = hd.AccountExtendedPublicKey.ckbAccountPath const pubkey = await device.getPublicKey(defaultPath) return { diff --git a/packages/neuron-wallet/src/controllers/multisig.ts b/packages/neuron-wallet/src/controllers/multisig.ts index ad5912cc84..8dfa307756 100644 --- a/packages/neuron-wallet/src/controllers/multisig.ts +++ b/packages/neuron-wallet/src/controllers/multisig.ts @@ -2,7 +2,7 @@ import fs from 'fs' import path from 'path' import { dialog, BrowserWindow } from 'electron' import { t } from 'i18next' -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import { scriptToAddress, addressToScript } from '../utils/scriptAndAddress' import { ResponseCode } from '../utils/const' import { parseMultisigTxJsonFromCkbCli } from '../utils/multisig' diff --git a/packages/neuron-wallet/src/controllers/sudt.ts b/packages/neuron-wallet/src/controllers/sudt.ts index 7b9813c497..c643890635 100644 --- a/packages/neuron-wallet/src/controllers/sudt.ts +++ b/packages/neuron-wallet/src/controllers/sudt.ts @@ -1,4 +1,3 @@ -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' import LiveCellService from '../services/live-cell-service' import AssetAccountInfo from '../models/asset-account-info' import Script, { ScriptHashType } from '../models/chain/script' @@ -35,13 +34,4 @@ export default class SUDTController { result: { tokenID: params.tokenID, symbol: symbol, tokenName: name, decimal: decimal }, } } - - public getSUDTTypeScriptHash(params: { tokenID: string }): Controller.Response { - const assetAccount = new AssetAccountInfo() - const script = new Script(assetAccount.infos.sudt.codeHash, params.tokenID, assetAccount.infos.sudt.hashType) - return { - status: ResponseCode.Success, - result: scriptToHash(script.toSDK()), - } - } } diff --git a/packages/neuron-wallet/src/controllers/wallets.ts b/packages/neuron-wallet/src/controllers/wallets.ts index 98566937b4..50dd050c3f 100644 --- a/packages/neuron-wallet/src/controllers/wallets.ts +++ b/packages/neuron-wallet/src/controllers/wallets.ts @@ -4,9 +4,8 @@ import { prefixWith0x } from '../utils/scriptAndAddress' import { dialog, SaveDialogReturnValue, BrowserWindow, OpenDialogReturnValue } from 'electron' import WalletsService, { Wallet, WalletProperties, FileKeystoreWallet } from '../services/wallets' import NetworksService from '../services/networks' -import { bytes } from '@ckb-lumos/codec' -import { Keychain, Keystore, ExtendedPrivateKey, AccountExtendedPublicKey } from '@ckb-lumos/hd' -import { generateMnemonic, validateMnemonic, mnemonicToSeedSync } from '@ckb-lumos/hd/lib/mnemonic' +import { bytes } from '@ckb-lumos/lumos/codec' +import { hd } from '@ckb-lumos/lumos' import CommandSubject from '../models/subjects/command' import { ResponseCode } from '../utils/const' import { @@ -35,6 +34,9 @@ import AddressParser from '../models/address-parser' import MultisigConfigModel from '../models/multisig-config' import { generateRPC } from '../utils/ckb-rpc' +const { Keychain, Keystore, ExtendedPrivateKey, AccountExtendedPublicKey, mnemonic } = hd +const { generateMnemonic, validateMnemonic, mnemonicToSeedSync } = mnemonic + export default class WalletsController { public async getAll(): Promise[]>> { const wallets = WalletsService.getInstance().getAll() @@ -230,7 +232,7 @@ export default class WalletsController { throw new WalletNotFound(id) } - const props: { name: string; keystore?: Keystore; device?: DeviceInfo; startBlockNumber?: string } = { + const props: { name: string; keystore?: hd.Keystore; device?: DeviceInfo; startBlockNumber?: string } = { name: name || wallet.name, startBlockNumber, } diff --git a/packages/neuron-wallet/src/database/address/meta.ts b/packages/neuron-wallet/src/database/address/meta.ts index 36de7a34f3..5ef8db354d 100644 --- a/packages/neuron-wallet/src/database/address/meta.ts +++ b/packages/neuron-wallet/src/database/address/meta.ts @@ -1,6 +1,6 @@ -import { bytes } from '@ckb-lumos/codec' +import { bytes } from '@ckb-lumos/lumos/codec' import { Address, AddressVersion } from '../../models/address' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import Script from '../../models/chain/script' import SystemScriptInfo from '../../models/system-script-info' import AssetAccountInfo from '../../models/asset-account-info' @@ -11,7 +11,7 @@ export default class AddressMeta implements Address { walletId: string address: string path: string - addressType: AddressType + addressType: hd.AddressType addressIndex: number blake160: string txCount?: number @@ -28,7 +28,7 @@ export default class AddressMeta implements Address { walletId: string, address: string, path: string, - addressType: AddressType, + addressType: hd.AddressType, addressIndex: number, blake160: string, version?: AddressVersion, diff --git a/packages/neuron-wallet/src/database/chain/entities/asset-account.ts b/packages/neuron-wallet/src/database/chain/entities/asset-account.ts index d59d67ecd4..009e30b8e3 100644 --- a/packages/neuron-wallet/src/database/chain/entities/asset-account.ts +++ b/packages/neuron-wallet/src/database/chain/entities/asset-account.ts @@ -1,9 +1,10 @@ import { Entity, Column, PrimaryGeneratedColumn, Index, ManyToOne, JoinColumn } from 'typeorm' import AssetAccountModel from '../../../models/asset-account' import SudtTokenInfo from './sudt-token-info' +import { UDTType } from '../../../utils/const' @Entity() -@Index(['tokenID', 'blake160'], { unique: true }) +@Index(['tokenID', 'blake160', 'udtType'], { unique: true }) export default class AssetAccount { @PrimaryGeneratedColumn() id!: number @@ -13,6 +14,12 @@ export default class AssetAccount { }) tokenID!: string + @Column({ + type: 'varchar', + nullable: true, + }) + udtType?: UDTType + @Column({ type: 'varchar', default: '', @@ -40,12 +47,14 @@ export default class AssetAccount { assetAccount.accountName = info.accountName assetAccount.balance = info.balance assetAccount.blake160 = info.blake160 + assetAccount.udtType = info.udtType const sudtTokenInfo = new SudtTokenInfo() sudtTokenInfo.tokenID = info.tokenID sudtTokenInfo.symbol = info.symbol sudtTokenInfo.tokenName = info.tokenName sudtTokenInfo.decimal = info.decimal + sudtTokenInfo.udtType = info.udtType assetAccount.sudtTokenInfo = sudtTokenInfo return assetAccount @@ -60,7 +69,8 @@ export default class AssetAccount { this.sudtTokenInfo.decimal, this.balance, this.blake160, - this.id + this.id, + this.udtType ) } } diff --git a/packages/neuron-wallet/src/database/chain/entities/cell-local-info.ts b/packages/neuron-wallet/src/database/chain/entities/cell-local-info.ts index 714e012559..a86b1a1885 100644 --- a/packages/neuron-wallet/src/database/chain/entities/cell-local-info.ts +++ b/packages/neuron-wallet/src/database/chain/entities/cell-local-info.ts @@ -1,4 +1,4 @@ -import type { OutPoint } from '@ckb-lumos/base' +import type { OutPoint } from '@ckb-lumos/lumos' import { Entity, PrimaryColumn, Column } from 'typeorm' @Entity() diff --git a/packages/neuron-wallet/src/database/chain/entities/hd-public-key-info.ts b/packages/neuron-wallet/src/database/chain/entities/hd-public-key-info.ts index e5fa061106..076b5ddc0c 100644 --- a/packages/neuron-wallet/src/database/chain/entities/hd-public-key-info.ts +++ b/packages/neuron-wallet/src/database/chain/entities/hd-public-key-info.ts @@ -1,6 +1,6 @@ import { Entity, Column, PrimaryGeneratedColumn, Index, CreateDateColumn } from 'typeorm' import HdPublicKeyInfoModel from '../../../models/keys/hd-public-key-info' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' @Entity() export default class HdPublicKeyInfo { @@ -14,7 +14,7 @@ export default class HdPublicKeyInfo { walletId!: string @Column() - addressType!: AddressType + addressType!: hd.AddressType @Column() @Index() diff --git a/packages/neuron-wallet/src/database/chain/entities/multisig-output.ts b/packages/neuron-wallet/src/database/chain/entities/multisig-output.ts index 628d93f827..61a7a302fb 100644 --- a/packages/neuron-wallet/src/database/chain/entities/multisig-output.ts +++ b/packages/neuron-wallet/src/database/chain/entities/multisig-output.ts @@ -1,7 +1,7 @@ import { Entity, BaseEntity, Column, PrimaryColumn } from 'typeorm' import Script, { ScriptHashType } from '../../../models/chain/script' import OutPoint from '../../../models/chain/out-point' -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import { OutputStatus } from '../../../models/chain/output' @Entity() diff --git a/packages/neuron-wallet/src/database/chain/entities/sudt-token-info.ts b/packages/neuron-wallet/src/database/chain/entities/sudt-token-info.ts index ec0614395b..35c6512f3a 100644 --- a/packages/neuron-wallet/src/database/chain/entities/sudt-token-info.ts +++ b/packages/neuron-wallet/src/database/chain/entities/sudt-token-info.ts @@ -1,14 +1,21 @@ import { Entity, Column, Index, OneToMany, PrimaryColumn } from 'typeorm' import AssetAccount from './asset-account' +import { UDTType } from '../../../utils/const' @Entity() -@Index(['tokenID'], { unique: true }) +@Index(['tokenID', 'udtType'], { unique: true }) export default class SudtTokenInfo { @PrimaryColumn({ type: 'varchar', }) tokenID!: string + @Column({ + type: 'varchar', + nullable: true, + }) + udtType?: UDTType + @Column({ type: 'varchar', }) @@ -33,6 +40,7 @@ export default class SudtTokenInfo { tokenName: this.tokenName, symbol: this.symbol, decimal: this.decimal, + udtType: this.udtType, } } } diff --git a/packages/neuron-wallet/src/database/chain/entities/sync-progress.ts b/packages/neuron-wallet/src/database/chain/entities/sync-progress.ts index 75229b5ec4..8400216781 100644 --- a/packages/neuron-wallet/src/database/chain/entities/sync-progress.ts +++ b/packages/neuron-wallet/src/database/chain/entities/sync-progress.ts @@ -1,5 +1,5 @@ -import { HexString } from '@ckb-lumos/base' -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { HexString } from '@ckb-lumos/lumos' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import { Entity, PrimaryColumn, Column } from 'typeorm' export enum SyncAddressType { diff --git a/packages/neuron-wallet/src/database/chain/migrations/1652945662504-UpdateOutputChequeLockHash.ts b/packages/neuron-wallet/src/database/chain/migrations/1652945662504-UpdateOutputChequeLockHash.ts index 01d8d3a719..6b23fd4d6c 100644 --- a/packages/neuron-wallet/src/database/chain/migrations/1652945662504-UpdateOutputChequeLockHash.ts +++ b/packages/neuron-wallet/src/database/chain/migrations/1652945662504-UpdateOutputChequeLockHash.ts @@ -1,5 +1,5 @@ import { In, MigrationInterface, QueryRunner } from "typeorm"; -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import { ScriptHashType } from "../../../models/chain/script"; import Output from "../entities/output"; diff --git a/packages/neuron-wallet/src/database/chain/migrations/1681360188494-AddTypeSyncProgress.ts b/packages/neuron-wallet/src/database/chain/migrations/1681360188494-AddTypeSyncProgress.ts index 3958f3e287..9a268ee990 100644 --- a/packages/neuron-wallet/src/database/chain/migrations/1681360188494-AddTypeSyncProgress.ts +++ b/packages/neuron-wallet/src/database/chain/migrations/1681360188494-AddTypeSyncProgress.ts @@ -1,6 +1,6 @@ import { MigrationInterface, QueryRunner, TableColumn, TableIndex } from "typeorm" import Multisig from "../../../models/multisig" -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import { SyncAddressType } from "../entities/sync-progress" import MultisigConfig from "../entities/multisig-config" diff --git a/packages/neuron-wallet/src/database/chain/migrations/1720089814860-AddUdtType.ts b/packages/neuron-wallet/src/database/chain/migrations/1720089814860-AddUdtType.ts new file mode 100644 index 0000000000..b30e1bf7f3 --- /dev/null +++ b/packages/neuron-wallet/src/database/chain/migrations/1720089814860-AddUdtType.ts @@ -0,0 +1,22 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class AddUdtType1720089814860 implements MigrationInterface { + name = 'AddUdtType1720089814860' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "sudt_token_info" ADD COLUMN "udtType" varchar;`) + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_37bb4f2a4a849bf0b1dadee2c7" ON "sudt_token_info" ("tokenID", "udtType") `); + await queryRunner.query(`UPDATE "sudt_token_info" set udtType="sUDT" where tokenID!="CKBytes"`) + await queryRunner.query(`ALTER TABLE "asset_account" ADD COLUMN "udtType" varchar;`) + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_5139df6b311e63ecdd93cd17ed" ON "asset_account" ("tokenID", "blake160", "udtType") `); + await queryRunner.query(`UPDATE "asset_account" set udtType="sUDT" where tokenID!="CKBytes"`) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_37bb4f2a4a849bf0b1dadee2c7"`); + await queryRunner.query(`ALTER TABLE "sudt_token_info" DROP COLUMN "udtType";`); + await queryRunner.query(`DROP INDEX "IDX_5139df6b311e63ecdd93cd17ed"`); + await queryRunner.query(`ALTER TABLE "asset_account" DROP COLUMN "udtType";`); + } + +} diff --git a/packages/neuron-wallet/src/database/chain/ormconfig.ts b/packages/neuron-wallet/src/database/chain/ormconfig.ts index c3458375cd..b8699466d2 100644 --- a/packages/neuron-wallet/src/database/chain/ormconfig.ts +++ b/packages/neuron-wallet/src/database/chain/ormconfig.ts @@ -69,6 +69,7 @@ import TxDescriptionSubscribe from './subscriber/tx-description-subscriber' import SudtTokenInfoSubscribe from './subscriber/sudt-token-info-subscriber' import AssetAccountSubscribe from './subscriber/asset-account-subscriber' import { AddStartBlockNumber1716539079505 } from './migrations/1716539079505-AddStartBlockNumber' +import { AddUdtType1720089814860 } from './migrations/1720089814860-AddUdtType' export const CONNECTION_NOT_FOUND_NAME = 'ConnectionNotFoundError' export type ConnectionName = 'light' | 'full' @@ -186,6 +187,7 @@ const getConnectionOptions = (genesisBlockHash: string, connectionName: Connecti RemoveAddressInIndexerCache1704357651876, AmendTransaction1709008125088, AddStartBlockNumber1716539079505, + AddUdtType1720089814860, ], subscribers: [ AddressSubscribe, diff --git a/packages/neuron-wallet/src/models/address.ts b/packages/neuron-wallet/src/models/address.ts index f8827a1c78..14243b1e86 100644 --- a/packages/neuron-wallet/src/models/address.ts +++ b/packages/neuron-wallet/src/models/address.ts @@ -1,4 +1,4 @@ -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' export enum AddressVersion { Testnet = 'testnet', @@ -9,7 +9,7 @@ export interface Address { walletId: string address: string path: string - addressType: AddressType + addressType: hd.AddressType addressIndex: number blake160: string txCount?: number diff --git a/packages/neuron-wallet/src/models/asset-account-info.ts b/packages/neuron-wallet/src/models/asset-account-info.ts index 285abb9cf6..1cd76177ba 100644 --- a/packages/neuron-wallet/src/models/asset-account-info.ts +++ b/packages/neuron-wallet/src/models/asset-account-info.ts @@ -1,4 +1,5 @@ -import { bytes, molecule } from '@ckb-lumos/codec' +import { bytes, struct, createFixedBytesCodec } from '@ckb-lumos/lumos/codec' +import { predefined } from '@ckb-lumos/config-manager' import CellDep, { DepType } from './chain/cell-dep' import Script, { ScriptHashType } from './chain/script' import OutPoint from './chain/out-point' @@ -6,9 +7,12 @@ import NetworksService from '../services/networks' import Transaction from './chain/transaction' import SystemScriptInfo from './system-script-info' import { Address } from './address' -import { createFixedHexBytesCodec } from '@ckb-lumos/codec/lib/blockchain' +import { UDTType } from '../utils/const' import { predefinedSporeConfigs, SporeConfig, SporeScript } from '@spore-sdk/core' +const createFixedHexBytesCodec = (byteLength: number) => + createFixedBytesCodec({ byteLength, pack: bytes.bytify, unpack: bytes.hexify }) + export interface ScriptCellInfo { cellDep: CellDep codeHash: string @@ -25,6 +29,7 @@ export default class AssetAccountInfo { private nftIssuerInfo: ScriptCellInfo private nftClassInfo: ScriptCellInfo private nftInfo: ScriptCellInfo + private xudt: ScriptCellInfo private sporeInfos: ScriptCellInfo[] private sporeClusterInfos: ScriptCellInfo[] @@ -37,19 +42,32 @@ export default class AssetAccountInfo { sudt: this.sudt, sudtInfo: this.sudtInfo, anyoneCanPay: this.anyoneCanPayInfo, + xudt: this.xudt, } } constructor(genesisBlockHash: string = NetworksService.getInstance().getCurrent().genesisHash) { - if (genesisBlockHash === AssetAccountInfo.MAINNET_GENESIS_BLOCK_HASH) { - this.sudt = { - cellDep: new CellDep( - new OutPoint(process.env.MAINNET_SUDT_DEP_TXHASH!, process.env.MAINNET_SUDT_DEP_INDEX!), - process.env.MAINNET_SUDT_DEP_TYPE! as DepType - ), - codeHash: process.env.MAINNET_SUDT_SCRIPT_CODEHASH!, - hashType: process.env.MAINNET_SUDT_SCRIPT_HASHTYPE! as ScriptHashType, - } + const isMainnet = genesisBlockHash === AssetAccountInfo.MAINNET_GENESIS_BLOCK_HASH + const { XUDT, SUDT, ANYONE_CAN_PAY } = isMainnet ? predefined.LINA.SCRIPTS : predefined.AGGRON4.SCRIPTS + this.xudt = { + cellDep: new CellDep(new OutPoint(XUDT.TX_HASH, XUDT.INDEX), XUDT.DEP_TYPE as DepType), + codeHash: XUDT.CODE_HASH, + hashType: XUDT.HASH_TYPE as ScriptHashType, + } + this.sudt = { + cellDep: new CellDep(new OutPoint(SUDT.TX_HASH, SUDT.INDEX), SUDT.DEP_TYPE as DepType), + codeHash: SUDT.CODE_HASH, + hashType: SUDT.HASH_TYPE as ScriptHashType, + } + this.anyoneCanPayInfo = { + cellDep: new CellDep( + new OutPoint(ANYONE_CAN_PAY.TX_HASH, ANYONE_CAN_PAY.INDEX), + ANYONE_CAN_PAY.DEP_TYPE as DepType + ), + codeHash: ANYONE_CAN_PAY.CODE_HASH, + hashType: ANYONE_CAN_PAY.HASH_TYPE as ScriptHashType, + } + if (isMainnet) { this.sudtInfo = { cellDep: new CellDep( new OutPoint(process.env.MAINNET_SUDT_INFO_DEP_TXHASH!, process.env.MAINNET_SUDT_INFO_DEP_INDEX!), @@ -58,14 +76,6 @@ export default class AssetAccountInfo { codeHash: process.env.MAINNET_SUDT_INFO_SCRIPT_CODEHASH!, hashType: process.env.MAINNET_SUDT_INFO_SCRIPT_HASHTYPE! as ScriptHashType, } - this.anyoneCanPayInfo = { - cellDep: new CellDep( - new OutPoint(process.env.MAINNET_ACP_DEP_TXHASH!, process.env.MAINNET_ACP_DEP_INDEX!), - process.env.MAINNET_ACP_DEP_TYPE! as DepType - ), - codeHash: process.env.MAINNET_ACP_SCRIPT_CODEHASH!, - hashType: process.env.MAINNET_ACP_SCRIPT_HASHTYPE! as ScriptHashType, - } this.legacyAnyoneCanPayInfo = { cellDep: new CellDep( new OutPoint(process.env.LEGACY_MAINNET_ACP_DEP_TXHASH!, process.env.LEGACY_MAINNET_ACP_DEP_INDEX!), @@ -114,19 +124,10 @@ export default class AssetAccountInfo { codeHash: process.env.MAINNET_NFT_SCRIPT_CODEHASH!, hashType: process.env.MAINNET_NFT_SCRIPT_HASH_TYPE! as ScriptHashType, } - // TODO infos for mainnet this.sporeInfos = [] this.sporeClusterInfos = [] } else { - this.sudt = { - cellDep: new CellDep( - new OutPoint(process.env.TESTNET_SUDT_DEP_TXHASH!, process.env.TESTNET_SUDT_DEP_INDEX!), - process.env.TESTNET_SUDT_DEP_TYPE! as DepType - ), - codeHash: process.env.TESTNET_SUDT_SCRIPT_CODEHASH!, - hashType: process.env.TESTNET_SUDT_SCRIPT_HASHTYPE! as ScriptHashType, - } this.sudtInfo = { cellDep: new CellDep( new OutPoint(process.env.TESTNET_SUDT_INFO_DEP_TXHASH!, process.env.TESTNET_SUDT_INFO_DEP_INDEX!), @@ -135,14 +136,6 @@ export default class AssetAccountInfo { codeHash: process.env.TESTNET_SUDT_INFO_SCRIPT_CODEHASH!, hashType: process.env.TESTNET_SUDT_INFO_SCRIPT_HASHTYPE! as ScriptHashType, } - this.anyoneCanPayInfo = { - cellDep: new CellDep( - new OutPoint(process.env.TESTNET_ACP_DEP_TXHASH!, process.env.TESTNET_ACP_DEP_INDEX!), - process.env.TESTNET_ACP_DEP_TYPE! as DepType - ), - codeHash: process.env.TESTNET_ACP_SCRIPT_CODEHASH!, - hashType: process.env.TESTNET_ACP_SCRIPT_HASHTYPE! as ScriptHashType, - } this.legacyAnyoneCanPayInfo = { cellDep: new CellDep( new OutPoint(process.env.LEGACY_TESTNET_ACP_DEP_TXHASH!, process.env.LEGACY_TESTNET_ACP_DEP_INDEX!), @@ -211,6 +204,10 @@ export default class AssetAccountInfo { return this.anyoneCanPayInfo.cellDep } + public get xudtCellDep(): CellDep { + return this.xudt.cellDep + } + public get anyoneCanPayCodeHash(): string { return this.anyoneCanPayInfo.codeHash } @@ -243,10 +240,6 @@ export default class AssetAccountInfo { return this.sporeClusterInfos } - public getAcpCodeHash(): string { - return this.anyoneCanPayInfo.codeHash - } - public getSudtCodeHash(): string { return this.sudt.codeHash } @@ -271,10 +264,29 @@ export default class AssetAccountInfo { return new Script(info.codeHash, args, info.hashType) } + public generateXudtScript(args: string): Script { + return new Script(this.xudt.codeHash, args, this.xudt.hashType) + } + + public generateUdtScript(args: string, udtType?: UDTType): Script | undefined { + switch (udtType) { + case UDTType.SUDT: + return this.generateSudtScript(args) + case UDTType.XUDT: + return this.generateXudtScript(args) + default: + return undefined + } + } + public isSudtScript(script: Script): boolean { return script.codeHash === this.sudt.codeHash && script.hashType === this.sudt.hashType } + public isXudtScript(script: Script): boolean { + return script.codeHash === this.xudt.codeHash && script.hashType === this.xudt.hashType + } + public isAnyoneCanPayScript(script: Script): boolean { const acpScripts = [this.anyoneCanPayInfo, this.pwAnyoneCanPayInfo] const exist = acpScripts.find(acpScript => { @@ -307,7 +319,7 @@ export default class AssetAccountInfo { public static findSignPathForCheque(addressInfos: Address[], chequeLockArgs: string) { const Bytes20 = createFixedHexBytesCodec(20) - const ChequeLockArgsCodec = molecule.struct( + const ChequeLockArgsCodec = struct( { receiverLockHash: Bytes20, senderLockHash: Bytes20, diff --git a/packages/neuron-wallet/src/models/asset-account.ts b/packages/neuron-wallet/src/models/asset-account.ts index 38f295423b..06e3c09ea8 100644 --- a/packages/neuron-wallet/src/models/asset-account.ts +++ b/packages/neuron-wallet/src/models/asset-account.ts @@ -1,3 +1,5 @@ +import { UDTType } from '../utils/const' + export default class AssetAccount { public id?: number public tokenID: string @@ -7,6 +9,7 @@ export default class AssetAccount { public decimal: string public balance: string public blake160: string + public udtType?: UDTType constructor( tokenID: string, @@ -16,7 +19,8 @@ export default class AssetAccount { decimal: string, balance: string, blake160: string, - id?: number + id?: number, + udtType?: UDTType ) { this.tokenID = tokenID this.symbol = symbol @@ -26,6 +30,7 @@ export default class AssetAccount { this.balance = balance this.blake160 = blake160 this.id = id + this.udtType = udtType } public static fromObject(params: { @@ -37,6 +42,7 @@ export default class AssetAccount { balance: string blake160: string id?: number + udtType?: UDTType }): AssetAccount { return new AssetAccount( params.tokenID, @@ -46,7 +52,8 @@ export default class AssetAccount { params.decimal, params.balance, params.blake160, - params.id + params.id, + params.udtType ) } } diff --git a/packages/neuron-wallet/src/models/blake2b.ts b/packages/neuron-wallet/src/models/blake2b.ts index 33c01368df..1cb5548ab2 100644 --- a/packages/neuron-wallet/src/models/blake2b.ts +++ b/packages/neuron-wallet/src/models/blake2b.ts @@ -1,5 +1,5 @@ -import { CKBHasher } from '@ckb-lumos/base/lib/utils' -import { bytes } from '@ckb-lumos/codec' +import { CKBHasher } from '@ckb-lumos/lumos/utils' +import { bytes } from '@ckb-lumos/lumos/codec' export const BLAKE160_HEX_LENGTH = 42 diff --git a/packages/neuron-wallet/src/models/chain/input.ts b/packages/neuron-wallet/src/models/chain/input.ts index 352989fab8..fcd587d2c1 100644 --- a/packages/neuron-wallet/src/models/chain/input.ts +++ b/packages/neuron-wallet/src/models/chain/input.ts @@ -1,6 +1,6 @@ import OutPoint from './out-point' import Script from './script' -import { BI } from '@ckb-lumos/bi' +import { BI } from '@ckb-lumos/lumos' import TypeChecker from '../../utils/type-checker' import { OutputStatus } from './output' diff --git a/packages/neuron-wallet/src/models/chain/live-cell.ts b/packages/neuron-wallet/src/models/chain/live-cell.ts index 9a7cda74a2..4efc95dd60 100644 --- a/packages/neuron-wallet/src/models/chain/live-cell.ts +++ b/packages/neuron-wallet/src/models/chain/live-cell.ts @@ -1,6 +1,6 @@ import Script, { ScriptHashType } from './script' import OutPoint from './out-point' -import { type Cell, type OutPoint as IOutPoint } from '@ckb-lumos/base' +import { type Cell, type OutPoint as IOutPoint } from '@ckb-lumos/lumos' const LUMOS_HASH_TYPE_MAP: Record = { type: ScriptHashType.Type, diff --git a/packages/neuron-wallet/src/models/chain/out-point.ts b/packages/neuron-wallet/src/models/chain/out-point.ts index 4b7f050791..19d30636c6 100644 --- a/packages/neuron-wallet/src/models/chain/out-point.ts +++ b/packages/neuron-wallet/src/models/chain/out-point.ts @@ -1,4 +1,4 @@ -import { BI } from '@ckb-lumos/bi' +import { BI } from '@ckb-lumos/lumos' import TypeChecker from '../../utils/type-checker' export default class OutPoint { diff --git a/packages/neuron-wallet/src/models/chain/output.ts b/packages/neuron-wallet/src/models/chain/output.ts index 9a15c8d774..3d7804c28c 100644 --- a/packages/neuron-wallet/src/models/chain/output.ts +++ b/packages/neuron-wallet/src/models/chain/output.ts @@ -1,8 +1,9 @@ import Script from './script' import OutPoint from './out-point' -import { bytes as byteUtils } from '@ckb-lumos/codec' -import { BI } from '@ckb-lumos/bi' +import { bytes as byteUtils } from '@ckb-lumos/lumos/codec' +import { BI, helpers } from '@ckb-lumos/lumos' import TypeChecker from '../../utils/type-checker' +import { MIN_CELL_CAPACITY } from '../../utils/const' // sent: pending transaction's output // pending: pending transaction's input @@ -109,7 +110,7 @@ export default class Output { depositTimestamp, multiSignBlake160, }: { - capacity: string + capacity?: string data?: string lock: Script type?: Script | null @@ -126,7 +127,18 @@ export default class Output { multiSignBlake160?: string | null }): Output { return new Output( - capacity, + capacity ?? + helpers + .minimalCellCapacity({ + cellOutput: { + // use MIN_CELL_CAPACITY to place holder + capacity: MIN_CELL_CAPACITY.toString(), + lock: Script.fromObject(lock), + type: type ? Script.fromObject(type) : undefined, + }, + data: data ?? '0x', + }) + .toString(), Script.fromObject(lock), type ? Script.fromObject(type) : type, data, @@ -227,4 +239,15 @@ export default class Output { output.type ? Script.fromSDK(output.type) : output.type ) } + + public minimalCellCapacity() { + return helpers.minimalCellCapacity({ + cellOutput: { + capacity: this.capacity, + lock: this.lock, + type: this.type ?? undefined, + }, + data: this.data, + }) + } } diff --git a/packages/neuron-wallet/src/models/chain/script.ts b/packages/neuron-wallet/src/models/chain/script.ts index a83305a59a..40034ea46f 100644 --- a/packages/neuron-wallet/src/models/chain/script.ts +++ b/packages/neuron-wallet/src/models/chain/script.ts @@ -1,5 +1,5 @@ -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' -import { bytes as byteUtils } from '@ckb-lumos/codec' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' +import { bytes as byteUtils } from '@ckb-lumos/lumos/codec' import TypeChecker from '../../utils/type-checker' export enum ScriptHashType { diff --git a/packages/neuron-wallet/src/models/chain/transaction-with-status.ts b/packages/neuron-wallet/src/models/chain/transaction-with-status.ts index 62899b088b..e0972774d3 100644 --- a/packages/neuron-wallet/src/models/chain/transaction-with-status.ts +++ b/packages/neuron-wallet/src/models/chain/transaction-with-status.ts @@ -1,7 +1,9 @@ -import { TransactionWithStatus as APITransactionWithStatus } from '@ckb-lumos/base/lib/api' +import { CKBComponents } from '@ckb-lumos/lumos/rpc' import Transaction from './transaction' import TxStatus from './tx-status' +type APITransactionWithStatus = CKBComponents.TransactionWithStatus + export default class TransactionWithStatus { public transaction: Transaction public txStatus: TxStatus diff --git a/packages/neuron-wallet/src/models/chain/transaction.ts b/packages/neuron-wallet/src/models/chain/transaction.ts index 613143dbb4..1dcf73993c 100644 --- a/packages/neuron-wallet/src/models/chain/transaction.ts +++ b/packages/neuron-wallet/src/models/chain/transaction.ts @@ -2,18 +2,19 @@ import CellDep from './cell-dep' import Input from './input' import Output from './output' import WitnessArgs from './witness-args' -import { BI } from '@ckb-lumos/bi' +import { BI } from '@ckb-lumos/lumos' import { serializeRawTransaction, serializeWitnessArgs } from '../../utils/serialization' import BlockHeader from './block-header' import TypeCheckerUtils from '../../utils/type-checker' import OutPoint from './out-point' import { Signatures } from '../../models/offline-sign' -import { utils } from '@ckb-lumos/base' +import { ckbHash } from '@ckb-lumos/lumos/utils' export enum TransactionStatus { Pending = 'pending', Success = 'success', Failed = 'failed', + Rejected = 'rejected', } export interface SudtTokenInfo { @@ -41,6 +42,7 @@ export interface NFTInfo { export enum AssetAccountType { CKB = 'CKB', SUDT = 'sUDT', + XUDT = 'xUDT', } export default class Transaction { @@ -278,7 +280,7 @@ export default class Transaction { } public computeHash(): string { - return utils.ckbHash(serializeRawTransaction(this.toSDKRawTransaction())) + return ckbHash(serializeRawTransaction(this.toSDKRawTransaction())) } public toSDKRawTransaction(): CKBComponents.RawTransaction { diff --git a/packages/neuron-wallet/src/models/chain/tx-status.ts b/packages/neuron-wallet/src/models/chain/tx-status.ts index a2c54c553a..ba2292e8d1 100644 --- a/packages/neuron-wallet/src/models/chain/tx-status.ts +++ b/packages/neuron-wallet/src/models/chain/tx-status.ts @@ -4,6 +4,7 @@ export enum TxStatusType { Pending = 'pending', Proposed = 'proposed', Committed = 'committed', + Rejected = 'rejected', } export default class TxStatus { @@ -28,6 +29,10 @@ export default class TxStatus { return this.status === TxStatusType.Committed } + public isRejected(): boolean { + return this.status === TxStatusType.Rejected + } + public toSDK() { return { blockHash: this.blockHash, diff --git a/packages/neuron-wallet/src/models/keys/hd-public-key-info.ts b/packages/neuron-wallet/src/models/keys/hd-public-key-info.ts index 86075d9589..b8981a636f 100644 --- a/packages/neuron-wallet/src/models/keys/hd-public-key-info.ts +++ b/packages/neuron-wallet/src/models/keys/hd-public-key-info.ts @@ -1,11 +1,11 @@ -import { AddressType, AccountExtendedPublicKey } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import { scriptToAddress } from '../../utils/scriptAndAddress' import SystemScriptInfo from '../../models/system-script-info' import NetworksService from '../../services/networks' export default class HdPublicKeyInfoModel { public walletId: string - public addressType: AddressType + public addressType: hd.AddressType public addressIndex: number public publicKeyInBlake160: string public description?: string @@ -22,12 +22,12 @@ export default class HdPublicKeyInfoModel { } public get path(): string { - return AccountExtendedPublicKey.pathFor(this.addressType, this.addressIndex) + return hd.AccountExtendedPublicKey.pathFor(this.addressType, this.addressIndex) } constructor( walletId: string, - addressType: AddressType, + addressType: hd.AddressType, addressIndex: number, publicKeyInBlake160: string, description?: string @@ -41,7 +41,7 @@ export default class HdPublicKeyInfoModel { public static fromObject(params: { walletId: string - addressType: AddressType + addressType: hd.AddressType addressIndex: number publicKeyInBlake160: string description?: string diff --git a/packages/neuron-wallet/src/models/multisig-config.ts b/packages/neuron-wallet/src/models/multisig-config.ts index 5c2258b7e5..a0a49f077d 100644 --- a/packages/neuron-wallet/src/models/multisig-config.ts +++ b/packages/neuron-wallet/src/models/multisig-config.ts @@ -1,4 +1,4 @@ -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import Multisig from './multisig' export default class MultisigConfigModel { diff --git a/packages/neuron-wallet/src/models/multisig.ts b/packages/neuron-wallet/src/models/multisig.ts index 6d62aaf6a6..e2810df24d 100644 --- a/packages/neuron-wallet/src/models/multisig.ts +++ b/packages/neuron-wallet/src/models/multisig.ts @@ -1,7 +1,7 @@ import { MultisigPrefixError } from '../exceptions' import SystemScriptInfo from './system-script-info' -import { since } from '@ckb-lumos/base' -import { bytes, number } from '@ckb-lumos/codec' +import { since } from '@ckb-lumos/lumos' +import { bytes, Uint64LE } from '@ckb-lumos/lumos/codec' import Blake2b, { BLAKE160_HEX_LENGTH } from './blake2b' export interface MultisigPrefix { @@ -38,7 +38,7 @@ export default class Multisig { const leftMinutes = totalMinutes % this.EPOCH_MINUTES const epochs = Math.floor(totalMinutes / this.EPOCH_MINUTES) + currentEpoch.number const result = this.epochSince(BigInt(this.EPOCH_MINUTES), BigInt(leftMinutes), BigInt(epochs)) - return bytes.hexify(number.Uint64LE.pack(result)) + return bytes.hexify(Uint64LE.pack(result)) } static args(blake160: string, minutes: number, headerEpoch: string): string { @@ -50,7 +50,7 @@ export default class Multisig { } static parseSince(args: string): bigint { - return number.Uint64LE.unpack(`0x${args.slice(BLAKE160_HEX_LENGTH)}`).toBigInt() + return Uint64LE.unpack(`0x${args.slice(BLAKE160_HEX_LENGTH)}`).toBigInt() } private static epochSince(length: bigint, index: bigint, number: bigint): bigint { diff --git a/packages/neuron-wallet/src/models/transaction-size.ts b/packages/neuron-wallet/src/models/transaction-size.ts index 072575950f..afbe471175 100644 --- a/packages/neuron-wallet/src/models/transaction-size.ts +++ b/packages/neuron-wallet/src/models/transaction-size.ts @@ -5,7 +5,7 @@ import Transaction from './chain/transaction' import Multisig from './multisig' import Script, { ScriptHashType } from './chain/script' import BufferUtils from '../utils/buffer' -import { bytes as byteUtils } from '@ckb-lumos/codec' +import { bytes as byteUtils } from '@ckb-lumos/lumos/codec' export default class TransactionSize { // https://github.com/zhangsoledad/rfcs/blob/zhangsoledad/ckb2023-overview/rfcs/0008-serialization/0008-serialization.md#fixvec---fixed-vector diff --git a/packages/neuron-wallet/src/services/addresses.ts b/packages/neuron-wallet/src/services/addresses.ts index 6f7f75b98c..8f16b045a1 100644 --- a/packages/neuron-wallet/src/services/addresses.ts +++ b/packages/neuron-wallet/src/services/addresses.ts @@ -1,4 +1,4 @@ -import { AddressType, AccountExtendedPublicKey } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import { publicKeyToAddress, DefaultAddressNumber } from '../utils/scriptAndAddress' import { Address as AddressInterface } from '../models/address' import AddressCreatedSubject from '../models/subjects/address-created-subject' @@ -19,9 +19,9 @@ const MAX_ADDRESS_COUNT = 100 export interface AddressMetaInfo { walletId: string - addressType: AddressType + addressType: hd.AddressType addressIndex: number - accountExtendedPublicKey: AccountExtendedPublicKey + accountExtendedPublicKey: hd.AccountExtendedPublicKey } export default class AddressService { @@ -58,7 +58,7 @@ export default class AddressService { private static async generateAndSave( walletId: string, - extendedKey: AccountExtendedPublicKey, + extendedKey: hd.AccountExtendedPublicKey, receivingStartIndex: number, changeStartIndex: number, receivingAddressCount: number = DefaultAddressNumber.Receiving, @@ -90,7 +90,7 @@ export default class AddressService { private static async recursiveGenerateAndSave( walletId: string, - extendedKey: AccountExtendedPublicKey, + extendedKey: hd.AccountExtendedPublicKey, isImporting: boolean | undefined, receivingAddressCount: number = DefaultAddressNumber.Receiving, changeAddressCount: number = DefaultAddressNumber.Change @@ -101,8 +101,8 @@ export default class AddressService { changeAddressCount ) if (!receivingCount && !changeCount) return undefined - const maxReceivingAddressIndex = await this.maxAddressIndex(walletId, AddressType.Receiving) - const maxChangeAddressIndex = await this.maxAddressIndex(walletId, AddressType.Change) + const maxReceivingAddressIndex = await this.maxAddressIndex(walletId, hd.AddressType.Receiving) + const maxChangeAddressIndex = await this.maxAddressIndex(walletId, hd.AddressType.Change) const nextReceivingIndex = maxReceivingAddressIndex === undefined ? 0 : maxReceivingAddressIndex + 1 const nextChangeIndex = maxChangeAddressIndex === undefined ? 0 : maxChangeAddressIndex + 1 @@ -159,7 +159,7 @@ export default class AddressService { changeAddressCount, }: { walletId: string - extendedKey: AccountExtendedPublicKey + extendedKey: hd.AccountExtendedPublicKey isImporting?: boolean receivingAddressCount?: number changeAddressCount?: number @@ -187,7 +187,7 @@ export default class AddressService { }: { walletId: string publicKey: string - addressType: AddressType + addressType: hd.AddressType addressIndex: number }): Promise { const isMainnet = NetworksService.getInstance().isMainnet() @@ -223,7 +223,7 @@ export default class AddressService { // Generate both receiving and change addresses. public static generateAddresses = ( walletId: string, - extendedKey: AccountExtendedPublicKey, + extendedKey: hd.AccountExtendedPublicKey, receivingStartIndex: number, changeStartIndex: number, receivingAddressCount: number = DefaultAddressNumber.Receiving, @@ -238,7 +238,7 @@ export default class AddressService { const receiving = Array.from({ length: receivingAddressCount }).map((_, idx) => { const addressMetaInfo: AddressMetaInfo = { walletId, - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, addressIndex: idx + receivingStartIndex, accountExtendedPublicKey: extendedKey, } @@ -247,7 +247,7 @@ export default class AddressService { const change = Array.from({ length: changeAddressCount }).map((_, idx) => { const addressMetaInfo: AddressMetaInfo = { walletId, - addressType: AddressType.Change, + addressType: hd.AddressType.Change, addressIndex: idx + changeStartIndex, accountExtendedPublicKey: extendedKey, } @@ -277,7 +277,7 @@ export default class AddressService { return address } - private static async maxAddressIndex(walletId: string, addressType: AddressType): Promise { + private static async maxAddressIndex(walletId: string, addressType: hd.AddressType): Promise { const result = await getConnection() .getRepository(HdPublicKeyInfo) .createQueryBuilder() @@ -296,8 +296,8 @@ export default class AddressService { private static async getGroupedUnusedAddressesByWalletId(walletId: string) { const allUnusedAddresses = await this.getUnusedAddressesByWalletId(walletId) - const unusedReceivingAddresses = allUnusedAddresses.filter(addr => addr.addressType === AddressType.Receiving) - const unusedChangeAddresses = allUnusedAddresses.filter(addr => addr.addressType === AddressType.Change) + const unusedReceivingAddresses = allUnusedAddresses.filter(addr => addr.addressType === hd.AddressType.Receiving) + const unusedChangeAddresses = allUnusedAddresses.filter(addr => addr.addressType === hd.AddressType.Change) return [unusedReceivingAddresses, unusedChangeAddresses] } @@ -349,7 +349,7 @@ export default class AddressService { const publicKeyInfo = await getConnection() .getRepository(HdPublicKeyInfo) .createQueryBuilder() - .where({ walletId, addressType: AddressType.Receiving }) + .where({ walletId, addressType: hd.AddressType.Receiving }) .orderBy('addressIndex', 'ASC') .getOne() diff --git a/packages/neuron-wallet/src/services/anyone-can-pay.ts b/packages/neuron-wallet/src/services/anyone-can-pay.ts index bfe9b8af33..054fbbc625 100644 --- a/packages/neuron-wallet/src/services/anyone-can-pay.ts +++ b/packages/neuron-wallet/src/services/anyone-can-pay.ts @@ -18,9 +18,11 @@ import LiveCellService from './live-cell-service' import WalletService from './wallets' import SystemScriptInfo from '../models/system-script-info' import CellsService from './cells' -import { MIN_SUDT_CAPACITY } from '../utils/const' +import { MIN_SUDT_CAPACITY, UDTType } from '../utils/const' import NetworksService from './networks' import { NetworkType } from '../models/network' +import BufferUtils from '../utils/buffer' +import { helpers } from '@ckb-lumos/lumos' export default class AnyoneCanPayService { public static async generateAnyoneCanPayTx( @@ -57,7 +59,7 @@ export default class AnyoneCanPayService { const targetOutput = isCKB ? await AnyoneCanPayService.getCKBTargetOutput(targetLockScript) - : await AnyoneCanPayService.getSUDTTargetOutput(targetLockScript, tokenID) + : await AnyoneCanPayService.getSUDTTargetOutput(targetLockScript, tokenID, assetAccount.udtType!) const wallet = WalletService.getInstance().get(walletID) const changeBlake160: string = (await wallet.getNextChangeAddress())!.blake160 @@ -112,18 +114,19 @@ export default class AnyoneCanPayService { throw new TargetLockError() } - private static async getSUDTTargetOutput(lockScript: Script, tokenID: string) { + private static async getSUDTTargetOutput(lockScript: Script, tokenID: string, udtType: UDTType) { if (SystemScriptInfo.isSecpScript(lockScript)) { return Output.fromObject({ - capacity: BigInt(MIN_SUDT_CAPACITY).toString(), lock: lockScript, - type: new AssetAccountInfo().generateSudtScript(tokenID), + type: new AssetAccountInfo().generateUdtScript(tokenID, udtType), + // use amount 0 to place holder amount + data: BufferUtils.writeBigUInt128LE(BigInt(0)), }) } const liveCellService = LiveCellService.getInstance() const targetOutputLiveCell: LiveCell | null = await liveCellService.getOneByLockScriptAndTypeScript( lockScript, - new AssetAccountInfo().generateSudtScript(tokenID) + new AssetAccountInfo().generateUdtScript(tokenID, udtType)! ) if (targetOutputLiveCell && new AssetAccountInfo().isAnyoneCanPayScript(lockScript)) { return Output.fromObject({ @@ -136,29 +139,38 @@ export default class AnyoneCanPayService { } return Output.fromObject({ - capacity: AnyoneCanPayService.getSUDTAddCapacity(lockScript.args), lock: lockScript, - type: new AssetAccountInfo().generateSudtScript(tokenID), + type: new AssetAccountInfo().generateUdtScript(tokenID, udtType), + // use amount 0 to place holder amount + data: BufferUtils.writeBigUInt128LE(BigInt(0)), }) } - private static getSUDTAddCapacity(args: string) { - const addArgsLength = BigInt(args.slice(2).length / 2 - 20) * BigInt(10 ** 8) - return (addArgsLength + BigInt(MIN_SUDT_CAPACITY)).toString() - } - - public static async getHoldSUDTCellCapacity(lockScript: Script, tokenID: string) { + public static async getHoldSUDTCellCapacity(lockScript: Script, tokenID: string, udtType?: UDTType) { if (SystemScriptInfo.isSecpScript(lockScript) || tokenID === 'CKBytes') { return undefined } const liveCellService = LiveCellService.getInstance() + const typeScript = new AssetAccountInfo().generateUdtScript(tokenID, udtType) + if (!typeScript) { + return undefined + } const targetOutputLiveCell: LiveCell | null = await liveCellService.getOneByLockScriptAndTypeScript( lockScript, - new AssetAccountInfo().generateSudtScript(tokenID) + typeScript ) if (targetOutputLiveCell && new AssetAccountInfo().isAnyoneCanPayScript(lockScript)) { return undefined } - return AnyoneCanPayService.getSUDTAddCapacity(lockScript.args) + return helpers + .minimalCellCapacity({ + cellOutput: { + capacity: MIN_SUDT_CAPACITY.toString(), + lock: lockScript, + type: typeScript, + }, + data: BufferUtils.writeBigUInt128LE(BigInt(0)), + }) + .toString() } } diff --git a/packages/neuron-wallet/src/services/asset-account-service.ts b/packages/neuron-wallet/src/services/asset-account-service.ts index 991338a744..563fe68ae4 100644 --- a/packages/neuron-wallet/src/services/asset-account-service.ts +++ b/packages/neuron-wallet/src/services/asset-account-service.ts @@ -15,11 +15,11 @@ import WalletService from './wallets' import OutPoint from '../models/chain/out-point' import SystemScriptInfo from '../models/system-script-info' import Input from '../models/chain/input' -import { MIN_CELL_CAPACITY } from '../utils/const' +import { MIN_CELL_CAPACITY, UDTType } from '../utils/const' import SudtTokenInfoService from './sudt-token-info' export default class AssetAccountService { - private static async getACPCells(publicKeyHash: string, tokenId: string = 'CKBytes') { + private static async getACPCells(publicKeyHash: string, tokenId: string = 'CKBytes', udtType?: UDTType) { const assetAccountInfo = new AssetAccountInfo() const anyoneCanPayLockHash = assetAccountInfo.generateAnyoneCanPayScript(publicKeyHash).computeHash() const outputs = await getConnection() @@ -27,7 +27,10 @@ export default class AssetAccountService { .findBy({ status: In([OutputStatus.Live, OutputStatus.Sent]), lockHash: anyoneCanPayLockHash, - typeHash: tokenId !== 'CKBytes' ? assetAccountInfo.generateSudtScript(tokenId).computeHash() : IsNull(), + typeHash: + tokenId !== 'CKBytes' + ? assetAccountInfo.generateUdtScript(tokenId, udtType ?? UDTType.SUDT)!.computeHash() + : IsNull(), }) return outputs @@ -49,10 +52,13 @@ export default class AssetAccountService { return availableBalance >= 0 ? availableBalance.toString() : BigInt(0) } - private static async calculateUDTAccountBalance(publicKeyHash: string, tokenId: string) { + private static async calculateUDTAccountBalance(publicKeyHash: string, tokenId: string, udtType?: UDTType) { const assetAccountInfo = new AssetAccountInfo() const anyoneCanPayLockHash = assetAccountInfo.generateAnyoneCanPayScript(publicKeyHash).computeHash() - const typeHash = assetAccountInfo.generateSudtScript(tokenId).computeHash() + const typeHash = + udtType === UDTType.SUDT + ? assetAccountInfo.generateSudtScript(tokenId).computeHash() + : assetAccountInfo.generateXudtScript(tokenId).computeHash() const outputs = await getConnection() .getRepository(OutputEntity) .createQueryBuilder('output') @@ -71,7 +77,11 @@ export default class AssetAccountService { } public static async destroyAssetAccount(walletID: string, assetAccount: AssetAccount) { - const cells = await AssetAccountService.getACPCells(assetAccount?.blake160, assetAccount.tokenID) + const cells = await AssetAccountService.getACPCells( + assetAccount?.blake160, + assetAccount.tokenID, + assetAccount.udtType + ) const inputs = cells.map(cell => { return Input.fromObject({ previousOutput: cell.outPoint(), @@ -126,7 +136,7 @@ export default class AssetAccountService { const model = aa.toModel() const tokenID = determineTokenID(aa) - const cells = await this.getACPCells(aa.blake160, tokenID) + const cells = await this.getACPCells(aa.blake160, tokenID, aa.udtType) if (!cells.length) { return } @@ -135,7 +145,7 @@ export default class AssetAccountService { const bigIntAmount = await this.calculateAvailableCKBBalance(aa.blake160) model.balance = bigIntAmount.toString() } else { - const bigIntAmount = await this.calculateUDTAccountBalance(aa.blake160, aa.tokenID) + const bigIntAmount = await this.calculateUDTAccountBalance(aa.blake160, aa.tokenID, aa.udtType) model.balance = bigIntAmount.toString() } @@ -171,23 +181,38 @@ export default class AssetAccountService { const bitIntAmount = await this.calculateAvailableCKBBalance(assetAccount.blake160) assetAccount.balance = bitIntAmount.toString() } else { - const bigIntAmount = await this.calculateUDTAccountBalance(assetAccount.blake160, assetAccount.tokenID) + const bigIntAmount = await this.calculateUDTAccountBalance( + assetAccount.blake160, + assetAccount.tokenID, + assetAccount.udtType + ) assetAccount.balance = bigIntAmount.toString() } return assetAccount } - public static async generateCreateTx( - walletID: string, - tokenID: string, - symbol: string, - accountName: string, - tokenName: string, - decimal: string, - feeRate: string, + public static async generateCreateTx({ + walletID, + tokenID, + symbol, + accountName, + tokenName, + decimal, + feeRate, + fee, + udtType, + }: { + walletID: string + tokenID: string + symbol: string + accountName: string + tokenName: string + decimal: string + feeRate: string fee: string - ): Promise<{ + udtType?: UDTType + }): Promise<{ assetAccount: AssetAccount tx: Transaction }> { @@ -203,31 +228,42 @@ export default class AssetAccountService { const addrObj = !wallet.isHDWallet() ? addresses[0] : addresses.find(a => !usedBlake160s.has(a.blake160))! // 2. generate AssetAccount object - const assetAccount = new AssetAccount(tokenID, symbol, accountName, tokenName, decimal, '0', addrObj.blake160) + const assetAccount = AssetAccount.fromObject({ + tokenID, + symbol, + accountName, + tokenName, + decimal, + balance: '0', + blake160: addrObj.blake160, + udtType, + }) // 3. generate tx const changeAddrObj = await wallet.getNextChangeAddress() let tx: Transaction | undefined try { - tx = await TransactionGenerator.generateCreateAnyoneCanPayTx( + tx = await TransactionGenerator.generateCreateAnyoneCanPayTx({ tokenID, - walletID, - addrObj.blake160, - changeAddrObj!.blake160, + walletId: walletID, + blake160: addrObj.blake160, + changeBlake160: changeAddrObj!.blake160, feeRate, - fee - ) + fee, + udtType, + }) } catch (err) { if (!(err instanceof CapacityNotEnoughForChange)) { throw err } - tx = await TransactionGenerator.generateCreateAnyoneCanPayTxUseAllBalance( + tx = await TransactionGenerator.generateCreateAnyoneCanPayTxUseAllBalance({ tokenID, - walletID, - addrObj.blake160, + walletId: walletID, + blake160: addrObj.blake160, feeRate, - fee - ) + fee, + udtType, + }) } return { @@ -236,12 +272,12 @@ export default class AssetAccountService { } } - public static async checkAndSaveAssetAccountWhenSync(tokenID: string, blake160: string) { + public static async checkAndSaveAssetAccountWhenSync(tokenID: string, blake160: string, udtType?: UDTType) { const isCKB = tokenID === 'CKBytes' const decimal = isCKB ? '8' : '' const symbol = isCKB ? 'CKB' : '' const tokenName = isCKB ? 'CKBytes' : '' - const assetAccount = new AssetAccount(tokenID, symbol, '', tokenName, decimal, '0', blake160) + const assetAccount = new AssetAccount(tokenID, symbol, '', tokenName, decimal, '0', blake160, undefined, udtType) const assetAccountEntity = AssetAccountEntity.fromModel(assetAccount) await SudtTokenInfoService.insertSudtTokenInfo(assetAccountEntity.sudtTokenInfo) const existAccountAccount = await getConnection() @@ -322,6 +358,18 @@ export default class AssetAccountService { return assetAccounts.map(aa => aa.blake160) } + private static async getExistAssetAccount(assetAccount: AssetAccount) { + return getConnection() + .getRepository(AssetAccountEntity) + .createQueryBuilder() + .where({ + tokenID: assetAccount.tokenID, + blake160: assetAccount.blake160, + udtType: assetAccount.udtType ?? IsNull(), + }) + .getOne() + } + public static async sendTx( walletID: string, assetAccount: AssetAccount, @@ -331,12 +379,9 @@ export default class AssetAccountService { ): Promise { // 1. check AssetAccount exists const connection = getConnection() - const exists = await connection.manager.query( - `SELECT EXISTS (SELECT 1 FROM asset_account where tokenID = ? AND blake160 = ?) as exist`, - [assetAccount.tokenID, assetAccount.blake160] - ) + const exists = await AssetAccountService.getExistAssetAccount(assetAccount) - if (exists[0].exist === 1 && walletID) { + if (exists && walletID) { // For hardware wallet in ckb asset account: // 1. If a ckb account has been created, another one cannot be created; // 2. If a ckb account has been destroyed, ckb account can be created. @@ -344,7 +389,11 @@ export default class AssetAccountService { if (wallet.isHardware()) { const address = await wallet.getNextAddress() if (address) { - const acpCells = await AssetAccountService.getACPCells(address.blake160, assetAccount.tokenID) + const acpCells = await AssetAccountService.getACPCells( + address.blake160, + assetAccount.tokenID, + assetAccount.udtType + ) if (acpCells.length) { throw new Error(`Asset account already exists!`) } else { @@ -352,10 +401,14 @@ export default class AssetAccountService { .createQueryBuilder() .delete() .from(AssetAccountEntity) - .where('tokenID = :tokenID AND blake160 = :blake160', { - tokenID: assetAccount.tokenID, - blake160: assetAccount.blake160, - }) + .where( + `tokenID = :tokenID AND blake160 = :blake160 ${assetAccount.udtType ? 'AND udtType = :udtType' : ''}`, + { + tokenID: assetAccount.tokenID, + blake160: assetAccount.blake160, + udtType: assetAccount.udtType, + } + ) .execute() } } @@ -486,7 +539,12 @@ export default class AssetAccountService { } const tokenId = chequeLiveCell.type!.args - const assetAccount = new AssetAccount(tokenId, '', '', '', '', '0', receiverAcpScript.args) + const udtType = assetAccountInfo.isSudtScript(chequeLiveCell.type!) + ? UDTType.SUDT + : assetAccountInfo.isXudtScript(chequeLiveCell.type!) + ? UDTType.XUDT + : undefined + const assetAccount = new AssetAccount(tokenId, '', '', '', '', '0', receiverAcpScript.args, undefined, udtType) return { tx, assetAccount } } diff --git a/packages/neuron-wallet/src/services/cells.ts b/packages/neuron-wallet/src/services/cells.ts index 03e8cc0a1f..48c876e88d 100644 --- a/packages/neuron-wallet/src/services/cells.ts +++ b/packages/neuron-wallet/src/services/cells.ts @@ -1,5 +1,5 @@ import { Brackets, In, IsNull, Not, type ObjectLiteral } from 'typeorm' -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import { getConnection } from '../database/chain/connection' import { scriptToAddress, addressToScript } from '../utils/scriptAndAddress' import { @@ -31,7 +31,7 @@ import AssetAccountInfo from '../models/asset-account-info' import NFT from '../models/nft' import MultisigConfigModel from '../models/multisig-config' import MultisigOutput from '../database/chain/entities/multisig-output' -import { bytes } from '@ckb-lumos/codec' +import { bytes } from '@ckb-lumos/lumos/codec' import { generateRPC } from '../utils/ckb-rpc' import { getClusterById, SporeData, unpackToRawClusterData } from '@spore-sdk/core' import NetworksService from './networks' @@ -39,6 +39,7 @@ import { LOCKTIME_ARGS_LENGTH, MIN_CELL_CAPACITY } from '../utils/const' import HdPublicKeyInfo from '../database/chain/entities/hd-public-key-info' import CellLocalInfoService from './cell-local-info' import CellLocalInfo from '../database/chain/entities/cell-local-info' +import { helpers } from '@ckb-lumos/lumos' export interface PaginationResult { totalCount: number @@ -57,6 +58,7 @@ export enum CustomizedType { NFTIssuer = 'NFTIssuer', SUDT = 'SUDT', + XUDT = 'XUDT', Spore = 'Spore', SporeCluster = 'SporeCluster', @@ -79,13 +81,13 @@ export enum TypeScriptCategory { NFTClass = CustomizedType.NFTClass, NFTIssuer = CustomizedType.NFTIssuer, SUDT = CustomizedType.SUDT, + XUDT = CustomizedType.XUDT, Spore = CustomizedType.Spore, Unknown = CustomizedType.Unknown, } export default class CellsService { private static ANYONE_CAN_PAY_CKB_CELL_MIN = BigInt(61 * 10 ** 8) - private static ANYONE_CAN_PAY_SUDT_CELL_MIN = BigInt(142 * 10 ** 8) public static async getBalancesByWalletId(walletId: string): Promise<{ liveBalances: Map @@ -296,6 +298,7 @@ export default class CellsService { const nftClassCodehash = assetAccountInfo.getNftClassInfo().codeHash const nftCodehash = assetAccountInfo.getNftInfo().codeHash const sudtCodehash = assetAccountInfo.getSudtCodeHash() + const xudtCodeHash = assetAccountInfo.infos.xudt.codeHash const sporeInfos = assetAccountInfo.getSporeInfos() const secp256k1LockHashes = [...blake160Hashes].map(blake160 => @@ -304,7 +307,7 @@ export default class CellsService { const skip = (pageNo - 1) * pageSize - const allMultiSignOutputs = await getConnection() + const allCustomizedOutputs = await getConnection() .getRepository(OutputEntity) .createQueryBuilder('output') .leftJoinAndSelect('output.transaction', 'tx') @@ -365,7 +368,7 @@ export default class CellsService { // to make the Spore NFT data available, // we need to fetch it from RPC instead of database const rpc = generateRPC(currentNetwork.remote, currentNetwork.type) - const sporeOutputs = allMultiSignOutputs.filter(item => + const sporeOutputs = allCustomizedOutputs.filter(item => sporeInfos.some(info => item.typeCodeHash && bytes.equal(info.codeHash, item.typeCodeHash)) ) @@ -393,7 +396,7 @@ export default class CellsService { }) ) - const matchedOutputs = allMultiSignOutputs.filter(o => { + const matchedOutputs = allCustomizedOutputs.filter(o => { if (o.multiSignBlake160) { return multiSignHashes.has(o.multiSignBlake160) } @@ -406,7 +409,11 @@ export default class CellsService { ) } - if (o.hasData && o.typeCodeHash === sudtCodehash && o.lockCodeHash === assetAccountInfo.anyoneCanPayCodeHash) { + if ( + o.hasData && + (o.typeCodeHash === sudtCodehash || o.typeCodeHash === xudtCodeHash) && + o.lockCodeHash === assetAccountInfo.anyoneCanPayCodeHash + ) { return false } @@ -466,10 +473,16 @@ export default class CellsService { }) } else if (o.typeCodeHash === sudtCodehash) { cell.setCustomizedAssetInfo({ - lock: CustomizedLock.SUDT, + lock: '', type: CustomizedType.SUDT, data: '', }) + } else if (o.typeCodeHash === xudtCodeHash) { + cell.setCustomizedAssetInfo({ + lock: '', + type: CustomizedType.XUDT, + data: '', + }) } else if (sporeInfos.some(info => o.typeCodeHash && bytes.equal(info.codeHash, o.typeCodeHash))) { const data = (() => { try { @@ -1113,8 +1126,14 @@ export default class CellsService { } else { totalSize += TransactionSize.secpLockWitness() inputOriginCells.push(cell) - // capacity - 142CKB, 142CKB remaining for change - inputCapacities -= this.ANYONE_CAN_PAY_SUDT_CELL_MIN + inputCapacities -= helpers.minimalCellCapacity({ + cellOutput: { + capacity: cell.capacity, + lock: cell.lock(), + type: cell.type(), + }, + data: cell.data, + }) totalSize += TransactionSize.sudtAnyoneCanPayOutput() + TransactionSize.sudtData() } inputs.push(input) @@ -1141,12 +1160,20 @@ export default class CellsService { .map(i => BigInt(i.capacity!)) .reduce((result, c) => result + c, BigInt(0)) let capacity: bigint = BigInt(0) - if (BigInt(cellCapacity) - this.ANYONE_CAN_PAY_SUDT_CELL_MIN >= extraPayCapacity) { + const curCellMinCapacity = helpers.minimalCellCapacity({ + cellOutput: { + capacity: cell.capacity, + lock: cell.lock(), + type: cell.type(), + }, + data: cell.data, + }) + if (BigInt(cellCapacity) - curCellMinCapacity >= extraPayCapacity) { capacity = BigInt(cellCapacity) - extraPayCapacity extraPayCapacity = BigInt(0) } else { - capacity = this.ANYONE_CAN_PAY_SUDT_CELL_MIN - extraPayCapacity = extraPayCapacity - (BigInt(cellCapacity) - this.ANYONE_CAN_PAY_SUDT_CELL_MIN) + capacity = curCellMinCapacity + extraPayCapacity = extraPayCapacity - (BigInt(cellCapacity) - curCellMinCapacity) } const output = Output.fromObject({ capacity: capacity.toString(), @@ -1365,6 +1392,8 @@ export default class CellsService { return TypeScriptCategory.NFTClass case assetAccountInfo.getSudtCodeHash(): return TypeScriptCategory.SUDT + case assetAccountInfo.infos.xudt.codeHash: + return TypeScriptCategory.XUDT case SystemScriptInfo.DAO_CODE_HASH: return TypeScriptCategory.DAO default: diff --git a/packages/neuron-wallet/src/services/hardware/common.ts b/packages/neuron-wallet/src/services/hardware/common.ts index 67bde2b3d6..be690f13f6 100644 --- a/packages/neuron-wallet/src/services/hardware/common.ts +++ b/packages/neuron-wallet/src/services/hardware/common.ts @@ -1,4 +1,6 @@ -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' + +type AddressType = hd.AddressType export enum Manufacturer { Ledger = 'Ledger', diff --git a/packages/neuron-wallet/src/services/hardware/hardware.ts b/packages/neuron-wallet/src/services/hardware/hardware.ts index fc0b1f9641..9a1c818090 100644 --- a/packages/neuron-wallet/src/services/hardware/hardware.ts +++ b/packages/neuron-wallet/src/services/hardware/hardware.ts @@ -7,13 +7,13 @@ import Multisig from '../../models/multisig' import WalletService from '../../services/wallets' import DeviceSignIndexSubject from '../../models/subjects/device-sign-index-subject' import type { DeviceInfo, ExtendedPublicKey, PublicKey } from './common' -import { AccountExtendedPublicKey } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import AssetAccountInfo from '../../models/asset-account-info' export abstract class Hardware { public deviceInfo: DeviceInfo public isConnected: boolean - protected defaultPath = AccountExtendedPublicKey.ckbAccountPath + protected defaultPath = hd.AccountExtendedPublicKey.ckbAccountPath constructor(device: DeviceInfo) { this.deviceInfo = device diff --git a/packages/neuron-wallet/src/services/hardware/ledger.ts b/packages/neuron-wallet/src/services/hardware/ledger.ts index d22bb8713c..1d6a7b791d 100644 --- a/packages/neuron-wallet/src/services/hardware/ledger.ts +++ b/packages/neuron-wallet/src/services/hardware/ledger.ts @@ -7,7 +7,7 @@ import type Transport from '@ledgerhq/hw-transport' import { Observable, timer } from 'rxjs' import { takeUntil, filter, scan } from 'rxjs/operators' import Transaction from '../../models/chain/transaction' -import { AddressType, AccountExtendedPublicKey } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import logger from '../../utils/logger' import NetworksService from '../../services/networks' import { generateRPC } from '../../utils/ckb-rpc' @@ -79,7 +79,7 @@ export default class Ledger extends Hardware { } const signature = await this.ledgerCKB!.signTransaction( - path === AccountExtendedPublicKey.pathForReceiving(0) ? this.defaultPath : path, + path === hd.AccountExtendedPublicKey.pathForReceiving(0) ? this.defaultPath : path, rawTx, witnesses, context, @@ -92,7 +92,7 @@ export default class Ledger extends Hardware { async signMessage(path: string, messageHex: string) { const message = this.removePrefix(messageHex) const signed = await this.ledgerCKB!.signMessage( - path === AccountExtendedPublicKey.pathForReceiving(0) ? this.defaultPath : path, + path === hd.AccountExtendedPublicKey.pathForReceiving(0) ? this.defaultPath : path, message, false ) @@ -108,7 +108,7 @@ export default class Ledger extends Hardware { const networkService = NetworksService.getInstance() const isTestnet = !networkService.isMainnet() const result = await this.ledgerCKB!.getWalletPublicKey( - path === AccountExtendedPublicKey.pathForReceiving(0) ? this.defaultPath : path, + path === hd.AccountExtendedPublicKey.pathForReceiving(0) ? this.defaultPath : path, isTestnet ) return result @@ -143,7 +143,7 @@ export default class Ledger extends Hardware { manufacturer: e.device.manufacturer, product: e.device.product, addressIndex: 0, - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, }, ] }, []) diff --git a/packages/neuron-wallet/src/services/multisig.ts b/packages/neuron-wallet/src/services/multisig.ts index 2f3da9467f..a2baccd5ee 100644 --- a/packages/neuron-wallet/src/services/multisig.ts +++ b/packages/neuron-wallet/src/services/multisig.ts @@ -4,7 +4,7 @@ import MultisigConfig from '../database/chain/entities/multisig-config' import MultisigOutput from '../database/chain/entities/multisig-output' import { MultisigConfigNotExistError, MultisigConfigExistError } from '../exceptions/multisig' import { rpcBatchRequest } from '../utils/rpc-request' -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import MultisigOutputChangedSubject from '../models/subjects/multisig-output-db-changed-subject' import Transaction from '../models/chain/transaction' import { OutputStatus } from '../models/chain/output' diff --git a/packages/neuron-wallet/src/services/node.ts b/packages/neuron-wallet/src/services/node.ts index 220bb5fa35..03cae0df0e 100644 --- a/packages/neuron-wallet/src/services/node.ts +++ b/packages/neuron-wallet/src/services/node.ts @@ -1,6 +1,6 @@ import fs from 'fs' import path from 'path' -import { BI } from '@ckb-lumos/bi' +import { BI } from '@ckb-lumos/lumos' import { app as electronApp, dialog, shell, app } from 'electron' import { t } from 'i18next' import { interval, BehaviorSubject, merge, Subject } from 'rxjs' diff --git a/packages/neuron-wallet/src/services/rpc-service.ts b/packages/neuron-wallet/src/services/rpc-service.ts index 8b59adf858..3f6aab645e 100644 --- a/packages/neuron-wallet/src/services/rpc-service.ts +++ b/packages/neuron-wallet/src/services/rpc-service.ts @@ -6,6 +6,7 @@ import TransactionWithStatus from '../models/chain/transaction-with-status' import logger from '../utils/logger' import { generateRPC } from '../utils/ckb-rpc' import { NetworkType } from '../models/network' +import TxStatus, { TxStatusType } from '../models/chain/tx-status' export default class RpcService { private retryTime: number @@ -29,20 +30,19 @@ export default class RpcService { return BlockHeader.fromSDK(result) } - /** - * TODO: rejected tx should be handled - * { - * transaction: null, - * txStatus: { blockHash: null, status: 'rejected' } - * } - */ - public async getTransaction(hash: string): Promise { + public async getTransaction( + hash: string + ): Promise { const result = await this.rpc.getTransaction(hash) if (result?.transaction) { return TransactionWithStatus.fromSDK(result) } - if ((result.txStatus as any) === 'rejected') { + if (result.txStatus.status === TxStatusType.Rejected) { logger.warn(`Transaction[${hash}] was rejected`) + return { + transaction: null, + txStatus: TxStatus.fromSDK(result.txStatus), + } } return undefined } diff --git a/packages/neuron-wallet/src/services/sdk-core.ts b/packages/neuron-wallet/src/services/sdk-core.ts index 36017e078c..738d7a109a 100644 --- a/packages/neuron-wallet/src/services/sdk-core.ts +++ b/packages/neuron-wallet/src/services/sdk-core.ts @@ -1,4 +1,4 @@ -import { CKBRPC } from '@ckb-lumos/rpc' +import { CKBRPC } from '@ckb-lumos/lumos/rpc' export const generateCKB = (url: string): CKBRPC => { return new CKBRPC(url, { fetch: (request, init) => globalThis.fetch(request, { ...init, keepalive: true }) }) diff --git a/packages/neuron-wallet/src/services/sign-message.ts b/packages/neuron-wallet/src/services/sign-message.ts index 31882eba15..31977328b7 100644 --- a/packages/neuron-wallet/src/services/sign-message.ts +++ b/packages/neuron-wallet/src/services/sign-message.ts @@ -1,12 +1,12 @@ import AddressService from './addresses' import WalletService, { Wallet } from './wallets' import Blake2b from '../models/blake2b' -import { key, Keychain } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import { ec as EC } from 'elliptic' import { AddressNotFound } from '../exceptions' import HardwareWalletService from './hardware' import AddressParser from '../models/address-parser' -import { bytes } from '@ckb-lumos/codec' +import { bytes } from '@ckb-lumos/lumos/codec' export default class SignMessage { static GENERATE_COUNT = 100 @@ -50,7 +50,7 @@ export default class SignMessage { private static signByPrivateKey(privateKey: string, message: string): string { const digest = SignMessage.signatureHash(message) - const signature = key.signRecoverable(digest, privateKey) + const signature = hd.key.signRecoverable(digest, privateKey) return signature } @@ -101,7 +101,7 @@ export default class SignMessage { private static getPrivateKey(wallet: Wallet, path: string, password: string): string { const masterPrivateKey = wallet.loadKeystore().extendedPrivateKey(password) - const masterKeychain = new Keychain( + const masterKeychain = new hd.Keychain( Buffer.from(bytes.bytify(masterPrivateKey.privateKey)), Buffer.from(bytes.bytify(masterPrivateKey.chainCode)) ) diff --git a/packages/neuron-wallet/src/services/sudt-token-info.ts b/packages/neuron-wallet/src/services/sudt-token-info.ts index 7195f2cdb2..f69f26c760 100644 --- a/packages/neuron-wallet/src/services/sudt-token-info.ts +++ b/packages/neuron-wallet/src/services/sudt-token-info.ts @@ -1,6 +1,7 @@ import { In, Not } from 'typeorm' import SudtTokenInfoEntity from '../database/chain/entities/sudt-token-info' import { getConnection } from '../database/chain/connection' +import { UDTType } from '../utils/const' export default class SudtTokenInfoService { static async findSudtTokenInfoByArgs(typeArgsList: string[]) { @@ -41,13 +42,14 @@ export default class SudtTokenInfoService { .execute() } - static getSudtTokenInfo(typeArgs: string): Promise { + static getSudtTokenInfo(typeArgs: string, udtType: UDTType): Promise { return getConnection() .getRepository(SudtTokenInfoEntity) .createQueryBuilder('info') .leftJoinAndSelect('info.assetAccounts', 'aa') - .where(`info.tokenID = :typeArgs`, { + .where(`info.tokenID = :typeArgs AND info.udtType = :udtType`, { typeArgs, + udtType, }) .getOne() } diff --git a/packages/neuron-wallet/src/services/sync-progress.ts b/packages/neuron-wallet/src/services/sync-progress.ts index 1c46bdac31..0d5060ec1b 100644 --- a/packages/neuron-wallet/src/services/sync-progress.ts +++ b/packages/neuron-wallet/src/services/sync-progress.ts @@ -1,5 +1,5 @@ import { In, LessThan, Not } from 'typeorm' -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import SyncProgress, { SyncAddressType } from '../database/chain/entities/sync-progress' import WalletService from './wallets' import { getConnection } from '../database/chain/connection' diff --git a/packages/neuron-wallet/src/services/transaction-sender.ts b/packages/neuron-wallet/src/services/transaction-sender.ts index a0681e4673..621b87835e 100644 --- a/packages/neuron-wallet/src/services/transaction-sender.ts +++ b/packages/neuron-wallet/src/services/transaction-sender.ts @@ -18,7 +18,7 @@ import Multisig from '../models/multisig' import Blake2b from '../models/blake2b' import logger from '../utils/logger' import { signWitnesses } from '../utils/signWitnesses' -import { bytes, number } from '@ckb-lumos/codec' +import { bytes, Uint64LE } from '@ckb-lumos/lumos/codec' import SystemScriptInfo from '../models/system-script-info' import AddressParser from '../models/address-parser' import HardwareWalletService from './hardware' @@ -41,10 +41,10 @@ import { SignStatus } from '../models/offline-sign' import NetworksService from './networks' import { generateRPC } from '../utils/ckb-rpc' import CellsService from './cells' -import { key, Keychain } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import { getClusterByOutPoint } from '@spore-sdk/core' import CellDep, { DepType } from '../models/chain/cell-dep' -import { dao } from '@ckb-lumos/common-scripts' +import { dao } from '@ckb-lumos/lumos/common-scripts' interface SignInfo { witnessArgs: WitnessArgs @@ -417,13 +417,13 @@ export default class TransactionSender { const serializedEmptyWitnessSize = bytes.bytify(serializedEmptyWitness).byteLength const blake2b = new Blake2b() blake2b.update(txHash) - blake2b.update(bytes.hexify(number.Uint64LE.pack(`0x${serializedEmptyWitnessSize.toString(16)}`))) + blake2b.update(bytes.hexify(Uint64LE.pack(`0x${serializedEmptyWitnessSize.toString(16)}`))) blake2b.update(serializedEmptyWitness) restWitnesses.forEach(w => { const wit: string = typeof w === 'string' ? w : serializeWitnessArgs(w.toSDK()) const byteLength = bytes.bytify(wit).byteLength - blake2b.update(bytes.hexify(number.Uint64LE.pack(`0x${byteLength.toString(16)}`))) + blake2b.update(bytes.hexify(Uint64LE.pack(`0x${byteLength.toString(16)}`))) blake2b.update(wit) }) @@ -432,7 +432,7 @@ export default class TransactionSender { if (!wallet.isHardware()) { // `privateKeyOrPath` variable here is a private key because wallet is not a hardware one. Otherwise, it will be a private key path. const privateKey = privateKeyOrPath - emptyWitness.lock = key.signRecoverable(message, privateKey) + emptyWitness.lock = hd.key.signRecoverable(message, privateKey) } return [emptyWitness, ...restWitnesses] @@ -930,7 +930,7 @@ export default class TransactionSender { // Derive all child private keys for specified BIP44 paths. public getPrivateKeys = (wallet: Wallet, paths: string[], password: string): PathAndPrivateKey[] => { const masterPrivateKey = wallet.loadKeystore().extendedPrivateKey(password) - const masterKeychain = new Keychain( + const masterKeychain = new hd.Keychain( Buffer.from(bytes.bytify(masterPrivateKey.privateKey)), Buffer.from(bytes.bytify(masterPrivateKey.chainCode)) ) diff --git a/packages/neuron-wallet/src/services/tx/failed-transaction.ts b/packages/neuron-wallet/src/services/tx/failed-transaction.ts index 996c53d336..96c8f754cf 100644 --- a/packages/neuron-wallet/src/services/tx/failed-transaction.ts +++ b/packages/neuron-wallet/src/services/tx/failed-transaction.ts @@ -9,16 +9,41 @@ import { TransactionStatus } from '../../models/chain/transaction' import AmendTransactionEntity from '../../database/chain/entities/amend-transaction' export class FailedTransaction { - public static pendings = async (): Promise => { - const pendingTransactions = await getConnection() + public static pendingOrFaileds = async (): Promise => { + const transactions = await getConnection() .getRepository(TransactionEntity) .createQueryBuilder('tx') .where({ - status: TransactionStatus.Pending, + status: In([TransactionStatus.Pending, TransactionStatus.Failed]), }) .getMany() - return pendingTransactions + return transactions + } + + public static deleteFailedTxs = async (hashes: string[]) => { + await getConnection().manager.transaction(async transactionalEntityManager => { + await transactionalEntityManager + .createQueryBuilder() + .delete() + .from(TransactionEntity) + .where({ hash: In(hashes) }) + .execute() + + await transactionalEntityManager + .createQueryBuilder() + .delete() + .from(OutputEntity) + .where({ outPointTxHash: In(hashes) }) + .execute() + + await transactionalEntityManager + .createQueryBuilder() + .delete() + .from(InputEntity) + .where({ outPointTxHash: In(hashes) }) + .execute() + }) } public static processAmendFailedTxs = async () => { @@ -56,28 +81,7 @@ export class FailedTransaction { } }) - await getConnection().manager.transaction(async transactionalEntityManager => { - await transactionalEntityManager - .createQueryBuilder() - .delete() - .from(TransactionEntity) - .where({ hash: In(removeTxs) }) - .execute() - - await transactionalEntityManager - .createQueryBuilder() - .delete() - .from(OutputEntity) - .where({ outPointTxHash: In(removeTxs) }) - .execute() - - await transactionalEntityManager - .createQueryBuilder() - .delete() - .from(InputEntity) - .where({ outPointTxHash: In(removeTxs) }) - .execute() - }) + await FailedTransaction.deleteFailedTxs(removeTxs) } // update tx status to TransactionStatus.Failed diff --git a/packages/neuron-wallet/src/services/tx/transaction-generator.ts b/packages/neuron-wallet/src/services/tx/transaction-generator.ts index 78746dc8b5..ab8079ce94 100644 --- a/packages/neuron-wallet/src/services/tx/transaction-generator.ts +++ b/packages/neuron-wallet/src/services/tx/transaction-generator.ts @@ -1,4 +1,4 @@ -import { bytes } from '@ckb-lumos/codec' +import { bytes } from '@ckb-lumos/lumos/codec' import CellsService from '../../services/cells' import { CapacityTooSmall, @@ -31,7 +31,7 @@ import AddressService from '../../services/addresses' import { addressToScript } from '../../utils/scriptAndAddress' import MultisigConfigModel from '../../models/multisig-config' import WalletService from '../../services/wallets' -import { MIN_CELL_CAPACITY, MIN_SUDT_CAPACITY } from '../../utils/const' +import { MIN_CELL_CAPACITY, UDTType } from '../../utils/const' import AssetAccountService from '../../services/asset-account-service' import LiveCellService from '../../services/live-cell-service' import NetworksService from '../networks' @@ -72,7 +72,7 @@ export class TransactionGenerator { if (!nftCell) return const nftTx = await this.getRpcService().getTransaction(outPoint.txHash) - const nftOriginalOutputData = nftTx?.transaction.outputsData[Number(outPoint.index)] + const nftOriginalOutputData = nftTx?.transaction?.outputsData[Number(outPoint.index)] if (!nftOriginalOutputData) return nftCell.data = nftOriginalOutputData @@ -651,37 +651,51 @@ export class TransactionGenerator { } // sUDT - public static async generateCreateAnyoneCanPayTx( - tokenID: string, - walletId: string, - blake160: string, - changeBlake160: string, - feeRate: string, + public static async generateCreateAnyoneCanPayTx({ + tokenID, + walletId, + blake160, + changeBlake160, + feeRate, + fee, + udtType, + }: { + tokenID: string + walletId: string + blake160: string + changeBlake160: string + feeRate: string fee: string - ): Promise { + udtType?: UDTType + }): Promise { // if tokenID === '' or 'CKBytes', create ckb cell const isCKB = tokenID === 'CKBytes' || tokenID === '' + if (!isCKB && !udtType) throw new Error('The udt token must has udt Type') const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep() const assetAccountInfo = new AssetAccountInfo() const sudtCellDep = assetAccountInfo.sudtCellDep - const needCapacities = isCKB ? BigInt(61 * 10 ** 8) : BigInt(142 * 10 ** 8) + const xudtCellDep = assetAccountInfo.xudtCellDep const output = Output.fromObject({ - capacity: needCapacities.toString(), lock: assetAccountInfo.generateAnyoneCanPayScript(blake160), - type: isCKB ? null : assetAccountInfo.generateSudtScript(tokenID), + type: isCKB + ? null + : udtType === UDTType.SUDT + ? assetAccountInfo.generateSudtScript(tokenID) + : assetAccountInfo.generateXudtScript(tokenID), data: isCKB ? '0x' : BufferUtils.writeBigUInt128LE(BigInt(0)), }) const tx = Transaction.fromObject({ version: '0', headerDeps: [], - cellDeps: [secpCellDep, sudtCellDep], + cellDeps: [secpCellDep, sudtCellDep, xudtCellDep], inputs: [], outputs: [output], outputsData: [output.data], witnesses: [], }) const baseSize: number = TransactionSize.tx(tx) + const needCapacities = BigInt(output.capacity) const { inputs, capacities, finalFee, hasChangeOutput } = await CellsService.gatherInputs( needCapacities.toString(), walletId, @@ -713,13 +727,21 @@ export class TransactionGenerator { return tx } - public static async generateCreateAnyoneCanPayTxUseAllBalance( - tokenID: string, - walletId: string, - blake160: string, - feeRate: string, + public static async generateCreateAnyoneCanPayTxUseAllBalance({ + tokenID, + walletId, + blake160, + feeRate, + fee, + udtType, + }: { + tokenID: string + walletId: string + blake160: string + feeRate: string fee: string - ): Promise { + udtType?: UDTType + }): Promise { // if tokenID === '' or 'CKBytes', create ckb cell const isCKB = tokenID === 'CKBytes' || tokenID === '' @@ -729,6 +751,7 @@ export class TransactionGenerator { const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep() const assetAccountInfo = new AssetAccountInfo() const sudtCellDep = assetAccountInfo.sudtCellDep + const xudtCellDep = assetAccountInfo.xudtCellDep const allInputs: Input[] = await CellsService.gatherAllInputs(walletId) @@ -741,14 +764,18 @@ export class TransactionGenerator { const output = Output.fromObject({ capacity: totalCapacity.toString(), lock: assetAccountInfo.generateAnyoneCanPayScript(blake160), - type: isCKB ? null : assetAccountInfo.generateSudtScript(tokenID), + type: isCKB + ? null + : udtType === UDTType.SUDT + ? assetAccountInfo.generateSudtScript(tokenID) + : assetAccountInfo.generateXudtScript(tokenID), data: isCKB ? '0x' : BufferUtils.writeBigUInt128LE(BigInt(0)), }) const tx = Transaction.fromObject({ version: '0', headerDeps: [], - cellDeps: [secpCellDep, sudtCellDep], + cellDeps: [secpCellDep, sudtCellDep, xudtCellDep], inputs: allInputs, outputs: [output], outputsData: [output.data], @@ -782,7 +809,7 @@ export class TransactionGenerator { throw new SudtAcpHaveDataError() } if (!isCKBAccount) { - cellDeps.push(assetAccountInfo.sudtCellDep) + cellDeps.push(assetAccountInfo.sudtCellDep, assetAccountInfo.xudtCellDep) } const output = Output.fromObject({ @@ -921,7 +948,6 @@ export class TransactionGenerator { ) { const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep() const assetAccountInfo = new AssetAccountInfo() - const sudtCellDep = assetAccountInfo.sudtCellDep const anyoneCanPayDep = assetAccountInfo.anyoneCanPayCellDep const targetAmount: bigint = amount === 'all' ? BigInt(0) : BufferUtils.parseAmountFromSUDTData(targetOutput.data) + BigInt(amount) @@ -940,10 +966,14 @@ export class TransactionGenerator { data: targetOutput.data, }) : undefined + const udtCellDep = + targetOutput.type && assetAccountInfo.isSudtScript(targetOutput.type) + ? assetAccountInfo.sudtCellDep + : assetAccountInfo.xudtCellDep const tx = Transaction.fromObject({ version: '0', headerDeps: [], - cellDeps: [secpCellDep, sudtCellDep, anyoneCanPayDep], + cellDeps: [secpCellDep, udtCellDep, anyoneCanPayDep], inputs: targetInput ? [targetInput] : [], outputs: [output], outputsData: [output.data], @@ -987,7 +1017,7 @@ export class TransactionGenerator { // amount assertion TransactionGenerator.checkTxCapacity(tx, 'generateAnyoneCanPayToSudtTx capacity not match!') - TransactionGenerator.checkTxSudtAmount(tx, 'generateAnyoneCanPayToSudtTx sUDT amount not match!', assetAccountInfo) + TransactionGenerator.checkTxUdtAmount(tx, 'generateAnyoneCanPayToSudtTx sUDT amount not match!', assetAccountInfo) return tx } @@ -1075,22 +1105,23 @@ export class TransactionGenerator { const assetAccountInfo = new AssetAccountInfo() const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep() - const sudtCellDep = assetAccountInfo.sudtCellDep + const udtCellDep = + assetAccount.udtType === UDTType.SUDT ? assetAccountInfo.sudtCellDep : assetAccountInfo.xudtCellDep const anyoneCanPayDep = assetAccountInfo.anyoneCanPayCellDep const senderAcpScript = assetAccountInfo.generateAnyoneCanPayScript(assetAccount.blake160) const receiverLockScript = AddressParser.parse(receiverAddress) const chequeCellTmp = Output.fromObject({ - capacity: BigInt(162 * 10 ** 8).toString(), lock: assetAccountInfo.generateChequeScript(bytes.hexify(Buffer.alloc(20)), bytes.hexify(Buffer.alloc(20))), - type: assetAccountInfo.generateSudtScript(assetAccount.tokenID), + type: assetAccountInfo.generateUdtScript(assetAccount.tokenID, assetAccount.udtType), + data: BufferUtils.writeBigUInt128LE(BigInt(0)), }) const tx = Transaction.fromObject({ version: '0', headerDeps: [], - cellDeps: [secpCellDep, sudtCellDep, anyoneCanPayDep], + cellDeps: [secpCellDep, udtCellDep, anyoneCanPayDep], inputs: [], outputs: [], outputsData: [], @@ -1173,7 +1204,7 @@ export class TransactionGenerator { tx.anyoneCanPaySendAmount = tx.sudtInfo.amount TransactionGenerator.checkTxCapacity(tx, 'generateCreateChequeTx capacity not match!') - TransactionGenerator.checkTxSudtAmount(tx, 'generateCreateChequeTx sUDT amount not match!', assetAccountInfo) + TransactionGenerator.checkTxUdtAmount(tx, 'generateCreateChequeTx sUDT amount not match!', assetAccountInfo) return tx } @@ -1204,11 +1235,13 @@ export class TransactionGenerator { } const chequeSenderLock = senderInputsByLockHash[0].lockScript() - const acpCellCapacity = BigInt(142 * 10 ** 8) const assetAccountInfo = new AssetAccountInfo() const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep() - const sudtCellDep = assetAccountInfo.sudtCellDep + const udtCellDep = + chequeCell.type && assetAccountInfo.isSudtScript(chequeCell.type) + ? assetAccountInfo.sudtCellDep + : assetAccountInfo.xudtCellDep const anyoneCanPayDep = assetAccountInfo.anyoneCanPayCellDep const chequeDep = assetAccountInfo.getChequeInfo().cellDep @@ -1229,7 +1262,7 @@ export class TransactionGenerator { const tx = Transaction.fromObject({ version: '0', - cellDeps: [secpCellDep, sudtCellDep, anyoneCanPayDep, chequeDep], + cellDeps: [secpCellDep, udtCellDep, anyoneCanPayDep, chequeDep], headerDeps: [], inputs: [chequeInput], outputs: [senderOutput], @@ -1241,6 +1274,7 @@ export class TransactionGenerator { const receiverAcpCells = await CellsService.getACPCells(receiverAcpScript, chequeCell.type!) let requiredCapacity = BigInt(0) + let acpCellCapacity = BigInt(0) if (receiverAcpCells.length) { const originalReceiverAcpOutput = receiverAcpCells[0] @@ -1264,16 +1298,16 @@ export class TransactionGenerator { data: originalReceiverAcpOutput.data, }) tx.inputs.push(receiverAcpInput) + acpCellCapacity = BigInt(newReceiverAcpOutput.capacity) tx.outputs.push(newReceiverAcpOutput) } else { - requiredCapacity = acpCellCapacity - const receiverAcpOutput = Output.fromObject({ - capacity: acpCellCapacity.toString(), lock: receiverAcpScript, type: chequeCell.type, data: chequeCell.data, }) + acpCellCapacity = BigInt(receiverAcpOutput.capacity) + requiredCapacity = BigInt(receiverAcpOutput.capacity) tx.outputs.push(receiverAcpOutput) } @@ -1306,7 +1340,7 @@ export class TransactionGenerator { } TransactionGenerator.checkTxCapacity(tx, 'generateClaimChequeTx capacity not match!') - TransactionGenerator.checkTxSudtAmount(tx, 'generateClaimChequeTx sUDT amount not match!', assetAccountInfo) + TransactionGenerator.checkTxUdtAmount(tx, 'generateClaimChequeTx sUDT amount not match!', assetAccountInfo) return tx } @@ -1378,12 +1412,13 @@ export class TransactionGenerator { const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep() const sudtCellDep = assetAccountInfo.sudtCellDep + const xudtCellDep = assetAccountInfo.xudtCellDep const anyoneCanPayDep = assetAccountInfo.anyoneCanPayCellDep const chequeDep = assetAccountInfo.getChequeInfo().cellDep const tx = Transaction.fromObject({ version: '0', - cellDeps: [secpCellDep, sudtCellDep, anyoneCanPayDep, chequeDep], + cellDeps: [secpCellDep, sudtCellDep, xudtCellDep, anyoneCanPayDep, chequeDep], headerDeps: [], inputs: [chequeSenderAcpInput, chequeInput], outputs: [senderAcpOutput], @@ -1410,7 +1445,7 @@ export class TransactionGenerator { tx.outputsData.push('0x') TransactionGenerator.checkTxCapacity(tx, 'generateWithdrawChequeTx capacity not match!') - TransactionGenerator.checkTxSudtAmount(tx, 'generateWithdrawChequeTx sUDT amount not match!', assetAccountInfo) + TransactionGenerator.checkTxUdtAmount(tx, 'generateWithdrawChequeTx sUDT amount not match!', assetAccountInfo) return tx } @@ -1456,7 +1491,6 @@ export class TransactionGenerator { ] const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep() - const sudtCellDep = assetAccountInfo.sudtCellDep let outputs: Output[] = [] let acpInputCell: Input | null = null const acpCodeHashes = new Set([sudtCell.lock.codeHash]) @@ -1511,7 +1545,12 @@ export class TransactionGenerator { const tx = Transaction.fromObject({ version: '0', headerDeps: [], - cellDeps: [secpCellDep, sudtCellDep, ...acpCellDeps.filter((v): v is CellDep => !!v)], + cellDeps: [ + secpCellDep, + assetAccountInfo.sudtCellDep, + assetAccountInfo.xudtCellDep, + ...acpCellDeps.filter((v): v is CellDep => !!v), + ], inputs: sudtMigrateAcpInputs, outputs: outputs, outputsData: outputs.map(v => v.data || '0x'), @@ -1521,7 +1560,7 @@ export class TransactionGenerator { const txSize = TransactionSize.tx(tx) + TransactionSize.secpLockWitness() * tx.inputs.length tx.fee = TransactionFee.fee(txSize, BigInt(feeRate)).toString() const outputCapacity = BigInt(inputSudtCell.capacity) - BigInt(tx.fee) - if (outputCapacity >= BigInt(MIN_SUDT_CAPACITY)) { + if (outputCapacity >= tx.outputs[0].minimalCellCapacity()) { tx.outputs[0].capacity = outputCapacity.toString() return tx } @@ -1577,18 +1616,29 @@ export class TransactionGenerator { ) } - private static checkTxSudtAmount(tx: Transaction, msg: string, assetAccountInfo: AssetAccountInfo) { - const inputAmount = tx.inputs + private static checkTxUdtAmount(tx: Transaction, msg: string, assetAccountInfo: AssetAccountInfo) { + const sudtInputAmount = tx.inputs .filter(i => i.type && assetAccountInfo.isSudtScript(i.type)) .map(i => BufferUtils.parseAmountFromSUDTData(i.data!)) .reduce((result, c) => result + c, BigInt(0)) - const outputAmount = tx.outputs + const sudtOutputAmount = tx.outputs .filter(o => o.type && assetAccountInfo.isSudtScript(o.type)) .map(o => BufferUtils.parseAmountFromSUDTData(o.data!)) .reduce((result, c) => result + c, BigInt(0)) - assert.equal(inputAmount.toString(), outputAmount.toString(), `${msg}: ${JSON.stringify(tx)}`) + assert.equal(sudtInputAmount.toString(), sudtOutputAmount.toString(), `${msg}: ${JSON.stringify(tx)}`) + + const xudtInputAmount = tx.inputs + .filter(i => i.type && assetAccountInfo.isXudtScript(i.type)) + .map(i => BufferUtils.parseAmountFromSUDTData(i.data!)) + .reduce((result, c) => result + c, BigInt(0)) + + const xudtOutputAmount = tx.outputs + .filter(o => o.type && assetAccountInfo.isXudtScript(o.type)) + .map(o => BufferUtils.parseAmountFromSUDTData(o.data!)) + .reduce((result, c) => result + c, BigInt(0)) + assert.equal(xudtInputAmount.toString(), xudtOutputAmount.toString(), `${msg}: ${JSON.stringify(tx)}`) } } diff --git a/packages/neuron-wallet/src/services/tx/transaction-service.ts b/packages/neuron-wallet/src/services/tx/transaction-service.ts index 8b43057ed9..18dbb29bf5 100644 --- a/packages/neuron-wallet/src/services/tx/transaction-service.ts +++ b/packages/neuron-wallet/src/services/tx/transaction-service.ts @@ -1,14 +1,8 @@ -import { CKBRPC } from '@ckb-lumos/rpc' +import { CKBRPC } from '@ckb-lumos/lumos/rpc' import TransactionEntity from '../../database/chain/entities/transaction' import OutputEntity from '../../database/chain/entities/output' import { getConnection } from '../../database/chain/connection' -import Transaction, { - TransactionStatus, - SudtInfo, - NFTType, - NFTInfo, - AssetAccountType, -} from '../../models/chain/transaction' +import Transaction, { TransactionStatus, NFTType, AssetAccountType } from '../../models/chain/transaction' import InputEntity from '../../database/chain/entities/input' import AddressParser from '../../models/address-parser' import AssetAccountInfo from '../../models/asset-account-info' @@ -22,6 +16,7 @@ import Input from '../../models/chain/input' import SudtTokenInfoService from '../sudt-token-info' import TransactionSize from '../../models/transaction-size' import Output from '../../models/chain/output' +import { UDTType } from '../../utils/const' export interface TransactionsByAddressesParam { pageNo: number @@ -93,6 +88,145 @@ export class TransactionsService { return 0 } + private static async getSudtInfo({ + txHash, + acpUdtInputs, + acpUdtOutputs, + udtType, + }: { + txHash: string + acpUdtInputs: InputEntity[] + acpUdtOutputs: OutputEntity[] + udtType: UDTType + }) { + const udtInput = acpUdtInputs.find(i => i.transactionHash === txHash) + const udtOutput = acpUdtOutputs.find(o => o.outPointTxHash === txHash) + const typeArgs: string | undefined | null = udtInput?.typeArgs ?? udtOutput?.typeArgs + const assetAccountType: AssetAccountType | undefined = + udtInput || udtOutput ? (udtType === UDTType.SUDT ? AssetAccountType.SUDT : AssetAccountType.XUDT) : undefined + if (!typeArgs) return undefined + const inputAmount = acpUdtInputs + .filter(i => i.transactionHash === txHash && i.typeArgs === typeArgs) + .map(i => BufferUtils.parseAmountFromSUDTData(i.data)) + .reduce((result, c) => result + c, BigInt(0)) + const outputAmount = acpUdtOutputs + .filter(o => o.outPointTxHash === txHash && o.typeArgs === typeArgs) + .map(o => BufferUtils.parseAmountFromSUDTData(o.data)) + .reduce((result, c) => result + c, BigInt(0)) + const amount = outputAmount - inputAmount + let txType = amount > 0 ? 'receive' : 'send' + if (udtInput && !udtOutput) { + txType = 'destroy' + } else if (!udtInput && udtOutput) { + txType = 'create' + } + + return { + sudtInfo: { + sUDT: (await SudtTokenInfoService.getSudtTokenInfo(typeArgs, udtType)) ?? undefined, + amount: amount.toString(), + }, + txType, + assetAccountType, + } + } + + private static async getAssetCKBInfo({ + txHash, + acpCKBInputs, + acpCKBOutputs, + }: { + txHash: string + acpCKBInputs: InputEntity[] + acpCKBOutputs: OutputEntity[] + }) { + const ckbAssetInput = acpCKBInputs.find(i => i.transactionHash === txHash) + const ckbAssetOutput = acpCKBOutputs.find(o => o.outPointTxHash === txHash) + if (!ckbAssetInput && !ckbAssetOutput) return + if (ckbAssetInput && !ckbAssetOutput) { + return { + txType: 'destroy', + assetAccountType: AssetAccountType.CKB, + } + } + if (!ckbAssetInput && ckbAssetOutput) { + return { + txType: 'create', + assetAccountType: AssetAccountType.CKB, + } + } + } + + private static getNtfInfo({ + txHash, + nftInputs, + nftOutputs, + }: { + txHash: string + nftInputs: InputEntity[] + nftOutputs: OutputEntity[] + }) { + const sendNFTCell = nftInputs.find(i => i.transactionHash === txHash) + const receiveNFTCell = nftOutputs.find(o => o.outPointTxHash === txHash) + + if (sendNFTCell) { + return { type: NFTType.Send, data: sendNFTCell.typeArgs! } + } + if (receiveNFTCell) { + return { type: NFTType.Receive, data: receiveNFTCell.typeArgs! } + } + } + + private static getDAOCapacity( + ckbChange: bigint, + txDaoInfo?: { + inputs: { + capacity: string + transactionHash: string + outPointTxHash: string + outPointIndex: string + data: string + }[] + outputs: { + capacity: string + transactionHash: string + daoData: string + }[] + } + ) { + if (!txDaoInfo) return + if (txDaoInfo.inputs.length && !txDaoInfo.outputs.length) { + return txDaoInfo.inputs.reduce((pre, cur) => BigInt(cur.capacity) + pre, ckbChange).toString() + } + if (!txDaoInfo.inputs.length && txDaoInfo.outputs.length) { + return `-${txDaoInfo.outputs.reduce((pre, cur) => BigInt(cur.capacity) + pre, BigInt(0)).toString()}` + } + } + + private static groupAssetCells(cells: T[]) { + const assetAccountInfo = new AssetAccountInfo() + const acpSudtCells: T[] = [] + const acpCKBCells: T[] = [] + const acpXudtCells: T[] = [] + cells.forEach(v => { + const typeScript = v.typeScript() + if (typeScript) { + if (assetAccountInfo.isSudtScript(typeScript)) { + acpSudtCells.push(v) + } else if (assetAccountInfo.isXudtScript(typeScript)) { + acpXudtCells.push(v) + } + } else { + acpCKBCells.push(v) + } + }) + return { + acpCKBCells, + acpSudtCells, + acpXudtCells, + } + } + public static async getAllByAddresses( params: TransactionsByAddressesParam, searchValue: string = '' @@ -359,14 +493,6 @@ export class TransactionsService { ) .getMany() - const anyoneCanPayInputs = assetAccountInputs.filter(i => i.typeScript()) - - const anyoneCanPayOutputs = assetAccountOutputs.filter(i => i.typeScript()) - - const ckbAssetInputs = assetAccountInputs.filter(i => !i.typeScript()) - - const ckbAssetOutputs = assetAccountOutputs.filter(i => !i.typeScript()) - const inputPreviousTxHashes: string[] = inputs.map(i => i.outPointTxHash).filter(h => !!h) as string[] const daoCellOutPoints: { txHash: string; index: string }[] = ( @@ -410,114 +536,53 @@ export class TransactionsService { } }) + const { + acpCKBCells: acpCKBInputs, + acpSudtCells: acpSudtInputs, + acpXudtCells: acpXudtInputs, + } = TransactionsService.groupAssetCells(assetAccountInputs) + const { + acpCKBCells: acpCKBOutputs, + acpSudtCells: acpSudtOutputs, + acpXudtCells: acpXudtOutputs, + } = TransactionsService.groupAssetCells(assetAccountOutputs) const txs = await Promise.all( transactions.map(async tx => { const value = sums.get(tx.hash!) || BigInt(0) - - let typeArgs: string | undefined | null - let txType: string = value > BigInt(0) ? 'receive' : 'send' - let assetAccountType: AssetAccountType | undefined - - const sudtInput = anyoneCanPayInputs.find( - i => i.transactionHash === tx.hash && assetAccountInfo.isSudtScript(i.typeScript()!) - ) - const sudtOutput = anyoneCanPayOutputs.find( - o => o.outPointTxHash === tx.hash && assetAccountInfo.isSudtScript(o.typeScript()!) - ) - if (sudtInput) { - typeArgs = sudtInput.typeArgs - if (!sudtOutput) { - txType = 'destroy' - assetAccountType = AssetAccountType.SUDT - } - } else { - if (sudtOutput) { - typeArgs = sudtOutput.typeArgs - txType = 'create' - assetAccountType = AssetAccountType.SUDT - } - } - - const ckbAssetInput = ckbAssetInputs.find(i => i.transactionHash === tx.hash) - const ckbAssetOutput = ckbAssetOutputs.find(o => o.outPointTxHash === tx.hash) - if (ckbAssetInput && !ckbAssetOutput) { - txType = 'destroy' - assetAccountType = AssetAccountType.CKB - } else if (!ckbAssetInput && ckbAssetOutput) { - txType = 'create' - assetAccountType = AssetAccountType.CKB - } - - let sudtInfo: SudtInfo | undefined - - if (typeArgs) { - // const typeArgs = sudtInput.typeArgs - const inputAmount = anyoneCanPayInputs - .filter( - i => - i.transactionHash === tx.hash && - assetAccountInfo.isSudtScript(i.typeScript()!) && - i.typeArgs === typeArgs - ) - .map(i => BufferUtils.parseAmountFromSUDTData(i.data)) - .reduce((result, c) => result + c, BigInt(0)) - const outputAmount = anyoneCanPayOutputs - .filter( - o => - o.outPointTxHash === tx.hash && - assetAccountInfo.isSudtScript(o.typeScript()!) && - o.typeArgs === typeArgs - ) - .map(o => BufferUtils.parseAmountFromSUDTData(o.data)) - .reduce((result, c) => result + c, BigInt(0)) - - const amount = outputAmount - inputAmount - const tokenInfo = await SudtTokenInfoService.getSudtTokenInfo(typeArgs) - - if (tokenInfo) { - sudtInfo = { - sUDT: tokenInfo, - amount: amount.toString(), - } - } - } - - const sendNFTCell = nftInputs.find(i => i.typeCodeHash === nftCodehash && i.transactionHash === tx.hash) - const receiveNFTCell = nftOutputs.find(o => o.typeCodeHash === nftCodehash && o.outPointTxHash === tx.hash) - - let nftInfo: NFTInfo | undefined - if (sendNFTCell) { - nftInfo = { type: NFTType.Send, data: sendNFTCell.typeArgs! } - } else if (receiveNFTCell) { - nftInfo = { type: NFTType.Receive, data: receiveNFTCell.typeArgs! } - } - - const txDaoInfo = daoInfo.get(tx.hash) - let daoCapacity: string | undefined - if (txDaoInfo) { - if (txDaoInfo.inputs.length && !txDaoInfo.outputs.length) { - daoCapacity = txDaoInfo.inputs.reduce((pre, cur) => BigInt(cur.capacity) + pre, BigInt(value)).toString() - } else if (!txDaoInfo.inputs.length && txDaoInfo.outputs.length) { - daoCapacity = `-${txDaoInfo.outputs.reduce((pre, cur) => BigInt(cur.capacity) + pre, BigInt(0)).toString()}` - } - } + const typeScriptInfo = + (await TransactionsService.getSudtInfo({ + txHash: tx.hash, + acpUdtInputs: acpSudtInputs, + acpUdtOutputs: acpSudtOutputs, + udtType: UDTType.SUDT, + })) || + (await TransactionsService.getSudtInfo({ + txHash: tx.hash, + acpUdtInputs: acpXudtInputs, + acpUdtOutputs: acpXudtOutputs, + udtType: UDTType.XUDT, + })) || + (await TransactionsService.getAssetCKBInfo({ + txHash: tx.hash, + acpCKBInputs, + acpCKBOutputs, + })) return Transaction.fromObject({ timestamp: tx.timestamp, value: value.toString(), hash: tx.hash, version: tx.version, - type: txType, - assetAccountType: assetAccountType, - nervosDao: !!txDaoInfo, status: tx.status, description: tx.description, createdAt: tx.createdAt, updatedAt: tx.updatedAt, blockNumber: tx.blockNumber, - sudtInfo: sudtInfo, - nftInfo: nftInfo, - daoCapacity, + ...typeScriptInfo, + type: typeScriptInfo?.txType ?? (value > BigInt(0) ? 'receive' : 'send'), + nftInfo: TransactionsService.getNtfInfo({ txHash: tx.hash, nftInputs, nftOutputs }), + nervosDao: !!daoInfo.get(tx.hash), + daoCapacity: TransactionsService.getDAOCapacity(value, daoInfo.get(tx.hash)), }) }) ) @@ -639,7 +704,7 @@ export class TransactionsService { hd_public_key_info.publicKeyInBlake160 FROM hd_public_key_info WHERE walletId = :walletId - ) + ) ${lock ? 'AND lockCodeHash = :lockCodeHash AND lockHashType = :lockHashType' : ''} UNION SELECT @@ -652,7 +717,7 @@ export class TransactionsService { SELECT hd_public_key_info.publicKeyInBlake160 FROM hd_public_key_info WHERE - walletId = :walletId + walletId = :walletId ) ${lock ? 'AND lockCodeHash = :lockCodeHash AND lockHashType = :lockHashType' : ''} ) AS cell diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 025bedd07f..2fb2bd6f4f 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -1,7 +1,7 @@ import { v4 as uuid } from 'uuid' import { WalletNotFound, IsRequired, UsedName, WalletFunctionNotSupported, DuplicateImportWallet } from '../exceptions' import Store from '../models/store' -import { Keystore, AccountExtendedPublicKey } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import WalletDeletedSubject from '../models/subjects/wallet-deleted-subject' import { WalletListSubject, CurrentWalletSubject } from '../models/subjects/wallets' import { DefaultAddressNumber } from '../utils/scriptAndAddress' @@ -29,7 +29,7 @@ export interface WalletProperties { extendedKey: string // Serialized account extended public key isHDWallet?: boolean device?: DeviceInfo - keystore?: Keystore + keystore?: hd.Keystore startBlockNumber?: string } @@ -76,11 +76,11 @@ export abstract class Wallet { throw new Error('not implemented') } - public loadKeystore = (): Keystore => { + public loadKeystore = (): hd.Keystore => { throw new WalletFunctionNotSupported(this.loadKeystore.name) } - public saveKeystore = (_keystore: Keystore): void => { + public saveKeystore = (_keystore: hd.Keystore): void => { throw new WalletFunctionNotSupported(this.saveKeystore.name) } @@ -92,7 +92,7 @@ export abstract class Wallet { throw new WalletFunctionNotSupported(this.getDeviceInfo.name) } - public accountExtendedPublicKey = (): AccountExtendedPublicKey => { + public accountExtendedPublicKey = (): hd.AccountExtendedPublicKey => { throw new WalletFunctionNotSupported(this.accountExtendedPublicKey.name) } @@ -149,8 +149,8 @@ export class FileKeystoreWallet extends Wallet { this.isHD = true } - accountExtendedPublicKey = (): AccountExtendedPublicKey => { - return AccountExtendedPublicKey.parse(this.extendedKey) + accountExtendedPublicKey = (): hd.AccountExtendedPublicKey => { + return hd.AccountExtendedPublicKey.parse(this.extendedKey) } public toJSON = () => { @@ -166,14 +166,14 @@ export class FileKeystoreWallet extends Wallet { public loadKeystore = () => { const data = fileService.readFileSync(MODULE_NAME, this.keystoreFileName()) - return Keystore.fromJson(data) + return hd.Keystore.fromJson(data) } static fromJSON = (json: WalletProperties) => { return new FileKeystoreWallet(json) } - public saveKeystore = (keystore: Keystore): void => { + public saveKeystore = (keystore: hd.Keystore): void => { fileService.writeFileSync(MODULE_NAME, this.keystoreFileName(), JSON.stringify({ ...keystore, id: this.id })) } @@ -235,8 +235,8 @@ export class HardwareWallet extends Wallet { this.isHD = false } - accountExtendedPublicKey = (): AccountExtendedPublicKey => { - return AccountExtendedPublicKey.parse(this.extendedKey) + accountExtendedPublicKey = (): hd.AccountExtendedPublicKey => { + return hd.AccountExtendedPublicKey.parse(this.extendedKey) } static fromJSON = (json: WalletProperties) => { @@ -249,7 +249,7 @@ export class HardwareWallet extends Wallet { public checkAndGenerateAddresses = async (): Promise => { const { addressType, addressIndex } = this.getDeviceInfo() - const { publicKey } = AccountExtendedPublicKey.parse(this.extendedKey) + const { publicKey } = hd.AccountExtendedPublicKey.parse(this.extendedKey) const address = await AddressService.generateAndSaveForPublicKeyQueue.asyncPush({ walletId: this.id, publicKey, diff --git a/packages/neuron-wallet/src/types/rpc.d.ts b/packages/neuron-wallet/src/types/rpc.d.ts index 10a7333fa2..fc922e398b 100644 --- a/packages/neuron-wallet/src/types/rpc.d.ts +++ b/packages/neuron-wallet/src/types/rpc.d.ts @@ -100,6 +100,8 @@ declare namespace RPC { } time_added_to_pool: Uint64 | null cycles: Uint64 | null + fee: Uint64 + min_replace_fee: Uint64 } export interface TransactionPoint { block_number: BlockNumber diff --git a/packages/neuron-wallet/src/utils/ckb-rpc.ts b/packages/neuron-wallet/src/utils/ckb-rpc.ts index fc33fbefe7..6a7d3a08d8 100644 --- a/packages/neuron-wallet/src/utils/ckb-rpc.ts +++ b/packages/neuron-wallet/src/utils/ckb-rpc.ts @@ -1,9 +1,7 @@ -import type { ParamsFormatter } from '@ckb-lumos/rpc' -import type { Block } from '@ckb-lumos/base' -import type { Script } from '@ckb-lumos/base' -import { HexString } from '@ckb-lumos/base' +import type { HexString, Block, Script } from '@ckb-lumos/lumos' import { CKBRPC } from '@ckb-lumos/rpc' import { Method as SdkRpcMethod } from '@ckb-lumos/rpc/lib/method' +import { type CKBComponents, type ParamsFormatter } from '@ckb-lumos/lumos/rpc' import * as resultFormatter from '@ckb-lumos/rpc/lib/resultFormatter' import { formatter as paramsFormatter } from '@ckb-lumos/rpc/lib/paramsFormatter' import { Base } from '@ckb-lumos/rpc/lib/Base' @@ -16,12 +14,11 @@ import { request } from 'undici' import CommonUtils from './common' import { NetworkType } from '../models/network' import type { RPCConfig } from '@ckb-lumos/rpc/lib/types/common' -import type { CKBComponents } from '@ckb-lumos/rpc/lib/types/api' export interface LightScriptFilter { script: Script blockNumber: CKBComponents.BlockNumber - scriptType: CKBRPC.ScriptType + scriptType: CKBComponents.ScriptType } export type LightScriptSyncStatus = LightScriptFilter @@ -67,7 +64,7 @@ const lightRPCProperties: Record[0] paramsFormatters: [ (searchKey: { script: CKBComponents.Script - scriptType: CKBRPC.ScriptType + scriptType: CKBComponents.ScriptType blockRange: [HexString, HexString] }) => ({ script: { @@ -111,7 +108,7 @@ const lightRPCProperties: Record[0] paramsFormatters: [paramsFormatter.toHash], resultFormatters: (result: { status: 'fetched' | 'fetching' | 'added' | 'not_found' - data?: RPC.TransactionWithStatus + data?: Parameters[0] }) => { return { status: result.status, @@ -149,7 +146,11 @@ export class LightRPC extends Base { // TODO: the type is not the same as full node here // @ts-ignore getTransactions: ( - searchKey: { script: CKBComponents.Script; scriptType: CKBRPC.ScriptType; blockRange: [HexString, HexString] }, + searchKey: { + script: CKBComponents.Script + scriptType: CKBComponents.ScriptType + blockRange: [HexString, HexString] + }, order: 'asc' | 'desc', limit: HexString, afterCursor: HexString diff --git a/packages/neuron-wallet/src/utils/const.ts b/packages/neuron-wallet/src/utils/const.ts index d294db6b7f..9059715d05 100644 --- a/packages/neuron-wallet/src/utils/const.ts +++ b/packages/neuron-wallet/src/utils/const.ts @@ -24,6 +24,11 @@ export enum ResponseCode { Success, } +export enum UDTType { + SUDT = 'sUDT', + XUDT = 'xUDT', +} + export default { ResponseCode, } diff --git a/packages/neuron-wallet/src/utils/multisig.ts b/packages/neuron-wallet/src/utils/multisig.ts index 5caef9529a..d692479f75 100644 --- a/packages/neuron-wallet/src/utils/multisig.ts +++ b/packages/neuron-wallet/src/utils/multisig.ts @@ -1,4 +1,4 @@ -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import Multisig from '../models/multisig' import MultisigConfigModel from '../models/multisig-config' import { Signatures, SignStatus } from '../models/offline-sign' diff --git a/packages/neuron-wallet/src/utils/scriptAndAddress.ts b/packages/neuron-wallet/src/utils/scriptAndAddress.ts index a20fb27596..cbceca958c 100644 --- a/packages/neuron-wallet/src/utils/scriptAndAddress.ts +++ b/packages/neuron-wallet/src/utils/scriptAndAddress.ts @@ -1,7 +1,6 @@ -import { key } from '@ckb-lumos/hd' -import { type Script } from '@ckb-lumos/base' -import { predefined } from '@ckb-lumos/config-manager' -import { encodeToAddress, parseAddress } from '@ckb-lumos/helpers' +import { type Script, hd } from '@ckb-lumos/lumos' +import { predefined } from '@ckb-lumos/lumos/config' +import { encodeToAddress, parseAddress } from '@ckb-lumos/lumos/helpers' import { systemScripts } from './systemScripts' export enum DefaultAddressNumber { @@ -16,7 +15,7 @@ export const publicKeyToAddress = (publicKey: string, isMainnet = false) => { { codeHash: systemScripts.SECP256K1_BLAKE160.CODE_HASH, hashType: systemScripts.SECP256K1_BLAKE160.HASH_TYPE, - args: key.publicKeyToBlake160(prefixWith0x(publicKey)), + args: hd.key.publicKeyToBlake160(prefixWith0x(publicKey)), }, isMainnet ) diff --git a/packages/neuron-wallet/src/utils/serialization.ts b/packages/neuron-wallet/src/utils/serialization.ts index f1559467b3..07cb03c032 100644 --- a/packages/neuron-wallet/src/utils/serialization.ts +++ b/packages/neuron-wallet/src/utils/serialization.ts @@ -1,5 +1,5 @@ -import { CellDep, OutPoint, Input, Output, RawTransaction, Transaction, blockchain, WitnessArgs } from '@ckb-lumos/base' -import { bytes } from '@ckb-lumos/codec' +import { CellDep, OutPoint, Input, Output, RawTransaction, Transaction, WitnessArgs } from '@ckb-lumos/lumos' +import { bytes, blockchain } from '@ckb-lumos/lumos/codec' /** * @param outPoint always required when serialize diff --git a/packages/neuron-wallet/src/utils/shannonToCKB.ts b/packages/neuron-wallet/src/utils/shannonToCKB.ts index 8d9ba94c69..dce470115c 100644 --- a/packages/neuron-wallet/src/utils/shannonToCKB.ts +++ b/packages/neuron-wallet/src/utils/shannonToCKB.ts @@ -1,4 +1,6 @@ -import { formatUnit, ckbDecimals } from '@ckb-lumos/bi' +import { formatUnit } from '@ckb-lumos/lumos/utils' + +const ckbDecimals = 8 const shannonToCKB = (shannon: bigint) => { return new Intl.NumberFormat('en-US', { diff --git a/packages/neuron-wallet/src/utils/signWitnesses.ts b/packages/neuron-wallet/src/utils/signWitnesses.ts index 0efade4466..47b97826ed 100644 --- a/packages/neuron-wallet/src/utils/signWitnesses.ts +++ b/packages/neuron-wallet/src/utils/signWitnesses.ts @@ -1,7 +1,7 @@ -import { bytes, number } from '@ckb-lumos/codec' +import { bytes, Uint64LE } from '@ckb-lumos/lumos/codec' import { serializeWitnessArgs } from './serialization' -import { CKBHasher } from '@ckb-lumos/base/lib/utils' -import { key } from '@ckb-lumos/hd' +import { CKBHasher } from '@ckb-lumos/lumos/utils' +import { hd } from '@ckb-lumos/lumos' type StructuredWitness = CKBComponents.WitnessArgs | CKBComponents.Witness @@ -31,16 +31,16 @@ export const signWitnesses = ({ const hasher = new CKBHasher() hasher.update(transactionHash) - hasher.update(number.Uint64LE.pack(serializedEmptyWitnessSize)) + hasher.update(Uint64LE.pack(serializedEmptyWitnessSize)) hasher.update(serializedEmptyWitnessBytes) witnesses.slice(1).forEach(witness => { const witnessBytes = bytes.bytify(typeof witness === 'string' ? witness : serializeWitnessArgs(witness)) - hasher.update(number.Uint64LE.pack(witnessBytes.byteLength)) + hasher.update(Uint64LE.pack(witnessBytes.byteLength)) hasher.update(witnessBytes) }) const message = hasher.digestHex() - emptyWitness.lock = key.signRecoverable(message, privateKey) + emptyWitness.lock = hd.key.signRecoverable(message, privateKey) return [serializeWitnessArgs(emptyWitness), ...witnesses.slice(1)] } diff --git a/packages/neuron-wallet/src/utils/sudt-value-to-amount.ts b/packages/neuron-wallet/src/utils/sudt-value-to-amount.ts index 37c1ed2c03..1f4b8b8429 100644 --- a/packages/neuron-wallet/src/utils/sudt-value-to-amount.ts +++ b/packages/neuron-wallet/src/utils/sudt-value-to-amount.ts @@ -1,4 +1,4 @@ -import { formatUnit } from '@ckb-lumos/bi' +import { formatUnit } from '@ckb-lumos/lumos/utils' const sudtValueToAmount = (value: string | null = '0', decimal: string | null = '') => { return value === null || value === '0' diff --git a/packages/neuron-wallet/src/utils/systemScripts.ts b/packages/neuron-wallet/src/utils/systemScripts.ts index d238c8d2a7..d11165fe21 100644 --- a/packages/neuron-wallet/src/utils/systemScripts.ts +++ b/packages/neuron-wallet/src/utils/systemScripts.ts @@ -1,4 +1,4 @@ -import { predefined } from '@ckb-lumos/config-manager' +import { predefined } from '@ckb-lumos/lumos/config' const systemScriptsMainnet = predefined.LINA.SCRIPTS const systemScriptsTestnet = predefined.AGGRON4.SCRIPTS diff --git a/packages/neuron-wallet/tests/block-sync-renderer/full-synchronizer.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/full-synchronizer.test.ts index b4af6a23a4..bceea87ad7 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/full-synchronizer.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/full-synchronizer.test.ts @@ -1,11 +1,13 @@ import { scriptToAddress } from '../../src/utils/scriptAndAddress' import { when } from 'jest-when' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import { Address, AddressVersion } from '../../src/models/address' import SystemScriptInfo from '../../src/models/system-script-info' import FullSynchronizer from '../../src/block-sync-renderer/sync/full-synchronizer' import { flushPromises } from '../test-utils' +const { AddressType } = hd + const stubbedTipFn = jest.fn() const stubbedGetTransactionFn = jest.fn() const stubbedGetHeaderFn = jest.fn() diff --git a/packages/neuron-wallet/tests/block-sync-renderer/indexer-cache-service.intg.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/indexer-cache-service.intg.test.ts index 2ba8f41a08..4d6022b2d3 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/indexer-cache-service.intg.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/indexer-cache-service.intg.test.ts @@ -1,11 +1,13 @@ import { when } from 'jest-when' import AddressMeta from '../../src/database/address/meta' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import { AddressVersion } from '../../src/models/address' import IndexerTxHashCache from '../../src/database/chain/entities/indexer-tx-hash-cache' import RpcService from '../../src/services/rpc-service' import { closeConnection, getConnection, initConnection } from '../setupAndTeardown' +const { AddressType } = hd + const stubbedGetTransactionFn = jest.fn() const stubbedGetHeaderFn = jest.fn() const stubbedCollectFn = jest.fn(() => { diff --git a/packages/neuron-wallet/tests/block-sync-renderer/light-synchronizer.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/light-synchronizer.test.ts index 0b8d0b9531..7221546503 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/light-synchronizer.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/light-synchronizer.test.ts @@ -1,4 +1,4 @@ -import type { Script } from '@ckb-lumos/base' +import type { Script } from '@ckb-lumos/lumos' import LightSynchronizer from '../../src/block-sync-renderer/sync/light-synchronizer' import AddressMeta from '../../src/database/address/meta' diff --git a/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts index 52051e88e8..d25151e60c 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts @@ -2,7 +2,7 @@ import '../../src/types/ckbComponents.d.ts' import { Subject } from 'rxjs' import { Tip } from '@ckb-lumos/base' import { scriptToAddress } from '../../src/utils/scriptAndAddress' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import SystemScriptInfo from '../../src/models/system-script-info' import { Address, AddressVersion } from '../../src/models/address' import Queue from '../../src/block-sync-renderer/sync/queue' @@ -105,7 +105,7 @@ describe('queue', () => { blake160: `0x${'0'.repeat(40)}`, walletId: fakeWalletId, path: '', - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, addressIndex: 0, txCount: 0, liveBalance: '', diff --git a/packages/neuron-wallet/tests/block-sync-renderer/synchronizer.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/synchronizer.test.ts index 9836446cf2..fc51c62735 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/synchronizer.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/synchronizer.test.ts @@ -1,6 +1,6 @@ import { scriptToAddress } from '../../src/utils/scriptAndAddress' -import { AddressType } from '@ckb-lumos/hd' -import { QueryOptions, type Cell } from '@ckb-lumos/base' +import { type Cell, hd } from '@ckb-lumos/lumos' +import { QueryOptions } from '@ckb-lumos/base' import { Address, AddressVersion } from '../../src/models/address' import SystemScriptInfo from '../../src/models/system-script-info' import { Synchronizer } from '../../src/block-sync-renderer/sync/synchronizer' @@ -40,7 +40,7 @@ const addressObj1: Address = { blake160: '0x', walletId: walletId1, path: '', - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, addressIndex: 0, txCount: 0, liveBalance: '', @@ -54,7 +54,7 @@ const addressObj2: Address = { blake160: '0x', walletId: walletId2, path: '', - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, addressIndex: 0, txCount: 0, liveBalance: '', diff --git a/packages/neuron-wallet/tests/controllers/anyone-can-pay.test.ts b/packages/neuron-wallet/tests/controllers/anyone-can-pay.test.ts index dd906cea2d..119d08800a 100644 --- a/packages/neuron-wallet/tests/controllers/anyone-can-pay.test.ts +++ b/packages/neuron-wallet/tests/controllers/anyone-can-pay.test.ts @@ -1,7 +1,7 @@ import AnyoneCanPayController from '../../src/controllers/anyone-can-pay' import Transaction from '../../src/models/chain/transaction' import { ServiceHasNoResponse } from '../../src/exceptions' -import { ResponseCode } from '../../src/utils/const' +import { ResponseCode, UDTType } from '../../src/utils/const' import AssetAccountInfo from '../../src/models/asset-account-info' import { addressToScript } from '../../src/utils/scriptAndAddress' @@ -133,8 +133,8 @@ describe('anyone-can-pay-controller', () => { it('correct address', async () => { const address = 'ckt1qq6pngwqn6e9vlm92th84rk0l4jp2h8lurchjmnwv8kq3rt5psf4vqvyxgyfu4z8yq4t790um8jef7lpm40h2csv4cv7m' - await anyoneCanPayController.getHoldSudtCellCapacity(address, 'tokenID') - expect(getHoldSUDTCellCapacityMock).toHaveBeenCalledWith(addressToScript(address), 'tokenID') + await anyoneCanPayController.getHoldSudtCellCapacity(address, 'tokenID', UDTType.SUDT) + expect(getHoldSUDTCellCapacityMock).toHaveBeenCalledWith(addressToScript(address), 'tokenID', UDTType.SUDT) }) it('error address', async () => { const address = 'ct1qq6pngwqn6e9vlm92th84rk0l4jp2h8lurchjmnwv8kq3rt5psf4vqvyxgyfu4z8yq4t790um8jef7lpm40h2csv4cv7m' diff --git a/packages/neuron-wallet/tests/controllers/cell-management.test.ts b/packages/neuron-wallet/tests/controllers/cell-management.test.ts index c41d19326f..aaab619266 100644 --- a/packages/neuron-wallet/tests/controllers/cell-management.test.ts +++ b/packages/neuron-wallet/tests/controllers/cell-management.test.ts @@ -1,4 +1,4 @@ -import type { OutPoint as OutPointSDK } from '@ckb-lumos/base' +import type { OutPoint as OutPointSDK } from '@ckb-lumos/lumos' import CellManagement from '../../src/controllers/cell-management' import CellLocalInfo from '../../src/database/chain/entities/cell-local-info' import { AddressNotFound, CurrentWalletNotSet } from '../../src/exceptions' diff --git a/packages/neuron-wallet/tests/database/address/meta.test.ts b/packages/neuron-wallet/tests/database/address/meta.test.ts index cdc9f5605e..af9b7f4b62 100644 --- a/packages/neuron-wallet/tests/database/address/meta.test.ts +++ b/packages/neuron-wallet/tests/database/address/meta.test.ts @@ -1,5 +1,5 @@ import { Address, AddressVersion } from '../../../src/models/address' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import AddressMeta from '../../../src/database/address/meta' import Multisig from '../../../src/models/multisig' import AssetAccountInfo from '../../../src/models/asset-account-info' @@ -9,7 +9,7 @@ describe('Address Dao tests', () => { walletId: '1', address: 'ckt1qyqrdsefa43s6m882pcj53m4gdnj4k440axqswmu83', path: "m/44'/309'/0'/0/0", - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, addressIndex: 0, txCount: 0, liveBalance: '0', diff --git a/packages/neuron-wallet/tests/mock/hardware.ts b/packages/neuron-wallet/tests/mock/hardware.ts index bc8c04f3b3..0ba564fcf0 100644 --- a/packages/neuron-wallet/tests/mock/hardware.ts +++ b/packages/neuron-wallet/tests/mock/hardware.ts @@ -1,5 +1,5 @@ import { DeviceInfo } from '../../src/services/hardware/common' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import type { Subscriber } from 'rxjs' enum Manufacturer { @@ -12,7 +12,7 @@ export const ledgerNanoS: DeviceInfo = { product: 'Nano S', isBluetooth: false, manufacturer: Manufacturer.Ledger, - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, addressIndex: 0, } @@ -22,7 +22,7 @@ export const LedgerNanoX: DeviceInfo = { product: 'Nano X', isBluetooth: true, manufacturer: Manufacturer.Ledger, - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, addressIndex: 0, } diff --git a/packages/neuron-wallet/tests/models/asset-account-info.test.ts b/packages/neuron-wallet/tests/models/asset-account-info.test.ts index cb7d34a570..7a21201fef 100644 --- a/packages/neuron-wallet/tests/models/asset-account-info.test.ts +++ b/packages/neuron-wallet/tests/models/asset-account-info.test.ts @@ -1,27 +1,27 @@ +import { predefined } from '@ckb-lumos/config-manager' import AssetAccountInfo from '../../src/models/asset-account-info' import CellDep, { DepType } from '../../src/models/chain/cell-dep' import OutPoint from '../../src/models/chain/out-point' -import { ScriptHashType } from '../../src/models/chain/script' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import AddressMeta from '../../src/database/address/meta' +const { AddressType } = hd + describe('AssetAccountInfo', () => { + const { SUDT, ANYONE_CAN_PAY } = predefined.AGGRON4.SCRIPTS const testnetSudtInfo = { - cellDep: new CellDep( - new OutPoint('0xc1b2ae129fad7465aaa9acc9785f842ba3e6e8b8051d899defa89f5508a77958', '0'), - DepType.Code - ), - codeHash: '0x48dbf59b4c7ee1547238021b4869bceedf4eea6b43772e5d66ef8865b6ae7212', - hashType: ScriptHashType.Data, + cellDep: new CellDep(new OutPoint(SUDT.TX_HASH, SUDT.INDEX), SUDT.DEP_TYPE as DepType), + codeHash: SUDT.CODE_HASH, + hashType: SUDT.HASH_TYPE, } const testnetAnyoneCanPayInfo = { cellDep: new CellDep( - new OutPoint('0x4f32b3e39bd1b6350d326fdfafdfe05e5221865c3098ae323096f0bfc69e0a8c', '0'), - DepType.DepGroup + new OutPoint(ANYONE_CAN_PAY.TX_HASH, ANYONE_CAN_PAY.INDEX), + ANYONE_CAN_PAY.DEP_TYPE as DepType ), - codeHash: process.env.TESTNET_ACP_SCRIPT_CODEHASH, - hashType: process.env.TESTNET_ACP_SCRIPT_HASHTYPE, + codeHash: ANYONE_CAN_PAY.CODE_HASH, + hashType: ANYONE_CAN_PAY.HASH_TYPE, } describe('testnet', () => { diff --git a/packages/neuron-wallet/tests/models/keys/hd-public-key-info.test.ts b/packages/neuron-wallet/tests/models/keys/hd-public-key-info.test.ts index a9aee99971..59e59ba484 100644 --- a/packages/neuron-wallet/tests/models/keys/hd-public-key-info.test.ts +++ b/packages/neuron-wallet/tests/models/keys/hd-public-key-info.test.ts @@ -1,5 +1,5 @@ import { scriptToAddress } from '../../../src/utils/scriptAndAddress' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import KeyInfos from '../../setupAndTeardown/public-key-info.fixture' import { systemScripts } from '../../../src/utils/systemScripts' import { NetworkType } from '../../../src/models/network' @@ -76,7 +76,7 @@ describe('HdPublicKeyInfoModel', () => { describe('with change address type', () => { beforeEach(() => { keyInfoModel = HdPublicKeyInfoModel.fromObject({ - addressType: AddressType.Change, + addressType: hd.AddressType.Change, addressIndex: 1, }) }) @@ -87,7 +87,7 @@ describe('HdPublicKeyInfoModel', () => { describe('with receive address type', () => { beforeEach(() => { keyInfoModel = HdPublicKeyInfoModel.fromObject({ - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, addressIndex: 1, }) }) diff --git a/packages/neuron-wallet/tests/models/transaction-size.test.ts b/packages/neuron-wallet/tests/models/transaction-size.test.ts index 26371673b8..884fe631ee 100644 --- a/packages/neuron-wallet/tests/models/transaction-size.test.ts +++ b/packages/neuron-wallet/tests/models/transaction-size.test.ts @@ -1,5 +1,6 @@ import TransactionSize from '../../src/models/transaction-size' -import { bytes as byteUtils } from '@ckb-lumos/codec' +import { bytes as byteUtils } from '@ckb-lumos/lumos/codec' +import { type CKBComponents } from '@ckb-lumos/lumos/rpc' import Script, { ScriptHashType } from '../../src/models/chain/script' import WitnessArgs from '../../src/models/chain/witness-args' import Transaction from '../../src/models/chain/transaction' @@ -115,7 +116,6 @@ describe('TransactionSize', () => { args: '0x59a27ef3ba84f061517d13f42cf44ed020610061', hashType: 'type', }, - type: null, }, ], outputsData: ['0x1234', '0x'], diff --git a/packages/neuron-wallet/tests/services/address.test.ts b/packages/neuron-wallet/tests/services/address.test.ts index c2b09c39e7..3083b5a588 100644 --- a/packages/neuron-wallet/tests/services/address.test.ts +++ b/packages/neuron-wallet/tests/services/address.test.ts @@ -1,7 +1,7 @@ import SystemScriptInfo from '../../src/models/system-script-info' import { OutputStatus } from '../../src/models/chain/output' import OutputEntity from '../../src/database/chain/entities/output' -import { AddressType, AccountExtendedPublicKey } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import { Address } from '../../src/models/address' import Transaction from '../../src/database/chain/entities/transaction' import { TransactionStatus } from '../../src/models/chain/transaction' @@ -10,6 +10,8 @@ import HdPublicKeyInfo from '../../src/database/chain/entities/hd-public-key-inf import { closeConnection, getConnection, initConnection } from '../setupAndTeardown' import { NetworkType } from '../../src/models/network' +const { AddressType, AccountExtendedPublicKey } = hd + const walletId = '1' const extendedKey = new AccountExtendedPublicKey( '0x03e5b310636a0f6e7dcdfffa98f28d7ed70df858bb47acf13db830bfde3510b3f3', diff --git a/packages/neuron-wallet/tests/services/anyone-can-pay.test.ts b/packages/neuron-wallet/tests/services/anyone-can-pay.test.ts index 4f259b2a8e..bb6955fb0f 100644 --- a/packages/neuron-wallet/tests/services/anyone-can-pay.test.ts +++ b/packages/neuron-wallet/tests/services/anyone-can-pay.test.ts @@ -5,7 +5,7 @@ import { initConnection, closeConnection, getConnection } from '../setupAndTeard import { AcpSendSameAccountError, TargetLockError, TargetOutputNotFoundError } from '../../src/exceptions' import AssetAccountInfo from '../../src/models/asset-account-info' import SystemScriptInfo from '../../src/models/system-script-info' -import { MIN_SUDT_CAPACITY } from '../../src/utils/const' +import { MIN_SUDT_CAPACITY, UDTType } from '../../src/utils/const' const addressParseMock = jest.fn() jest.mock('../../src/models/address-parser', () => ({ @@ -78,7 +78,9 @@ describe('anyone-can-pay-service', () => { 'tokenName', '8', '0', - '0x62260b4dd406bee8a021185edaa60b7a77f7e99a' + '0x62260b4dd406bee8a021185edaa60b7a77f7e99a', + undefined, + UDTType.SUDT ) ) const ckbAssetAccount = AssetAccountEntity.fromModel( @@ -202,9 +204,9 @@ describe('anyone-can-pay-service', () => { assetAccountEntity.id ) expect(fromObjectMock).toHaveBeenCalledWith({ - capacity: BigInt(MIN_SUDT_CAPACITY).toString(), lock: targetLockScript, type: new AssetAccountInfo().generateSudtScript(assetAccount.tokenID), + data: '0x00000000000000000000000000000000', }) expect(generateAnyoneCanPayToSudtTxMock).toHaveBeenCalledWith( 'walletId', @@ -292,12 +294,13 @@ describe('anyone-can-pay-service', () => { //@ts-ignore await AnyoneCanPayService.getSUDTTargetOutput( SystemScriptInfo.generateSecpScript(assetAccount.blake160), - 'tokenID' + 'tokenID', + UDTType.SUDT ) expect(fromObjectMock).toHaveBeenCalledWith({ - capacity: BigInt(MIN_SUDT_CAPACITY).toString(), lock: SystemScriptInfo.generateSecpScript(assetAccount.blake160), type: new AssetAccountInfo().generateSudtScript('tokenID'), + data: '0x00000000000000000000000000000000', }) }) it('send to anyone pay address not exist', async () => { @@ -305,12 +308,13 @@ describe('anyone-can-pay-service', () => { //@ts-ignore await AnyoneCanPayService.getSUDTTargetOutput( new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), - 'tokenID' + 'tokenID', + UDTType.SUDT ) expect(fromObjectMock).toHaveBeenCalledWith({ - capacity: BigInt(MIN_SUDT_CAPACITY).toString(), lock: new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), type: new AssetAccountInfo().generateSudtScript('tokenID'), + data: '0x00000000000000000000000000000000', }) }) it('send to anyone pay address exist', async () => { @@ -345,11 +349,15 @@ describe('anyone-can-pay-service', () => { getOneByLockScriptAndTypeScriptMock.mockResolvedValue(undefined) const args = `0x${'0'.repeat(40)}` //@ts-ignore - await AnyoneCanPayService.getSUDTTargetOutput(new AssetAccountInfo().generateChequeScript(args, args), 'tokenID') + await AnyoneCanPayService.getSUDTTargetOutput( + new AssetAccountInfo().generateChequeScript(args, args), + 'tokenID', + UDTType.SUDT + ) expect(fromObjectMock).toHaveBeenCalledWith({ - capacity: BigInt(162 * 10 ** 8).toString(), lock: new AssetAccountInfo().generateChequeScript(args, args), type: new AssetAccountInfo().generateSudtScript('tokenID'), + data: '0x00000000000000000000000000000000', }) }) }) @@ -358,7 +366,8 @@ describe('anyone-can-pay-service', () => { it('is secp256 address', async () => { const res = await AnyoneCanPayService.getHoldSUDTCellCapacity( SystemScriptInfo.generateSecpScript(assetAccount.blake160), - '0x00' + '0x00', + UDTType.SUDT ) expect(res).toBe(undefined) }) @@ -373,7 +382,8 @@ describe('anyone-can-pay-service', () => { getOneByLockScriptAndTypeScriptMock.mockResolvedValue({}) const res = await AnyoneCanPayService.getHoldSUDTCellCapacity( new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), - '0x00' + '0x00', + UDTType.SUDT ) expect(res).toBe(undefined) }) @@ -381,7 +391,8 @@ describe('anyone-can-pay-service', () => { getOneByLockScriptAndTypeScriptMock.mockResolvedValue(undefined) const res = await AnyoneCanPayService.getHoldSUDTCellCapacity( new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), - '0x00' + `0x${'00'.repeat(32)}`, + UDTType.SUDT ) expect(res).toBe(BigInt(MIN_SUDT_CAPACITY).toString()) }) @@ -389,7 +400,8 @@ describe('anyone-can-pay-service', () => { getOneByLockScriptAndTypeScriptMock.mockResolvedValue(undefined) const res = await AnyoneCanPayService.getHoldSUDTCellCapacity( new AssetAccountInfo().generateChequeScript(assetAccount.blake160, assetAccount.blake160), - '0x00' + `0x${'00'.repeat(32)}`, + UDTType.SUDT ) expect(res).toBe(BigInt(162 * 10 ** 8).toString()) }) diff --git a/packages/neuron-wallet/tests/services/asset-account-service.test.ts b/packages/neuron-wallet/tests/services/asset-account-service.test.ts index 0e980b8a08..b4fea15789 100644 --- a/packages/neuron-wallet/tests/services/asset-account-service.test.ts +++ b/packages/neuron-wallet/tests/services/asset-account-service.test.ts @@ -11,13 +11,14 @@ import { TransactionStatus } from '../../src/models/chain/transaction' import { closeConnection, createAccounts, getConnection, initConnection } from '../setupAndTeardown' import accounts from '../setupAndTeardown/accounts.fixture' import HdPublicKeyInfo from '../../src/database/chain/entities/hd-public-key-info' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import OutPoint from '../../src/models/chain/out-point' import { when } from 'jest-when' import SystemScriptInfo from '../../src/models/system-script-info' import Script from '../../src/models/chain/script' import Input from '../../src/models/chain/input' import { keyInfos } from '../setupAndTeardown/public-key-info.fixture' +import { UDTType } from '../../src/utils/const' const stubbedWalletServiceGet = jest.fn() const stubbedGenerateClaimChequeTx = jest.fn() @@ -59,7 +60,8 @@ const generateOutput = ( tokenAmount = '100', customData: string | undefined = undefined, status: OutputStatus = OutputStatus.Live, - lock?: Script + lock?: Script, + udtType?: UDTType ) => { const outputEntity = new OutputEntity() outputEntity.outPointTxHash = randomHex() @@ -76,7 +78,7 @@ const generateOutput = ( outputEntity.data = customData || '0x' outputEntity.hasData = customData ? true : false if (tokenID !== 'CKBytes') { - const type = assetAccountInfo.generateSudtScript(tokenID) + const type = assetAccountInfo.generateUdtScript(tokenID, udtType ?? UDTType.SUDT)! outputEntity.typeCodeHash = type.codeHash outputEntity.typeArgs = type.args outputEntity.typeHashType = type.hashType @@ -146,7 +148,7 @@ describe('AssetAccountService', () => { const keyInfo = HdPublicKeyInfo.fromObject({ walletId, - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, addressIndex: 0, publicKeyInBlake160: blake160, }) @@ -251,6 +253,7 @@ describe('AssetAccountService', () => { describe('#getAll', () => { const tokenID = '0x' + '0'.repeat(64) + const xUdtTokenID = '0x' + '1'.repeat(64) describe('with both sUDT and CKB accounts', () => { describe('with live cells', () => { @@ -264,6 +267,17 @@ describe('AssetAccountService', () => { balance: '0', accountName: 'sUDT', blake160, + udtType: UDTType.SUDT, + }), + AssetAccount.fromObject({ + tokenID: xUdtTokenID, + symbol: 'xUDT', + tokenName: 'xUDT', + decimal: '0', + balance: '0', + accountName: 'xUDT', + blake160, + udtType: UDTType.XUDT, }), AssetAccount.fromObject({ tokenID: 'CKBytes', @@ -280,6 +294,7 @@ describe('AssetAccountService', () => { generateOutput(undefined, undefined, undefined, toShannon(1000)), generateOutput(tokenID), generateOutput(tokenID), + generateOutput(xUdtTokenID), ] await createAccounts(assetAccounts, outputs) }) @@ -302,6 +317,17 @@ describe('AssetAccountService', () => { balance: '0', accountName: 'sUDT', blake160, + udtType: UDTType.SUDT, + }), + AssetAccount.fromObject({ + tokenID: xUdtTokenID, + symbol: 'xUDT', + tokenName: 'xUDT', + decimal: '0', + balance: '0', + accountName: 'xUDT', + blake160, + udtType: UDTType.XUDT, }), AssetAccount.fromObject({ tokenID: 'CKBytes', @@ -318,13 +344,35 @@ describe('AssetAccountService', () => { generateOutput(undefined, undefined, undefined, toShannon(1000), undefined, undefined, OutputStatus.Sent), generateOutput(tokenID), generateOutput(tokenID, undefined, undefined, undefined, undefined, undefined, OutputStatus.Sent), + generateOutput( + xUdtTokenID, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + UDTType.XUDT + ), + generateOutput( + xUdtTokenID, + undefined, + undefined, + undefined, + undefined, + undefined, + OutputStatus.Sent, + undefined, + UDTType.XUDT + ), ] await createAccounts(assetAccounts, outputs) }) it('includes balance calculations for both sUDT and CKB accounts', async () => { const result = await AssetAccountService.getAll(walletId) - expect(result.length).toEqual(2) + expect(result.length).toEqual(3) expect(result.find((a: any) => a.tokenID === tokenID)?.balance).toEqual('200') expect(result.find((a: any) => a.tokenID === 'CKBytes')?.balance).toEqual(toShannon(2000 - 61).toString()) }) @@ -507,6 +555,7 @@ describe('AssetAccountService', () => { balance: '0', accountName: 'sUDT', blake160, + udtType: UDTType.SUDT, }), AssetAccount.fromObject({ tokenID: 'CKBytes', @@ -962,7 +1011,9 @@ describe('AssetAccountService', () => { '', '', '0', - '0x0000000000000000000000000000000000000000' + '0x0000000000000000000000000000000000000000', + undefined, + UDTType.SUDT ) const tx = {} beforeEach(async () => { diff --git a/packages/neuron-wallet/tests/services/cell-local-info.test.ts b/packages/neuron-wallet/tests/services/cell-local-info.test.ts index 066f906415..9d27d3eac5 100644 --- a/packages/neuron-wallet/tests/services/cell-local-info.test.ts +++ b/packages/neuron-wallet/tests/services/cell-local-info.test.ts @@ -1,4 +1,4 @@ -import type { OutPoint } from '@ckb-lumos/base' +import type { OutPoint } from '@ckb-lumos/lumos' import CellLocalInfoService from '../../src/services/cell-local-info' import { closeConnection, getConnection, initConnection } from '../setupAndTeardown' import CellLocalInfo from '../../src/database/chain/entities/cell-local-info' diff --git a/packages/neuron-wallet/tests/services/cells.test.ts b/packages/neuron-wallet/tests/services/cells.test.ts index 813a373f69..d2f7f90637 100644 --- a/packages/neuron-wallet/tests/services/cells.test.ts +++ b/packages/neuron-wallet/tests/services/cells.test.ts @@ -1,6 +1,6 @@ -import type { OutPoint as OutPointSDK } from '@ckb-lumos/base' +import type { OutPoint as OutPointSDK } from '@ckb-lumos/lumos' import { scriptToAddress } from '../../src/utils/scriptAndAddress' -import { bytes } from '@ckb-lumos/codec' +import { bytes } from '@ckb-lumos/lumos/codec' import OutputEntity from '../../src/database/chain/entities/output' import InputEntity from '../../src/database/chain/entities/input' import { OutputStatus } from '../../src/models/chain/output' @@ -1270,6 +1270,10 @@ describe('CellsService', () => { generateCell('666', OutputStatus.Live, true, typeScript, { lockScript: bobDefaultLock }), // sudt asset generateCell('777', OutputStatus.Live, true, sudtType, { lockScript: bobDefaultLock }), + // xudt asset + generateCell('888', OutputStatus.Live, true, assetAccountInfo.generateXudtScript('0x'), { + lockScript: bobDefaultLock, + }), ] await getConnection().manager.save(cells) }) @@ -1280,10 +1284,10 @@ describe('CellsService', () => { result = await CellsService.getCustomizedAssetCells([publicKeyHash], 1, 10) }) it('returns all items', () => { - expect(result.totalCount).toEqual(7) - expect(result.items.length).toEqual(7) + expect(result.totalCount).toEqual(8) + expect(result.items.length).toEqual(8) const totalCapacity = result.items.reduce((total: number, cell: any) => total + parseInt(cell.capacity), 0) - expect(totalCapacity).toEqual(100 * 3 + 10000 * 2 + 666 + 777) + expect(totalCapacity).toEqual(100 * 3 + 10000 * 2 + 666 + 777 + 888) }) it('attaches setCustomizedAssetInfo to single multisign cells', async () => { const singleMultiSignCells = result.items.filter( @@ -1312,23 +1316,32 @@ describe('CellsService', () => { const cells = result.items.filter((item: any) => item.capacity === '777') expect(cells.length).toEqual(1) expect(cells[0].customizedAssetInfo).toEqual({ - lock: CustomizedLock.SUDT, + lock: '', type: CustomizedType.SUDT, data: '', }) }) + it('attaches setCustomizedAssetInfo to xudt cells', () => { + const cells = result.items.filter((item: any) => item.capacity === '888') + expect(cells.length).toEqual(1) + expect(cells[0].customizedAssetInfo).toEqual({ + lock: '', + type: CustomizedType.XUDT, + data: '', + }) + }) }) describe('within pagination scope', () => { it('returns first page result', async () => { const page = 1 const result = await CellsService.getCustomizedAssetCells([publicKeyHash], page, pageSize) - expect(result.totalCount).toEqual(7) + expect(result.totalCount).toEqual(8) expect(result.items.length).toEqual(pageSize) }) it('returns the remaining cells for the last page', async () => { const page = 2 const result = await CellsService.getCustomizedAssetCells([publicKeyHash], page, pageSize) - expect(result.totalCount).toEqual(7) + expect(result.totalCount).toEqual(8) expect(result.items.length).toEqual(2) }) }) @@ -1336,7 +1349,7 @@ describe('CellsService', () => { it('returns empty result', async () => { const page = 8 const result = await CellsService.getCustomizedAssetCells([publicKeyHash], page, pageSize) - expect(result.totalCount).toEqual(7) + expect(result.totalCount).toEqual(8) expect(result.items.length).toEqual(0) }) }) diff --git a/packages/neuron-wallet/tests/services/multisig.test.ts b/packages/neuron-wallet/tests/services/multisig.test.ts index 444c916b22..155cfab9f0 100644 --- a/packages/neuron-wallet/tests/services/multisig.test.ts +++ b/packages/neuron-wallet/tests/services/multisig.test.ts @@ -1,3 +1,12 @@ +jest.doMock('../../src/models/subjects/multisig-config-db-changed-subject', () => ({ + getSubject() { + return { + next: jest.fn(), + subscribe: jest.fn(), + } + }, +})) + import MultisigConfig from '../../src/database/chain/entities/multisig-config' import MultisigConfigModel from '../../src/models/multisig-config' import MultisigService from '../../src/services/multisig' @@ -6,7 +15,7 @@ import { OutputStatus } from '../../src/models/chain/output' import { keyInfos } from '../setupAndTeardown/public-key-info.fixture' import Multisig from '../../src/models/multisig' import SystemScriptInfo from '../../src/models/system-script-info' -import { computeScriptHash as scriptToHash } from '@ckb-lumos/base/lib/utils' +import { computeScriptHash as scriptToHash } from '@ckb-lumos/lumos/utils' import { closeConnection, getConnection, initConnection } from '../setupAndTeardown' import { NetworkType } from '../../src/models/network' import { scheduler } from 'timers/promises' @@ -85,13 +94,14 @@ describe('multisig service', () => { multisigConfigModel.id = res?.id await getConnection().manager.save(multisigOutput) rpcBatchRequestMock.mockResolvedValue([]) - }) + }, 20_000) afterEach(async () => { const connection = getConnection() - await connection.synchronize(true) + await connection.getRepository(MultisigConfig).clear() + await connection.getRepository(MultisigOutput).clear() rpcBatchRequestMock.mockReset() multisigOutputChangedSubjectNextMock.mockReset() - }) + }, 20_000) describe('save multisig config', () => { it('has exist', async () => { diff --git a/packages/neuron-wallet/tests/services/networks.test.ts b/packages/neuron-wallet/tests/services/networks.test.ts index af3ad18a67..98b2b910ca 100644 --- a/packages/neuron-wallet/tests/services/networks.test.ts +++ b/packages/neuron-wallet/tests/services/networks.test.ts @@ -158,21 +158,27 @@ describe(`Unit tests of networks service`, () => { describe(`validation on parameters`, () => { describe(`validation on parameters`, () => { it(`service.create requires name, and remote`, async () => { - expect(service.create(undefined as any, undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) - expect(service.create('network name', undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) + await expect(service.create(undefined as any, undefined as any)).rejects.toThrowError( + t(ERROR_MESSAGE.MISSING_ARG) + ) + await expect(service.create('network name', undefined as any)).rejects.toThrowError( + t(ERROR_MESSAGE.MISSING_ARG) + ) }) - it(`service.update requires id, options`, () => { - expect(service.update(undefined as any, undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) - expect(service.update('', undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) + it(`service.update requires id, options`, async () => { + await expect(service.update(undefined as any, undefined as any)).rejects.toThrowError( + t(ERROR_MESSAGE.MISSING_ARG) + ) + await expect(service.update('', undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) }) - it(`service.delete requires id `, () => { - expect(service.delete(undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) + it(`service.delete requires id `, async () => { + await expect(service.delete(undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) }) - it(`service.activate requires id `, () => { - expect(service.activate(undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) + it(`service.activate requires id `, async () => { + await expect(service.activate(undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) }) }) }) @@ -182,18 +188,18 @@ describe(`Unit tests of networks service`, () => { await service.create('Default', 'http://127.0.0.1:8114') }) - it(`create network with existing name of Default`, () => { - expect(service.create('Default', 'http://127.0.0.1:8114')).rejects.toThrowError(t(ERROR_MESSAGE.NAME_USED)) + it(`create network with existing name of Default`, async () => { + await expect(service.create('Default', 'http://127.0.0.1:8114')).rejects.toThrowError(t(ERROR_MESSAGE.NAME_USED)) }) - it(`update network which is not existing`, () => { + it(`update network which is not existing`, async () => { const id = `not-existing-id` - expect(service.update(id, {})).rejects.toThrowError(t(ERROR_MESSAGE.NETWORK_ID_NOT_FOUND, { id })) + await expect(service.update(id, {})).rejects.toThrowError(t(ERROR_MESSAGE.NETWORK_ID_NOT_FOUND, { id })) }) - it(`activate network which is not existing`, () => { + it(`activate network which is not existing`, async () => { const id = `not-existing-id` - expect(service.activate(id)).rejects.toThrowError(t(ERROR_MESSAGE.NETWORK_ID_NOT_FOUND, { id })) + await expect(service.activate(id)).rejects.toThrowError(t(ERROR_MESSAGE.NETWORK_ID_NOT_FOUND, { id })) }) }) @@ -223,6 +229,7 @@ describe(`Unit tests of networks service`, () => { service.readSync = readSyncMock service.writeSync = writeSyncMock service.updateAll = updateAllMock + service.activate = jest.fn() }) afterEach(() => { readSyncMock.mockReset() diff --git a/packages/neuron-wallet/tests/services/sudt-token-info.test.ts b/packages/neuron-wallet/tests/services/sudt-token-info.test.ts index f89fd33088..9ce636567d 100644 --- a/packages/neuron-wallet/tests/services/sudt-token-info.test.ts +++ b/packages/neuron-wallet/tests/services/sudt-token-info.test.ts @@ -4,6 +4,7 @@ import { closeConnection, getConnection, initConnection } from '../setupAndTeard import HdPublicKeyInfo from '../../src/database/chain/entities/hd-public-key-info' import AssetAccountEntity from '../../src/database/chain/entities/asset-account' import accounts from '../setupAndTeardown/accounts.fixture' +import { UDTType } from '../../src/utils/const' const defaultTokenId = '0x' + '0'.repeat(64) @@ -162,19 +163,19 @@ describe('sudt token info service', () => { }) it('no token info', async () => { - await expect(SudtTokenInfoService.getSudtTokenInfo('0x')).resolves.toBeNull() + await expect(SudtTokenInfoService.getSudtTokenInfo('0x', UDTType.SUDT)).resolves.toBeNull() }) it('token info not match', async () => { const entity = AssetAccountEntity.fromModel(assetAccount) await getConnection().manager.save([entity.sudtTokenInfo, entity]) - await expect(SudtTokenInfoService.getSudtTokenInfo(`0x${'00'.repeat(20)}`)).resolves.toBeNull() + await expect(SudtTokenInfoService.getSudtTokenInfo(`0x${'00'.repeat(20)}`, UDTType.SUDT)).resolves.toBeNull() }) it('match token info', async () => { const entity = AssetAccountEntity.fromModel(assetAccount) await getConnection().manager.save([entity.sudtTokenInfo, entity]) - const result = await SudtTokenInfoService.getSudtTokenInfo(assetAccount.tokenID) + const result = await SudtTokenInfoService.getSudtTokenInfo(assetAccount.tokenID, UDTType.SUDT) expect(result).toBeDefined() expect(result?.assetAccounts).toHaveLength(1) }) diff --git a/packages/neuron-wallet/tests/services/tx-wallet.test.ts b/packages/neuron-wallet/tests/services/tx-wallet.test.ts index 66cde86d55..17992d97d0 100644 --- a/packages/neuron-wallet/tests/services/tx-wallet.test.ts +++ b/packages/neuron-wallet/tests/services/tx-wallet.test.ts @@ -1,7 +1,6 @@ import WalletService from '../../src/services/wallets' -import { bytes } from '@ckb-lumos/codec' -import { Keychain, Keystore, ExtendedPrivateKey, AccountExtendedPublicKey } from '@ckb-lumos/hd' -import { mnemonicToSeedSync } from '@ckb-lumos/hd/lib/mnemonic' +import { bytes } from '@ckb-lumos/lumos/codec' +import { hd } from '@ckb-lumos/lumos' import TransactionSender from '../../src/services/transaction-sender' import { signWitnesses } from '../../src/utils/signWitnesses' @@ -41,18 +40,18 @@ describe('get keys with paths', () => { }) it('get keys', () => { - const seed = mnemonicToSeedSync(mnemonic) - const masterKeychain = Keychain.fromSeed(seed) - const extendedKey = new ExtendedPrivateKey( + const seed = hd.mnemonic.mnemonicToSeedSync(mnemonic) + const masterKeychain = hd.Keychain.fromSeed(seed) + const extendedKey = new hd.ExtendedPrivateKey( bytes.hexify(masterKeychain.privateKey), bytes.hexify(masterKeychain.chainCode) ) const privateKey = bytes.hexify(masterKeychain.derivePath(receivingPath).privateKey) expect(privateKey).toEqual(receivingPrivateKey) - const keystore = Keystore.create(extendedKey, password) + const keystore = hd.Keystore.create(extendedKey, password) - const accountKeychain = masterKeychain.derivePath(AccountExtendedPublicKey.ckbAccountPath) - const accountExtendedPublicKey = new AccountExtendedPublicKey( + const accountKeychain = masterKeychain.derivePath(hd.AccountExtendedPublicKey.ckbAccountPath) + const accountExtendedPublicKey = new hd.AccountExtendedPublicKey( bytes.hexify(accountKeychain.publicKey), bytes.hexify(accountKeychain.chainCode) ) diff --git a/packages/neuron-wallet/tests/services/tx/transaction-generator.test.ts b/packages/neuron-wallet/tests/services/tx/transaction-generator.test.ts index c8ba7d414a..057a0c6018 100644 --- a/packages/neuron-wallet/tests/services/tx/transaction-generator.test.ts +++ b/packages/neuron-wallet/tests/services/tx/transaction-generator.test.ts @@ -1,6 +1,6 @@ import { when } from 'jest-when' -import { bytes } from '@ckb-lumos/codec' -import { since } from '@ckb-lumos/base' +import { bytes } from '@ckb-lumos/lumos/codec' +import { since } from '@ckb-lumos/lumos' import OutputEntity from '../../../src/database/chain/entities/output' import InputEntity from '../../../src/database/chain/entities/input' import TransactionEntity from '../../../src/database/chain/entities/transaction' @@ -87,6 +87,7 @@ import AssetAccount from '../../../src/models/asset-account' import MultisigConfigModel from '../../../src/models/multisig-config' import MultisigOutput from '../../../src/database/chain/entities/multisig-output' import { closeConnection, getConnection, initConnection } from '../../setupAndTeardown' +import { UDTType } from '../../../src/utils/const' describe('TransactionGenerator', () => { beforeAll(async () => { @@ -2094,14 +2095,14 @@ describe('TransactionGenerator', () => { describe('generateCreateAnyoneCanPayTx', () => { const feeRate = '1000' it('create ckb', async () => { - const tx = await TransactionGenerator.generateCreateAnyoneCanPayTx( - 'CKBytes', - walletId1, - alice.lockScript.args, - bob.lockScript.args, + const tx = await TransactionGenerator.generateCreateAnyoneCanPayTx({ + tokenID: 'CKBytes', + walletId: walletId1, + blake160: alice.lockScript.args, + changeBlake160: bob.lockScript.args, feeRate, - '0' - ) + fee: '0', + }) // check fee const inputCapacities = tx.inputs.map(i => BigInt(i.capacity ?? 0)).reduce((result, c) => result + c, BigInt(0)) @@ -2129,14 +2130,15 @@ describe('TransactionGenerator', () => { it('create sudt', async () => { const tokenID = '0x' + '0'.repeat(64) - const tx = await TransactionGenerator.generateCreateAnyoneCanPayTx( + const tx = await TransactionGenerator.generateCreateAnyoneCanPayTx({ tokenID, - walletId1, - alice.lockScript.args, - bob.lockScript.args, + walletId: walletId1, + blake160: alice.lockScript.args, + changeBlake160: bob.lockScript.args, feeRate, - '0' - ) + fee: '0', + udtType: UDTType.SUDT, + }) // check fee const inputCapacities = tx.inputs.map(i => BigInt(i.capacity ?? 0)).reduce((result, c) => result + c, BigInt(0)) @@ -2193,7 +2195,7 @@ describe('TransactionGenerator', () => { type: senderAcpLiveCell.type(), data: BufferUtils.writeBigUInt128LE(BigInt(110)), }) - assetAccount = new AssetAccount(tokenID, '', '', '', '', '', alice.lockScript.args) + assetAccount = new AssetAccount(tokenID, '', '', '', '', '', alice.lockScript.args, undefined, UDTType.SUDT) }) describe('with numeric send amount', () => { beforeEach(async () => { @@ -2561,11 +2563,11 @@ describe('TransactionGenerator', () => { }) const bobLockHash = scriptToAddress(bobAnyoneCanPayLockScript) const res = (await TransactionGenerator.generateSudtMigrateAcpTx(sudtCell, bobLockHash)) as Transaction - expect(res.outputs).toHaveLength(3) + expect(res.outputs).toHaveLength(2) expect(res.outputs[1].data).toEqual(BufferUtils.writeBigUInt128LE(BigInt(200))) - expect(res.outputs[2].capacity).toEqual((BigInt(secpCell.capacity) - BigInt(res.fee ?? 0)).toString()) - expect(res.inputs).toHaveLength(3) - expect(res.inputs[2].lockHash).toBe(bobAnyoneCanPayLockScript.computeHash()) + expect(res.outputs[0].capacity).toEqual((BigInt(sudtCell.capacity) - BigInt(res.fee ?? 0)).toString()) + expect(res.inputs).toHaveLength(2) + expect(res.inputs[1].lockHash).toBe(bobAnyoneCanPayLockScript.computeHash()) }) }) @@ -2633,13 +2635,13 @@ describe('TransactionGenerator', () => { const cells: OutputEntity[] = [generateCell(toShannon('100'), OutputStatus.Live, false, null)] await getConnection().manager.save(cells) - const tx = await TransactionGenerator.generateCreateAnyoneCanPayTxUseAllBalance( - 'CKBytes', - walletId1, - alice.lockScript.args, + const tx = await TransactionGenerator.generateCreateAnyoneCanPayTxUseAllBalance({ + tokenID: 'CKBytes', + walletId: walletId1, + blake160: alice.lockScript.args, feeRate, - '0' - ) + fee: '0', + }) // check fee const inputCapacities = tx.inputs.map(i => BigInt(i.capacity ?? 0)).reduce((result, c) => result + c, BigInt(0)) @@ -2667,13 +2669,14 @@ describe('TransactionGenerator', () => { await getConnection().manager.save(cells) const tokenID = '0x' + '0'.repeat(64) - const tx = await TransactionGenerator.generateCreateAnyoneCanPayTxUseAllBalance( + const tx = await TransactionGenerator.generateCreateAnyoneCanPayTxUseAllBalance({ tokenID, - walletId1, - alice.lockScript.args, + walletId: walletId1, + blake160: alice.lockScript.args, feeRate, - '0' - ) + fee: '0', + udtType: UDTType.SUDT, + }) // check fee const inputCapacities = tx.inputs.map(i => BigInt(i.capacity ?? 0)).reduce((result, c) => result + c, BigInt(0)) @@ -2689,6 +2692,35 @@ describe('TransactionGenerator', () => { expect(assetAccountInfo.isAnyoneCanPayScript(output.lock)).toBe(true) expect(output.data).toEqual('0x' + '0'.repeat(32)) }) + + it('create xudt', async () => { + const cells: OutputEntity[] = [generateCell(toShannon('143'), OutputStatus.Live, false, null)] + await getConnection().manager.save(cells) + + const tokenID = '0x' + '0'.repeat(64) + const tx = await TransactionGenerator.generateCreateAnyoneCanPayTxUseAllBalance({ + tokenID, + walletId: walletId1, + blake160: alice.lockScript.args, + feeRate, + fee: '0', + udtType: UDTType.XUDT, + }) + + // check fee + const inputCapacities = tx.inputs.map(i => BigInt(i.capacity ?? 0)).reduce((result, c) => result + c, BigInt(0)) + const outputCapacities = tx.outputs.map(o => BigInt(o.capacity)).reduce((result, c) => result + c, BigInt(0)) + expect(tx.fee).toEqual((inputCapacities - outputCapacities).toString()) + + // check output + expect(tx.outputs.length).toEqual(1) + + const output = tx.outputs[0] + expect(output.capacity).toEqual((BigInt(143 * 10 ** 8) - BigInt(tx.fee ?? 0)).toString()) + expect(assetAccountInfo.isXudtScript(output.type!)).toBe(true) + expect(assetAccountInfo.isAnyoneCanPayScript(output.lock)).toBe(true) + expect(output.data).toEqual('0x' + '0'.repeat(32)) + }) }) describe('#generateMigrateLegacyACPTx', () => { diff --git a/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts b/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts index 919d8f3bdd..eaf1894650 100644 --- a/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts +++ b/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts @@ -1,4 +1,5 @@ -import { bytes } from '@ckb-lumos/codec' +import { CKBComponents } from '@ckb-lumos/lumos/rpc' +import { bytes } from '@ckb-lumos/lumos/codec' import 'dotenv/config' const stubbedRPCServiceConstructor = jest.fn() @@ -145,7 +146,7 @@ jest.doMock('services/hardware', () => ({ }), })) -jest.doMock('@ckb-lumos/rpc', () => { +jest.doMock('@ckb-lumos/lumos/rpc', () => { return { CKBRPC: class CKBRPC { url: string @@ -158,7 +159,7 @@ jest.doMock('@ckb-lumos/rpc', () => { } }) -jest.doMock('@ckb-lumos/common-scripts', () => { +jest.doMock('@ckb-lumos/lumos/common-scripts', () => { return { dao: { calculateMaximumWithdraw: stubbedCalculateDaoMaximumWithdraw, @@ -187,7 +188,7 @@ import OutPoint from '../../../src/models/chain/out-point' import Input from '../../../src/models/chain/input' import Script, { ScriptHashType } from '../../../src/models/chain/script' import Output from '../../../src/models/chain/output' -import { AddressType, Keystore } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import WitnessArgs from '../../../src/models/chain/witness-args' import CellWithStatus from '../../../src/models/chain/cell-with-status' import SystemScriptInfo from '../../../src/models/system-script-info' @@ -256,7 +257,7 @@ describe('TransactionSender Test', () => { name: 'wallet-test1', id: '11', extendedKey: 'a', - keystore: new Keystore( + keystore: new hd.Keystore( { cipher: 'wallet1', cipherparams: { iv: 'wallet1' }, @@ -325,7 +326,7 @@ describe('TransactionSender Test', () => { walletId: fakeWallet.id, address: '', path: `m/44'/309'/0'/0/0`, - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, addressIndex: 1, txCount: 0, liveBalance: '0', diff --git a/packages/neuron-wallet/tests/services/tx/transaction-service.test.ts b/packages/neuron-wallet/tests/services/tx/transaction-service.test.ts index 6b5f9165a8..05850caa09 100644 --- a/packages/neuron-wallet/tests/services/tx/transaction-service.test.ts +++ b/packages/neuron-wallet/tests/services/tx/transaction-service.test.ts @@ -32,7 +32,7 @@ jest.mock('../../../src/services/rpc-service', () => { }) const ckbRpcExecMock = jest.fn() -jest.mock('@ckb-lumos/rpc', () => { +jest.mock('@ckb-lumos/lumos/rpc', () => { return { CKBRPC: class CKBRPC { url: string diff --git a/packages/neuron-wallet/tests/services/wallets.test.ts b/packages/neuron-wallet/tests/services/wallets.test.ts index 5940e0c57a..0d7eec58c6 100644 --- a/packages/neuron-wallet/tests/services/wallets.test.ts +++ b/packages/neuron-wallet/tests/services/wallets.test.ts @@ -1,6 +1,6 @@ import { when } from 'jest-when' import { WalletFunctionNotSupported, DuplicateImportWallet } from '../../src/exceptions/wallet' -import { AddressType, Keystore, AccountExtendedPublicKey } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import { Manufacturer } from '../../src/services/hardware/common' import { prefixWith0x } from '../../src/utils/scriptAndAddress' @@ -76,7 +76,7 @@ describe('wallet service', () => { name: 'wallet-test1', id: '', extendedKey: `${fakePublicKey}${fakeChainCode}`, - keystore: new Keystore( + keystore: new hd.Keystore( { cipher: 'wallet1', cipherparams: { iv: 'wallet1' }, @@ -99,7 +99,7 @@ describe('wallet service', () => { name: 'wallet-test2', id: '', extendedKey: 'b'.repeat(66) + '2'.repeat(64), - keystore: new Keystore( + keystore: new hd.Keystore( { cipher: 'wallet2', cipherparams: { iv: 'wallet2' }, @@ -122,7 +122,7 @@ describe('wallet service', () => { name: 'wallet-test3', id: '', extendedKey: 'c'.repeat(66) + '3'.repeat(64), - keystore: new Keystore( + keystore: new hd.Keystore( { cipher: 'wallet3', cipherparams: { iv: 'wallet1' }, @@ -152,7 +152,7 @@ describe('wallet service', () => { descriptor: '', vendorId: '10086', addressIndex: 0, - addressType: AddressType.Receiving, + addressType: hd.AddressType.Receiving, }, } @@ -160,7 +160,7 @@ describe('wallet service', () => { name: 'wallet-test5', id: '', extendedKey: 'b'.repeat(66) + '2'.repeat(64), - keystore: new Keystore( + keystore: new hd.Keystore( { cipher: 'wallet5', cipherparams: { iv: 'wallet1' }, @@ -294,7 +294,7 @@ describe('wallet service', () => { await wallet.checkAndGenerateAddresses() }) it('calls AddressService.generateAndSaveForExtendedKey', async () => { - const { publicKey } = AccountExtendedPublicKey.parse(wallet4.extendedKey) + const { publicKey } = hd.AccountExtendedPublicKey.parse(wallet4.extendedKey) expect(stubbedGenerateAndSaveForPublicKeyQueueAsyncPush).toHaveBeenCalledWith({ walletId: createdWallet.id, publicKey, diff --git a/packages/neuron-wallet/tests/setupAndTeardown/accounts.fixture.ts b/packages/neuron-wallet/tests/setupAndTeardown/accounts.fixture.ts index 21d4c06b97..86d25a65fc 100644 --- a/packages/neuron-wallet/tests/setupAndTeardown/accounts.fixture.ts +++ b/packages/neuron-wallet/tests/setupAndTeardown/accounts.fixture.ts @@ -1,4 +1,5 @@ import AssetAccount from '../../src/models/asset-account' +import { UDTType } from '../../src/utils/const' import { DEPLOY_KEY } from './keys' const ASSET_ACCOUNT = { @@ -9,6 +10,7 @@ const ASSET_ACCOUNT = { balance: '0', accountName: 'SUDT Account', blake160: DEPLOY_KEY.blake160, + udtType: UDTType.SUDT, } const CKB_ASSET_ACCOUNT = { diff --git a/packages/neuron-wallet/tests/setupAndTeardown/public-key-info.fixture.ts b/packages/neuron-wallet/tests/setupAndTeardown/public-key-info.fixture.ts index d11da66bfb..821b67e66d 100644 --- a/packages/neuron-wallet/tests/setupAndTeardown/public-key-info.fixture.ts +++ b/packages/neuron-wallet/tests/setupAndTeardown/public-key-info.fixture.ts @@ -1,7 +1,9 @@ import { scriptToAddress } from '../../src/utils/scriptAndAddress' -import { AddressType } from '@ckb-lumos/hd' +import { hd } from '@ckb-lumos/lumos' import SystemScriptInfo from '../../src/models/system-script-info' +const AddressType = hd.AddressType + const walletId1 = 'w1' const walletId2 = 'w2' const walletId3 = 'w3' diff --git a/yarn.lock b/yarn.lock index 39a48252f9..75fbbf33bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2117,129 +2117,158 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@ckb-lumos/base@0.21.1", "@ckb-lumos/base@^0.21.0-next.0": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/base/-/base-0.21.1.tgz#1faf7909b5a68a124256d937cfb0fa03bb6b5457" - integrity sha512-7O+jBl7pqMsRbYTMNnbpamgaQzvaLZq+ftMtnKZ3A+Zbs6hZcGbz/6nfbRZnyJitPXQHRPT5KAQz6g+TiYqJGg== - dependencies: - "@ckb-lumos/bi" "0.21.1" - "@ckb-lumos/codec" "0.21.1" - "@ckb-lumos/toolkit" "0.21.1" +"@ckb-lumos/base@0.23.0", "@ckb-lumos/base@^0.21.0-next.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/base/-/base-0.23.0.tgz#507e2860dd49547268e9088e10aa2051507d4343" + integrity sha512-8aLFsUyWIK0rT7GQlYFuXyiG5lQ2bLRK2GvUsxv5G7I3nJ1UyxjwvVOdtlsR/cwhzOam3ujwqASqBIayBL6GLA== + dependencies: + "@ckb-lumos/bi" "0.23.0" + "@ckb-lumos/codec" "0.23.0" + "@ckb-lumos/toolkit" "0.23.0" "@types/blake2b" "^2.1.0" "@types/lodash.isequal" "^4.5.5" blake2b "^2.1.3" js-xxhash "^1.0.4" lodash.isequal "^4.5.0" -"@ckb-lumos/bi@0.21.1", "@ckb-lumos/bi@^0.21.0-next.0": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/bi/-/bi-0.21.1.tgz#dfaa0968a9ffd990c1c4fcfc0711f20f09eb0485" - integrity sha512-6q8uesvu3DAM7GReei9H5seino4tnakTeg8uXtZBPDC6rboMohLCPQvEwhl1iHmsybXvBYVQt4Te1BPPZtuaRw== +"@ckb-lumos/bi@0.23.0", "@ckb-lumos/bi@^0.21.0-next.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/bi/-/bi-0.23.0.tgz#8439d712b823234b858bffff2636ffc21d98199f" + integrity sha512-KAy+lyVpL+Al4XD+c9tHrA9DSpHkMusyXtTS81aNZi5MyL6F9jrVmFcqLorhfyfl8Fsv2sEjMe5Neo2Y+w/RJQ== dependencies: jsbi "^4.1.0" -"@ckb-lumos/ckb-indexer@0.21.1": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/ckb-indexer/-/ckb-indexer-0.21.1.tgz#a0e0ac3261c98181dc8c72e9e726030bb210779d" - integrity sha512-592pMVP3lwTXF7TmlOcayvGYKOhkYpjbLHUDo7By4yWbm7ZpdexaN5hn0X1sjJgMuee5prxGr9/fY684VTpJQw== - dependencies: - "@ckb-lumos/base" "0.21.1" - "@ckb-lumos/bi" "0.21.1" - "@ckb-lumos/codec" "0.21.1" - "@ckb-lumos/rpc" "0.21.1" - "@ckb-lumos/toolkit" "0.21.1" +"@ckb-lumos/ckb-indexer@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/ckb-indexer/-/ckb-indexer-0.23.0.tgz#67cbf4539904ea511517fda1e23c5ec4515b574d" + integrity sha512-yLODLJzvtz4M6W6OJR4iRbBTUGrKReV2dhVePPjbH/HRkRY6f6J6cEM9+qM2I3QABmaCXeAM3hWvnWU9hjalQQ== + dependencies: + "@ckb-lumos/base" "0.23.0" + "@ckb-lumos/bi" "0.23.0" + "@ckb-lumos/codec" "0.23.0" + "@ckb-lumos/rpc" "0.23.0" + "@ckb-lumos/toolkit" "0.23.0" cross-fetch "^3.1.5" events "^3.3.0" -"@ckb-lumos/codec@0.21.1", "@ckb-lumos/codec@^0.21.0-next.0": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/codec/-/codec-0.21.1.tgz#160f21efa0cded6ea461eb6476f9af6010b682e0" - integrity sha512-z6IUUxVZrx663iC7VM9CmaQZL8jsdM3ybgz0UCS24JgBXTNec+Uz0/Zrl7yeH6fBpVls44C2wObcHKigKaNVAA== - dependencies: - "@ckb-lumos/bi" "0.21.1" - -"@ckb-lumos/common-scripts@0.21.1", "@ckb-lumos/common-scripts@^0.21.0-next.0": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/common-scripts/-/common-scripts-0.21.1.tgz#64776b5ce55d8c66898a3ab592c7f77fe13d865e" - integrity sha512-EfZQ9wdxPmEsxVVwtBjhpZVKbYCm1FJkMt59ABsIO1Ub7yi0qap7AQl0MMbuLwWIGKwS2w0U3wx/oJPm7z1RXg== - dependencies: - "@ckb-lumos/base" "0.21.1" - "@ckb-lumos/bi" "0.21.1" - "@ckb-lumos/codec" "0.21.1" - "@ckb-lumos/config-manager" "0.21.1" - "@ckb-lumos/helpers" "0.21.1" - "@ckb-lumos/rpc" "0.21.1" - "@ckb-lumos/toolkit" "0.21.1" +"@ckb-lumos/codec@0.23.0", "@ckb-lumos/codec@^0.21.0-next.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/codec/-/codec-0.23.0.tgz#abc8c2da95931859d3347608af4b461d27c5daff" + integrity sha512-FwYooXnsFDjlHHnlFnCTB1UbBzV72I0VjkRpeauFk5nQ4+/75xl28ywK3J14M+0aHTnYU9msXUTRDAGqC0CaNQ== + dependencies: + "@ckb-lumos/bi" "0.23.0" + +"@ckb-lumos/common-scripts@0.23.0", "@ckb-lumos/common-scripts@^0.21.0-next.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/common-scripts/-/common-scripts-0.23.0.tgz#ccb04214ca7186829036ddcbb0dc1b5326127a90" + integrity sha512-Dwic0Al94afdGNu+TGAMmZiU5OVF/zvXbzhCvNmkFS25t8BxPdFjGEc0MlWBI4ZSEoGRrC0O+BOxjzfl5VxSYg== + dependencies: + "@ckb-lumos/base" "0.23.0" + "@ckb-lumos/bi" "0.23.0" + "@ckb-lumos/codec" "0.23.0" + "@ckb-lumos/config-manager" "0.23.0" + "@ckb-lumos/helpers" "0.23.0" + "@ckb-lumos/rpc" "0.23.0" + "@ckb-lumos/toolkit" "0.23.0" + bech32 "^2.0.0" + bs58 "^5.0.0" immutable "^4.3.0" -"@ckb-lumos/config-manager@0.21.1", "@ckb-lumos/config-manager@^0.21.0-next.0": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/config-manager/-/config-manager-0.21.1.tgz#857050ebf2ca38096d8fae26b6a8927164798ca3" - integrity sha512-BmrNqYyaksdCKHWagyC8+R8GUxhIO+sOM5S925jlkpjju2sUbH0Id2/zmdb7I9KxdKnbx3WsR+hqy7/bYqw1lA== +"@ckb-lumos/config-manager@0.23.0", "@ckb-lumos/config-manager@^0.21.0-next.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/config-manager/-/config-manager-0.23.0.tgz#93a607f7857c9a24fae86735e29f1ca40ee34fb5" + integrity sha512-MvNyzGIJTmIpEf5WJB3TkE4icZyZ2HZhFIfJB2SXDRAC84E02jxENPelCnqRbM1rlFHnxjh/5a/oCi5LcXefag== dependencies: - "@ckb-lumos/base" "0.21.1" - "@ckb-lumos/bi" "0.21.1" - "@ckb-lumos/codec" "0.21.1" + "@ckb-lumos/base" "0.23.0" + "@ckb-lumos/bi" "0.23.0" + "@ckb-lumos/codec" "0.23.0" + "@ckb-lumos/rpc" "0.23.0" "@types/deep-freeze-strict" "^1.1.0" deep-freeze-strict "^1.1.1" -"@ckb-lumos/hd@0.21.1": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/hd/-/hd-0.21.1.tgz#406026ac2b570f72b4407149cb941d09bb8a0ab6" - integrity sha512-BnfpJf/sx/dJzL5BrOxPeKbKgv2x74KWd0xwjw1/gBQ2IMhu0S1mLwFsOT3Zu2nuhpQYvZGvr0cd3vD/SoMDow== +"@ckb-lumos/hd@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/hd/-/hd-0.23.0.tgz#97ddf6e291bdb44b7b8d61bcf437c3a1b17d0182" + integrity sha512-z7EsR/GeX54hq4ukqwW3nrqLCsYrTWIFAjZLR1Ao8xycqQp0IBjCWZLLjRrZY6krbUQpVOoiKo3NBLpPW36LXg== dependencies: - "@ckb-lumos/base" "0.21.1" - "@ckb-lumos/bi" "0.21.1" + "@ckb-lumos/base" "0.23.0" + "@ckb-lumos/bi" "0.23.0" bn.js "^5.1.3" elliptic "^6.5.4" scrypt-js "^3.0.1" sha3 "^2.1.3" uuid "^8.3.0" -"@ckb-lumos/helpers@0.21.1": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/helpers/-/helpers-0.21.1.tgz#fffd455071f51556b2cd2539a255b3759893da08" - integrity sha512-jFN6DtWzwVNEY4kmnzczRaQqtyRJQwzAEuHRUQ0LqTiIGM+SlfgjH/l/InAG4cIhDOurMudnUJ4ex68wmbkhVw== - dependencies: - "@ckb-lumos/base" "0.21.1" - "@ckb-lumos/bi" "0.21.1" - "@ckb-lumos/codec" "0.21.1" - "@ckb-lumos/config-manager" "0.21.1" - "@ckb-lumos/toolkit" "0.21.1" +"@ckb-lumos/helpers@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/helpers/-/helpers-0.23.0.tgz#095a6d4752d756287cfbee0360c614d27a5f71f3" + integrity sha512-yfD28vSn1BBk8BA+/ivL7pF3rMsx4OPQ+UUJjsQiR1zGdkNR3zhJOecgICeddJGYDTBBDVgwHcuyoekLxQzmGg== + dependencies: + "@ckb-lumos/base" "0.23.0" + "@ckb-lumos/bi" "0.23.0" + "@ckb-lumos/codec" "0.23.0" + "@ckb-lumos/config-manager" "0.23.0" + "@ckb-lumos/toolkit" "0.23.0" bech32 "^2.0.0" immutable "^4.3.0" -"@ckb-lumos/lumos@^0.21.0-next.0": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/lumos/-/lumos-0.21.1.tgz#ff5a9a10859b305530026668bd14cdc12e5e7532" - integrity sha512-a5n8xaIUvmaPsw2fBki8Jamy6/6uQnLWDZM9SQX29cZ1YVoAk/slnBmEbCIGXmxDhcuAlLkTeJaiLDKEGrZ6pg== - dependencies: - "@ckb-lumos/base" "0.21.1" - "@ckb-lumos/bi" "0.21.1" - "@ckb-lumos/ckb-indexer" "0.21.1" - "@ckb-lumos/common-scripts" "0.21.1" - "@ckb-lumos/config-manager" "0.21.1" - "@ckb-lumos/hd" "0.21.1" - "@ckb-lumos/helpers" "0.21.1" - "@ckb-lumos/rpc" "0.21.1" - "@ckb-lumos/toolkit" "0.21.1" - -"@ckb-lumos/rpc@0.21.1", "@ckb-lumos/rpc@^0.21.0-next.0": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/rpc/-/rpc-0.21.1.tgz#f6a6b3ed6d76adfb84c148e4b4acadb7fbaa7d7a" - integrity sha512-gZWXYCyQ98s84Pb+buOiYL3HOIxQPLHQdCyo96GFerNw9lB1XsbaGWzfHPYpZvOQqYtnJ1GUfTkQkADrQ7hmew== - dependencies: - "@ckb-lumos/base" "0.21.1" - "@ckb-lumos/bi" "0.21.1" +"@ckb-lumos/light-client@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/light-client/-/light-client-0.23.0.tgz#093f28d4183971f1212241271e7b23bad9909689" + integrity sha512-O+dbfubDjl0iODiQ8Q+RVJLfuXYNCN6c0am8xEv4vvazLwfw1y/vn6fG/pFu9Mc1GahZ58y9o6fkUgs8ujH3Mg== + dependencies: + "@ckb-lumos/base" "0.23.0" + "@ckb-lumos/ckb-indexer" "0.23.0" + "@ckb-lumos/rpc" "0.23.0" + cross-fetch "^3.1.5" + events "^3.3.0" + +"@ckb-lumos/lumos@0.23.0", "@ckb-lumos/lumos@^0.21.0-next.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/lumos/-/lumos-0.23.0.tgz#638b4780a990f42059f86c3e4e33cbd7e6557782" + integrity sha512-ocsmzgTgevVwyQeQkUZrg4PLJCfX48D5MEBNYTMoGh5b1g0f1iEBHcAgw4WBGOKgMJQmGRmWB5P6tPDZ3OZBwQ== + dependencies: + "@ckb-lumos/base" "0.23.0" + "@ckb-lumos/bi" "0.23.0" + "@ckb-lumos/ckb-indexer" "0.23.0" + "@ckb-lumos/codec" "0.23.0" + "@ckb-lumos/common-scripts" "0.23.0" + "@ckb-lumos/config-manager" "0.23.0" + "@ckb-lumos/hd" "0.23.0" + "@ckb-lumos/helpers" "0.23.0" + "@ckb-lumos/light-client" "0.23.0" + "@ckb-lumos/rpc" "0.23.0" + "@ckb-lumos/toolkit" "0.23.0" + "@ckb-lumos/transaction-manager" "0.23.0" + +"@ckb-lumos/rpc@0.23.0", "@ckb-lumos/rpc@^0.21.0-next.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/rpc/-/rpc-0.23.0.tgz#e17bd281e62e17957db80459e6be25d0c64bbb59" + integrity sha512-NEY1Wb2cNMYdHwcZYtd8XZ3CP6WGPd25hcsudoDAFlAt9vjHsPlNiwSS7tcZCZfg1XiJy3taViVgG8pFemgpbA== + dependencies: + "@ckb-lumos/base" "0.23.0" + "@ckb-lumos/bi" "0.23.0" abort-controller "^3.0.0" cross-fetch "^3.1.5" -"@ckb-lumos/toolkit@0.21.1": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@ckb-lumos/toolkit/-/toolkit-0.21.1.tgz#bcf4bf05615375087e3dd02fb087b797a8c67f37" - integrity sha512-awrFos7uQXEVGbqKSv/8Fc8B8XAfxdYoyYak4zFyAAmxxA0NiTTvk9V8TsOA7zVXpxct4Jal22+qUe+4Jg8T/g== +"@ckb-lumos/toolkit@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/toolkit/-/toolkit-0.23.0.tgz#4f5d25ea4292bd77dfc191506984ffc2c38078f7" + integrity sha512-7LTsUFfoNCBWJLgh+V/QFnemjGw+y4mmLeQvubwYuJqIPIhIpwKUuKRzkvVG8snA8xVQSfjSSQOs5m3mKp66Kg== dependencies: - "@ckb-lumos/bi" "0.21.1" + "@ckb-lumos/bi" "0.23.0" + +"@ckb-lumos/transaction-manager@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/transaction-manager/-/transaction-manager-0.23.0.tgz#2e90d7f0fe5613fd594a7f0b7a2a48c3336b98dd" + integrity sha512-sfwt2g8JlYxr5jRx5r/UZNffTpkwn3sh4dD2THzKmX0S1CsSgww2D1ZD7yruWwSu05ZLKlDPFVKyJ50tNc3LuQ== + dependencies: + "@ckb-lumos/base" "0.23.0" + "@ckb-lumos/ckb-indexer" "0.23.0" + "@ckb-lumos/codec" "0.23.0" + "@ckb-lumos/rpc" "0.23.0" + "@ckb-lumos/toolkit" "0.23.0" + immutable "^4.3.0" "@cnakazawa/watch@^1.0.3": version "1.0.4" @@ -2254,6 +2283,13 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@csstools/normalize.css@*": version "12.0.0" resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-12.0.0.tgz#a9583a75c3f150667771f30b60d9f059473e62c4" @@ -3157,6 +3193,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" @@ -3180,6 +3221,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.18" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" @@ -5238,6 +5287,26 @@ resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + "@tufjs/canonical-json@2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz#a52f61a3d7374833fca945b2549bc30a2dd40d0a" @@ -6599,11 +6668,23 @@ acorn-walk@^7.1.1, acorn-walk@^7.2.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== +acorn-walk@^8.1.1: + version "8.3.3" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" + integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== + dependencies: + acorn "^8.11.0" + acorn@^7.1.1, acorn@^7.4.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.11.0, acorn@^8.4.1: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + acorn@^8.11.2, acorn@^8.9.0: version "8.11.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" @@ -6896,6 +6977,11 @@ are-we-there-yet@^3.0.0: delegates "^1.0.0" readable-stream "^3.6.0" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + arg@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" @@ -7496,6 +7582,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base-x@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" + integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== + base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -7781,6 +7872,13 @@ bs-logger@0.x: dependencies: fast-json-stable-stringify "2.x" +bs58@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" + integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== + dependencies: + base-x "^4.0.0" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -8804,6 +8902,11 @@ crc@^3.8.0: dependencies: buffer "^5.1.0" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-env@7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" @@ -9416,6 +9519,11 @@ diff-sequences@^29.6.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-compare@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-3.3.0.tgz#2c749f973b5c4b5d087f11edaae730db31788416" @@ -14440,7 +14548,7 @@ make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: dependencies: semver "^6.0.0" -make-error@1.x: +make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -18854,16 +18962,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18981,14 +19080,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -19602,6 +19694,25 @@ ts-jest@29.2.0: semver "^7.5.3" yargs-parser "^21.0.1" +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + ts-pnp@^1.1.6: version "1.2.0" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" @@ -20163,6 +20274,11 @@ uuid@^9.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-to-istanbul@^8.1.0: version "8.1.1" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" @@ -20769,16 +20885,7 @@ workbox-window@6.6.1: "@types/trusted-types" "^2.0.2" workbox-core "6.6.1" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20982,6 +21089,11 @@ yauzl@^2.10.0: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"