diff --git a/CHANGELOG.md b/CHANGELOG.md index b1fb7bb9a8..02eac30843 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,15 @@ -# 0.100.0 (2021-09-24) +# 0.100.1 (2021-09-29) + +[CKB v0.100.0](https://github.com/nervosnetwork/ckb/releases/tag/v0.100.0) was released on Sep. 22nd, 2021. This version of CKB node is now bundled and preconfigured in Neuron. + +**Please note that in order to adapt to the latest version of CKB, Neuron will resynchronize the data on the chain, and the whole synchronization may take a long time.** + +### Hotfix +* Rename ckb-indexer data folder from `ckb-indexer` to `ckb_indexer_data`. +* [GHSA-33f9-j839-rf8h](https://github.com/advisories/GHSA-33f9-j839-rf8h): Upgrade immer to 9.0.6. + + +# 0.100.0 (2021-09-25) [CKB v0.100.0](https://github.com/nervosnetwork/ckb/releases/tag/v0.100.0) was released on Sep. 22nd, 2021. This version of CKB node is now bundled and preconfigured in Neuron. diff --git a/lerna.json b/lerna.json index 6951042f12..6ce79cdb26 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "0.100.0", + "version": "0.100.1", "npmClient": "yarn", "useWorkspaces": true } diff --git a/package.json b/package.json index 1440c2a60d..9f1330f759 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "neuron", "productName": "Neuron", "description": "CKB Neuron Wallet", - "version": "0.100.0", + "version": "0.100.1", "private": true, "author": { "name": "Nervos Core Dev", diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json index 9c5227926d..21a0a00f2e 100644 --- a/packages/neuron-ui/package.json +++ b/packages/neuron-ui/package.json @@ -1,6 +1,6 @@ { "name": "neuron-ui", - "version": "0.100.0", + "version": "0.100.1", "private": true, "author": { "name": "Nervos Core Dev", @@ -50,7 +50,7 @@ "canvg": "2.0.0", "grommet-icons": "4.4.0", "i18next": "17.0.13", - "immer": "8.0.1", + "immer": "9.0.6", "jsqr": "1.2.0", "office-ui-fabric-react": "7.31.1", "qr.js": "0.0.0", diff --git a/packages/neuron-ui/src/states/init/app.ts b/packages/neuron-ui/src/states/init/app.ts index 16139cece4..35a433466a 100644 --- a/packages/neuron-ui/src/states/init/app.ts +++ b/packages/neuron-ui/src/states/init/app.ts @@ -10,7 +10,7 @@ const initNotifications: Array = [ }, ] -export const appState: Readonly = { +export const appState: State.App = { tipBlockNumber: '', tipBlockHash: '', tipBlockTimestamp: 0, diff --git a/packages/neuron-ui/src/states/init/chain.ts b/packages/neuron-ui/src/states/init/chain.ts index 6e21876a22..1ae00ee80c 100644 --- a/packages/neuron-ui/src/states/init/chain.ts +++ b/packages/neuron-ui/src/states/init/chain.ts @@ -1,7 +1,7 @@ import { currentNetworkID } from 'services/localCache' import { ConnectionStatus } from 'utils' -export const transactionState: Readonly = { +export const transactionState: State.DetailedTransaction = { value: '', hash: '', type: 'receive', diff --git a/packages/neuron-ui/src/states/init/nervosDAO.ts b/packages/neuron-ui/src/states/init/nervosDAO.ts index 19620303c2..da0414c1e3 100644 --- a/packages/neuron-ui/src/states/init/nervosDAO.ts +++ b/packages/neuron-ui/src/states/init/nervosDAO.ts @@ -1,4 +1,4 @@ -export const emptyNervosDaoData: Readonly = { +export const emptyNervosDaoData: State.NervosDAO = { records: [], } diff --git a/packages/neuron-ui/src/states/init/settings.ts b/packages/neuron-ui/src/states/init/settings.ts index dc9ff9914b..87049df80e 100644 --- a/packages/neuron-ui/src/states/init/settings.ts +++ b/packages/neuron-ui/src/states/init/settings.ts @@ -1,6 +1,6 @@ import { wallets, networks } from 'services/localCache' -export const settingsState: Readonly = { +export const settingsState: State.Settings = { general: {}, networks: networks.load(), wallets: wallets.load(), diff --git a/packages/neuron-ui/src/states/init/updater.ts b/packages/neuron-ui/src/states/init/updater.ts index b960f9d951..487b8769c6 100644 --- a/packages/neuron-ui/src/states/init/updater.ts +++ b/packages/neuron-ui/src/states/init/updater.ts @@ -1,4 +1,4 @@ -const appUpdaterState: Readonly = { +const appUpdaterState: State.AppUpdater = { checking: false, downloadProgress: -1, version: '', diff --git a/packages/neuron-ui/src/states/init/wallet.ts b/packages/neuron-ui/src/states/init/wallet.ts index ea1db11326..d9bbbff977 100644 --- a/packages/neuron-ui/src/states/init/wallet.ts +++ b/packages/neuron-ui/src/states/init/wallet.ts @@ -1,6 +1,6 @@ import { addresses, currentWallet } from 'services/localCache' -export const emptyWallet: Readonly = { +export const emptyWallet: State.Wallet = { name: '', id: '', balance: '0', @@ -9,7 +9,7 @@ export const emptyWallet: Readonly = { const wallet = currentWallet.load() -export const walletState: Readonly = { +export const walletState: State.Wallet = { name: wallet.name || '', id: wallet.id || '', balance: '0', diff --git a/packages/neuron-ui/src/types/App/index.d.ts b/packages/neuron-ui/src/types/App/index.d.ts index 522f806458..52902e00ae 100644 --- a/packages/neuron-ui/src/types/App/index.d.ts +++ b/packages/neuron-ui/src/types/App/index.d.ts @@ -1,87 +1,76 @@ declare namespace State { interface Transaction { - readonly type: 'send' | 'receive' - readonly createdAt: string - readonly updatedAt: string - readonly timestamp: string - readonly value: string - readonly hash: string - readonly description: string - readonly blockNumber: string - readonly status: 'pending' | 'success' | 'failed' - readonly nervosDao: boolean - readonly sudtInfo?: Readonly<{ - sUDT: { - tokenID: string - tokenName: string - symbol: string - decimal: string - } + type: 'send' | 'receive' + createdAt: string + updatedAt: string + timestamp: string + value: string + hash: string + description: string + blockNumber: string + status: 'pending' | 'success' | 'failed' + nervosDao: boolean + sudtInfo?: { + sUDT: Record<'tokenID' | 'tokenName' | 'symbol' | 'decimal', string> amount: string - }> - readonly nftInfo?: { + } + nftInfo?: { type: 'send' | 'receive' data: string } } interface DetailedInput { - readonly capacity: string | null - readonly lockHash: string | null - readonly previousOutput: { - readonly blockHash: string | null - readonly cell: Readonly<{ - txHash: string - index: string - } | null> + capacity: string | null + lockHash: string | null + previousOutput: { + blockHash: string | null + cell: Record<'txHash' | 'index', string> | null } - readonly lock: Readonly + lock: CKBComponents.Script | null } interface DetailedOutput { - readonly capacity: string - readonly lock: Readonly - readonly lockHash: string - readonly outPoint: Readonly<{ - index: string - txHash: string - }> + capacity: string + lock: CKBComponents.Script + lockHash: string + outPoint: CKBComponents.OutPoint } interface DetailedTransaction extends Transaction { - readonly blockHash: string - readonly blockNumber: string - readonly deps: any[] - readonly inputs: Readonly - readonly inputsCount: string - readonly outputs: Readonly - readonly outputsCount: string - readonly witnesses: string[] + blockHash: string + blockNumber: string + deps: any[] + inputs: DetailedInput[] + inputsCount: string + outputs: DetailedOutput[] + outputsCount: string + witnesses: string[] } interface Output { - readonly address: string | undefined - readonly amount: string | undefined - readonly unit: any - readonly date?: string + address: string | undefined + amount: string | undefined + unit: any + date?: string } type MessageType = 'success' | 'warning' | 'alert' - interface Message> { - readonly type: MessageType - readonly timestamp: number - readonly code?: Code - readonly content?: string - readonly meta?: Meta + interface Message>> { + type: MessageType + timestamp: number + code?: Code + content?: string + meta?: Meta } interface Send { - readonly txID: string - readonly outputs: Readonly - readonly price: string - readonly description: string - readonly generatedTx: any + txID: string + outputs: Output[] + price: string + description: string + generatedTx: any } interface Popup { - readonly timestamp: number - readonly text: string + timestamp: number + text: string } interface PasswordRequest { @@ -100,56 +89,50 @@ declare namespace State { | 'migrate-acp' | 'send-nft' | null - readonly walletID: string + walletID: string } - type AlertDialog = Readonly<{ title: string; message: string }> | null + type AlertDialog = Record<'title' | 'message', string> | null type GlobalDialogType = 'unlock-success' | 'rebuild-sync' | null interface App { - readonly tipBlockNumber: string - readonly tipBlockHash: string - readonly tipBlockTimestamp: number - readonly chain: string - readonly difficulty: bigint - readonly epoch: string - readonly send: Readonly - readonly passwordRequest: PasswordRequest + tipBlockNumber: string + tipBlockHash: string + tipBlockTimestamp: number + chain: string + difficulty: bigint + epoch: string + send: Send + passwordRequest: PasswordRequest // TODO: is the field used in the app? - readonly messages: { - readonly [index: string]: Message | null - } - readonly popups: Readonly - readonly notifications: Readonly - readonly globalDialog: GlobalDialogType - readonly alertDialog: AlertDialog - readonly loadings: Readonly<{ - sending: boolean - addressList: boolean - transactionList: boolean - }> - readonly showTopAlert: boolean - readonly showAllNotifications: boolean - readonly isAllowedToFetchList: boolean - readonly loadedTransaction: any + messages: Record + popups: Popup[] + notifications: Message[] + globalDialog: GlobalDialogType + alertDialog: AlertDialog + loadings: Record<'sending' | 'addressList' | 'transactionList', boolean> + showTopAlert: boolean + showAllNotifications: boolean + isAllowedToFetchList: boolean + loadedTransaction: any } interface NetworkProperty { - readonly name: string - readonly remote: string - readonly chain: 'ckb' | 'ckb_testnet' | 'ckb_dev' | string - readonly type: 0 | 1 + name: string + remote: string + chain: 'ckb' | 'ckb_testnet' | 'ckb_dev' | string + type: 0 | 1 } interface Network extends NetworkProperty { - readonly id: NetworkID + id: NetworkID } interface WalletIdentity { - readonly id: string - readonly name: string - readonly device?: DeviceInfo - readonly isHD?: boolean + id: string + name: string + device?: DeviceInfo + isHD?: boolean } enum Manufacturer { @@ -171,18 +154,18 @@ declare namespace State { } interface Address { - readonly address: string - readonly identifier: string - readonly description: string - readonly type: 0 | 1 // 0 for receiving, 1 for change - readonly txCount: number - readonly balance: string - readonly index: number + address: string + identifier: string + description: string + type: 0 | 1 // 0 for receiving, 1 for change + txCount: number + balance: string + index: number } interface Wallet extends WalletIdentity { - readonly balance: string - readonly addresses: Readonly + balance: string + addresses: Address[] } type ConnectionStatus = 'online' | 'offline' | 'connecting' @@ -195,86 +178,65 @@ declare namespace State { }> interface Chain { - readonly networkID: string - readonly connectionStatus: ConnectionStatus - readonly syncState: SyncState - readonly transactions: Readonly<{ + networkID: string + connectionStatus: ConnectionStatus + syncState: SyncState + transactions: { pageNo: number pageSize: number totalCount: number - items: Readonly + items: Transaction[] keywords: string - }> + } } interface Settings { - readonly general: {} - readonly networks: Readonly - readonly wallets: Readonly + general: {} + networks: Network[] + wallets: WalletIdentity[] } + type DaoActionInfo = Record<'txHash' | 'timestamp', string> + interface NervosDAORecord { - readonly blockNumber: string // '0', the block of current status. Namely it's the deposit block number if the depositOutPoint is undefined, or the withdrawn block number if the depositOutPoint - readonly blockHash: string - readonly capacity: string - readonly lock: Readonly<{ - codeHash: string - hashType: 'type' | 'data' - args: string - }> - readonly type: Readonly<{ - codeHash: string - hashType: 'type' | 'data' - args: string - }> - readonly lockHash: string - readonly typeHash: string | null - readonly outPoint: Readonly<{ - txHash: string - index: string // '0' - }> - readonly status: 'live' | 'dead' | 'sent' | 'pending' | 'failed' // 1. status === deat => record is completed; 2. status === sent => depositing or withdrawing; 3. status === live => record is deposited or locked; 4. status === pending => unlocking - readonly daoData: string // locktime epoch in le - readonly data: string - readonly timestamp: string - readonly depositOutPoint?: Readonly<{ - txHash: string - index: string - }> - readonly depositTimestamp?: string - readonly multiSignBlake160: string | null - readonly depositInfo?: { - txHash: string - timestamp: string - } - readonly withdrawInfo?: { - txHash: string - timestamp: string - } - readonly unlockInfo?: { - txHash: string - timestamp: string - } + blockNumber: string // '0', the block of current status. Namely it's the deposit block number if the depositOutPoint is undefined, or the withdrawn block number if the depositOutPoint + blockHash: string + capacity: string + lock: CKBComponents.Script + type: CKBComponents.Script + lockHash: string + typeHash: string | null + outPoint: CKBComponents.OutPoint + status: 'live' | 'dead' | 'sent' | 'pending' | 'failed' // 1. status === deat => record is completed; 2. status === sent => depositing or withdrawing; 3. status === live => record is deposited or locked; 4. status === pending => unlocking + daoData: string // locktime epoch in le + data: string + timestamp: string + depositOutPoint?: CKBComponents.OutPoint + depositTimestamp?: string + multiSignBlake160: string | null + depositInfo?: DaoActionInfo + withdrawInfo?: DaoActionInfo + unlockInfo?: DaoActionInfo } interface NervosDAO { - readonly records: Readonly + records: NervosDAORecord[] } interface AppUpdater { - readonly checking: boolean - readonly downloadProgress: number - readonly version: string - readonly releaseNotes: string + checking: boolean + downloadProgress: number + version: string + releaseNotes: string } interface AppWithNeuronWallet { - readonly app: App - readonly chain: Chain - readonly settings: Settings - readonly wallet: Wallet - readonly nervosDAO: NervosDAO - readonly updater: AppUpdater - readonly experimental: { tx: any; assetAccount?: any } | null + app: App + chain: Chain + settings: Settings + wallet: Wallet + nervosDAO: NervosDAO + updater: AppUpdater + experimental: { tx: any; assetAccount?: any } | null } } diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json index 9fb2097029..9cbf65b31c 100644 --- a/packages/neuron-wallet/package.json +++ b/packages/neuron-wallet/package.json @@ -3,7 +3,7 @@ "productName": "Neuron", "description": "CKB Neuron Wallet", "homepage": "https://www.nervos.org/", - "version": "0.100.0", + "version": "0.100.1", "private": true, "author": { "name": "Nervos Core Dev", @@ -86,7 +86,7 @@ "electron-notarize": "0.2.1", "jest-when": "2.7.2", "lint-staged": "9.2.5", - "neuron-ui": "0.100.0", + "neuron-ui": "0.100.1", "rimraf": "3.0.0", "ttypescript": "1.5.10" } diff --git a/packages/neuron-wallet/src/controllers/app/index.ts b/packages/neuron-wallet/src/controllers/app/index.ts index 57f4d97938..c989139ea5 100644 --- a/packages/neuron-wallet/src/controllers/app/index.ts +++ b/packages/neuron-wallet/src/controllers/app/index.ts @@ -30,19 +30,19 @@ export default class AppController { public start = async () => { registerListeners() + if (!env.isTestMode) { + await this.mercuryController.migrate() + } await this.apiController.mount() this.syncApiController = SyncApiController.getInstance() this.syncApiController.mount() await this.openWindow() - if (!env.isTestMode) { - await this.mercuryController.migrate() - } } - public end = () => { + public end = async () => { if (!env.isTestMode) { - new NodeController().stopNode() - IndexerService.getInstance().stop() + await new NodeController().stopNode() + await IndexerService.getInstance().stop() } } diff --git a/packages/neuron-wallet/src/controllers/mercury.ts b/packages/neuron-wallet/src/controllers/mercury.ts index 2fdfa26411..e55e5c5234 100644 --- a/packages/neuron-wallet/src/controllers/mercury.ts +++ b/packages/neuron-wallet/src/controllers/mercury.ts @@ -5,8 +5,6 @@ import env from 'env' import { dialog } from 'electron' import { t } from 'i18next' import { deleteFolderRecursive } from 'block-sync-renderer/sync/indexer-folder-manager' -import NodeController from './node' -import SyncController from './sync' const { app } = env @@ -17,16 +15,19 @@ export default class MerucuryController { const lumosDataPath = app.isPackaged ? path.resolve(app.getPath('userData'), lumosIndexerDBFolder) : path.resolve(app.getPath('userData'), './dev', lumosIndexerDBFolder) + const ckbIndexerDBFolder = './ckb-indexer' + const ckbIndexerDataPath = app.isPackaged ? + path.resolve(app.getPath('userData'), ckbIndexerDBFolder) : + path.resolve(app.getPath('userData'), './dev', ckbIndexerDBFolder) // User has old synchronized data if (fs.existsSync(ckbPath) && fs.existsSync(lumosDataPath)) { - const node = new NodeController() - await node.stopNode() - await this.openMigrateDialog('hard-fork') deleteFolderRecursive(lumosDataPath) deleteFolderRecursive(ckbPath) - await node.startNode() - const syncController = new SyncController() - await syncController.clearCache(true) + await this.openMigrateDialog('hard-fork') + } + if (fs.existsSync(ckbIndexerDataPath)) { + deleteFolderRecursive(ckbIndexerDataPath) + await this.openMigrateDialog('hard-fork') } // TODO: mercury migration when mercury 1.0 is ready } diff --git a/packages/neuron-wallet/src/main.ts b/packages/neuron-wallet/src/main.ts index 1469d3b34e..2efa325469 100644 --- a/packages/neuron-wallet/src/main.ts +++ b/packages/neuron-wallet/src/main.ts @@ -15,7 +15,7 @@ if (singleInstanceLock) { }) app.on('before-quit', async () => { - appController.end() + await appController.end() }) app.on('activate', appController.openWindow) diff --git a/packages/neuron-wallet/src/services/indexer.ts b/packages/neuron-wallet/src/services/indexer.ts index b3435cc9bf..2f6c6cd4d4 100644 --- a/packages/neuron-wallet/src/services/indexer.ts +++ b/packages/neuron-wallet/src/services/indexer.ts @@ -27,6 +27,7 @@ const { app } = env export default class IndexerService { private indexer: ChildProcess | null = null private static instance: IndexerService + private static indexerDataFolder = './ckb_indexer_data' public static PORT = '8118' public static get LISTEN_URI() { return `http://localhost:${IndexerService.PORT}` @@ -54,8 +55,8 @@ export default class IndexerService { getDataPath = (network: Network): string => { return app.isPackaged ? - path.resolve(app.getPath('userData'), './ckb-indexer', './data', `./${network.genesisHash}`) : - path.resolve(app.getPath('userData'), './dev', './ckb-indexer', './data', `./${network.genesisHash}`) + path.resolve(app.getPath('userData'), IndexerService.indexerDataFolder, './data', `./${network.genesisHash}`) : + path.resolve(app.getPath('userData'), './dev', IndexerService.indexerDataFolder, './data', `./${network.genesisHash}`) } async stop() { diff --git a/yarn.lock b/yarn.lock index c14a4c3994..ac0f2ff80b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10870,10 +10870,10 @@ immer@1.10.0: resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== -immer@8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656" - integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA== +immer@9.0.6: + version "9.0.6" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.6.tgz#7a96bf2674d06c8143e327cbf73539388ddf1a73" + integrity sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ== immutable@^4.0.0-rc.12: version "4.0.0-rc.12"