diff --git a/package-lock.json b/package-lock.json index 1606ee8..65a886b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,7 @@ "version": "0.23.0", "license": "BSD-3-Clause", "dependencies": { - "@ethersphere/bee-js": "^5.2.0", - "@ethersphere/manifest-js": "1.2.1", + "@ethersphere/bee-js": "^6.2.0", "@ethersphere/swarm-cid": "^0.1.0", "@material-ui/core": "4.12.3", "@material-ui/icons": "4.11.2", @@ -27,6 +26,7 @@ "formik": "2.2.9", "formik-material-ui": "3.0.1", "jszip": "^3.7.1", + "mantaray-js": "^1.0.3", "material-ui-dropzone": "3.5.0", "notistack": "1.0.10", "opener": "1.5.2", @@ -105,7 +105,7 @@ "webpack-cli": "^4.10.0" }, "engines": { - "bee": "1.11.1-1992b846", + "bee": "1.16.1-8e269c8", "node": ">=14.0.0", "npm": ">=6.9.0" }, @@ -2440,33 +2440,54 @@ } }, "node_modules/@ethersphere/bee-js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-5.2.0.tgz", - "integrity": "sha512-BM9lBiKC/tMbYNTEs3uyDyAwpED+v6u46DEXyFh7BLCUPg12LBWv0O12XmQj5ybzXnUT4ptHU9UXu3oGHph8Vw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-6.2.0.tgz", + "integrity": "sha512-QWuVvW+c9z+AFWuRL+YBZECDyV3G5qeD9L0J7Tx7HYMugoDjMAjeRyNHjkf0a5np57q3i9MAE2P678rjSJ1Yaw==", "dependencies": { "@ethersphere/swarm-cid": "^0.1.0", "@types/readable-stream": "^2.3.13", - "bufferutil": "^4.0.6", + "axios": "^1.3.4", + "cafe-utility": "^10.8.1", "elliptic": "^6.5.4", "fetch-blob": "2.1.2", "isomorphic-ws": "^4.0.1", "js-sha3": "^0.8.0", - "ky": "^0.33.2", - "ky-universal": "^0.11.0", "semver": "^7.3.5", "tar-js": "^0.3.0", - "utf-8-validate": "^5.0.9", "web-streams-polyfill": "^4.0.0-beta.3", "ws": "^8.7.0" }, "engines": { - "bee": "1.12.0-88c1d236", + "bee": "1.13.0-f1067884", "beeApiVersion": "4.0.0", "beeDebugApiVersion": "4.0.0", "node": ">=14.0.0", "npm": ">=6.0.0" } }, + "node_modules/@ethersphere/bee-js/node_modules/axios": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/@ethersphere/bee-js/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@ethersphere/bee-js/node_modules/web-streams-polyfill": { "version": "4.0.0-beta.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", @@ -2495,22 +2516,6 @@ } } }, - "node_modules/@ethersphere/manifest-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@ethersphere/manifest-js/-/manifest-js-1.2.1.tgz", - "integrity": "sha512-HfeQ5h9KuH8xTxYY6bmSNwmpalrdDyOu4Sl6mrAN2W2iJlIjuG5DeirseSEFXElKPwEdv03PzZt2vARPna8sfw==", - "dependencies": { - "mantaray-js": "^1.0.3" - }, - "engines": { - "bee": "1.6.0-6ceadd35", - "node": ">=12.0.0", - "npm": ">=6.0.0" - }, - "peerDependencies": { - "@ethersphere/bee-js": ">=4.x" - } - }, "node_modules/@ethersphere/swarm-cid": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@ethersphere/swarm-cid/-/swarm-cid-0.1.0.tgz", @@ -5656,17 +5661,6 @@ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "dev": true }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -6058,8 +6052,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -6899,6 +6892,8 @@ "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", "hasInstallScript": true, + "optional": true, + "peer": true, "dependencies": { "node-gyp-build": "^4.3.0" }, @@ -6926,6 +6921,11 @@ "node": ">= 0.8" } }, + "node_modules/cafe-utility": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/cafe-utility/-/cafe-utility-10.9.1.tgz", + "integrity": "sha512-/gq+ANoYvMJKrXXI/2YAiB2KhNlRhxB5XcWbbMWFA39LLCxkPhG5A9Ehy4QGv28EvndZLbBV44lJyCG+JIoDuw==" + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -7337,7 +7337,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -8211,14 +8210,6 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, "node_modules/data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -8331,7 +8322,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -9903,14 +9893,6 @@ "ws": "7.4.6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -10512,9 +10494,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.14.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", - "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "funding": [ { "type": "individual", @@ -10664,39 +10646,6 @@ "node": ">=0.4.x" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/formdata-polyfill/node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, "node_modules/formik": { "version": "2.2.9", "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.9.tgz", @@ -13726,41 +13675,6 @@ "node": ">= 8" } }, - "node_modules/ky": { - "version": "0.33.2", - "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.2.tgz", - "integrity": "sha512-f6oS2rKUcPu5FzdqCDbFpmzis/JlqFZw8uIHm/jf8Kc3vtnW+VDhuashOAKyBZv8bFiZFZUMNxTC0JtahEvujA==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/ky?sponsor=1" - } - }, - "node_modules/ky-universal": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.11.0.tgz", - "integrity": "sha512-65KyweaWvk+uKKkCrfAf+xqN2/epw1IJDtlyCPxYffFCMR8u1sp2U65NtWpnozYfZxQ6IUzIlvUcw+hQ82U2Xw==", - "dependencies": { - "abort-controller": "^3.0.0", - "node-fetch": "^3.2.10" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/ky-universal?sponsor=1" - }, - "peerDependencies": { - "ky": ">=0.31.4", - "web-streams-polyfill": ">=3.2.1" - }, - "peerDependenciesMeta": { - "web-streams-polyfill": { - "optional": true - } - } - }, "node_modules/language-subtag-registry": { "version": "0.3.21", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", @@ -14145,7 +14059,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -14154,7 +14067,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -14397,63 +14309,6 @@ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", - "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/node-fetch/node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -14467,6 +14322,8 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "optional": true, + "peer": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -16634,8 +16491,7 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/psl": { "version": "1.8.0", @@ -19653,6 +19509,8 @@ "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", "hasInstallScript": true, + "optional": true, + "peer": true, "dependencies": { "node-gyp-build": "^4.3.0" }, @@ -19808,14 +19666,6 @@ "minimalistic-assert": "^1.0.0" } }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "engines": { - "node": ">= 8" - } - }, "node_modules/web-vitals": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-2.1.2.tgz", @@ -22455,26 +22305,44 @@ } }, "@ethersphere/bee-js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-5.2.0.tgz", - "integrity": "sha512-BM9lBiKC/tMbYNTEs3uyDyAwpED+v6u46DEXyFh7BLCUPg12LBWv0O12XmQj5ybzXnUT4ptHU9UXu3oGHph8Vw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-6.2.0.tgz", + "integrity": "sha512-QWuVvW+c9z+AFWuRL+YBZECDyV3G5qeD9L0J7Tx7HYMugoDjMAjeRyNHjkf0a5np57q3i9MAE2P678rjSJ1Yaw==", "requires": { "@ethersphere/swarm-cid": "^0.1.0", "@types/readable-stream": "^2.3.13", - "bufferutil": "^4.0.6", + "axios": "^1.3.4", + "cafe-utility": "^10.8.1", "elliptic": "^6.5.4", "fetch-blob": "2.1.2", "isomorphic-ws": "^4.0.1", "js-sha3": "^0.8.0", - "ky": "^0.33.2", - "ky-universal": "^0.11.0", "semver": "^7.3.5", "tar-js": "^0.3.0", - "utf-8-validate": "^5.0.9", "web-streams-polyfill": "^4.0.0-beta.3", "ws": "^8.7.0" }, "dependencies": { + "axios": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "web-streams-polyfill": { "version": "4.0.0-beta.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", @@ -22488,14 +22356,6 @@ } } }, - "@ethersphere/manifest-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@ethersphere/manifest-js/-/manifest-js-1.2.1.tgz", - "integrity": "sha512-HfeQ5h9KuH8xTxYY6bmSNwmpalrdDyOu4Sl6mrAN2W2iJlIjuG5DeirseSEFXElKPwEdv03PzZt2vARPna8sfw==", - "requires": { - "mantaray-js": "^1.0.3" - } - }, "@ethersphere/swarm-cid": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@ethersphere/swarm-cid/-/swarm-cid-0.1.0.tgz", @@ -24752,14 +24612,6 @@ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "dev": true }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -25058,8 +24910,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "at-least-node": { "version": "1.0.0", @@ -25698,6 +25549,8 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "optional": true, + "peer": true, "requires": { "node-gyp-build": "^4.3.0" } @@ -25713,6 +25566,11 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" }, + "cafe-utility": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/cafe-utility/-/cafe-utility-10.9.1.tgz", + "integrity": "sha512-/gq+ANoYvMJKrXXI/2YAiB2KhNlRhxB5XcWbbMWFA39LLCxkPhG5A9Ehy4QGv28EvndZLbBV44lJyCG+JIoDuw==" + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -26030,7 +25888,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -26696,11 +26553,6 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, - "data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" - }, "data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -26783,8 +26635,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "depcheck": { "version": "1.4.3", @@ -27974,11 +27825,6 @@ } } }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -28459,9 +28305,9 @@ "dev": true }, "follow-redirects": { - "version": "1.14.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", - "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==" + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" }, "for-each": { "version": "0.3.3", @@ -28557,25 +28403,6 @@ "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=" }, - "formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "requires": { - "fetch-blob": "^3.1.2" - }, - "dependencies": { - "fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "requires": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - } - } - } - }, "formik": { "version": "2.2.9", "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.9.tgz", @@ -30825,20 +30652,6 @@ "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", "dev": true }, - "ky": { - "version": "0.33.2", - "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.2.tgz", - "integrity": "sha512-f6oS2rKUcPu5FzdqCDbFpmzis/JlqFZw8uIHm/jf8Kc3vtnW+VDhuashOAKyBZv8bFiZFZUMNxTC0JtahEvujA==" - }, - "ky-universal": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.11.0.tgz", - "integrity": "sha512-65KyweaWvk+uKKkCrfAf+xqN2/epw1IJDtlyCPxYffFCMR8u1sp2U65NtWpnozYfZxQ6IUzIlvUcw+hQ82U2Xw==", - "requires": { - "abort-controller": "^3.0.0", - "node-fetch": "^3.2.10" - } - }, "language-subtag-registry": { "version": "0.3.21", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", @@ -31154,14 +30967,12 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "requires": { "mime-db": "1.52.0" } @@ -31351,32 +31162,6 @@ } } }, - "node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" - }, - "node-fetch": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", - "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", - "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "dependencies": { - "fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "requires": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - } - } - } - }, "node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -31386,7 +31171,9 @@ "node-gyp-build": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", - "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==" + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "optional": true, + "peer": true }, "node-int64": { "version": "0.4.0", @@ -32833,8 +32620,7 @@ "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "psl": { "version": "1.8.0", @@ -35138,6 +34924,8 @@ "version": "5.0.9", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", + "optional": true, + "peer": true, "requires": { "node-gyp-build": "^4.3.0" } @@ -35271,11 +35059,6 @@ "minimalistic-assert": "^1.0.0" } }, - "web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" - }, "web-vitals": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-2.1.2.tgz", diff --git a/package.json b/package.json index 754f907..8264d2b 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,7 @@ "url": "https://github.com/ethersphere/bee-dashboard.git" }, "dependencies": { - "@ethersphere/bee-js": "^5.2.0", - "@ethersphere/manifest-js": "1.2.1", + "@ethersphere/bee-js": "^6.2.0", "@ethersphere/swarm-cid": "^0.1.0", "@material-ui/core": "4.12.3", "@material-ui/icons": "4.11.2", @@ -44,6 +43,7 @@ "formik": "2.2.9", "formik-material-ui": "3.0.1", "jszip": "^3.7.1", + "mantaray-js": "^1.0.3", "material-ui-dropzone": "3.5.0", "notistack": "1.0.10", "opener": "1.5.2", @@ -137,7 +137,7 @@ "lint:check": "eslint \"src/**/*.ts\" \"src/**/*.tsx\" && prettier --check \"src/**/*.ts\" \"src/**/*.tsx\"", "check:types": "tsc --project tsconfig.lib.json", "update-map-data": "node ./utils/update-map-data.js", - "bee": "bee-factory start" + "bee": "npx bee-factory start" }, "files": [ "lib", @@ -159,6 +159,6 @@ "engines": { "node": ">=14.0.0", "npm": ">=6.9.0", - "bee": "1.12.0-88c1d236" + "bee": "1.16.1-8e269c8" } } diff --git a/src/components/ExpandableListItem.tsx b/src/components/ExpandableListItem.tsx index b9db46f..38a9bf5 100644 --- a/src/components/ExpandableListItem.tsx +++ b/src/components/ExpandableListItem.tsx @@ -1,8 +1,8 @@ -import { ReactElement, ReactNode } from 'react' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' -import { Typography, Grid, IconButton, Tooltip } from '@material-ui/core' -import Info from 'remixicon-react/InformationLineIcon' +import { Grid, IconButton, Tooltip, Typography } from '@material-ui/core' import ListItem from '@material-ui/core/ListItem' +import { Theme, createStyles, makeStyles } from '@material-ui/core/styles' +import { ReactElement, ReactNode } from 'react' +import Info from 'remixicon-react/InformationLineIcon' const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/src/components/StampExtensionModal.tsx b/src/components/StampExtensionModal.tsx new file mode 100644 index 0000000..59a1cd4 --- /dev/null +++ b/src/components/StampExtensionModal.tsx @@ -0,0 +1,97 @@ +import { BeeDebug } from '@ethersphere/bee-js' +import Button from '@material-ui/core/Button' +import Dialog from '@material-ui/core/Dialog' +import DialogActions from '@material-ui/core/DialogActions' +import DialogContent from '@material-ui/core/DialogContent' +import DialogTitle from '@material-ui/core/DialogTitle' +import Input from '@material-ui/core/Input' +import { useSnackbar } from 'notistack' +import { ReactElement, ReactNode, useState } from 'react' +import { SwarmSelect } from './SwarmSelect' + +interface Props { + label: string + icon: ReactNode + beeDebug: BeeDebug + stamp: string +} + +export default function StampExtensionModal({ label, icon, beeDebug, stamp }: Props): ReactElement { + const [open, setOpen] = useState(false) + const [amount, setAmount] = useState('') + const [type, setType] = useState<'Topup' | 'Dilute'>('Topup') + const { enqueueSnackbar } = useSnackbar() + + const handleClickOpen = (e: React.MouseEvent) => { + setOpen(true) + e.stopPropagation() + } + + const handleClose = () => { + setOpen(false) + } + + const handleAction = async () => { + if (type === 'Topup') { + try { + await beeDebug.topUpBatch(stamp, amount) + enqueueSnackbar(`Successfully topped up stamp, your changes will appear soon`, { variant: 'success' }) + } catch (error) { + enqueueSnackbar(`Failed to topup stamp: ${error || 'Unknown reason'}`, { variant: 'error' }) + } + } + + if (type === 'Dilute') { + try { + await beeDebug.diluteBatch(stamp, parseInt(amount, 10)) + enqueueSnackbar(`Successfully diluted stamp, your changes will appear soon`, { variant: 'success' }) + } catch (error) { + enqueueSnackbar(`Failed to dilute stamp: ${error || 'Unknown reason'}`, { variant: 'error' }) + } + } + } + + const handleChange = (event: React.ChangeEvent) => { + setAmount(event.target.value) + } + + return ( +
+ + + {label} + + setType(event.target.value as 'Topup' | 'Dilute')} + options={[ + { value: 'Topup', label: 'Topup' }, + { value: 'Dilute', label: 'Dilute' }, + ]} + /> + + + + + + + +
+ ) +} diff --git a/src/components/SwarmSelect.tsx b/src/components/SwarmSelect.tsx index f374e0a..b9671b7 100644 --- a/src/components/SwarmSelect.tsx +++ b/src/components/SwarmSelect.tsx @@ -30,6 +30,7 @@ interface Props { formik?: boolean defaultValue?: string placeholder?: string + disabled?: boolean } const useStyles = makeStyles((theme: Theme) => @@ -60,6 +61,7 @@ export function SwarmSelect({ onChange, label, placeholder, + disabled = false, }: Props): ReactElement { const classes = useStyles() @@ -69,6 +71,7 @@ export function SwarmSelect({ {label && {label}} {label}}
- {error && ( - - Error loading postage stamps details: {error.message} - - )} + {error && } {!error && ( <>
diff --git a/src/pages/accounting/PeerBalances.tsx b/src/pages/accounting/PeerBalances.tsx index e5d25f7..130d011 100644 --- a/src/pages/accounting/PeerBalances.tsx +++ b/src/pages/accounting/PeerBalances.tsx @@ -14,13 +14,15 @@ interface Props { } export default function PeerBalances({ accounting, isLoadingUncashed, totalUncashed }: Props): ReactElement | null { + const uncashedPeers = accounting?.filter(({ uncashedAmount }) => uncashedAmount.toBigNumber.isGreaterThan('0')) || [] + return ( - {accounting?.map(({ peer, balance, received, sent, uncashedAmount, total }) => ( + {uncashedPeers.map(({ peer, balance, received, sent, uncashedAmount, total }) => ( {available && identity.feedHash ? ( <> - - - - + ) : ( diff --git a/src/pages/files/AssetSummary.tsx b/src/pages/files/AssetSummary.tsx index 943bd56..5424990 100644 --- a/src/pages/files/AssetSummary.tsx +++ b/src/pages/files/AssetSummary.tsx @@ -1,7 +1,6 @@ -import * as swarmCid from '@ethersphere/swarm-cid' +import { Utils } from '@ethersphere/bee-js' import { Box } from '@material-ui/core' import { ReactElement } from 'react' -import { Utils } from '@ethersphere/bee-js' import { DocumentationText } from '../../components/DocumentationText' import ExpandableListItemKey from '../../components/ExpandableListItemKey' import ExpandableListItemLink from '../../components/ExpandableListItemLink' @@ -19,16 +18,6 @@ export function AssetSummary({ isWebsite, reference }: Props): ReactElement { {isHash && } {!isHash && } - - {isWebsite && isHash && ( - - )} The Swarm Gateway is graciously provided by the Swarm Foundation. This service is under development and provided diff --git a/src/pages/files/Download.tsx b/src/pages/files/Download.tsx index 95f1ca7..bd3f87e 100644 --- a/src/pages/files/Download.tsx +++ b/src/pages/files/Download.tsx @@ -1,17 +1,17 @@ import { BeeModes, Utils } from '@ethersphere/bee-js' -import { ManifestJs } from '@ethersphere/manifest-js' import { useSnackbar } from 'notistack' import { ReactElement, useContext, useState } from 'react' import { useNavigate } from 'react-router-dom' import Search from 'remixicon-react/SearchLineIcon' import ExpandableListItemInput from '../../components/ExpandableListItemInput' import { History } from '../../components/History' +import { Context as BeeContext } from '../../providers/Bee' import { Context as FileContext, defaultUploadOrigin } from '../../providers/File' import { Context as SettingsContext } from '../../providers/Settings' -import { Context as BeeContext } from '../../providers/Bee' import { ROUTES } from '../../routes' import { recognizeEnsOrSwarmHash, regexpEns } from '../../utils' import { determineHistoryName, HISTORY_KEYS, putHistory } from '../../utils/local-storage' +import { ManifestJs } from '../../utils/manifest' import { FileNavigation } from './FileNavigation' export function Download(): ReactElement { @@ -34,9 +34,7 @@ export function Download(): ReactElement { ) { setReferenceError(undefined) } else { - setReferenceError( - 'Incorrect format of swarm hash. Expected 64 or 128 hexstring characters, bzz.link url or ENS domain.', - ) + setReferenceError('Incorrect format of swarm hash. Expected 64 or 128 hexstring characters or ENS domain.') } } diff --git a/src/pages/files/Share.tsx b/src/pages/files/Share.tsx index 0f758f5..b748c89 100644 --- a/src/pages/files/Share.tsx +++ b/src/pages/files/Share.tsx @@ -1,4 +1,3 @@ -import { ManifestJs } from '@ethersphere/manifest-js' import { Box, Typography } from '@material-ui/core' import { saveAs } from 'file-saver' import JSZip from 'jszip' @@ -13,6 +12,7 @@ import { Context as BeeContext } from '../../providers/Bee' import { Context as SettingsContext } from '../../providers/Settings' import { ROUTES } from '../../routes' import { determineHistoryName, HISTORY_KEYS, putHistory } from '../../utils/local-storage' +import { ManifestJs } from '../../utils/manifest' import { AssetPreview } from './AssetPreview' import { AssetSummary } from './AssetSummary' import { DownloadActionBar } from './DownloadActionBar' diff --git a/src/pages/files/Upload.tsx b/src/pages/files/Upload.tsx index 3bb163c..94a84a2 100644 --- a/src/pages/files/Upload.tsx +++ b/src/pages/files/Upload.tsx @@ -7,11 +7,11 @@ import { HistoryHeader } from '../../components/HistoryHeader' import { ProgressIndicator } from '../../components/ProgressIndicator' import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard' import { META_FILE_NAME, PREVIEW_FILE_NAME } from '../../constants' -import { CheckState, Context as BeeContext } from '../../providers/Bee' -import { Context as IdentityContext, Identity } from '../../providers/Feeds' +import { Context as BeeContext, CheckState } from '../../providers/Bee' +import { Identity, Context as IdentityContext } from '../../providers/Feeds' import { Context as FileContext } from '../../providers/File' import { Context as SettingsContext } from '../../providers/Settings' -import { Context as StampsContext, EnrichedPostageBatch } from '../../providers/Stamps' +import { EnrichedPostageBatch, Context as StampsContext } from '../../providers/Stamps' import { ROUTES } from '../../routes' import { waitUntilStampUsable } from '../../utils' import { detectIndexHtml, getAssetNameFromFiles, packageFile } from '../../utils/file' @@ -130,7 +130,7 @@ export function Upload(): ReactElement { } beeApi - .uploadFiles(stamp.batchID, fls, { indexDocument }) + .uploadFiles(stamp.batchID, fls, { indexDocument, deferred: true }) .then(hash => { putHistory(HISTORY_KEYS.UPLOAD_HISTORY, hash.reference, getAssetNameFromFiles(files)) diff --git a/src/pages/gift-code/index.tsx b/src/pages/gift-code/index.tsx index d692079..1edd931 100644 --- a/src/pages/gift-code/index.tsx +++ b/src/pages/gift-code/index.tsx @@ -1,22 +1,22 @@ import { Box, Tooltip, Typography } from '@material-ui/core' +import { Wallet } from 'ethers' import { useSnackbar } from 'notistack' import { ReactElement, useContext, useEffect, useState } from 'react' +import { useNavigate } from 'react-router' import Check from 'remixicon-react/CheckLineIcon' import X from 'remixicon-react/CloseLineIcon' -import { useNavigate } from 'react-router' -import { Wallet } from 'ethers' import ExpandableListItem from '../../components/ExpandableListItem' import ExpandableListItemActions from '../../components/ExpandableListItemActions' import ExpandableListItemKey from '../../components/ExpandableListItemKey' import { HistoryHeader } from '../../components/HistoryHeader' import { Loading } from '../../components/Loading' import { SwarmButton } from '../../components/SwarmButton' -import { Context as BalanceProvider } from '../../providers/WalletBalance' -import { Context as TopUpContext } from '../../providers/TopUp' +import { Token } from '../../models/Token' import { Context as SettingsContext } from '../../providers/Settings' +import { Context as TopUpContext } from '../../providers/TopUp' +import { Context as BalanceProvider } from '../../providers/WalletBalance' import { createGiftWallet } from '../../utils/desktop' import { ResolvedWallet } from '../../utils/wallet' -import { Token } from '../../models/Token' const GIFT_WALLET_FUND_DAI_AMOUNT = Token.fromDecimal('0.1', 18) const GIFT_WALLET_FUND_BZZ_AMOUNT = Token.fromDecimal('0.5', 16) @@ -31,6 +31,9 @@ export default function Index(): ReactElement { useEffect(() => { async function mapGiftWallets() { + if (!rpcProvider) { + return + } const results = [] for (const giftWallet of giftWallets) { results.push(await ResolvedWallet.make(giftWallet, rpcProvider)) diff --git a/src/pages/stamps/PostageStampCreation.tsx b/src/pages/stamps/PostageStampCreation.tsx index ce8e9d6..a9ac3fb 100644 --- a/src/pages/stamps/PostageStampCreation.tsx +++ b/src/pages/stamps/PostageStampCreation.tsx @@ -1,11 +1,11 @@ import { PostageBatchOptions } from '@ethersphere/bee-js' import { Box, Grid, Typography } from '@material-ui/core' import BigNumber from 'bignumber.js' -import { Form, Formik, FormikHelpers } from 'formik' import { useSnackbar } from 'notistack' -import { ReactElement, useContext } from 'react' +import { ReactElement, useContext, useEffect, useState } from 'react' import Check from 'remixicon-react/CheckLineIcon' import { SwarmButton } from '../../components/SwarmButton' +import { SwarmSelect } from '../../components/SwarmSelect' import { SwarmTextInput } from '../../components/SwarmTextInput' import { Context as BeeContext } from '../../providers/Bee' import { Context as SettingsContext } from '../../providers/Settings' @@ -19,18 +19,6 @@ import { } from '../../utils' import { getHumanReadableFileSize } from '../../utils/file' -interface FormValues { - depth?: string - amount?: string - label?: string -} -type FormErrors = Partial -const initialFormValues: FormValues = { - depth: '', - amount: '', - label: '', -} - interface Props { onFinished: () => void } @@ -40,6 +28,13 @@ export function PostageStampCreation({ onFinished }: Props): ReactElement { const { refresh } = useContext(StampsContext) const { beeDebugApi } = useContext(SettingsContext) + const [depthInput, setDepthInput] = useState('') + const [amountInput, setAmountInput] = useState('') + const [labelInput, setLabelInput] = useState('') + const [immutable, setImmutable] = useState(false) + const [errors, setErrors] = useState>({}) + const [submitting, setSubmitting] = useState(false) + const { enqueueSnackbar } = useSnackbar() function getFileSize(depth: number): string { @@ -76,6 +71,73 @@ export function PostageStampCreation({ onFinished }: Props): ReactElement { return `${price.toSignificantDigits()} xBZZ` } + async function submit() { + try { + // This is really just a typeguard, the validation pretty much guarantees these will have the right values + if (!depthInput || !amountInput) { + return + } + + if (!beeDebugApi) { + return + } + + setSubmitting(true) + const amount = BigInt(amountInput) + const depth = Number.parseInt(depthInput) + const options: PostageBatchOptions = { + waitForUsable: false, + label: labelInput || undefined, + immutableFlag: immutable, + } + + const batchId = await beeDebugApi.createPostageBatch(amount.toString(), depth, options) + await waitUntilStampExists(batchId, beeDebugApi) + await refresh() + onFinished() + } catch (e) { + console.error(e) // eslint-disable-line + enqueueSnackbar(`Error: ${(e as Error).message}`, { variant: 'error' }) + } + setSubmitting(false) + } + + useEffect(() => { + function validate() { + const errors: Record = {} + + if (!depthInput) { + errors.depth = 'Required field' + } else { + const depth = new BigNumber(depthInput) + + if (!depth.isInteger()) { + errors.depth = 'Depth must be an integer' + } else if (depth.isLessThan(17)) { + errors.depth = 'Minimal depth is 17' + } else if (depth.isGreaterThan(255)) { + errors.depth = 'Depth has to be at most 255' + } + } + + if (!amountInput) { + errors.amount = 'Required field' + } else { + const amount = new BigNumber(amountInput) + + if (!amount.isInteger()) { + errors.amount = 'Amount must be an integer' + } else if (amount.isLessThanOrEqualTo(0)) { + errors.amount = 'Amount must be greater than 0' + } + } + + return errors + } + + setErrors(validate()) + }, [depthInput, amountInput]) + return ( <> @@ -92,102 +154,72 @@ export function PostageStampCreation({ onFinished }: Props): ReactElement { . - ) => { - try { - // This is really just a typeguard, the validation pretty much guarantees these will have the right values - if (!values.depth || !values.amount) return - - if (!beeDebugApi) return - - const amount = BigInt(values.amount) - const depth = Number.parseInt(values.depth) - const options: PostageBatchOptions = { waitForUsable: false, label: values.label || undefined } - const batchId = await beeDebugApi.createPostageBatch(amount.toString(), depth, options) - await waitUntilStampExists(batchId, beeDebugApi) - actions.resetForm() - await refresh() - onFinished() - } catch (e) { - console.error(e) // eslint-disable-line - enqueueSnackbar(`Error: ${(e as Error).message}`, { variant: 'error' }) - actions.setSubmitting(false) - } - }} - validate={(values: FormValues) => { - const errors: FormErrors = {} - - // Depth - if (!values.depth) errors.depth = 'Required field' - else { - const depth = new BigNumber(values.depth) - - if (!depth.isInteger()) errors.depth = 'Depth must be an integer' - else if (depth.isLessThan(17)) errors.depth = 'Minimal depth is 17' - else if (depth.isGreaterThan(255)) errors.depth = 'Depth has to be at most 255' - } - - // Amount - if (!values.amount) errors.amount = 'Required field' - else { - const amount = new BigNumber(values.amount) - - if (!amount.isInteger()) errors.amount = 'Amount must be an integer' - else if (amount.isLessThanOrEqualTo(0)) errors.amount = 'Amount must be greater than 0' - } - - return errors - }} + + setDepthInput(event.target.value)} /> + + + Corresponding file size + {!errors.depth && depthInput ? getFileSize(parseInt(depthInput, 10)) : '-'} + + + + + setAmountInput(event.target.value)} /> + + + Corresponding TTL (Time to live) + {!errors.amount && amountInput ? getTtl(Number.parseInt(amountInput, 10)) : '-'} + + + + + setLabelInput(event.target.value)} /> + + + setImmutable(event.target.value === 'Yes')} + options={[ + { value: 'Yes', label: 'Yes' }, + { value: 'No', label: 'No' }, + ]} + /> + + + {immutable && ( + + Once an immutable stamp is maxed out, it disallows further content uploads, thereby safeguarding your + previously uploaded content from unintentional overwriting. + + )} + {!immutable && ( + + When a mutable stamp reaches full capacity, it still permits new content uploads. However, this comes + with the caveat of overwriting previously uploaded content associated with the same stamp. + + )} + + + + + + Indicative Price + + {!errors.amount && !errors.depth && amountInput && depthInput + ? getPrice(parseInt(depthInput, 10), BigInt(amountInput)) + : '-'} + + + + 0} + onClick={submit} + iconType={Check} + loading={submitting} > - {({ submitForm, isValid, isSubmitting, values, errors }) => ( -
- - - - - Corresponding file size - - {!errors.depth && values.depth ? getFileSize(parseInt(values.depth, 10)) : '-'} - - - - - - - - - Corresponding TTL (Time to live) - - {!errors.amount && values.amount ? getTtl(Number.parseInt(values.amount, 10)) : '-'} - - - - - - - - - - Indicative Price - - {!errors.amount && !errors.depth && values.amount && values.depth - ? getPrice(parseInt(values.depth, 10), BigInt(values.amount)) - : '-'} - - - - - Buy New Stamp - -
- )} -
+ Buy New Stamp + ) } diff --git a/src/pages/stamps/StampsTable.tsx b/src/pages/stamps/StampsTable.tsx index 8df6e38..1837268 100644 --- a/src/pages/stamps/StampsTable.tsx +++ b/src/pages/stamps/StampsTable.tsx @@ -1,8 +1,12 @@ -import type { ReactElement } from 'react' +import { ReactElement, useContext } from 'react' +import TimerFlash from 'remixicon-react/TimerFlashFillIcon' import ExpandableElement from '../../components/ExpandableElement' import ExpandableList from '../../components/ExpandableList' import ExpandableListItem from '../../components/ExpandableListItem' +import ExpandableListItemActions from '../../components/ExpandableListItemActions' import ExpandableListItemKey from '../../components/ExpandableListItemKey' +import StampExtensionModal from '../../components/StampExtensionModal' +import { Context } from '../../providers/Settings' import { EnrichedPostageBatch } from '../../providers/Stamps' import { secondsToTimeString } from '../../utils' import { getHumanReadableFileSize } from '../../utils/file' @@ -13,7 +17,11 @@ interface Props { } function StampsTable({ postageStamps }: Props): ReactElement | null { - if (postageStamps === null) return null + const { beeDebugApi } = useContext(Context) + + if (!postageStamps || !beeDebugApi) { + return null + } return ( @@ -38,7 +46,16 @@ function StampsTable({ postageStamps }: Props): ReactElement | null { + + + } + beeDebug={beeDebugApi} + stamp={stamp.batchID} + /> + } > diff --git a/src/providers/Bee.tsx b/src/providers/Bee.tsx index 0d2e0f4..63586e0 100644 --- a/src/providers/Bee.tsx +++ b/src/providers/Bee.tsx @@ -9,7 +9,7 @@ import { Peer, Topology, } from '@ethersphere/bee-js' -import { createContext, ReactChild, ReactElement, useContext, useEffect, useState } from 'react' +import { ReactChild, ReactElement, createContext, useContext, useEffect, useState } from 'react' import semver from 'semver' import PackageJson from '../../package.json' import { useLatestBeeRelease } from '../hooks/apiHooks' diff --git a/src/providers/Settings.tsx b/src/providers/Settings.tsx index 8538927..a414400 100644 --- a/src/providers/Settings.tsx +++ b/src/providers/Settings.tsx @@ -1,8 +1,8 @@ import { Bee, BeeDebug } from '@ethersphere/bee-js' import { providers } from 'ethers' -import { createContext, ReactNode, ReactElement, useEffect, useState } from 'react' -import { useGetBeeConfig } from '../hooks/apiHooks' +import { ReactElement, ReactNode, createContext, useEffect, useState } from 'react' import { DEFAULT_BEE_API_HOST, DEFAULT_BEE_DEBUG_API_HOST, DEFAULT_RPC_URL } from '../constants' +import { useGetBeeConfig } from '../hooks/apiHooks' const LocalStorageKeys = { providerUrl: 'json-rpc-provider', @@ -18,7 +18,7 @@ interface ContextInterface { isDesktop: boolean desktopUrl: string rpcProviderUrl: string - rpcProvider: providers.JsonRpcProvider + rpcProvider: providers.JsonRpcProvider | null cors: string | null dataDir: string | null ensResolver: string | null @@ -42,7 +42,7 @@ const initialValues: ContextInterface = { desktopUrl: window.location.origin, setAndPersistJsonRpcProvider: async () => {}, // eslint-disable-line rpcProviderUrl: '', - rpcProvider: new providers.JsonRpcProvider(''), + rpcProvider: null, cors: null, dataDir: null, ensResolver: null, diff --git a/src/utils/index.ts b/src/utils/index.ts index 23f8575..b97da58 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,4 +1,4 @@ -import { BatchId, BeeDebug, BeeResponseError, PostageBatch } from '@ethersphere/bee-js' +import { BatchId, BeeDebug, PostageBatch } from '@ethersphere/bee-js' import { decodeCid } from '@ethersphere/swarm-cid' import { BigNumber } from 'bignumber.js' import { BZZ_LINK_DOMAIN } from '../constants' @@ -258,11 +258,8 @@ async function waitForStamp( const stamp = await beeDebug.getPostageBatch(batchId) if (stamp[field]) return stamp - } catch (e) { - // TODO: Workaround for https://github.com/ethersphere/bee/issues/3300 - if ((e as BeeResponseError).message !== 'Bad Request: cannot get batch') { - throw e - } + } catch { + // ignore } await sleepMs(pollingFrequency) diff --git a/src/utils/manifest.ts b/src/utils/manifest.ts new file mode 100644 index 0000000..47e631e --- /dev/null +++ b/src/utils/manifest.ts @@ -0,0 +1,149 @@ +import { Bee, Utils } from '@ethersphere/bee-js' +import { loadAllNodes, MantarayNode, MetadataMapping, Reference } from 'mantaray-js' + +interface ValueNode extends MantarayNode { + getEntry: Reference +} + +/** + * The ASCII code of the character `/`. + * + * This prefix of the root node holds metadata such as the index document. + */ +const INDEX_DOCUMENT_FORK_PREFIX = '47' + +export class ManifestJs { + private bee: Bee + + constructor(bee: Bee) { + this.bee = bee + } + + /** + * Tests whether a given Swarm hash is a valid mantaray manifest + */ + public async isManifest(hash: string): Promise { + try { + const data = await this.bee.downloadData(hash) + const node = new MantarayNode() + node.deserialize(data) + + return true + } catch { + return false + } + } + + /** + * Retrieves `website-index-document` from a Swarm hash, or `null` if it is not present + */ + public async getIndexDocumentPath(hash: string): Promise { + const metadata = await this.getRootSlashMetadata(hash) + + if (!metadata) { + return null + } + + return metadata['website-index-document'] || null + } + + /** + * Retrieves all paths with the associated hashes from a Swarm manifest + */ + public async getHashes(hash: string): Promise> { + const data = await this.bee.downloadData(hash) + const node = new MantarayNode() + node.deserialize(data) + await loadAllNodes(this.load.bind(this), node) + const result = {} + this.extractHashes(result, node) + + return result + } + + /** + * Resolves an arbitrary Swarm feed manifest to its latest update reference. + * @returns `/bzz` root manifest hash, or `Promise` if hash is not a feed manifest + * @throws in case of network errors or bad input + */ + public async resolveFeedManifest(hash: string): Promise { + const metadata = await this.getRootSlashMetadata(hash) + + if (!metadata) { + return null + } + + const owner = metadata['swarm-feed-owner'] + const topic = metadata['swarm-feed-topic'] + + if (!owner || !topic) { + return null + } + + const reader = this.bee.makeFeedReader('sequence', topic, owner) + const response = await reader.download() + + return response.reference + } + + private async getRootSlashMetadata(hash: string): Promise { + const data = await this.bee.downloadData(hash) + const node = new MantarayNode() + node.deserialize(data) + + if (!node.forks) { + return null + } + const fork = node.forks[INDEX_DOCUMENT_FORK_PREFIX] + + if (!fork) { + return null + } + const metadataNode = fork.node + + if (!metadataNode.IsWithMetadataType()) { + return null + } + const metadata = metadataNode.getMetadata + + if (!metadata) { + return null + } + + return metadata + } + + private extractHashes(result: Record, node: MantarayNode, prefix = ''): void { + if (!node.forks) { + return + } + for (const fork of Object.values(node.forks)) { + const path = prefix + this.bytesToUtf8(fork.prefix) + const childNode = fork.node + + if (this.isValueNode(childNode, path)) { + result[path] = Utils.bytesToHex(childNode.getEntry) + } + + if (childNode.isEdgeType()) { + this.extractHashes(result, childNode, path) + } + } + } + + private load(reference: Uint8Array) { + return this.bee.downloadData(Utils.bytesToHex(reference)) + } + + private bytesToUtf8(bytes: Uint8Array): string { + return new TextDecoder('utf-8').decode(bytes) + } + + private isValueNode(node: MantarayNode, path: string): node is ValueNode { + return !this.isRootSlash(node, path) && node.isValueType() && typeof node.getEntry !== 'undefined' + } + + private isRootSlash(node: MantarayNode, path: string): boolean { + return path === '/' && node.IsWithMetadataType() + } +}