From c2192cf99bd88252b8a5ce5d50fbb641b1659678 Mon Sep 17 00:00:00 2001 From: Mikhail Petrov Date: Thu, 16 Jan 2025 21:14:55 +0300 Subject: [PATCH 1/5] github: add build workflow Signed-off-by: Mikhail Petrov --- .github/workflows/build.yml | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..9dc1868 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,67 @@ +name: Build + +on: + pull_request: + branches: + - master + types: [opened, synchronize] + paths-ignore: + - '**/*.md' + push: + # Build for the master branch. + branches: + - master + release: + types: + - published + workflow_dispatch: + inputs: + ref: + description: 'Ref to build [default: latest master; examples: v0.4.0, 9595da7d83efc330ca0bc94bef482e4edfbcf8fd]' + required: false + default: '' + deploy: + description: 'Deploy to production [default: false; examples: true, false]' + required: false + default: 'false' + +jobs: + build_release: + name: Build and deploy + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.ref }} + # Allows to fetch all history for all branches and tags. Need this for proper versioning. + fetch-depth: 0 + + - name: Build + run: make release + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: release + path: ./archive.fs.neo.org-*.tar.gz + if-no-files-found: error + + - name: Attach binary to the release as an asset + if: ${{ github.event_name == 'release' }} + run: gh release upload ${{ github.event.release.tag_name }} ./archive.fs.neo.org-*.tar.gz + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish to NeoFS + if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy == 'true') }} + uses: nspcc-dev/gh-push-to-neofs@master + with: + NEOFS_WALLET: ${{ secrets.NEOFS_WALLET }} + NEOFS_WALLET_PASSWORD: ${{ secrets.NEOFS_WALLET_PASSWORD }} + NEOFS_NETWORK_DOMAIN: ${{ vars.NEOFS_NETWORK_DOMAIN }} + NEOFS_HTTP_GATE: ${{ vars.NEOFS_HTTP_GATE }} + STORE_OBJECTS_CID: ${{ vars.STORE_OBJECTS_CID }} + PATH_TO_FILES_DIR: archive.fs.neo.org + STRIP_PREFIX: true + REPLACE_CONTAINER_CONTENTS: true From 04c0f17850f46a474a96d003cb09c7696cc522ae Mon Sep 17 00:00:00 2001 From: Mikhail Petrov Date: Thu, 16 Jan 2025 21:18:55 +0300 Subject: [PATCH 2/5] dockerignore: add one Follows send.fs.neo.org mostly. Signed-off-by: Mikhail Petrov --- .dockerignore | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1ee0d4d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +node_modules +npm-debug.log +build +.dockerignore +**/.git +**/.DS_Store +**/node_modules From f35400398f91fcbe8bf25aa7fd99b06a3a3d2285 Mon Sep 17 00:00:00 2001 From: Mikhail Petrov Date: Sat, 1 Feb 2025 00:50:28 +0300 Subject: [PATCH 3/5] makefile: add one Follows send.fs.neo.org mostly. Signed-off-by: Mikhail Petrov --- Makefile | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c31d95e --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +#!/usr/bin/make -f + +SHELL = bash + +VERSION ?= "$(shell git describe --tags --match "v*" --abbrev=8 2>/dev/null | sed -r 's,^v([0-9]+\.[0-9]+)\.([0-9]+)(-.*)?$$,\1 \2 \3,' | while read mm patch suffix; do if [ -z "$$suffix" ]; then echo $$mm.$$patch; else patch=`expr $$patch + 1`; echo $$mm.$${patch}-pre$$suffix; fi; done)" +SITE_DIR ?= archive.fs.neo.org +RELEASE_DIR ?= $(SITE_DIR)-$(VERSION) +RELEASE_PATH ?= $(SITE_DIR)-$(VERSION).tar.gz +CURRENT_UID ?= $(shell id -u $$USER) + +PORT = 3000 + +$(SITE_DIR): + docker run \ + -v $$(pwd)/src:/usr/src/app/src \ + -v $$(pwd)/public:/usr/src/app/public \ + -v $$(pwd)/package.json:/usr/src/app/package.json \ + -v $$(pwd)/$(SITE_DIR):/usr/src/app/$(SITE_DIR) \ + -e CURRENT_UID=$(CURRENT_UID) \ + -w /usr/src/app node:14-alpine \ + sh -c 'npm install && REACT_APP_VERSION=$(VERSION) npm run build && chown -R $$CURRENT_UID: $(SITE_DIR)' + +start: + docker run \ + -p $(PORT):3000 \ + -v `pwd`:/usr/src/app \ + -w /usr/src/app node:14-alpine \ + sh -c 'npm install --silent && npm run build && npm install -g serve && serve -s $(SITE_DIR) -p 3000' + +release: $(SITE_DIR) + cp $(SITE_DIR)/index.html $(SITE_DIR)/about + @ln -sf $(SITE_DIR) $(RELEASE_DIR) + @tar cfvhz $(RELEASE_PATH) $(RELEASE_DIR) + +clean: + @echo "Cleaning up ..." + @rm -rf $(SITE_DIR) $(RELEASE_DIR) $(RELEASE_PATH) + +release_name: + @echo $(RELEASE_PATH) + +version: + @echo $(VERSION) From a0de4321ba3e2da0746935d974fcb82a99f06e60 Mon Sep 17 00:00:00 2001 From: Mikhail Petrov Date: Fri, 7 Feb 2025 14:35:54 +0300 Subject: [PATCH 4/5] readme: add one with logo Signed-off-by: Mikhail Petrov --- .github/logo.svg | 129 +++++++++++++++++++++++++++++++++++++++++++++++ README.md | 31 ++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 .github/logo.svg create mode 100644 README.md diff --git a/.github/logo.svg b/.github/logo.svg new file mode 100644 index 0000000..b4da076 --- /dev/null +++ b/.github/logo.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..7ff664a --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +

