Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| da0ae9cd94 | |||
| 528a810690 | |||
| 0c74dae4e8 | |||
| d42d440f85 | |||
| 0c262a4811 | |||
| 0603018f09 | |||
| 677b6de0f8 | |||
| 27f965ef63 | |||
| e72347d87a | |||
| 0260df61de | |||
| e986d7ca22 | |||
| df925b013b |
@@ -19,9 +19,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
REACT_APP_BEE_HOST: https://api.test-node.staging.ethswarm.org/
|
REACT_APP_BEE_HOST: https://api.test-node.staging.ethswarm.org/
|
||||||
REACT_APP_BEE_DEBUG_HOST: https://debug.test-node.staging.ethswarm.org/
|
REACT_APP_BEE_DEBUG_HOST: https://debug.test-node.staging.ethswarm.org/
|
||||||
REACT_APP_DEV_MODE: 1
|
|
||||||
REACT_APP_SENTRY_KEY: ${{ secrets.SENTRY_KEY }}
|
|
||||||
REACT_APP_SENTRY_ENVIRONMENT: 'preview'
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -60,9 +57,6 @@ jobs:
|
|||||||
- name: Types check
|
- name: Types check
|
||||||
run: npm run check:types
|
run: npm run check:types
|
||||||
|
|
||||||
- name: Types build
|
|
||||||
run: npm run compile:types
|
|
||||||
|
|
||||||
- name: Update supported Bee action
|
- name: Update supported Bee action
|
||||||
uses: ethersphere/update-supported-bee-action@v1
|
uses: ethersphere/update-supported-bee-action@v1
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.ref == 'refs/heads/master'
|
||||||
|
|||||||
@@ -15,20 +15,6 @@ jobs:
|
|||||||
node-version: 18
|
node-version: 18
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run compile:types
|
|
||||||
- run: npm publish --access public
|
- run: npm publish --access public
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||||
- id: cleanVersion
|
|
||||||
run: |
|
|
||||||
version="${{ github.event.release.release.tag_name }}"
|
|
||||||
echo "::set-output name=value::${version/v}"
|
|
||||||
- name: Create Sentry release
|
|
||||||
uses: getsentry/action-release@v1
|
|
||||||
env:
|
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
||||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
|
||||||
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
|
||||||
with:
|
|
||||||
sourcemaps: ./build/static/js
|
|
||||||
version: ${{ steps.cleanVersion.outputs.value }}
|
|
||||||
|
|||||||
@@ -17,9 +17,6 @@ jobs:
|
|||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
env:
|
|
||||||
REACT_APP_SENTRY_KEY: ${{ secrets.SENTRY_KEY }}
|
|
||||||
REACT_APP_SENTRY_ENVIRONMENT: 'pages'
|
|
||||||
- run: echo "dashboard.ethswarm.org" > ./build/CNAME
|
- run: echo "dashboard.ethswarm.org" > ./build/CNAME
|
||||||
- name: Deploy to gh-pages
|
- name: Deploy to gh-pages
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
|
|||||||
@@ -1,5 +1,38 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.20.0](https://github.com/ethersphere/bee-dashboard/compare/v0.19.3...v0.20.0) (2022-09-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* error reporting callback ([#530](https://github.com/ethersphere/bee-dashboard/issues/530)) ([0c74dae](https://github.com/ethersphere/bee-dashboard/commit/0c74dae4e88916cf54c3c0500b37203b865e48a7))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* show update notifications only on non-auto-updating Swarm Desktops ([#543](https://github.com/ethersphere/bee-dashboard/issues/543)) ([528a810](https://github.com/ethersphere/bee-dashboard/commit/528a8106907ef176bcdb68b3386c2f3f9ea98a47))
|
||||||
|
|
||||||
|
## [0.19.3](https://github.com/ethersphere/bee-dashboard/compare/v0.19.2...v0.19.3) (2022-08-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* pass isBeeDesktop from provider to hook ([#525](https://github.com/ethersphere/bee-dashboard/issues/525)) ([677b6de](https://github.com/ethersphere/bee-dashboard/commit/677b6de0f82b02e1487420e3c08fbd19a949f97b))
|
||||||
|
|
||||||
|
## [0.19.2](https://github.com/ethersphere/bee-dashboard/compare/v0.19.1...v0.19.2) (2022-08-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* remove sentry ([#520](https://github.com/ethersphere/bee-dashboard/issues/520)) ([0260df6](https://github.com/ethersphere/bee-dashboard/commit/0260df61de0619202a819b79820cfbef6e3757ae))
|
||||||
|
|
||||||
|
## [0.19.1](https://github.com/ethersphere/bee-dashboard/compare/v0.19.0...v0.19.1) (2022-08-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* compile types when building the library ([#516](https://github.com/ethersphere/bee-dashboard/issues/516)) ([df925b0](https://github.com/ethersphere/bee-dashboard/commit/df925b013bb02a16d308a86050ec8e0e0e361ff7))
|
||||||
|
|
||||||
## [0.19.0](https://github.com/ethersphere/bee-dashboard/compare/v0.18.2...v0.19.0) (2022-08-03)
|
## [0.19.0](https://github.com/ethersphere/bee-dashboard/compare/v0.18.2...v0.19.0) (2022-08-03)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,15 @@ npm start
|
|||||||
|
|
||||||
The Bee Dashboard runs in development mode on [http://localhost:3031/](http://localhost:3031/)
|
The Bee Dashboard runs in development mode on [http://localhost:3031/](http://localhost:3031/)
|
||||||
|
|
||||||
> Setting the `REACT_APP_DEV_MODE=1` environment variable, or opening Bee Dashboard with the query string `?devMode=1` loosens some checks. This makes it possible to develop Bee Dashboard without having connected peers and chequebook properly set up, effectively supporting the dev mode of Bee itself.
|
#### Environmental variables
|
||||||
|
|
||||||
|
The CRA supports to specify "environmental variables" during build time which are then hardcoded into the served static files.
|
||||||
|
We support following variables:
|
||||||
|
|
||||||
|
- `REACT_APP_BEE_DESKTOP_ENABLED` (`boolean`) that toggles if the Dashboard is in Desktop mode or not.
|
||||||
|
- `REACT_APP_BEE_DESKTOP_URL` (`string`) defines custom URL where the Desktop API is expected. By default, it is same origin under which the Dashboard is served.
|
||||||
|
- `REACT_APP_BEE_API_URL` (`string`) defines custom Bee API URL to be used as default one. By default, the `http://localhost:1633` is used.
|
||||||
|
- `REACT_APP_BEE_DEBUG_API_URL` (`string`) defines custom Bee Debug API URL to be used as default one. By default, the `http://localhost:1635` is used.
|
||||||
|
|
||||||
#### Swarm Desktop development
|
#### Swarm Desktop development
|
||||||
|
|
||||||
|
|||||||
Generated
+11
-175
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@ethersphere/bee-dashboard",
|
"name": "@ethersphere/bee-dashboard",
|
||||||
"version": "0.19.0",
|
"version": "0.20.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@ethersphere/bee-dashboard",
|
"name": "@ethersphere/bee-dashboard",
|
||||||
"version": "0.19.0",
|
"version": "0.20.0",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ethersphere/bee-js": "^5.0.0",
|
"@ethersphere/bee-js": "^5.0.0",
|
||||||
@@ -15,8 +15,6 @@
|
|||||||
"@material-ui/core": "4.12.3",
|
"@material-ui/core": "4.12.3",
|
||||||
"@material-ui/icons": "4.11.2",
|
"@material-ui/icons": "4.11.2",
|
||||||
"@material-ui/lab": "4.0.0-alpha.57",
|
"@material-ui/lab": "4.0.0-alpha.57",
|
||||||
"@sentry/react": "^7.1.1",
|
|
||||||
"@sentry/tracing": "^7.1.1",
|
|
||||||
"assert": "^2.0.0",
|
"assert": "^2.0.0",
|
||||||
"axios": "0.24.0",
|
"axios": "0.24.0",
|
||||||
"bignumber.js": "9.0.1",
|
"bignumber.js": "9.0.1",
|
||||||
@@ -65,9 +63,9 @@
|
|||||||
"@types/file-saver": "2.0.4",
|
"@types/file-saver": "2.0.4",
|
||||||
"@types/jest": "27.0.2",
|
"@types/jest": "27.0.2",
|
||||||
"@types/qrcode.react": "1.0.2",
|
"@types/qrcode.react": "1.0.2",
|
||||||
"@types/react": ">=17.0.0 || >=18.0.0",
|
"@types/react": "17.0.34",
|
||||||
"@types/react-copy-to-clipboard": "5.0.2",
|
"@types/react-copy-to-clipboard": "5.0.2",
|
||||||
"@types/react-dom": ">=17.0.0 || >=18.0.0",
|
"@types/react-dom": "17.0.11",
|
||||||
"@types/react-router": "5.1.18",
|
"@types/react-router": "5.1.18",
|
||||||
"@types/react-router-dom": "5.3.2",
|
"@types/react-router-dom": "5.3.2",
|
||||||
"@types/react-syntax-highlighter": "13.5.2",
|
"@types/react-syntax-highlighter": "13.5.2",
|
||||||
@@ -101,7 +99,7 @@
|
|||||||
"react-scripts": "^5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"ts-node": "^10.8.1",
|
"ts-node": "^10.8.1",
|
||||||
"typescript": "4.7.3",
|
"typescript": "4.8.2",
|
||||||
"web-vitals": "2.1.2",
|
"web-vitals": "2.1.2",
|
||||||
"webpack": "^5.73.0",
|
"webpack": "^5.73.0",
|
||||||
"webpack-cli": "^4.10.0"
|
"webpack-cli": "^4.10.0"
|
||||||
@@ -4183,99 +4181,6 @@
|
|||||||
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==",
|
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/browser": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-5AQvStZ+nOP/yxsBmeMZpeGLVtuOgnCNvswKd/c1CJwNw7bDmCE4TQeNKp1C3Gb7lSdBk8ViwUKn0ZpoVQ5MTw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@sentry/core": "7.1.1",
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"@sentry/utils": "7.1.1",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@sentry/core": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-SADdAoG5u1LTJhPN5KPtn5HHmH6r0mr6h2LokuZnhj6/okrAuCIIKOb6Fh8jV7j2VuABvew8+FjJHORxi7D/3Q==",
|
|
||||||
"dependencies": {
|
|
||||||
"@sentry/hub": "7.1.1",
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"@sentry/utils": "7.1.1",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@sentry/hub": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-ASsRVjYDIii6ZTf36JnIYKHWBQBk0P42Tgq324MpyPgaeVDg3saBcyXO5iAtWvY6Vmdi2H4JCVDoir2Zz3Me1w==",
|
|
||||||
"dependencies": {
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"@sentry/utils": "7.1.1",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@sentry/react": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-Z7cZvXHIWxg7OhOSy4InhrRgQPRNtHsyOkIAHkgwW32JYOGTg1HdqQ5mFUxQLejhU/YqsxVjTK4CI58FATykLw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@sentry/browser": "7.1.1",
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"@sentry/utils": "7.1.1",
|
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "15.x || 16.x || 17.x || 18.x"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@sentry/tracing": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-MJ+EPGfvPlgbJOcZRoIl6+Oi0oRE2nIi/HP2BPJSKGxXFi2Y09bcZUwfxOH8fkUa465jOGBFdCm+sXcbyExvuw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@sentry/hub": "7.1.1",
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"@sentry/utils": "7.1.1",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@sentry/types": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-5N1UMd2SqvUXprcIUMyDEju3H9lJY2oWfWQBGo0lG6Amn/lGAPAYlchg+4vQCLutDQMyd8K9zPwcbKn4u6gHdw==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@sentry/utils": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-DPRHDf3InfyVgmxToE4Z+AATAR4OVm+wsXDLFGGyncR91CE1x4wLQKOcAJJwX3F0Hz1VHENfmx1DvyYTHOrC/A==",
|
|
||||||
"dependencies": {
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@sinclair/typebox": {
|
"node_modules/@sinclair/typebox": {
|
||||||
"version": "0.23.5",
|
"version": "0.23.5",
|
||||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz",
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz",
|
||||||
@@ -19505,9 +19410,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "4.7.3",
|
"version": "4.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz",
|
||||||
"integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==",
|
"integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
@@ -23578,75 +23483,6 @@
|
|||||||
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==",
|
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@sentry/browser": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-5AQvStZ+nOP/yxsBmeMZpeGLVtuOgnCNvswKd/c1CJwNw7bDmCE4TQeNKp1C3Gb7lSdBk8ViwUKn0ZpoVQ5MTw==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/core": "7.1.1",
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"@sentry/utils": "7.1.1",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/core": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-SADdAoG5u1LTJhPN5KPtn5HHmH6r0mr6h2LokuZnhj6/okrAuCIIKOb6Fh8jV7j2VuABvew8+FjJHORxi7D/3Q==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/hub": "7.1.1",
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"@sentry/utils": "7.1.1",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/hub": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-ASsRVjYDIii6ZTf36JnIYKHWBQBk0P42Tgq324MpyPgaeVDg3saBcyXO5iAtWvY6Vmdi2H4JCVDoir2Zz3Me1w==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"@sentry/utils": "7.1.1",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/react": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-Z7cZvXHIWxg7OhOSy4InhrRgQPRNtHsyOkIAHkgwW32JYOGTg1HdqQ5mFUxQLejhU/YqsxVjTK4CI58FATykLw==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/browser": "7.1.1",
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"@sentry/utils": "7.1.1",
|
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/tracing": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-MJ+EPGfvPlgbJOcZRoIl6+Oi0oRE2nIi/HP2BPJSKGxXFi2Y09bcZUwfxOH8fkUa465jOGBFdCm+sXcbyExvuw==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/hub": "7.1.1",
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"@sentry/utils": "7.1.1",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sentry/types": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-5N1UMd2SqvUXprcIUMyDEju3H9lJY2oWfWQBGo0lG6Amn/lGAPAYlchg+4vQCLutDQMyd8K9zPwcbKn4u6gHdw=="
|
|
||||||
},
|
|
||||||
"@sentry/utils": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-DPRHDf3InfyVgmxToE4Z+AATAR4OVm+wsXDLFGGyncR91CE1x4wLQKOcAJJwX3F0Hz1VHENfmx1DvyYTHOrC/A==",
|
|
||||||
"requires": {
|
|
||||||
"@sentry/types": "7.1.1",
|
|
||||||
"tslib": "^1.9.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@sinclair/typebox": {
|
"@sinclair/typebox": {
|
||||||
"version": "0.23.5",
|
"version": "0.23.5",
|
||||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz",
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz",
|
||||||
@@ -35074,9 +34910,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "4.7.3",
|
"version": "4.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz",
|
||||||
"integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==",
|
"integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"unbox-primitive": {
|
"unbox-primitive": {
|
||||||
|
|||||||
+3
-5
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ethersphere/bee-dashboard",
|
"name": "@ethersphere/bee-dashboard",
|
||||||
"version": "0.19.0",
|
"version": "0.20.0",
|
||||||
"description": "An app which helps users to setup their Bee node and do actions like cash out cheques",
|
"description": "An app which helps users to setup their Bee node and do actions like cash out cheques",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"bee",
|
"bee",
|
||||||
@@ -32,8 +32,6 @@
|
|||||||
"@material-ui/core": "4.12.3",
|
"@material-ui/core": "4.12.3",
|
||||||
"@material-ui/icons": "4.11.2",
|
"@material-ui/icons": "4.11.2",
|
||||||
"@material-ui/lab": "4.0.0-alpha.57",
|
"@material-ui/lab": "4.0.0-alpha.57",
|
||||||
"@sentry/react": "^7.1.1",
|
|
||||||
"@sentry/tracing": "^7.1.1",
|
|
||||||
"assert": "^2.0.0",
|
"assert": "^2.0.0",
|
||||||
"axios": "0.24.0",
|
"axios": "0.24.0",
|
||||||
"bignumber.js": "9.0.1",
|
"bignumber.js": "9.0.1",
|
||||||
@@ -115,7 +113,7 @@
|
|||||||
"react-scripts": "^5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"ts-node": "^10.8.1",
|
"ts-node": "^10.8.1",
|
||||||
"typescript": "4.7.3",
|
"typescript": "4.8.2",
|
||||||
"web-vitals": "2.1.2",
|
"web-vitals": "2.1.2",
|
||||||
"webpack": "^5.73.0",
|
"webpack": "^5.73.0",
|
||||||
"webpack-cli": "^4.10.0"
|
"webpack-cli": "^4.10.0"
|
||||||
@@ -129,7 +127,7 @@
|
|||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
"desktop": "node ./desktop.mjs",
|
"desktop": "node ./desktop.mjs",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
"build:component": "rimraf ./lib && webpack --mode=production",
|
"build:component": "rimraf ./lib && webpack --mode=production && npm run compile:types",
|
||||||
"compile:types": "tsc --project tsconfig.lib.json --emitDeclarationOnly --declaration",
|
"compile:types": "tsc --project tsconfig.lib.json --emitDeclarationOnly --declaration",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test",
|
||||||
"test:ui": "node ui-test/index.js",
|
"test:ui": "node ui-test/index.js",
|
||||||
|
|||||||
+14
-25
@@ -3,7 +3,6 @@ import { ThemeProvider } from '@material-ui/core/styles'
|
|||||||
import { SnackbarProvider } from 'notistack'
|
import { SnackbarProvider } from 'notistack'
|
||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { HashRouter as Router } from 'react-router-dom'
|
import { HashRouter as Router } from 'react-router-dom'
|
||||||
import * as Sentry from '@sentry/react'
|
|
||||||
import './App.css'
|
import './App.css'
|
||||||
import Dashboard from './layout/Dashboard'
|
import Dashboard from './layout/Dashboard'
|
||||||
import { Provider as BeeProvider } from './providers/Bee'
|
import { Provider as BeeProvider } from './providers/Bee'
|
||||||
@@ -16,23 +15,24 @@ import { Provider as TopUpProvider } from './providers/TopUp'
|
|||||||
import { Provider as BalanceProvider } from './providers/WalletBalance'
|
import { Provider as BalanceProvider } from './providers/WalletBalance'
|
||||||
import BaseRouter from './routes'
|
import BaseRouter from './routes'
|
||||||
import { theme } from './theme'
|
import { theme } from './theme'
|
||||||
import { config } from './config'
|
|
||||||
import ItsBroken from './layout/ItsBroken'
|
|
||||||
import { initSentry } from './utils/sentry'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
beeApiUrl?: string
|
beeApiUrl?: string
|
||||||
beeDebugApiUrl?: string
|
beeDebugApiUrl?: string
|
||||||
lockedApiSettings?: boolean
|
lockedApiSettings?: boolean
|
||||||
isBeeDesktop?: boolean
|
isDesktop?: boolean
|
||||||
|
desktopUrl?: string
|
||||||
|
errorReporting?: (err: Error) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.SENTRY_KEY) {
|
const App = ({
|
||||||
// eslint-disable-next-line no-console
|
beeApiUrl,
|
||||||
initSentry().catch(e => console.error(e))
|
beeDebugApiUrl,
|
||||||
}
|
lockedApiSettings,
|
||||||
|
isDesktop,
|
||||||
const App = ({ beeApiUrl, beeDebugApiUrl, lockedApiSettings, isBeeDesktop }: Props): ReactElement => {
|
desktopUrl,
|
||||||
|
errorReporting,
|
||||||
|
}: Props): ReactElement => {
|
||||||
const mainApp = (
|
const mainApp = (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
@@ -40,7 +40,8 @@ const App = ({ beeApiUrl, beeDebugApiUrl, lockedApiSettings, isBeeDesktop }: Pro
|
|||||||
beeApiUrl={beeApiUrl}
|
beeApiUrl={beeApiUrl}
|
||||||
beeDebugApiUrl={beeDebugApiUrl}
|
beeDebugApiUrl={beeDebugApiUrl}
|
||||||
lockedApiSettings={lockedApiSettings}
|
lockedApiSettings={lockedApiSettings}
|
||||||
isBeeDesktop={isBeeDesktop}
|
isDesktop={isDesktop}
|
||||||
|
desktopUrl={desktopUrl}
|
||||||
>
|
>
|
||||||
<TopUpProvider>
|
<TopUpProvider>
|
||||||
<BeeProvider>
|
<BeeProvider>
|
||||||
@@ -53,7 +54,7 @@ const App = ({ beeApiUrl, beeDebugApiUrl, lockedApiSettings, isBeeDesktop }: Pro
|
|||||||
<Router>
|
<Router>
|
||||||
<>
|
<>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<Dashboard>
|
<Dashboard errorReporting={errorReporting}>
|
||||||
<BaseRouter />
|
<BaseRouter />
|
||||||
</Dashboard>
|
</Dashboard>
|
||||||
</>
|
</>
|
||||||
@@ -71,18 +72,6 @@ const App = ({ beeApiUrl, beeDebugApiUrl, lockedApiSettings, isBeeDesktop }: Pro
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
// Displays Report Dialog when some component crashes
|
|
||||||
if (config.SENTRY_KEY) {
|
|
||||||
return (
|
|
||||||
<Sentry.ErrorBoundary
|
|
||||||
showDialog
|
|
||||||
fallback={({ error, componentStack, resetError }) => <ItsBroken message={error.message} />}
|
|
||||||
>
|
|
||||||
{mainApp}
|
|
||||||
</Sentry.ErrorBoundary>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return mainApp
|
return mainApp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Component, ErrorInfo, ReactElement } from 'react'
|
import { Component, ErrorInfo, ReactElement } from 'react'
|
||||||
import ItsBroken from '../layout/ItsBroken'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: ReactElement
|
children: ReactElement
|
||||||
|
errorReporting?: (err: Error) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
@@ -10,8 +10,11 @@ interface State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class ErrorBoundary extends Component<Props, State> {
|
export default class ErrorBoundary extends Component<Props, State> {
|
||||||
|
private errorReporting?: (err: Error) => void
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
this.errorReporting = props.errorReporting
|
||||||
this.state = { error: null }
|
this.state = { error: null }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,13 +24,17 @@ export default class ErrorBoundary extends Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
||||||
// You can also log the error to an error reporting service
|
if (this.errorReporting) {
|
||||||
|
this.errorReporting(error)
|
||||||
|
}
|
||||||
|
|
||||||
console.error({ error, errorInfo }) // eslint-disable-line
|
console.error({ error, errorInfo }) // eslint-disable-line
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): ReactElement {
|
render(): ReactElement {
|
||||||
if (this.state.error) {
|
if (this.state.error) {
|
||||||
return <ItsBroken message={this.state.error.message} />
|
// You can render any custom fallback UI
|
||||||
|
return <h1>Something went wrong. Error: {this.state.error.message}</h1>
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.props.children
|
return this.props.children
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Typography } from '@material-ui/core/'
|
import { Typography } from '@material-ui/core/'
|
||||||
import { ReactElement } from 'react'
|
import { ReactElement } from 'react'
|
||||||
import Identicon from 'react-identicons'
|
import Identicon from 'react-identicons'
|
||||||
import { config } from '../config'
|
|
||||||
import ClipboardCopy from './ClipboardCopy'
|
import ClipboardCopy from './ClipboardCopy'
|
||||||
import QRCodeModal from './QRCodeModal'
|
import QRCodeModal from './QRCodeModal'
|
||||||
|
import { BLOCKCHAIN_EXPLORER_URL } from '../constants'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
address: string | undefined
|
address: string | undefined
|
||||||
@@ -36,7 +36,7 @@ export default function EthereumAddress(props: Props): ReactElement {
|
|||||||
}
|
}
|
||||||
: { marginRight: '7px' }
|
: { marginRight: '7px' }
|
||||||
}
|
}
|
||||||
href={`${config.BLOCKCHAIN_EXPLORER_URL}/${props.transaction ? 'tx' : 'address'}/${props.address}`}
|
href={`${BLOCKCHAIN_EXPLORER_URL}/${props.transaction ? 'tx' : 'address'}/${props.address}`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
import { ReactElement, useEffect, useState } from 'react'
|
|
||||||
import * as Sentry from '@sentry/react'
|
|
||||||
import { Link } from '@material-ui/core'
|
|
||||||
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
|
|
||||||
import MessageSquare from 'remixicon-react/Message2LineIcon'
|
|
||||||
|
|
||||||
import config from '../config'
|
|
||||||
import SideBarItem from './SideBarItem'
|
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
|
||||||
createStyles({
|
|
||||||
link: {
|
|
||||||
color: '#9f9f9f',
|
|
||||||
textDecoration: 'none',
|
|
||||||
'&:hover': {
|
|
||||||
textDecoration: 'none',
|
|
||||||
|
|
||||||
// https://github.com/mui-org/material-ui/issues/22543
|
|
||||||
'@media (hover: none)': {
|
|
||||||
textDecoration: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
icon: {
|
|
||||||
height: theme.spacing(4),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses Sentry DNS so it could be transformed into API call
|
|
||||||
* Sentry DNS like https://1asfasdf2312asdf3@o132123.ingest.sentry.io/13123123
|
|
||||||
*/
|
|
||||||
const SENTRY_PARSING_REGEX = /^https:\/\/(?<key>\w+)@(?<sub>\w+)\.ingest\.sentry\.io\/(?<path>\d+)$/gm
|
|
||||||
|
|
||||||
async function isSentryReachable(): Promise<boolean> {
|
|
||||||
const key = config.SENTRY_KEY
|
|
||||||
|
|
||||||
if (!key) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const match = SENTRY_PARSING_REGEX.exec(key)
|
|
||||||
|
|
||||||
if (!match) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = `https://${match.groups?.sub}.ingest.sentry.io/api/${match.groups?.path}/envelope/?sentry_key=${match.groups?.key}`
|
|
||||||
|
|
||||||
try {
|
|
||||||
await fetch(url, { method: 'POST' })
|
|
||||||
|
|
||||||
// Since we got some reply (even though most probably with some error) that means Sentry is reachable ==> lets provide the Feedback form
|
|
||||||
return true
|
|
||||||
} catch (e) {
|
|
||||||
// If an error was thrown than the request was blocked by the browser so Sentry is not accessible to us
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showFeedbackForm(): void {
|
|
||||||
const eventId = Sentry.captureMessage('User feedback')
|
|
||||||
Sentry.showReportDialog({
|
|
||||||
eventId,
|
|
||||||
title: 'Provide us feedback!',
|
|
||||||
subtitle: 'Share with us what you like and/or dislike.',
|
|
||||||
subtitle2: 'We will be very happy.',
|
|
||||||
labelComments: 'What is your impression about this app?',
|
|
||||||
labelSubmit: 'Send Feedback',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Feedback(): ReactElement {
|
|
||||||
const [sentryEnabled, setSentryEnabled] = useState(false)
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
// Run this only on component mount to verify once that Sentry is reachable
|
|
||||||
useEffect(() => {
|
|
||||||
isSentryReachable().then(result => {
|
|
||||||
setSentryEnabled(result)
|
|
||||||
})
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
if (sentryEnabled) {
|
|
||||||
return (
|
|
||||||
<Link onClick={showFeedbackForm} className={classes.link}>
|
|
||||||
<SideBarItem iconStart={<MessageSquare className={classes.icon} />} label={<span>Send feedback</span>} />
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return <></>
|
|
||||||
}
|
|
||||||
@@ -12,12 +12,11 @@ import { Context as BeeContext } from '../providers/Bee'
|
|||||||
import { Context as SettingsContext } from '../providers/Settings'
|
import { Context as SettingsContext } from '../providers/Settings'
|
||||||
import DashboardLogo from '../assets/dashboard-logo.svg'
|
import DashboardLogo from '../assets/dashboard-logo.svg'
|
||||||
import DesktopLogo from '../assets/desktop-logo.svg'
|
import DesktopLogo from '../assets/desktop-logo.svg'
|
||||||
import { config } from '../config'
|
|
||||||
import { ROUTES } from '../routes'
|
import { ROUTES } from '../routes'
|
||||||
import Feedback from './Feedback'
|
|
||||||
import SideBarItem from './SideBarItem'
|
import SideBarItem from './SideBarItem'
|
||||||
import SideBarStatus from './SideBarStatus'
|
import SideBarStatus from './SideBarStatus'
|
||||||
import { BeeModes } from '@ethersphere/bee-js'
|
import { BeeModes } from '@ethersphere/bee-js'
|
||||||
|
import { BEE_DOCS_HOST } from '../constants'
|
||||||
|
|
||||||
const drawerWidth = 300
|
const drawerWidth = 300
|
||||||
|
|
||||||
@@ -67,7 +66,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
|
|
||||||
export default function SideBar(): ReactElement {
|
export default function SideBar(): ReactElement {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const { isBeeDesktop } = useContext(SettingsContext)
|
const { isDesktop } = useContext(SettingsContext)
|
||||||
const { nodeInfo } = useContext(BeeContext)
|
const { nodeInfo } = useContext(BeeContext)
|
||||||
|
|
||||||
const navBarItems = [
|
const navBarItems = [
|
||||||
@@ -100,7 +99,7 @@ export default function SideBar(): ReactElement {
|
|||||||
<Grid container direction="column" justifyContent="space-between" className={classes.root}>
|
<Grid container direction="column" justifyContent="space-between" className={classes.root}>
|
||||||
<Grid className={classes.logo}>
|
<Grid className={classes.logo}>
|
||||||
<Link to={ROUTES.INFO}>
|
<Link to={ROUTES.INFO}>
|
||||||
<img alt="swarm" src={isBeeDesktop ? DesktopLogo : DashboardLogo} />
|
<img alt="swarm" src={isDesktop ? DesktopLogo : DashboardLogo} />
|
||||||
</Link>
|
</Link>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid>
|
<Grid>
|
||||||
@@ -119,7 +118,7 @@ export default function SideBar(): ReactElement {
|
|||||||
</List>
|
</List>
|
||||||
<Divider className={classes.divider} />
|
<Divider className={classes.divider} />
|
||||||
<List>
|
<List>
|
||||||
<MUILink href={config.BEE_DOCS_HOST} target="_blank" className={classes.link}>
|
<MUILink href={BEE_DOCS_HOST} target="_blank" className={classes.link}>
|
||||||
<SideBarItem
|
<SideBarItem
|
||||||
iconStart={<DocsIcon className={classes.icon} />}
|
iconStart={<DocsIcon className={classes.icon} />}
|
||||||
iconEnd={<ExternalLinkIcon className={classes.icon} color="#595959" />}
|
iconEnd={<ExternalLinkIcon className={classes.icon} color="#595959" />}
|
||||||
@@ -133,7 +132,6 @@ export default function SideBar(): ReactElement {
|
|||||||
<Link to={ROUTES.STATUS} className={classes.link}>
|
<Link to={ROUTES.STATUS} className={classes.link}>
|
||||||
<SideBarStatus path={ROUTES.STATUS} />
|
<SideBarStatus path={ROUTES.STATUS} />
|
||||||
</Link>
|
</Link>
|
||||||
<Feedback />
|
|
||||||
</List>
|
</List>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
|
|||||||
import type { ReactElement } from 'react'
|
import type { ReactElement } from 'react'
|
||||||
import Activity from 'remixicon-react/PulseLineIcon'
|
import Activity from 'remixicon-react/PulseLineIcon'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { config } from '../config'
|
|
||||||
import { ROUTES } from '../routes'
|
import { ROUTES } from '../routes'
|
||||||
|
import { BEE_DISCORD_HOST, BEE_DOCS_HOST } from '../constants'
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
@@ -37,11 +37,11 @@ export default function TroubleshootConnectionCard(): ReactElement {
|
|||||||
<Grid item className={classes.content}>
|
<Grid item className={classes.content}>
|
||||||
<Typography align="center">
|
<Typography align="center">
|
||||||
Please check your node status to fix the problem. You can also check out the{' '}
|
Please check your node status to fix the problem. You can also check out the{' '}
|
||||||
<MuiLink href={config.BEE_DOCS_HOST} target="_blank" rel="noreferrer">
|
<MuiLink href={BEE_DOCS_HOST} target="_blank" rel="noreferrer">
|
||||||
Swarm Bee Docs
|
Swarm Bee Docs
|
||||||
</MuiLink>{' '}
|
</MuiLink>{' '}
|
||||||
or ask for support on the{' '}
|
or ask for support on the{' '}
|
||||||
<MuiLink href={config.BEE_DISCORD_HOST} target="_blank" rel="noreferrer">
|
<MuiLink href={BEE_DISCORD_HOST} target="_blank" rel="noreferrer">
|
||||||
Ethereum Swarm Discord
|
Ethereum Swarm Discord
|
||||||
</MuiLink>
|
</MuiLink>
|
||||||
.
|
.
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
class Config {
|
|
||||||
public readonly BEE_API_HOST: string
|
|
||||||
public readonly BEE_DEBUG_API_HOST: string
|
|
||||||
public readonly BLOCKCHAIN_EXPLORER_URL: string
|
|
||||||
public readonly BEE_DOCS_HOST: string
|
|
||||||
public readonly BEE_DISCORD_HOST: string
|
|
||||||
public readonly GITHUB_REPO_URL: string
|
|
||||||
public readonly BEE_DESKTOP_ENABLED: boolean
|
|
||||||
public readonly BEE_DESKTOP_URL: string
|
|
||||||
public readonly SENTRY_KEY: string | undefined
|
|
||||||
public readonly SENTRY_ENVIRONMENT: string | undefined
|
|
||||||
public readonly DEFAULT_RPC_URL: string
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.BEE_API_HOST = sessionStorage.getItem('api_host') ?? process.env.REACT_APP_BEE_HOST ?? 'http://localhost:1633'
|
|
||||||
this.SENTRY_KEY = process.env.REACT_APP_SENTRY_KEY
|
|
||||||
this.SENTRY_ENVIRONMENT = process.env.REACT_APP_SENTRY_ENVIRONMENT
|
|
||||||
this.BEE_DEBUG_API_HOST =
|
|
||||||
sessionStorage.getItem('debug_api_host') ?? process.env.REACT_APP_BEE_DEBUG_HOST ?? 'http://localhost:1635'
|
|
||||||
this.BLOCKCHAIN_EXPLORER_URL =
|
|
||||||
process.env.REACT_APP_BLOCKCHAIN_EXPLORER_URL ?? 'https://blockscout.com/xdai/mainnet'
|
|
||||||
this.BEE_DOCS_HOST = process.env.REACT_APP_BEE_DOCS_HOST ?? 'https://docs.ethswarm.org/docs/'
|
|
||||||
this.BEE_DISCORD_HOST = process.env.REACT_APP_BEE_DISCORD_HOST ?? 'https://discord.gg/eKr9XPv7'
|
|
||||||
this.GITHUB_REPO_URL = process.env.REACT_APP_BEE_GITHUB_REPO_URL ?? 'https://api.github.com/repos/ethersphere/bee'
|
|
||||||
this.BEE_DESKTOP_ENABLED = process.env.REACT_APP_BEE_DESKTOP_ENABLED === 'true'
|
|
||||||
this.BEE_DESKTOP_URL = process.env.REACT_APP_BEE_DESKTOP_URL ?? window.location.origin
|
|
||||||
this.DEFAULT_RPC_URL = process.env.REACT_APP_DEFAULT_RPC_URL ?? 'https://xdai.fairdatasociety.org'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const config = new Config()
|
|
||||||
|
|
||||||
export default config
|
|
||||||
+11
-1
@@ -1,4 +1,14 @@
|
|||||||
export const META_FILE_NAME = '.swarmgatewaymeta.json'
|
export const META_FILE_NAME = '.swarmgatewaymeta.json'
|
||||||
export const PREVIEW_FILE_NAME = '.swarmgatewaypreview.jpeg'
|
export const PREVIEW_FILE_NAME = '.swarmgatewaypreview.jpeg'
|
||||||
export const PREVIEW_DIMENSIONS = { maxWidth: 250, maxHeight: 175 }
|
export const PREVIEW_DIMENSIONS = { maxWidth: 250, maxHeight: 175 }
|
||||||
export const BZZ_LINK_DOMAIN = process.env.REACT_APP_BZZ_LINK_DOMAIN || 'bzz.link'
|
export const BZZ_LINK_DOMAIN = 'bzz.link'
|
||||||
|
export const BLOCKCHAIN_EXPLORER_URL = 'https://blockscout.com/xdai/mainnet'
|
||||||
|
export const BEE_DOCS_HOST = 'https://docs.ethswarm.org/docs/'
|
||||||
|
export const BEE_DISCORD_HOST = 'https://discord.gg/eKr9XPv7'
|
||||||
|
export const GITHUB_REPO_URL = 'https://api.github.com/repos/ethersphere/bee'
|
||||||
|
export const BEE_DESKTOP_LATEST_RELEASE_PAGE = 'https://github.com/ethersphere/bee-desktop/releases/latest'
|
||||||
|
export const BEE_DESKTOP_LATEST_RELEASE_PAGE_API =
|
||||||
|
'https://api.github.com/repos/ethersphere/bee-desktop/releases/latest'
|
||||||
|
export const DEFAULT_BEE_API_HOST = 'http://localhost:1633'
|
||||||
|
export const DEFAULT_BEE_DEBUG_API_HOST = 'http://localhost:1635'
|
||||||
|
export const DEFAULT_RPC_URL = 'https://xdai.fairdatasociety.org'
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { renderHook } from '@testing-library/react-hooks'
|
import { renderHook } from '@testing-library/react-hooks'
|
||||||
import express from 'express'
|
|
||||||
import cors from 'cors'
|
import cors from 'cors'
|
||||||
|
import express from 'express'
|
||||||
import type { Server } from 'http'
|
import type { Server } from 'http'
|
||||||
import { useIsBeeDesktop } from './apiHooks'
|
import { useBeeDesktop } from './apiHooks'
|
||||||
|
|
||||||
interface AddressInfo {
|
interface AddressInfo {
|
||||||
address: string
|
address: string
|
||||||
@@ -39,9 +39,9 @@ afterAll(async () => {
|
|||||||
await new Promise(resolve => serverCorrect.close(resolve))
|
await new Promise(resolve => serverCorrect.close(resolve))
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('useIsBeeDesktop', () => {
|
describe('useBeeDesktop', () => {
|
||||||
it('should not have error when connected to bee-desktop', async () => {
|
it('should not have error when connected to bee-desktop', async () => {
|
||||||
const { result, waitFor } = renderHook(() => useIsBeeDesktop(true, { BEE_DESKTOP_URL: serverCorrectURL }))
|
const { result, waitFor } = renderHook(() => useBeeDesktop(true, serverCorrectURL))
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(result.current.isLoading).toBe(false)
|
expect(result.current.isLoading).toBe(false)
|
||||||
|
|||||||
+20
-25
@@ -1,8 +1,8 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { config } from '../config'
|
|
||||||
import { getJson } from '../utils/net'
|
|
||||||
import { getLatestBeeDesktopVersion } from '../utils/desktop'
|
import { getLatestBeeDesktopVersion } from '../utils/desktop'
|
||||||
|
import { getJson } from '../utils/net'
|
||||||
|
import { GITHUB_REPO_URL } from '../constants'
|
||||||
|
|
||||||
export interface LatestBeeReleaseHook {
|
export interface LatestBeeReleaseHook {
|
||||||
latestBeeRelease: LatestBeeRelease | null
|
latestBeeRelease: LatestBeeRelease | null
|
||||||
@@ -10,7 +10,7 @@ export interface LatestBeeReleaseHook {
|
|||||||
error: Error | null
|
error: Error | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IsBeeDesktopHook {
|
export interface BeeDesktopHook {
|
||||||
error: Error | null
|
error: Error | null
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
beeDesktopVersion: string
|
beeDesktopVersion: string
|
||||||
@@ -21,16 +21,7 @@ export interface NewDesktopVersionHook {
|
|||||||
newBeeDesktopVersion: string
|
newBeeDesktopVersion: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Config {
|
export const useBeeDesktop = (isBeeDesktop = false, desktopUrl: string): BeeDesktopHook => {
|
||||||
BEE_DESKTOP_URL: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect if the dashboard is run within bee-desktop
|
|
||||||
*
|
|
||||||
* @returns isBeeDesktop true if this is run within bee-desktop
|
|
||||||
*/
|
|
||||||
export const useIsBeeDesktop = (isBeeDesktop = false, conf: Config = config): IsBeeDesktopHook => {
|
|
||||||
const [desktopAutoUpdateEnabled, setDesktopAutoUpdateEnabled] = useState<boolean>(true)
|
const [desktopAutoUpdateEnabled, setDesktopAutoUpdateEnabled] = useState<boolean>(true)
|
||||||
const [beeDesktopVersion, setBeeDesktopVersion] = useState<string>('')
|
const [beeDesktopVersion, setBeeDesktopVersion] = useState<string>('')
|
||||||
const [isLoading, setLoading] = useState<boolean>(true)
|
const [isLoading, setLoading] = useState<boolean>(true)
|
||||||
@@ -42,7 +33,7 @@ export const useIsBeeDesktop = (isBeeDesktop = false, conf: Config = config): Is
|
|||||||
setError(null)
|
setError(null)
|
||||||
} else {
|
} else {
|
||||||
axios
|
axios
|
||||||
.get(`${conf.BEE_DESKTOP_URL}/info`)
|
.get(`${desktopUrl}/info`)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
setBeeDesktopVersion(res.data?.version)
|
setBeeDesktopVersion(res.data?.version)
|
||||||
setDesktopAutoUpdateEnabled(res.data?.autoUpdateEnabled)
|
setDesktopAutoUpdateEnabled(res.data?.autoUpdateEnabled)
|
||||||
@@ -55,13 +46,13 @@ export const useIsBeeDesktop = (isBeeDesktop = false, conf: Config = config): Is
|
|||||||
setLoading(false)
|
setLoading(false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [conf, isBeeDesktop])
|
}, [desktopUrl, isBeeDesktop])
|
||||||
|
|
||||||
return { error, isLoading, beeDesktopVersion, desktopAutoUpdateEnabled }
|
return { error, isLoading, beeDesktopVersion, desktopAutoUpdateEnabled }
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkNewVersion(conf: Config): Promise<string> {
|
async function checkNewVersion(desktopUrl: string): Promise<string> {
|
||||||
const resJson = await (await fetch(`${conf.BEE_DESKTOP_URL}/info`)).json()
|
const resJson = await (await fetch(`${desktopUrl}/info`)).json()
|
||||||
const currentVersion = resJson.version
|
const currentVersion = resJson.version
|
||||||
const latestVersion = await getLatestBeeDesktopVersion()
|
const latestVersion = await getLatestBeeDesktopVersion()
|
||||||
|
|
||||||
@@ -72,20 +63,24 @@ async function checkNewVersion(conf: Config): Promise<string> {
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useNewBeeDesktopVersion(isBeeDesktop: boolean, conf: Config = config): NewDesktopVersionHook {
|
export function useNewBeeDesktopVersion(
|
||||||
|
isBeeDesktop: boolean,
|
||||||
|
desktopUrl: string,
|
||||||
|
desktopAutoUpdateEnabled: boolean,
|
||||||
|
): NewDesktopVersionHook {
|
||||||
const [newBeeDesktopVersion, setNewBeeDesktopVersion] = useState<string>('')
|
const [newBeeDesktopVersion, setNewBeeDesktopVersion] = useState<string>('')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isBeeDesktop) {
|
if (!isBeeDesktop || desktopAutoUpdateEnabled) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNewVersion(conf).then(version => {
|
checkNewVersion(desktopUrl).then(version => {
|
||||||
if (version !== '') {
|
if (version !== '') {
|
||||||
setNewBeeDesktopVersion(version)
|
setNewBeeDesktopVersion(version)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [isBeeDesktop, conf])
|
}, [isBeeDesktop, desktopUrl, desktopAutoUpdateEnabled])
|
||||||
|
|
||||||
return { newBeeDesktopVersion }
|
return { newBeeDesktopVersion }
|
||||||
}
|
}
|
||||||
@@ -115,13 +110,13 @@ export interface GetBeeConfig {
|
|||||||
error: Error | null
|
error: Error | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useGetBeeConfig = (conf: Config = config): GetBeeConfig => {
|
export const useGetBeeConfig = (desktopUrl: string): GetBeeConfig => {
|
||||||
const [beeConfig, setBeeConfig] = useState<BeeConfig | null>(null)
|
const [beeConfig, setBeeConfig] = useState<BeeConfig | null>(null)
|
||||||
const [isLoading, setLoading] = useState<boolean>(true)
|
const [isLoading, setLoading] = useState<boolean>(true)
|
||||||
const [error, setError] = useState<Error | null>(null)
|
const [error, setError] = useState<Error | null>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getJson<BeeConfig>(`${conf.BEE_DESKTOP_URL}/config`)
|
getJson<BeeConfig>(`${desktopUrl}/config`)
|
||||||
.then(beeConf => {
|
.then(beeConf => {
|
||||||
setBeeConfig(beeConf)
|
setBeeConfig(beeConf)
|
||||||
setError(null)
|
setError(null)
|
||||||
@@ -133,7 +128,7 @@ export const useGetBeeConfig = (conf: Config = config): GetBeeConfig => {
|
|||||||
.finally(() => {
|
.finally(() => {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
})
|
})
|
||||||
}, [conf])
|
}, [desktopUrl])
|
||||||
|
|
||||||
return { config: beeConfig, isLoading, error }
|
return { config: beeConfig, isLoading, error }
|
||||||
}
|
}
|
||||||
@@ -145,7 +140,7 @@ export const useLatestBeeRelease = (): LatestBeeReleaseHook => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
axios
|
axios
|
||||||
.get(`${config.GITHUB_REPO_URL}/releases/latest`)
|
.get(`${GITHUB_REPO_URL}/releases/latest`)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
setLatestBeeRelease(res.data)
|
setLatestBeeRelease(res.data)
|
||||||
})
|
})
|
||||||
|
|||||||
+6
-1
@@ -4,9 +4,14 @@ import './index.css'
|
|||||||
import App from './App'
|
import App from './App'
|
||||||
import reportWebVitals from './reportWebVitals'
|
import reportWebVitals from './reportWebVitals'
|
||||||
|
|
||||||
|
const desktopEnabled = Boolean(process.env.REACT_APP_BEE_DESKTOP_ENABLED)
|
||||||
|
const desktopUrl = process.env.REACT_APP_BEE_DESKTOP_URL
|
||||||
|
const beeApiUrl = process.env.REACT_APP_BEE_API_URL
|
||||||
|
const beeDebugApiUrl = process.env.REACT_APP_BEE_DEBUG_API_URL
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App />
|
<App isDesktop={desktopEnabled} desktopUrl={desktopUrl} beeApiUrl={beeApiUrl} beeDebugApiUrl={beeDebugApiUrl} />
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById('root'),
|
document.getElementById('root'),
|
||||||
)
|
)
|
||||||
|
|||||||
+18
-26
@@ -7,11 +7,8 @@ import ErrorBoundary from '../components/ErrorBoundary'
|
|||||||
import SideBar from '../components/SideBar'
|
import SideBar from '../components/SideBar'
|
||||||
import { Context as BeeContext } from '../providers/Bee'
|
import { Context as BeeContext } from '../providers/Bee'
|
||||||
import { Context as SettingsContext } from '../providers/Settings'
|
import { Context as SettingsContext } from '../providers/Settings'
|
||||||
import config from '../config'
|
import { useBeeDesktop, useNewBeeDesktopVersion } from '../hooks/apiHooks'
|
||||||
import * as Sentry from '@sentry/react'
|
import { BEE_DESKTOP_LATEST_RELEASE_PAGE } from '../constants'
|
||||||
import ItsBroken from './ItsBroken'
|
|
||||||
import { useNewBeeDesktopVersion } from '../hooks/apiHooks'
|
|
||||||
import { BEE_DESKTOP_LATEST_RELEASE_PAGE } from '../utils/desktop'
|
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
@@ -24,6 +21,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children?: ReactElement
|
children?: ReactElement
|
||||||
|
errorReporting?: (err: Error) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const Dashboard = (props: Props): ReactElement => {
|
const Dashboard = (props: Props): ReactElement => {
|
||||||
@@ -31,13 +29,14 @@ const Dashboard = (props: Props): ReactElement => {
|
|||||||
|
|
||||||
const { isLoading, isLatestBeeVersion, latestBeeRelease, latestBeeVersionUrl, latestUserVersion } =
|
const { isLoading, isLatestBeeVersion, latestBeeRelease, latestBeeVersionUrl, latestUserVersion } =
|
||||||
useContext(BeeContext)
|
useContext(BeeContext)
|
||||||
const { isBeeDesktop } = useContext(SettingsContext)
|
const { isDesktop, desktopUrl } = useContext(SettingsContext)
|
||||||
const { newBeeDesktopVersion } = useNewBeeDesktopVersion(isBeeDesktop)
|
const { desktopAutoUpdateEnabled } = useBeeDesktop(isDesktop, desktopUrl)
|
||||||
|
const { newBeeDesktopVersion } = useNewBeeDesktopVersion(isDesktop, desktopUrl, desktopAutoUpdateEnabled)
|
||||||
const { enqueueSnackbar, closeSnackbar } = useSnackbar()
|
const { enqueueSnackbar, closeSnackbar } = useSnackbar()
|
||||||
|
|
||||||
// New version of Bee client notification
|
// New version of Bee client notification
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isLoading && !isBeeDesktop && !isLatestBeeVersion && latestBeeRelease && latestUserVersion) {
|
if (!isLoading && !isDesktop && !isLatestBeeVersion && latestBeeRelease && latestUserVersion) {
|
||||||
enqueueSnackbar(`There is new Bee version ${latestBeeRelease?.name}!`, {
|
enqueueSnackbar(`There is new Bee version ${latestBeeRelease?.name}!`, {
|
||||||
variant: 'warning',
|
variant: 'warning',
|
||||||
preventDuplicate: true,
|
preventDuplicate: true,
|
||||||
@@ -68,7 +67,7 @@ const Dashboard = (props: Props): ReactElement => {
|
|||||||
closeSnackbar,
|
closeSnackbar,
|
||||||
enqueueSnackbar,
|
enqueueSnackbar,
|
||||||
isLatestBeeVersion,
|
isLatestBeeVersion,
|
||||||
isBeeDesktop,
|
isDesktop,
|
||||||
latestBeeRelease,
|
latestBeeRelease,
|
||||||
latestBeeVersionUrl,
|
latestBeeVersionUrl,
|
||||||
isLoading,
|
isLoading,
|
||||||
@@ -76,6 +75,11 @@ const Dashboard = (props: Props): ReactElement => {
|
|||||||
])
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// When autoupdate is enabled then we leave the version check for the built-in Electron update mechanism
|
||||||
|
if (desktopAutoUpdateEnabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (newBeeDesktopVersion !== '') {
|
if (newBeeDesktopVersion !== '') {
|
||||||
enqueueSnackbar(`There is new Swarm Dashboard version ${newBeeDesktopVersion}!`, {
|
enqueueSnackbar(`There is new Swarm Dashboard version ${newBeeDesktopVersion}!`, {
|
||||||
variant: 'warning',
|
variant: 'warning',
|
||||||
@@ -103,7 +107,7 @@ const Dashboard = (props: Props): ReactElement => {
|
|||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [enqueueSnackbar, closeSnackbar, newBeeDesktopVersion])
|
}, [enqueueSnackbar, closeSnackbar, newBeeDesktopVersion, desktopAutoUpdateEnabled])
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<>
|
<>
|
||||||
@@ -117,25 +121,13 @@ const Dashboard = (props: Props): ReactElement => {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
let errorBoundaryWithContent
|
|
||||||
|
|
||||||
if (config.SENTRY_KEY) {
|
|
||||||
errorBoundaryWithContent = (
|
|
||||||
<Sentry.ErrorBoundary
|
|
||||||
showDialog
|
|
||||||
fallback={({ error, componentStack, resetError }) => <ItsBroken message={error.message} />}
|
|
||||||
>
|
|
||||||
{content}
|
|
||||||
</Sentry.ErrorBoundary>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
errorBoundaryWithContent = <ErrorBoundary>{content}</ErrorBoundary>
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex' }}>
|
<div style={{ display: 'flex' }}>
|
||||||
<SideBar />
|
<SideBar />
|
||||||
<Container className={classes.content}>{errorBoundaryWithContent}</Container>
|
<Container className={classes.content}>
|
||||||
|
{' '}
|
||||||
|
<ErrorBoundary errorReporting={props.errorReporting}>{content}</ErrorBoundary>
|
||||||
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
import { Container } from '@material-ui/core'
|
|
||||||
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
|
|
||||||
import { ReactElement } from 'react'
|
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
|
||||||
createStyles({
|
|
||||||
content: {
|
|
||||||
backgroundColor: theme.palette.background.default,
|
|
||||||
minHeight: '100vh',
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
errorMsg: {
|
|
||||||
marginTop: '30px',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
message: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Provide some nicer design
|
|
||||||
const ItsBroken = ({ message }: Props): ReactElement => {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Container className={classes.content}>
|
|
||||||
<h1>Ups, there was a problem 😅</h1>
|
|
||||||
<h3 className={classes.errorMsg}>Error: {message}</h3>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ItsBroken
|
|
||||||
@@ -20,7 +20,7 @@ import { Header } from '../Header'
|
|||||||
|
|
||||||
export function AccountWallet(): ReactElement {
|
export function AccountWallet(): ReactElement {
|
||||||
const { nodeAddresses, nodeInfo, status } = useContext(BeeContext)
|
const { nodeAddresses, nodeInfo, status } = useContext(BeeContext)
|
||||||
const { isBeeDesktop } = useContext(SettingsContext)
|
const { isDesktop } = useContext(SettingsContext)
|
||||||
const { balance } = useContext(BalanceProvider)
|
const { balance } = useContext(BalanceProvider)
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
@@ -72,7 +72,7 @@ export function AccountWallet(): ReactElement {
|
|||||||
<SwarmButton onClick={onCheckTransactions} iconType={Link}>
|
<SwarmButton onClick={onCheckTransactions} iconType={Link}>
|
||||||
Check transactions on Blockscout
|
Check transactions on Blockscout
|
||||||
</SwarmButton>
|
</SwarmButton>
|
||||||
{isBeeDesktop && (
|
{isDesktop && (
|
||||||
<SwarmButton onClick={onInvite} iconType={Gift}>
|
<SwarmButton onClick={onInvite} iconType={Gift}>
|
||||||
Invite to Swarm...
|
Invite to Swarm...
|
||||||
</SwarmButton>
|
</SwarmButton>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { useNavigate, useParams } from 'react-router-dom'
|
|||||||
import { HistoryHeader } from '../../components/HistoryHeader'
|
import { HistoryHeader } from '../../components/HistoryHeader'
|
||||||
import { Loading } from '../../components/Loading'
|
import { Loading } from '../../components/Loading'
|
||||||
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard'
|
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard'
|
||||||
import config from '../../config'
|
|
||||||
import { META_FILE_NAME, PREVIEW_FILE_NAME } from '../../constants'
|
import { META_FILE_NAME, PREVIEW_FILE_NAME } from '../../constants'
|
||||||
import { Context as BeeContext } from '../../providers/Bee'
|
import { Context as BeeContext } from '../../providers/Bee'
|
||||||
import { Context as SettingsContext } from '../../providers/Settings'
|
import { Context as SettingsContext } from '../../providers/Settings'
|
||||||
@@ -78,7 +77,7 @@ export function Share(): ReactElement {
|
|||||||
} catch (e) {} // eslint-disable-line no-empty
|
} catch (e) {} // eslint-disable-line no-empty
|
||||||
|
|
||||||
if (previewFile) {
|
if (previewFile) {
|
||||||
setPreview(`${config.BEE_API_HOST}/bzz/${reference}/${PREVIEW_FILE_NAME}`)
|
setPreview(`${apiUrl}/bzz/${reference}/${PREVIEW_FILE_NAME}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
setMetadata(metadata)
|
setMetadata(metadata)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const GIFT_WALLET_FUND_BZZ_AMOUNT = Token.fromDecimal('0.5', 16)
|
|||||||
|
|
||||||
export default function Index(): ReactElement {
|
export default function Index(): ReactElement {
|
||||||
const { giftWallets, addGiftWallet } = useContext(TopUpContext)
|
const { giftWallets, addGiftWallet } = useContext(TopUpContext)
|
||||||
const { provider } = useContext(SettingsContext)
|
const { provider, desktopUrl } = useContext(SettingsContext)
|
||||||
const { balance } = useContext(BalanceProvider)
|
const { balance } = useContext(BalanceProvider)
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
@@ -50,7 +50,7 @@ export default function Index(): ReactElement {
|
|||||||
try {
|
try {
|
||||||
const wallet = Wallet.createRandom()
|
const wallet = Wallet.createRandom()
|
||||||
addGiftWallet(wallet)
|
addGiftWallet(wallet)
|
||||||
await createGiftWallet(wallet.address)
|
await createGiftWallet(desktopUrl, wallet.address)
|
||||||
enqueueSnackbar('Succesfully funded gift wallet', { variant: 'success' })
|
enqueueSnackbar('Succesfully funded gift wallet', { variant: 'success' })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error) // eslint-disable-line
|
console.error(error) // eslint-disable-line
|
||||||
|
|||||||
+14
-15
@@ -1,21 +1,20 @@
|
|||||||
import { ReactElement, useContext } from 'react'
|
|
||||||
import { Button } from '@material-ui/core'
|
import { Button } from '@material-ui/core'
|
||||||
import Wallet from 'remixicon-react/Wallet3LineIcon'
|
import { ReactElement, useContext } from 'react'
|
||||||
|
import { useNavigate } from 'react-router'
|
||||||
import ExchangeFunds from 'remixicon-react/ExchangeFundsLineIcon'
|
import ExchangeFunds from 'remixicon-react/ExchangeFundsLineIcon'
|
||||||
import Upload from 'remixicon-react/UploadLineIcon'
|
import Upload from 'remixicon-react/UploadLineIcon'
|
||||||
|
import Wallet from 'remixicon-react/Wallet3LineIcon'
|
||||||
|
import Card from '../../components/Card'
|
||||||
|
import ExpandableListItem from '../../components/ExpandableListItem'
|
||||||
|
import Map from '../../components/Map'
|
||||||
|
import { useBeeDesktop, useNewBeeDesktopVersion } from '../../hooks/apiHooks'
|
||||||
import { Context as BeeContext } from '../../providers/Bee'
|
import { Context as BeeContext } from '../../providers/Bee'
|
||||||
import { Context as SettingsContext } from '../../providers/Settings'
|
import { Context as SettingsContext } from '../../providers/Settings'
|
||||||
import { Context as BalanceProvider } from '../../providers/WalletBalance'
|
import { Context as BalanceProvider } from '../../providers/WalletBalance'
|
||||||
import Card from '../../components/Card'
|
|
||||||
import Map from '../../components/Map'
|
|
||||||
import ExpandableListItem from '../../components/ExpandableListItem'
|
|
||||||
import { useNavigate } from 'react-router'
|
|
||||||
import { ROUTES } from '../../routes'
|
import { ROUTES } from '../../routes'
|
||||||
import { useIsBeeDesktop, useNewBeeDesktopVersion } from '../../hooks/apiHooks'
|
|
||||||
import { BEE_DESKTOP_LATEST_RELEASE_PAGE } from '../../utils/desktop'
|
|
||||||
import NodeInfoCard from './NodeInfoCard'
|
|
||||||
import { chainIdToName } from '../../utils/chain'
|
import { chainIdToName } from '../../utils/chain'
|
||||||
|
import NodeInfoCard from './NodeInfoCard'
|
||||||
|
import { BEE_DESKTOP_LATEST_RELEASE_PAGE } from '../../constants'
|
||||||
|
|
||||||
export default function Status(): ReactElement {
|
export default function Status(): ReactElement {
|
||||||
const {
|
const {
|
||||||
@@ -28,10 +27,10 @@ export default function Status(): ReactElement {
|
|||||||
chequebookBalance,
|
chequebookBalance,
|
||||||
chainId,
|
chainId,
|
||||||
} = useContext(BeeContext)
|
} = useContext(BeeContext)
|
||||||
const { isBeeDesktop } = useContext(SettingsContext)
|
const { isDesktop, desktopUrl } = useContext(SettingsContext)
|
||||||
const { balance, error } = useContext(BalanceProvider)
|
const { balance, error } = useContext(BalanceProvider)
|
||||||
const { beeDesktopVersion } = useIsBeeDesktop()
|
const { beeDesktopVersion } = useBeeDesktop(isDesktop, desktopUrl)
|
||||||
const { newBeeDesktopVersion } = useNewBeeDesktopVersion(isBeeDesktop)
|
const { newBeeDesktopVersion } = useNewBeeDesktopVersion(isDesktop, desktopUrl, false)
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
let balanceText = 'Loading...'
|
let balanceText = 'Loading...'
|
||||||
@@ -115,7 +114,7 @@ export default function Status(): ReactElement {
|
|||||||
<ExpandableListItem label="Connected peers" value={topology?.connected ?? '-'} />
|
<ExpandableListItem label="Connected peers" value={topology?.connected ?? '-'} />
|
||||||
<ExpandableListItem label="Population" value={topology?.population ?? '-'} />
|
<ExpandableListItem label="Population" value={topology?.population ?? '-'} />
|
||||||
<div style={{ height: '16px' }} />
|
<div style={{ height: '16px' }} />
|
||||||
{isBeeDesktop && (
|
{isDesktop && (
|
||||||
<ExpandableListItem
|
<ExpandableListItem
|
||||||
label="Desktop version"
|
label="Desktop version"
|
||||||
value={
|
value={
|
||||||
@@ -143,7 +142,7 @@ export default function Status(): ReactElement {
|
|||||||
Bee
|
Bee
|
||||||
</a>
|
</a>
|
||||||
{` ${latestUserVersion ?? '-'} `}
|
{` ${latestUserVersion ?? '-'} `}
|
||||||
{latestUserVersion && !isBeeDesktop && (
|
{latestUserVersion && !isDesktop && (
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export default function SettingsPage(): ReactElement {
|
|||||||
ensResolver,
|
ensResolver,
|
||||||
providerUrl,
|
providerUrl,
|
||||||
isLoading,
|
isLoading,
|
||||||
isBeeDesktop,
|
isDesktop,
|
||||||
setAndPersistJsonRpcProvider,
|
setAndPersistJsonRpcProvider,
|
||||||
} = useContext(SettingsContext)
|
} = useContext(SettingsContext)
|
||||||
const { refresh } = useContext(BeeContext)
|
const { refresh } = useContext(BeeContext)
|
||||||
@@ -39,13 +39,13 @@ export default function SettingsPage(): ReactElement {
|
|||||||
label="Bee API"
|
label="Bee API"
|
||||||
value={apiUrl}
|
value={apiUrl}
|
||||||
onConfirm={setApiUrl}
|
onConfirm={setApiUrl}
|
||||||
locked={lockedApiSettings || isBeeDesktop}
|
locked={lockedApiSettings || isDesktop}
|
||||||
/>
|
/>
|
||||||
<ExpandableListItemInput
|
<ExpandableListItemInput
|
||||||
label="Bee Debug API"
|
label="Bee Debug API"
|
||||||
value={apiDebugUrl}
|
value={apiDebugUrl}
|
||||||
onConfirm={setDebugApiUrl}
|
onConfirm={setDebugApiUrl}
|
||||||
locked={lockedApiSettings || isBeeDesktop}
|
locked={lockedApiSettings || isDesktop}
|
||||||
/>
|
/>
|
||||||
<ExpandableListItemInput
|
<ExpandableListItemInput
|
||||||
label="Blockchain RPC URL"
|
label="Blockchain RPC URL"
|
||||||
@@ -65,7 +65,7 @@ export default function SettingsPage(): ReactElement {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ExpandableList>
|
</ExpandableList>
|
||||||
{isBeeDesktop && (
|
{isDesktop && (
|
||||||
<ExpandableList label="Desktop Settings" defaultOpen>
|
<ExpandableList label="Desktop Settings" defaultOpen>
|
||||||
<ExpandableListItemInput label="CORS" value={cors ?? '-'} locked />
|
<ExpandableListItemInput label="CORS" value={cors ?? '-'} locked />
|
||||||
<ExpandableListItemInput label="Data DIR" value={dataDir ?? '-'} locked />
|
<ExpandableListItemInput label="Data DIR" value={dataDir ?? '-'} locked />
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import { BeeModes } from '@ethersphere/bee-js'
|
|||||||
|
|
||||||
export function GiftCardFund(): ReactElement {
|
export function GiftCardFund(): ReactElement {
|
||||||
const { nodeAddresses, nodeInfo } = useContext(BeeContext)
|
const { nodeAddresses, nodeInfo } = useContext(BeeContext)
|
||||||
const { isBeeDesktop, provider, providerUrl } = useContext(SettingsContext)
|
const { isDesktop, desktopUrl, provider, providerUrl } = useContext(SettingsContext)
|
||||||
const { balance } = useContext(BalanceProvider)
|
const { balance } = useContext(BalanceProvider)
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
@@ -45,13 +45,13 @@ export function GiftCardFund(): ReactElement {
|
|||||||
return <Loading />
|
return <Loading />
|
||||||
}
|
}
|
||||||
|
|
||||||
const canUpgradeToLightNode = isBeeDesktop && nodeInfo?.beeMode === BeeModes.ULTRA_LIGHT
|
const canUpgradeToLightNode = isDesktop && nodeInfo?.beeMode === BeeModes.ULTRA_LIGHT
|
||||||
|
|
||||||
async function restart() {
|
async function restart() {
|
||||||
try {
|
try {
|
||||||
await sleepMs(5_000)
|
await sleepMs(5_000)
|
||||||
await upgradeToLightNode(providerUrl)
|
await upgradeToLightNode(desktopUrl, providerUrl)
|
||||||
await restartBeeNode()
|
await restartBeeNode(desktopUrl)
|
||||||
enqueueSnackbar('Upgraded to light node', { variant: 'success' })
|
enqueueSnackbar('Upgraded to light node', { variant: 'success' })
|
||||||
navigate(ROUTES.RESTART_LIGHT)
|
navigate(ROUTES.RESTART_LIGHT)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
+17
-15
@@ -31,13 +31,21 @@ interface Props {
|
|||||||
header: string
|
header: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPositiveDecimal(value: string): boolean {
|
||||||
|
try {
|
||||||
|
return new BigNumber(value).isPositive()
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function Swap({ header }: Props): ReactElement {
|
export function Swap({ header }: Props): ReactElement {
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [hasSwapped, setSwapped] = useState(false)
|
const [hasSwapped, setSwapped] = useState(false)
|
||||||
const [userInputSwap, setUserInputSwap] = useState<string | null>(null)
|
const [userInputSwap, setUserInputSwap] = useState<string | null>(null)
|
||||||
const [price, setPrice] = useState(DaiToken.fromDecimal('0.6', 18))
|
const [price, setPrice] = useState(DaiToken.fromDecimal('0.6', 18))
|
||||||
|
|
||||||
const { providerUrl, isBeeDesktop } = useContext(SettingsContext)
|
const { providerUrl, isDesktop, desktopUrl } = useContext(SettingsContext)
|
||||||
const { nodeAddresses, nodeInfo } = useContext(BeeContext)
|
const { nodeAddresses, nodeInfo } = useContext(BeeContext)
|
||||||
const { balance } = useContext(BalanceProvider)
|
const { balance } = useContext(BalanceProvider)
|
||||||
|
|
||||||
@@ -46,8 +54,8 @@ export function Swap({ header }: Props): ReactElement {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
getBzzPriceAsDai().then(setPrice).catch(console.error)
|
getBzzPriceAsDai(desktopUrl).then(setPrice).catch(console.error)
|
||||||
}, [])
|
}, [desktopUrl])
|
||||||
|
|
||||||
if (!balance || !nodeAddresses) {
|
if (!balance || !nodeAddresses) {
|
||||||
return <Loading />
|
return <Loading />
|
||||||
@@ -58,14 +66,6 @@ export function Swap({ header }: Props): ReactElement {
|
|||||||
|
|
||||||
let daiToSwap: DaiToken
|
let daiToSwap: DaiToken
|
||||||
|
|
||||||
function isPositiveDecimal(value: string): boolean {
|
|
||||||
try {
|
|
||||||
return new BigNumber(value).isPositive()
|
|
||||||
} catch {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userInputSwap && isPositiveDecimal(userInputSwap)) {
|
if (userInputSwap && isPositiveDecimal(userInputSwap)) {
|
||||||
daiToSwap = DaiToken.fromDecimal(userInputSwap, 18)
|
daiToSwap = DaiToken.fromDecimal(userInputSwap, 18)
|
||||||
} else {
|
} else {
|
||||||
@@ -75,13 +75,14 @@ export function Swap({ header }: Props): ReactElement {
|
|||||||
const daiAfterSwap = new DaiToken(balance.dai.toBigNumber.minus(daiToSwap.toBigNumber))
|
const daiAfterSwap = new DaiToken(balance.dai.toBigNumber.minus(daiToSwap.toBigNumber))
|
||||||
const bzzAfterSwap = new BzzToken(daiToSwap.toBigNumber.dividedBy(100).dividedToIntegerBy(price.toDecimal))
|
const bzzAfterSwap = new BzzToken(daiToSwap.toBigNumber.dividedBy(100).dividedToIntegerBy(price.toDecimal))
|
||||||
|
|
||||||
const canUpgradeToLightNode = isBeeDesktop && nodeInfo?.beeMode === BeeModes.ULTRA_LIGHT
|
const canUpgradeToLightNode = isDesktop && nodeInfo?.beeMode === BeeModes.ULTRA_LIGHT
|
||||||
|
|
||||||
async function restart() {
|
async function restart() {
|
||||||
try {
|
try {
|
||||||
await sleepMs(5_000)
|
await sleepMs(5_000)
|
||||||
await upgradeToLightNode(providerUrl)
|
await upgradeToLightNode(desktopUrl, providerUrl)
|
||||||
await restartBeeNode()
|
await restartBeeNode(desktopUrl)
|
||||||
|
|
||||||
enqueueSnackbar('Upgraded to light node', { variant: 'success' })
|
enqueueSnackbar('Upgraded to light node', { variant: 'success' })
|
||||||
navigate(ROUTES.RESTART_LIGHT)
|
navigate(ROUTES.RESTART_LIGHT)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -96,8 +97,9 @@ export function Swap({ header }: Props): ReactElement {
|
|||||||
}
|
}
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
setSwapped(true)
|
setSwapped(true)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await performSwap(daiToSwap.toString)
|
await performSwap(desktopUrl, daiToSwap.toString)
|
||||||
enqueueSnackbar('Successfully swapped', { variant: 'success' })
|
enqueueSnackbar('Successfully swapped', { variant: 'success' })
|
||||||
|
|
||||||
if (canUpgradeToLightNode) await restart()
|
if (canUpgradeToLightNode) await restart()
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const MINIMUM_XBZZ = '0.1'
|
|||||||
export default function TopUp(): ReactElement {
|
export default function TopUp(): ReactElement {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const styles = useStyles()
|
const styles = useStyles()
|
||||||
const { isBeeDesktop } = useContext(SettingsContext)
|
const { isDesktop, desktopUrl } = useContext(SettingsContext)
|
||||||
const { nodeInfo, status } = useContext(BeeContext)
|
const { nodeInfo, status } = useContext(BeeContext)
|
||||||
const { balance } = useContext(BalanceProvider)
|
const { balance } = useContext(BalanceProvider)
|
||||||
const { providerUrl } = useContext(SettingsContext)
|
const { providerUrl } = useContext(SettingsContext)
|
||||||
@@ -47,7 +47,7 @@ export default function TopUp(): ReactElement {
|
|||||||
const { enqueueSnackbar } = useSnackbar()
|
const { enqueueSnackbar } = useSnackbar()
|
||||||
|
|
||||||
const canUpgradeToLightNode =
|
const canUpgradeToLightNode =
|
||||||
isBeeDesktop &&
|
isDesktop &&
|
||||||
nodeInfo?.beeMode === BeeModes.ULTRA_LIGHT &&
|
nodeInfo?.beeMode === BeeModes.ULTRA_LIGHT &&
|
||||||
balance?.dai.toDecimal.gte(MINIMUM_XDAI) &&
|
balance?.dai.toDecimal.gte(MINIMUM_XDAI) &&
|
||||||
balance?.bzz.toDecimal.gte(MINIMUM_XBZZ)
|
balance?.bzz.toDecimal.gte(MINIMUM_XBZZ)
|
||||||
@@ -55,8 +55,8 @@ export default function TopUp(): ReactElement {
|
|||||||
async function restart() {
|
async function restart() {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
await upgradeToLightNode(providerUrl)
|
await upgradeToLightNode(desktopUrl, providerUrl)
|
||||||
await restartBeeNode()
|
await restartBeeNode(desktopUrl)
|
||||||
enqueueSnackbar('Upgraded to light node', { variant: 'success' })
|
enqueueSnackbar('Upgraded to light node', { variant: 'success' })
|
||||||
navigate(ROUTES.RESTART_LIGHT)
|
navigate(ROUTES.RESTART_LIGHT)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
+68
-47
@@ -1,15 +1,15 @@
|
|||||||
import { Bee, BeeDebug } from '@ethersphere/bee-js'
|
import { Bee, BeeDebug } from '@ethersphere/bee-js'
|
||||||
import { providers } from 'ethers'
|
import { providers } from 'ethers'
|
||||||
import { createContext, ReactNode, ReactElement, useEffect, useState } from 'react'
|
import { createContext, ReactNode, ReactElement, useEffect, useState } from 'react'
|
||||||
import { config as appConfig } from '../config'
|
|
||||||
import { useGetBeeConfig } from '../hooks/apiHooks'
|
import { useGetBeeConfig } from '../hooks/apiHooks'
|
||||||
import { restartBeeNode, setJsonRpcInDesktop } from '../utils/desktop'
|
import { restartBeeNode, setJsonRpcInDesktop } from '../utils/desktop'
|
||||||
|
import { DEFAULT_BEE_API_HOST, DEFAULT_BEE_DEBUG_API_HOST, DEFAULT_RPC_URL } from '../constants'
|
||||||
|
|
||||||
const LocalStorageKeys = {
|
const LocalStorageKeys = {
|
||||||
providerUrl: 'json-rpc-provider',
|
providerUrl: 'json-rpc-provider',
|
||||||
}
|
}
|
||||||
|
|
||||||
const providerUrl = localStorage.getItem('json-rpc-provider') || appConfig.DEFAULT_RPC_URL
|
const providerUrl = localStorage.getItem('json-rpc-provider') || DEFAULT_RPC_URL
|
||||||
|
|
||||||
interface ContextInterface {
|
interface ContextInterface {
|
||||||
apiUrl: string
|
apiUrl: string
|
||||||
@@ -18,6 +18,8 @@ interface ContextInterface {
|
|||||||
beeDebugApi: BeeDebug | null
|
beeDebugApi: BeeDebug | null
|
||||||
lockedApiSettings: boolean
|
lockedApiSettings: boolean
|
||||||
desktopApiKey: string
|
desktopApiKey: string
|
||||||
|
isDesktop: boolean
|
||||||
|
desktopUrl: string
|
||||||
providerUrl: string
|
providerUrl: string
|
||||||
provider: providers.JsonRpcProvider
|
provider: providers.JsonRpcProvider
|
||||||
cors: string | null
|
cors: string | null
|
||||||
@@ -26,27 +28,27 @@ interface ContextInterface {
|
|||||||
setApiUrl: (url: string) => void
|
setApiUrl: (url: string) => void
|
||||||
setDebugApiUrl: (url: string) => void
|
setDebugApiUrl: (url: string) => void
|
||||||
setAndPersistJsonRpcProvider: (url: string) => Promise<void>
|
setAndPersistJsonRpcProvider: (url: string) => Promise<void>
|
||||||
isBeeDesktop: boolean
|
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
error: Error | null
|
error: Error | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialValues: ContextInterface = {
|
const initialValues: ContextInterface = {
|
||||||
apiUrl: appConfig.BEE_API_HOST,
|
|
||||||
apiDebugUrl: appConfig.BEE_DEBUG_API_HOST,
|
|
||||||
beeApi: null,
|
beeApi: null,
|
||||||
beeDebugApi: null,
|
beeDebugApi: null,
|
||||||
|
apiUrl: DEFAULT_BEE_API_HOST,
|
||||||
|
apiDebugUrl: DEFAULT_BEE_DEBUG_API_HOST,
|
||||||
setApiUrl: () => {}, // eslint-disable-line
|
setApiUrl: () => {}, // eslint-disable-line
|
||||||
setDebugApiUrl: () => {}, // eslint-disable-line
|
setDebugApiUrl: () => {}, // eslint-disable-line
|
||||||
lockedApiSettings: false,
|
lockedApiSettings: false,
|
||||||
|
isDesktop: false,
|
||||||
desktopApiKey: '',
|
desktopApiKey: '',
|
||||||
|
desktopUrl: window.location.origin,
|
||||||
setAndPersistJsonRpcProvider: async () => {}, // eslint-disable-line
|
setAndPersistJsonRpcProvider: async () => {}, // eslint-disable-line
|
||||||
providerUrl,
|
providerUrl,
|
||||||
provider: new providers.JsonRpcProvider(providerUrl),
|
provider: new providers.JsonRpcProvider(providerUrl),
|
||||||
cors: null,
|
cors: null,
|
||||||
dataDir: null,
|
dataDir: null,
|
||||||
ensResolver: null,
|
ensResolver: null,
|
||||||
isBeeDesktop: false,
|
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
error: null,
|
error: null,
|
||||||
}
|
}
|
||||||
@@ -54,21 +56,22 @@ const initialValues: ContextInterface = {
|
|||||||
export const Context = createContext<ContextInterface>(initialValues)
|
export const Context = createContext<ContextInterface>(initialValues)
|
||||||
export const Consumer = Context.Consumer
|
export const Consumer = Context.Consumer
|
||||||
|
|
||||||
interface Props {
|
interface InitialSettings {
|
||||||
children: ReactNode
|
|
||||||
beeApiUrl?: string
|
beeApiUrl?: string
|
||||||
beeDebugApiUrl?: string
|
beeDebugApiUrl?: string
|
||||||
lockedApiSettings?: boolean
|
lockedApiSettings?: boolean
|
||||||
isBeeDesktop?: boolean
|
isDesktop?: boolean
|
||||||
|
desktopUrl?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Provider({
|
interface Props extends InitialSettings {
|
||||||
children,
|
children: ReactNode
|
||||||
beeApiUrl,
|
}
|
||||||
beeDebugApiUrl,
|
|
||||||
lockedApiSettings: extLockedApiSettings,
|
export function Provider({ children, ...propsSettings }: Props): ReactElement {
|
||||||
isBeeDesktop: extIsBeeDesktop,
|
const desktopUrl = propsSettings.desktopUrl ?? initialValues.desktopUrl
|
||||||
}: Props): ReactElement {
|
const isDesktop = Boolean(propsSettings.isDesktop)
|
||||||
|
|
||||||
const [apiUrl, setApiUrl] = useState<string>(initialValues.apiUrl)
|
const [apiUrl, setApiUrl] = useState<string>(initialValues.apiUrl)
|
||||||
const [apiDebugUrl, setDebugApiUrl] = useState<string>(initialValues.apiDebugUrl)
|
const [apiDebugUrl, setDebugApiUrl] = useState<string>(initialValues.apiDebugUrl)
|
||||||
const [beeApi, setBeeApi] = useState<Bee | null>(null)
|
const [beeApi, setBeeApi] = useState<Bee | null>(null)
|
||||||
@@ -76,35 +79,17 @@ export function Provider({
|
|||||||
const [desktopApiKey, setDesktopApiKey] = useState<string>(initialValues.desktopApiKey)
|
const [desktopApiKey, setDesktopApiKey] = useState<string>(initialValues.desktopApiKey)
|
||||||
const [providerUrl, setProviderUrl] = useState(initialValues.providerUrl)
|
const [providerUrl, setProviderUrl] = useState(initialValues.providerUrl)
|
||||||
const [provider, setProvider] = useState(initialValues.provider)
|
const [provider, setProvider] = useState(initialValues.provider)
|
||||||
const { config, isLoading, error } = useGetBeeConfig()
|
const { config, isLoading, error } = useGetBeeConfig(desktopUrl)
|
||||||
|
|
||||||
const isBeeDesktop = Boolean(extIsBeeDesktop ?? appConfig.BEE_DESKTOP_ENABLED)
|
const url = makeHttpUrl(
|
||||||
|
config?.['api-addr'] ?? sessionStorage.getItem('api_host') ?? propsSettings.beeApiUrl ?? apiUrl,
|
||||||
async function setAndPersistJsonRpcProvider(providerUrl: string) {
|
)
|
||||||
try {
|
const debugUrl = makeHttpUrl(
|
||||||
localStorage.setItem(LocalStorageKeys.providerUrl, providerUrl)
|
config?.['debug-api-addr'] ??
|
||||||
setProviderUrl(providerUrl)
|
sessionStorage.getItem('debug_api_host') ??
|
||||||
setProvider(new providers.JsonRpcProvider(providerUrl))
|
propsSettings.beeDebugApiUrl ??
|
||||||
|
apiDebugUrl,
|
||||||
if (isBeeDesktop) {
|
)
|
||||||
await setJsonRpcInDesktop(providerUrl)
|
|
||||||
await restartBeeNode()
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error) // eslint-disable-line
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeHttpUrl(string: string): string {
|
|
||||||
if (!string.startsWith('http')) {
|
|
||||||
return `http://${string}`
|
|
||||||
}
|
|
||||||
|
|
||||||
return string
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = makeHttpUrl(config?.['api-addr'] || beeApiUrl || apiUrl)
|
|
||||||
const debugUrl = makeHttpUrl(config?.['debug-api-addr'] || beeDebugApiUrl || apiDebugUrl)
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const urlSearchParams = new URLSearchParams(window.location.search)
|
const urlSearchParams = new URLSearchParams(window.location.search)
|
||||||
@@ -144,15 +129,21 @@ export function Provider({
|
|||||||
beeDebugApi,
|
beeDebugApi,
|
||||||
setApiUrl,
|
setApiUrl,
|
||||||
setDebugApiUrl,
|
setDebugApiUrl,
|
||||||
lockedApiSettings: Boolean(extLockedApiSettings),
|
lockedApiSettings: Boolean(propsSettings.lockedApiSettings),
|
||||||
desktopApiKey,
|
desktopApiKey,
|
||||||
|
isDesktop,
|
||||||
|
desktopUrl,
|
||||||
provider,
|
provider,
|
||||||
providerUrl,
|
providerUrl,
|
||||||
cors: config?.['cors-allowed-origins'] ?? null,
|
cors: config?.['cors-allowed-origins'] ?? null,
|
||||||
dataDir: config?.['data-dir'] ?? null,
|
dataDir: config?.['data-dir'] ?? null,
|
||||||
ensResolver: config?.['resolver-options'] ?? null,
|
ensResolver: config?.['resolver-options'] ?? null,
|
||||||
setAndPersistJsonRpcProvider,
|
setAndPersistJsonRpcProvider: setAndPersistJsonRpcProviderClosure(
|
||||||
isBeeDesktop,
|
isDesktop,
|
||||||
|
desktopUrl,
|
||||||
|
setProviderUrl,
|
||||||
|
setProvider,
|
||||||
|
),
|
||||||
isLoading,
|
isLoading,
|
||||||
error,
|
error,
|
||||||
}}
|
}}
|
||||||
@@ -161,3 +152,33 @@ export function Provider({
|
|||||||
</Context.Provider>
|
</Context.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeHttpUrl(string: string): string {
|
||||||
|
if (!string.startsWith('http')) {
|
||||||
|
return `http://${string}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return string
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAndPersistJsonRpcProviderClosure(
|
||||||
|
isDesktop: boolean,
|
||||||
|
desktopUrl: string,
|
||||||
|
setProviderUrl: (url: string) => void,
|
||||||
|
setProvider: (prov: providers.JsonRpcProvider) => void,
|
||||||
|
) {
|
||||||
|
return async (providerUrl: string) => {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(LocalStorageKeys.providerUrl, providerUrl)
|
||||||
|
setProviderUrl(providerUrl)
|
||||||
|
setProvider(new providers.JsonRpcProvider(providerUrl))
|
||||||
|
|
||||||
|
if (isDesktop) {
|
||||||
|
await setJsonRpcInDesktop(desktopUrl, providerUrl)
|
||||||
|
await restartBeeNode(desktopUrl)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error) // eslint-disable-line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -61,7 +61,7 @@ export const ACCOUNT_TABS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const BaseRouter = (): ReactElement => {
|
const BaseRouter = (): ReactElement => {
|
||||||
const { isBeeDesktop } = useContext(SettingsContext)
|
const { isDesktop } = useContext(SettingsContext)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
@@ -88,7 +88,7 @@ const BaseRouter = (): ReactElement => {
|
|||||||
<Route path={ROUTES.ACCOUNT_FEEDS_NEW} element={<CreateNewFeed />} />
|
<Route path={ROUTES.ACCOUNT_FEEDS_NEW} element={<CreateNewFeed />} />
|
||||||
<Route path={ROUTES.ACCOUNT_FEEDS_UPDATE} element={<UpdateFeed />} />
|
<Route path={ROUTES.ACCOUNT_FEEDS_UPDATE} element={<UpdateFeed />} />
|
||||||
<Route path={ROUTES.ACCOUNT_FEEDS_VIEW} element={<FeedSubpage />} />
|
<Route path={ROUTES.ACCOUNT_FEEDS_VIEW} element={<FeedSubpage />} />
|
||||||
{isBeeDesktop && <Route path={ROUTES.ACCOUNT_INVITATIONS} element={<GiftCards />} />}
|
{isDesktop && <Route path={ROUTES.ACCOUNT_INVITATIONS} element={<GiftCards />} />}
|
||||||
</Routes>
|
</Routes>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-51
@@ -1,81 +1,47 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { DaiToken } from '../models/DaiToken'
|
import { DaiToken } from '../models/DaiToken'
|
||||||
import { Token } from '../models/Token'
|
import { Token } from '../models/Token'
|
||||||
import { getJson, postJson, sendRequest } from './net'
|
import { postJson } from './net'
|
||||||
|
import { BEE_DESKTOP_LATEST_RELEASE_PAGE_API } from '../constants'
|
||||||
|
|
||||||
interface DesktopStatus {
|
export async function getBzzPriceAsDai(desktopUrl: string): Promise<Token> {
|
||||||
status: 0 | 1 | 2
|
const response = await axios.get(`${desktopUrl}/price`)
|
||||||
address: string | null
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
config: Record<string, any>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const BEE_DESKTOP_LATEST_RELEASE_PAGE = 'https://github.com/ethersphere/bee-desktop/releases/latest'
|
|
||||||
|
|
||||||
export async function getDesktopStatus(): Promise<DesktopStatus> {
|
|
||||||
const response = await getJson(`${getDesktopHost()}/status`)
|
|
||||||
|
|
||||||
return response as DesktopStatus
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getBzzPriceAsDai(): Promise<Token> {
|
|
||||||
const response = await axios.get(`${getDesktopHost()}/price`)
|
|
||||||
|
|
||||||
return DaiToken.fromDecimal(response.data, 18)
|
return DaiToken.fromDecimal(response.data, 18)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function upgradeToLightNode(rpcProvider: string): Promise<void> {
|
export async function upgradeToLightNode(desktopUrl: string, rpcProvider: string): Promise<void> {
|
||||||
await updateDesktopConfiguration({
|
await updateDesktopConfiguration(desktopUrl, {
|
||||||
'chain-enable': true,
|
'chain-enable': true,
|
||||||
'swap-enable': true,
|
'swap-enable': true,
|
||||||
'swap-endpoint': rpcProvider,
|
'swap-endpoint': rpcProvider,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setJsonRpcInDesktop(value: string): Promise<void> {
|
export async function setJsonRpcInDesktop(desktopUrl: string, value: string): Promise<void> {
|
||||||
await updateDesktopConfiguration({
|
await updateDesktopConfiguration(desktopUrl, {
|
||||||
'swap-endpoint': value,
|
'swap-endpoint': value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateDesktopConfiguration(values: Record<string, unknown>): Promise<void> {
|
async function updateDesktopConfiguration(desktopUrl: string, values: Record<string, unknown>): Promise<void> {
|
||||||
await postJson(`${getDesktopHost()}/config`, values)
|
await postJson(`${desktopUrl}/config`, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function restartBeeNode(): Promise<void> {
|
export async function restartBeeNode(desktopUrl: string): Promise<void> {
|
||||||
await postJson(`${getDesktopHost()}/restart`)
|
await postJson(`${desktopUrl}/restart`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createGiftWallet(address: string): Promise<void> {
|
export async function createGiftWallet(desktopUrl: string, address: string): Promise<void> {
|
||||||
await postJson(`${getDesktopHost()}/gift-wallet/${address}`)
|
await postJson(`${desktopUrl}/gift-wallet/${address}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function performSwap(daiAmount: string): Promise<void> {
|
export async function performSwap(desktopUrl: string, daiAmount: string): Promise<void> {
|
||||||
await postJson(`${getDesktopHost()}/swap`, { dai: daiAmount })
|
await postJson(`${desktopUrl}/swap`, { dai: daiAmount })
|
||||||
}
|
|
||||||
|
|
||||||
export async function getBeeDesktopLogs(): Promise<string> {
|
|
||||||
const response = await sendRequest(`${getDesktopHost()}/logs/bee-desktop`, 'GET')
|
|
||||||
|
|
||||||
return response as unknown as string
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getBeeLogs(): Promise<string> {
|
|
||||||
const response = await sendRequest(`${getDesktopHost()}/logs/bee`, 'GET')
|
|
||||||
|
|
||||||
return response as unknown as string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getLatestBeeDesktopVersion(): Promise<string> {
|
export async function getLatestBeeDesktopVersion(): Promise<string> {
|
||||||
const response = await (await fetch('https://api.github.com/repos/ethersphere/bee-desktop/releases/latest')).json()
|
const response = await (await fetch(BEE_DESKTOP_LATEST_RELEASE_PAGE_API)).json()
|
||||||
|
|
||||||
return response.tag_name.replace('v', '') // We get for example "v0.12.1"
|
return response.tag_name.replace('v', '') // We get for example "v0.12.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDesktopHost(): string {
|
|
||||||
if (process.env.REACT_APP_BEE_DESKTOP_URL) {
|
|
||||||
return process.env.REACT_APP_BEE_DESKTOP_URL
|
|
||||||
}
|
|
||||||
|
|
||||||
return `http://${window.location.host}`
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
import { config } from '../config'
|
|
||||||
import * as Sentry from '@sentry/react'
|
|
||||||
import packageJson from '../../package.json'
|
|
||||||
import { BrowserTracing } from '@sentry/tracing'
|
|
||||||
import { getBeeDesktopLogs, getBeeLogs } from './desktop'
|
|
||||||
|
|
||||||
export async function initSentry(): Promise<void> {
|
|
||||||
let tunnelAvailable
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await fetch(`${config.BEE_DESKTOP_URL}/sentry`, { method: 'OPTIONS' })
|
|
||||||
|
|
||||||
if (result.status === 204) {
|
|
||||||
tunnelAvailable = true
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// There was an error, so tunnel is not available
|
|
||||||
tunnelAvailable = false
|
|
||||||
}
|
|
||||||
|
|
||||||
Sentry.init({
|
|
||||||
dsn: config.SENTRY_KEY,
|
|
||||||
release: packageJson.version,
|
|
||||||
environment: config.SENTRY_ENVIRONMENT,
|
|
||||||
tunnel: tunnelAvailable ? `${config.BEE_DESKTOP_URL}/sentry` : undefined,
|
|
||||||
integrations: [new BrowserTracing({ tracingOrigins: [config.BEE_DESKTOP_URL] })],
|
|
||||||
tracesSampleRate: 0.4,
|
|
||||||
beforeSend: async (event, hint) => {
|
|
||||||
hint.attachments = []
|
|
||||||
|
|
||||||
try {
|
|
||||||
// This will fail if we are not running in Bee Desktop, but that is alright
|
|
||||||
hint.attachments.push({ filename: 'bee-desktop.log', data: await getBeeDesktopLogs() })
|
|
||||||
// eslint-disable-next-line no-empty
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// This will fail if we are not running in Bee Desktop, but that is alright
|
|
||||||
hint.attachments.push({ filename: 'bee.log', data: await getBeeLogs() })
|
|
||||||
// eslint-disable-next-line no-empty
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
return event
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user