Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3173ec9342 | ||
|
|
c8352e6537 | ||
|
|
9fbc6423d1 | ||
|
|
e4f691ab78 | ||
|
|
446276fadf | ||
|
|
1b574ac347 | ||
|
|
0c7db9cd30 | ||
|
|
fc977cc43a | ||
|
|
0a0151d1dd | ||
|
|
369f0e375c | ||
|
|
79ca03823c | ||
|
|
49f3ee17a0 | ||
|
|
841e82e233 | ||
|
|
2212ea7433 | ||
|
|
f257066d5a | ||
|
|
027bf0d405 |
64
.github/workflows/docker-image.yml
vendored
Normal file
64
.github/workflows/docker-image.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
name: Build and deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
paths-ignore:
|
||||||
|
- '.github/**'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
paths-ignore:
|
||||||
|
- '.github/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
logLevel:
|
||||||
|
description: 'Log level'
|
||||||
|
required: true
|
||||||
|
default: 'warning'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- info
|
||||||
|
- warning
|
||||||
|
- debug
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- name: Get branch data
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push image
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
tags: kandrusyak/blockchain-ui:master
|
||||||
|
deploy:
|
||||||
|
needs: build
|
||||||
|
name: Deploy to host
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- name: Get branch data
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Deploying changes
|
||||||
|
uses: appleboy/ssh-action@master
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.SSH_HOST }}
|
||||||
|
username: ${{ secrets.SSH_USERNAME }}
|
||||||
|
password: ${{ secrets.SSH_PASSWORD }}
|
||||||
|
script: |
|
||||||
|
docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
./update.sh
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
FROM node:16-alpine AS builder
|
FROM node:16-alpine AS builder
|
||||||
|
|
||||||
|
RUN apk --update add --no-cache curl git python3 alpine-sdk bash autoconf libtool automake
|
||||||
|
|
||||||
WORKDIR /front
|
WORKDIR /front
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|||||||
713
package-lock.json
generated
713
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -2,7 +2,7 @@
|
|||||||
"name": "mosaic-react",
|
"name": "mosaic-react",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "webpack-dev-server",
|
"dev": "webpack-dev-server --https",
|
||||||
"build:dev": "webpack --mode development --progress",
|
"build:dev": "webpack --mode development --progress",
|
||||||
"build:prod": "webpack --mode production --progress"
|
"build:prod": "webpack --mode production --progress"
|
||||||
},
|
},
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-flatpickr": "^3.10.7",
|
"react-flatpickr": "^3.10.7",
|
||||||
|
"react-loader-spinner": "^5.2.0",
|
||||||
"react-router-dom": "^6.2.1",
|
"react-router-dom": "^6.2.1",
|
||||||
"react-transition-group": "^4.4.1",
|
"react-transition-group": "^4.4.1",
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
@@ -34,18 +35,18 @@
|
|||||||
"@babel/core": "^7.18.5",
|
"@babel/core": "^7.18.5",
|
||||||
"@babel/preset-env": "^7.18.2",
|
"@babel/preset-env": "^7.18.2",
|
||||||
"@babel/preset-react": "^7.17.12",
|
"@babel/preset-react": "^7.17.12",
|
||||||
|
"autoprefixer": "^10.4.5",
|
||||||
"babel-loader": "^8.2.5",
|
"babel-loader": "^8.2.5",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
|
||||||
"css-loader": "^6.7.1",
|
"css-loader": "^6.7.1",
|
||||||
|
"file-loader": "^6.2.0",
|
||||||
"html-loader": "^3.1.2",
|
"html-loader": "^3.1.2",
|
||||||
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"postcss": "^8.4.5",
|
"postcss": "^8.4.5",
|
||||||
|
"postcss-loader": "^7.0.0",
|
||||||
"sass": "^1.52.3",
|
"sass": "^1.52.3",
|
||||||
"sass-loader": "^13.0.0",
|
"sass-loader": "^13.0.0",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"file-loader": "^6.2.0",
|
|
||||||
"postcss-loader": "^7.0.0",
|
|
||||||
"tailwindcss": "^3.0.18",
|
"tailwindcss": "^3.0.18",
|
||||||
"autoprefixer": "^10.4.5",
|
|
||||||
"webpack": "^5.73.0",
|
"webpack": "^5.73.0",
|
||||||
"webpack-cli": "^4.10.0",
|
"webpack-cli": "^4.10.0",
|
||||||
"webpack-dev-server": "^4.9.2"
|
"webpack-dev-server": "^4.9.2"
|
||||||
|
|||||||
@@ -19,8 +19,11 @@ import Onboarding4 from "./pages/Onboarding4";
|
|||||||
import SharedData from "./pages/SharedData";
|
import SharedData from "./pages/SharedData";
|
||||||
import ResetPassword from "./pages/ResetPassword";
|
import ResetPassword from "./pages/ResetPassword";
|
||||||
import SignIn from "./pages/SignIn";
|
import SignIn from "./pages/SignIn";
|
||||||
|
import {LoadingOverlay} from './components/LoadingOverlay';
|
||||||
|
import {store} from './store/store';
|
||||||
|
import {observer} from 'mobx-react-lite';
|
||||||
|
|
||||||
function App() {
|
const App = observer(() => {
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
useEffect(()=> {
|
useEffect(()=> {
|
||||||
@@ -35,6 +38,7 @@ function App() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{ store.loading && <LoadingOverlay /> }
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route exact path="/" element={<Onboarding1 />} />
|
<Route exact path="/" element={<Onboarding1 />} />
|
||||||
<Route path="/digitalId/profile-id" element={<ProfileId />} />
|
<Route path="/digitalId/profile-id" element={<ProfileId />} />
|
||||||
@@ -50,6 +54,6 @@ function App() {
|
|||||||
</Routes>
|
</Routes>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
15
src/components/LoadingOverlay.jsx
Normal file
15
src/components/LoadingOverlay.jsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import React from 'react';
|
||||||
|
import {ThreeCircles} from 'react-loader-spinner';
|
||||||
|
|
||||||
|
export const LoadingOverlay = () => ReactDOM.createPortal((
|
||||||
|
<div className='absolute left-0 top-0 h-screen w-screen z-50 loading-overlay'>
|
||||||
|
<ThreeCircles
|
||||||
|
height="100"
|
||||||
|
width="100"
|
||||||
|
color="#6366f1"
|
||||||
|
visible={true}
|
||||||
|
ariaLabel="three-circles-rotating"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
), document.body)
|
||||||
@@ -9,3 +9,10 @@
|
|||||||
@apply ring-0;
|
@apply ring-0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading-overlay {
|
||||||
|
background-color: rgba(0, 0, 0, 0.25);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ import App from './App'
|
|||||||
|
|
||||||
globalThis.Buffer = Buffer
|
globalThis.Buffer = Buffer
|
||||||
|
|
||||||
|
BigInt.prototype.toJSON = function() {
|
||||||
|
return this.toString()
|
||||||
|
}
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<Router>
|
<Router>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import Header from '../../partials/Header';
|
|||||||
import ProfileTable from '../../partials/profile/ProfileTable';
|
import ProfileTable from '../../partials/profile/ProfileTable';
|
||||||
import Image from '../../images/transactions-image-04.svg';
|
import Image from '../../images/transactions-image-04.svg';
|
||||||
import {labelMap} from '../../shared/labelMap';
|
import {labelMap} from '../../shared/labelMap';
|
||||||
|
import {statusMap} from "../../shared/statusMap";
|
||||||
|
|
||||||
const initialPropertyValues = ['First name', 'Second name', 'Birthdate', 'Gender', 'National doctype', 'National doc ID', 'National doc issue date', 'National doc expiry date'];
|
const initialPropertyValues = ['First name', 'Second name', 'Birthdate', 'Gender', 'National doctype', 'National doc ID', 'National doc issue date', 'National doc expiry date'];
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ const Profile = observer (() => {
|
|||||||
value: '',
|
value: '',
|
||||||
seed: String(Math.floor(Math.random() * 90000000000000000000), 10),
|
seed: String(Math.floor(Math.random() * 90000000000000000000), 10),
|
||||||
};
|
};
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||||
const [buttonPanelOpen, setButtonPanelOpen] = useState(true);
|
const [buttonPanelOpen, setButtonPanelOpen] = useState(true);
|
||||||
const [removePanelOpen, setRemovePanelOpen] = useState(false);
|
const [removePanelOpen, setRemovePanelOpen] = useState(false);
|
||||||
@@ -28,7 +29,8 @@ const Profile = observer (() => {
|
|||||||
const [updatedValues, setUpdatedValues] = useState([defaultValues]);
|
const [updatedValues, setUpdatedValues] = useState([defaultValues]);
|
||||||
const [addedValues, setAddedValues] = useState(defaultValues);
|
const [addedValues, setAddedValues] = useState(defaultValues);
|
||||||
const [isCheck, setIsCheck] = useState([]);
|
const [isCheck, setIsCheck] = useState([]);
|
||||||
const [alreadyExists, setAlreadyExists] = useState(false);
|
const [alreadyExists, setAlreadyExists] = useState(false)
|
||||||
|
const [blockChainValue, setBlockChainValue] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleSelectedItems(isCheck);
|
handleSelectedItems(isCheck);
|
||||||
@@ -57,12 +59,15 @@ const Profile = observer (() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const changeUpdatedValues = (value, field, key) => {
|
const changeUpdatedValues = (value, field, key) => {
|
||||||
|
if(field==='value') {
|
||||||
|
setBlockChainValue(value)
|
||||||
|
}
|
||||||
setUpdatedValues((prevState) =>
|
setUpdatedValues((prevState) =>
|
||||||
prevState.map((elem) => (
|
prevState.map((elem) => (
|
||||||
(elem.key === key) ? {
|
(elem.key === key) ? {
|
||||||
...elem,
|
...elem,
|
||||||
[field]: value,
|
[field]: value,
|
||||||
} : elem
|
} : elem
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@@ -127,8 +132,10 @@ const Profile = observer (() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const deleteDataParameters = () => {
|
const deleteDataParameters = () => {
|
||||||
const changeData = store.decryptedAccountData.filter(item=>!selectedItems.includes(item.key))
|
const changeData = store.decryptedAccountData.filter(item=>!selectedItems.includes(item.key));
|
||||||
store.pushAccountData(changeData);
|
store.pushAccountData(changeData);
|
||||||
|
if(storeOnBlockchain)
|
||||||
|
store.pushAccountDataToBlockchain(changeData.filter(elem=>elem.status!=='Stored'))
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeInitialArray = () => {
|
const changeInitialArray = () => {
|
||||||
@@ -138,6 +145,7 @@ const Profile = observer (() => {
|
|||||||
if (elem.label === item.label) {
|
if (elem.label === item.label) {
|
||||||
newArr.push({
|
newArr.push({
|
||||||
...elem,
|
...elem,
|
||||||
|
status: 'new',
|
||||||
'value': item.value,
|
'value': item.value,
|
||||||
'seed': item.seed,
|
'seed': item.seed,
|
||||||
})
|
})
|
||||||
@@ -153,6 +161,8 @@ const Profile = observer (() => {
|
|||||||
const changeDataParameters = () => {
|
const changeDataParameters = () => {
|
||||||
const updatedData = changeInitialArray();
|
const updatedData = changeInitialArray();
|
||||||
store.pushAccountData(updatedData);
|
store.pushAccountData(updatedData);
|
||||||
|
if(storeOnBlockchain)
|
||||||
|
store.pushAccountDataToBlockchain(updatedData.filter(elem=>elem.status!=='Stored'))
|
||||||
};
|
};
|
||||||
|
|
||||||
const addDataParameters = () => {
|
const addDataParameters = () => {
|
||||||
@@ -162,6 +172,8 @@ const Profile = observer (() => {
|
|||||||
else
|
else
|
||||||
addedValues.key = addedValues.label
|
addedValues.key = addedValues.label
|
||||||
store.pushAccountData(store.decryptedAccountData.concat(addedValues));
|
store.pushAccountData(store.decryptedAccountData.concat(addedValues));
|
||||||
|
if(storeOnBlockchain)
|
||||||
|
store.pushAccountDataToBlockchain(store.decryptedAccountData.concat(addedValues).filter(elem=>elem.status!=='Stored'))
|
||||||
};
|
};
|
||||||
|
|
||||||
const cancelAddPanel = () => {
|
const cancelAddPanel = () => {
|
||||||
@@ -352,7 +364,7 @@ const Profile = observer (() => {
|
|||||||
required
|
required
|
||||||
onChange={(e) => changeUpdatedValues(e.target.value, 'label', item.key)}
|
onChange={(e) => changeUpdatedValues(e.target.value, 'label', item.key)}
|
||||||
value={item.label}
|
value={item.label}
|
||||||
disabled='disabled'
|
disabled
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -364,7 +376,7 @@ const Profile = observer (() => {
|
|||||||
type="text"
|
type="text"
|
||||||
required
|
required
|
||||||
onChange={(e) => changeUpdatedValues(e.target.value, 'value', item.key)}
|
onChange={(e) => changeUpdatedValues(e.target.value, 'value', item.key)}
|
||||||
value={item.value}
|
value={item.status===statusMap.blockchained?blockChainValue : item.value}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ function ProfileTable({
|
|||||||
image={defaultData.image}
|
image={defaultData.image}
|
||||||
value={data.value.charAt(0).toUpperCase()+data.value.slice(1)}
|
value={data.value.charAt(0).toUpperCase()+data.value.slice(1)}
|
||||||
property={data.label}
|
property={data.label}
|
||||||
status={defaultData.status}
|
status={data.status}
|
||||||
transactions={defaultData.transactions}
|
transactions={defaultData.transactions}
|
||||||
avatars={defaultData.avatars}
|
avatars={defaultData.avatars}
|
||||||
handleClick={handleClick}
|
handleClick={handleClick}
|
||||||
@@ -69,7 +69,7 @@ function ProfileTable({
|
|||||||
image={defaultData.image}
|
image={defaultData.image}
|
||||||
value={data.value.charAt(0).toUpperCase()+data.value.slice(1)}
|
value={data.value.charAt(0).toUpperCase()+data.value.slice(1)}
|
||||||
property={data.label}
|
property={data.label}
|
||||||
status={defaultData.status}
|
status={data.status}
|
||||||
transactions={defaultData.transactions}
|
transactions={defaultData.transactions}
|
||||||
avatars={defaultData.avatars}
|
avatars={defaultData.avatars}
|
||||||
handleClick={handleClick}
|
handleClick={handleClick}
|
||||||
@@ -95,7 +95,7 @@ function ProfileTable({
|
|||||||
image={defaultData.image}
|
image={defaultData.image}
|
||||||
value={data.value.charAt(0).toUpperCase()+data.value.slice(1)}
|
value={data.value.charAt(0).toUpperCase()+data.value.slice(1)}
|
||||||
property={data.label}
|
property={data.label}
|
||||||
status={defaultData.status}
|
status={data.status}
|
||||||
transactions={defaultData.transactions}
|
transactions={defaultData.transactions}
|
||||||
avatars={defaultData.avatars}
|
avatars={defaultData.avatars}
|
||||||
handleClick={handleClick}
|
handleClick={handleClick}
|
||||||
@@ -121,7 +121,7 @@ function ProfileTable({
|
|||||||
image={defaultData.image}
|
image={defaultData.image}
|
||||||
value={data.value}
|
value={data.value}
|
||||||
property={data.label}
|
property={data.label}
|
||||||
status={defaultData.status}
|
status={data.status}
|
||||||
transactions={defaultData.transactions}
|
transactions={defaultData.transactions}
|
||||||
avatars={defaultData.avatars}
|
avatars={defaultData.avatars}
|
||||||
handleClick={handleClick}
|
handleClick={handleClick}
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import { statusMap } from '../../shared/statusMap';
|
||||||
|
|
||||||
function ProfileTableItem(props) {
|
function ProfileTableItem(props) {
|
||||||
const [descriptionOpen, setDescriptionOpen] = useState(false);
|
const [descriptionOpen, setDescriptionOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<tr className={`${props.status !== 'Progress' || 'bg-[#eaf0f6]'}`}>
|
<tr>
|
||||||
<td className="pl-4 pr-4 py-3 whitespace-nowrap w-px">
|
<td className="pl-4 pr-4 py-3 whitespace-nowrap w-px">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<label className="inline-flex">
|
<label className="inline-flex">
|
||||||
<span className="sr-only">Select</span>
|
<span className="sr-only">Select</span>
|
||||||
<input id={props.id} className="form-checkbox" type="checkbox" onChange={props.handleClick} checked={props.isChecked} />
|
<input
|
||||||
|
id={props.id}
|
||||||
|
className="form-checkbox"
|
||||||
|
type="checkbox"
|
||||||
|
onChange={props.handleClick}
|
||||||
|
checked={props.isChecked}
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -19,45 +26,51 @@ function ProfileTableItem(props) {
|
|||||||
<div className="w-9 h-9 shrink-0 mr-2 sm:mr-4">
|
<div className="w-9 h-9 shrink-0 mr-2 sm:mr-4">
|
||||||
<img className="rounded-full" src={props.image} width="40" height="40" alt={props.property} />
|
<img className="rounded-full" src={props.image} width="40" height="40" alt={props.property} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col w-60">
|
<div className="flex flex-col w-60">
|
||||||
<div className="font-semibold text-slate-800 text-base">{props.value}</div>
|
<div className="font-semibold text-slate-800 text-base">
|
||||||
|
{props.status === statusMap.blockchained || props.status === statusMap.processed
|
||||||
|
? `${props.value.slice(0, 4)}****${props.value.slice(props.value.length - 4)}`
|
||||||
|
: props.value}
|
||||||
|
</div>
|
||||||
<div className="font-normal text-xxs">{props.property}</div>
|
<div className="font-normal text-xxs">{props.property}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="py-3 whitespace-nowrap w-px">
|
<td className="py-3 whitespace-nowrap w-px px-2.5 text-left min-w-[117px]">
|
||||||
<div className="w-fit text-xs inline-flex font-medium px-2.5 py-1">
|
<div className="w-fit text-xs inline-flex font-medium py-1">
|
||||||
{(props.status === 'Progress') ? (
|
{props.status === statusMap.blockchained ? (
|
||||||
<div className="bg-amber-100 text-amber-600 rounded-full text-center px-2.5 py-1">
|
<div className="bg-amber-100 text-amber-600 rounded-full text-center px-2.5 py-1">{props.status}</div>
|
||||||
{props.status}
|
) : props.status === statusMap.processed ? (
|
||||||
</div>) :
|
<div className="bg-amber-100 text-amber-600 rounded-full text-center px-2.5 py-1">{props.status}</div>
|
||||||
(props.status === 'Stored') ? (
|
) : props.status === statusMap.stored ? (
|
||||||
<div className="bg-slate-700 text-slate-100 rounded-full text-center px-2.5 py-1">
|
<div className="bg-slate-700 text-slate-100 rounded-full text-center px-2.5 py-1">{props.status}</div>
|
||||||
{props.status}
|
) : props.status === statusMap.completed ? (
|
||||||
</div>) :
|
<div className="bg-emerald-100 text-emerald-600 rounded-full text-center px-2.5 py-1">{props.status}</div>
|
||||||
(props.status === 'Completed') ? (
|
) : (
|
||||||
<div className="bg-emerald-100 text-emerald-600 rounded-full text-center px-2.5 py-1">
|
<div className="bg-rose-100 text-rose-600 rounded-full text-center px-2.5 py-1">{props.status}</div>
|
||||||
{props.status}
|
)}
|
||||||
</div>) : (
|
|
||||||
<div className="bg-rose-100 text-rose-600 rounded-full text-center px-2.5 py-1">
|
|
||||||
{props.status}
|
|
||||||
</div>)
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-2 py-3 whitespace-nowrap w-[340px] box-border">
|
<td className="px-2 py-3 whitespace-nowrap w-[340px] box-border">
|
||||||
<div className="flex flex-wrap items-center -m-1.5 justify-center">
|
<div className="flex flex-wrap items-center -m-1.5 justify-center">
|
||||||
<div className="flex -space-x-3 -ml-0.5">
|
<div className="flex -space-x-3 -ml-0.5">
|
||||||
{(props.avatars) ? (
|
{props.avatars
|
||||||
props.avatars.map((avatar, index) => (
|
? props.avatars.map((avatar, index) => (
|
||||||
<img className="rounded-full border-2 border-slate-100 box-content" key={index} src={avatar} width="32" height="32" alt="Avatar" />
|
<img
|
||||||
|
className="rounded-full border-2 border-slate-100 box-content"
|
||||||
|
key={index}
|
||||||
|
src={avatar}
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
alt="Avatar"
|
||||||
|
/>
|
||||||
))
|
))
|
||||||
): null}
|
: null}
|
||||||
<button className="flex justify-center items-center w-9 h-9 rounded-full bg-white border-2 border-slate-200 hover:border-slate-300 text-indigo-500 shadow-sm transition duration-150">
|
<button className="flex justify-center items-center w-9 h-9 rounded-full bg-white border-2 border-slate-200 hover:border-slate-300 text-indigo-500 shadow-sm transition duration-150">
|
||||||
<span className="sr-only">Add avatar</span>
|
<span className="sr-only">Add avatar</span>
|
||||||
<svg className="w-4 h-4 fill-current" viewBox="0 0 16 16">
|
<svg className="w-4 h-4 fill-current" viewBox="0 0 16 16">
|
||||||
<path d="M15 7H9V1c0-.6-.4-1-1-1S7 .4 7 1v6H1c-.6 0-1 .4-1 1s.4 1 1 1h6v6c0 .6.4 1 1 1s1-.4 1-1V9h6c.6 0 1-.4 1-1s-.4-1-1-1z" />
|
<path d="M15 7H9V1c0-.6-.4-1-1-1S7 .4 7 1v6H1c-.6 0-1 .4-1 1s.4 1 1 1h6v6c0 .6.4 1 1 1s1-.4 1-1V9h6c.6 0 1-.4 1-1s-.4-1-1-1z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -74,31 +87,40 @@ function ProfileTableItem(props) {
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="py-3 whitespace-nowrap w-px pr-1.5">
|
<td className="py-3 whitespace-nowrap w-px pr-1.5">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<button
|
<button
|
||||||
className={`text-slate-400 hover:text-slate-500 transform ${descriptionOpen && 'rotate-180'}`}
|
className={`text-slate-400 hover:text-slate-500 transform ${descriptionOpen && 'rotate-180'}`}
|
||||||
aria-expanded={descriptionOpen}
|
aria-expanded={descriptionOpen}
|
||||||
onClick={() => setDescriptionOpen(!descriptionOpen)}
|
onClick={() => setDescriptionOpen(!descriptionOpen)}
|
||||||
aria-controls={`description-${props.id}`}
|
aria-controls={`description-${props.id}`}
|
||||||
>
|
>
|
||||||
<span className="sr-only">Show more</span>
|
<span className="sr-only">Show more</span>
|
||||||
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32">
|
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32">
|
||||||
<path d="M16 20l-5.4-5.4 1.4-1.4 4 4 4-4 1.4 1.4z" />
|
<path d="M16 20l-5.4-5.4 1.4-1.4 4 4 4-4 1.4 1.4z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr className={`${!descriptionOpen && 'hidden'} ${props.status !== 'Progress' || 'bg-[#eaf0f6]'}` }>
|
<tr className={`${!descriptionOpen && 'hidden'}`}>
|
||||||
<td colSpan="10" className="px-12 pt-3.5 pb-[14px]">
|
<td colSpan="10" className="px-12 pt-3.5 pb-[14px]">
|
||||||
<div className="flex items-center gap-x-5">
|
<div className="flex items-center gap-x-5">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="placeholder">Seed</label>
|
<label className="block text-sm font-medium mb-1" htmlFor="placeholder">
|
||||||
<input id="placeholder" className="form-input w-[396px] bg-white" type="text" placeholder="2342423423423234223" />
|
Seed
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="placeholder"
|
||||||
|
className="form-input w-[396px] bg-white"
|
||||||
|
type="text"
|
||||||
|
placeholder="2342423423423234223"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="block text-sm font-medium mb-1">Transaction</span>
|
<span className="block text-sm font-medium mb-1">Transaction</span>
|
||||||
<a href="" className="w-[396px] text-slate-400 font-normal text-sm underline">0x12831823791203192418234841238468</a>
|
<a href="" className="w-[396px] text-slate-400 font-normal text-sm underline">
|
||||||
|
0x12831823791203192418234841238468
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* Progress validation bar */}
|
{/* Progress validation bar */}
|
||||||
@@ -113,8 +135,11 @@ function ProfileTableItem(props) {
|
|||||||
{props.transactions.map((data, index) => (
|
{props.transactions.map((data, index) => (
|
||||||
<li className="relative py-2" key={index}>
|
<li className="relative py-2" key={index}>
|
||||||
<div className="flex items-center mb-2.5">
|
<div className="flex items-center mb-2.5">
|
||||||
{(props.transactions[index+1]) ? (
|
{props.transactions[index + 1] ? (
|
||||||
<div className="absolute left-0 h-full w-0.5 bg-slate-200 self-start ml-2.5 -translate-x-1/2 translate-y-3" aria-hidden="true"></div>
|
<div
|
||||||
|
className="absolute left-0 h-full w-0.5 bg-slate-200 self-start ml-2.5 -translate-x-1/2 translate-y-3"
|
||||||
|
aria-hidden="true"
|
||||||
|
></div>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="absolute left-0 rounded-full bg-indigo-500" aria-hidden="true">
|
<div className="absolute left-0 rounded-full bg-indigo-500" aria-hidden="true">
|
||||||
<svg className="w-5 h-5 fill-current text-white" viewBox="0 0 20 20">
|
<svg className="w-5 h-5 fill-current text-white" viewBox="0 0 20 20">
|
||||||
@@ -123,15 +148,21 @@ function ProfileTableItem(props) {
|
|||||||
</div>
|
</div>
|
||||||
<h3 className="pl-9 whitespace-nowrap">
|
<h3 className="pl-9 whitespace-nowrap">
|
||||||
<span className="text-validateSize font-bold text-slate-800">Validate by </span>
|
<span className="text-validateSize font-bold text-slate-800">Validate by </span>
|
||||||
<a href="" className="font-bold text-validateSize underline text-indigo-500">{data}</a>
|
<a href="" className="font-bold text-validateSize underline text-indigo-500">
|
||||||
|
{data}
|
||||||
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="pl-9">
|
<div className="pl-9">
|
||||||
<a href="" className="w-[396px] text-slate-800 font-semibold text-base underline">{data}</a>
|
<a href="" className="w-[396px] text-slate-800 font-semibold text-base underline">
|
||||||
|
{data}
|
||||||
|
</a>
|
||||||
<span className="block text-xxs font-normal mb-1">Transactions ID</span>
|
<span className="block text-xxs font-normal mb-1">Transactions ID</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="pl-9">
|
<div className="pl-9">
|
||||||
<a href="" className="w-[396px] text-slate-800 font-semibold text-base underline">{data.slice(2, data.length)}</a>
|
<a href="" className="w-[396px] text-slate-800 font-semibold text-base underline">
|
||||||
|
{data.slice(2, data.length)}
|
||||||
|
</a>
|
||||||
<span className="block text-xxs font-normal mb-1">Validated data</span>
|
<span className="block text-xxs font-normal mb-1">Validated data</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="pl-9 pt-[14px]">
|
<div className="pl-9 pt-[14px]">
|
||||||
@@ -139,15 +170,15 @@ function ProfileTableItem(props) {
|
|||||||
Explore ->
|
Explore ->
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {store} from '../store/store';
|
import {store} from '../store/store';
|
||||||
|
import {jsonReplacer} from '../utils/Utils';
|
||||||
|
|
||||||
function prepareUrl(url) {
|
function prepareUrl(url) {
|
||||||
if (url.startsWith('http')) return url;
|
if (url.startsWith('http')) return url;
|
||||||
@@ -8,13 +9,22 @@ function prepareUrl(url) {
|
|||||||
function handleRequest(method, url, headers, attempts, token, body) {
|
function handleRequest(method, url, headers, attempts, token, body) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
(function internalRequest() {
|
(function internalRequest() {
|
||||||
|
if(store)
|
||||||
|
store.loading = true;
|
||||||
return request(method, url, headers, token, body)
|
return request(method, url, headers, token, body)
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
.catch(err => --attempts > 0 ? internalRequest() : reject(err))
|
.catch(err => --attempts > 0 ? internalRequest() : reject(err))
|
||||||
})()
|
})()
|
||||||
})
|
})
|
||||||
.then((res) => res.json())
|
.then((res) => {
|
||||||
.catch(() => [])
|
store.loading = false;
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
store.loading = false;
|
||||||
|
console.log(err)
|
||||||
|
return {}
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,14 +57,14 @@ function request(method, url, headers = {}, token, body) {
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
...headers
|
...headers
|
||||||
},
|
},
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body, jsonReplacer),
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (!token) {
|
if (!token) {
|
||||||
requestOptions.headers.Authorization = null;
|
requestOptions.headers.Authorization = null;
|
||||||
}
|
}
|
||||||
setTimeout(() => controller.abort(), 3000);
|
setTimeout(() => controller.abort(), 15000);
|
||||||
return fetch(prepareUrl(url), requestOptions);
|
return fetch(prepareUrl(url), requestOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
7
src/shared/statusMap.js
Normal file
7
src/shared/statusMap.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export const statusMap={
|
||||||
|
completed:'Completed',
|
||||||
|
incorrect:'Incorrect',
|
||||||
|
stored: 'Stored',
|
||||||
|
blockchained: 'Blockchained',
|
||||||
|
processed: 'Processed'
|
||||||
|
}
|
||||||
@@ -1,131 +1,202 @@
|
|||||||
import {reaction, makeAutoObservable, onBecomeObserved, onBecomeUnobserved} from "mobx";
|
import { reaction, makeAutoObservable, onBecomeObserved, onBecomeUnobserved } from 'mobx';
|
||||||
import {cryptography} from "@liskhq/lisk-client";
|
import { cryptography } from '@liskhq/lisk-client';
|
||||||
import { passphrase } from "@liskhq/lisk-client";
|
import { passphrase } from '@liskhq/lisk-client';
|
||||||
import {getNodeInfo} from '../api/node';
|
import { getNodeInfo } from '../api/node';
|
||||||
import {fetchWrapper} from '../shared/fetchWrapper';
|
import { fetchWrapper } from '../shared/fetchWrapper';
|
||||||
import {labelMap} from "../shared/labelMap";
|
import { labelMap } from '../shared/labelMap';
|
||||||
import {generateSvgAvatar} from "../images/GenerateOnboardingSvg/GenerateSvg";
|
import { generateSvgAvatar } from '../images/GenerateOnboardingSvg/GenerateSvg';
|
||||||
|
import {decryptedData} from "../utils/decryptedData";
|
||||||
|
import { encryptAccountData, generateTransaction, hashAccountData } from '../utils/Utils';
|
||||||
|
|
||||||
class Store {
|
class Store {
|
||||||
_accountData = []
|
_accountData = [];
|
||||||
|
|
||||||
_passPhrase = ''
|
_passPhrase = '';
|
||||||
|
|
||||||
_nodeInfo = {}
|
_nodeInfo = {};
|
||||||
|
|
||||||
_keysArray = []
|
_keysArray = [];
|
||||||
|
|
||||||
_sharedData = []
|
_sharedData = [];
|
||||||
|
|
||||||
_transactionsInfo = []
|
_transactionsInfo = [];
|
||||||
|
|
||||||
|
_accountInfo = {};
|
||||||
|
|
||||||
|
_loading = false;
|
||||||
|
|
||||||
|
_tempTransactions = [];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this, {});
|
makeAutoObservable(this, {});
|
||||||
|
|
||||||
this.fetchNodeInfo()
|
reaction(
|
||||||
|
() => this.keysArray,
|
||||||
|
() => this.fetchSharedData()
|
||||||
|
);
|
||||||
|
reaction(
|
||||||
|
() => this.address,
|
||||||
|
() => this.fetchAccountInfo()
|
||||||
|
);
|
||||||
|
onBecomeObserved(this, 'decryptedAccountData', () => this.fetchNewAccountData());
|
||||||
|
onBecomeObserved(this, 'sharedData', () => this.fetchKeysArray());
|
||||||
|
onBecomeUnobserved(this, 'sharedData', () => this.unobservedSharedData());
|
||||||
|
onBecomeObserved(this, 'transactionsInfo', () => this.fetchTransactionsInfo());
|
||||||
|
onBecomeUnobserved(this, 'transactionsInfo', () => this.unobservedTransactionsInfo());
|
||||||
|
|
||||||
reaction(() => this.keysArray, () => this.fetchSharedData())
|
this.fetchNodeInfo();
|
||||||
onBecomeObserved(this, "decryptedAccountData", () => this.fetchNewAccountData())
|
}
|
||||||
onBecomeObserved(this, "sharedData", () => this.fetchKeysArray())
|
|
||||||
onBecomeUnobserved(this, "sharedData", () => this.unobservedSharedData())
|
|
||||||
onBecomeObserved(this, "transactionsInfo", () => this.fetchTransactionsInfo())
|
|
||||||
onBecomeUnobserved(this, "transactionsInfo", () => this.unobservedTransactionsInfo())
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchNewAccountData() {
|
fetchNewAccountData() {
|
||||||
getNodeInfo()
|
getNodeInfo()
|
||||||
.then((info)=>{
|
.then((info) => {
|
||||||
this.fetchNodeInfoSuccess(info)
|
this.fetchNodeInfoSuccess(info);
|
||||||
fetchWrapper.getAuth('data/private', {
|
fetchWrapper
|
||||||
networkIdentifier: this.nodeInfo.networkIdentifier,
|
.getAuth('data/private', {
|
||||||
lastBlockID: this.nodeInfo.lastBlockID
|
networkIdentifier: this.nodeInfo.networkIdentifier,
|
||||||
}).then((res) => this.accountDataFetchChange(res))
|
lastBlockID: this.nodeInfo.lastBlockID,
|
||||||
})
|
})
|
||||||
.catch((err) => this.fetchNodeInfoFailed(err))
|
.then((res) => this.accountDataFetchChange(res))
|
||||||
|
.catch((err) => this.fetchError(err));
|
||||||
|
})
|
||||||
|
.catch((err) => this.fetchError(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
pushAccountData(data = this.accountData) {
|
fetchAccountInfo() {
|
||||||
fetchWrapper.postAuth('data/private', {
|
fetchWrapper
|
||||||
networkIdentifier: this.nodeInfo.networkIdentifier,
|
.get(`accounts/${this.address}`)
|
||||||
lastBlockID: this.nodeInfo.lastBlockID
|
.then((res) => this.fetchAccountInfoSuccess(res))
|
||||||
}, [...this.encryptAccountData(data)])
|
.catch((err) => this.fetchError(err));
|
||||||
.then(() => this.fetchNewAccountData())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchKeysArray() {
|
fetchKeysArray() {
|
||||||
getNodeInfo()
|
getNodeInfo()
|
||||||
.then((info)=>{
|
.then((info) => {
|
||||||
this.fetchNodeInfoSuccess(info)
|
this.fetchNodeInfoSuccess(info);
|
||||||
fetchWrapper.getAuth('data/shared/', {
|
fetchWrapper
|
||||||
networkIdentifier: this.nodeInfo.networkIdentifier,
|
.getAuth('data/shared/', {
|
||||||
lastBlockID: this.nodeInfo.lastBlockID
|
networkIdentifier: this.nodeInfo.networkIdentifier,
|
||||||
}).then((res) => this.keysArrayFetchChange(res))
|
lastBlockID: this.nodeInfo.lastBlockID,
|
||||||
})
|
})
|
||||||
.catch((err) => this.fetchNodeInfoFailed(err))
|
.then((res) => this.keysArrayFetchChange(res));
|
||||||
|
})
|
||||||
|
.catch((err) => this.fetchError(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchTransactionsInfo() {
|
fetchTransactionsInfo() {
|
||||||
fetchWrapper.get(`account/transactions/${this.address}`, {
|
fetchWrapper
|
||||||
|
.get(`account/transactions/${this.address}`, {
|
||||||
networkIdentifier: this.nodeInfo.networkIdentifier,
|
networkIdentifier: this.nodeInfo.networkIdentifier,
|
||||||
lastBlockID: this.nodeInfo.lastBlockID
|
lastBlockID: this.nodeInfo.lastBlockID,
|
||||||
}).then((res) => this.saveInfoTransactions(res))
|
})
|
||||||
};
|
.then((res) => this.saveInfoTransactions(res))
|
||||||
|
.catch((err) => this.fetchError(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchTempTransactions() {
|
||||||
|
fetchWrapper
|
||||||
|
.get('node/transactions')
|
||||||
|
.then((res) => this.fetchTempTransactionsSuccess(res))
|
||||||
|
.catch((err) => this.fetchError(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchPassPhrase() {
|
||||||
|
this._passPhrase = sessionStorage.getItem('passPhrase') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchSharedData() {
|
||||||
|
this._keysArray.forEach((elem) =>
|
||||||
|
fetchWrapper
|
||||||
|
.get(`data/shared/${elem}`)
|
||||||
|
.then((res) => this.changeSharedData(res))
|
||||||
|
.catch((err) => this.fetchError(err))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchNodeInfo() {
|
||||||
|
getNodeInfo()
|
||||||
|
.then((info) => this.fetchNodeInfoSuccess(info))
|
||||||
|
.catch((err) => this.fetchError(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
pushAccountData(data = this.accountData) {
|
||||||
|
fetchWrapper
|
||||||
|
.postAuth(
|
||||||
|
'data/private',
|
||||||
|
{
|
||||||
|
networkIdentifier: this.nodeInfo.networkIdentifier,
|
||||||
|
lastBlockID: this.nodeInfo.lastBlockID,
|
||||||
|
},
|
||||||
|
[...encryptAccountData(data, this.passPhrase, this.pubKey)]
|
||||||
|
)
|
||||||
|
.then(() => this.fetchNewAccountData())
|
||||||
|
.catch((err) => this.fetchError(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
pushAccountDataToBlockchain(data = this.decryptedAccountData) {
|
||||||
|
const [removed, changed] = hashAccountData(data, this.decryptedAccountData, this.accountFeaturesMap);
|
||||||
|
const builder = generateTransaction(
|
||||||
|
BigInt(this.accountInfo?.sequence?.nonce || 0),
|
||||||
|
this.addressAndPubKey.publicKey,
|
||||||
|
this.nodeInfo.networkIdentifier,
|
||||||
|
this.passPhrase
|
||||||
|
);
|
||||||
|
|
||||||
|
let signedTx = null;
|
||||||
|
|
||||||
|
if (removed.length !== 0) signedTx = builder.remove(removed);
|
||||||
|
|
||||||
|
if (changed.length !== 0) signedTx = builder.update(changed);
|
||||||
|
if (signedTx) {
|
||||||
|
fetchWrapper.post('transactions', {}, signedTx)
|
||||||
|
.then(() => this.fetchTempTransactions())
|
||||||
|
.catch((err) => this.fetchError(err));
|
||||||
|
this.accountInfo.sequence.nonce++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
generatePassPhrase() {
|
generatePassPhrase() {
|
||||||
this._passPhrase = passphrase.Mnemonic.generateMnemonic();
|
this._passPhrase = passphrase.Mnemonic.generateMnemonic();
|
||||||
sessionStorage.setItem('passPhrase', this._passPhrase);
|
sessionStorage.setItem('passPhrase', this._passPhrase);
|
||||||
};
|
|
||||||
|
|
||||||
savePastPassPhrase(phrase) {
|
|
||||||
this._passPhrase=phrase
|
|
||||||
sessionStorage.setItem('passPhrase', this._passPhrase);
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchPassPhrase() {
|
|
||||||
this._passPhrase = sessionStorage.getItem('passPhrase') || ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchSharedData() {
|
savePastPassPhrase(phrase) {
|
||||||
this._keysArray.forEach((elem) => fetchWrapper.get(`data/shared/${elem}`).then((res) => this.changeSharedData(res)))
|
this._passPhrase = phrase;
|
||||||
};
|
sessionStorage.setItem('passPhrase', this._passPhrase);
|
||||||
|
}
|
||||||
|
|
||||||
unobservedTransactionsInfo() {
|
unobservedTransactionsInfo() {
|
||||||
this._transactionsInfo = []
|
this._transactionsInfo = [];
|
||||||
};
|
}
|
||||||
|
|
||||||
unobservedSharedData() {
|
unobservedSharedData() {
|
||||||
this._sharedData = []
|
this._sharedData = [];
|
||||||
};
|
}
|
||||||
|
|
||||||
changeSharedData(incomingData) {
|
changeSharedData(incomingData) {
|
||||||
this._sharedData.push({
|
this._sharedData.push({
|
||||||
data: incomingData.data,
|
data: incomingData.data,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
saveDataRegistration(data) {
|
saveDataRegistration(data) {
|
||||||
this._accountData = data;
|
this._accountData = data;
|
||||||
};
|
}
|
||||||
|
|
||||||
clearDataRegistration() {
|
clearDataRegistration() {
|
||||||
this._accountData = [];
|
this._accountData = [];
|
||||||
};
|
|
||||||
|
|
||||||
fetchNodeInfo() {
|
|
||||||
getNodeInfo()
|
|
||||||
.then((info)=>this.fetchNodeInfoSuccess(info))
|
|
||||||
.catch((err) => this.fetchNodeInfoFailed(err))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
saveInfoTransactions(transaction) {
|
saveInfoTransactions(transaction) {
|
||||||
this._transactionsInfo = transaction.data
|
this._transactionsInfo = transaction.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
accountDataFetchChange(res) {
|
accountDataFetchChange(res) {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
this._accountData = res.data;
|
this._accountData = res.data;
|
||||||
}
|
}
|
||||||
};
|
this.fetchTempTransactions();
|
||||||
|
}
|
||||||
|
|
||||||
keysArrayFetchChange(res) {
|
keysArrayFetchChange(res) {
|
||||||
this._keysArray = res.data;
|
this._keysArray = res.data;
|
||||||
@@ -133,70 +204,67 @@ class Store {
|
|||||||
|
|
||||||
fetchNodeInfoSuccess(info) {
|
fetchNodeInfoSuccess(info) {
|
||||||
this._nodeInfo = info.data;
|
this._nodeInfo = info.data;
|
||||||
|
this.fetchPassPhrase();
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchNodeInfoFailed(err) {
|
fetchAccountInfoSuccess(res) {
|
||||||
|
this._accountInfo = res.data;
|
||||||
|
if (this.accountInfo?.sequence?.nonce)
|
||||||
|
this.accountInfo.sequence.nonce = parseInt(this.accountInfo.sequence.nonce) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchTempTransactionsSuccess(res) {
|
||||||
|
this._tempTransactions = res.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchError(err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
get sharedData() {
|
get sharedData() {
|
||||||
return this._sharedData.map(elem => ({
|
return this._sharedData.map((elem) => ({
|
||||||
data: elem.data.map(item => ({
|
data: elem.data.map((item) => ({
|
||||||
label: labelMap[item.label],
|
label: labelMap[item.label],
|
||||||
value: item.value,
|
value: item.value,
|
||||||
}))
|
})),
|
||||||
}));
|
}));
|
||||||
};
|
}
|
||||||
|
|
||||||
get transactionsInfo() {
|
get transactionsInfo() {
|
||||||
return this._transactionsInfo.map(item => {
|
return this._transactionsInfo.map((item) => {
|
||||||
return {
|
return {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
sender_avatar: item.asset.recipientAddress && generateSvgAvatar(item.senderPublicKey),
|
sender_avatar: item.asset.recipientAddress && generateSvgAvatar(item.senderPublicKey),
|
||||||
avatar_size: 24,
|
avatar_size: 24,
|
||||||
transaction: item.asset.features.map(asset => {
|
transaction: item.asset.features.map((asset) => {
|
||||||
return {
|
return {
|
||||||
transaction_id: item.id,
|
transaction_id: item.id,
|
||||||
address: item.asset.recipientAddress && cryptography.bufferToHex(cryptography.getAddressFromPublicKey(cryptography.hexToBuffer(item.senderPublicKey))),
|
address:
|
||||||
|
item.asset.recipientAddress &&
|
||||||
|
cryptography.bufferToHex(
|
||||||
|
cryptography.getAddressFromPublicKey(cryptography.hexToBuffer(item.senderPublicKey))
|
||||||
|
),
|
||||||
value: asset.value,
|
value: asset.value,
|
||||||
label: labelMap[asset.label] || asset.label
|
label: labelMap[asset.label] || asset.label,
|
||||||
}
|
};
|
||||||
})
|
}),
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get decryptedAccountData() {
|
get decryptedAccountData() {
|
||||||
return this._accountData.map((elem) => ({
|
return decryptedData(this._accountData, this.accountFeatures, this.passPhrase, this.pubKey)
|
||||||
...elem,
|
|
||||||
key: elem.label,
|
|
||||||
label: labelMap[elem.label] || elem.label,
|
|
||||||
value: cryptography.decryptMessageWithPassphrase(elem.value, elem.value_nonce, this.passPhrase, this.pubKey).split(':')[1]
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
encryptAccountData(data) {
|
|
||||||
return data.map((item) => {
|
|
||||||
let value = cryptography.encryptMessageWithPassphrase(cryptography.getRandomBytes(32).toString('hex') + ":" + item.value, this.passPhrase, this.pubKey);
|
|
||||||
return {
|
|
||||||
label: item.key,
|
|
||||||
value: value.encryptedMessage,
|
|
||||||
value_nonce: value.nonce,
|
|
||||||
seed: item.seed,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get firstName() {
|
get firstName() {
|
||||||
return this.decryptedAccountData.find(item => item.key === 'firstname')?.value
|
return this.decryptedAccountData.find((item) => item.key === 'firstname')?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get lastName() {
|
get lastName() {
|
||||||
return this.decryptedAccountData.find(item => item.key === 'secondname')?.value
|
return this.decryptedAccountData.find((item) => item.key === 'secondname')?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get accountName() {
|
get accountName() {
|
||||||
return this.firstName || this.lastName || this.pubKey
|
return this.firstName || this.lastName || this.pubKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
get keysArray() {
|
get keysArray() {
|
||||||
@@ -204,13 +272,16 @@ class Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get passPhrase() {
|
get passPhrase() {
|
||||||
this.fetchPassPhrase()
|
return this._passPhrase;
|
||||||
return this._passPhrase
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get accountData() {
|
get accountData() {
|
||||||
return this._accountData
|
return this._accountData;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
get accountInfo() {
|
||||||
|
return this._accountInfo;
|
||||||
|
}
|
||||||
|
|
||||||
get nodeInfo() {
|
get nodeInfo() {
|
||||||
return this._nodeInfo;
|
return this._nodeInfo;
|
||||||
@@ -225,15 +296,56 @@ class Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get address() {
|
get address() {
|
||||||
return this.addressAndPubKey.address.toString('hex')
|
return this.addressAndPubKey.address.toString('hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
get tokenKey() {
|
get tokenKey() {
|
||||||
const stringToSign = this.nodeInfo.networkIdentifier + this.nodeInfo.lastBlockID;
|
const stringToSign = this.nodeInfo.networkIdentifier + this.nodeInfo.lastBlockID;
|
||||||
if(!stringToSign)
|
if (!stringToSign) return '';
|
||||||
return '';
|
const sign = cryptography.signDataWithPassphrase(Buffer.from(stringToSign, 'hex'), this.passPhrase).toString('hex');
|
||||||
const sign = cryptography.signDataWithPassphrase(Buffer.from(stringToSign, 'hex'), this.passPhrase).toString('hex')
|
return this.pubKey + ':' + sign;
|
||||||
return this.pubKey + ':' +sign
|
}
|
||||||
|
|
||||||
|
get accountIdentity() {
|
||||||
|
return this.accountInfo?.identity || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
get accountFeatures() {
|
||||||
|
return this.accountIdentity?.features || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
get accountFeaturesMap() {
|
||||||
|
return this.accountFeatures.reduce(
|
||||||
|
(acc, item) => ({
|
||||||
|
...acc,
|
||||||
|
[item.label]: item.value,
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get loading() {
|
||||||
|
return this._loading;
|
||||||
|
}
|
||||||
|
|
||||||
|
set loading(value) {
|
||||||
|
this._loading = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get tempTransactions() {
|
||||||
|
return this._tempTransactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
get processedFeatures() {
|
||||||
|
return this.tempTransactions
|
||||||
|
.filter(item => item.senderPublicKey === this.pubKey)
|
||||||
|
.reduce((acc, item) => {
|
||||||
|
const { features } = item.asset;
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
...features.reduce((obj, feature) => ({...obj, [feature.label]: true}), {})
|
||||||
|
}
|
||||||
|
}, {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
127
src/utils/Schemas.js
Normal file
127
src/utils/Schemas.js
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
export const IdentityModuleSchema = {
|
||||||
|
$id: 'idntty/identity/module',
|
||||||
|
title: 'Identity module account schema',
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
features: {
|
||||||
|
fieldNumber: 1,
|
||||||
|
type: 'array',
|
||||||
|
maxItems: 256,
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['label', 'value'],
|
||||||
|
properties: {
|
||||||
|
label: { fieldNumber: 1, dataType: 'string'},
|
||||||
|
value: { fieldNumber: 2, dataType: 'bytes'},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
verifications: {
|
||||||
|
fieldNumber: 2,
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['label', 'account', 'tx'],
|
||||||
|
properties: {
|
||||||
|
label: { fieldNumber: 1, dataType: 'string'},
|
||||||
|
account: { fieldNumber: 2, dataType: 'bytes'},
|
||||||
|
tx: { fieldNumber: 3, dataType: 'bytes'},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: {features: [], verifications: []}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const setFeatureAssetSchema = {
|
||||||
|
$id: 'idntty/identity/setfeature',
|
||||||
|
title: 'Asset schema to set or update account features for identity module',
|
||||||
|
type: 'object',
|
||||||
|
required: ['features'],
|
||||||
|
properties: {
|
||||||
|
features: {
|
||||||
|
fieldNumber: 1,
|
||||||
|
type: 'array',
|
||||||
|
minItems: 1,
|
||||||
|
maxItems: 16,
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['label','value'],
|
||||||
|
properties: {
|
||||||
|
label: { fieldNumber: 1, dataType: 'string', maxLength: 16},
|
||||||
|
value: { fieldNumber: 2, dataType: 'bytes', maxLength: 32},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const removeFeatureAssetSchema = {
|
||||||
|
$id: 'idntty/identity/removefeature',
|
||||||
|
title: 'Asset schema to remove account features for identity module',
|
||||||
|
type: 'object',
|
||||||
|
required: ['features'],
|
||||||
|
properties: {
|
||||||
|
features: {
|
||||||
|
fieldNumber: 1,
|
||||||
|
type: 'array',
|
||||||
|
minItems: 1,
|
||||||
|
maxItems: 16,
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['label'],
|
||||||
|
properties: {
|
||||||
|
label: { fieldNumber: 1, dataType: 'string', maxLength: 16},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const validateFeatureAssetSchema = {
|
||||||
|
$id: 'idntty/identity/validatefeature',
|
||||||
|
title: 'Asset schema to validate account features for identity module',
|
||||||
|
type: 'object',
|
||||||
|
required: ['recipientAddress','features'],
|
||||||
|
properties: {
|
||||||
|
recipientAddress: {fieldNumber: 1, dataType: 'bytes', minLength: 20, maxLength: 20},
|
||||||
|
features: {
|
||||||
|
fieldNumber: 2,
|
||||||
|
type: 'array',
|
||||||
|
minItems: 1,
|
||||||
|
maxItems: 16,
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['label', 'value'],
|
||||||
|
properties: {
|
||||||
|
label: { fieldNumber: 1, dataType: 'string', maxLength: 16},
|
||||||
|
value: { fieldNumber: 2, dataType: 'bytes', maxLength: 32},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const invalidateFeatureAssetSchema = {
|
||||||
|
$id: 'idntty/identity/invalidatefeature',
|
||||||
|
title: 'Asset schema to invalidate account features for identity module',
|
||||||
|
type: 'object',
|
||||||
|
required: ['recipientAddress','features'],
|
||||||
|
properties: {
|
||||||
|
recipientAddress: {fieldNumber: 1, dataType: 'bytes', minLength: 20, maxLength: 20},
|
||||||
|
features: {
|
||||||
|
fieldNumber: 2,
|
||||||
|
type: 'array',
|
||||||
|
minItems: 1,
|
||||||
|
maxItems: 16,
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['label'],
|
||||||
|
properties: {
|
||||||
|
label: { fieldNumber: 1, dataType: 'string', maxLength: 16},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
import resolveConfig from 'tailwindcss/resolveConfig';
|
import resolveConfig from 'tailwindcss/resolveConfig';
|
||||||
|
import {cryptography, transactions} from '@liskhq/lisk-client';
|
||||||
|
import {removeFeatureAssetSchema, setFeatureAssetSchema} from './Schemas';
|
||||||
|
import {statusMap} from "../shared/statusMap";
|
||||||
|
import {labelMap} from "../shared/labelMap";
|
||||||
|
|
||||||
export const tailwindConfig = () => {
|
export const tailwindConfig = () => {
|
||||||
// Tailwind config
|
// Tailwind config
|
||||||
@@ -32,3 +36,123 @@ export const formatThousands = (value) => Intl.NumberFormat('en-US', {
|
|||||||
maximumSignificantDigits: 3,
|
maximumSignificantDigits: 3,
|
||||||
notation: 'compact',
|
notation: 'compact',
|
||||||
}).format(value);
|
}).format(value);
|
||||||
|
|
||||||
|
export const encryptAccountData = (data = [], passPhrase = '', pubKey = '') => {
|
||||||
|
return data.filter(item=>item.status!==statusMap.blockchained).map((item) => {
|
||||||
|
let value = cryptography.encryptMessageWithPassphrase(item.seed + ":" + item.value, passPhrase, pubKey);
|
||||||
|
return {
|
||||||
|
label: item.key,
|
||||||
|
value: value.encryptedMessage,
|
||||||
|
value_nonce: value.nonce,
|
||||||
|
seed: item.seed,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hashAccountData = (data = [], oldData = [], hashMap = {}) => {
|
||||||
|
const accountMap = data.reduce((acc, item) => ({
|
||||||
|
...acc,
|
||||||
|
[item.label]: item.value
|
||||||
|
}), {})
|
||||||
|
|
||||||
|
const oldAccountMap = oldData.reduce((acc, item) => ({
|
||||||
|
...acc,
|
||||||
|
[item.label]: item.value
|
||||||
|
}), {})
|
||||||
|
const removed = oldData.reduce((acc, item) => {
|
||||||
|
if(!accountMap[item.label] && !data.find(elem=>elem.label===item.label))
|
||||||
|
return [...acc, {label: item.label}];
|
||||||
|
return acc
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const changed = data.reduce((acc, item) => {
|
||||||
|
if(!oldAccountMap[item.label])
|
||||||
|
return [ ...acc, item ]
|
||||||
|
const oldValue = hashMap[item.key];
|
||||||
|
const newValue = hashValue(item.value, item.seed).toString('hex')
|
||||||
|
if(oldValue !== newValue && item.status==='new')
|
||||||
|
return [ ...acc, item ]
|
||||||
|
return acc;
|
||||||
|
}, [])
|
||||||
|
return [
|
||||||
|
removed,
|
||||||
|
changed.map((item) => {
|
||||||
|
const value = hashValue(item.value, item.seed);
|
||||||
|
return {
|
||||||
|
label: item.key,
|
||||||
|
value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const jsonReplacer = (key, value) => {
|
||||||
|
if (key === 'big') {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hashValue = (value = '', seed = '') => cryptography.hash(Buffer.concat([Buffer.from(seed, 'utf8'), cryptography.hash(value, 'utf8')]));
|
||||||
|
|
||||||
|
export const generateTransaction = (nonce = BigInt(0), senderPublicKey = '', networkIdentifier = '', passPhrase = '', fee = BigInt(500000),) => {
|
||||||
|
return {
|
||||||
|
update: (features) => generateSetTransaction(features, nonce, senderPublicKey, networkIdentifier, passPhrase, fee),
|
||||||
|
remove: (features) => generateRemoveTransaction(features, nonce, senderPublicKey, networkIdentifier, passPhrase, fee),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const generateSetTransaction = (features, nonce = BigInt(0), senderPublicKey = '', networkIdentifier = '', passPhrase = '', fee = BigInt(500000)) => {
|
||||||
|
const tx = {
|
||||||
|
"moduleID": 1001,
|
||||||
|
"assetID": 1,
|
||||||
|
nonce,
|
||||||
|
senderPublicKey,
|
||||||
|
fee,
|
||||||
|
"asset": {
|
||||||
|
features
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if(features.length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const signedTx = transactions.signTransaction(setFeatureAssetSchema,
|
||||||
|
tx, Buffer.from(networkIdentifier, "hex"),
|
||||||
|
passPhrase)
|
||||||
|
|
||||||
|
signedTx.senderPublicKey = signedTx.senderPublicKey.toString("hex");
|
||||||
|
signedTx.signatures[0] = signedTx.signatures[0].toString("hex");
|
||||||
|
signedTx.asset.features = signedTx.asset.features.map(feature => ({
|
||||||
|
...feature,
|
||||||
|
value: feature.value.toString("hex")
|
||||||
|
}))
|
||||||
|
|
||||||
|
delete signedTx.id;
|
||||||
|
|
||||||
|
return signedTx;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const generateRemoveTransaction = (features, nonce = BigInt(0), senderPublicKey = '', networkIdentifier = '', passPhrase = '', fee = BigInt(500000)) => {
|
||||||
|
const tx = {
|
||||||
|
"moduleID": 1001,
|
||||||
|
"assetID": 2,
|
||||||
|
nonce,
|
||||||
|
senderPublicKey,
|
||||||
|
fee,
|
||||||
|
"asset": {
|
||||||
|
features
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const signedTx = transactions.signTransaction(removeFeatureAssetSchema,
|
||||||
|
tx, Buffer.from(networkIdentifier, "hex"),
|
||||||
|
passPhrase)
|
||||||
|
|
||||||
|
signedTx.senderPublicKey = signedTx.senderPublicKey.toString(
|
||||||
|
"hex");
|
||||||
|
signedTx.signatures[0] = signedTx.signatures[0].toString("hex");
|
||||||
|
|
||||||
|
delete signedTx.id;
|
||||||
|
|
||||||
|
return signedTx;
|
||||||
|
}
|
||||||
|
|||||||
48
src/utils/decryptedData.js
Normal file
48
src/utils/decryptedData.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import {labelMap} from "../shared/labelMap";
|
||||||
|
import {statusMap} from "../shared/statusMap";
|
||||||
|
import {cryptography} from "@liskhq/lisk-client";
|
||||||
|
|
||||||
|
export const decryptedData=(serverData, blockchainData, passPhrase, pubKey)=>{
|
||||||
|
const allAccountData=serverData.concat(blockchainData.filter(item=>!serverData.find(elem=>elem.label===item.label)))
|
||||||
|
return allAccountData.map((elem) => {
|
||||||
|
const initialData={
|
||||||
|
...elem,
|
||||||
|
key: elem.label,
|
||||||
|
label: labelMap[elem.label] || elem.label,
|
||||||
|
status: '',
|
||||||
|
value: '',
|
||||||
|
seed: ''
|
||||||
|
}
|
||||||
|
if(!serverData.find(item=>item.label===elem.label)) {
|
||||||
|
return {
|
||||||
|
...initialData,
|
||||||
|
status: statusMap.blockchained,
|
||||||
|
value: elem.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const [seed, value] = cryptography.decryptMessageWithPassphrase(elem.value, elem.value_nonce, passPhrase, pubKey).split(':');
|
||||||
|
const hashValue=cryptography.hash(Buffer.concat([Buffer.from(seed, 'utf8'), cryptography.hash(value, 'utf8')])).toString('hex')
|
||||||
|
if(!blockchainData.find(item=>item.label===elem.label)) {
|
||||||
|
return {
|
||||||
|
...initialData,
|
||||||
|
status: statusMap.stored,
|
||||||
|
value,
|
||||||
|
seed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(blockchainData.find(item=>item.label===elem.label).value!==hashValue) {
|
||||||
|
return {
|
||||||
|
...initialData,
|
||||||
|
status: statusMap.incorrect,
|
||||||
|
value,
|
||||||
|
seed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...initialData,
|
||||||
|
status: statusMap.completed,
|
||||||
|
value,
|
||||||
|
seed
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user