+NeoFS +

+

+ NeoFS is a decentralized distributed object storage integrated with the Neo Blockchain. +

+ +--- +![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/nspcc-dev/archive-fs-neo-org?sort=semver) +![License](https://img.shields.io/github/license/nspcc-dev/archive-fs-neo-org.svg?style=popout) + +# Overview + +Archive.NeoFS – Offline Synchronization Package. Download an offline block dump up to a certain block height. This web application is built on the React framework. + +# Requirements + +- docker +- make +- node (`14+`) + +# Make instructions + +* Compile the build using `make` (will be generated in `archive-fs-neo-org` dir) +* Start app using `make start PORT=3000` (PORT=3000 by default) +* Clean up cache directories using `make clean` +* Get release directory with tar.gz using `make release` + +# License + +- [GNU General Public License v3.0](LICENSE) From eeceaf676731c507f0976abe071b31da5fe31aee Mon Sep 17 00:00:00 2001 From: Mikhail Petrov Date: Fri, 7 Feb 2025 14:36:09 +0300 Subject: [PATCH 5/5] web: Init first version with downloading blocks dump, closes #1 Signed-off-by: Mikhail Petrov --- package.json | 42 ++++ public/img/close.svg | 1 + public/img/cover.png | Bin 0 -> 78268 bytes public/img/favicon.ico | Bin 0 -> 15086 bytes public/img/logo.svg | 103 +++++++++ public/img/socials/github.svg | 1 + public/img/socials/medium.svg | 6 + public/img/socials/neo.svg | 64 ++++++ public/img/socials/neo_spcc.svg | 108 +++++++++ public/img/socials/twitter.svg | 1 + public/img/socials/youtube.svg | 1 + public/index.html | 28 +++ src/About.tsx | 37 +++ src/App.css | 386 ++++++++++++++++++++++++++++++++ src/App.tsx | 275 +++++++++++++++++++++++ src/Home.tsx | 276 +++++++++++++++++++++++ src/NotFound.tsx | 35 +++ src/api.ts | 50 +++++ src/index.tsx | 13 ++ 19 files changed, 1427 insertions(+) create mode 100644 package.json create mode 100644 public/img/close.svg create mode 100644 public/img/cover.png create mode 100644 public/img/favicon.ico create mode 100644 public/img/logo.svg create mode 100644 public/img/socials/github.svg create mode 100644 public/img/socials/medium.svg create mode 100644 public/img/socials/neo.svg create mode 100644 public/img/socials/neo_spcc.svg create mode 100644 public/img/socials/twitter.svg create mode 100644 public/img/socials/youtube.svg create mode 100644 public/index.html create mode 100644 src/About.tsx create mode 100644 src/App.css create mode 100644 src/App.tsx create mode 100644 src/Home.tsx create mode 100644 src/NotFound.tsx create mode 100644 src/api.ts create mode 100644 src/index.tsx diff --git a/package.json b/package.json new file mode 100644 index 0000000..f2ab157 --- /dev/null +++ b/package.json @@ -0,0 +1,42 @@ +{ + "name": "archive-fs-neo-org", + "version": "0.0.1", + "private": true, + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.4.0", + "@fortawesome/free-brands-svg-icons": "^6.4.0", + "@fortawesome/free-regular-svg-icons": "^6.4.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/react-fontawesome": "^0.2.0", + "@types/react": "^18.2.41", + "@types/react-dom": "^18.2.17", + "base-58": "^0.0.1", + "bulma": "^0.9.4", + "react": "^17.0.2", + "react-bulma-components": "^4.1.0", + "react-dom": "^17.0.2", + "react-router-dom": "^6.10.0" + }, + "scripts": { + "start": "REACT_APP_VERSION=$(make version) GENERATE_SOURCEMAP=false react-scripts start", + "build": "GENERATE_SOURCEMAP=false BUILD_PATH='./archive.fs.neo.org' react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "devDependencies": { + "dotenv": "^16.0.3", + "react-scripts": "^5.0.1", + "typescript": "^4.9.5" + } +} diff --git a/public/img/close.svg b/public/img/close.svg new file mode 100644 index 0000000..73396e3 --- /dev/null +++ b/public/img/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/cover.png b/public/img/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..2dc96248fe53fdd886c2b6599e690d1f616e7365 GIT binary patch literal 78268 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౫`ObRyvujmxp(m!IvYi*t-z2DE{* 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�J;cTDHp@qmW7c7G^OTJe|1>F8ShXMi9 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 Ad;kCd literal 0 HcmV?d00001 diff --git a/public/img/favicon.ico b/public/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5a1c5538f5432ddf07b4cff9b48a0597d9b85043 GIT binary patch literal 15086 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 R + + + + + image/svg+xml + + NeoFS + + + + + + + + NeoFS + + + + + + + + + + + + diff --git a/public/img/socials/github.svg b/public/img/socials/github.svg new file mode 100644 index 0000000..aa05db9 --- /dev/null +++ b/public/img/socials/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/socials/medium.svg b/public/img/socials/medium.svg new file mode 100644 index 0000000..08a9433 --- /dev/null +++ b/public/img/socials/medium.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/public/img/socials/neo.svg b/public/img/socials/neo.svg new file mode 100644 index 0000000..75e2d8b --- /dev/null +++ b/public/img/socials/neo.svg @@ -0,0 +1,64 @@ + + + + + + image/svg+xml + + Asset 9 + + + + + + + + Asset 9 + + + diff --git a/public/img/socials/neo_spcc.svg b/public/img/socials/neo_spcc.svg new file mode 100644 index 0000000..d0b04c6 --- /dev/null +++ b/public/img/socials/neo_spcc.svg @@ -0,0 +1,108 @@ + + + + + + image/svg+xml + + Asset 9 + + + + + + + + Asset 9 + + + + + + + + + + + + + + + + + + + + diff --git a/public/img/socials/twitter.svg b/public/img/socials/twitter.svg new file mode 100644 index 0000000..1970575 --- /dev/null +++ b/public/img/socials/twitter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/socials/youtube.svg b/public/img/socials/youtube.svg new file mode 100644 index 0000000..6c30aa1 --- /dev/null +++ b/public/img/socials/youtube.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..89f78c0 --- /dev/null +++ b/public/index.html @@ -0,0 +1,28 @@ + + + + + Archive.NeoFS + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/src/About.tsx b/src/About.tsx new file mode 100644 index 0000000..3923cc3 --- /dev/null +++ b/src/About.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { + Content, + Container, + Section, + Heading, + Tile, + Notification, +} from 'react-bulma-components'; + +const About = () => { + return ( + +
+ + ); +} + +export default About; diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..ea0fe5d --- /dev/null +++ b/src/App.css @@ -0,0 +1,386 @@ +body { + margin: 0; + padding: 0; + color: #111827; + background: #fff; + font-family: 'Poppins', sans-serif; + min-width: 300px; + -webkit-tap-highlight-color: rgba(255, 255, 255, 0); +} + +a { + text-decoration: none; +} + +#about a { + color: #02af92 +} + +:focus { + outline-color: #02af92; +} + +.input:active, +.input:focus, +.is-active.input, +.is-active.textarea, +.is-focused.input, +.is-focused.textarea, +.select select.is-active, +.select select.is-focused, +.select select:active, +.select select:focus, +.textarea:active, +.textarea:focus { + border-color: #02af92; +} + +.input[disabled] { + border-color: #dbdbdb; +} + +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.select select[disabled] { + border-color: #dbdbdb !important; +} + +.select:not(.is-multiple):not(.is-loading)::after { + border-color: #02af92; +} + +.select_block { + display: flex; + align-items: center; + flex-direction: column; + margin-bottom: 0 !important; +} + +.select_block select { + min-width: 300px; +} + +.inputs_block { + display: flex; + justify-content: center; +} + +.inputs_block input { + width: 145px; + margin: 0 5px; +} + +progress { + border-radius: 6px !important; + text-align: center; + margin: 10px auto !important; + max-width: 90%; + height: 10px !important; +} + +progress::-webkit-progress-value { + background: #02af92 !important; +} + +.navbar-item, +.navbar-link { + color: #ffffff80 !important; + background: transparent !important; +} + +.notification a:not(.button):not(.dropdown-item) { + text-decoration: none; +} + +.notification { + padding: 1.25rem 1.5rem 1.25rem 1.5rem; +} + +a.navbar-item:hover, +div.navbar-item:hover { + cursor: pointer; + color: #fff !important; +} + +.navbar, +.navbar-menu { + background: #29363b; +} + +.navbar-burger { + color: #ffffff; +} + +.tooltip { + position: absolute; + min-width: 70px; + background: #29363b; + text-align: center; + padding: 4px 8px; + font-size: 12px; + border-radius: 4px; + color: #fff; + top: -80%; +} + +.tooltip:after { + position: absolute; + border: solid transparent; + content: ""; + height: 0; + width: 0; + top: 100%; + right: 50%; + border-width: 6px; + margin: -2px -6px; + border-top-color: #29363b; +} + +.socials { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 20px; +} + +.socials a { + line-height: 0; + margin: 0 10px; +} + +.social_pipe { + border-right: 2px solid rgb(0, 0, 0); + padding-right: 10px; + display: flex; +} + +.button { + outline: none; + box-shadow: unset !important; +} + +.button.is-primary, +.notification.is-primary { + color: #fff; + background: #02af92; + border-color: #02af92; +} + +.notification.is-primary { + padding: 0.5rem 1rem; + margin-bottom: 0.5rem; +} + +.notification>.delete { + right: 1rem; + top: 0.65rem; +} + +.file.is-boxed .file-cta { + border-style: dashed; + border-width: 2px; +} + +.file-cta, +.file-name { + white-space: normal; + text-align: center; +} + +.file.is-boxed .file-icon { + height: 3.5em; +} + +.label { + font-weight: 400; +} + +.button.is-focused, +.button:focus { + border-color: inherit; +} + +.footer .subtitle { + line-height: 1.5; +} + +code { + padding: 0.2em 0.4em; + margin: 0; + font-size: 85%; + white-space: break-spaces; + background-color: #eff1f2; + color: inherit; + border-radius: 6px; +} + +.content pre { + color: inherit; + border-radius: 4px; +} + +/* modal */ +.modal { + position: fixed; + z-index: 102; + display: flex; + justify-content: center; + align-items: center; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.4); +} + +.modal_close_panel { + position: fixed; + z-index: 102; + display: flex; + justify-content: center; + align-items: center; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: auto; +} + +.modal_content { + position: absolute; + background: #fff; + border-radius: 4px; + z-index: 103; + padding: 1.25rem 1.5rem 1.25rem 1.5rem; + min-width: 300px; + max-width: 350px; + margin: 10px; +} + +.modal_scroll { + overflow-y: auto; + width: 100%; + display: flex; + justify-content: center; + align-items: flex-start; +} + +.modal_scroll .modal_content { + position: relative; +} + +.modal_close { + padding: 5px; + position: absolute; + top: 0; + right: 0; +} + +.modal_close img { + cursor: pointer; +} + +.modal_loader { + display: flex; + margin: 5px auto 15px; + -webkit-animation: pulse 1.5s infinite linear; + animation: pulse 1.5s infinite linear; +} + +@media (prefers-color-scheme: dark) { + html { + background: #2d333b; + } + + body { + color: #adbac7; + background: #22272d; + } + + .navbar-menu, + .footer, + .modal_content { + background: #2d333b; + } + + .subtitle, + .navbar-item, + .navbar-link, + .label { + color: #adbac7 !important; + } + + .notification code, + .notification pre { + background: #343942; + } + + .notification.is-primary .subtitle { + color: #fff !important; + } + + .navbar, + .file-cta:hover { + background: #2d333b !important; + } + + .notification { + background: #22272d; + border: 2px solid #343942; + } + + .file-cta { + background: #22272d; + border-color: #343942; + color: #adbac7 !important; + } + + .input, + .select select, + .textarea { + color: #adbac7; + background-color: #22272d; + border-color: #343942; + outline: none !important; + } + + .select:not(.is-multiple):not(.is-loading)::after { + border-color: #adbac7; + } + + .socials a { + filter: invert(1); + } + + .social_pipe { + border-color: #fff; + } +} + +@media (min-width: 1025px) { + .navbar-menu { + margin-right: 6rem; + } + + .navbar-brand { + margin-left: 6rem; + } +} + +@media (max-width: 500px) { + .title { + font-size: 20px; + } + + .section { + padding: 1.5rem 1rem; + } + + .notification { + padding: 1rem; + } +} diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..321d014 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,275 @@ +import React, { useState } from 'react'; +import { Link, Route, Routes } from "react-router-dom"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { + Navbar, + Heading, + Footer, + Progress, + Button, +} from 'react-bulma-components'; +import Home from './Home.tsx'; +import About from './About.tsx'; +import NotFound from './NotFound.tsx'; +import 'bulma/css/bulma.min.css'; +import './App.css'; + +import { + faSpinner, + faDownload, +} from '@fortawesome/free-solid-svg-icons'; + +library.add( + faDownload, + faSpinner, +); + +interface NetItem { + title: string + containerId: string + rpc: string + maxBlock: number +} + +interface Modal { + current: string | null + params: any + btn: string | null | Function +} + +export const App = () => { + const [nets, setNets] = useState([{ + title: 'Mainnet', + containerId: '3RCdP3ZubyKyo8qFeo7EJPryidTZaGCMdUjqFJaaEKBV', + rpc: 'https://rpc10.n3.nspcc.ru:10331', + maxBlock: 0, + }, { + title: 'Testnet', + containerId: 'A8nGtDemWrm2SjfcGAG6wvrxmXwqc5fwr8ezNDm6FraT', + rpc: 'https://rpc.t5.n3.nspcc.ru:20331', + maxBlock: 0, + }, { + title: 'NeoFS Mainnet', + containerId: 'BP71MqY7nJhpuHfdQU3infRSjMgVmSFFt9GfG2GGMZJj', + rpc: 'https://rpc.morph.fs.neo.org', + maxBlock: 0, + }, { + title: 'NeoFS Testnet', + containerId: '98xz5YeanzxRCpH6EfUhECVm2MynGYchDN4naJViHT9M', + rpc: 'https://rpc1.morph.t5.fs.neo.org', + maxBlock: 0, + }]); + const [currentDownloadedBlock, setCurrentDownloadedBlock] = useState(0); + const [menuActive, setMenuActive] = useState(false); + const [isLoading, setLoading] = useState(false); + const [modal, setModal] = useState({ + current: null, + params: '', + btn: null, + }); + + const onModal = (current: string | null = null, params: any = null, btn: string | null = null) => { + setModal({ current, params, btn }); + }; + + const roundNumber = (num: number): number => { + const rounded = num.toFixed(2); + return parseFloat(rounded) % 1 === 0 ? parseInt(rounded) : parseFloat(rounded); + }; + + return ( + <> + {(modal.current === 'success' || modal.current === 'failed') && ( +
+
onModal()} + /> +
+
onModal()} + > + close +
+ {modal.current === 'success' ? 'Success' : 'Failed'} +

