diff --git a/.eslintrc b/.eslintrc
index a0b0cbab3b..603b09bc9a 100755
--- a/.eslintrc
+++ b/.eslintrc
@@ -67,10 +67,8 @@
"react/no-array-index-key": "warn",
"react/no-unused-prop-types": "warn",
"react/prefer-stateless-function": 0,
- "react/prop-types": "warn",
+ "react/prop-types": 0,
"react/require-default-props": 0,
- "react/sort-comp": 0,
- "react/state-in-constructor": 0,
"react/jsx-first-prop-new-line": [1, "multiline-multiprop"],
"@typescript-eslint/ban-ts-comment": 1,
"@typescript-eslint/no-empty-function": 1,
@@ -78,22 +76,15 @@
"import/no-unresolved": 1,
"@typescript-eslint/no-var-requires": 1,
"camelcase": 1,
- "no-empty": 1,
+ "no-empty": 1,
"@typescript-eslint/no-explicit-any": 1,
"no-shadow": 1,
"react/no-did-update-set-state": 1,
- "react/static-property-placement": 0,
- "react/jsx-one-expression-per-line": 0,
- "react/jsx-curly-newline": 0,
- "react/jsx-indent": 0
+ "react/sort-comp": 0,
+ "react/state-in-constructor": 0,
+ "react/static-property-placement": 0
},
- "plugins": [
- "@typescript-eslint",
- "import",
- "promise",
- "react",
- "jest"
- ],
+ "plugins": ["@typescript-eslint", "import", "promise", "react", "jest"],
"globals": {
"API": true,
"API_VERSION": true,
@@ -103,10 +94,19 @@
"Process": true // TODO: remove after fix
},
"settings": {
- "import/resolver": {
+ "import/resolver": {
"node": {
- "extensions": [".js", ".jsx",".ts", ".tsx"]
+ "extensions": [".js", ".jsx", ".ts", ".tsx"]
+ }
+ }
+ },
+ "overrides": [
+ {
+ "files": "**/*.ts",
+ "rules": {
+ "no-useless-constructor": "off",
+ "@typescript-eslint/no-useless-constructor": "error"
}
}
- }
+ ]
}
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index de92566601..a91508a26b 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -20,7 +20,7 @@ or animated GIFs of important UI changes in both English and Japanese.
Do not use shadow or any effects. On macOS this can be accomplished the following way:
1. Use the Command+Shift+4 keyboard shortcut.
2. Press the Spacebar.
-3. Hold the Option button and click the window you want to capture.
+3. Hold the Option button and click the window you want to capture.
-->
## Testing Checklist
@@ -29,7 +29,6 @@ Do not use shadow or any effects. On macOS this can be accomplished the followin
Open a thread on #daedalus-qa on Slack, mention `@daedalusqa` and `@daedalusteam`, link the thread below
-->
-
- [Slack QA thread](https://input-output-rnd.slack.com/messages/GGKFXSKC6)
- [ ] Test
@@ -38,15 +37,17 @@ Open a thread on #daedalus-qa on Slack, mention `@daedalusqa` and `@daedalusteam
## Review Checklist
### Basics
-- [ ] PR assigned to the PR author(s)
+
+- [ ] PR assigned to the PR author(s)
- [ ] `input-output-hk/daedalus-dev` and `input-output-hk/daedalus-qa` assigned as PR reviewers
- [ ] If there are UI changes, Alexander Rukin assigned as an additional reviewer
+- [ ] All visual regression testing has been reviewed (assign `run Chromatic` label to PR to trigger the run)
- [ ] PR has appropriate labels (`release-vNext`, `feature`/`bug`/`chore`, `WIP`)
- [ ] PR link is added to a Jira ticket, ticket moved to In Review
- [ ] PR is updated to the most recent version of the target branch (and there are no conflicts)
- [ ] PR has a good description that summarizes all changes
- [ ] PR contains screenshots (in case of UI changes)
-- [ ] CHANGELOG entry has been added to the top of the appropriate section (*Features*, *Fixes*, *Chores*) and is linked to the correct PR on GitHub
+- [ ] CHANGELOG entry has been added to the top of the appropriate section (_Features_, _Fixes_, _Chores_) and is linked to the correct PR on GitHub
- [ ] There are no missing translations (running `yarn manage:translations` produces no changes)
- [ ] Text changes are proofread and approved (Jane Wild / Amy Reeve)
- [ ] Japanese text changes are proofread and approved (Junko Oda)
@@ -54,12 +55,14 @@ Open a thread on #daedalus-qa on Slack, mention `@daedalusqa` and `@daedalusteam
- [ ] In case of dependency changes `yarn.lock` file is updated
### Code Quality
+
- [ ] Important parts of the code are properly commented and documented
-- [ ] Code is properly typed with flow
+- [ ] Code is properly typed with typescript types
- [ ] React components are split-up enough to avoid unnecessary re-renderings
- [ ] Any code that only works in main process is neatly separated from components
### Testing
+
- [ ] New feature/change is covered by acceptance tests
- [ ] New feature/change is manually tested and approved by QA team
- [ ] All existing acceptance tests are still up-to-date
@@ -67,4 +70,5 @@ Open a thread on #daedalus-qa on Slack, mention `@daedalusqa` and `@daedalusteam
- [ ] All existing Daedalus Testing scenarios are still up-to-date
### After Review
+
- [ ] Update Slack QA thread by marking it with a green checkmark
diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml
index aeddc615d6..fc5a939007 100644
--- a/.github/workflows/chromatic.yml
+++ b/.github/workflows/chromatic.yml
@@ -1,8 +1,18 @@
name: 'Chromatic'
-on: push
+on:
+ pull_request:
+ types:
+ - labeled
+ push:
+ branches:
+ - develop
+
jobs:
chromatic-deployment:
+ if: contains(github.event.pull_request.labels.*.name, 'run Chromatic') || github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
+ env:
+ STORYBOOK_FREEZE_DATE: "true"
steps:
- uses: actions/checkout@v1
- name: Setup Node.js
@@ -18,6 +28,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
exitZeroOnChanges: true
+ buildScriptName: 'storybook:build:chromatic'
- name: Publish to Chromatic and auto accept changes
if: github.ref == 'refs/heads/develop'
uses: chromaui/action@v1
@@ -25,3 +36,4 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
autoAcceptChanges: true
+ buildScriptName: 'storybook:build:chromatic'
diff --git a/.github/workflows/run_tests_on_pr.yml b/.github/workflows/run_tests_on_pr.yml
deleted file mode 100644
index 3ce7787de8..0000000000
--- a/.github/workflows/run_tests_on_pr.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Run Tests for Pull Requests
-on:
- pull_request:
- branches:
- - develop
- - master
-jobs:
- tests:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout Repo
- uses: actions/checkout@v2
- - name: Setup Node.js
- uses: actions/setup-node@v2
- with:
- node-version: "12"
- - run: yarn install
- - run: yarn test:jest
diff --git a/.github/workflows/verify_pr.yml b/.github/workflows/verify_pr.yml
new file mode 100644
index 0000000000..1d8df8c6bd
--- /dev/null
+++ b/.github/workflows/verify_pr.yml
@@ -0,0 +1,26 @@
+name: Verify Pull Request
+on:
+ pull_request:
+jobs:
+ tests:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Repo
+ uses: actions/checkout@v2
+ - name: Setup Node.js
+ uses: actions/setup-node@v2
+ with:
+ node-version: "14"
+ - name: Restore node_modules from cache
+ uses: actions/cache@v2
+ with:
+ path: '**/node_modules'
+ key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
+ - name: Install dependencies
+ run: yarn --frozen-lockfile
+ - name: Run checks
+ run: yarn check:all
+ - name: Ensure there are no uncommited changes
+ run: git diff --exit-code || (echo "Did you forget to run 'yarn check:all' and commit changes?" && exit 1)
+ - name: Run tests
+ run: yarn test:jest --maxWorkers=3
diff --git a/.gitignore b/.gitignore
index b43c8bb717..d785b3b350 100755
--- a/.gitignore
+++ b/.gitignore
@@ -119,3 +119,6 @@ Debug
/cardano-cli
/cardano-wallet
.vscode
+
+# Typescript
+*.scss.d.ts
diff --git a/BESTPRACTICES.md b/BESTPRACTICES.md
index 538779a638..785cb2f16e 100644
--- a/BESTPRACTICES.md
+++ b/BESTPRACTICES.md
@@ -1108,7 +1108,7 @@ type Props = {
};
```
-For preventing syntax errors, leave a comma after the last key/value pair incase the type definition's properties are rearranged or expanded upon in the future.
+For preventing syntax errors, leave a comma after the last key/value pair in case the type definition's properties are rearranged or expanded upon in the future.
:white_check_mark: ***Do***
@@ -1204,7 +1204,7 @@ const Names = () => (
## Formatting Selectors
* Use class selectors instead of ID selectors.
-* Use camelCase or dashed-case instead of PascelCase or names_with_underscores.
+* Use camel case or dashed-case instead of pascal case or names_with_underscores.
* Give each selector its own line.
* Put a space before the opening brace `{` in rule declarations.
* Put closing braces `}` of rule declarations on a new line.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f49216e1df..8d0380703c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,110 @@
## vNext
+### Features
+
+- Added ASCII name to token header when metadata name is missing ([PR 2904](https://github.com/input-output-hk/daedalus/pull/2904))
+- Improved IPC by reducing the amount of messages from periodic events ([PR 2892](https://github.com/input-output-hk/daedalus/pull/2892))
+- Improved RTS flags splash screen message ([PR 2901](https://github.com/input-output-hk/daedalus/pull/2901))
+- Implemented error message when trying to leave wallet without enough ada to support tokens ([PR 2783](https://github.com/input-output-hk/daedalus/pull/2783))
+
+### Fixes
+
+- Fixed stake pool list view overlapping news feed ([PR 2917](https://github.com/input-output-hk/daedalus/pull/2917))
+- Restored opacity for search icon when focused ([PR 2909](https://github.com/input-output-hk/daedalus/pull/2909))
+- Fixed styling of the incentivized testnet rewards wallet dropdown ([PR 2907](https://github.com/input-output-hk/daedalus/pull/2907))
+- Fix warning sign displayed when recommend decimals is zero ([PR 2905](https://github.com/input-output-hk/daedalus/pull/2905))
+- Fixed discrete tooltip being clipped by loading overlay when stake pools are adjusted ([PR 2902](https://github.com/input-output-hk/daedalus/pull/2902))
+- Sets minimum transaction fee to ada input field when tokens are removed ([PR 2918](https://github.com/input-output-hk/daedalus/pull/2918))
+
+### Chores
+
+- Fixed spelling issues and typos ([PR 2915](https://github.com/input-output-hk/daedalus/pull/2915))
+- Removed SASS ts-lint ignore comments ([PR 2870](https://github.com/input-output-hk/daedalus/pull/2870))
+- Enabled debugging of the main process ([PR 2893](https://github.com/input-output-hk/daedalus/pull/2893))
+
+## 4.9.0
+
+### Features
+
+- Added display of current/unspent rewards ([PR 2803](https://github.com/input-output-hk/daedalus/pull/2803))
+- Improve the syncing screen by showing syncing progress split into three stages ([PR 2877](https://github.com/input-output-hk/daedalus/pull/2877))
+- Improved stake pool searchbar ([PR 2847](https://github.com/input-output-hk/daedalus/pull/2847))
+- Implemented catalyst dynamic content ([PR 2856](https://github.com/input-output-hk/daedalus/pull/2856))
+
+### Fixes
+
+- Fixed main container zIndex ([PR 2863](https://github.com/input-output-hk/daedalus/pull/2863))
+- Fixed ui overlap issues ([PR 2881](https://github.com/input-output-hk/daedalus/pull/2881))
+- Fixed the gap between Stake Pool View options ([PR 2899](https://github.com/input-output-hk/daedalus/pull/2899))
+
+### Chores
+
+- Fixed Daedalus menu in Storybook used for theme and language selection ([PR 2886](https://github.com/input-output-hk/daedalus/pull/2886))
+
+## 4.9.0-FC1
+
+### Features
+
+- Added table view for delegated stake pools list ([PR 2837](https://github.com/input-output-hk/daedalus/pull/2837))
+- Removed Discreet mode notification ([PR 2852](https://github.com/input-output-hk/daedalus/pull/2852))
+- Unified CPU info in diagnostics dialog ([PR 2818](https://github.com/input-output-hk/daedalus/pull/2818))
+- Implemented wallet sorting on sidebar menu ([PR 2775](https://github.com/input-output-hk/daedalus/pull/2775))
+- Implemented new token picker ([PR 2787](https://github.com/input-output-hk/daedalus/pull/2787))
+- Improved wallet send form ([PR 2791](https://github.com/input-output-hk/daedalus/pull/2791), [PR 2859](https://github.com/input-output-hk/daedalus/pull/2859))
+
+### Fixes
+
+- Fixed rewards CSV export issues ([PR 2885](https://github.com/input-output-hk/daedalus/pull/2885))
+- Fixed behaviour of wallet settings option of the app menu ([PR 2838](https://github.com/input-output-hk/daedalus/pull/2838))
+- Fixed styling of ITN rewards feature ([PR 2861](https://github.com/input-output-hk/daedalus/pull/2861))
+- Fixed available disk space takes a long time to show ([PR 2849](https://github.com/input-output-hk/daedalus/pull/2849))
+
+### Chores
+
+- Migrated codebase from javascript to typescript ([PR 2843](https://github.com/input-output-hk/daedalus/pull/2843))
+- Updated the list of team members ([PR 2805](https://github.com/input-output-hk/daedalus/pull/2805))
+
+## 4.8.0
+
+### Features
+
+- Added dynamic RTS flags setting ([PR 2758](https://github.com/input-output-hk/daedalus/pull/2758/files))
+- Improved UI/UX of RTS flags settings ([PR 2842](https://github.com/input-output-hk/daedalus/pull/2842), [PR 2846](https://github.com/input-output-hk/daedalus/pull/2846))
+- Updated messages about Cardano node sync on the initial screen ([PR 2827](https://github.com/input-output-hk/daedalus/pull/2827), [PR 2831](https://github.com/input-output-hk/daedalus/pull/2831))
+
+### Chores
+
+- Updated check-disk-space version ([PR 2845](https://github.com/input-output-hk/daedalus/pull/2845))
+- Updated CWB and Cardano Node ([PR 2822](https://github.com/input-output-hk/daedalus/pull/2822))
+
+### Fixes
+
+- Fixed blockchain verification progress text ([PR 2840](https://github.com/input-output-hk/daedalus/pull/2840))
+
+## 4.8.0-FC1
+
+### Features
+
+- Added dynamic RTS flags setting ([PR 2758](https://github.com/input-output-hk/daedalus/pull/2758/files))
+- Improved UI/UX of RTS flags settings ([PR 2842](https://github.com/input-output-hk/daedalus/pull/2842), [PR 2846](https://github.com/input-output-hk/daedalus/pull/2846))
+- Updated messages about Cardano node sync on the initial screen ([PR 2827](https://github.com/input-output-hk/daedalus/pull/2827), [PR 2831](https://github.com/input-output-hk/daedalus/pull/2831))
+
+### Chores
+
+- Updated check-disk-space version ([PR 2845](https://github.com/input-output-hk/daedalus/pull/2845))
+- Updated CWB and Cardano Node ([PR 2822](https://github.com/input-output-hk/daedalus/pull/2822))
+
+### Fixes
+
+- Fixed blockchain verification progress text ([PR 2840](https://github.com/input-output-hk/daedalus/pull/2840))
+
+## 4.7.0
+
+### Features
+
+- Updated Catalyst dates ([PR 2812](https://github.com/input-output-hk/daedalus/pull/2812))
+
### Fixes
- Fixed immediate language updates of application top menu bar ([PR 2813](https://github.com/input-output-hk/daedalus/pull/2813))
diff --git a/README.md b/README.md
index 4cd19ffcd9..58330abddf 100644
--- a/README.md
+++ b/README.md
@@ -65,8 +65,8 @@ If you get SSL error when running `nix-shell` (SSL peer certificate or SSH remot
1. Run `yarn nix:selfnode` from `daedalus`.
2. Run `yarn dev` from the subsequent `nix-shell` (use `KEEP_LOCAL_CLUSTER_RUNNING` environment variable to keep the local cluster running after Daedalus exits: `KEEP_LOCAL_CLUSTER_RUNNING=true yarn dev`)
-3. Run `yarn start` from a second `nix-shell` instance (running step 1 from a new terminal instance)
-4. Once Daedalus has started and has gotten past the loading screen run the following commands from a new terminal window if you wish to import funded wallets:
+ 1. Alternatively: run `yarn nix:selfnode yarn dev` to achieve the same thing in a single command. Note: after `yarn dev` exits, you will still remain in the `nix-shell`.
+3. Once Daedalus has started and has gotten past the loading screen run the following commands from a new terminal window if you wish to import funded wallets:
- Byron wallets: `yarn byron:wallet:importer`
- Shelley wallets: `yarn shelley:wallet:importer`
- Mary wallets: `yarn mary:wallet:importer` (all of which contain native tokens which are visible once selfnode enters Mary era)
@@ -95,37 +95,37 @@ If you get SSL error when running `nix-shell` (SSL peer certificate or SSH remot
1. Run `yarn nix:mainnet` from `daedalus`.
2. Run `yarn dev` from the subsequent `nix-shell`
-3. Run `yarn start` from a second `nix-shell` instance (running step 1 from a new terminal instance)
+3. Or in one command: `yarn nix:mainnet yarn dev`
#### Flight
1. Run `yarn nix:flight` from `daedalus`.
2. Run `yarn dev` from the subsequent `nix-shell`
-3. Run `yarn start` from a second `nix-shell` instance (running step 1 from a new terminal instance)
+3. Or in one command: `yarn nix:flight yarn dev`
#### Testnet
1. Run `yarn nix:testnet` from `daedalus`.
2. Run `yarn dev` from the subsequent `nix-shell`
-3. Run `yarn start` from a second `nix-shell` instance (running step 1 from a new terminal instance)
+3. Or in one command: `yarn nix:testnet yarn dev`
#### Staging
1. Run `yarn nix:staging` from `daedalus`.
2. Run `yarn dev` from the subsequent `nix-shell`
-3. Run `yarn start` from a second `nix-shell` instance (running step 1 from a new terminal instance)
+3. Or in one command: `yarn nix:staging yarn dev`
#### Shelley QA
1. Run `yarn nix:shelley_qa` from `daedalus`.
2. Run `yarn dev` from the subsequent `nix-shell`
-3. Run `yarn start` from a second `nix-shell` instance (running step 1 from a new terminal instance)
+3. Or in one command: `yarn nix:shelley_qa yarn dev`
#### Alonzo Purple
1. Run `yarn nix:alonzo_purple` from `daedalus`.
2. Run `yarn dev` from the subsequent `nix-shell`
-3. Run `yarn start` from a second `nix-shell` instance (running step 1 from a new terminal instance)
+3. Or in one command: `yarn nix:alonzo_purple yarn dev`
#### Native token metadata server
@@ -201,6 +201,15 @@ Make sure to list bootstrap in externals in `webpack.config.base.js` or the app
externals: ['bootstrap']
```
+### Debugging
+
+You can debug the main process by following one of these approaches:
+- [VSCode](https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_attaching-to-nodejs)
+- [Chrome](https://nodejs.org/en/docs/guides/debugging-getting-started/#inspector-clients)
+- [IntelliJ](https://www.jetbrains.com/help/idea/run-debug-configuration-node-js-remote-debug.html)
+
+The inspector runs on port 9229
+
## Testing
You can find more details regarding tests setup within
diff --git a/bors.toml b/bors.toml
index 5375315116..c8cf3c886a 100644
--- a/bors.toml
+++ b/bors.toml
@@ -1,11 +1,6 @@
status = [
# Buildkite: osx/linux installers
"buildkite/daedalus",
-
- # Hydra: we just care about tests attribute set
- "ci/hydra:Cardano:daedalus:tests.runTsc",
- "ci/hydra:Cardano:daedalus:tests.runLint",
- "ci/hydra:Cardano:daedalus:tests.runShellcheck"
]
timeout_sec = 7200
required_approvals = 1
diff --git a/declaration.d.ts b/declaration.d.ts
index cf2f235f2d..e598e2a913 100644
--- a/declaration.d.ts
+++ b/declaration.d.ts
@@ -22,6 +22,17 @@ type Daedalus = {
};
};
+export type $ElementType<
+ T extends { [P in K & any]: any },
+ K extends keyof T | number
+> = T[K];
+
+export type EnumMap<
+ K extends string,
+ V,
+ O extends Record = any
+> = O & Record>;
+
declare global {
namespace NodeJS {
interface ProcessEnv {
diff --git a/default.nix b/default.nix
index 1f8d485afa..09f9c5f7bd 100644
--- a/default.nix
+++ b/default.nix
@@ -40,7 +40,7 @@ let
inherit (pkgs.lib) optionalString optional concatStringsSep;
inherit (pkgs) writeTextFile;
crossSystem = lib: (crossSystemTable lib).${target} or null;
- # TODO, nsis cant cross-compile with the nixpkgs daedalus currently uses
+ # TODO, nsis can't cross-compile with the nixpkgs daedalus currently uses
nsisNixPkgs = import localLib.sources.nixpkgs-nsis {};
installPath = ".daedalus";
needSignedBinaries = (signingKeys != null) || (HSMServer != null);
@@ -55,7 +55,7 @@ let
cardanoLib = localLib.iohkNix.cardanoLib;
daedalus-bridge = self.bridgeTable.${nodeImplementation};
- nodejs = pkgs.nodejs-16_x;
+ nodejs = pkgs.nodejs-14_x;
nodePackages = pkgs.nodePackages.override { nodejs = self.nodejs; };
yarnInfo = {
version = "1.22.4";
@@ -319,8 +319,6 @@ let
electron = pkgs.callPackage ./installers/nix/electron.nix {};
tests = {
- runTsc = self.callPackage ./tests/tsc.nix {};
- runLint = self.callPackage ./tests/lint.nix {};
runShellcheck = self.callPackage ./tests/shellcheck.nix { src = ./.;};
};
nix-bundle = import sources.nix-bundle { nixpkgs = pkgs; };
diff --git a/gulpfile.js b/gulpfile.js
index 691d5de763..1bee16bc46 100755
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -51,6 +51,8 @@ gulp.task(
)
);
+gulp.task('typedef:sass', shell.task('yarn typedef:sass --watch'));
+
gulp.task(
'clear:cache',
shell.task('rimraf ./node_modules/.cache && rimraf .cache-loader')
diff --git a/installers/common/MacInstaller.hs b/installers/common/MacInstaller.hs
index fc3ec70d7d..666907a6d0 100644
--- a/installers/common/MacInstaller.hs
+++ b/installers/common/MacInstaller.hs
@@ -152,6 +152,8 @@ sign_cmd "$ABS_PATH/Contents/Resources/app/build/HID.node"
sign_cmd "$ABS_PATH/Contents/Resources/app/node_modules/keccak/bin/darwin-x64-"*"/keccak.node"
sign_cmd "$ABS_PATH/Contents/Resources/app/node_modules/keccak/build/Release/addon.node"
sign_cmd "$ABS_PATH/Contents/Resources/app/node_modules/keccak/prebuilds/darwin-x64/node.napi.node"
+sign_cmd "$ABS_PATH/Contents/Resources/app/node_modules/blake-hash/prebuilds/darwin-x64/node.napi.node"
+sign_cmd "$ABS_PATH/Contents/Resources/app/node_modules/tiny-secp256k1/build/Release/secp256k1.node"
# Sign the whole component deeply
sign_cmd "$ABS_PATH"
diff --git a/jest.config.js b/jest.config.js
index fba7a4c536..536e373727 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -89,6 +89,7 @@ module.exports = {
// Jest does not support WASM imports from ESM modules
// https://github.com/facebook/jest/issues/9430
'^@iohk-jormungandr/wallet-js$': 'identity-obj-proxy',
+ 'tests/(.*)': '/tests/$1',
},
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
@@ -182,10 +183,10 @@ module.exports = {
},
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
- // transformIgnorePatterns: [
- // "/node_modules/",
- // "\\.pnp\\.[^\\/]+$"
- // ],
+ transformIgnorePatterns: [
+ 'node_modules/(?!react-polymorph)',
+ // "\\.pnp\\.[^\\/]+$"
+ ],
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined,
diff --git a/nix/nsis-inner.nix b/nix/nsis-inner.nix
index 32ef9d2377..4dc4e26c08 100644
--- a/nix/nsis-inner.nix
+++ b/nix/nsis-inner.nix
@@ -43,7 +43,7 @@ in stdenv.mkDerivation {
'';
meta = with lib; {
- descripition = "System to create Windows installers";
+ description = "System to create Windows installers";
homepage = "https://nsis.sourceforge.io/";
};
}
diff --git a/nix/sources.json b/nix/sources.json
index 7c132cb34e..940f079cd6 100644
--- a/nix/sources.json
+++ b/nix/sources.json
@@ -1,14 +1,14 @@
{
"cardano-node": {
- "branch": "tags/1.32.1",
+ "branch": "tags/1.33.0",
"description": null,
"homepage": null,
"owner": "input-output-hk",
"repo": "cardano-node",
- "rev": "4f65fb9a27aa7e3a1873ab4211e412af780a3648",
- "sha256": "00k9fqrm0gphjji23x0nc9z6bqh8bqrncgivn3mi3csacjzicrrx",
+ "rev": "814df2c146f5d56f8c35a681fe75e85b905aed5d",
+ "sha256": "1hr00wqzmcyc3x0kp2hyw78rfmimf6z4zd4vv85b9zv3nqbjgrik",
"type": "tarball",
- "url": "https://github.com/input-output-hk/cardano-node/archive/4f65fb9a27aa7e3a1873ab4211e412af780a3648.tar.gz",
+ "url": "https://github.com/input-output-hk/cardano-node/archive/814df2c146f5d56f8c35a681fe75e85b905aed5d.tar.gz",
"url_template": "https://github.com///archive/.tar.gz"
},
"cardano-shell": {
@@ -24,15 +24,15 @@
"url_template": "https://github.com///archive/.tar.gz"
},
"cardano-wallet": {
- "branch": "anviking/ADP-1081/node-alonzo-rc",
+ "branch": "master",
"description": "Official Wallet Backend & API for Cardano decentralized",
"homepage": null,
"owner": "input-output-hk",
"repo": "cardano-wallet",
- "rev": "760140e238a5fbca61d1b286d7a80ece058dc729",
- "sha256": "014njpddrlqm9bbab636h2gf58zkm0bx04i1jsn07vh5j3k0gri6",
+ "rev": "a5085acbd2670c24251cf8d76a4e83c77a2679ba",
+ "sha256": "1apzfy7qdgf6l0lb3icqz3rvaq2w3a53xq6wvhqnbfi8i7cacy03",
"type": "tarball",
- "url": "https://github.com/input-output-hk/cardano-wallet/archive/760140e238a5fbca61d1b286d7a80ece058dc729.tar.gz",
+ "url": "https://github.com/input-output-hk/cardano-wallet/archive/a5085acbd2670c24251cf8d76a4e83c77a2679ba.tar.gz",
"url_template": "https://github.com///archive/.tar.gz"
},
"gitignore": {
diff --git a/nix/yarn-nix-shell.sh b/nix/yarn-nix-shell.sh
new file mode 100755
index 0000000000..bccb6bf67e
--- /dev/null
+++ b/nix/yarn-nix-shell.sh
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+
+# This small wrapper over `nix-shell`, called from package.json
+# (e.g. `yarn nix:testnet`) allows to specify an initial command to be
+# run inside the `nix-shell` once its ready, e.g.:
+#
+# $ yarn nix:testnet yarn dev
+#
+# After the command finishes, you will still be left inside the
+# nix-shell.
+
+if [ $# -lt 2 ] ; then
+ echo >&2 'fatal: usage: '"$0"' [ ...]'
+ exit 1
+fi
+
+NETWORK="$1" ; shift
+cluster="$1" ; shift
+
+# Unfortunately, we need to shell-escape the command:
+# cf.
+command=''
+while [ $# -gt 0 ] ; do
+ command="$command '""${1//\'/\'\\\'\'}""'" ; shift
+done
+
+if [ -z "$command" ] ; then
+ command=':' # no-op, if no command
+fi
+
+export NETWORK
+# `return` will make the user stay in `nix-shell` after the initial command finishes:
+exec nix-shell --argstr nodeImplementation cardano --argstr cluster "$cluster" --command "$command ; return"
diff --git a/package.json b/package.json
index bd6ad38e66..ce4c578c0c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "daedalus",
"productName": "Daedalus",
- "version": "4.6.0",
+ "version": "4.9.0",
"description": "Cryptocurrency Wallet",
"main": "./dist/main/index.js",
"scripts": {
@@ -40,25 +40,27 @@
"cleanup": "mop -v",
"lint": "eslint --format=node_modules/eslint-formatter-pretty source storybook utils --ext .ts,.tsx",
"compile": "tsc --noEmit",
+ "precompile": "yarn typedef:sass",
"prettier": "./node_modules/.bin/prettier \"**/*.*\"",
"prettier:check": "yarn prettier --check",
"prettier:format": "yarn prettier --write --loglevel warn",
"stylelint": "./node_modules/.bin/stylelint \"**/*.scss\"",
"stylelint:fix": "yarn stylelint --fix",
- "manage:translations": "gulp purge:translations && gulp clear:cache && yarn build && ts-node ./translations/translation-runner.ts",
+ "manage:translations": "gulp purge:translations && gulp clear:cache && gulp build && ts-node ./translations/translation-runner.ts",
"storybook": "start-storybook -p 6006 -c storybook --ci /",
"storybook:build": "build-storybook -c storybook -o dist/storybook",
+ "storybook:build:chromatic": "build-storybook -c storybook",
"themes:check:createTheme": "gulp build:themes && ts-node -r esm ./dist/scripts/check.js",
"themes:update": "gulp build:themes && ts-node -r esm ./dist/scripts/update.js && yarn prettier --loglevel warn --write source/renderer/app/themes/daedalus/*.ts",
- "themes:copy": "babel-node source/renderer/app/themes/utils/copyTheme.ts && yarn prettier --loglevel warn --write source/renderer/app/themes/daedalus/*.ts",
+ "themes:copy": "ts-node -r @babel/register -r @babel/polyfill source/renderer/app/themes/utils/copyTheme.ts && yarn prettier --loglevel warn --write source/renderer/app/themes/daedalus/*.ts",
"clear:cache": "gulp clear:cache",
- "nix:alonzo_purple": "NETWORK=alonzo_purple nix-shell --argstr nodeImplementation cardano --argstr cluster alonzo_purple",
- "nix:mainnet": "NETWORK=mainnet nix-shell --argstr nodeImplementation cardano --argstr cluster mainnet",
- "nix:flight": "NETWORK=mainnet nix-shell --argstr nodeImplementation cardano --argstr cluster mainnet_flight",
- "nix:selfnode": "NETWORK=selfnode nix-shell --argstr nodeImplementation cardano --argstr cluster selfnode",
- "nix:shelley_qa": "NETWORK=shelley_qa nix-shell --argstr nodeImplementation cardano --argstr cluster shelley_qa",
- "nix:staging": "NETWORK=staging nix-shell --argstr nodeImplementation cardano --argstr cluster staging",
- "nix:testnet": "NETWORK=testnet nix-shell --argstr nodeImplementation cardano --argstr cluster testnet",
+ "nix:alonzo_purple": "./nix/yarn-nix-shell.sh alonzo_purple alonzo_purple",
+ "nix:mainnet": "./nix/yarn-nix-shell.sh mainnet mainnet",
+ "nix:flight": "./nix/yarn-nix-shell.sh mainnet mainnet_flight",
+ "nix:selfnode": "./nix/yarn-nix-shell.sh selfnode selfnode",
+ "nix:shelley_qa": "./nix/yarn-nix-shell.sh shelley_qa shelley_qa",
+ "nix:staging": "./nix/yarn-nix-shell.sh staging staging",
+ "nix:testnet": "./nix/yarn-nix-shell.sh testnet testnet",
"byron:wallet:importer": "ts-node utils/api-importer/byron-wallet-importer.ts",
"shelley:wallet:importer": "ts-node utils/api-importer/shelley-wallet-importer.ts",
"mary:wallet:importer": "ts-node utils/api-importer/mary-wallet-importer.ts",
@@ -67,7 +69,9 @@
"yoroi:wallet:importer": "ts-node utils/api-importer/yoroi-wallet-importer.ts",
"create-news-verification-hashes": "ts-node utils/create-news-verification-hashes/index.ts",
"lockfile:check": "ts-node utils/lockfile-checker/index.ts --check",
- "lockfile:fix": "ts-node utils/lockfile-checker/index.ts --fix"
+ "lockfile:fix": "ts-node utils/lockfile-checker/index.ts --fix",
+ "postinstall": "./scripts/postinstall.sh",
+ "typedef:sass": "typed-scss-modules source/renderer/app"
},
"bin": {
"electron": "./node_modules/.bin/electron"
@@ -100,12 +104,13 @@
"@testing-library/jest-dom": "5.15.1",
"@testing-library/react": "12.1.2",
"@types/aes-js": "3.1.1",
- "@types/node": "17.0.7",
+ "@types/jest": "27.4.0",
+ "@types/node": "17.0.12",
"@types/qrcode.react": "1.0.2",
"@types/react": "17.0.38",
"@types/react-svg-inline": "2.1.3",
- "@typescript-eslint/eslint-plugin": "5.9.0",
- "@typescript-eslint/parser": "5.9.0",
+ "@typescript-eslint/eslint-plugin": "5.10.1",
+ "@typescript-eslint/parser": "5.10.1",
"asar": "2.1.0",
"autodll-webpack-plugin": "0.4.2",
"axios": "0.24.0",
@@ -115,7 +120,7 @@
"babel-plugin-react-intl": "3.0.1",
"bufferutil": "4.0.1",
"cache-loader": "4.1.0",
- "chai": "4.2.0",
+ "chai": "4.3.4",
"chalk": "4.1.0",
"concurrently": "5.3.0",
"cross-env": "7.0.2",
@@ -157,7 +162,7 @@
"mini-css-extract-plugin": "2.3.0",
"minimist": "1.2.5",
"mobx-react-devtools": "6.1.1",
- "node-forge": "0.10.0",
+ "node-forge": "1.0.0",
"nodemon": "2.0.15",
"npmlog": "4.1.2",
"path-browserify": "1.0.1",
@@ -179,11 +184,12 @@
"style-loader": "3.2.1",
"stylelint": "13.7.2",
"stylelint-order": "4.1.0",
- "svg-inline-loader": "^0.8.2",
+ "svg-inline-loader": "0.8.2",
"thread-loader": "2.1.3",
"timemachine": "0.3.2",
"transform-loader": "0.2.4",
"ts-node": "10.4.0",
+ "typed-scss-modules": "5.0.0",
"typescript": "4.5.4",
"utf-8-validate": "5.0.2",
"webdriverio": "5.18.7",
@@ -211,22 +217,24 @@
"cardano-js": "0.4.8",
"cardano-launcher": "0.20211105.1",
"cbor": "5.0.2",
- "check-disk-space": "3.1.0",
+ "check-disk-space": "3.2.0",
"chroma-js": "2.1.0",
"classnames": "2.2.6",
"csv-stringify": "5.5.1",
"cucumber-html-reporter": "5.2.0",
"electron": "13.6.3",
"electron-log-daedalus": "2.2.21",
- "electron-store": "8.0.0",
+ "electron-store": "8.0.1",
"es6-error": "4.1.1",
- "find-process": "1.4.4",
+ "find-process": "1.4.7",
"fireworks-js": "1.0.4",
"form-data": "3.0.0",
"fs-extra": "9.0.1",
+ "fuse.js": "6.5.3",
"glob": "7.1.6",
"graceful-fs": "4.2.4",
"gulp": "4.0.2",
+ "highlight-words": "1.2.0",
"history": "4.10.1",
"humanize-duration": "3.23.1",
"inquirer": "7.3.3",
@@ -240,6 +248,7 @@
"mobx-react-form": "2.0.8",
"mobx-react-router": "4.1.0",
"moment": "2.29.0",
+ "nanoid": "3.2.0",
"node-downloader-helper": "1.0.18",
"omit-deep-lodash": "1.1.5",
"pbkdf2": "3.1.2",
@@ -258,7 +267,7 @@
"react-intl": "2.7.2",
"react-lottie": "1.2.3",
"react-markdown": "4.3.1",
- "react-polymorph": "1.0.1",
+ "react-polymorph": "1.0.3",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-svg-inline": "2.1.1",
@@ -275,6 +284,7 @@
"shasum": "1.0.2",
"source-map-support": "0.5.19",
"spectron-fake-dialog": "0.0.1",
+ "tail": "2.2.4",
"tcp-port-used": "1.0.1",
"trezor-connect": "8.2.4-extended",
"unorm": "1.6.0",
@@ -283,7 +293,7 @@
"validator": "13.7.0"
},
"devEngines": {
- "node": "16.13.2",
+ "node": ">=16.13.2",
"yarn": "1.22.4"
},
"husky": {
diff --git a/scripts/build-cross-windows.sh b/scripts/build-cross-windows.sh
index 1f9b0adcb5..5cec7e32d3 100755
--- a/scripts/build-cross-windows.sh
+++ b/scripts/build-cross-windows.sh
@@ -1,15 +1,15 @@
#!/usr/bin/env bash
-
set -e
+source "$(dirname "$0")/utils.sh"
BUILDKITE_BUILD_NUMBER="$1"
upload_artifacts() {
- buildkite-agent artifact upload "$@" --job "$BUILDKITE_JOB_ID"
+ retry 5 buildkite-agent artifact upload "$@" --job "$BUILDKITE_JOB_ID"
}
upload_artifacts_public() {
- buildkite-agent artifact upload "$@" "${ARTIFACT_BUCKET:-}" --job "$BUILDKITE_JOB_ID"
+ retry 5 buildkite-agent artifact upload "$@" "${ARTIFACT_BUCKET:-}" --job "$BUILDKITE_JOB_ID"
}
CLUSTERS="$(xargs echo -n < "$(dirname "$0")/../installer-clusters.cfg")"
diff --git a/scripts/build-installer-nix.sh b/scripts/build-installer-nix.sh
index d144c7923d..ea175313a3 100755
--- a/scripts/build-installer-nix.sh
+++ b/scripts/build-installer-nix.sh
@@ -1,15 +1,15 @@
#!/usr/bin/env bash
-
set -e
+source "$(dirname "$0")/utils.sh"
BUILDKITE_BUILD_NUMBER="$1"
upload_artifacts() {
- buildkite-agent artifact upload "$@" --job "$BUILDKITE_JOB_ID"
+ retry 5 buildkite-agent artifact upload "$@" --job "$BUILDKITE_JOB_ID"
}
upload_artifacts_public() {
- buildkite-agent artifact upload "$@" "${ARTIFACT_BUCKET:-}" --job "$BUILDKITE_JOB_ID"
+ retry 5 buildkite-agent artifact upload "$@" "${ARTIFACT_BUCKET:-}" --job "$BUILDKITE_JOB_ID"
}
rm -rf dist || true
diff --git a/scripts/build-installer-unix.sh b/scripts/build-installer-unix.sh
index ccb2bf6d1d..dbf717f4e3 100755
--- a/scripts/build-installer-unix.sh
+++ b/scripts/build-installer-unix.sh
@@ -1,53 +1,14 @@
#!/usr/bin/env bash
+set -e
+source "$(dirname "$0")/utils.sh"
+
# DEPENDENCIES (binaries should be in PATH):
# 0. 'git'
# 1. 'curl'
# 2. 'nix-shell'
-set -e
-
CLUSTERS="$(xargs echo -n < "$(dirname "$0")"/../installer-clusters.cfg)"
-usage() {
- test -z "$1" || { echo "ERROR: $*" >&2; echo >&2; }
- cat >&2 <&2; exit 1; }
-retry() {
- local tries=$1; arg2nz "iteration count" "$1"; shift
- for i in $(seq 1 "${tries}")
- do if "$@"
- then return 0
- else echo "failed, retry #$i of ${tries}"
- fi
- sleep 5s
- done
- fail "persistent failure to exec: $*"
-}
-
###
### Argument processing
###
@@ -76,8 +37,8 @@ while test $# -ge 1
do case "$1" in
--clusters ) CLUSTERS="$2"; shift;;
--fast-impure ) export fast_impure=true;;
- --build-id ) arg2nz "build identifier" "$2"; build_id="$2"; shift;;
- --nix-path ) arg2nz "NIX_PATH value" "$2";
+ --build-id ) validate_arguments "build identifier" "$2"; build_id="$2"; shift;;
+ --nix-path ) validate_arguments "NIX_PATH value" "$2";
export NIX_PATH="$2"; shift;;
--test-installer ) test_installer="--test-installer";;
@@ -117,11 +78,11 @@ export PATH=$HOME/.local/bin:$PATH
if [ -n "${NIX_SSL_CERT_FILE-}" ]; then export SSL_CERT_FILE=$NIX_SSL_CERT_FILE; fi
upload_artifacts() {
- buildkite-agent artifact upload "$@" --job "$BUILDKITE_JOB_ID"
+ retry 5 buildkite-agent artifact upload "$@" --job "$BUILDKITE_JOB_ID"
}
upload_artifacts_public() {
- buildkite-agent artifact upload "$@" "${ARTIFACT_BUCKET:-}" --job "$BUILDKITE_JOB_ID"
+ retry 5 buildkite-agent artifact upload "$@" "${ARTIFACT_BUCKET:-}" --job "$BUILDKITE_JOB_ID"
}
function checkItnCluster() {
diff --git a/scripts/postinstall.sh b/scripts/postinstall.sh
new file mode 100755
index 0000000000..b361f58733
--- /dev/null
+++ b/scripts/postinstall.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+if [[ "$CI" != "true" ]]; then
+ yarn lockfile:fix
+fi
diff --git a/scripts/utils.sh b/scripts/utils.sh
new file mode 100755
index 0000000000..1174bb4503
--- /dev/null
+++ b/scripts/utils.sh
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+
+usage() {
+ test -z "$1" || { echo "ERROR: $*" >&2; echo >&2; }
+ cat >&2 <&2
+ exit 1
+}
+
+retry() {
+ local tries=$1
+ validate_arguments "iteration count" "$1"
+ shift
+ for i in $(seq 1 "${tries}"); do
+ if "$@"; then
+ return 0
+ else
+ echo "failed, retry #$i of ${tries}"
+ fi
+ sleep 5
+ done
+ fail "persistent failure to exec: $*"
+}
diff --git a/source/common/config/downloadManagerConfig.ts b/source/common/config/downloadManagerConfig.ts
index 8e2b82b4a3..4030c5e22a 100644
--- a/source/common/config/downloadManagerConfig.ts
+++ b/source/common/config/downloadManagerConfig.ts
@@ -1,14 +1,13 @@
// https://www.npmjs.com/package/node-downloader-helper
import type {
- AllowedDownloadDirectories,
+ AllowedDownloadDirectoriesValues,
+ AllowedDownloadDirectoriesKeys,
+ AllowedDownloadDirectoriesMap,
DownloadState,
DownloadEventType,
} from '../types/downloadManager.types';
-export const ALLOWED_DOWNLOAD_DIRECTORIES: Record<
- string,
- AllowedDownloadDirectories
-> = {
+export const ALLOWED_DOWNLOAD_DIRECTORIES: AllowedDownloadDirectoriesMap = {
DOWNLOADS: 'downloads',
DESKTOP: 'desktop',
STATE_DIRECTORY: 'stateDirectory',
diff --git a/source/common/config/electron-store.config.ts b/source/common/config/electron-store.config.ts
index ba08b4aa2e..7455f7c4ff 100644
--- a/source/common/config/electron-store.config.ts
+++ b/source/common/config/electron-store.config.ts
@@ -10,19 +10,17 @@ export const STORAGE_KEYS: Record = {
APP_AUTOMATIC_UPDATE_FAILED: 'APP-AUTOMATIC-UPDATE-FAILED',
APP_UPDATE_COMPLETED: 'APP-UPDATE-COMPLETED',
ASSET_DATA: 'ASSET-DATA',
- ASSET_SETTINGS_DIALOG_WAS_OPENED: 'ASSET-SETTINGS-DIALOG-WAS-OPENED',
CURRENCY_ACTIVE: 'CURRENCY-ACTIVE',
CURRENCY_SELECTED: 'CURRENCY-SELECTED',
DATA_LAYER_MIGRATION_ACCEPTANCE: 'DATA-LAYER-MIGRATION-ACCEPTANCE',
DISCREET_MODE_ENABLED: 'DISCREET-MODE-ENABLED',
- DISCREET_MODE_SETTINGS_TOOLTIP: 'DISCREET-MODE-SETTINGS-TOOLTIP',
- DISCREET_MODE_NOTIFICATION: 'DISCREET-MODE-NOTIFICATION',
DOWNLOAD_MANAGER: 'DOWNLOAD-MANAGER',
HARDWARE_WALLETS: 'HARDWARE-WALLETS',
HARDWARE_WALLET_DEVICES: 'HARDWARE-WALLET-DEVICES',
READ_NEWS: 'READ-NEWS',
RESET: 'RESET',
SMASH_SERVER: 'SMASH-SERVER',
+ STAKE_POOLS_LIST_VIEW_TOOLTIP: 'STAKE-POOLS-LIST-VIEW-TOOLTIP',
STAKING_INFO_WAS_OPEN: 'ALONZO-INFO-WAS-OPEN',
TERMS_OF_USE_ACCEPTANCE: 'TERMS-OF-USE-ACCEPTANCE',
THEME: 'THEME',
diff --git a/source/common/ipc/api.ts b/source/common/ipc/api.ts
index dd69d9cb06..fe58d9c20d 100644
--- a/source/common/ipc/api.ts
+++ b/source/common/ipc/api.ts
@@ -14,6 +14,7 @@ import type { GenerateVotingPDFParams } from '../types/voting-pdf-request.types'
import type { GenerateCsvParams } from '../types/csv-request.types';
import type { GenerateQRCodeParams } from '../types/save-qrCode.types';
import type {
+ BlockSyncType,
CardanoNodeState,
CardanoStatus,
FaultInjectionIpcRequest,
@@ -177,9 +178,16 @@ export type SubmitBugReportRequestMainResponse = void;
/**
* Channel to rebuild the electron application menu after the language setting changes
*/
+export enum WalletSettingsStateEnum {
+ hidden = 'hidden',
+ disabled = 'disabled',
+ enabled = 'enabled',
+}
+
export const REBUILD_APP_MENU_CHANNEL = 'REBUILD_APP_MENU_CHANNEL';
export type RebuildAppMenuRendererRequest = {
isNavigationEnabled: boolean;
+ walletSettingsState: WalletSettingsStateEnum;
};
export type RebuildAppMenuMainResponse = void;
@@ -312,14 +320,6 @@ export type GenerateWalletMigrationReportRendererRequest =
WalletMigrationReportData;
export type GenerateWalletMigrationReportMainResponse = void;
-/**
- * Channel for enabling application menu navigation
- */
-export const ENABLE_APPLICATION_MENU_NAVIGATION_CHANNEL =
- 'ENABLE_APPLICATION_MENU_NAVIGATION_CHANNEL';
-export type EnableApplicationMenuNavigationRendererRequest = void;
-export type EnableApplicationMenuNavigationMainResponse = void;
-
/**
* Channel for generating wallet migration report
*/
@@ -456,9 +456,13 @@ export type IntrospectAddressMainResponse = IntrospectAddressResponse;
/**
* Channel for checking block replay progress
*/
-export const GET_BLOCK_REPLAY_STATUS_CHANNEL = 'GetBlockReplayProgressChannel';
-export type GetBlockReplayProgressRendererRequest = void;
-export type GetBlockReplayProgressMainResponse = number;
+export const GET_BLOCK_SYNC_PROGRESS_CHANNEL = 'GetBlockSyncProgressChannel';
+export type GetBlockSyncProgressType = BlockSyncType;
+export type GetBlockSyncProgressRendererRequest = void;
+export type GetBlockSyncProgressMainResponse = {
+ progress: number;
+ type: GetBlockSyncProgressType;
+};
/**
* Channels for connecting / interacting with Hardware Wallet devices
@@ -482,9 +486,9 @@ export type getCardanoAdaAppRendererRequest = {
export type getCardanoAdaAppMainResponse = HardwareWalletCardanoAdaAppResponse;
export const GET_HARDWARE_WALLET_CONNECTION_CHANNEL =
'GET_HARDWARE_WALLET_CONNECTION_CHANNEL';
-export type getHardwareWalletConnectiontMainRequest =
+export type getHardwareWalletConnectionMainRequest =
HardwareWalletConnectionRequest;
-export type getHardwareWalletConnectiontRendererResponse = Record;
+export type getHardwareWalletConnectionRendererResponse = Record;
export const SIGN_TRANSACTION_LEDGER_CHANNEL =
'SIGN_TRANSACTION_LEDGER_CHANNEL';
export type signTransactionLedgerRendererRequest = LedgerSignTransactionRequest;
@@ -513,3 +517,6 @@ export type deriveAddressMainResponse = string;
export const SHOW_ADDRESS_CHANNEL = 'SHOW_ADDRESS_CHANNEL';
export type showAddressRendererRequest = showAddressRendererRequestType;
export type showAddressMainResponse = void;
+export const TOGGLE_RTS_FLAGS_MODE_CHANNEL = 'TOGGLE_RTS_FLAGS_MODE_CHANNEL';
+export type ToggleRTSFlagsModeRendererRequest = void;
+export type ToggleRTSFlagsModeMainResponse = void;
diff --git a/source/common/ipc/constants.ts b/source/common/ipc/constants.ts
index 727b0ca928..75bdd93820 100644
--- a/source/common/ipc/constants.ts
+++ b/source/common/ipc/constants.ts
@@ -2,6 +2,7 @@ export const DIALOGS = {
ABOUT: 'ABOUT_DIALOG',
DAEDALUS_DIAGNOSTICS: 'DAEDALUS_DIAGNOSTICS_DIALOG',
ITN_REWARDS_REDEMPTION: 'ITN_REWARDS_REDEMPTION_DIALOG',
+ TOGGLE_RTS_FLAGS_MODE: 'TOGGLE_RTS_FLAGS_MODE_DIALOG',
};
export const NOTIFICATIONS = {
DOWNLOAD_LOGS: 'DOWNLOAD_LOGS_NOTIFICATION',
diff --git a/source/common/types/address-introspection.types.ts b/source/common/types/address-introspection.types.ts
index 7c96e0bea1..fca6abf3cf 100644
--- a/source/common/types/address-introspection.types.ts
+++ b/source/common/types/address-introspection.types.ts
@@ -1,33 +1,26 @@
export type IntrospectAddressRequest = {
input: string;
};
-
export type AddressStyle = 'Byron' | 'Icarus' | 'Shelley';
-
export type AddressType = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15;
-
export type ChainPointer = {
slot_num: number;
transaction_index: number;
output_index: number;
};
-
export type AddressBase = {
address_type: AddressType;
address_style: AddressStyle;
network_tag: number | null;
stake_reference: 'none' | 'by pointer' | 'by value';
};
-
export type ByronAddress = AddressBase & {
address_root: string;
derivation_path: string;
};
-
export type IcarusAddress = AddressBase & {
address_root: string;
};
-
export type ShelleyAddress = AddressBase & {
pointer?: ChainPointer;
script_hash?: string;
@@ -35,7 +28,6 @@ export type ShelleyAddress = AddressBase & {
stake_key_hash?: string;
stake_script_hash?: string;
};
-
export type IntrospectAddressResponse =
| {
introspection: ByronAddress | IcarusAddress | ShelleyAddress;
diff --git a/source/common/types/cardano-node.types.ts b/source/common/types/cardano-node.types.ts
index 563516195c..fcc526b29f 100644
--- a/source/common/types/cardano-node.types.ts
+++ b/source/common/types/cardano-node.types.ts
@@ -1,4 +1,3 @@
-import { EnumMap } from '../../renderer/app/types/enumTypes';
import {
MAINNET,
TESTNET,
@@ -54,7 +53,7 @@ export type CardanoNodeState =
| 'errored'
| 'unknown'
| 'unrecoverable';
-
+// @ts-ignore ts-migrate(2304) FIXME: Cannot find name 'EnumMap'.
export const CardanoNodeStates: EnumMap = {
STARTING: 'starting',
RUNNING: 'running',
@@ -136,6 +135,7 @@ export type CardanoStatus = {
hasBeenConnected: boolean;
cardanoNodePID: number;
cardanoWalletPID: number;
+ isRTSFlagsModeEnabled: boolean;
};
export type NetworkMagicType = Array;
export const NetworkMagics: {
@@ -159,3 +159,8 @@ export const NetworkMagics: {
// Cardano Selfnode network magic
[SELFNODE]: [1, null],
};
+export enum BlockSyncType {
+ pushingLedger = 'pushingLedger',
+ replayedBlock = 'replayedBlock',
+ validatingChunk = 'validatingChunk',
+}
diff --git a/source/common/types/downloadManager.types.ts b/source/common/types/downloadManager.types.ts
index 6b7b2ddd51..33c7fba9d3 100644
--- a/source/common/types/downloadManager.types.ts
+++ b/source/common/types/downloadManager.types.ts
@@ -1,7 +1,17 @@
-export type AllowedDownloadDirectories =
+export type AllowedDownloadDirectoriesValues =
| 'stateDirectory'
| 'downloads'
| 'desktop';
+
+export type AllowedDownloadDirectoriesKeys =
+ | 'DOWNLOADS'
+ | 'DESKTOP'
+ | 'STATE_DIRECTORY';
+
+export type AllowedDownloadDirectoriesMap = {
+ [day in AllowedDownloadDirectoriesKeys]: AllowedDownloadDirectoriesValues;
+};
+
// https://www.npmjs.com/package/node-downloader-helper
export type DownloadRequest = {
/**
@@ -12,7 +22,7 @@ export type DownloadRequest = {
*/
id?: string;
fileUrl: string;
- destinationDirectoryName?: AllowedDownloadDirectories;
+ destinationDirectoryName?: AllowedDownloadDirectoriesValues;
options?: DownloadRequestOptions | null | undefined;
resumeDownload?: {
temporaryFilename: string;
@@ -47,7 +57,7 @@ export type DownloadRequestOptions = {
httpsRequestOptions?: Record;
// Override the https request options, ex: to add SSL Certs
progressIsThrottled?: boolean;
- // by default, the progress is sent every second. if `false` it will be sent every milisecond
+ // by default, the progress is sent every second. if `false` it will be sent every millisecond
persistLocalData?: boolean; // by default, the localdata information is deleted after the end of the download
};
// https://www.npmjs.com/package/node-downloader-helper
@@ -82,7 +92,7 @@ export type DownloadInfo = {
fileUrl: string;
originalFilename: string;
temporaryFilename: string;
- destinationDirectoryName: AllowedDownloadDirectories;
+ destinationDirectoryName: AllowedDownloadDirectoriesValues;
destinationPath: string;
options: DownloadRequestOptions;
};
@@ -138,7 +148,7 @@ export type DownloadInfoProgress = {
downloaded: number;
// downloaded size in bytes
progress: number;
- // progress porcentage 0-100%
+ // progress percentage 0-100%
speed: number; // download speed in bytes
};
export type DownloadInfoEnd = {
@@ -147,7 +157,7 @@ export type DownloadInfoEnd = {
totalSize: number;
// total file size got from the server
incomplete: boolean;
- // true/false if the download endend but still incomplete
+ // true/false if the download ended but still incomplete
onDiskSize: number;
// total size of file on the disk
downloadedSize: number; // the total size downloaded
diff --git a/source/common/types/electron-store.types.ts b/source/common/types/electron-store.types.ts
index 01b13b9c82..bb3481c833 100644
--- a/source/common/types/electron-store.types.ts
+++ b/source/common/types/electron-store.types.ts
@@ -9,14 +9,13 @@ export type StorageKey =
| 'CURRENCY-SELECTED'
| 'DATA-LAYER-MIGRATION-ACCEPTANCE'
| 'DISCREET-MODE-ENABLED'
- | 'DISCREET-MODE-SETTINGS-TOOLTIP'
- | 'DISCREET-MODE-NOTIFICATION'
| 'DOWNLOAD-MANAGER'
| 'HARDWARE-WALLET-DEVICES'
| 'HARDWARE-WALLETS'
| 'READ-NEWS'
| 'RESET'
| 'SMASH-SERVER'
+ | 'STAKE-POOLS-LIST-VIEW-TOOLTIP'
| 'TERMS-OF-USE-ACCEPTANCE'
| 'THEME'
| 'TOKEN-FAVORITES'
diff --git a/source/common/types/environment.types.ts b/source/common/types/environment.types.ts
index 3b8ca04250..8513e67d0f 100644
--- a/source/common/types/environment.types.ts
+++ b/source/common/types/environment.types.ts
@@ -24,6 +24,7 @@ export type Environment = {
os: string;
cpu: string;
ram: number;
+ hasMetHardwareRequirements: boolean;
installerVersion: string;
version: string;
isWindows: boolean;
@@ -71,3 +72,9 @@ export const networkPrettyNames = {
selfnode: 'Selfnode',
development: 'Development',
};
+export type CpuThreadData = {
+ model: string;
+ speed: number;
+ times: Record;
+};
+export type Cpu = Array;
diff --git a/source/common/types/logging.types.ts b/source/common/types/logging.types.ts
index 9aa2f77368..e8d93af11e 100644
--- a/source/common/types/logging.types.ts
+++ b/source/common/types/logging.types.ts
@@ -19,10 +19,10 @@ import type { AdaApiStakePool } from '../../renderer/app/api/staking/types';
export type LoggingLevel = 'debug' | 'info' | 'error' | 'warn';
export type Logger = {
- debug: (arg0: string, arg1: Record | null | undefined) => void;
- info: (arg0: string, arg1: Record | null | undefined) => void;
- error: (arg0: string, arg1: Record | null | undefined) => void;
- warn: (arg0: string, arg1: Record | null | undefined) => void;
+ debug: (arg0: string, arg1?: Record | null | undefined) => void;
+ info: (arg0: string, arg1?: Record | null | undefined) => void;
+ error: (arg0: string, arg1?: Record | null | undefined) => void;
+ warn: (arg0: string, arg1?: Record | null | undefined) => void;
};
export type FormatMessageContextParams = {
appName: string;
diff --git a/source/main/cardano/CardanoNode.ts b/source/main/cardano/CardanoNode.ts
index 6f707257de..4f2e34292a 100644
--- a/source/main/cardano/CardanoNode.ts
+++ b/source/main/cardano/CardanoNode.ts
@@ -29,6 +29,7 @@ import { CardanoSelfnodeLauncher } from './CardanoSelfnodeLauncher';
import { launcherConfig } from '../config';
import type { NodeConfig } from '../config';
import type { Logger } from '../../common/types/logging.types';
+import { containsRTSFlags } from '../utils/containsRTSFlags';
/* eslint-disable consistent-return */
type Actions = {
@@ -84,6 +85,7 @@ export type CardanoNodeConfig = {
// Path to cardano-cli executable
isStaging: boolean;
metadataUrl?: string;
+ rtsFlags: Array;
};
const CARDANO_UPDATE_EXIT_CODE = 20;
// grab the current network on which Daedalus is running
@@ -229,6 +231,7 @@ export class CardanoNode {
return Object.assign({}, this._status, {
cardanoNodePID: get(this, '_node.pid', 0),
cardanoWalletPID: get(this, '_node.wpid', 0),
+ isRTSFlagsModeEnabled: containsRTSFlags(this._config.rtsFlags),
});
}
@@ -519,7 +522,7 @@ export class CardanoNode {
}
/**
- * Kills cardano-node and waitsup to `killTimeout` for the node to
+ * Kills cardano-node and waits up to `killTimeout` for the node to
* report the exit message.
*
* @returns {Promise} resolves if the node could be killed, rejects with error otherwise.
diff --git a/source/main/cardano/CardanoWalletLauncher.ts b/source/main/cardano/CardanoWalletLauncher.ts
index 70afc2f22b..c825ae36c7 100644
--- a/source/main/cardano/CardanoWalletLauncher.ts
+++ b/source/main/cardano/CardanoWalletLauncher.ts
@@ -35,6 +35,7 @@ export type WalletOptions = {
cliBin: string;
isStaging: boolean;
metadataUrl?: string;
+ rtsFlags: Array;
};
export async function CardanoWalletLauncher(
walletOptions: WalletOptions
@@ -54,6 +55,7 @@ export async function CardanoWalletLauncher(
cliBin,
isStaging,
metadataUrl,
+ rtsFlags,
} = walletOptions;
// TODO: Update launcher config to pass number
const syncToleranceSeconds = parseInt(syncTolerance.replace('s', ''), 10);
@@ -146,11 +148,20 @@ export async function CardanoWalletLauncher(
logger.info('Launching Wallet with --token-metadata-server flag', {
tokenMetadataServer,
});
+
// RTS flags:
- nodeConfig.rtsOpts = [];
- logger.info('Launching Cardano Node with RTS flags', {
- rtsFlags: nodeConfig.rtsOpts,
- });
+ // 1) "-H4G -M6553M -c70" 16.0% peak RSS reduction and a sub-percentile CPU regression
+ // 2) "-H4G -M6553M" 18.5% peak RSS reduction and a second-best CPU regression
+ if (!!rtsFlags && rtsFlags?.length > 0) {
+ nodeConfig.rtsOpts = rtsFlags;
+ logger.info('Launching Cardano Node with RTS flags', {
+ rtsFlags,
+ });
+ } else {
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
+ logger.info('Launching Cardano Node without RTS flags');
+ }
+
merge(launcherConfig, {
nodeConfig,
tlsConfiguration,
diff --git a/source/main/cardano/setup.ts b/source/main/cardano/setup.ts
index 5be36aa199..f56f496ad2 100644
--- a/source/main/cardano/setup.ts
+++ b/source/main/cardano/setup.ts
@@ -49,10 +49,12 @@ const restartCardanoNode = async (node: CardanoNode) => {
*
* @param launcherConfig {LauncherConfig}
* @param mainWindow
+ * @param rtsFlags flags used to start cardano-node
*/
export const setupCardanoNode = (
launcherConfig: LauncherConfig,
- mainWindow: BrowserWindow
+ mainWindow: BrowserWindow,
+ rtsFlags: Array
): CardanoNode => {
const {
logsPrefix,
@@ -78,6 +80,7 @@ export const setupCardanoNode = (
configPath,
syncTolerance,
cliBin,
+ rtsFlags,
isStaging,
metadataUrl,
startupTimeout: NODE_STARTUP_TIMEOUT,
diff --git a/source/main/config.ts b/source/main/config.ts
index 93968a36b0..9dd57d40b9 100644
--- a/source/main/config.ts
+++ b/source/main/config.ts
@@ -103,7 +103,7 @@ export const windowOptions: WindowOptionsType = {
nodeIntegration: isTest,
webviewTag: false,
enableRemoteModule: isTest,
- preload: path.join(__dirname, './preload.ts'),
+ preload: path.join(__dirname, './preload.js'),
// @ts-ignore ts-migrate(2322) FIXME: Type '{ nodeIntegration: boolean; webviewTag: fals... Remove this comment to see the full error message
additionalArguments: isBlankScreenFixActive ? ['--safe-mode'] : [],
},
@@ -132,11 +132,11 @@ export const buildLabel = getBuildLabel(
);
// Logging config
export const ALLOWED_LOGS = [
- 'Daedalus.tson',
- 'System-info.tson',
- 'Daedalus-versions.tson',
- 'State-snapshot.tson',
- 'Wallet-migration-report.tson',
+ 'Daedalus.json',
+ 'System-info.json',
+ 'Daedalus-versions.json',
+ 'State-snapshot.json',
+ 'Wallet-migration-report.json',
'cardano-wallet.log',
'node.log',
];
@@ -171,12 +171,13 @@ export const DISK_SPACE_RECOMMENDED_PERCENTAGE = 15; // 15% of the total disk sp
export const DISK_SPACE_CHECK_TIMEOUT = 9 * 1000; // Timeout for checking disks pace
-export const BLOCK_REPLAY_PROGRESS_CHECK_INTERVAL = 1 * 1000; // 1 seconds | unit: milliseconds
-
// Used if token metadata server URL is not defined in launcher config
export const FALLBACK_TOKEN_METADATA_SERVER_URL =
'https://metadata.cardano-testnet.iohkdev.io';
+export const MINIMUM_AMOUNT_OF_RAM_FOR_RTS_FLAGS = 16 * 1024 * 1024 * 1024; // 16gb RAM
+
// Used by mock-token-metadata-server
export const MOCK_TOKEN_METADATA_SERVER_URL = 'http://localhost';
export const MOCK_TOKEN_METADATA_SERVER_PORT =
process.env.MOCK_TOKEN_METADATA_SERVER_PORT || 0;
+export const RTS_FLAGS = ['-c'];
diff --git a/source/main/environment.ts b/source/main/environment.ts
index da9286c61e..89eab9f420 100644
--- a/source/main/environment.ts
+++ b/source/main/environment.ts
@@ -19,6 +19,12 @@ import {
checkIsWindows,
checkIsLinux,
} from '../common/utils/environmentCheckers';
+// Daedalus requires minimum 16 gigabytes of RAM, but some devices having 16 GB
+// actually have a slightly smaller RAM size (eg. 15.99 GB), therefore we used 15 GB threshold
+//
+// TODO figure out better place for it - can't import from config.js as it would be a circular dep
+// https://input-output.atlassian.net/browse/DDW-928
+export const RECOMMENDED_RAM_IN_BYTES = 15 * 1024 * 1024 * 1024;
/* ==================================================================
= Evaluations =
@@ -36,14 +42,10 @@ const isAlonzoPurple = checkIsAlonzoPurple(NETWORK);
const isShelleyQA = checkIsShelleyQA(NETWORK);
const isSelfnode = checkIsSelfnode(NETWORK);
const isDevelopment = checkIsDevelopment(NETWORK);
-const isWatchMode =
- (process.env.IS_WATCH_MODE && process.env.IS_WATCH_MODE === 'true') || false;
-const keepLocalClusterRunning =
- (process.env.KEEP_LOCAL_CLUSTER_RUNNING &&
- process.env.KEEP_LOCAL_CLUSTER_RUNNING === 'true') ||
- false;
+const keepLocalClusterRunning = process.env.KEEP_LOCAL_CLUSTER_RUNNING;
const API_VERSION = process.env.API_VERSION || 'dev';
-const NODE_VERSION = '1.32.1'; // TODO: pick up this value from process.env
+const NODE_VERSION = '1.33.0'; // TODO: pick up this value from process.env
+
const mainProcessID = get(process, 'ppid', '-');
const rendererProcessID = process.pid;
const PLATFORM = os.platform();
@@ -51,13 +53,12 @@ const PLATFORM_VERSION = os.release();
const OS = OS_NAMES[PLATFORM] || PLATFORM;
const cpu = os.cpus();
const ram = os.totalmem();
+const hasMetHardwareRequirements = ram >= RECOMMENDED_RAM_IN_BYTES;
const isBlankScreenFixActive = includes(process.argv.slice(1), '--safe-mode');
const BUILD = process.env.BUILD_NUMBER || 'dev';
const BUILD_NUMBER = uniq([API_VERSION, BUILD]).join('.');
const INSTALLER_VERSION = uniq([API_VERSION, BUILD]).join('.');
-const MOBX_DEV_TOOLS =
- (process.env.MOBX_DEV_TOOLS && process.env.MOBX_DEV_TOOLS === 'true') ||
- false;
+const MOBX_DEV_TOOLS = process.env.MOBX_DEV_TOOLS || false;
const isMacOS = checkIsMacOS(PLATFORM);
const isWindows = checkIsWindows(PLATFORM);
const isLinux = checkIsLinux(PLATFORM);
@@ -101,6 +102,7 @@ export const environment: Environment = Object.assign(
isLinux,
isBlankScreenFixActive,
keepLocalClusterRunning,
+ hasMetHardwareRequirements,
},
process.env
);
diff --git a/source/main/index.ts b/source/main/index.ts
index c21a57c0af..c3d1794ec7 100644
--- a/source/main/index.ts
+++ b/source/main/index.ts
@@ -1,7 +1,10 @@
import os from 'os';
import path from 'path';
import { app, dialog, BrowserWindow, screen, shell } from 'electron';
+import type { Event } from 'electron';
+import { client } from 'electron-connect';
import EventEmitter from 'events';
+import { WalletSettingsStateEnum } from '../common/ipc/api';
import { requestElectronStore } from './ipc/electronStoreConversation';
import { logger } from './utils/logging';
import {
@@ -19,6 +22,7 @@ import mainErrorHandler from './utils/mainErrorHandler';
import {
launcherConfig,
pubLogsFolderPath,
+ RTS_FLAGS,
stateDirectoryPath,
} from './config';
import { setupCardanoNode } from './cardano/setup';
@@ -40,12 +44,17 @@ import type {
import { logUsedVersion } from './utils/logUsedVersion';
import { setStateSnapshotLogChannel } from './ipc/set-log-state-snapshot';
import { generateWalletMigrationReportChannel } from './ipc/generateWalletMigrationReportChannel';
-import { enableApplicationMenuNavigationChannel } from './ipc/enableApplicationMenuNavigationChannel';
import { pauseActiveDownloads } from './ipc/downloadManagerChannel';
import {
restoreSavedWindowBounds,
saveWindowBoundsOnSizeAndPositionChange,
} from './windows/windowBounds';
+import {
+ getRtsFlagsSettings,
+ storeRtsFlagsSettings,
+} from './utils/rtsFlagsSettings';
+import { toggleRTSFlagsModeChannel } from './ipc/toggleRTSFlagsModeChannel';
+import { containsRTSFlags } from './utils/containsRTSFlags';
/* eslint-disable consistent-return */
// Global references to windows to prevent them from being garbage collected
@@ -54,6 +63,7 @@ let cardanoNode: CardanoNode;
const {
isDev,
isTest,
+ isWatchMode,
isBlankScreenFixActive,
isSelfnode,
network,
@@ -80,6 +90,7 @@ const safeExit = async () => {
pauseActiveDownloads();
if (!cardanoNode || cardanoNode.state === CardanoNodeStates.STOPPED) {
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info('Daedalus:safeExit: exiting Daedalus with code 0', {
code: 0,
});
@@ -95,15 +106,18 @@ const safeExit = async () => {
try {
const pid = cardanoNode.pid || 'null';
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info(`Daedalus:safeExit: stopping cardano-node with PID: ${pid}`, {
pid,
});
await cardanoNode.stop();
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info('Daedalus:safeExit: exiting Daedalus with code 0', {
code: 0,
});
safeExitWithCode(0);
} catch (error) {
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.error('Daedalus:safeExit: cardano-node did not exit correctly', {
error,
});
@@ -111,6 +125,13 @@ const safeExit = async () => {
}
};
+const handleWindowClose = async (event: Event | null | undefined) => {
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
+ logger.info('mainWindow received event. Safe exiting Daedalus now.');
+ event?.preventDefault();
+ await safeExit();
+};
+
const onAppReady = async () => {
setupLogging();
logUsedVersion(
@@ -142,13 +163,17 @@ const onAppReady = async () => {
process.env.PATH,
process.env.DAEDALUS_INSTALL_DIRECTORY,
].join(path.delimiter);
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info(`Daedalus is starting at ${startTime}`, {
startTime,
});
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info('Updating System-info.json file', { ...systemInfo.data });
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info(`Current working directory is: ${process.cwd()}`, {
cwd: process.cwd(),
});
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info('System and user locale', {
systemLocale,
userLocale,
@@ -157,50 +182,48 @@ const onAppReady = async () => {
await installChromeExtensions(isDev);
// @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info('Setting up Main Window...');
- // @ts-ignore ts-migrate(2345) FIXME: Argument of type 'unknown' is not assignable to pa... Remove this comment to see the full error message
- mainWindow = createMainWindow(userLocale, () =>
+ mainWindow = createMainWindow(
+ // @ts-ignore ts-migrate(2345) FIXME: Argument of type 'unknown' is not assignable to pa... Remove this comment to see the full error message
+ userLocale,
// @ts-ignore ts-migrate(2345) FIXME: Argument of type 'Electron.Screen' is not assignab... Remove this comment to see the full error message
restoreSavedWindowBounds(screen, requestElectronStore)
);
saveWindowBoundsOnSizeAndPositionChange(mainWindow, requestElectronStore);
+ const currentRtsFlags = getRtsFlagsSettings(network) || [];
// @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
- logger.info('Setting up Cardano Node...');
- cardanoNode = setupCardanoNode(launcherConfig, mainWindow);
+ logger.info(
+ `Setting up Cardano Node... with flags: ${JSON.stringify(currentRtsFlags)}`
+ );
+ cardanoNode = setupCardanoNode(launcherConfig, mainWindow, currentRtsFlags);
// @ts-ignore ts-migrate(2345) FIXME: Argument of type 'unknown' is not assignable to pa... Remove this comment to see the full error message
buildAppMenus(mainWindow, cardanoNode, userLocale, {
isNavigationEnabled: false,
+ walletSettingsState: WalletSettingsStateEnum.hidden,
});
- enableApplicationMenuNavigationChannel.onReceive(
- () =>
- new Promise((resolve) => {
- const locale = getLocale(network);
- // @ts-ignore ts-migrate(2345) FIXME: Argument of type 'unknown' is not assignable to pa... Remove this comment to see the full error message
- buildAppMenus(mainWindow, cardanoNode, locale, {
- isNavigationEnabled: true,
- });
- resolve();
- })
- );
rebuildApplicationMenu.onReceive(
- (data) =>
+ ({ walletSettingsState, isNavigationEnabled }) =>
new Promise((resolve) => {
const locale = getLocale(network);
// @ts-ignore ts-migrate(2345) FIXME: Argument of type 'unknown' is not assignable to pa... Remove this comment to see the full error message
buildAppMenus(mainWindow, cardanoNode, locale, {
- isNavigationEnabled: data.isNavigationEnabled,
+ isNavigationEnabled,
+ walletSettingsState,
});
// @ts-ignore ts-migrate(2339) FIXME: Property 'updateTitle' does not exist on type 'Bro... Remove this comment to see the full error message
mainWindow.updateTitle(locale);
+ // @ts-ignore ts-migrate(2794) FIXME: Expected 1 arguments, but got 0. Did you forget to... Remove this comment to see the full error message
resolve();
})
);
setStateSnapshotLogChannel.onReceive(
- (data: SetStateSnapshotLogMainResponse) =>
- Promise.resolve(logStateSnapshot(data))
+ (data: SetStateSnapshotLogMainResponse) => {
+ return Promise.resolve(logStateSnapshot(data));
+ }
);
generateWalletMigrationReportChannel.onReceive(
- (data: GenerateWalletMigrationReportRendererRequest) =>
- Promise.resolve(generateWalletMigrationReport(data))
+ (data: GenerateWalletMigrationReportRendererRequest) => {
+ return Promise.resolve(generateWalletMigrationReport(data));
+ }
);
getStateDirectoryPathChannel.onRequest(() =>
Promise.resolve(stateDirectoryPath)
@@ -209,6 +232,12 @@ const onAppReady = async () => {
Promise.resolve(app.getPath('desktop'))
);
getSystemLocaleChannel.onRequest(() => Promise.resolve(systemLocale));
+ toggleRTSFlagsModeChannel.onReceive(() => {
+ const flagsToSet = containsRTSFlags(currentRtsFlags) ? [] : RTS_FLAGS;
+ storeRtsFlagsSettings(environment.network, flagsToSet);
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
+ return handleWindowClose();
+ });
const handleCheckDiskSpace = handleDiskSpace(mainWindow, cardanoNode);
const onMainError = (error: string) => {
@@ -219,22 +248,22 @@ const onAppReady = async () => {
};
mainErrorHandler(onMainError);
+ handleCheckBlockReplayProgress(mainWindow, launcherConfig.logsPrefix);
await handleCheckDiskSpace();
- await handleCheckBlockReplayProgress(mainWindow, launcherConfig.logsPrefix);
- mainWindow.on('close', async (event) => {
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
- logger.info(
- 'mainWindow received event. Safe exiting Daedalus now.'
- );
- event.preventDefault();
- await safeExit();
- });
+
+ if (isWatchMode) {
+ // Connect to electron-connect server which restarts / reloads windows on file changes
+ client.create(mainWindow);
+ }
+
+ mainWindow.on('close', handleWindowClose);
// Security feature: Prevent creation of new browser windows
// https://github.com/electron/electron/blob/master/docs/tutorial/security.md#14-disable-or-limit-creation-of-new-windows
app.on('web-contents-created', (_, contents) => {
contents.on('new-window', (event, url) => {
// Prevent creation of new BrowserWindows via links / window.open
event.preventDefault();
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info('Prevented creation of new browser window', {
url,
});
@@ -250,6 +279,7 @@ const onAppReady = async () => {
if (isSelfnode) {
if (keepLocalClusterRunning || isTest) {
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info(
'ipcMain: Keeping the local cluster running while exiting Daedalus',
{
diff --git a/source/main/ipc/downloadManagerChannel.ts b/source/main/ipc/downloadManagerChannel.ts
index 0ad41fd41f..a275b72160 100644
--- a/source/main/ipc/downloadManagerChannel.ts
+++ b/source/main/ipc/downloadManagerChannel.ts
@@ -206,8 +206,9 @@ const getDownloadLocalData = async ({
};
const getDownloadsLocalData =
- // @ts-ignore ts-migrate(2322) FIXME: Type 'unknown' is not assignable to type 'Download... Remove this comment to see the full error message
- async (): Promise => localStorage.getAll();
+ async (): Promise => {
+ return localStorage.getAll() as Promise;
+ };
const clearDownloadLocalData = async ({
fileName,
diff --git a/source/main/ipc/electronStoreConversation.ts b/source/main/ipc/electronStoreConversation.ts
index 32f27c6647..f35dd075d1 100644
--- a/source/main/ipc/electronStoreConversation.ts
+++ b/source/main/ipc/electronStoreConversation.ts
@@ -31,14 +31,13 @@ const reset = async () => {
await unset(keys.CURRENCY_SELECTED);
await unset(keys.DATA_LAYER_MIGRATION_ACCEPTANCE);
await unset(keys.DISCREET_MODE_ENABLED);
- await unset(keys.DISCREET_MODE_SETTINGS_TOOLTIP);
- await unset(keys.DISCREET_MODE_NOTIFICATION);
await unset(keys.DOWNLOAD_MANAGER);
await unset(keys.HARDWARE_WALLET_DEVICES);
await unset(keys.HARDWARE_WALLETS);
await unset(keys.READ_NEWS);
await unset(keys.SMASH_SERVER);
await unset(keys.STAKING_INFO_WAS_OPEN);
+ await unset(keys.STAKE_POOLS_LIST_VIEW_TOOLTIP);
await unset(keys.TERMS_OF_USE_ACCEPTANCE);
await unset(keys.THEME);
await unset(keys.USER_DATE_FORMAT_ENGLISH);
diff --git a/source/main/ipc/get-block-sync-progress.ts b/source/main/ipc/get-block-sync-progress.ts
new file mode 100644
index 0000000000..5613f5a21c
--- /dev/null
+++ b/source/main/ipc/get-block-sync-progress.ts
@@ -0,0 +1,13 @@
+import { MainIpcChannel } from './lib/MainIpcChannel';
+import { GET_BLOCK_SYNC_PROGRESS_CHANNEL } from '../../common/ipc/api';
+import type {
+ GetBlockSyncProgressRendererRequest,
+ GetBlockSyncProgressMainResponse,
+} from '../../common/ipc/api';
+
+// IpcChannel
+
+export const getBlockSyncProgressChannel: MainIpcChannel<
+ GetBlockSyncProgressRendererRequest,
+ GetBlockSyncProgressMainResponse
+> = new MainIpcChannel(GET_BLOCK_SYNC_PROGRESS_CHANNEL);
diff --git a/source/main/ipc/getHardwareWalletChannel.ts b/source/main/ipc/getHardwareWalletChannel.ts
index 6bfa2adddf..c20b5f559c 100644
--- a/source/main/ipc/getHardwareWalletChannel.ts
+++ b/source/main/ipc/getHardwareWalletChannel.ts
@@ -22,8 +22,8 @@ import type {
getCardanoAdaAppRendererRequest,
getExtendedPublicKeyMainResponse,
getExtendedPublicKeyRendererRequest,
- getHardwareWalletConnectiontMainRequest,
- getHardwareWalletConnectiontRendererResponse,
+ getHardwareWalletConnectionMainRequest,
+ getHardwareWalletConnectionRendererResponse,
getHardwareWalletTransportMainResponse,
getHardwareWalletTransportRendererRequest,
handleInitLedgerConnectMainResponse,
@@ -80,8 +80,8 @@ const getCardanoAdaAppChannel: MainIpcChannel<
getCardanoAdaAppMainResponse
> = new MainIpcChannel(GET_CARDANO_ADA_APP_CHANNEL);
const getHardwareWalletConnectionChannel: MainIpcChannel<
- getHardwareWalletConnectiontMainRequest,
- getHardwareWalletConnectiontRendererResponse
+ getHardwareWalletConnectionMainRequest,
+ getHardwareWalletConnectionRendererResponse
> = new MainIpcChannel(GET_HARDWARE_WALLET_CONNECTION_CHANNEL);
const signTransactionLedgerChannel: MainIpcChannel<
signTransactionLedgerRendererRequest,
diff --git a/source/main/ipc/manageAppUpdateChannel.ts b/source/main/ipc/manageAppUpdateChannel.ts
index 7bc2fbe66d..0aaa69df9b 100644
--- a/source/main/ipc/manageAppUpdateChannel.ts
+++ b/source/main/ipc/manageAppUpdateChannel.ts
@@ -79,8 +79,8 @@ export const handleManageAppUpdateRequests = (window: BrowserWindow) => {
return true;
};
- const installUpdate = async (filePath) =>
- new Promise((resolve, reject) => {
+ const installUpdate = async (filePath) => {
+ return new Promise((resolve, reject) => {
const { name: functionPrefix } = installUpdate;
response(null, functionPrefix, 'installation begin.');
const { updateRunnerBin } = launcherConfig;
@@ -171,6 +171,7 @@ export const handleManageAppUpdateRequests = (window: BrowserWindow) => {
return resolve(response(true, functionPrefix));
});
});
+ };
// @ts-ignore ts-migrate(2345) FIXME: Argument of type '({ filePath, hash: expectedHash ... Remove this comment to see the full error message
manageAppUpdateChannel.onRequest(async ({ filePath, hash: expectedHash }) => {
diff --git a/source/main/ipc/toggleRTSFlagsModeChannel.ts b/source/main/ipc/toggleRTSFlagsModeChannel.ts
new file mode 100644
index 0000000000..0375018bb5
--- /dev/null
+++ b/source/main/ipc/toggleRTSFlagsModeChannel.ts
@@ -0,0 +1,11 @@
+import { TOGGLE_RTS_FLAGS_MODE_CHANNEL } from '../../common/ipc/api';
+import type {
+ ToggleRTSFlagsModeMainResponse,
+ ToggleRTSFlagsModeRendererRequest,
+} from '../../common/ipc/api';
+import { MainIpcChannel } from './lib/MainIpcChannel';
+
+export const toggleRTSFlagsModeChannel: MainIpcChannel<
+ ToggleRTSFlagsModeRendererRequest,
+ ToggleRTSFlagsModeMainResponse
+> = new MainIpcChannel(TOGGLE_RTS_FLAGS_MODE_CHANNEL);
diff --git a/source/main/locales/en-US.json b/source/main/locales/en-US.json
index 977b539f85..7fdc70661b 100644
--- a/source/main/locales/en-US.json
+++ b/source/main/locales/en-US.json
@@ -22,6 +22,13 @@
"menu.edit.undo": "Undo",
"menu.helpSupport": "Help",
"menu.helpSupport.blankScreenFix": "Blank Screen Fix",
+ "menu.helpSupport.usingRtsFlags": "Using RTS flags",
+ "menu.helpSupport.rtsFlagsDialogCancel": "Cancel",
+ "menu.helpSupport.rtsFlagsDialogConfirm": "Yes",
+ "menu.helpSupport.enableRtsFlagsDialogMessage": "When enabled, the Cardano node will attempt to reduce its RAM usage",
+ "menu.helpSupport.enableRtsFlagsDialogTitle": "Enable RAM management (RTS Flags)",
+ "menu.helpSupport.disableRtsFlagsDialogMessage": "When disabled, we will restart cardano-node in default mode",
+ "menu.helpSupport.disableRtsFlagsDialogTitle": "Disable RAM management (RTS Flags)",
"menu.helpSupport.blankScreenFixDialogCancel": "Cancel",
"menu.helpSupport.blankScreenFixDialogConfirm": "Yes",
"menu.helpSupport.blankScreenFixDialogMessage": "Turn off 'Blank screen fix'? \n \nDisabling the blank screen fix setting will improve the performance of user interface rendering by enabling graphics acceleration, however, some users may find that Daedalus runs better with this setting enabled. If you see a blank screen instead of the Daedalus user interface after disabling this setting and restarting Daedalus, please turn this setting back on. \n \nDo you want to disable this setting and restart Daedalus?",
@@ -43,5 +50,6 @@
"menu.view.toggleDeveloperTools": "Toggle Developer Tools",
"menu.view.toggleFullScreen": "Toggle Full Screen",
"menu.view.toggleMaximumWindowSize": "Toggle Maximum Window Size",
- "window.title.blankScreenFix": "['Blank screen fix' active]"
+ "window.title.blankScreenFix": "['Blank screen fix' active]",
+ "window.title.usingRtsFlags": "['Using RTS flags' active]"
}
diff --git a/source/main/locales/ja-JP.json b/source/main/locales/ja-JP.json
index c681f2dd91..e153ae0042 100644
--- a/source/main/locales/ja-JP.json
+++ b/source/main/locales/ja-JP.json
@@ -22,6 +22,13 @@
"menu.edit.undo": "元に戻す",
"menu.helpSupport": "ヘルプ",
"menu.helpSupport.blankScreenFix": "ブランク画面修正",
+ "menu.helpSupport.usingRtsFlags": "RTSフラグの使用",
+ "menu.helpSupport.rtsFlagsDialogCancel": "Cancel",
+ "menu.helpSupport.rtsFlagsDialogConfirm": "Yes",
+ "menu.helpSupport.enableRtsFlagsDialogMessage": "When enabled, the Cardano node will attempt to reduce its RAM usage",
+ "menu.helpSupport.enableRtsFlagsDialogTitle": "Enable RAM management (RTSフラグの使用\")",
+ "menu.helpSupport.disableRtsFlagsDialogMessage": "When disabled, we will restart cardano-node in default mode",
+ "menu.helpSupport.disableRtsFlagsDialogTitle": "Disable RAM management (RTSフラグの使用\")",
"menu.helpSupport.blankScreenFixDialogCancel": "キャンセル",
"menu.helpSupport.blankScreenFixDialogConfirm": "はい",
"menu.helpSupport.blankScreenFixDialogMessage": "「ブランク画面修正」を無効にしますか? \n \nブランク画面修正設定を無効にすると、グラフィックアクセラレーションが有効化されてユーザーインターフェイスのレンダリングパフォーマンスが向上しますが、この設定を有効にした方がDaedalusがスムーズに作動する場合があります。この設定を無効にしてDaedalusを再起動した際にDaedalusユーザーインターフェイスの代わりにブランク画面が表示される場合は、この設定をもう一度有効にしてください。 \n \nこの設定を無効にしてDaedalusを再起動しますか。",
@@ -43,5 +50,6 @@
"menu.view.toggleDeveloperTools": "開発者ツール切替え",
"menu.view.toggleFullScreen": "フルスクリーン切替え",
"menu.view.toggleMaximumWindowSize": "最大ウインドウサイズ切り切り替え",
- "window.title.blankScreenFix": "[「ブランク画面修正」有効 ]"
+ "window.title.blankScreenFix": "[「ブランク画面修正」有効 ]",
+ "window.title.usingRtsFlags": "[「RTSフラグの使用」が有効]"
}
diff --git a/source/main/menus/MenuActions.types.ts b/source/main/menus/MenuActions.types.ts
index 13e85aaa5c..3d239cb5ab 100644
--- a/source/main/menus/MenuActions.types.ts
+++ b/source/main/menus/MenuActions.types.ts
@@ -1,5 +1,6 @@
export type MenuActions = {
toggleBlankScreenFix: (...args: Array) => any;
+ openToggleRTSFlagsModeDialog: (...args: Array) => any;
openAboutDialog: (...args: Array) => any;
openDaedalusDiagnosticsDialog: (...args: Array) => any;
openItnRewardsRedemptionDialog: (...args: Array) => any;
diff --git a/source/main/menus/osx.ts b/source/main/menus/osx.ts
index 909ff6b35a..e1795a8e2c 100644
--- a/source/main/menus/osx.ts
+++ b/source/main/menus/osx.ts
@@ -7,9 +7,10 @@ import { environment } from '../environment';
import { showUiPartChannel } from '../ipc/control-ui-parts';
import { NOTIFICATIONS } from '../../common/ipc/constants';
import { generateSupportRequestLink } from '../../common/utils/reporting';
+import { buildKnownIssueFixesSubmenu } from './submenuBuilders';
+import { WalletSettingsStateEnum } from '../../common/ipc/api';
const id = 'menu';
-const { isBlankScreenFixActive } = environment;
export const osxMenu = (
app: App,
window: BrowserWindow,
@@ -17,6 +18,7 @@ export const osxMenu = (
translations: {},
locale: string,
isNavigationEnabled: boolean,
+ walletSettingsState: WalletSettingsStateEnum,
translation: (...args: Array) => any = getTranslation(translations, id)
) => [
{
@@ -65,7 +67,10 @@ export const osxMenu = (
actions.openWalletSettingsPage();
},
- enabled: isNavigationEnabled,
+ enabled:
+ isNavigationEnabled &&
+ walletSettingsState === WalletSettingsStateEnum.enabled,
+ visible: walletSettingsState !== WalletSettingsStateEnum.hidden,
},
{
type: 'separator',
@@ -157,23 +162,7 @@ export const osxMenu = (
{
label: translation('helpSupport'),
submenu: compact([
- {
- label: translation('helpSupport.knownIssues'),
-
- click() {
- const faqLink = translation('helpSupport.knownIssuesUrl');
- shell.openExternal(faqLink);
- },
- },
- {
- label: translation('helpSupport.blankScreenFix'),
- type: 'checkbox',
- checked: isBlankScreenFixActive,
-
- click(item) {
- actions.toggleBlankScreenFix(item);
- },
- },
+ ...buildKnownIssueFixesSubmenu(actions, translations, translation),
{
type: 'separator',
},
@@ -185,15 +174,6 @@ export const osxMenu = (
shell.openExternal(safetyTipsLinkUrl);
},
},
- /* {
- label: translation('helpSupport.featureRequest'),
- click() {
- const featureRequestLinkUrl = translation(
- 'helpSupport.featureRequestUrl'
- );
- shell.openExternal(featureRequestLinkUrl);
- },
- }, */
{
label: translation('helpSupport.supportRequest'),
diff --git a/source/main/menus/submenuBuilders.ts b/source/main/menus/submenuBuilders.ts
new file mode 100644
index 0000000000..5777e3ac18
--- /dev/null
+++ b/source/main/menus/submenuBuilders.ts
@@ -0,0 +1,49 @@
+import { shell } from 'electron';
+import type { MenuItem } from 'electron';
+import { getRtsFlagsSettings } from '../utils/rtsFlagsSettings';
+import { environment } from '../environment';
+import type { MenuActions } from './MenuActions.types';
+import { getTranslation } from '../utils/getTranslation';
+
+export const buildKnownIssueFixesSubmenu = (
+ actions: MenuActions,
+ translations: {},
+ translate: (...args: Array) => any = getTranslation(translations, 'menu')
+): MenuItem[] => {
+ const { isBlankScreenFixActive, network } = environment;
+ const rtsFlags = getRtsFlagsSettings(network);
+ const areRTSFlagsEnabled = !!rtsFlags?.length && rtsFlags.length > 0;
+ return [
+ // @ts-ignore ts-migrate(2740) FIXME: Type '{ label: any; click(): void; }' is missing t... Remove this comment to see the full error message
+ {
+ label: translate('helpSupport.knownIssues'),
+
+ click() {
+ const faqLink = translate('helpSupport.knownIssuesUrl');
+ shell.openExternal(faqLink);
+ },
+ },
+ // @ts-ignore ts-migrate(2740) FIXME: Type '{ label: any; type: "checkbox"; checked: boo... Remove this comment to see the full error message
+ {
+ label: translate('helpSupport.blankScreenFix'),
+ type: 'checkbox',
+ checked: isBlankScreenFixActive,
+
+ click(item) {
+ actions.toggleBlankScreenFix(item);
+ },
+ },
+ // @ts-ignore ts-migrate(2740) FIXME: Type '{ label: any; type: "checkbox"; checked: boo... Remove this comment to see the full error message
+ {
+ label: translate('helpSupport.usingRtsFlags'),
+ type: 'checkbox',
+ checked: areRTSFlagsEnabled,
+
+ click(item) {
+ actions.openToggleRTSFlagsModeDialog(!areRTSFlagsEnabled);
+ // keep previous setting until app restart
+ item.checked = areRTSFlagsEnabled;
+ },
+ },
+ ];
+};
diff --git a/source/main/menus/win-linux.ts b/source/main/menus/win-linux.ts
index 8dc416bb50..b070b5e0d2 100644
--- a/source/main/menus/win-linux.ts
+++ b/source/main/menus/win-linux.ts
@@ -7,9 +7,10 @@ import { environment } from '../environment';
import { NOTIFICATIONS } from '../../common/ipc/constants';
import { showUiPartChannel } from '../ipc/control-ui-parts';
import { generateSupportRequestLink } from '../../common/utils/reporting';
+import { buildKnownIssueFixesSubmenu } from './submenuBuilders';
+import { WalletSettingsStateEnum } from '../../common/ipc/api';
const id = 'menu';
-const { isWindows, isBlankScreenFixActive } = environment;
export const winLinuxMenu = (
app: App,
window: BrowserWindow,
@@ -17,6 +18,7 @@ export const winLinuxMenu = (
translations: {},
locale: string,
isNavigationEnabled: boolean,
+ walletSettingsState: WalletSettingsStateEnum,
translation: (...args: Array) => any = getTranslation(translations, id)
) => [
{
@@ -127,12 +129,15 @@ export const winLinuxMenu = (
actions.openWalletSettingsPage();
},
- enabled: isNavigationEnabled,
+ enabled:
+ isNavigationEnabled &&
+ walletSettingsState === WalletSettingsStateEnum.enabled,
+ visible: walletSettingsState !== WalletSettingsStateEnum.hidden,
},
{
type: 'separator',
},
- isWindows
+ environment.isWindows
? {
label: translation('view.toggleFullScreen'),
accelerator: 'F11',
@@ -167,23 +172,7 @@ export const winLinuxMenu = (
{
label: translation('helpSupport'),
submenu: compact([
- {
- label: translation('helpSupport.knownIssues'),
-
- click() {
- const faqLink = translation('helpSupport.knownIssuesUrl');
- shell.openExternal(faqLink);
- },
- },
- {
- label: translation('helpSupport.blankScreenFix'),
- type: 'checkbox',
- checked: isBlankScreenFixActive,
-
- click(item) {
- actions.toggleBlankScreenFix(item);
- },
- },
+ ...buildKnownIssueFixesSubmenu(actions, translations, translation),
{
type: 'separator',
},
diff --git a/source/main/utils/blockSyncProgressHelpers.spec.ts b/source/main/utils/blockSyncProgressHelpers.spec.ts
new file mode 100644
index 0000000000..853347b9df
--- /dev/null
+++ b/source/main/utils/blockSyncProgressHelpers.spec.ts
@@ -0,0 +1,28 @@
+import moment from 'moment';
+import { isItFreshLog } from './blockSyncProgressHelpers';
+
+describe('blockSyncProgressHelpers', () => {
+ it('should return true for newer logs', () => {
+ const time = '2022-02-18 13:18:47.66';
+ const applicationStartDate = moment.utc(time).add(-1, 'minute');
+ const line = `[34m[XX-M:cardano.node.ChainDB:Info:30][0m [${time} UTC] Validating chunk no. 2256 out of 2256. Progress: 99.96%`;
+
+ expect(isItFreshLog(applicationStartDate, line)).toBe(true);
+ });
+
+ it('should return false for logs of same time', () => {
+ const time = '2022-02-18 13:18:47.66';
+ const applicationStartDate = moment.utc(time);
+ const line = `[34m[XX-M:cardano.node.ChainDB:Info:30][0m [${time} UTC] Validating chunk no. 2256 out of 2256. Progress: 99.96%`;
+
+ expect(isItFreshLog(applicationStartDate, line)).toBe(false);
+ });
+
+ it('should return false for older logs', () => {
+ const time = '2022-02-18 13:18:47.66';
+ const applicationStartDate = moment.utc(time).add(1, 'minute');
+ const line = `[34m[XX-M:cardano.node.ChainDB:Info:30][0m [${time} UTC] Validating chunk no. 2256 out of 2256. Progress: 99.96%`;
+
+ expect(isItFreshLog(applicationStartDate, line)).toBe(false);
+ });
+});
diff --git a/source/main/utils/blockSyncProgressHelpers.ts b/source/main/utils/blockSyncProgressHelpers.ts
new file mode 100644
index 0000000000..d7802474ad
--- /dev/null
+++ b/source/main/utils/blockSyncProgressHelpers.ts
@@ -0,0 +1,12 @@
+import moment, { Moment } from 'moment';
+
+export function isItFreshLog(applicationStartDate: Moment, line: string) {
+ const [, logDate] =
+ line.match(/\[(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\.\d+) UTC]/) || [];
+
+ if (!logDate) {
+ return false;
+ }
+
+ return applicationStartDate.isBefore(moment.utc(logDate));
+}
diff --git a/source/main/utils/buildAppMenus.ts b/source/main/utils/buildAppMenus.ts
index bd6cb622b2..31ee34b3d7 100644
--- a/source/main/utils/buildAppMenus.ts
+++ b/source/main/utils/buildAppMenus.ts
@@ -1,4 +1,5 @@
-import { app, globalShortcut, Menu, BrowserWindow, dialog } from 'electron';
+import { app, BrowserWindow, dialog, globalShortcut, Menu } from 'electron';
+import { WalletSettingsStateEnum } from '../../common/ipc/api';
import { environment } from '../environment';
import { winLinuxMenu } from '../menus/win-linux';
import { osxMenu } from '../menus/osx';
@@ -9,17 +10,23 @@ import { DIALOGS, PAGES } from '../../common/ipc/constants';
import { showUiPartChannel } from '../ipc/control-ui-parts';
import { getTranslation } from './getTranslation';
+interface Data {
+ isNavigationEnabled: boolean;
+ walletSettingsState: WalletSettingsStateEnum;
+}
export const buildAppMenus = async (
mainWindow: BrowserWindow,
cardanoNode: CardanoNode | null | undefined,
locale: string,
- data: {
- isNavigationEnabled: boolean;
- }
+ { isNavigationEnabled, walletSettingsState }: Data
) => {
- const { ABOUT, DAEDALUS_DIAGNOSTICS, ITN_REWARDS_REDEMPTION } = DIALOGS;
+ const {
+ ABOUT,
+ DAEDALUS_DIAGNOSTICS,
+ ITN_REWARDS_REDEMPTION,
+ TOGGLE_RTS_FLAGS_MODE,
+ } = DIALOGS;
const { SETTINGS, WALLET_SETTINGS } = PAGES;
- const { isNavigationEnabled } = data;
const { isMacOS, isBlankScreenFixActive } = environment;
const translations = require(`../locales/${locale}`);
@@ -53,6 +60,7 @@ export const buildAppMenus = async (
// @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info('Restarting in BlankScreenFix...');
if (cardanoNode) await cardanoNode.stop();
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info('Exiting Daedalus with code 21', {
code: 21,
});
@@ -63,6 +71,7 @@ export const buildAppMenus = async (
// @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info('Restarting without BlankScreenFix...');
if (cardanoNode) await cardanoNode.stop();
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.info('Exiting Daedalus with code 22', {
code: 22,
});
@@ -103,6 +112,11 @@ export const buildAppMenus = async (
item.checked = isBlankScreenFixActive;
};
+ const openToggleRTSFlagsModeDialog = () => {
+ // @ts-ignore ts-migrate(2345) FIXME: Argument of type 'BrowserWindow' is not assignable... Remove this comment to see the full error message
+ if (mainWindow) showUiPartChannel.send(TOGGLE_RTS_FLAGS_MODE, mainWindow);
+ };
+
const menuActions = {
openAboutDialog,
openDaedalusDiagnosticsDialog,
@@ -110,6 +124,7 @@ export const buildAppMenus = async (
openSettingsPage,
openWalletSettingsPage,
toggleBlankScreenFix,
+ openToggleRTSFlagsModeDialog,
};
// Build app menus
let menu;
@@ -123,7 +138,8 @@ export const buildAppMenus = async (
menuActions,
translations,
locale,
- isNavigationEnabled
+ isNavigationEnabled,
+ walletSettingsState
)
);
Menu.setApplicationMenu(menu);
@@ -136,7 +152,8 @@ export const buildAppMenus = async (
menuActions,
translations,
locale,
- isNavigationEnabled
+ isNavigationEnabled,
+ walletSettingsState
)
);
mainWindow.setMenu(menu);
diff --git a/source/main/utils/containsRTSFlags.ts b/source/main/utils/containsRTSFlags.ts
new file mode 100644
index 0000000000..c6c6a6266d
--- /dev/null
+++ b/source/main/utils/containsRTSFlags.ts
@@ -0,0 +1,4 @@
+import { isEqual } from 'lodash';
+import { RTS_FLAGS } from '../config';
+
+export const containsRTSFlags = (flags: string[]) => isEqual(flags, RTS_FLAGS);
diff --git a/source/main/utils/downloadManager.ts b/source/main/utils/downloadManager.ts
index 22b47b3947..dfe1bf7de4 100644
--- a/source/main/utils/downloadManager.ts
+++ b/source/main/utils/downloadManager.ts
@@ -17,7 +17,7 @@ import type {
DownloadMainResponse,
} from '../../common/ipc/api';
import type {
- AllowedDownloadDirectories,
+ AllowedDownloadDirectoriesValues,
DownloadInfoInit,
DownloadInfoProgress,
DownloadInfoEnd,
@@ -31,7 +31,7 @@ export const downloads = {};
export const getIdFromFileName = (fileName: string): string =>
fileName.replace(/\./g, '-');
export const getPathFromDirectoryName = (
- directoryName: AllowedDownloadDirectories
+ directoryName: AllowedDownloadDirectoriesValues
) => {
const downloadsDirectory = `${stateDirectoryPath}/Downloads`;
@@ -39,7 +39,7 @@ export const getPathFromDirectoryName = (
case ALLOWED_DOWNLOAD_DIRECTORIES.DESKTOP:
return app.getPath('desktop');
- case ALLOWED_DOWNLOAD_DIRECTORIES.DOWLOADS:
+ case ALLOWED_DOWNLOAD_DIRECTORIES.DOWNLOADS:
return app.getPath('downloads');
default:
diff --git a/source/main/utils/handleCheckBlockReplayProgress.ts b/source/main/utils/handleCheckBlockReplayProgress.ts
index 6bc1d7594e..60510f5f93 100644
--- a/source/main/utils/handleCheckBlockReplayProgress.ts
+++ b/source/main/utils/handleCheckBlockReplayProgress.ts
@@ -1,49 +1,77 @@
import { BrowserWindow } from 'electron';
import fs from 'fs';
-import readline from 'readline';
+import moment from 'moment';
import path from 'path';
-import { getBlockReplayProgressChannel } from '../ipc/get-block-replay-progress';
-import { BLOCK_REPLAY_PROGRESS_CHECK_INTERVAL } from '../config';
+import { Tail } from 'tail';
+import { getBlockSyncProgressChannel } from '../ipc/get-block-sync-progress';
+import type { GetBlockSyncProgressType } from '../../common/ipc/api';
+import { BlockSyncType } from '../../common/types/cardano-node.types';
+import { isItFreshLog } from './blockSyncProgressHelpers';
+
+const blockKeyword = 'Replayed block';
+const validatingChunkKeyword = 'Validating chunk';
+const validatedChunkKeyword = 'Validated chunk';
+const ledgerKeyword = 'Pushing ledger state';
+
+const progressKeywords = [
+ blockKeyword,
+ validatingChunkKeyword,
+ validatedChunkKeyword,
+ ledgerKeyword,
+];
+
+const keywordTypeMap: Record = {
+ [blockKeyword]: BlockSyncType.replayedBlock,
+ [validatingChunkKeyword]: BlockSyncType.validatingChunk,
+ [validatedChunkKeyword]: BlockSyncType.validatingChunk,
+ [ledgerKeyword]: BlockSyncType.pushingLedger,
+};
+
+function containProgressKeywords(line: string) {
+ return progressKeywords.some((keyword) => line.includes(keyword));
+}
+
+function getProgressType(line: string): GetBlockSyncProgressType | null {
+ const key = progressKeywords.find((k) => line.includes(k));
+
+ if (!key) {
+ return null;
+ }
+
+ return keywordTypeMap[key];
+}
+
+const applicationStartDate = moment.utc();
export const handleCheckBlockReplayProgress = (
mainWindow: BrowserWindow,
logsDirectoryPath: string
) => {
- const checkBlockReplayProgress = async () => {
- const filename = 'node.log';
- const logFilePath = `${logsDirectoryPath}/pub/`;
- const filePath = path.join(logFilePath, filename);
- if (!fs.existsSync(filePath)) return;
- const fileStream = fs.createReadStream(filePath);
- const rl = readline.createInterface({
- input: fileStream,
- });
- const progress = [];
-
- for await (const line of rl) {
- if (line.includes('block replay')) {
- progress.push(line);
- }
+ const filename = 'node.log';
+ const logFilePath = `${logsDirectoryPath}/pub/`;
+ const filePath = path.join(logFilePath, filename);
+ if (!fs.existsSync(filePath)) return;
+
+ const tail = new Tail(filePath);
+
+ tail.on('line', (line) => {
+ if (
+ !isItFreshLog(applicationStartDate, line) ||
+ !containProgressKeywords(line)
+ ) {
+ return;
}
- if (!progress.length) return;
- const finalProgress = progress.slice(-1).pop();
- const percentage = finalProgress.split('block replay progress (%) =').pop();
+ const percentage = line.match(/Progress:([\s\d.,]+)%/)?.[1];
+ const progressType = getProgressType(line);
+ if (!percentage || !progressType) {
+ return;
+ }
const finalProgressPercentage = parseFloat(percentage);
// Send result to renderer process (NetworkStatusStore)
- getBlockReplayProgressChannel.send(
- finalProgressPercentage,
+ getBlockSyncProgressChannel.send(
+ { progress: finalProgressPercentage, type: progressType },
mainWindow.webContents
);
- };
-
- const setBlockReplayProgressCheckingInterval = () => {
- setInterval(async () => {
- checkBlockReplayProgress();
- }, BLOCK_REPLAY_PROGRESS_CHECK_INTERVAL);
- };
-
- // Start default interval
- setBlockReplayProgressCheckingInterval();
- return checkBlockReplayProgress;
+ });
};
diff --git a/source/main/utils/handleDiskSpace.ts b/source/main/utils/handleDiskSpace.ts
index 720c00810c..c18618ed55 100644
--- a/source/main/utils/handleDiskSpace.ts
+++ b/source/main/utils/handleDiskSpace.ts
@@ -1,6 +1,4 @@
import { BrowserWindow } from 'electron';
-
-/* eslint import/no-unresolved: "off" */
import checkDiskSpace from 'check-disk-space';
import prettysize from 'prettysize';
import { getDiskSpaceStatusChannel } from '../ipc/get-disk-space-status';
diff --git a/source/main/utils/restoreKeystore.ts b/source/main/utils/restoreKeystore.ts
index d04a0d1c8b..df221f1ebb 100644
--- a/source/main/utils/restoreKeystore.ts
+++ b/source/main/utils/restoreKeystore.ts
@@ -12,8 +12,8 @@ export type EncryptedSecretKey = {
export type WalletId = string;
export const decodeKeystore = async (
bytes: Buffer
-): Promise =>
- cbor.decodeAll(bytes).then((obj) => {
+): Promise => {
+ return cbor.decodeAll(bytes).then((obj) => {
/**
* The original 'UserSecret' from cardano-sl looks like this:
*
@@ -48,6 +48,7 @@ export const decodeKeystore = async (
const usWalletSet = obj[0][3].map((x) => toEncryptedSecretKey(x[0]));
return usKeys.concat(usWalletSet);
});
+};
const toEncryptedSecretKey = ([encryptedPayload, passphraseHash]: [
Buffer,
diff --git a/source/main/utils/rtsFlagsSettings.ts b/source/main/utils/rtsFlagsSettings.ts
new file mode 100644
index 0000000000..185e0ec04e
--- /dev/null
+++ b/source/main/utils/rtsFlagsSettings.ts
@@ -0,0 +1,34 @@
+import Store from 'electron-store';
+import { logger } from './logging';
+
+const store = new Store();
+
+const getStoreKey = (network: string): string => `${network}-RTS-FLAGS`;
+
+export const getRtsFlagsSettings = (network: string): string[] | null => {
+ try {
+ const flags = store.get(getStoreKey(network));
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
+ logger.info(`[RTS-FLAGS] Read ${network} flags: ${flags} from config`);
+ // @ts-ignore ts-migrate(2740) FIXME: Type '{}' is missing the following properties from... Remove this comment to see the full error message
+ return flags;
+ } catch (error) {
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
+ logger.error(
+ `[RTS-FLAGS] Failed to read ${network} flags from config`,
+ error
+ );
+ }
+
+ return null;
+};
+export const storeRtsFlagsSettings = (
+ network: string,
+ flags: string[]
+): void => {
+ // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
+ logger.info(
+ `[RTS-FLAGS] Persisted ${network} flags: [${flags.toString()}] in config`
+ );
+ store.set(getStoreKey(network), flags);
+};
diff --git a/source/main/utils/safeExitWithCode.ts b/source/main/utils/safeExitWithCode.ts
index a7193a8163..de1f520478 100644
--- a/source/main/utils/safeExitWithCode.ts
+++ b/source/main/utils/safeExitWithCode.ts
@@ -12,3 +12,17 @@ export const safeExitWithCode = (exitCode = 0) => {
app.exit(exitCode);
});
};
+export const relaunch = () => {
+ const { file } = log.transports;
+ // Prevent electron-log from writing to stream
+ file.level = false;
+ // Flush the stream to the log file and exit afterwards.
+ // https://nodejs.org/api/stream.html#stream_writable_end_chunk_encoding_callback
+ file.stream.end('', 'utf8', () => {
+ app.releaseSingleInstanceLock();
+ app.relaunch({
+ args: process.argv.slice(1).concat(['--relaunch']),
+ });
+ app.exit(0);
+ });
+};
diff --git a/source/main/windows/main.ts b/source/main/windows/main.ts
index 1cfbcc7ec6..1e7fe70d88 100644
--- a/source/main/windows/main.ts
+++ b/source/main/windows/main.ts
@@ -7,9 +7,11 @@ import { getTranslation } from '../utils/getTranslation';
import { getContentMinimumSize } from '../utils/getContentMinimumSize';
import { buildLabel, launcherConfig } from '../config';
import { ledgerStatus } from '../ipc/getHardwareWalletChannel';
+import { getRtsFlagsSettings } from '../utils/rtsFlagsSettings';
const rendererErrorHandler = new RendererErrorHandler();
-const { isDev, isTest, isLinux, isBlankScreenFixActive } = environment;
+const { isDev, isTest, isLinux, isBlankScreenFixActive, network } = environment;
+const rtsFlags = getRtsFlagsSettings(network);
const id = 'window';
const getWindowTitle = (locale: string): string => {
@@ -19,6 +21,8 @@ const getWindowTitle = (locale: string): string => {
let title = buildLabel;
if (isBlankScreenFixActive)
title += ` ${translation('title.blankScreenFix')}`;
+ if (!!rtsFlags && rtsFlags?.length > 0)
+ title += ` ${translation('title.usingRtsFlags')}`;
return title;
};
@@ -34,15 +38,12 @@ type WindowOptionsType = {
};
icon?: string;
};
-export const createMainWindow = (
- locale: string,
- getWindowBounds: () => Rectangle | null | undefined
-) => {
+export const createMainWindow = (locale: string, windowBounds?: Rectangle) => {
const windowOptions: WindowOptionsType = {
show: false,
width: 1150,
height: 870,
- ...getWindowBounds(),
+ ...windowBounds,
webPreferences: {
nodeIntegration: isTest,
webviewTag: false,
@@ -76,13 +77,7 @@ export const createMainWindow = (
if (event.sender !== window.webContents) return;
window.close();
});
-
- if (isDev) {
- window.loadURL(`http://localhost:8080`);
- } else {
- window.loadURL(`file://${__dirname}/../renderer/index.html`);
- }
-
+ window.loadURL(`file://${__dirname}/../renderer/index.html`);
window.on('page-title-updated', (event) => {
event.preventDefault();
});
@@ -149,8 +144,6 @@ export const createMainWindow = (
* window constructor above was buggy (height was not correctly applied)
*/
window.on('ready-to-show', () => {
- const windowBounds = getWindowBounds();
-
if (windowBounds) {
window.setBounds(windowBounds);
}
diff --git a/source/renderer/app/App.tsx b/source/renderer/app/App.tsx
index d7f7433253..d89ec81216 100755
--- a/source/renderer/app/App.tsx
+++ b/source/renderer/app/App.tsx
@@ -19,6 +19,9 @@ import { DIALOGS } from '../../common/ipc/constants';
import type { StoresMap } from './stores/index';
import type { ActionsMap } from './actions/index';
import NewsFeedContainer from './containers/news/NewsFeedContainer';
+import ToggleRTSFlagsDialogContainer from './containers/knownIssues/ToggleRTSFlagsDialogContainer';
+import RTSFlagsRecommendationOverlayContainer from './containers/knownIssues/RTSFlagsRecommendationOverlayContainer';
+import { MenuUpdater } from './containers/MenuUpdater';
@observer
class App extends Component<{
@@ -43,7 +46,7 @@ class App extends Component<{
const themeVars = require(`./themes/daedalus/${currentTheme}.ts`).default;
- const { ABOUT, DAEDALUS_DIAGNOSTICS } = DIALOGS;
+ const { ABOUT, DAEDALUS_DIAGNOSTICS, TOGGLE_RTS_FLAGS_MODE } = DIALOGS;
const canShowNews =
!isSetupPage && // Active page is not "Language Selection" or "Terms of Use"
!isNodeStopping && // Daedalus is not shutting down
@@ -59,6 +62,7 @@ class App extends Component<{
{/* @ts-ignore ts-migrate(2769) FIXME: No overload matches this call. */}
+
),
- ,
+ // @ts-ignore ts-migrate(2345) FIXME: Argument of type 'string' is not assignable to par... Remove this comment to see the full error message
+ isActiveDialog(TOGGLE_RTS_FLAGS_MODE) && (
+
+ ),
]}
+
+
{canShowNews && [
,
,
diff --git a/source/renderer/app/actions/app-actions.ts b/source/renderer/app/actions/app-actions.ts
index 50610aab49..952fff8903 100644
--- a/source/renderer/app/actions/app-actions.ts
+++ b/source/renderer/app/actions/app-actions.ts
@@ -14,4 +14,6 @@ export default class AppActions {
// Daedalus Diagnostics dialog actions
closeDaedalusDiagnosticsDialog: Action = new Action();
openDaedalusDiagnosticsDialog: Action = new Action();
+ closeToggleRTSFlagsModeDialog: Action = new Action();
+ openToggleRTSFlagsModeDialog: Action = new Action();
}
diff --git a/source/renderer/app/actions/assets-actions.ts b/source/renderer/app/actions/assets-actions.ts
index 3ce30aff9f..8767768b69 100644
--- a/source/renderer/app/actions/assets-actions.ts
+++ b/source/renderer/app/actions/assets-actions.ts
@@ -2,14 +2,14 @@ import Action from './lib/Action';
import type { AssetToken } from '../api/assets/types'; // ======= ASSETS ACTIONS =======
export default class AssetsActions {
- onAssetSettingsOpen: Action<{
+ setEditedAsset: Action<{
asset: AssetToken;
}> = new Action();
onAssetSettingsSubmit: Action<{
asset: AssetToken;
decimals: number;
}> = new Action();
- onAssetSettingsCancel: Action = new Action();
+ unsetEditedAsset: Action = new Action();
onOpenAssetSend: Action<{
uniqueId: string;
}> = new Action();
diff --git a/source/renderer/app/actions/lib/Action.ts b/source/renderer/app/actions/lib/Action.ts
index 34e1fbef6f..79b7aac220 100644
--- a/source/renderer/app/actions/lib/Action.ts
+++ b/source/renderer/app/actions/lib/Action.ts
@@ -30,7 +30,7 @@ export default class Action {
this.listeners.push(listener);
}
- trigger(params: Params) {
+ trigger(params?: Params) {
this.listeners.forEach((listener) => listener(params));
}
diff --git a/source/renderer/app/actions/network-status-actions.ts b/source/renderer/app/actions/network-status-actions.ts
index 1daff53f4d..224c73c2c9 100644
--- a/source/renderer/app/actions/network-status-actions.ts
+++ b/source/renderer/app/actions/network-status-actions.ts
@@ -7,4 +7,5 @@ export default class NetworkStatusActions {
toggleSplash: Action = new Action();
copyStateDirectoryPath: Action = new Action();
forceCheckNetworkClock: Action = new Action();
+ toggleRTSFlagsMode: Action = new Action();
}
diff --git a/source/renderer/app/actions/profile-actions.ts b/source/renderer/app/actions/profile-actions.ts
index 8599f0015f..5732ac47e4 100644
--- a/source/renderer/app/actions/profile-actions.ts
+++ b/source/renderer/app/actions/profile-actions.ts
@@ -20,4 +20,5 @@ export default class ProfileActions {
theme: string;
}> = new Action();
finishInitialScreenSettings: Action = new Action();
+ acknowledgeRTSModeRecommendation: Action = new Action();
}
diff --git a/source/renderer/app/actions/wallets-actions.ts b/source/renderer/app/actions/wallets-actions.ts
index d05dc7795c..ed4149038b 100644
--- a/source/renderer/app/actions/wallets-actions.ts
+++ b/source/renderer/app/actions/wallets-actions.ts
@@ -60,6 +60,7 @@ export default class WalletsActions {
passphrase: string;
assets?: Array;
assetsAmounts?: Array;
+ hasAssetsRemainingAfterTransaction?: boolean;
}> = new Action();
chooseWalletExportType: Action<{
walletExportType: WalletExportTypeChoices;
diff --git a/source/renderer/app/api/api.ts b/source/renderer/app/api/api.ts
index f8a6d25c33..a4b54f5217 100644
--- a/source/renderer/app/api/api.ts
+++ b/source/renderer/app/api/api.ts
@@ -40,6 +40,7 @@ import { getPublicKey } from './transactions/requests/getPublicKey';
import { getICOPublicKey } from './transactions/requests/getICOPublicKey';
// Voting requests
import { createWalletSignature } from './voting/requests/createWalletSignature';
+import { getCatalystFund } from './voting/requests/getCatalystFund';
// Wallets requests
import { updateSpendingPassword } from './wallets/requests/updateSpendingPassword';
import { updateByronSpendingPassword } from './wallets/requests/updateByronSpendingPassword';
@@ -84,6 +85,7 @@ import { cardanoFaultInjectionChannel } from '../ipc/cardano.ipc';
import patchAdaApi from './utils/patchAdaApi';
import { getLegacyWalletId, utcStringToDate } from './utils';
import { logger } from '../utils/logging';
+import { hexToString } from '../utils/strings';
import {
unscrambleMnemonics,
scrambleMnemonics,
@@ -126,7 +128,7 @@ import type {
GetNetworkParametersApiResponse,
} from './network/types';
// Transactions Types
-import type {
+import {
Transaction,
TransactionFee,
TransactionWithdrawals,
@@ -148,7 +150,7 @@ import type {
ICOPublicKeyParams,
} from './transactions/types';
// Wallets Types
-import type {
+import {
AdaWallet,
AdaWallets,
CreateHardwareWalletRequest,
@@ -203,6 +205,8 @@ import type {
import type {
CreateVotingRegistrationRequest,
CreateWalletSignatureRequest,
+ GetCatalystFundResponse,
+ CatalystFund,
} from './voting/types';
import type { StakePoolProps } from '../domains/StakePool';
import type { FaultInjectionIpcRequest } from '../../../common/types/cardano-node.types';
@@ -211,7 +215,7 @@ import { getSHA256HexForString } from './utils/hashing';
import { getNewsHash } from './news/requests/getNewsHash';
import { deleteTransaction } from './transactions/requests/deleteTransaction';
import { WALLET_BYRON_KINDS } from '../config/walletRestoreConfig';
-import ApiError from '../domains/ApiError';
+import ApiError, { ErrorType } from '../domains/ApiError';
import { formattedAmountToLovelace } from '../utils/formatters';
import type {
GetAssetsRequest,
@@ -223,11 +227,12 @@ import type { AssetLocalData } from './utils/localStorage';
import Asset from '../domains/Asset';
import { getAssets } from './assets/requests/getAssets';
import { getAccountPublicKey } from './wallets/requests/getAccountPublicKey';
+import { doesWalletRequireAdaToRemainToSupportTokens } from './utils/apiHelpers';
export default class AdaApi {
config: RequestConfig;
// We need to preserve all asset metadata during single runtime in order
- // to avoid losing it in case of Token Metadata Registry server unvailability
+ // to avoid losing it in case of Token Metadata Registry server unavailability
storedAssetMetadata: StoredAssetMetadata = {};
constructor(isTest: boolean, config: RequestConfig) {
@@ -240,13 +245,13 @@ export default class AdaApi {
}
getWallets = async (): Promise> => {
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getWallets called');
- const { getHardwareWalletLocalData, getHardwareWalletsLocalData } =
- global.daedalus.api.localStorage;
+ const { getHardwareWalletsLocalData } = global.daedalus.api.localStorage;
try {
- const wallets: AdaWallets = await getWallets(this.config);
+ const wallets: Array = await getWallets(
+ this.config
+ );
const legacyWallets: LegacyAdaWallets = await getLegacyWallets(
this.config
);
@@ -267,14 +272,15 @@ export default class AdaApi {
},
isLegacy: true,
};
- // @ts-ignore ts-migrate(2345) FIXME: Argument of type '{ address_pool_gap: number; dele... Remove this comment to see the full error message
wallets.push({ ...legacyAdaWallet, ...extraLegacyWalletProps });
});
// @TODO - Remove this once we get hardware wallet flag from WBE
return await Promise.all(
- wallets.map(async (wallet) => {
+ wallets.map(async (wallet: AdaWallet) => {
const { id } = wallet;
- const walletData = await getHardwareWalletLocalData(id);
+
+ const walletData = hwLocalData[id];
+
return _createWalletFromServerData({
...wallet,
isHardwareWallet:
@@ -453,18 +459,19 @@ export default class AdaApi {
parameters: request,
});
const { walletId, order, fromDate, toDate, isLegacy } = request;
+
const params = Object.assign(
{},
{
order: order || 'descending',
+ },
+ !!fromDate && {
+ start: `${moment.utc(fromDate).format('YYYY-MM-DDTHH:mm:ss')}Z`,
+ },
+ !!toDate && {
+ end: `${moment.utc(toDate).format('YYYY-MM-DDTHH:mm:ss')}Z`,
}
);
- if (fromDate)
- // @ts-ignore ts-migrate(2339) FIXME: Property 'start' does not exist on type '{ order: ... Remove this comment to see the full error message
- params.start = `${moment.utc(fromDate).format('YYYY-MM-DDTHH:mm:ss')}Z`;
- if (toDate)
- // @ts-ignore ts-migrate(2339) FIXME: Property 'end' does not exist on type '{ order: "a... Remove this comment to see the full error message
- params.end = `${moment.utc(toDate).format('YYYY-MM-DDTHH:mm:ss')}Z`;
try {
let response;
@@ -832,7 +839,9 @@ export default class AdaApi {
}
};
createTransaction = async (
- request: CreateTransactionRequest
+ request: CreateTransactionRequest & {
+ hasAssetsRemainingAfterTransaction: boolean;
+ }
): Promise => {
logger.debug('AdaApi::createTransaction called', {
parameters: filterLogData(request),
@@ -845,6 +854,7 @@ export default class AdaApi {
isLegacy,
assets,
withdrawal = TransactionWithdrawal,
+ hasAssetsRemainingAfterTransaction,
} = request;
try {
@@ -884,7 +894,8 @@ export default class AdaApi {
logger.error('AdaApi::createTransaction error', {
error,
});
- throw new ApiError(error)
+
+ const apiError = new ApiError(error)
.set('wrongEncryptionPassphrase')
.where('code', 'bad_request')
.inc('message', 'passphrase is too short')
@@ -892,8 +903,18 @@ export default class AdaApi {
linkLabel: 'tooBigTransactionErrorLinkLabel',
linkURL: 'tooBigTransactionErrorLinkURL',
})
- .where('code', 'transaction_is_too_big')
- .result();
+ .where('code', 'transaction_is_too_big');
+
+ const { requiresAdaToRemainToSupportNativeTokens, adaToRemain } =
+ doesWalletRequireAdaToRemainToSupportTokens(
+ error,
+ hasAssetsRemainingAfterTransaction
+ );
+ if (requiresAdaToRemainToSupportNativeTokens) {
+ apiError.set('cannotLeaveWalletEmpty', true, { adaToRemain });
+ }
+
+ throw apiError.result();
}
};
// For testing purpose ONLY
@@ -1020,6 +1041,7 @@ export default class AdaApi {
const { fee, minimumAda } = _createTransactionFeeFromServerData(response);
const amountWithFee = formattedTxAmount.plus(fee);
+ // @ts-ignore ts-migrate(2304) FIXME: Cannot find name 'Array'.
const isRewardsRedemptionRequest = Array.isArray(withdrawal);
if (!isRewardsRedemptionRequest && amountWithFee.gt(walletBalance)) {
@@ -1067,6 +1089,7 @@ export default class AdaApi {
.set(notEnoughMoneyError, true)
.where('code', 'not_enough_money')
.set('utxoTooSmall', true, {
+ // @ts-ignore ts-migrate(2339) FIXME: Property 'exec' does not exist on type '{}'.
minimumAda: get(
/(Expected min coin value: +)([0-9]+.[0-9]+)/.exec(error.message),
2,
@@ -1135,7 +1158,7 @@ export default class AdaApi {
walletId,
data,
});
- // @TODO - handle CHANGE paramete on smarter way and change corresponding downstream logic
+ // @TODO - handle CHANGE parameter on smarter way and change corresponding downstream logic
const outputs = concat(response.outputs, response.change);
// Calculate fee from inputs and outputs
const inputsData = [];
@@ -1145,7 +1168,7 @@ export default class AdaApi {
let totalOutputs = new BigNumber(0);
map(response.inputs, (input) => {
const inputAmount = new BigNumber(input.amount.quantity.toString());
- // @ts-ignore ts-migrate(2339) FIXME: Property 'assets' does not exist on type '{ addres... Remove this comment to see the full error message
+ // @ts-ignore ts-migrate(2339) FIXME: Property 'assets' does not exist on type 'unknown'... Remove this comment to see the full error message
const inputAssets = map(input.assets, (asset) => ({
policyId: asset.policy_id,
assetName: asset.asset_name,
@@ -1160,11 +1183,12 @@ export default class AdaApi {
derivationPath: input.derivation_path,
assets: inputAssets,
};
+ // @ts-ignore ts-migrate(2339) FIXME: Property 'push' does not exist on type '{}'.
inputsData.push(inputData);
});
map(outputs, (output) => {
const outputAmount = new BigNumber(output.amount.quantity.toString());
- // @ts-ignore ts-migrate(2339) FIXME: Property 'assets' does not exist on type '{ addres... Remove this comment to see the full error message
+ // @ts-ignore ts-migrate(2339) FIXME: Property 'assets' does not exist on type 'unknown'... Remove this comment to see the full error message
const outputAssets = map(output.assets, (asset) => ({
policyId: asset.policy_id,
assetName: asset.asset_name,
@@ -1177,6 +1201,7 @@ export default class AdaApi {
derivationPath: output.derivation_path || null,
assets: outputAssets,
};
+ // @ts-ignore ts-migrate(2339) FIXME: Property 'push' does not exist on type '{}'.
outputsData.push(outputData);
});
@@ -1187,6 +1212,7 @@ export default class AdaApi {
rewardAccountPath: certificate.reward_account_path,
pool: certificate.pool || null,
};
+ // @ts-ignore ts-migrate(2339) FIXME: Property 'push' does not exist on type '{}'.
certificatesData.push(certificateData);
});
}
@@ -1454,14 +1480,12 @@ export default class AdaApi {
mnemonic.split(' ').length === ADA_CERTIFICATE_MNEMONIC_LENGTH;
getWalletRecoveryPhrase(): Promise> {
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getWalletRecoveryPhrase called');
try {
const response: Promise> = new Promise((resolve) =>
resolve(generateAccountMnemonics(WALLET_RECOVERY_PHRASE_WORD_COUNT))
);
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getWalletRecoveryPhrase success');
return response;
} catch (error) {
@@ -1473,14 +1497,12 @@ export default class AdaApi {
}
getWalletCertificateAdditionalMnemonics(): Promise> {
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getWalletCertificateAdditionalMnemonics called');
try {
const response: Promise> = new Promise((resolve) =>
resolve(generateAdditionalMnemonics())
);
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getWalletCertificateAdditionalMnemonics success');
return response;
} catch (error) {
@@ -1494,7 +1516,6 @@ export default class AdaApi {
getWalletCertificateRecoveryPhrase(
request: GetWalletCertificateRecoveryPhraseRequest
): Promise> {
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getWalletCertificateRecoveryPhrase called');
const { passphrase, input: scrambledInput } = request;
@@ -1507,7 +1528,6 @@ export default class AdaApi {
})
)
);
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getWalletCertificateRecoveryPhrase success');
return response;
} catch (error) {
@@ -1521,7 +1541,6 @@ export default class AdaApi {
getWalletRecoveryPhraseFromCertificate(
request: GetWalletRecoveryPhraseFromCertificateRequest
): Promise> {
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getWalletRecoveryPhraseFromCertificate called');
const { passphrase, scrambledInput } = request;
@@ -1530,7 +1549,6 @@ export default class AdaApi {
passphrase,
scrambledInput,
});
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getWalletRecoveryPhraseFromCertificate success');
return Promise.resolve(response);
} catch (error) {
@@ -1904,7 +1922,7 @@ export default class AdaApi {
logger.debug('AdaApi::restoreByronLedgerWallet success', {
wallet,
});
- // @ts-ignore ts-migrate(2345) FIXME: Argument of type '{ address_pool_gap: number; dele... Remove this comment to see the full error message
+ // @ts-ignore ts-migrate(2345) FIXME: Argument of type '{ address_pool_gap: number; delegation... Remove this comment to see the full error message
return _createWalletFromServerData(wallet);
} catch (error) {
logger.error('AdaApi::restoreByronLedgerWallet error', {
@@ -2093,7 +2111,6 @@ export default class AdaApi {
});
}
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::updateSpendingPassword success');
return true;
} catch (error) {
@@ -2136,7 +2153,6 @@ export default class AdaApi {
}
};
getSmashSettings = async (): Promise => {
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getSmashSettings called');
try {
@@ -2194,10 +2210,9 @@ export default class AdaApi {
);
if (!isSmashServerValid) {
- const error = {
+ const error: ErrorType = {
code: 'invalid_smash_server',
};
- // @ts-ignore ts-migrate(2345) FIXME: Argument of type '{ code: string; }' is not assign... Remove this comment to see the full error message
throw new ApiError(error);
}
@@ -2322,8 +2337,7 @@ export default class AdaApi {
});
try {
- // @ts-ignore ts-migrate(2322) FIXME: Type '[]' is not assignable to type 'Promise<[]>'.
- const response: Promise<[]> = await exportWalletAsJSON(this.config, {
+ const response: [] = await exportWalletAsJSON(this.config, {
walletId,
filePath,
});
@@ -2469,7 +2483,6 @@ export default class AdaApi {
}
};
testReset = async (): Promise => {
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::testReset called');
try {
@@ -2483,7 +2496,6 @@ export default class AdaApi {
})
)
);
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::testReset success');
} catch (error) {
logger.error('AdaApi::testReset error', {
@@ -2493,7 +2505,6 @@ export default class AdaApi {
}
};
getNetworkInfo = async (): Promise => {
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getNetworkInfo called');
try {
@@ -2554,6 +2565,7 @@ export default class AdaApi {
throw new ApiError(error);
}
};
+ // @ts-ignore ts-migrate(2583) FIXME: Cannot find name 'Promise'. Do you need to change ... Remove this comment to see the full error message
getNetworkClock = async (
isForceCheck: boolean
): Promise => {
@@ -2582,6 +2594,7 @@ export default class AdaApi {
throw new ApiError(error);
}
};
+ // @ts-ignore ts-migrate(2583) FIXME: Cannot find name 'Promise'. Do you need to change ... Remove this comment to see the full error message
getNetworkParameters = async (): Promise => {
// @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getNetworkParameters called');
@@ -2626,7 +2639,6 @@ export default class AdaApi {
}
};
getNews = async (): Promise => {
- // @ts-ignore ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
logger.debug('AdaApi::getNews called');
// Fetch news json
let rawNews: string;
@@ -2919,6 +2931,42 @@ export default class AdaApi {
fakeStakePoolsJson: Array
) => void;
setStakePoolsFetchingFailed: () => void;
+ getCatalystFund = async (): Promise => {
+ logger.debug('AdaApi::getCatalystFund called', {});
+
+ try {
+ const catalystFund = await getCatalystFund();
+
+ logger.debug('AdaApi::getCatalystFund success', {
+ catalystFund,
+ });
+
+ return {
+ current: {
+ number: catalystFund.id + 1,
+ startTime: new Date(catalystFund.fund_start_time),
+ endTime: new Date(catalystFund.fund_end_time),
+ resultsTime: new Date(
+ catalystFund.chain_vote_plans?.[0]?.chain_committee_end_time
+ ),
+ registrationSnapshotTime: new Date(
+ catalystFund.registration_snapshot_time
+ ),
+ },
+ next: {
+ number: catalystFund.id + 2,
+ startTime: new Date(catalystFund.next_fund_start_time),
+ registrationSnapshotTime: new Date(
+ catalystFund.next_registration_snapshot_time
+ ),
+ },
+ };
+ } catch (error) {
+ logger.error('AdaApi::getCatalystFund error', {
+ error,
+ });
+ }
+ };
} // ========== TRANSFORM SERVER DATA INTO FRONTEND MODELS =========
const _createWalletFromServerData = action(
@@ -2984,6 +3032,7 @@ const _createWalletFromServerData = action(
uniqueId,
policyId,
assetName,
+ assetNameASCII: hexToString(assetName),
quantity: new BigNumber(quantity.toString()),
};
}),
@@ -2994,6 +3043,7 @@ const _createWalletFromServerData = action(
uniqueId,
policyId,
assetName,
+ assetNameASCII: hexToString(assetName),
quantity: new BigNumber(quantity.toString()),
};
}),
diff --git a/source/renderer/app/api/assets/types.ts b/source/renderer/app/api/assets/types.ts
index 7c33c9de64..47a2d43f16 100644
--- a/source/renderer/app/api/assets/types.ts
+++ b/source/renderer/app/api/assets/types.ts
@@ -49,6 +49,7 @@ export type ApiTokens = Array;
export type Token = {
policyId: string;
assetName: string;
+ assetNameASCII?: string;
quantity: BigNumber;
address?: string | null | undefined;
uniqueId: string;
diff --git a/source/renderer/app/api/staking/types.ts b/source/renderer/app/api/staking/types.ts
index 1a6729c6b2..eee5b6db55 100644
--- a/source/renderer/app/api/staking/types.ts
+++ b/source/renderer/app/api/staking/types.ts
@@ -56,8 +56,11 @@ export type AdaApiStakePools = Array;
export type Reward = {
date?: string;
wallet: string;
- reward: BigNumber;
+ total: BigNumber;
+ unspent: BigNumber;
rewardsAddress: string;
+ isRestoring: boolean;
+ syncingProgress: number;
pool?: StakePool;
};
export type EpochData = {
diff --git a/source/renderer/app/api/transactions/requests/selectCoins.ts b/source/renderer/app/api/transactions/requests/selectCoins.ts
index 2f50197548..dfdd898023 100644
--- a/source/renderer/app/api/transactions/requests/selectCoins.ts
+++ b/source/renderer/app/api/transactions/requests/selectCoins.ts
@@ -63,8 +63,8 @@ export type SelectCoinsResponseType = {
export const selectCoins = (
config: RequestConfig,
{ walletId, data }: SelectCoinsRequestType
-): Promise =>
- request(
+): Promise => {
+ return request(
{
method: 'POST',
path: `/v2/wallets/${walletId}/coin-selections/random`,
@@ -73,3 +73,4 @@ export const selectCoins = (
{},
data
);
+};
diff --git a/source/renderer/app/api/utils/apiHelpers.spec.ts b/source/renderer/app/api/utils/apiHelpers.spec.ts
new file mode 100644
index 0000000000..07fedfa470
--- /dev/null
+++ b/source/renderer/app/api/utils/apiHelpers.spec.ts
@@ -0,0 +1,76 @@
+import { ErrorType } from '../../domains/ApiError';
+import { doesWalletRequireAdaToRemainToSupportTokens } from './apiHelpers';
+
+describe('throw error if not enough Ada to support tokens', () => {
+ it('should not throw if error.code is not "cannot_cover_fee"', () => {
+ const error: ErrorType = { code: 'bad_request' };
+
+ expect(doesWalletRequireAdaToRemainToSupportTokens(error, true)).toEqual({
+ requiresAdaToRemainToSupportNativeTokens: false,
+ });
+ });
+ it('should not throw error if error code is "cannot_cover_fee" but hasAssetsRemainingAfterTransaction is undefined', () => {
+ const error: ErrorType = {
+ message:
+ 'I cannot proceed with transaction, I need approximately 1.6 ada to proceed',
+ code: 'cannot_cover_fee',
+ };
+
+ expect(doesWalletRequireAdaToRemainToSupportTokens(error)).toEqual({
+ requiresAdaToRemainToSupportNativeTokens: false,
+ });
+ });
+ it('should not throw error if error code is "cannot_cover_fee" but message does not match regex', () => {
+ const error: ErrorType = {
+ message: 'other message',
+ code: 'cannot_cover_fee',
+ };
+
+ expect(doesWalletRequireAdaToRemainToSupportTokens(error, true)).toEqual({
+ requiresAdaToRemainToSupportNativeTokens: false,
+ });
+ });
+ it('should not throw error if error code is not "cannot_cover_fee" and message matches regex', () => {
+ const error: ErrorType = {
+ message:
+ 'I cannot proceed with transaction, I need approximately 1.6 ada to proceed',
+ code: 'bad_request',
+ };
+
+ expect(doesWalletRequireAdaToRemainToSupportTokens(error, true)).toEqual({
+ requiresAdaToRemainToSupportNativeTokens: false,
+ });
+ });
+ it('should not throw if there are no tokens remaining in wallet after transaction', () => {
+ const error: ErrorType = { code: 'cannot_cover_fee' };
+
+ expect(doesWalletRequireAdaToRemainToSupportTokens(error, true)).toEqual({
+ requiresAdaToRemainToSupportNativeTokens: false,
+ });
+ });
+ it('should throw if there are tokens remaining in wallet after transaction and error is "cannot_cover_fee" and round to 2 minimum ada', () => {
+ const error: ErrorType = {
+ message:
+ 'I am unable to finalize the transaction, as there is not enough ada available to pay for the fee and also pay for the minimum ada quantities of all change outputs. I need approximately 0.629344 ada to proceed. Try increasing your wallet balance or sending a smaller amount.',
+ code: 'cannot_cover_fee',
+ };
+
+ expect(doesWalletRequireAdaToRemainToSupportTokens(error, true)).toEqual({
+ requiresAdaToRemainToSupportNativeTokens: true,
+ adaToRemain: 2,
+ });
+ });
+
+ it('should throw if there are tokens remaining in wallet after transaction and error is "cannot_cover_fee" and round to 2 nearest whole value provided by error', () => {
+ const error: ErrorType = {
+ message:
+ 'I am unable to finalize the transaction, as there is not enough ada available to pay for the fee and also pay for the minimum ada quantities of all change outputs. I need approximately 2.629344 ada to proceed. Try increasing your wallet balance or sending a smaller amount.',
+ code: 'cannot_cover_fee',
+ };
+
+ expect(doesWalletRequireAdaToRemainToSupportTokens(error, true)).toEqual({
+ requiresAdaToRemainToSupportNativeTokens: true,
+ adaToRemain: 3,
+ });
+ });
+});
diff --git a/source/renderer/app/api/utils/apiHelpers.ts b/source/renderer/app/api/utils/apiHelpers.ts
index 8e20197929..85f51f2927 100644
--- a/source/renderer/app/api/utils/apiHelpers.ts
+++ b/source/renderer/app/api/utils/apiHelpers.ts
@@ -1,4 +1,5 @@
import { ApiMethodNotYetImplementedError } from '../common/errors';
+import { ErrorType } from '../../domains/ApiError';
export const notYetImplemented = async () =>
new Promise((resolve, reject) => {
@@ -21,3 +22,27 @@ export const testSync = (apiMethod: (...args: Array) => any) => {
// helper code for deferring API call execution
export const wait = (ms: number): Promise =>
new Promise((resolve) => setTimeout(resolve, ms));
+export const doesWalletRequireAdaToRemainToSupportTokens = (
+ error: ErrorType,
+ hasAssetsRemainingAfterTransaction?: boolean
+): {
+ requiresAdaToRemainToSupportNativeTokens: boolean;
+ adaToRemain?: number;
+} => {
+ const adaToProceedRegex = new RegExp(
+ /.*I need approximately([\s\d.,]+)ada to proceed.*/
+ );
+
+ if (
+ error.code === 'cannot_cover_fee' &&
+ hasAssetsRemainingAfterTransaction &&
+ adaToProceedRegex.test(error.message)
+ ) {
+ const roundedAda = Math.ceil(
+ Number(error.message.replace(adaToProceedRegex, '$1'))
+ );
+ const adaToRemain = roundedAda > 2 ? roundedAda : 2;
+ return { requiresAdaToRemainToSupportNativeTokens: true, adaToRemain };
+ }
+ return { requiresAdaToRemainToSupportNativeTokens: false };
+};
diff --git a/source/renderer/app/api/utils/localStorage.ts b/source/renderer/app/api/utils/localStorage.ts
index 70bf003c15..4951c37aba 100644
--- a/source/renderer/app/api/utils/localStorage.ts
+++ b/source/renderer/app/api/utils/localStorage.ts
@@ -306,12 +306,6 @@ export default class LocalStorageApi {
assetLocalData,
`${policyId}${assetName}`
);
- getAssetSettingsDialogWasOpened = (): Promise =>
- LocalStorageApi.get(keys.ASSET_SETTINGS_DIALOG_WAS_OPENED, false);
- setAssetSettingsDialogWasOpened = (): Promise =>
- LocalStorageApi.set(keys.ASSET_SETTINGS_DIALOG_WAS_OPENED, true);
- unsetAssetSettingsDialogWasOpened = (): Promise =>
- LocalStorageApi.unset(keys.ASSET_SETTINGS_DIALOG_WAS_OPENED);
getSmashServer = (): Promise =>
LocalStorageApi.get(keys.SMASH_SERVER);
setSmashServer = (smashServerUrl: string): Promise =>
@@ -404,6 +398,12 @@ export default class LocalStorageApi {
LocalStorageApi.unset(keys.HARDWARE_WALLET_DEVICES, deviceId);
unsetHardwareWalletDevicesAll = async (): Promise =>
LocalStorageApi.unset(keys.HARDWARE_WALLET_DEVICES);
+ setStakePoolsListViewTooltip = async (visited: boolean): Promise =>
+ LocalStorageApi.set(keys.STAKE_POOLS_LIST_VIEW_TOOLTIP, visited);
+ getStakePoolsListViewTooltip = async (): Promise =>
+ LocalStorageApi.get(keys.STAKE_POOLS_LIST_VIEW_TOOLTIP, true);
+ unsetStakePoolsListViewTooltip = async (): Promise =>
+ LocalStorageApi.unset(keys.STAKE_POOLS_LIST_VIEW_TOOLTIP);
reset = async () => {
await LocalStorageApi.reset();
};
diff --git a/source/renderer/app/api/utils/patchAdaApi.ts b/source/renderer/app/api/utils/patchAdaApi.ts
index 313e017011..b25bfeaede 100644
--- a/source/renderer/app/api/utils/patchAdaApi.ts
+++ b/source/renderer/app/api/utils/patchAdaApi.ts
@@ -86,24 +86,29 @@ export default (api: AdaApi) => {
}
// Always mutate newsfeed target version to current app version
- const newsFeedItems = map(testingNewsFeedData.items, (item) => ({
- ...item,
- target: {
- ...item.target,
- daedalusVersion: item.target.daedalusVersion ? packageJsonVersion : '',
- },
- }));
+ const newsFeedItems = map(testingNewsFeedData.items, (item) => {
+ return {
+ ...item,
+ target: {
+ ...item.target,
+ daedalusVersion: item.target.daedalusVersion
+ ? packageJsonVersion
+ : '',
+ },
+ };
+ });
TESTING_NEWSFEED_JSON = { ...testingNewsFeedData, items: newsFeedItems };
};
- api.getNews = (): Promise =>
- new Promise((resolve, reject) => {
+ api.getNews = (): Promise => {
+ return new Promise((resolve, reject) => {
if (!TESTING_NEWSFEED_JSON) {
reject(new Error('Unable to fetch news'));
} else {
resolve(TESTING_NEWSFEED_JSON);
}
});
+ };
api.setTestingWallet = (
testingWalletData: Record,
@@ -155,10 +160,12 @@ export default (api: AdaApi) => {
LOCAL_TIME_DIFFERENCE = timeDifference;
};
- api.getNetworkClock = async () => ({
- status: 'available',
- offset: LOCAL_TIME_DIFFERENCE,
- });
+ api.getNetworkClock = async () => {
+ return {
+ status: 'available',
+ offset: LOCAL_TIME_DIFFERENCE,
+ };
+ };
api.resetTestOverrides = () => {
TESTING_WALLETS_DATA = {};
diff --git a/source/renderer/app/api/utils/requestV0.ts b/source/renderer/app/api/utils/requestV0.ts
index 32db8fa75c..fae10c3225 100644
--- a/source/renderer/app/api/utils/requestV0.ts
+++ b/source/renderer/app/api/utils/requestV0.ts
@@ -39,7 +39,7 @@ function typedRequest(
queryString = `?passphrase=${encryptedPassphrase}`;
}
- // Passphrase must be ommited from rest query params
+ // Passphrase must be omitted from rest query params
queryParams = omit(queryParams, 'passphrase');
// @ts-ignore ts-migrate(2345) FIXME: Argument of type 'boolean' is not assignable to pa... Remove this comment to see the full error message
diff --git a/source/renderer/app/api/voting/requests/getCatalystFund.ts b/source/renderer/app/api/voting/requests/getCatalystFund.ts
new file mode 100644
index 0000000000..dd0efc55cd
--- /dev/null
+++ b/source/renderer/app/api/voting/requests/getCatalystFund.ts
@@ -0,0 +1,11 @@
+import { externalRequest } from '../../utils/externalRequest';
+import { MAINNET_SERVICING_STATION_URL } from '../../../config/urlsConfig';
+import { GetCatalystFundResponse } from '../types';
+
+export const getCatalystFund = (): Promise =>
+ externalRequest({
+ hostname: MAINNET_SERVICING_STATION_URL,
+ path: '/api/v0/fund',
+ method: 'GET',
+ protocol: 'https',
+ });
diff --git a/source/renderer/app/api/voting/types.ts b/source/renderer/app/api/voting/types.ts
index 288409ff2d..ab15db9d65 100644
--- a/source/renderer/app/api/voting/types.ts
+++ b/source/renderer/app/api/voting/types.ts
@@ -27,3 +27,29 @@ export type SignatureParams = {
passphrase: string;
};
};
+export type GetCatalystFundResponse = {
+ id: number;
+ fund_end_time: string;
+ fund_name: string;
+ fund_start_time: string;
+ next_fund_start_time: string;
+ next_registration_snapshot_time: string;
+ registration_snapshot_time: string;
+ chain_vote_plans: Array<{
+ chain_committee_end_time: string;
+ }>;
+};
+export type CatalystFund = {
+ current: {
+ number: number;
+ startTime: Date;
+ endTime: Date;
+ resultsTime: Date;
+ registrationSnapshotTime: Date;
+ };
+ next: {
+ number: number;
+ startTime: Date;
+ registrationSnapshotTime: Date;
+ };
+};
diff --git a/source/renderer/app/api/wallets/requests/createHardwareWallet.ts b/source/renderer/app/api/wallets/requests/createHardwareWallet.ts
index 270ccf5241..8318736118 100644
--- a/source/renderer/app/api/wallets/requests/createHardwareWallet.ts
+++ b/source/renderer/app/api/wallets/requests/createHardwareWallet.ts
@@ -13,8 +13,8 @@ export const createHardwareWallet = (
}: {
walletInitData: WalletInitData;
}
-): Promise =>
- request(
+): Promise => {
+ return request(
{
method: 'POST',
path: '/v2/wallets',
@@ -23,3 +23,4 @@ export const createHardwareWallet = (
{},
walletInitData
);
+};
diff --git a/source/renderer/app/assets/images/check-mark-universal.inline.svg b/source/renderer/app/assets/images/check-mark-universal.inline.svg
new file mode 100644
index 0000000000..9def2a6cc5
--- /dev/null
+++ b/source/renderer/app/assets/images/check-mark-universal.inline.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/source/renderer/app/assets/images/question-mark-universal.inline.svg b/source/renderer/app/assets/images/question-mark-universal.inline.svg
new file mode 100644
index 0000000000..f764a39b03
--- /dev/null
+++ b/source/renderer/app/assets/images/question-mark-universal.inline.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/source/renderer/app/assets/images/remove.inline.svg b/source/renderer/app/assets/images/remove.inline.svg
new file mode 100644
index 0000000000..89d76e64ba
--- /dev/null
+++ b/source/renderer/app/assets/images/remove.inline.svg
@@ -0,0 +1,3 @@
+
diff --git a/source/renderer/app/assets/images/search.inline.svg b/source/renderer/app/assets/images/search.inline.svg
index 0304c9c043..f83eb9153d 100644
--- a/source/renderer/app/assets/images/search.inline.svg
+++ b/source/renderer/app/assets/images/search.inline.svg
@@ -1,7 +1,7 @@