mirror of
https://github.com/oceanprotocol/commons.git
synced 2023-03-15 18:03:00 +01:00
Merge pull request #101 from oceanprotocol/feature/web3-detection
Refactor web3 detection and bootstrapping process
This commit is contained in:
commit
2aa46699a2
339
client/package-lock.json
generated
339
client/package-lock.json
generated
@ -1044,6 +1044,16 @@
|
|||||||
"integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==",
|
"integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@jest/types": {
|
||||||
|
"version": "24.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jest/types/-/types-24.7.0.tgz",
|
||||||
|
"integrity": "sha512-ipJUa2rFWiKoBqMKP63Myb6h9+iT3FHRTF2M8OR6irxWzItisa8i4dcSg14IbvmXUnBlHBlUQPYUHWyX3UPpYA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/istanbul-lib-coverage": "^2.0.0",
|
||||||
|
"@types/yargs": "^12.0.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@mrmlnc/readdir-enhanced": {
|
"@mrmlnc/readdir-enhanced": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
||||||
@ -1071,15 +1081,16 @@
|
|||||||
"integrity": "sha512-c1LvaH+e1tzow0gZLwSWe19ap+DrZuNmZfxBdwEVEPQXarI0jTXa5qVDoiBow8kBWaqSIUgFAzQOJW8rKdlS1A=="
|
"integrity": "sha512-c1LvaH+e1tzow0gZLwSWe19ap+DrZuNmZfxBdwEVEPQXarI0jTXa5qVDoiBow8kBWaqSIUgFAzQOJW8rKdlS1A=="
|
||||||
},
|
},
|
||||||
"@oceanprotocol/squid": {
|
"@oceanprotocol/squid": {
|
||||||
"version": "0.5.3",
|
"version": "0.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/squid/-/squid-0.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/squid/-/squid-0.5.4.tgz",
|
||||||
"integrity": "sha512-tPOg+z9hYYN/6QoM7BDw1N5uQQQvbEj8xITtC1aYEoAM1tHaauAIecQjVQQaumkepaz8F1t1kmWUP2t7RQVqgg==",
|
"integrity": "sha512-ozOTLNJX0GiKShum09e13LZ9zUKedWA5G8+H3Pwu3+lbdLYkRSeCg5eLXDUJxUN12+leiCnW/TZDoV9ZOmcd4w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@oceanprotocol/keeper-contracts": "^0.9.0",
|
"@oceanprotocol/keeper-contracts": "^0.9.1",
|
||||||
"bignumber.js": "^8.0.1",
|
"bignumber.js": "^8.1.1",
|
||||||
"deprecated-decorator": "^0.1.6",
|
"deprecated-decorator": "^0.1.6",
|
||||||
"ethereumjs-util": "^6.0.0",
|
"ethereumjs-util": "^6.1.0",
|
||||||
"node-fetch": "^2.3.0",
|
"node-fetch": "^2.3.0",
|
||||||
|
"save-file": "^2.3.1",
|
||||||
"uuid": "^3.3.2",
|
"uuid": "^3.3.2",
|
||||||
"web3": "1.0.0-beta.37",
|
"web3": "1.0.0-beta.37",
|
||||||
"whatwg-url": "^7.0.0"
|
"whatwg-url": "^7.0.0"
|
||||||
@ -1106,6 +1117,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/typographies/-/typographies-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/typographies/-/typographies-0.1.0.tgz",
|
||||||
"integrity": "sha512-kMsZsqvzpz9KzVbVZzllwhPoIC3zbqsdRrClagZL/C2PHzgLrKGC1kYn3gPt0RMIFg9ZjrwieKaxlgIK9i9zzg=="
|
"integrity": "sha512-kMsZsqvzpz9KzVbVZzllwhPoIC3zbqsdRrClagZL/C2PHzgLrKGC1kYn3gPt0RMIFg9ZjrwieKaxlgIK9i9zzg=="
|
||||||
},
|
},
|
||||||
|
"@sheerun/mutationobserver-shim": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@svgr/babel-plugin-add-jsx-attribute": {
|
"@svgr/babel-plugin-add-jsx-attribute": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz",
|
||||||
@ -1394,6 +1411,12 @@
|
|||||||
"integrity": "sha1-kU2r1QVG2bAUKAbkLHK8fCt+B4c=",
|
"integrity": "sha1-kU2r1QVG2bAUKAbkLHK8fCt+B4c=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/istanbul-lib-coverage": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-eAtOAFZefEnfJiRFQBGw1eYqa5GTLCZ1y86N0XSI/D6EB+E8z6VPV/UL7Gi5UEclFqoQk+6NRqEDsfmDLXn8sg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/jest": {
|
"@types/jest": {
|
||||||
"version": "24.0.11",
|
"version": "24.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.11.tgz",
|
||||||
@ -1552,6 +1575,12 @@
|
|||||||
"@types/underscore": "*"
|
"@types/underscore": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/yargs": {
|
||||||
|
"version": "12.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.12.tgz",
|
||||||
|
"integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@webassemblyjs/ast": {
|
"@webassemblyjs/ast": {
|
||||||
"version": "1.7.11",
|
"version": "1.7.11",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz",
|
||||||
@ -2417,6 +2446,11 @@
|
|||||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"atob-lite": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY="
|
||||||
|
},
|
||||||
"autoprefixer": {
|
"autoprefixer": {
|
||||||
"version": "9.5.1",
|
"version": "9.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.5.1.tgz",
|
||||||
@ -4818,6 +4852,26 @@
|
|||||||
"randomfill": "^1.0.3"
|
"randomfill": "^1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"css": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"source-map": "^0.6.1",
|
||||||
|
"source-map-resolve": "^0.5.2",
|
||||||
|
"urix": "^0.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"source-map": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"css-blank-pseudo": {
|
"css-blank-pseudo": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz",
|
||||||
@ -5217,6 +5271,12 @@
|
|||||||
"integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
|
"integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"css.escape": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
|
||||||
|
"integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"cssdb": {
|
"cssdb": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz",
|
||||||
@ -5920,6 +5980,12 @@
|
|||||||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"diff-sequences": {
|
||||||
|
"version": "24.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.3.0.tgz",
|
||||||
|
"integrity": "sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"diffie-hellman": {
|
"diffie-hellman": {
|
||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
|
||||||
@ -6017,6 +6083,47 @@
|
|||||||
"entities": "^1.1.1"
|
"entities": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dom-testing-library": {
|
||||||
|
"version": "3.19.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-testing-library/-/dom-testing-library-3.19.1.tgz",
|
||||||
|
"integrity": "sha512-cv5k+OiDhmdjHimDcal5Yz6yHv6nXwhzW3wyXrFeIGk7jSdqqFxqzhjriPvYMrV8XNNZHUDwp0dTu6SeCtO/4w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.3.4",
|
||||||
|
"@sheerun/mutationobserver-shim": "^0.3.2",
|
||||||
|
"pretty-format": "^24.5.0",
|
||||||
|
"wait-for-expect": "^1.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pretty-format": {
|
||||||
|
"version": "24.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz",
|
||||||
|
"integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@jest/types": "^24.7.0",
|
||||||
|
"ansi-regex": "^4.0.0",
|
||||||
|
"ansi-styles": "^3.2.0",
|
||||||
|
"react-is": "^16.8.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"dom-walk": {
|
"dom-walk": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
|
||||||
@ -6090,6 +6197,11 @@
|
|||||||
"create-hmac": "^1.1.4"
|
"create-hmac": "^1.1.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dtype": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-zQUjI84GFETs0uj1dI9popvihDQ="
|
||||||
|
},
|
||||||
"duplexer": {
|
"duplexer": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||||
@ -7487,6 +7599,11 @@
|
|||||||
"schema-utils": "^1.0.0"
|
"schema-utils": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"file-saver": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-dCB3K7/BvAcUmtmh1DzFdv0eXSVJ9IAFt1mw3XZfAexodNRoE29l3xB2EX4wH2q8m/UTzwzEPq/ArYk98kUkBQ=="
|
||||||
|
},
|
||||||
"file-type": {
|
"file-type": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
|
||||||
@ -7620,6 +7737,14 @@
|
|||||||
"integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=",
|
"integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"flatten-vertex-data": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/flatten-vertex-data/-/flatten-vertex-data-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-BvCBFK2NZqerFTdMDgqfHBwxYWnxeCkwONsw6PvBMcUXqo8U/KDWwmXhqx1x2kLIg7DqIsJfOaJFOmlua3Lxuw==",
|
||||||
|
"requires": {
|
||||||
|
"dtype": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flush-write-stream": {
|
"flush-write-stream": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
|
||||||
@ -10005,6 +10130,11 @@
|
|||||||
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
|
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"is-base64": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-base64/-/is-base64-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-WRRyllsGXJM7ZN7gPTCCQ/6wNPTRDwiWdPK66l5sJzcU/oOzcIcRRf0Rux8bkpox/1yjt0F6VJRsQOIG2qz5sg=="
|
||||||
|
},
|
||||||
"is-binary-path": {
|
"is-binary-path": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
|
||||||
@ -10014,6 +10144,11 @@
|
|||||||
"binary-extensions": "^1.0.0"
|
"binary-extensions": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-blob": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-blob/-/is-blob-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-o9fZb+HD/wZex84nwsIea6ksGDI="
|
||||||
|
},
|
||||||
"is-buffer": {
|
"is-buffer": {
|
||||||
"version": "1.1.6",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||||
@ -10861,6 +10996,123 @@
|
|||||||
"detect-newline": "^2.1.0"
|
"detect-newline": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jest-dom": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/jest-dom/-/jest-dom-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-V9LdySiA74/spcAKEG3FRMRKnisKlcYr3EeCNYI4n7CWNE7uYg5WoBUHeGXirjWjRYLLZ5vx8rUaR/6x6o75oQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^2.4.1",
|
||||||
|
"css": "^2.2.3",
|
||||||
|
"css.escape": "^1.5.1",
|
||||||
|
"jest-diff": "^24.0.0",
|
||||||
|
"jest-matcher-utils": "^24.0.0",
|
||||||
|
"lodash": "^4.17.11",
|
||||||
|
"pretty-format": "^24.0.0",
|
||||||
|
"redent": "^2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chalk": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indent-string": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
|
||||||
|
"integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"jest-diff": {
|
||||||
|
"version": "24.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz",
|
||||||
|
"integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^2.0.1",
|
||||||
|
"diff-sequences": "^24.3.0",
|
||||||
|
"jest-get-type": "^24.3.0",
|
||||||
|
"pretty-format": "^24.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jest-get-type": {
|
||||||
|
"version": "24.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz",
|
||||||
|
"integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"jest-matcher-utils": {
|
||||||
|
"version": "24.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz",
|
||||||
|
"integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^2.0.1",
|
||||||
|
"jest-diff": "^24.7.0",
|
||||||
|
"jest-get-type": "^24.3.0",
|
||||||
|
"pretty-format": "^24.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pretty-format": {
|
||||||
|
"version": "24.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz",
|
||||||
|
"integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@jest/types": "^24.7.0",
|
||||||
|
"ansi-regex": "^4.0.0",
|
||||||
|
"ansi-styles": "^3.2.0",
|
||||||
|
"react-is": "^16.8.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redent": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"indent-string": "^3.0.0",
|
||||||
|
"strip-indent": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"strip-indent": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"jest-each": {
|
"jest-each": {
|
||||||
"version": "23.6.0",
|
"version": "23.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.6.0.tgz",
|
||||||
@ -19382,6 +19634,16 @@
|
|||||||
"shallowequal": "^1.0.1"
|
"shallowequal": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-testing-library": {
|
||||||
|
"version": "6.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-testing-library/-/react-testing-library-6.1.2.tgz",
|
||||||
|
"integrity": "sha512-z69lhRDGe7u/NOjDCeFRoe1cB5ckJ4656n0tj/Fdcr6OoBUu7q9DBw0ftR7v5i3GRpdSWelnvl+feZFOyXyxwg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.4.2",
|
||||||
|
"dom-testing-library": "^3.19.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-transition-group": {
|
"react-transition-group": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-3.0.0.tgz",
|
||||||
@ -20524,6 +20786,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"save-file": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/save-file/-/save-file-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-VOD2Ojb1/kuj0XbvSXzZ5xr4rRSZD8f+HzKWGztXNp93gBQDj3njFt9HMhmLtnwd7q0BjJkzLXqd8M2+PFS1qg==",
|
||||||
|
"requires": {
|
||||||
|
"file-saver": "^2.0.0-rc.4",
|
||||||
|
"is-blob": "^1.0.0",
|
||||||
|
"is-buffer": "^2.0.0",
|
||||||
|
"simple-mime": "^0.1.0",
|
||||||
|
"to-array-buffer": "^3.2.0",
|
||||||
|
"write": "^1.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"is-buffer": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw=="
|
||||||
|
},
|
||||||
|
"write": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
|
||||||
|
"requires": {
|
||||||
|
"mkdirp": "^0.5.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"sax": {
|
"sax": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||||
@ -20856,6 +21146,11 @@
|
|||||||
"simple-concat": "^1.0.0"
|
"simple-concat": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"simple-mime": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-mime/-/simple-mime-0.1.0.tgz",
|
||||||
|
"integrity": "sha1-lfUXxPRm18/1YacfydqyWW6p7y4="
|
||||||
|
},
|
||||||
"simple-swizzle": {
|
"simple-swizzle": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||||
@ -21416,6 +21711,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"string-to-arraybuffer": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-to-arraybuffer/-/string-to-arraybuffer-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-DaGZidzi93dwjQen5I2osxR9ERS/R7B1PFyufNMnzhj+fmlDQAc1DSDIJVJhgI8Oq221efIMbABUBdPHDRt43Q==",
|
||||||
|
"requires": {
|
||||||
|
"atob-lite": "^2.0.0",
|
||||||
|
"is-base64": "^0.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||||
@ -21958,6 +22262,23 @@
|
|||||||
"integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
|
"integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"to-array-buffer": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-array-buffer/-/to-array-buffer-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-zN33mwi0gpL+7xW1ITLfJ48CEj6ZQW0ZAP0MU+2W3kEY0PAIncyuxmD4OqkUVhPAbTP7amq9j/iwvZKYS+lzSQ==",
|
||||||
|
"requires": {
|
||||||
|
"flatten-vertex-data": "^1.0.2",
|
||||||
|
"is-blob": "^2.0.1",
|
||||||
|
"string-to-arraybuffer": "^1.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"is-blob": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-blob/-/is-blob-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-SmqVJYMnAeqrKLcwq6TXu1rpAg3yipVlMZIqR5u510rxoOzJGW9GQY6g+WtWkcc44pjbWAuxzZDCkbgf5e6r0Q=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"to-arraybuffer": {
|
"to-arraybuffer": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
|
||||||
@ -22644,6 +22965,12 @@
|
|||||||
"browser-process-hrtime": "^0.1.2"
|
"browser-process-hrtime": "^0.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"wait-for-expect": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/wait-for-expect/-/wait-for-expect-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-vd9JOqqEcBbCDhARWhW85ecjaEcfBLuXgVBqatfS3iw6oU4kzAcs+sCNjF+TC9YHPImCW7ypsuQc+htscIAQCw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"walker": {
|
"walker": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
|
||||||
|
@ -46,8 +46,10 @@
|
|||||||
"@types/react-router-dom": "^4.3.1",
|
"@types/react-router-dom": "^4.3.1",
|
||||||
"@types/react-transition-group": "^2.8.0",
|
"@types/react-transition-group": "^2.8.0",
|
||||||
"@types/web3": "^1.0.18",
|
"@types/web3": "^1.0.18",
|
||||||
|
"jest-dom": "^3.1.3",
|
||||||
"node-sass": "^4.11.0",
|
"node-sass": "^4.11.0",
|
||||||
"react-scripts": "^2.1.8",
|
"react-scripts": "^2.1.8",
|
||||||
|
"react-testing-library": "^6.1.2",
|
||||||
"typescript": "^3.4.2"
|
"typescript": "^3.4.2"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -1,275 +1,44 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import Web3 from 'web3'
|
|
||||||
import { BrowserRouter as Router } from 'react-router-dom'
|
import { BrowserRouter as Router } from 'react-router-dom'
|
||||||
import { Logger } from '@oceanprotocol/squid'
|
|
||||||
import Header from './components/organisms/Header'
|
import Header from './components/organisms/Header'
|
||||||
import Footer from './components/organisms/Footer'
|
import Footer from './components/organisms/Footer'
|
||||||
import Spinner from './components/atoms/Spinner'
|
import Spinner from './components/atoms/Spinner'
|
||||||
import { User } from './context/User'
|
import { User } from './context'
|
||||||
import { provideOcean } from './ocean'
|
import UserProvider from './context/UserProvider'
|
||||||
import Routes from './Routes'
|
import Routes from './Routes'
|
||||||
import './styles/global.scss'
|
import './styles/global.scss'
|
||||||
import styles from './App.module.scss'
|
import styles from './App.module.scss'
|
||||||
|
|
||||||
import {
|
export default class App extends Component {
|
||||||
nodeHost,
|
|
||||||
nodePort,
|
|
||||||
nodeScheme,
|
|
||||||
faucetHost,
|
|
||||||
faucetPort,
|
|
||||||
faucetScheme
|
|
||||||
} from './config/config'
|
|
||||||
|
|
||||||
const POLL_ACCOUNTS = 1000 // every 1s
|
|
||||||
const POLL_NETWORK = POLL_ACCOUNTS * 60 // every 1 min
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
web3: Web3
|
|
||||||
ethereum: any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AppState {
|
|
||||||
isLogged: boolean
|
|
||||||
isLoading: boolean
|
|
||||||
isWeb3: boolean
|
|
||||||
isNile: boolean
|
|
||||||
account: string
|
|
||||||
balance: {
|
|
||||||
eth: number
|
|
||||||
ocn: number
|
|
||||||
}
|
|
||||||
network: string
|
|
||||||
web3: Web3
|
|
||||||
ocean: any
|
|
||||||
startLogin: () => void
|
|
||||||
message: string
|
|
||||||
}
|
|
||||||
|
|
||||||
class App extends Component<{}, AppState> {
|
|
||||||
private accountsInterval: any
|
|
||||||
private networkInterval: any
|
|
||||||
|
|
||||||
public startLogin = (event?: any) => {
|
|
||||||
if (event) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
this.startLoginProcess()
|
|
||||||
}
|
|
||||||
|
|
||||||
private requestFromFaucet = async () => {
|
|
||||||
if (this.state.account !== '') {
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`${faucetScheme}://${faucetHost}:${faucetPort}/faucet`,
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
Accept: 'application/json',
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
address: this.state.account,
|
|
||||||
agent: 'commons'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return response.json()
|
|
||||||
} catch (error) {
|
|
||||||
Logger.log('requestFromFaucet', error)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// no account found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public state = {
|
|
||||||
isLogged: false,
|
|
||||||
isLoading: true,
|
|
||||||
isWeb3: false,
|
|
||||||
isNile: false,
|
|
||||||
balance: {
|
|
||||||
eth: 0,
|
|
||||||
ocn: 0
|
|
||||||
},
|
|
||||||
network: '',
|
|
||||||
web3: new Web3(
|
|
||||||
new Web3.providers.HttpProvider(
|
|
||||||
`${nodeScheme}://${nodeHost}:${nodePort}`
|
|
||||||
)
|
|
||||||
),
|
|
||||||
account: '',
|
|
||||||
ocean: {} as any,
|
|
||||||
startLogin: this.startLogin,
|
|
||||||
requestFromFaucet: this.requestFromFaucet,
|
|
||||||
message: 'Connecting to Ocean...'
|
|
||||||
}
|
|
||||||
|
|
||||||
public async componentDidMount() {
|
|
||||||
await this.bootstrap()
|
|
||||||
this.initAccountsPoll()
|
|
||||||
this.initNetworkPoll()
|
|
||||||
}
|
|
||||||
|
|
||||||
private bootstrap = async () => {
|
|
||||||
try {
|
|
||||||
if (window.web3) {
|
|
||||||
const web3 = new Web3(window.web3.currentProvider)
|
|
||||||
const { ocean } = await provideOcean(web3)
|
|
||||||
const accounts = await ocean.accounts.list()
|
|
||||||
const network = await ocean.keeper.getNetworkName()
|
|
||||||
const isNile = network === 'Nile'
|
|
||||||
if (accounts.length > 0) {
|
|
||||||
const balance = await accounts[0].getBalance()
|
|
||||||
this.setState({
|
|
||||||
isWeb3: true,
|
|
||||||
isLogged: true,
|
|
||||||
isNile,
|
|
||||||
ocean,
|
|
||||||
web3,
|
|
||||||
balance,
|
|
||||||
network,
|
|
||||||
account: accounts[0].getId(),
|
|
||||||
isLoading: false
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
isWeb3: true,
|
|
||||||
isNile,
|
|
||||||
ocean,
|
|
||||||
web3,
|
|
||||||
network,
|
|
||||||
isLoading: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const { ocean } = await provideOcean(this.state.web3)
|
|
||||||
const network = await ocean.keeper.getNetworkName()
|
|
||||||
const isNile = network === 'Nile'
|
|
||||||
this.setState({
|
|
||||||
isNile,
|
|
||||||
ocean,
|
|
||||||
network,
|
|
||||||
isLoading: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// error in bootstrap process
|
|
||||||
// show error connecting to ocean
|
|
||||||
Logger.log('web3 error', e)
|
|
||||||
this.setState({
|
|
||||||
isLoading: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private initAccountsPoll() {
|
|
||||||
if (!this.accountsInterval) {
|
|
||||||
this.accountsInterval = setInterval(
|
|
||||||
this.fetchAccounts,
|
|
||||||
POLL_ACCOUNTS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private initNetworkPoll() {
|
|
||||||
if (!this.networkInterval) {
|
|
||||||
this.networkInterval = setInterval(this.fetchNetwork, POLL_NETWORK)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fetchAccounts = async () => {
|
|
||||||
const { web3 } = window
|
|
||||||
const { ocean } = this.state
|
|
||||||
|
|
||||||
if (web3) {
|
|
||||||
const accounts = await ocean.accounts.list()
|
|
||||||
|
|
||||||
if (accounts.length > 0) {
|
|
||||||
const account = accounts[0].getId()
|
|
||||||
|
|
||||||
if (account !== this.state.account) {
|
|
||||||
const balance = await accounts[0].getBalance()
|
|
||||||
this.setState({ account, balance, isLogged: true })
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.state.isLogged !== false &&
|
|
||||||
this.setState({ isLogged: false, account: '' })
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.state.isWeb3 !== false &&
|
|
||||||
this.setState({
|
|
||||||
isWeb3: false,
|
|
||||||
isLogged: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fetchNetwork = async () => {
|
|
||||||
const { web3 } = window
|
|
||||||
const { ocean } = this.state
|
|
||||||
|
|
||||||
if (web3) {
|
|
||||||
const network = await ocean.keeper.getNetworkName()
|
|
||||||
const isNile = network === 'Nile'
|
|
||||||
|
|
||||||
network !== this.state.network && this.setState({ isNile, network })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private startLoginProcess = async () => {
|
|
||||||
try {
|
|
||||||
if (this.state.isWeb3 && window.ethereum) {
|
|
||||||
await window.ethereum.enable()
|
|
||||||
const accounts = await this.state.ocean.accounts.list()
|
|
||||||
if (accounts.length > 0) {
|
|
||||||
const balance = await accounts[0].getBalance()
|
|
||||||
this.setState({
|
|
||||||
isLogged: true,
|
|
||||||
balance,
|
|
||||||
account: accounts[0].getId()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// not unlocked
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// no metamask/mist, show installation guide!
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
Logger.log('error logging', e)
|
|
||||||
// error in logging process
|
|
||||||
// show error
|
|
||||||
// rerun bootstrap process?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<div className={styles.app}>
|
<UserProvider>
|
||||||
<User.Provider value={this.state}>
|
<div className={styles.app}>
|
||||||
<Router>
|
<Router>
|
||||||
<>
|
<>
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
<main className={styles.main}>
|
<main className={styles.main}>
|
||||||
{this.state.isLoading ? (
|
<User.Consumer>
|
||||||
<div className={styles.loader}>
|
{states =>
|
||||||
<Spinner message={this.state.message} />
|
states.isLoading ? (
|
||||||
</div>
|
<div className={styles.loader}>
|
||||||
) : (
|
<Spinner
|
||||||
<Routes />
|
message={states.message}
|
||||||
)}
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Routes />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</User.Consumer>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
</Router>
|
</Router>
|
||||||
</User.Provider>
|
</div>
|
||||||
</div>
|
</UserProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Route, Switch } from 'react-router-dom'
|
import { Route, Switch } from 'react-router-dom'
|
||||||
import withTracker from './withTracker'
|
import withTracker from './hoc/withTracker'
|
||||||
|
|
||||||
import About from './routes/About'
|
import About from './routes/About'
|
||||||
import Details from './routes/Details/'
|
import Details from './routes/Details/'
|
||||||
|
@ -1,16 +1,54 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import { render } from 'react-testing-library'
|
||||||
|
import { BrowserRouter as Router } from 'react-router-dom'
|
||||||
import Button from './Button'
|
import Button from './Button'
|
||||||
|
|
||||||
it('Button renders without crashing', () => {
|
describe('Button', () => {
|
||||||
const div = document.createElement('div')
|
it('default renders correctly without crashing', () => {
|
||||||
ReactDOM.render(
|
const { getByTestId } = render(
|
||||||
<>
|
<Button data-testid="button-default">I am a default button</Button>
|
||||||
<Button>I am a button</Button>
|
)
|
||||||
<Button primary>I am a primary button</Button>
|
expect(getByTestId('button-default')).toHaveTextContent('default')
|
||||||
<Button href="https://hello.com">I am a button</Button>
|
})
|
||||||
</>,
|
|
||||||
div
|
it('primary renders correctly without crashing', () => {
|
||||||
)
|
const { getByTestId } = render(
|
||||||
ReactDOM.unmountComponentAtNode(div)
|
<Button data-testid="button-primary" primary>
|
||||||
|
I am a primary button
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
expect(getByTestId('button-primary')).toHaveTextContent('primary')
|
||||||
|
expect(getByTestId('button-primary').className).toMatch(/buttonPrimary/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Link renders correctly without crashing', () => {
|
||||||
|
const { getByTestId } = render(
|
||||||
|
<Router>
|
||||||
|
<Button data-testid="button-to" to="https://hello.com">
|
||||||
|
I am a Link button
|
||||||
|
</Button>
|
||||||
|
</Router>
|
||||||
|
)
|
||||||
|
expect(getByTestId('button-to')).toHaveTextContent('Link')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('href renders correctly without crashing', () => {
|
||||||
|
const { getByTestId } = render(
|
||||||
|
<Button data-testid="button-href" href="https://hello.com">
|
||||||
|
I am a href button
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
expect(getByTestId('button-href')).toHaveTextContent('href')
|
||||||
|
expect(getByTestId('button-href').nodeName).toBe('A')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('link renders correctly without crashing', () => {
|
||||||
|
const { getByTestId } = render(
|
||||||
|
<Button data-testid="button-link" link>
|
||||||
|
I am a link button
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
expect(getByTestId('button-link')).toHaveTextContent('link')
|
||||||
|
expect(getByTestId('button-link').className).toMatch(/link/)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import cx from 'classnames'
|
import cx from 'classnames'
|
||||||
import { User } from '../../../context/User'
|
import { User } from '../../../context'
|
||||||
import styles from './Indicator.module.scss'
|
import styles from './Indicator.module.scss'
|
||||||
|
|
||||||
const Indicator = ({
|
const Indicator = ({
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { PureComponent } from 'react'
|
import React, { PureComponent } from 'react'
|
||||||
import Dotdotdot from 'react-dotdotdot'
|
import Dotdotdot from 'react-dotdotdot'
|
||||||
import { User } from '../../../context/User'
|
import { User } from '../../../context'
|
||||||
import styles from './Popover.module.scss'
|
import styles from './Popover.module.scss'
|
||||||
|
|
||||||
export default class Popover extends PureComponent<{
|
export default class Popover extends PureComponent<{
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import React, { PureComponent } from 'react'
|
import React, { PureComponent } from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Logger } from '@oceanprotocol/squid'
|
import { Logger } from '@oceanprotocol/squid'
|
||||||
import { User } from '../../context/User'
|
import { User } from '../../context'
|
||||||
import Spinner from '../atoms/Spinner'
|
import Spinner from '../atoms/Spinner'
|
||||||
import Asset from '../molecules/Asset'
|
import Asset from '../molecules/Asset'
|
||||||
import Web3message from './Web3message'
|
|
||||||
import styles from './AssetsUser.module.scss'
|
import styles from './AssetsUser.module.scss'
|
||||||
|
|
||||||
export default class AssetsUser extends PureComponent<
|
export default class AssetsUser extends PureComponent<
|
||||||
@ -13,32 +12,42 @@ export default class AssetsUser extends PureComponent<
|
|||||||
> {
|
> {
|
||||||
public state = { results: [], isLoading: true }
|
public state = { results: [], isLoading: true }
|
||||||
|
|
||||||
|
public _isMounted: boolean = false
|
||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
this.searchOcean()
|
this._isMounted = true
|
||||||
|
this._isMounted && this.searchOcean()
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentWillUnmount() {
|
||||||
|
this._isMounted = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private async searchOcean() {
|
private async searchOcean() {
|
||||||
if (this.context.account) {
|
const { account, ocean } = this.context
|
||||||
this.context.ocean.keeper.didRegistry.contract.getPastEvents(
|
|
||||||
|
if (account) {
|
||||||
|
ocean.keeper.didRegistry.contract.getPastEvents(
|
||||||
'DIDAttributeRegistered',
|
'DIDAttributeRegistered',
|
||||||
{
|
{
|
||||||
filter: { _owner: this.context.account },
|
filter: { _owner: account },
|
||||||
fromBlock: 0,
|
fromBlock: 0,
|
||||||
toBlock: 'latest'
|
toBlock: 'latest'
|
||||||
},
|
},
|
||||||
async (error: any, events: any) => {
|
async (error: any, events: any) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
Logger.log('error retrieving', error)
|
Logger.log('error retrieving', error)
|
||||||
this.setState({ isLoading: false })
|
this._isMounted && this.setState({ isLoading: false })
|
||||||
} else {
|
} else {
|
||||||
const results = []
|
const results = []
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
const ddo = await this.context.ocean.assets.resolve(
|
const ddo = await ocean.assets.resolve(
|
||||||
`did:op:${event.returnValues._did.substring(2)}`
|
`did:op:${event.returnValues._did.substring(2)}`
|
||||||
)
|
)
|
||||||
results.push(ddo)
|
results.push(ddo)
|
||||||
}
|
}
|
||||||
this.setState({ results, isLoading: false })
|
this._isMounted &&
|
||||||
|
this.setState({ results, isLoading: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -48,48 +57,51 @@ export default class AssetsUser extends PureComponent<
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return this.context.isNile && this.context.account ? (
|
const { account, isNile } = this.context
|
||||||
<div className={styles.assetsUser}>
|
|
||||||
{this.props.recent && (
|
|
||||||
<h2 className={styles.subTitle}>
|
|
||||||
Your Latest Published Data Sets
|
|
||||||
</h2>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{this.state.isLoading ? (
|
return (
|
||||||
<Spinner />
|
isNile &&
|
||||||
) : this.state.results.length ? (
|
account && (
|
||||||
<>
|
<div className={styles.assetsUser}>
|
||||||
{this.state.results
|
{this.props.recent && (
|
||||||
.slice(
|
<h2 className={styles.subTitle}>
|
||||||
0,
|
Your Latest Published Data Sets
|
||||||
this.props.recent
|
</h2>
|
||||||
? this.props.recent
|
)}
|
||||||
: undefined
|
|
||||||
)
|
{this.state.isLoading ? (
|
||||||
.filter(asset => !!asset)
|
<Spinner />
|
||||||
.map((asset: any) => (
|
) : this.state.results.length ? (
|
||||||
<Asset
|
<>
|
||||||
list={this.props.list}
|
{this.state.results
|
||||||
key={asset.id}
|
.slice(
|
||||||
asset={asset}
|
0,
|
||||||
/>
|
this.props.recent
|
||||||
))}
|
? this.props.recent
|
||||||
{this.props.recent && (
|
: undefined
|
||||||
<Link className={styles.link} to={'/history'}>
|
)
|
||||||
All Data Sets
|
.filter(asset => !!asset)
|
||||||
</Link>
|
.map((asset: any) => (
|
||||||
)}
|
<Asset
|
||||||
</>
|
list={this.props.list}
|
||||||
) : (
|
key={asset.id}
|
||||||
<div className={styles.empty}>
|
asset={asset}
|
||||||
<p>No Data Sets Yet.</p>
|
/>
|
||||||
<Link to="/publish">+ Publish A Data Set</Link>
|
))}
|
||||||
</div>
|
{this.props.recent && (
|
||||||
)}
|
<Link className={styles.link} to={'/history'}>
|
||||||
</div>
|
All Data Sets
|
||||||
) : (
|
</Link>
|
||||||
<Web3message />
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className={styles.empty}>
|
||||||
|
<p>No Data Sets Yet.</p>
|
||||||
|
<Link to="/publish">+ Publish A Data Set</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { PureComponent } from 'react'
|
import React, { PureComponent } from 'react'
|
||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import { ReactComponent as Logo } from '@oceanprotocol/art/logo/logo.svg'
|
import { ReactComponent as Logo } from '@oceanprotocol/art/logo/logo.svg'
|
||||||
import { User } from '../../context/User'
|
import { User } from '../../context'
|
||||||
import AccountStatus from '../molecules/AccountStatus'
|
import AccountStatus from '../molecules/AccountStatus'
|
||||||
import styles from './Header.module.scss'
|
import styles from './Header.module.scss'
|
||||||
|
|
||||||
|
11
client/src/components/organisms/Web3message.test.tsx
Normal file
11
client/src/components/organisms/Web3message.test.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render } from 'react-testing-library'
|
||||||
|
import Web3message from './Web3message'
|
||||||
|
|
||||||
|
describe('Web3message', () => {
|
||||||
|
it('default renders without crashing', () => {
|
||||||
|
const { container } = render(<Web3message />)
|
||||||
|
|
||||||
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
@ -3,69 +3,54 @@ import Dotdotdot from 'react-dotdotdot'
|
|||||||
import Button from '../atoms/Button'
|
import Button from '../atoms/Button'
|
||||||
import AccountStatus from '../molecules/AccountStatus'
|
import AccountStatus from '../molecules/AccountStatus'
|
||||||
import styles from './Web3message.module.scss'
|
import styles from './Web3message.module.scss'
|
||||||
import { User } from '../../context/User'
|
import { User } from '../../context'
|
||||||
|
import content from '../../data/web3message.json'
|
||||||
|
|
||||||
export default class Web3message extends PureComponent {
|
export default class Web3message extends PureComponent {
|
||||||
private noWeb3 = () => (
|
private message = (
|
||||||
|
message: string,
|
||||||
|
account?: string,
|
||||||
|
unlockAccounts?: () => any
|
||||||
|
) => (
|
||||||
<div className={styles.message}>
|
<div className={styles.message}>
|
||||||
<AccountStatus className={styles.status} /> Not a Web3 Browser. For
|
<AccountStatus className={styles.status} />{' '}
|
||||||
publishing or downloading an asset you need to{' '}
|
{account ? (
|
||||||
<a
|
<Dotdotdot clamp={1}>
|
||||||
href="https://docs.oceanprotocol.com/tutorials/metamask-setup/"
|
{message}
|
||||||
target="_blank"
|
<code className={styles.account}>{account}</code>
|
||||||
rel="noopener noreferrer"
|
</Dotdotdot>
|
||||||
>
|
) : (
|
||||||
setup MetaMask
|
<>
|
||||||
</a>{' '}
|
<span dangerouslySetInnerHTML={{ __html: message }} />{' '}
|
||||||
or use any other Web3-capable plugin or browser.
|
{unlockAccounts && (
|
||||||
</div>
|
<Button onClick={() => unlockAccounts()} link>
|
||||||
)
|
Unlock Account
|
||||||
|
</Button>
|
||||||
private unlockAccount = (states: any) => (
|
)}
|
||||||
<div className={styles.message}>
|
</>
|
||||||
<AccountStatus className={styles.status} /> Account locked. For
|
)}
|
||||||
publishing and downloading an asset you need to unlock your Web3
|
|
||||||
account.{' '}
|
|
||||||
<Button link onClick={states.startLogin}>
|
|
||||||
Unlock account
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
private haveAccount = (account: string) => (
|
|
||||||
<div className={styles.message}>
|
|
||||||
<AccountStatus className={styles.status} />
|
|
||||||
<Dotdotdot clamp={1}>
|
|
||||||
Connected with account
|
|
||||||
<code className={styles.account}>{account}</code>
|
|
||||||
</Dotdotdot>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
private wrongNetwork = (network: string) => (
|
|
||||||
<div className={styles.message}>
|
|
||||||
<AccountStatus className={styles.status} /> Not connected to Nile
|
|
||||||
network, but to {network}.<br />
|
|
||||||
Please connect in MetaMask with Custom RPC{' '}
|
|
||||||
<code>{`https://nile.dev-ocean.com`}</code>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
const {
|
||||||
<User.Consumer>
|
isWeb3,
|
||||||
{states =>
|
isNile,
|
||||||
!states.isWeb3
|
isLogged,
|
||||||
? this.noWeb3()
|
account,
|
||||||
: !states.isNile
|
unlockAccounts
|
||||||
? this.wrongNetwork(states.network)
|
} = this.context
|
||||||
: !states.isLogged
|
|
||||||
? this.unlockAccount(states)
|
return !isWeb3
|
||||||
: states.isLogged
|
? this.message(content.noweb3)
|
||||||
? this.haveAccount(states.account)
|
: !isNile
|
||||||
: null
|
? this.message(content.wrongNetwork)
|
||||||
}
|
: !isLogged
|
||||||
</User.Consumer>
|
? this.message(content.noAccount, '', unlockAccounts)
|
||||||
)
|
: isLogged
|
||||||
|
? this.message(content.hasAccount, account)
|
||||||
|
: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Web3message.contextType = User
|
||||||
|
244
client/src/context/UserProvider.tsx
Normal file
244
client/src/context/UserProvider.tsx
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
import React, { PureComponent } from 'react'
|
||||||
|
import Web3 from 'web3'
|
||||||
|
import { Logger } from '@oceanprotocol/squid'
|
||||||
|
import { User } from '.'
|
||||||
|
import { provideOcean, requestFromFaucet, FaucetResponse } from '../ocean'
|
||||||
|
import { nodeHost, nodePort, nodeScheme } from '../config/config'
|
||||||
|
|
||||||
|
const POLL_ACCOUNTS = 1000 // every 1s
|
||||||
|
const POLL_NETWORK = POLL_ACCOUNTS * 60 // every 1 min
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
web3: Web3
|
||||||
|
ethereum: {
|
||||||
|
enable(): void
|
||||||
|
host: string
|
||||||
|
supportsSubscriptions(): boolean
|
||||||
|
send(method: string, parameters: any[]): Promise<any[]>
|
||||||
|
sendBatch(methods: any[], moduleInstance: any): Promise<any[]>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UserProviderState {
|
||||||
|
isLogged: boolean
|
||||||
|
isLoading: boolean
|
||||||
|
isWeb3: boolean
|
||||||
|
isNile: boolean
|
||||||
|
account: string
|
||||||
|
balance: {
|
||||||
|
eth: number
|
||||||
|
ocn: number
|
||||||
|
}
|
||||||
|
network: string
|
||||||
|
web3: Web3
|
||||||
|
ocean: any
|
||||||
|
requestFromFaucet(account: string): Promise<FaucetResponse>
|
||||||
|
unlockAccounts(): Promise<any>
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class UserProvider extends PureComponent<{}, UserProviderState> {
|
||||||
|
private unlockAccounts = async () => {
|
||||||
|
try {
|
||||||
|
await window.ethereum.enable()
|
||||||
|
} catch (error) {
|
||||||
|
// User denied account access...
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public state = {
|
||||||
|
isLogged: false,
|
||||||
|
isLoading: true,
|
||||||
|
isWeb3: false,
|
||||||
|
isNile: false,
|
||||||
|
balance: {
|
||||||
|
eth: 0,
|
||||||
|
ocn: 0
|
||||||
|
},
|
||||||
|
network: '',
|
||||||
|
web3: new Web3(
|
||||||
|
new Web3.providers.HttpProvider(
|
||||||
|
`${nodeScheme}://${nodeHost}:${nodePort}`
|
||||||
|
)
|
||||||
|
),
|
||||||
|
account: '',
|
||||||
|
ocean: {} as any,
|
||||||
|
requestFromFaucet: () => requestFromFaucet(''),
|
||||||
|
unlockAccounts: () => this.unlockAccounts(),
|
||||||
|
message: 'Connecting to Ocean...'
|
||||||
|
}
|
||||||
|
|
||||||
|
private accountsInterval: any = null
|
||||||
|
private networkInterval: any = null
|
||||||
|
|
||||||
|
public async componentDidMount() {
|
||||||
|
await this.bootstrap()
|
||||||
|
|
||||||
|
this.initAccountsPoll()
|
||||||
|
this.initNetworkPoll()
|
||||||
|
}
|
||||||
|
|
||||||
|
private initAccountsPoll() {
|
||||||
|
if (!this.accountsInterval) {
|
||||||
|
this.accountsInterval = setInterval(
|
||||||
|
this.fetchAccounts,
|
||||||
|
POLL_ACCOUNTS
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private initNetworkPoll() {
|
||||||
|
if (!this.networkInterval) {
|
||||||
|
this.networkInterval = setInterval(this.fetchNetwork, POLL_NETWORK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getWeb3 = async () => {
|
||||||
|
// Modern dapp browsers
|
||||||
|
if (window.ethereum) {
|
||||||
|
window.web3 = new Web3(window.ethereum)
|
||||||
|
return window.web3
|
||||||
|
}
|
||||||
|
// Legacy dapp browsers
|
||||||
|
else if (window.web3) {
|
||||||
|
window.web3 = new Web3(window.web3.currentProvider)
|
||||||
|
return window.web3
|
||||||
|
}
|
||||||
|
// Non-dapp browsers
|
||||||
|
else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bootstrap = async () => {
|
||||||
|
try {
|
||||||
|
//
|
||||||
|
// Start with Web3 detection only
|
||||||
|
//
|
||||||
|
this.setState({ message: 'Setting up Web3...' })
|
||||||
|
let web3 = await this.getWeb3()
|
||||||
|
|
||||||
|
web3
|
||||||
|
? this.setState({ isWeb3: true })
|
||||||
|
: this.setState({ isWeb3: false })
|
||||||
|
|
||||||
|
// Modern & legacy dapp browsers
|
||||||
|
if (web3 && this.state.isWeb3) {
|
||||||
|
//
|
||||||
|
// Detecting network with window.web3
|
||||||
|
//
|
||||||
|
let isNile
|
||||||
|
|
||||||
|
await window.web3.eth.net.getId((err, netId) => {
|
||||||
|
if (err) return
|
||||||
|
|
||||||
|
isNile = netId === 8995
|
||||||
|
const network = isNile ? 'Nile' : netId.toString()
|
||||||
|
|
||||||
|
if (
|
||||||
|
isNile !== this.state.isNile ||
|
||||||
|
network !== this.state.network
|
||||||
|
) {
|
||||||
|
this.setState({ isNile, network })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!isNile) {
|
||||||
|
web3 = this.state.web3 // eslint-disable-line
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Provide the Ocean
|
||||||
|
//
|
||||||
|
this.setState({ message: 'Connecting to Ocean...' })
|
||||||
|
|
||||||
|
const { ocean } = await provideOcean(web3)
|
||||||
|
this.setState({ ocean, message: 'Getting accounts...' })
|
||||||
|
|
||||||
|
// Get accounts
|
||||||
|
await this.fetchAccounts()
|
||||||
|
|
||||||
|
this.setState({ isLoading: false, message: '' })
|
||||||
|
}
|
||||||
|
// Non-dapp browsers
|
||||||
|
else {
|
||||||
|
this.setState({ message: 'Connecting to Ocean...' })
|
||||||
|
const { ocean } = await provideOcean(this.state.web3)
|
||||||
|
this.setState({ ocean, isLoading: false })
|
||||||
|
|
||||||
|
this.fetchNetwork()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// error in bootstrap process
|
||||||
|
// show error connecting to ocean
|
||||||
|
Logger.log('web3 error', e)
|
||||||
|
this.setState({ isLoading: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fetchAccounts = async () => {
|
||||||
|
const { ocean, isWeb3, isLogged, isNile } = this.state
|
||||||
|
|
||||||
|
if (isWeb3) {
|
||||||
|
let accounts
|
||||||
|
|
||||||
|
// Modern dapp browsers
|
||||||
|
if (window.ethereum && !isLogged && isNile) {
|
||||||
|
// simply set to empty, and have user click a button somewhere
|
||||||
|
// to initiate account unlocking
|
||||||
|
accounts = []
|
||||||
|
|
||||||
|
// alternatively, automatically prompt for account unlocking
|
||||||
|
// await this.unlockAccounts()
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts = await ocean.accounts.list()
|
||||||
|
|
||||||
|
if (accounts.length > 0) {
|
||||||
|
const account = await accounts[0].getId()
|
||||||
|
|
||||||
|
if (account !== this.state.account) {
|
||||||
|
this.setState({
|
||||||
|
account,
|
||||||
|
isLogged: true,
|
||||||
|
requestFromFaucet: () => requestFromFaucet(account)
|
||||||
|
})
|
||||||
|
|
||||||
|
await this.fetchBalance(accounts[0])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
!isLogged && this.setState({ isLogged: false, account: '' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fetchBalance = async (account: any) => {
|
||||||
|
const balance = await account.getBalance()
|
||||||
|
const { eth, ocn } = balance
|
||||||
|
if (eth !== this.state.balance.eth || ocn !== this.state.balance.ocn) {
|
||||||
|
this.setState({ balance: { eth, ocn } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fetchNetwork = async () => {
|
||||||
|
const { ocean, isWeb3 } = this.state
|
||||||
|
|
||||||
|
if (isWeb3) {
|
||||||
|
const network = await ocean.keeper.getNetworkName()
|
||||||
|
const isNile = network === 'Nile'
|
||||||
|
|
||||||
|
network !== this.state.network && this.setState({ isNile, network })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return (
|
||||||
|
<User.Provider value={this.state}>
|
||||||
|
{this.props.children}
|
||||||
|
</User.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -13,10 +13,11 @@ export const User = React.createContext({
|
|||||||
ocn: 0
|
ocn: 0
|
||||||
},
|
},
|
||||||
network: '',
|
network: '',
|
||||||
startLogin: () => {
|
|
||||||
/* empty */
|
|
||||||
},
|
|
||||||
requestFromFaucet: () => {
|
requestFromFaucet: () => {
|
||||||
/* empty */
|
/* empty */
|
||||||
}
|
},
|
||||||
|
unlockAccounts: () => {
|
||||||
|
/* empty */
|
||||||
|
},
|
||||||
|
message: ''
|
||||||
})
|
})
|
6
client/src/data/web3message.json
Normal file
6
client/src/data/web3message.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"noweb3": "Not a Web3 Browser. For publishing and downloading an asset you need to <a href='https://docs.oceanprotocol.com/tutorials/metamask-setup/' target='_blank' rel='noopener noreferrer'>setup MetaMask</a> or use any other Web3-capable plugin or browser.",
|
||||||
|
"noAccount": "No accounts detected. For publishing and downloading an asset you need to unlock your Web3 account.",
|
||||||
|
"hasAccount": "Connected with account ",
|
||||||
|
"wrongNetwork": "Not connected to Nile network.<br />Please connect in MetaMask with Custom RPC <code>https://nile.dev-ocean.com</code>"
|
||||||
|
}
|
33
client/src/hoc/withTracker.tsx
Normal file
33
client/src/hoc/withTracker.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React, { useEffect } from 'react'
|
||||||
|
import ReactGA, { FieldsObject } from 'react-ga'
|
||||||
|
import { RouteComponentProps } from 'react-router-dom'
|
||||||
|
import { analyticsId } from '../config/config'
|
||||||
|
|
||||||
|
const withTracker = <P extends RouteComponentProps>(
|
||||||
|
WrappedComponent: any,
|
||||||
|
options: FieldsObject = {}
|
||||||
|
) => {
|
||||||
|
ReactGA.initialize(analyticsId, {
|
||||||
|
testMode: process.env.NODE_ENV === 'development',
|
||||||
|
debug: false
|
||||||
|
})
|
||||||
|
|
||||||
|
const trackPage = (page: string) => {
|
||||||
|
options.isWeb3 = window.web3 !== undefined
|
||||||
|
|
||||||
|
ReactGA.set({ page, ...options })
|
||||||
|
ReactGA.pageview(page)
|
||||||
|
}
|
||||||
|
|
||||||
|
const HOC = (props: P) => {
|
||||||
|
useEffect(() => trackPage(props.location.pathname), [
|
||||||
|
props.location.pathname
|
||||||
|
])
|
||||||
|
|
||||||
|
return <WrappedComponent {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
return HOC
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withTracker
|
@ -1,4 +1,4 @@
|
|||||||
import { Ocean } from '@oceanprotocol/squid'
|
import { Ocean, Logger } from '@oceanprotocol/squid'
|
||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -9,6 +9,9 @@ import {
|
|||||||
brizoPort,
|
brizoPort,
|
||||||
brizoScheme,
|
brizoScheme,
|
||||||
brizoAddress,
|
brizoAddress,
|
||||||
|
faucetHost,
|
||||||
|
faucetPort,
|
||||||
|
faucetScheme,
|
||||||
nodeHost,
|
nodeHost,
|
||||||
nodePort,
|
nodePort,
|
||||||
nodeScheme,
|
nodeScheme,
|
||||||
@ -43,3 +46,32 @@ export async function provideOcean(web3provider: Web3) {
|
|||||||
|
|
||||||
return { ocean }
|
return { ocean }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Faucet
|
||||||
|
//
|
||||||
|
export interface FaucetResponse {
|
||||||
|
success: boolean
|
||||||
|
message: string
|
||||||
|
trxHash?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function requestFromFaucet(account: string) {
|
||||||
|
try {
|
||||||
|
const url = `${faucetScheme}://${faucetHost}:${faucetPort}/faucet`
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
address: account,
|
||||||
|
agent: 'commons'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return response.json()
|
||||||
|
} catch (error) {
|
||||||
|
Logger.log('requestFromFaucet', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@ import { Logger } from '@oceanprotocol/squid'
|
|||||||
import filesize from 'filesize'
|
import filesize from 'filesize'
|
||||||
import Button from '../../components/atoms/Button'
|
import Button from '../../components/atoms/Button'
|
||||||
import Spinner from '../../components/atoms/Spinner'
|
import Spinner from '../../components/atoms/Spinner'
|
||||||
import { User } from '../../context/User'
|
import { User } from '../../context'
|
||||||
import styles from './AssetFile.module.scss'
|
import styles from './AssetFile.module.scss'
|
||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ export default class AssetFile extends PureComponent<
|
|||||||
public render() {
|
public render() {
|
||||||
const { ddo, file } = this.props
|
const { ddo, file } = this.props
|
||||||
const { isLoading, message, error } = this.state
|
const { isLoading, message, error } = this.state
|
||||||
const { isLogged } = this.context
|
const { isLogged, isNile } = this.context
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.fileWrap}>
|
<div className={styles.fileWrap}>
|
||||||
@ -98,7 +98,7 @@ export default class AssetFile extends PureComponent<
|
|||||||
primary
|
primary
|
||||||
className={styles.buttonMain}
|
className={styles.buttonMain}
|
||||||
onClick={() => this.purchaseAsset(ddo, file.index)}
|
onClick={() => this.purchaseAsset(ddo, file.index)}
|
||||||
disabled={!isLogged}
|
disabled={!isLogged || !isNile}
|
||||||
>
|
>
|
||||||
Get file
|
Get file
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { PureComponent } from 'react'
|
import React, { PureComponent } from 'react'
|
||||||
import AssetFile from './AssetFile'
|
import AssetFile from './AssetFile'
|
||||||
import { User } from '../../context/User'
|
import { User } from '../../context'
|
||||||
import Web3message from '../../components/organisms/Web3message'
|
import Web3message from '../../components/organisms/Web3message'
|
||||||
import styles from './AssetFilesDetails.module.scss'
|
import styles from './AssetFilesDetails.module.scss'
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import Route from '../../components/templates/Route'
|
import Route from '../../components/templates/Route'
|
||||||
import Spinner from '../../components/atoms/Spinner'
|
import Spinner from '../../components/atoms/Spinner'
|
||||||
import { User } from '../../context/User'
|
import { User } from '../../context'
|
||||||
import AssetDetails from './AssetDetails'
|
import AssetDetails from './AssetDetails'
|
||||||
import stylesApp from '../../App.module.scss'
|
import stylesApp from '../../App.module.scss'
|
||||||
|
|
||||||
@ -29,18 +29,14 @@ export default class Details extends Component<DetailsProps, DetailsState> {
|
|||||||
public render() {
|
public render() {
|
||||||
const { metadata, ddo } = this.state
|
const { metadata, ddo } = this.state
|
||||||
|
|
||||||
return (
|
return metadata.base.name !== '' ? (
|
||||||
<Route
|
<Route title={metadata.base.name}>
|
||||||
title={metadata.base ? metadata.base.name : 'Loading Details'}
|
<AssetDetails metadata={metadata} ddo={ddo} />
|
||||||
>
|
|
||||||
{metadata && metadata.base.name ? (
|
|
||||||
<AssetDetails metadata={metadata} ddo={ddo} />
|
|
||||||
) : (
|
|
||||||
<div className={stylesApp.loader}>
|
|
||||||
<Spinner message={'Loading asset...'} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Route>
|
</Route>
|
||||||
|
) : (
|
||||||
|
<div className={stylesApp.loader}>
|
||||||
|
<Spinner message={'Loading asset...'} />
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React, { PureComponent } from 'react'
|
import React, { PureComponent } from 'react'
|
||||||
|
import { FaucetResponse } from '../ocean'
|
||||||
import Route from '../components/templates/Route'
|
import Route from '../components/templates/Route'
|
||||||
import Button from '../components/atoms/Button'
|
import Button from '../components/atoms/Button'
|
||||||
import Spinner from '../components/atoms/Spinner'
|
import Spinner from '../components/atoms/Spinner'
|
||||||
import { User } from '../context/User'
|
import { User } from '../context'
|
||||||
import Web3message from '../components/organisms/Web3message'
|
import Web3message from '../components/organisms/Web3message'
|
||||||
import styles from './Faucet.module.scss'
|
import styles from './Faucet.module.scss'
|
||||||
|
|
||||||
@ -21,7 +22,9 @@ export default class Faucet extends PureComponent<{}, FaucetState> {
|
|||||||
trxHash: undefined
|
trxHash: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTokens = async (requestFromFaucet: () => any) => {
|
private getTokens = async (
|
||||||
|
requestFromFaucet: () => Promise<FaucetResponse>
|
||||||
|
) => {
|
||||||
this.setState({ isLoading: true })
|
this.setState({ isLoading: true })
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -77,7 +80,7 @@ export default class Faucet extends PureComponent<{}, FaucetState> {
|
|||||||
<Button
|
<Button
|
||||||
primary
|
primary
|
||||||
onClick={() => this.getTokens(this.context.requestFromFaucet)}
|
onClick={() => this.getTokens(this.context.requestFromFaucet)}
|
||||||
disabled={!this.context.isLogged}
|
disabled={!this.context.isLogged || !this.context.isNile}
|
||||||
>
|
>
|
||||||
Request Ether
|
Request Ether
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -1,13 +1,21 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import Route from '../components/templates/Route'
|
import Route from '../components/templates/Route'
|
||||||
import AssetsUser from '../components/organisms/AssetsUser'
|
import AssetsUser from '../components/organisms/AssetsUser'
|
||||||
|
import Web3message from '../components/organisms/Web3message'
|
||||||
|
import { User } from '../context'
|
||||||
|
|
||||||
export default class History extends Component {
|
export default class History extends Component {
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<Route title="History">
|
<Route title="History">
|
||||||
|
{(!this.context.isLogged || !this.context.isNile) && (
|
||||||
|
<Web3message />
|
||||||
|
)}
|
||||||
|
|
||||||
<AssetsUser list />
|
<AssetsUser list />
|
||||||
</Route>
|
</Route>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
History.contextType = User
|
||||||
|
@ -3,7 +3,7 @@ import Input from '../../components/atoms/Form/Input'
|
|||||||
import Label from '../../components/atoms/Form/Label'
|
import Label from '../../components/atoms/Form/Label'
|
||||||
import Row from '../../components/atoms/Form/Row'
|
import Row from '../../components/atoms/Form/Row'
|
||||||
import Button from '../../components/atoms/Button'
|
import Button from '../../components/atoms/Button'
|
||||||
import { User } from '../../context/User'
|
import { User } from '../../context'
|
||||||
import Files from './Files/'
|
import Files from './Files/'
|
||||||
import StepRegisterContent from './StepRegisterContent'
|
import StepRegisterContent from './StepRegisterContent'
|
||||||
import styles from './Step.module.scss'
|
import styles from './Step.module.scss'
|
||||||
@ -154,29 +154,9 @@ export default class Step extends PureComponent<StepProps, {}> {
|
|||||||
{this.nextButton()}
|
{this.nextButton()}
|
||||||
|
|
||||||
{lastStep && (
|
{lastStep && (
|
||||||
<User.Consumer>
|
<Button disabled={!this.context.isLogged} primary>
|
||||||
{states =>
|
Register asset
|
||||||
states.isLogged ? (
|
</Button>
|
||||||
<Button primary>Register asset</Button>
|
|
||||||
) : states.isWeb3 ? (
|
|
||||||
<Button onClick={states.startLogin}>
|
|
||||||
Register asset (unlock Metamask)
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button
|
|
||||||
onClick={(e: Event) => {
|
|
||||||
e.preventDefault()
|
|
||||||
window.open(
|
|
||||||
'https://docs.oceanprotocol.com/tutorials/metamask-setup/',
|
|
||||||
'_blank'
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Register asset (install Metamask)
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</User.Consumer>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -3,7 +3,8 @@ import { Logger } from '@oceanprotocol/squid'
|
|||||||
import Route from '../../components/templates/Route'
|
import Route from '../../components/templates/Route'
|
||||||
import Form from '../../components/atoms/Form/Form'
|
import Form from '../../components/atoms/Form/Form'
|
||||||
import AssetModel from '../../models/AssetModel'
|
import AssetModel from '../../models/AssetModel'
|
||||||
import { User } from '../../context/User'
|
import { User } from '../../context'
|
||||||
|
import Web3message from '../../components/organisms/Web3message'
|
||||||
import Step from './Step'
|
import Step from './Step'
|
||||||
import Progress from './Progress'
|
import Progress from './Progress'
|
||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
@ -318,6 +319,10 @@ class Publish extends Component<{}, PublishState> {
|
|||||||
title="Publish"
|
title="Publish"
|
||||||
description="Publish a new data set into the Ocean Protocol Network."
|
description="Publish a new data set into the Ocean Protocol Network."
|
||||||
>
|
>
|
||||||
|
{(!this.context.isLogged || !this.context.isNile) && (
|
||||||
|
<Web3message />
|
||||||
|
)}
|
||||||
|
|
||||||
<Progress steps={steps} currentStep={this.state.currentStep} />
|
<Progress steps={steps} currentStep={this.state.currentStep} />
|
||||||
|
|
||||||
<Form onSubmit={this.registerAsset}>
|
<Form onSubmit={this.registerAsset}>
|
||||||
|
@ -3,7 +3,7 @@ import queryString from 'query-string'
|
|||||||
import { Logger } from '@oceanprotocol/squid'
|
import { Logger } from '@oceanprotocol/squid'
|
||||||
import Spinner from '../components/atoms/Spinner'
|
import Spinner from '../components/atoms/Spinner'
|
||||||
import Route from '../components/templates/Route'
|
import Route from '../components/templates/Route'
|
||||||
import { User } from '../context/User'
|
import { User } from '../context'
|
||||||
import Asset from '../components/molecules/Asset'
|
import Asset from '../components/molecules/Asset'
|
||||||
import Pagination from '../components/molecules/Pagination'
|
import Pagination from '../components/molecules/Pagination'
|
||||||
import styles from './Search.module.scss'
|
import styles from './Search.module.scss'
|
||||||
|
2
client/src/setupTests.js
Normal file
2
client/src/setupTests.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import 'jest-dom/extend-expect'
|
||||||
|
import 'react-testing-library/cleanup-after-each'
|
@ -1,46 +0,0 @@
|
|||||||
import React, { PureComponent } from 'react'
|
|
||||||
import ReactGA from 'react-ga'
|
|
||||||
|
|
||||||
import { analyticsId } from './config/config'
|
|
||||||
|
|
||||||
interface TrackerProps {
|
|
||||||
location: Location
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactGA.initialize(analyticsId, {
|
|
||||||
testMode: process.env.NODE_ENV === 'test'
|
|
||||||
})
|
|
||||||
|
|
||||||
export default function withTracker(WrappedComponent: any, options: any = {}) {
|
|
||||||
const trackPage = (page: string) => {
|
|
||||||
options.isWeb3 = window.web3 !== undefined
|
|
||||||
ReactGA.set({
|
|
||||||
page,
|
|
||||||
...options
|
|
||||||
})
|
|
||||||
ReactGA.pageview(page)
|
|
||||||
}
|
|
||||||
|
|
||||||
return class HOC extends PureComponent<TrackerProps, {}> {
|
|
||||||
public componentDidMount() {
|
|
||||||
const page =
|
|
||||||
this.props.location.pathname + this.props.location.search
|
|
||||||
trackPage(page)
|
|
||||||
}
|
|
||||||
|
|
||||||
public componentWillReceiveProps(nextProps: any) {
|
|
||||||
const currentPage = this.props.location.pathname
|
|
||||||
const nextPage = nextProps.location.pathname
|
|
||||||
|
|
||||||
if (currentPage !== nextPage) {
|
|
||||||
trackPage(
|
|
||||||
nextProps.location.pathname + nextProps.location.search
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
|
||||||
return <WrappedComponent {...this.props} />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user