{modal.params}

+ {typeof modal.btn === 'function' && ( + + )} + {modal.btn === 'about' && ( + + )} +
+
+ )} + {modal.current === 'loading' && ( +
+
{} : () => { + onModal(); + setCurrentDownloadedBlock(0); + }} + /> +
+ {`Snapshot`} + {`${modal.params.spanStart} - ${modal.params.spanEnd} (${nets[modal.params.network].title})`} + {currentDownloadedBlock / (modal.params.spanEnd - modal.params.spanStart + 1) === 1 ? 'Success!' : 'Writing'} + + {`${currentDownloadedBlock} / ${modal.params.spanEnd - modal.params.spanStart + 1} (${roundNumber((currentDownloadedBlock / (modal.params.spanEnd - modal.params.spanStart + 1)) * 100)}%)`} +
+
+ )} + + + + logo + + setMenuActive(!menuActive)} + /> + + + + setMenuActive(false)} + > + Download + + setMenuActive(false)} + > + About + + + + +
+ + } + /> + } + /> + } + /> + +
+ + + ); +} diff --git a/src/Home.tsx b/src/Home.tsx new file mode 100644 index 0000000..42e021f --- /dev/null +++ b/src/Home.tsx @@ -0,0 +1,276 @@ +import React, { useState, useEffect } from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { + Content, + Container, + Form, + Section, + Heading, + Tile, + Tag, + Notification, + Button, +} from 'react-bulma-components'; +import api from './api.ts'; + +const base58 = require('base-58'); + +interface NetItem { + title: string + containerId: string +} + +interface FormData { + spanStart: number | '' + spanEnd: number | '' + network: number +} + +const Home = ({ + onModal, + nets, + setNets, + setCurrentDownloadedBlock, + isLoading, + setLoading, +}) => { + const [formData, setFormData] = useState({ + spanStart: 0, + spanEnd: '', + network: 0, + }); + + let fileHandle: FileSystemFileHandle | null = null; + + useEffect(() => { + if (nets[formData.network].maxBlock === 0) { + api('POST', nets[formData.network].rpc, { + "jsonrpc": "2.0", + "id": 1, + "method": "getblockcount", + "params": [] + }).then((res: any) => { + const netsTemp = [...nets]; + netsTemp[formData.network].maxBlock = Math.floor(res.result / 128000) * 128000; + setNets(netsTemp); + + setFormData({ ...formData, spanEnd: nets[formData.network].maxBlock }); + }).catch(() => { + onModal('failed', 'Failed to fetch the last available block'); + }); + } else { + if (formData.spanEnd > nets[formData.network].maxBlock) return setFormData({ ...formData, spanEnd: nets[formData.network].maxBlock }); + } + },[formData.network]); // eslint-disable-line react-hooks/exhaustive-deps + + const fetchBlocksInRange = async (retryIndex: number | null = null) => { + if (formData.spanStart === '' || formData.spanEnd === '' || formData.spanEnd < 0) return onModal('failed', 'Insert correct data'); + if (formData.spanStart < 0 || formData.spanEnd < 0 || formData.spanStart > nets[formData.network].maxBlock || formData.spanEnd > nets[formData.network].maxBlock) return onModal('failed', 'Insert correct borders'); + + + if (retryIndex === null) { + setLoading(true); + } + const currentNet: NetItem = nets[formData.network]; + + try { + if (retryIndex === null) { + fileHandle = await window.showSaveFilePicker({ + suggestedName: `chain.${formData.spanStart}.acc`, + types: [{ accept: { 'application/octet-stream': ['.acc'] } }], + }); + } + onModal('loading', formData); + + const writableStream = await fileHandle?.createWritable(retryIndex === null ? {} : { keepExistingData: true }); + + const blockCount = formData.spanEnd - formData.spanStart + 1; + if (retryIndex === null) { + await writableStream?.write(new Int32Array([blockCount]).buffer); + } else { + const offset: any = (await fileHandle?.getFile())?.size; + writableStream?.seek(offset) + } + + const indexFileStart = Math.floor(formData.spanStart / 128000); + const indexFileCount = Math.ceil((formData.spanEnd - formData.spanStart) / 128000) + indexFileStart; + for (let indexFile = indexFileStart; indexFile <= indexFileCount; indexFile += 1) { + + const indexData: Uint8Array | string = await fetchIndexFile(currentNet, indexFile); + if (typeof indexData === 'string') { + await writableStream?.close(); + onModal('failed', indexData, (retryIndexTemp: number) => fetchBlocksInRange(+formData.spanStart + retryIndexTemp)); + return + } + + const uint8Data = new Uint8Array(indexData); + const objectsData: string[] = []; + for (let i = 0; i < uint8Data.length; i += 32) { + const chunk = uint8Data.slice(i, i + 32); + const encoded = base58.encode(chunk); + objectsData.push(encoded); + } + + const startBlock = retryIndex !== null ? retryIndex : formData.spanStart; + for (let i = startBlock - (128000 * indexFile); i <= objectsData.length; i += 1) { + if (blockCount <= (indexFile * 128000 + i - formData.spanStart)) { + await writableStream?.close(); + return + } + + const objectData: Uint8Array | string = await fetchBlock(currentNet, objectsData[i]); + if (typeof objectData === 'string') { + await writableStream?.close(); + onModal('failed', objectData, (currentDownloadedBlockTemp: number) => fetchBlocksInRange(+formData.spanStart + currentDownloadedBlockTemp)); + return + } + + const blockSize = new Uint32Array([objectData.byteLength]); + await writableStream?.write(blockSize.buffer); + await writableStream?.write(new Uint8Array(objectData)); + setCurrentDownloadedBlock((indexFile * 128000 + i) - formData.spanStart + 1); + } + } + } catch (error: any) { + if (error.message.indexOf('showSaveFilePicker is not a function') !== -1) { + onModal('failed', 'Your current browser does not support this site\'s functionality. For the best experience, please use Chrome 86+ (recommended).', 'about'); + } else { + onModal('failed', error.message || 'Error occurred during block fetching.', (retryIndexTemp: number) => fetchBlocksInRange(+formData.spanStart + retryIndexTemp)); + } + } finally { + setLoading(false); + } + }; + + const fetchIndexFile = async (currentNet: NetItem, indexNumber: number): Promise => { + try { + const searchResponse: any = await api('POST', `/objects/${currentNet.containerId}/search?walletConnect=false&offset=0&limit=1`, { + filters: [{ + "key": "Index", + "match": "MatchStringEqual", + "value": indexNumber.toString(), + }], + }); + + const objectId = searchResponse.objects[0]?.address.objectId; + if (!objectId) { + return `Error occurred during index fetching #${indexNumber}`; + } + + const indexResponse = await api('GET', `/objects/${currentNet.containerId}/by_id/${objectId}?walletConnect=false`); + return indexResponse as Uint8Array; + } catch (err: any) { + return `Error occurred during index fetching #${indexNumber}: ${err.message}`; + } + }; + + const fetchBlock = async (currentNet: NetItem, objectId: string): Promise => { + try { + const blockResponse = await api('GET', `/objects/${currentNet.containerId}/by_id/${objectId}?walletConnect=false`); + return blockResponse as Uint8Array; + } catch (err: any) { + return `Error occurred during object fetching ${objectId}: ${err.message}`; + } + }; + + return ( + +
+ + + + Archive.NeoFS – Offline Synchronization Package + +

Easily download an offline package of blocks up to a specific block height.

+

Manual steps:

+
    +
  • Choose start and end snapshot option for the data range;
  • +
  • Select the desired network;
  • +
  • Click the Download button;
  • +
  • Wait for .acc file to download to your device. 🚀
  • +
+

For the best experience, please use Chrome 86+.

+
+
+
+
+ + + + Prepare snapshot + + + { + if (e.target.value === '' || /^[0-9]*[.]?[0-9]*$/.test(e.target.value)) { + setFormData({ ...formData, spanStart: e.target.value !== '' && e.target.value >= 0 ? Number(e.target.value) : '' }); + } + }} + disabled={isLoading} + /> + + + { + if (e.target.value === '' || /^[0-9]*[.]?[0-9]*$/.test(e.target.value)) { + setFormData({ ...formData, spanEnd: e.target.value !== '' && e.target.value >= 0 ? Number(e.target.value) : '' }); + } + }} + disabled={isLoading} + /> + + + + + setFormData({ ...formData, network: Number(e.target.value) })} + value={formData.network} + disabled={isLoading} + > + + + + + + + + + {`the latest available block is ${nets[formData.network].maxBlock ? nets[formData.network].maxBlock : '-'}`} + + + + + + + +
+
+ ); +} + +export default Home; diff --git a/src/NotFound.tsx b/src/NotFound.tsx new file mode 100644 index 0000000..b1f393d --- /dev/null +++ b/src/NotFound.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { + Container, + Section, + Heading, + Tile, + Notification, + Button, +} from 'react-bulma-components'; + +const NotFound = () => { + return ( + +
+ + + + 404 Not Found + Page not found + + + + + + +
+
+ ); +}; + +export default NotFound; diff --git a/src/api.ts b/src/api.ts new file mode 100644 index 0000000..24577ef --- /dev/null +++ b/src/api.ts @@ -0,0 +1,50 @@ +const server = 'https://rest.fs.neo.org/v1'; + +type Methods = "GET" | "POST"; + +async function serverRequest(method: Methods, url: string, params: object, headers: any) { + const json: any = { + method, + headers, + } + + if (json['headers']['Content-Type']) { + json['body'] = params; + } else if (Object.keys(params).length > 0) { + json['body'] = JSON.stringify(params); + json['headers']['Content-Type'] = 'application/json'; + } + + let activeUrl: string = url; + if (url.indexOf('https') === -1) { + activeUrl = `${server}${url}`; + } + + return fetch(activeUrl, json).catch((error: any) => error); +} + +export default function api(method: Methods, url: string, params: object = {}, headers: object = {}) { + return new Promise((resolve, reject) => { + serverRequest(method, url, params, headers).then(async (response: any) => { + if (response && response.status === 204) { + resolve({ status: 'success' }); + } else { + let res: any = response; + if (response?.status === 200 && url.indexOf('by_id') !== -1) { + res = await response.arrayBuffer(); + resolve(res); + } else if (response?.status === 200) { + res = await response.json(); + resolve(res); + } else { + try { + res = await response.json(); + reject(res); + } catch (err) { + reject(response); + } + } + } + }); + }); +} diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..6302304 --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import { App } from './App.tsx'; +import { BrowserRouter } from "react-router-dom"; + +ReactDOM.render( + + + + + , + document.getElementById('root') +);
+ + + + About Service + +

