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==",
|
||||
"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": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
||||
@ -1071,15 +1081,16 @@
|
||||
"integrity": "sha512-c1LvaH+e1tzow0gZLwSWe19ap+DrZuNmZfxBdwEVEPQXarI0jTXa5qVDoiBow8kBWaqSIUgFAzQOJW8rKdlS1A=="
|
||||
},
|
||||
"@oceanprotocol/squid": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/squid/-/squid-0.5.3.tgz",
|
||||
"integrity": "sha512-tPOg+z9hYYN/6QoM7BDw1N5uQQQvbEj8xITtC1aYEoAM1tHaauAIecQjVQQaumkepaz8F1t1kmWUP2t7RQVqgg==",
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/squid/-/squid-0.5.4.tgz",
|
||||
"integrity": "sha512-ozOTLNJX0GiKShum09e13LZ9zUKedWA5G8+H3Pwu3+lbdLYkRSeCg5eLXDUJxUN12+leiCnW/TZDoV9ZOmcd4w==",
|
||||
"requires": {
|
||||
"@oceanprotocol/keeper-contracts": "^0.9.0",
|
||||
"bignumber.js": "^8.0.1",
|
||||
"@oceanprotocol/keeper-contracts": "^0.9.1",
|
||||
"bignumber.js": "^8.1.1",
|
||||
"deprecated-decorator": "^0.1.6",
|
||||
"ethereumjs-util": "^6.0.0",
|
||||
"ethereumjs-util": "^6.1.0",
|
||||
"node-fetch": "^2.3.0",
|
||||
"save-file": "^2.3.1",
|
||||
"uuid": "^3.3.2",
|
||||
"web3": "1.0.0-beta.37",
|
||||
"whatwg-url": "^7.0.0"
|
||||
@ -1106,6 +1117,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/typographies/-/typographies-0.1.0.tgz",
|
||||
"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": {
|
||||
"version": "4.2.0",
|
||||
"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=",
|
||||
"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": {
|
||||
"version": "24.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.11.tgz",
|
||||
@ -1552,6 +1575,12 @@
|
||||
"@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": {
|
||||
"version": "1.7.11",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz",
|
||||
@ -2417,6 +2446,11 @@
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||
"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": {
|
||||
"version": "9.5.1",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.5.1.tgz",
|
||||
@ -4818,6 +4852,26 @@
|
||||
"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": {
|
||||
"version": "0.1.4",
|
||||
"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==",
|
||||
"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": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz",
|
||||
@ -5920,6 +5980,12 @@
|
||||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
||||
"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": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
|
||||
@ -6017,6 +6083,47 @@
|
||||
"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": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
|
||||
@ -6090,6 +6197,11 @@
|
||||
"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": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||
@ -7487,6 +7599,11 @@
|
||||
"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": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
|
||||
@ -7620,6 +7737,14 @@
|
||||
"integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=",
|
||||
"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": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
|
||||
@ -10005,6 +10130,11 @@
|
||||
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
|
||||
"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": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
|
||||
@ -10014,6 +10144,11 @@
|
||||
"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": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||
@ -10861,6 +10996,123 @@
|
||||
"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": {
|
||||
"version": "23.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.6.0.tgz",
|
||||
@ -19382,6 +19634,16 @@
|
||||
"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": {
|
||||
"version": "3.0.0",
|
||||
"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": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
@ -20856,6 +21146,11 @@
|
||||
"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": {
|
||||
"version": "0.2.2",
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
@ -21958,6 +22262,23 @@
|
||||
"integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
|
||||
"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": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
|
||||
@ -22644,6 +22965,12 @@
|
||||
"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": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
|
||||
|
@ -46,8 +46,10 @@
|
||||
"@types/react-router-dom": "^4.3.1",
|
||||
"@types/react-transition-group": "^2.8.0",
|
||||
"@types/web3": "^1.0.18",
|
||||
"jest-dom": "^3.1.3",
|
||||
"node-sass": "^4.11.0",
|
||||
"react-scripts": "^2.1.8",
|
||||
"react-testing-library": "^6.1.2",
|
||||
"typescript": "^3.4.2"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -1,275 +1,44 @@
|
||||
import React, { Component } from 'react'
|
||||
import Web3 from 'web3'
|
||||
import { BrowserRouter as Router } from 'react-router-dom'
|
||||
import { Logger } from '@oceanprotocol/squid'
|
||||
import Header from './components/organisms/Header'
|
||||
import Footer from './components/organisms/Footer'
|
||||
import Spinner from './components/atoms/Spinner'
|
||||
import { User } from './context/User'
|
||||
import { provideOcean } from './ocean'
|
||||
import { User } from './context'
|
||||
import UserProvider from './context/UserProvider'
|
||||
import Routes from './Routes'
|
||||
import './styles/global.scss'
|
||||
import styles from './App.module.scss'
|
||||
|
||||
import {
|
||||
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?
|
||||
}
|
||||
}
|
||||
|
||||
export default class App extends Component {
|
||||
public render() {
|
||||
return (
|
||||
<UserProvider>
|
||||
<div className={styles.app}>
|
||||
<User.Provider value={this.state}>
|
||||
<Router>
|
||||
<>
|
||||
<Header />
|
||||
|
||||
<main className={styles.main}>
|
||||
{this.state.isLoading ? (
|
||||
<User.Consumer>
|
||||
{states =>
|
||||
states.isLoading ? (
|
||||
<div className={styles.loader}>
|
||||
<Spinner message={this.state.message} />
|
||||
<Spinner
|
||||
message={states.message}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<Routes />
|
||||
)}
|
||||
)
|
||||
}
|
||||
</User.Consumer>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</>
|
||||
</Router>
|
||||
</User.Provider>
|
||||
</div>
|
||||
</UserProvider>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default App
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { Route, Switch } from 'react-router-dom'
|
||||
import withTracker from './withTracker'
|
||||
import withTracker from './hoc/withTracker'
|
||||
|
||||
import About from './routes/About'
|
||||
import Details from './routes/Details/'
|
||||
|
@ -1,16 +1,54 @@
|
||||
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'
|
||||
|
||||
it('Button renders without crashing', () => {
|
||||
const div = document.createElement('div')
|
||||
ReactDOM.render(
|
||||
<>
|
||||
<Button>I am a button</Button>
|
||||
<Button primary>I am a primary button</Button>
|
||||
<Button href="https://hello.com">I am a button</Button>
|
||||
</>,
|
||||
div
|
||||
describe('Button', () => {
|
||||
it('default renders correctly without crashing', () => {
|
||||
const { getByTestId } = render(
|
||||
<Button data-testid="button-default">I am a default button</Button>
|
||||
)
|
||||
ReactDOM.unmountComponentAtNode(div)
|
||||
expect(getByTestId('button-default')).toHaveTextContent('default')
|
||||
})
|
||||
|
||||
it('primary renders correctly without crashing', () => {
|
||||
const { getByTestId } = render(
|
||||
<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 cx from 'classnames'
|
||||
import { User } from '../../../context/User'
|
||||
import { User } from '../../../context'
|
||||
import styles from './Indicator.module.scss'
|
||||
|
||||
const Indicator = ({
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import Dotdotdot from 'react-dotdotdot'
|
||||
import { User } from '../../../context/User'
|
||||
import { User } from '../../../context'
|
||||
import styles from './Popover.module.scss'
|
||||
|
||||
export default class Popover extends PureComponent<{
|
||||
|
@ -1,10 +1,9 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Logger } from '@oceanprotocol/squid'
|
||||
import { User } from '../../context/User'
|
||||
import { User } from '../../context'
|
||||
import Spinner from '../atoms/Spinner'
|
||||
import Asset from '../molecules/Asset'
|
||||
import Web3message from './Web3message'
|
||||
import styles from './AssetsUser.module.scss'
|
||||
|
||||
export default class AssetsUser extends PureComponent<
|
||||
@ -13,31 +12,41 @@ export default class AssetsUser extends PureComponent<
|
||||
> {
|
||||
public state = { results: [], isLoading: true }
|
||||
|
||||
public _isMounted: boolean = false
|
||||
|
||||
public componentDidMount() {
|
||||
this.searchOcean()
|
||||
this._isMounted = true
|
||||
this._isMounted && this.searchOcean()
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
this._isMounted = false
|
||||
}
|
||||
|
||||
private async searchOcean() {
|
||||
if (this.context.account) {
|
||||
this.context.ocean.keeper.didRegistry.contract.getPastEvents(
|
||||
const { account, ocean } = this.context
|
||||
|
||||
if (account) {
|
||||
ocean.keeper.didRegistry.contract.getPastEvents(
|
||||
'DIDAttributeRegistered',
|
||||
{
|
||||
filter: { _owner: this.context.account },
|
||||
filter: { _owner: account },
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
},
|
||||
async (error: any, events: any) => {
|
||||
if (error) {
|
||||
Logger.log('error retrieving', error)
|
||||
this.setState({ isLoading: false })
|
||||
this._isMounted && this.setState({ isLoading: false })
|
||||
} else {
|
||||
const results = []
|
||||
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)}`
|
||||
)
|
||||
results.push(ddo)
|
||||
}
|
||||
this._isMounted &&
|
||||
this.setState({ results, isLoading: false })
|
||||
}
|
||||
}
|
||||
@ -48,7 +57,11 @@ export default class AssetsUser extends PureComponent<
|
||||
}
|
||||
|
||||
public render() {
|
||||
return this.context.isNile && this.context.account ? (
|
||||
const { account, isNile } = this.context
|
||||
|
||||
return (
|
||||
isNile &&
|
||||
account && (
|
||||
<div className={styles.assetsUser}>
|
||||
{this.props.recent && (
|
||||
<h2 className={styles.subTitle}>
|
||||
@ -88,8 +101,7 @@ export default class AssetsUser extends PureComponent<
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Web3message />
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import { NavLink } from 'react-router-dom'
|
||||
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 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 AccountStatus from '../molecules/AccountStatus'
|
||||
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 {
|
||||
private noWeb3 = () => (
|
||||
private message = (
|
||||
message: string,
|
||||
account?: string,
|
||||
unlockAccounts?: () => any
|
||||
) => (
|
||||
<div className={styles.message}>
|
||||
<AccountStatus className={styles.status} /> Not a Web3 Browser. For
|
||||
publishing or 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.
|
||||
</div>
|
||||
)
|
||||
|
||||
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} />
|
||||
<AccountStatus className={styles.status} />{' '}
|
||||
{account ? (
|
||||
<Dotdotdot clamp={1}>
|
||||
Connected with account
|
||||
{message}
|
||||
<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>
|
||||
) : (
|
||||
<>
|
||||
<span dangerouslySetInnerHTML={{ __html: message }} />{' '}
|
||||
{unlockAccounts && (
|
||||
<Button onClick={() => unlockAccounts()} link>
|
||||
Unlock Account
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<User.Consumer>
|
||||
{states =>
|
||||
!states.isWeb3
|
||||
? this.noWeb3()
|
||||
: !states.isNile
|
||||
? this.wrongNetwork(states.network)
|
||||
: !states.isLogged
|
||||
? this.unlockAccount(states)
|
||||
: states.isLogged
|
||||
? this.haveAccount(states.account)
|
||||
const {
|
||||
isWeb3,
|
||||
isNile,
|
||||
isLogged,
|
||||
account,
|
||||
unlockAccounts
|
||||
} = this.context
|
||||
|
||||
return !isWeb3
|
||||
? this.message(content.noweb3)
|
||||
: !isNile
|
||||
? this.message(content.wrongNetwork)
|
||||
: !isLogged
|
||||
? this.message(content.noAccount, '', unlockAccounts)
|
||||
: isLogged
|
||||
? this.message(content.hasAccount, account)
|
||||
: null
|
||||
}
|
||||
</User.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
},
|
||||
network: '',
|
||||
startLogin: () => {
|
||||
/* empty */
|
||||
},
|
||||
requestFromFaucet: () => {
|
||||
/* 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 {
|
||||
@ -9,6 +9,9 @@ import {
|
||||
brizoPort,
|
||||
brizoScheme,
|
||||
brizoAddress,
|
||||
faucetHost,
|
||||
faucetPort,
|
||||
faucetScheme,
|
||||
nodeHost,
|
||||
nodePort,
|
||||
nodeScheme,
|
||||
@ -43,3 +46,32 @@ export async function provideOcean(web3provider: Web3) {
|
||||
|
||||
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 Button from '../../components/atoms/Button'
|
||||
import Spinner from '../../components/atoms/Spinner'
|
||||
import { User } from '../../context/User'
|
||||
import { User } from '../../context'
|
||||
import styles from './AssetFile.module.scss'
|
||||
import ReactGA from 'react-ga'
|
||||
|
||||
@ -76,7 +76,7 @@ export default class AssetFile extends PureComponent<
|
||||
public render() {
|
||||
const { ddo, file } = this.props
|
||||
const { isLoading, message, error } = this.state
|
||||
const { isLogged } = this.context
|
||||
const { isLogged, isNile } = this.context
|
||||
|
||||
return (
|
||||
<div className={styles.fileWrap}>
|
||||
@ -98,7 +98,7 @@ export default class AssetFile extends PureComponent<
|
||||
primary
|
||||
className={styles.buttonMain}
|
||||
onClick={() => this.purchaseAsset(ddo, file.index)}
|
||||
disabled={!isLogged}
|
||||
disabled={!isLogged || !isNile}
|
||||
>
|
||||
Get file
|
||||
</Button>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import AssetFile from './AssetFile'
|
||||
import { User } from '../../context/User'
|
||||
import { User } from '../../context'
|
||||
import Web3message from '../../components/organisms/Web3message'
|
||||
import styles from './AssetFilesDetails.module.scss'
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react'
|
||||
import Route from '../../components/templates/Route'
|
||||
import Spinner from '../../components/atoms/Spinner'
|
||||
import { User } from '../../context/User'
|
||||
import { User } from '../../context'
|
||||
import AssetDetails from './AssetDetails'
|
||||
import stylesApp from '../../App.module.scss'
|
||||
|
||||
@ -29,18 +29,14 @@ export default class Details extends Component<DetailsProps, DetailsState> {
|
||||
public render() {
|
||||
const { metadata, ddo } = this.state
|
||||
|
||||
return (
|
||||
<Route
|
||||
title={metadata.base ? metadata.base.name : 'Loading Details'}
|
||||
>
|
||||
{metadata && metadata.base.name ? (
|
||||
return metadata.base.name !== '' ? (
|
||||
<Route title={metadata.base.name}>
|
||||
<AssetDetails metadata={metadata} ddo={ddo} />
|
||||
</Route>
|
||||
) : (
|
||||
<div className={stylesApp.loader}>
|
||||
<Spinner message={'Loading asset...'} />
|
||||
</div>
|
||||
)}
|
||||
</Route>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import { FaucetResponse } from '../ocean'
|
||||
import Route from '../components/templates/Route'
|
||||
import Button from '../components/atoms/Button'
|
||||
import Spinner from '../components/atoms/Spinner'
|
||||
import { User } from '../context/User'
|
||||
import { User } from '../context'
|
||||
import Web3message from '../components/organisms/Web3message'
|
||||
import styles from './Faucet.module.scss'
|
||||
|
||||
@ -21,7 +22,9 @@ export default class Faucet extends PureComponent<{}, FaucetState> {
|
||||
trxHash: undefined
|
||||
}
|
||||
|
||||
private getTokens = async (requestFromFaucet: () => any) => {
|
||||
private getTokens = async (
|
||||
requestFromFaucet: () => Promise<FaucetResponse>
|
||||
) => {
|
||||
this.setState({ isLoading: true })
|
||||
|
||||
try {
|
||||
@ -77,7 +80,7 @@ export default class Faucet extends PureComponent<{}, FaucetState> {
|
||||
<Button
|
||||
primary
|
||||
onClick={() => this.getTokens(this.context.requestFromFaucet)}
|
||||
disabled={!this.context.isLogged}
|
||||
disabled={!this.context.isLogged || !this.context.isNile}
|
||||
>
|
||||
Request Ether
|
||||
</Button>
|
||||
|
@ -1,13 +1,21 @@
|
||||
import React, { Component } from 'react'
|
||||
import Route from '../components/templates/Route'
|
||||
import AssetsUser from '../components/organisms/AssetsUser'
|
||||
import Web3message from '../components/organisms/Web3message'
|
||||
import { User } from '../context'
|
||||
|
||||
export default class History extends Component {
|
||||
public render() {
|
||||
return (
|
||||
<Route title="History">
|
||||
{(!this.context.isLogged || !this.context.isNile) && (
|
||||
<Web3message />
|
||||
)}
|
||||
|
||||
<AssetsUser list />
|
||||
</Route>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
History.contextType = User
|
||||
|
@ -3,7 +3,7 @@ import Input from '../../components/atoms/Form/Input'
|
||||
import Label from '../../components/atoms/Form/Label'
|
||||
import Row from '../../components/atoms/Form/Row'
|
||||
import Button from '../../components/atoms/Button'
|
||||
import { User } from '../../context/User'
|
||||
import { User } from '../../context'
|
||||
import Files from './Files/'
|
||||
import StepRegisterContent from './StepRegisterContent'
|
||||
import styles from './Step.module.scss'
|
||||
@ -154,29 +154,9 @@ export default class Step extends PureComponent<StepProps, {}> {
|
||||
{this.nextButton()}
|
||||
|
||||
{lastStep && (
|
||||
<User.Consumer>
|
||||
{states =>
|
||||
states.isLogged ? (
|
||||
<Button primary>Register asset</Button>
|
||||
) : states.isWeb3 ? (
|
||||
<Button onClick={states.startLogin}>
|
||||
Register asset (unlock Metamask)
|
||||
<Button disabled={!this.context.isLogged} primary>
|
||||
Register asset
|
||||
</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>
|
||||
</>
|
||||
|
@ -3,7 +3,8 @@ import { Logger } from '@oceanprotocol/squid'
|
||||
import Route from '../../components/templates/Route'
|
||||
import Form from '../../components/atoms/Form/Form'
|
||||
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 Progress from './Progress'
|
||||
import ReactGA from 'react-ga'
|
||||
@ -318,6 +319,10 @@ class Publish extends Component<{}, PublishState> {
|
||||
title="Publish"
|
||||
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} />
|
||||
|
||||
<Form onSubmit={this.registerAsset}>
|
||||
|
@ -3,7 +3,7 @@ import queryString from 'query-string'
|
||||
import { Logger } from '@oceanprotocol/squid'
|
||||
import Spinner from '../components/atoms/Spinner'
|
||||
import Route from '../components/templates/Route'
|
||||
import { User } from '../context/User'
|
||||
import { User } from '../context'
|
||||
import Asset from '../components/molecules/Asset'
|
||||
import Pagination from '../components/molecules/Pagination'
|
||||
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