Archive.NeoFS is a web application that allows users to create blockchain archives of any span (from block 0 to the current block or a custom range) directly in the browser. It operates fully client-side, leveraging standard NeoFS REST gateway APIs and in-browser streaming techniques to efficiently fetch and store blocks without requiring additional backend processing.

+

The service supports four networks: mainnet, testnet, NeoFS mainnet, and NeoFS testnet. It interacts with the NeoFS REST gateway to retrieve blockchain data stored in NeoFS objects and assembles them into a structured archive format (.acc), that is compatible with both C# Neo node and NeoGo.

+

Frontend part first determines the latest available block in the selected network using the getblockcount method in the RPC request. Each block is stored as a separate object with a unique Object ID (OID), while index files contain references to batches of 128,000 blocks, mapping block indices to their corresponding OIDs. It then, using NeoFS REST gateway, the program first retrieves index files using SEARCH, then extracts object IDs then fetches these objects (containing blocks) via GET NeoFS request.

+

The process runs entirely in the browser using the showSaveFilePicker API for file handling and the WritableStream API for efficient in-browser streaming. Downloaded blocks are written directly into an archive .acc file, ensuring minimal memory overhead. However, due to API limitations, this feature is only supported in modern browsers: Chrome 86+ (recommended).

+ + + + +