feat: add account tabs (#378)
* feat: add account tabs * chore: bump * refactor: change network tab for old accounting * feat: new fonts and text transformation, chequebook tab * feat: polishing
This commit is contained in:
+11
-46
@@ -1,63 +1,28 @@
|
||||
@font-face {
|
||||
font-family: 'Work Sans';
|
||||
font-family: 'iAWriterQuattroV';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(assets/fonts/WorkSans/WorkSans-Light.ttf) format('truetype');
|
||||
src: url(assets/fonts/iAWriterQuattroV.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Work Sans';
|
||||
font-family: 'iAWriterMonoV';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(assets/fonts/WorkSans/WorkSans-Regular.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(assets/fonts/WorkSans/WorkSans-Medium.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(assets/fonts/WorkSans/WorkSans-SemiBold.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'IBMPlexMono500';
|
||||
src: url(assets/fonts/IBMPlexMono500.ttf) format('truetype');
|
||||
font-weight: 500;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'IBMPlexMono600';
|
||||
src: url(assets/fonts/IBMPlexMono600.ttf) format('truetype');
|
||||
font-weight: 600;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'IBMPlexMonoregular';
|
||||
src: url(assets/fonts/IBMPlexMonoregular.ttf) format('truetype');
|
||||
font-weight: 300;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'WorkSans-Italic-VariableFont_wght';
|
||||
src: url(assets/fonts/WorkSans-Italic-VariableFont_wght.ttf) format('truetype');
|
||||
font-weight: 700;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'WorkSans-VariableFont_wght';
|
||||
src: url(assets/fonts/WorkSans-VariableFont_wght.ttf) format('truetype');
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(assets/fonts/iAWriterMonoV.ttf) format('truetype');
|
||||
}
|
||||
|
||||
.App {
|
||||
font-family: 'Work Sans', 'Helvetica Neue', HelveticaNeue, Helvetica, Arial, sans-serif;
|
||||
font-family: 'iAWriterQuattroV', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
|
||||
'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a,
|
||||
button {
|
||||
font-family: 'IBMPlexMono500' !important;
|
||||
font-family: 'iAWriterMonoV' !important;
|
||||
color: #dd7700;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+25
-32
@@ -1,11 +1,13 @@
|
||||
import { BeeModes } from '@ethersphere/bee-js'
|
||||
import { Divider, Drawer, Grid, Link as MUILink, List } from '@material-ui/core'
|
||||
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
|
||||
import { OpenInNewSharp } from '@material-ui/icons'
|
||||
import type { ReactElement } from 'react'
|
||||
import { Bookmark, BookOpen, Briefcase, DollarSign, FileText, Gift, Home, Layers, Settings } from 'react-feather'
|
||||
import { ReactElement, useContext } from 'react'
|
||||
import { BookOpen, Briefcase, DollarSign, FileText, Home, Settings } from 'react-feather'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Logo from '../assets/logo.svg'
|
||||
import { config } from '../config'
|
||||
import { Context } from '../providers/Bee'
|
||||
import { ROUTES } from '../routes'
|
||||
import SideBarItem from './SideBarItem'
|
||||
import SideBarStatus from './SideBarStatus'
|
||||
@@ -22,35 +24,22 @@ const navBarItems = [
|
||||
icon: FileText,
|
||||
},
|
||||
{
|
||||
label: 'Feeds',
|
||||
path: ROUTES.FEEDS,
|
||||
icon: Bookmark,
|
||||
label: 'Account',
|
||||
path: ROUTES.ACCOUNT_WALLET,
|
||||
icon: Briefcase,
|
||||
pathMatcherSubstring: '/account/',
|
||||
},
|
||||
{
|
||||
label: 'Stamps',
|
||||
path: ROUTES.STAMPS,
|
||||
icon: Layers,
|
||||
},
|
||||
{
|
||||
label: 'Accounting',
|
||||
path: ROUTES.ACCOUNTING,
|
||||
label: 'Top Up',
|
||||
path: ROUTES.WALLET,
|
||||
icon: DollarSign,
|
||||
requiresMode: BeeModes.ULTRA_LIGHT,
|
||||
},
|
||||
{
|
||||
label: 'Settings',
|
||||
path: ROUTES.SETTINGS,
|
||||
icon: Settings,
|
||||
},
|
||||
{
|
||||
label: 'Account',
|
||||
path: ROUTES.WALLET,
|
||||
icon: Briefcase,
|
||||
},
|
||||
{
|
||||
label: 'Gift Wallets',
|
||||
path: ROUTES.GIFT_CODES,
|
||||
icon: Gift,
|
||||
},
|
||||
]
|
||||
|
||||
const drawerWidth = 300
|
||||
@@ -103,6 +92,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
|
||||
export default function SideBar(): ReactElement {
|
||||
const classes = useStyles()
|
||||
const { nodeInfo } = useContext(Context)
|
||||
|
||||
return (
|
||||
<Drawer className={classes.drawer} variant="permanent" anchor="left" classes={{ paper: classes.drawerPaper }}>
|
||||
@@ -114,16 +104,19 @@ export default function SideBar(): ReactElement {
|
||||
</Grid>
|
||||
<Grid>
|
||||
<List>
|
||||
{navBarItems.map(p => (
|
||||
<Link to={p.path} key={p.path} className={classes.link}>
|
||||
<SideBarItem
|
||||
key={p.path}
|
||||
iconStart={<p.icon className={classes.icon} />}
|
||||
path={p.path}
|
||||
label={p.label}
|
||||
/>
|
||||
</Link>
|
||||
))}
|
||||
{navBarItems
|
||||
.filter(p => !p.requiresMode || nodeInfo?.beeMode === p.requiresMode)
|
||||
.map(p => (
|
||||
<Link to={p.path} key={p.path} className={classes.link}>
|
||||
<SideBarItem
|
||||
key={p.path}
|
||||
iconStart={<p.icon className={classes.icon} />}
|
||||
path={p.path}
|
||||
pathMatcherSubstring={p.pathMatcherSubstring}
|
||||
label={p.label}
|
||||
/>
|
||||
</Link>
|
||||
))}
|
||||
</List>
|
||||
<Divider className={classes.divider} />
|
||||
<List>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { ListItem, ListItemIcon, ListItemText } from '@material-ui/core'
|
||||
import { createStyles, makeStyles, Theme, withStyles } from '@material-ui/core/styles'
|
||||
import type { ReactElement, ReactNode } from 'react'
|
||||
import { useLocation, matchPath } from 'react-router-dom'
|
||||
|
||||
import { createStyles, Theme, makeStyles, withStyles } from '@material-ui/core/styles'
|
||||
import { ListItemText, ListItemIcon, ListItem } from '@material-ui/core'
|
||||
import { matchPath, useLocation } from 'react-router-dom'
|
||||
|
||||
const StyledListItem = withStyles((theme: Theme) => ({
|
||||
root: {
|
||||
@@ -45,12 +44,15 @@ interface Props {
|
||||
iconEnd?: ReactNode
|
||||
path?: string
|
||||
label: ReactNode
|
||||
pathMatcherSubstring?: string
|
||||
}
|
||||
|
||||
export default function SideBarItem({ iconStart, iconEnd, path, label }: Props): ReactElement {
|
||||
export default function SideBarItem({ iconStart, iconEnd, path, label, pathMatcherSubstring }: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
const location = useLocation()
|
||||
const isSelected = Boolean(path && matchPath(location.pathname, path))
|
||||
const isSelected = pathMatcherSubstring
|
||||
? location.pathname.startsWith(pathMatcherSubstring)
|
||||
: Boolean(path && matchPath(location.pathname, path))
|
||||
|
||||
return (
|
||||
<StyledListItem button selected={isSelected} disableRipple>
|
||||
|
||||
@@ -16,7 +16,7 @@ interface Props {
|
||||
const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
button: {
|
||||
height: '52px',
|
||||
height: '42px',
|
||||
position: 'relative',
|
||||
whiteSpace: 'nowrap',
|
||||
color: '#242424',
|
||||
|
||||
+3
-5
@@ -2,9 +2,8 @@ body {
|
||||
height: 100vh;
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
font-family: 'Work Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
font-family: 'iAWriterQuattroV', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
|
||||
'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
@@ -16,6 +15,5 @@ body {
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { createStyles, makeStyles, Tab, Tabs, Theme } from '@material-ui/core'
|
||||
import { ReactElement } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { ACCOUNT_TABS } from '../../routes'
|
||||
|
||||
const tabMap = {
|
||||
WALLET: 0,
|
||||
CHEQUEBOOK: 1,
|
||||
STAMPS: 2,
|
||||
FEEDS: 3,
|
||||
}
|
||||
|
||||
interface Props {
|
||||
active: 'WALLET' | 'CHEQUEBOOK' | 'STAMPS' | 'FEEDS'
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
marginBottom: theme.spacing(4),
|
||||
textTransform: 'none',
|
||||
},
|
||||
leftTab: {
|
||||
marginRight: theme.spacing(0.125),
|
||||
},
|
||||
centerTab: {
|
||||
marginLeft: theme.spacing(0.125),
|
||||
marginRight: theme.spacing(0.125),
|
||||
},
|
||||
rightTab: {
|
||||
marginLeft: theme.spacing(0.125),
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
export function AccountNavigation({ active }: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
const navigate = useNavigate()
|
||||
|
||||
function onChange(event: React.ChangeEvent<Record<string, never>>, newValue: number) {
|
||||
navigate(ACCOUNT_TABS[newValue])
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Tabs value={tabMap[active]} onChange={onChange} variant="fullWidth">
|
||||
<Tab className={classes.leftTab} key="WALLET" label="Wallet" />
|
||||
<Tab className={classes.centerTab} key="CHEQUEBOOK" label="Chequebook" />
|
||||
<Tab className={classes.centerTab} key="STAMPS" label="Stamps" />
|
||||
<Tab className={classes.rightTab} key="FEEDS" label="Feeds" />
|
||||
</Tabs>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Box, Typography } from '@material-ui/core'
|
||||
import { ReactElement } from 'react'
|
||||
|
||||
export function Header(): ReactElement {
|
||||
return (
|
||||
<Box mb={4}>
|
||||
<Typography variant="h1">Account</Typography>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { ReactElement, useContext } from 'react'
|
||||
import ExpandableList from '../../../components/ExpandableList'
|
||||
import ExpandableListItem from '../../../components/ExpandableListItem'
|
||||
import ExpandableListItemActions from '../../../components/ExpandableListItemActions'
|
||||
import ExpandableListItemKey from '../../../components/ExpandableListItemKey'
|
||||
import TroubleshootConnectionCard from '../../../components/TroubleshootConnectionCard'
|
||||
import DepositModal from '../../../containers/DepositModal'
|
||||
import WithdrawModal from '../../../containers/WithdrawModal'
|
||||
import { useAccounting } from '../../../hooks/accounting'
|
||||
import { CheckState, Context as BeeContext } from '../../../providers/Bee'
|
||||
import { Context as SettingsContext } from '../../../providers/Settings'
|
||||
import PeerBalances from '../../accounting/PeerBalances'
|
||||
import { AccountNavigation } from '../AccountNavigation'
|
||||
import { Header } from '../Header'
|
||||
|
||||
export function AccountChequebook(): ReactElement {
|
||||
const { status, nodeAddresses, chequebookAddress, chequebookBalance, settlements, peerBalances } =
|
||||
useContext(BeeContext)
|
||||
const { beeDebugApi } = useContext(SettingsContext)
|
||||
|
||||
const { accounting, totalUncashed, isLoadingUncashed } = useAccounting(beeDebugApi, settlements, peerBalances)
|
||||
|
||||
if (status.all === CheckState.ERROR) return <TroubleshootConnectionCard />
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<AccountNavigation active="CHEQUEBOOK" />
|
||||
<div>
|
||||
<ExpandableList label="Chequebook" defaultOpen>
|
||||
<ExpandableListItem label="Total Balance" value={`${chequebookBalance?.totalBalance.toFixedDecimal()} BZZ`} />
|
||||
<ExpandableListItem
|
||||
label="Available Uncommitted Balance"
|
||||
value={`${chequebookBalance?.availableBalance.toFixedDecimal()} BZZ`}
|
||||
/>
|
||||
<ExpandableListItem
|
||||
label="Total Cheques Amount Sent"
|
||||
value={`${settlements?.totalSent.toFixedDecimal()} BZZ`}
|
||||
/>
|
||||
<ExpandableListItem
|
||||
label="Total Cheques Amount Received"
|
||||
value={`${settlements?.totalReceived.toFixedDecimal()} BZZ`}
|
||||
/>
|
||||
<ExpandableListItemActions>
|
||||
<WithdrawModal />
|
||||
<DepositModal />
|
||||
</ExpandableListItemActions>
|
||||
</ExpandableList>
|
||||
<ExpandableList label="Blockchain" defaultOpen>
|
||||
<ExpandableListItemKey label="Ethereum address" value={nodeAddresses?.ethereum || ''} />
|
||||
<ExpandableListItemKey
|
||||
label="Chequebook contract address"
|
||||
value={chequebookAddress?.chequebookAddress || ''}
|
||||
/>
|
||||
</ExpandableList>
|
||||
<PeerBalances accounting={accounting} isLoadingUncashed={isLoadingUncashed} totalUncashed={totalUncashed} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import { Box } from '@material-ui/core'
|
||||
import { ReactElement, useContext, useState } from 'react'
|
||||
import { Download, Info, PlusSquare, Trash } from 'react-feather'
|
||||
import { useNavigate } from 'react-router'
|
||||
import ExpandableList from '../../../components/ExpandableList'
|
||||
import ExpandableListItem from '../../../components/ExpandableListItem'
|
||||
import ExpandableListItemActions from '../../../components/ExpandableListItemActions'
|
||||
import ExpandableListItemKey from '../../../components/ExpandableListItemKey'
|
||||
import { SwarmButton } from '../../../components/SwarmButton'
|
||||
import { Context as IdentityContext, Identity } from '../../../providers/Feeds'
|
||||
import { ROUTES } from '../../../routes'
|
||||
import { formatEnum } from '../../../utils'
|
||||
import { persistIdentitiesWithoutUpdate } from '../../../utils/identity'
|
||||
import { DeleteFeedDialog } from '../../feeds/DeleteFeedDialog'
|
||||
import { ExportFeedDialog } from '../../feeds/ExportFeedDialog'
|
||||
import { ImportFeedDialog } from '../../feeds/ImportFeedDialog'
|
||||
import { AccountNavigation } from '../AccountNavigation'
|
||||
import { Header } from '../Header'
|
||||
|
||||
export function AccountFeeds(): ReactElement {
|
||||
const { identities, setIdentities } = useContext(IdentityContext)
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
const [selectedIdentity, setSelectedIdentity] = useState<Identity | null>(null)
|
||||
const [showImport, setShowImport] = useState(false)
|
||||
const [showExport, setShowExport] = useState(false)
|
||||
const [showDelete, setShowDelete] = useState(false)
|
||||
|
||||
function createNewFeed() {
|
||||
return navigate(ROUTES.ACCOUNT_FEEDS_NEW)
|
||||
}
|
||||
|
||||
function viewFeed(uuid: string) {
|
||||
navigate(ROUTES.ACCOUNT_FEEDS_VIEW.replace(':uuid', uuid))
|
||||
}
|
||||
|
||||
function onDialogClose() {
|
||||
setShowDelete(false)
|
||||
setShowExport(false)
|
||||
setShowImport(false)
|
||||
setSelectedIdentity(null)
|
||||
}
|
||||
|
||||
function onDelete(identity: Identity) {
|
||||
onDialogClose()
|
||||
const updatedFeeds = identities.filter(x => x.uuid !== identity.uuid)
|
||||
setIdentities(updatedFeeds)
|
||||
persistIdentitiesWithoutUpdate(updatedFeeds)
|
||||
}
|
||||
|
||||
function onShowExport(identity: Identity) {
|
||||
setSelectedIdentity(identity)
|
||||
setShowExport(true)
|
||||
}
|
||||
|
||||
function onShowDelete(identity: Identity) {
|
||||
setSelectedIdentity(identity)
|
||||
setShowDelete(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<AccountNavigation active="FEEDS" />
|
||||
{showImport && <ImportFeedDialog onClose={() => setShowImport(false)} />}
|
||||
{showExport && selectedIdentity && <ExportFeedDialog identity={selectedIdentity} onClose={onDialogClose} />}
|
||||
{showDelete && selectedIdentity && (
|
||||
<DeleteFeedDialog
|
||||
identity={selectedIdentity}
|
||||
onClose={onDialogClose}
|
||||
onConfirm={(identity: Identity) => onDelete(identity)}
|
||||
/>
|
||||
)}
|
||||
<Box mb={4}>
|
||||
<ExpandableListItemActions>
|
||||
<SwarmButton iconType={PlusSquare} onClick={createNewFeed}>
|
||||
Create New Feed
|
||||
</SwarmButton>
|
||||
<SwarmButton iconType={PlusSquare} onClick={() => setShowImport(true)}>
|
||||
Import Feed
|
||||
</SwarmButton>
|
||||
</ExpandableListItemActions>
|
||||
</Box>
|
||||
{identities.map((x, i) => (
|
||||
<ExpandableList key={i} label={`${x.name} Website`} defaultOpen>
|
||||
<Box mb={0.5}>
|
||||
<ExpandableList label={x.name} level={1}>
|
||||
<ExpandableListItemKey label="Identity address" value={x.address} />
|
||||
<ExpandableListItem label="Identity type" value={formatEnum(x.type)} />
|
||||
</ExpandableList>
|
||||
</Box>
|
||||
<ExpandableListItemKey label="Topic" value={'00'.repeat(32)} />
|
||||
{x.feedHash && <ExpandableListItemKey label="Feed hash" value={x.feedHash} />}
|
||||
<Box mt={0.75}>
|
||||
<ExpandableListItemActions>
|
||||
<SwarmButton onClick={() => viewFeed(x.uuid)} iconType={Info}>
|
||||
View Feed Page
|
||||
</SwarmButton>
|
||||
<SwarmButton onClick={() => onShowExport(x)} iconType={Download}>
|
||||
Export...
|
||||
</SwarmButton>
|
||||
<SwarmButton onClick={() => onShowDelete(x)} iconType={Trash}>
|
||||
Delete...
|
||||
</SwarmButton>
|
||||
</ExpandableListItemActions>
|
||||
</Box>
|
||||
</ExpandableList>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import { CircularProgress, Container, createStyles, makeStyles } from '@material-ui/core'
|
||||
import { ReactElement, useContext, useEffect } from 'react'
|
||||
import { PlusSquare } from 'react-feather'
|
||||
import { useNavigate } from 'react-router'
|
||||
import { SwarmButton } from '../../../components/SwarmButton'
|
||||
import TroubleshootConnectionCard from '../../../components/TroubleshootConnectionCard'
|
||||
import { CheckState, Context as BeeContext } from '../../../providers/Bee'
|
||||
import { Context as StampsContext } from '../../../providers/Stamps'
|
||||
import { ROUTES } from '../../../routes'
|
||||
import StampsTable from '../../stamps/StampsTable'
|
||||
import { AccountNavigation } from '../AccountNavigation'
|
||||
import { Header } from '../Header'
|
||||
|
||||
const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
root: {
|
||||
width: '100%',
|
||||
display: 'grid',
|
||||
},
|
||||
actions: {
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
flex: '0 1 auto',
|
||||
flexWrap: 'wrap',
|
||||
alignItems: 'center',
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
export function AccountStamps(): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
const { stamps, isLoading, error, start, stop } = useContext(StampsContext)
|
||||
const { status } = useContext(BeeContext)
|
||||
|
||||
useEffect(() => {
|
||||
if (!status.all) return
|
||||
start()
|
||||
|
||||
return () => stop()
|
||||
}, [status]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
if (status.all === CheckState.ERROR) return <TroubleshootConnectionCard />
|
||||
|
||||
function navigateToNewStamp() {
|
||||
navigate(ROUTES.ACCOUNT_STAMPS_NEW)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<AccountNavigation active="STAMPS" />
|
||||
<div className={classes.root}>
|
||||
{error && (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
Error loading postage stamps details: {error.message}
|
||||
</Container>
|
||||
)}
|
||||
{!error && (
|
||||
<>
|
||||
<div className={classes.actions}>
|
||||
<SwarmButton onClick={navigateToNewStamp} iconType={PlusSquare}>
|
||||
Buy New Postage Stamp
|
||||
</SwarmButton>
|
||||
<div style={{ height: '5px' }}>{isLoading && <CircularProgress />}</div>
|
||||
</div>
|
||||
<StampsTable postageStamps={stamps} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Box, Grid, Typography } from '@material-ui/core'
|
||||
import { ReactElement, useContext } from 'react'
|
||||
import { Download, Gift, Link } from 'react-feather'
|
||||
import { useNavigate } from 'react-router'
|
||||
import ExpandableListItem from '../../../components/ExpandableListItem'
|
||||
import ExpandableListItemActions from '../../../components/ExpandableListItemActions'
|
||||
import ExpandableListItemKey from '../../../components/ExpandableListItemKey'
|
||||
import { Loading } from '../../../components/Loading'
|
||||
import { SwarmButton } from '../../../components/SwarmButton'
|
||||
import { Context } from '../../../providers/Bee'
|
||||
import { ROUTES } from '../../../routes'
|
||||
import { AccountNavigation } from '../AccountNavigation'
|
||||
import { Header } from '../Header'
|
||||
|
||||
export function AccountWallet(): ReactElement {
|
||||
const { balance } = useContext(Context)
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
if (!balance) {
|
||||
return <Loading />
|
||||
}
|
||||
|
||||
function onCheckTransactions() {
|
||||
window.open(`https://blockscout.com/xdai/mainnet/address/${balance?.address}/transactions`, '_blank')
|
||||
}
|
||||
|
||||
function onInvite() {
|
||||
navigate(ROUTES.ACCOUNT_INVITATIONS)
|
||||
}
|
||||
|
||||
function onDeposit() {
|
||||
navigate(ROUTES.WALLET)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<AccountNavigation active="WALLET" />
|
||||
<Box mb={4}>
|
||||
<Grid container direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Typography variant="h2">Wallet balance</Typography>
|
||||
<SwarmButton onClick={onDeposit} iconType={Download}>
|
||||
Deposit
|
||||
</SwarmButton>
|
||||
</Grid>
|
||||
</Box>
|
||||
<Box mb={0.25}>
|
||||
<ExpandableListItemKey label="Node wallet address" value={balance.address} expanded />
|
||||
</Box>
|
||||
<Box mb={0.25}>
|
||||
<ExpandableListItem label="XDAI balance" value={`${balance.dai.toSignificantDigits(4)} XDAI`} />
|
||||
</Box>
|
||||
<Box mb={2}>
|
||||
<ExpandableListItem label="BZZ balance" value={`${balance.bzz.toSignificantDigits(4)} BZZ`} />
|
||||
</Box>
|
||||
<ExpandableListItemActions>
|
||||
<SwarmButton onClick={onCheckTransactions} iconType={Link}>
|
||||
Check transactions on Blockscout
|
||||
</SwarmButton>
|
||||
<SwarmButton onClick={onInvite} iconType={Gift}>
|
||||
Invite to Swarm...
|
||||
</SwarmButton>
|
||||
</ExpandableListItemActions>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import { ReactElement, useContext } from 'react'
|
||||
|
||||
import PeerBalances from './PeerBalances'
|
||||
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard'
|
||||
import { CheckState, Context as BeeContext } from '../../providers/Bee'
|
||||
import { Context as SettingsContext } from '../../providers/Settings'
|
||||
import { useAccounting } from '../../hooks/accounting'
|
||||
import ExpandableList from '../../components/ExpandableList'
|
||||
import ExpandableListItem from '../../components/ExpandableListItem'
|
||||
import ExpandableListItemActions from '../../components/ExpandableListItemActions'
|
||||
import ExpandableListItemKey from '../../components/ExpandableListItemKey'
|
||||
import WithdrawModal from '../../containers/WithdrawModal'
|
||||
import DepositModal from '../../containers/DepositModal'
|
||||
|
||||
export default function Accounting(): ReactElement {
|
||||
const { status, nodeAddresses, chequebookAddress, chequebookBalance, settlements, peerBalances } =
|
||||
useContext(BeeContext)
|
||||
const { beeDebugApi } = useContext(SettingsContext)
|
||||
|
||||
const { accounting, totalUncashed, isLoadingUncashed } = useAccounting(beeDebugApi, settlements, peerBalances)
|
||||
|
||||
if (status.all === CheckState.ERROR) return <TroubleshootConnectionCard />
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ExpandableList label="Chequebook" defaultOpen>
|
||||
<ExpandableListItem label="Total Balance" value={`${chequebookBalance?.totalBalance.toFixedDecimal()} BZZ`} />
|
||||
<ExpandableListItem
|
||||
label="Available Uncommitted Balance"
|
||||
value={`${chequebookBalance?.availableBalance.toFixedDecimal()} BZZ`}
|
||||
/>
|
||||
<ExpandableListItem
|
||||
label="Total Cheques Amount Sent"
|
||||
value={`${settlements?.totalSent.toFixedDecimal()} BZZ`}
|
||||
/>
|
||||
<ExpandableListItem
|
||||
label="Total Cheques Amount Received"
|
||||
value={`${settlements?.totalReceived.toFixedDecimal()} BZZ`}
|
||||
/>
|
||||
<ExpandableListItemActions>
|
||||
<WithdrawModal />
|
||||
<DepositModal />
|
||||
</ExpandableListItemActions>
|
||||
</ExpandableList>
|
||||
<ExpandableList label="Blockchain" defaultOpen>
|
||||
<ExpandableListItemKey label="Ethereum address" value={nodeAddresses?.ethereum || ''} />
|
||||
<ExpandableListItemKey label="Chequebook contract address" value={chequebookAddress?.chequebookAddress || ''} />
|
||||
</ExpandableList>
|
||||
<PeerBalances accounting={accounting} isLoadingUncashed={isLoadingUncashed} totalUncashed={totalUncashed} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -65,7 +65,7 @@ export default function CreateNewFeed(): ReactElement {
|
||||
const identity = await convertWalletToIdentity(wallet, values.type, values.identityName, values.password)
|
||||
persistIdentity(identities, identity)
|
||||
setIdentities(identities)
|
||||
navigate(ROUTES.FEEDS)
|
||||
navigate(ROUTES.ACCOUNT_FEEDS)
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as swarmCid from '@ethersphere/swarm-cid'
|
||||
import { Box } from '@material-ui/core'
|
||||
import { ReactElement, useContext, useEffect, useState } from 'react'
|
||||
import { X } from 'react-feather'
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { DocumentationText } from '../../components/DocumentationText'
|
||||
import ExpandableListItemActions from '../../components/ExpandableListItemActions'
|
||||
import ExpandableListItemKey from '../../components/ExpandableListItemKey'
|
||||
@@ -40,13 +40,13 @@ export function FeedSubpage(): ReactElement {
|
||||
}, [beeApi, uuid, identity])
|
||||
|
||||
if (!identity || !status.all) {
|
||||
navigate(ROUTES.FEEDS, { replace: true })
|
||||
navigate(ROUTES.ACCOUNT_FEEDS, { replace: true })
|
||||
|
||||
return <></>
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
navigate(ROUTES.FEEDS)
|
||||
navigate(ROUTES.ACCOUNT_FEEDS)
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Box, Grid, Typography } from '@material-ui/core'
|
||||
import { useSnackbar } from 'notistack'
|
||||
import { ReactElement, useContext, useEffect, useState } from 'react'
|
||||
import { Bookmark, X } from 'react-feather'
|
||||
import { useParams, useNavigate } from 'react-router'
|
||||
import { useNavigate, useParams } from 'react-router'
|
||||
import ExpandableListItemActions from '../../components/ExpandableListItemActions'
|
||||
import { HistoryHeader } from '../../components/HistoryHeader'
|
||||
import { SwarmButton } from '../../components/SwarmButton'
|
||||
@@ -73,10 +73,10 @@ export default function UpdateFeed(): ReactElement {
|
||||
}
|
||||
|
||||
try {
|
||||
await updateFeed(beeApi, identity, hash!, selectedStamp, password as string) // eslint-disable-line
|
||||
await updateFeed(beeApi, beeDebugApi, identity, hash!, selectedStamp, password as string) // eslint-disable-line
|
||||
persistIdentity(identities, identity)
|
||||
setIdentities([...identities])
|
||||
navigate(ROUTES.FEEDS_PAGE.replace(':uuid', identity.uuid))
|
||||
navigate(ROUTES.ACCOUNT_FEEDS_VIEW.replace(':uuid', identity.uuid))
|
||||
} catch (error: unknown) {
|
||||
setLoading(false)
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ export default function Feeds(): ReactElement {
|
||||
const [showDelete, setShowDelete] = useState(false)
|
||||
|
||||
function createNewFeed() {
|
||||
return navigate(ROUTES.FEEDS_NEW)
|
||||
return navigate(ROUTES.ACCOUNT_FEEDS_NEW)
|
||||
}
|
||||
|
||||
function viewFeed(uuid: string) {
|
||||
navigate(ROUTES.FEEDS_PAGE.replace(':uuid', uuid))
|
||||
navigate(ROUTES.ACCOUNT_FEEDS_VIEW.replace(':uuid', uuid))
|
||||
}
|
||||
|
||||
function onDialogClose() {
|
||||
|
||||
@@ -99,7 +99,7 @@ export function Share(): ReactElement {
|
||||
}
|
||||
|
||||
function onUpdateFeed() {
|
||||
navigate(ROUTES.FEEDS_UPDATE.replace(':hash', reference))
|
||||
navigate(ROUTES.ACCOUNT_FEEDS_UPDATE.replace(':hash', reference))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { Context as FileContext } from '../../providers/File'
|
||||
import { Context as SettingsContext } from '../../providers/Settings'
|
||||
import { Context as StampsContext, EnrichedPostageBatch } from '../../providers/Stamps'
|
||||
import { ROUTES } from '../../routes'
|
||||
import { waitUntilStampUsable } from '../../utils'
|
||||
import { detectIndexHtml, getAssetNameFromFiles, packageFile } from '../../utils/file'
|
||||
import { persistIdentity, updateFeed } from '../../utils/identity'
|
||||
import { HISTORY_KEYS, putHistory } from '../../utils/local-storage'
|
||||
@@ -31,7 +32,7 @@ export function Upload(): ReactElement {
|
||||
const [showPasswordPrompt, setShowPasswordPrompt] = useState(false)
|
||||
|
||||
const { refresh } = useContext(StampsContext)
|
||||
const { beeApi } = useContext(SettingsContext)
|
||||
const { beeApi, beeDebugApi } = useContext(SettingsContext)
|
||||
const { files, setFiles, uploadOrigin, metadata, previewUri, previewBlob } = useContext(FileContext)
|
||||
const { identities, setIdentities } = useContext(IdentityContext)
|
||||
const { status } = useContext(BeeContext)
|
||||
@@ -66,7 +67,7 @@ export function Upload(): ReactElement {
|
||||
}
|
||||
}
|
||||
|
||||
const uploadFiles = (password?: string) => {
|
||||
const uploadFiles = async (password?: string) => {
|
||||
if (!beeApi || !files.length || !stamp || !metadata) {
|
||||
return
|
||||
}
|
||||
@@ -122,6 +123,10 @@ export function Upload(): ReactElement {
|
||||
|
||||
setUploading(true)
|
||||
|
||||
if (beeDebugApi) {
|
||||
await waitUntilStampUsable(stamp.batchID, beeDebugApi)
|
||||
}
|
||||
|
||||
beeApi
|
||||
.uploadFiles(stamp.batchID, fls, { indexDocument })
|
||||
.then(hash => {
|
||||
@@ -130,11 +135,13 @@ export function Upload(): ReactElement {
|
||||
if (uploadOrigin.origin === 'UPLOAD') {
|
||||
navigate(ROUTES.HASH.replace(':hash', hash.reference), { replace: true })
|
||||
} else {
|
||||
updateFeed(beeApi, identity as Identity, hash.reference, stamp.batchID, password as string).then(() => {
|
||||
persistIdentity(identities, identity as Identity)
|
||||
setIdentities([...identities])
|
||||
navigate(ROUTES.FEEDS_PAGE.replace(':uuid', uploadOrigin.uuid as string), { replace: true })
|
||||
})
|
||||
updateFeed(beeApi, beeDebugApi, identity as Identity, hash.reference, stamp.batchID, password as string).then(
|
||||
() => {
|
||||
persistIdentity(identities, identity as Identity)
|
||||
setIdentities([...identities])
|
||||
navigate(ROUTES.ACCOUNT_FEEDS_VIEW.replace(':uuid', uploadOrigin.uuid as string), { replace: true })
|
||||
},
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
|
||||
@@ -8,7 +8,7 @@ export function CreatePostageStampPage(): ReactElement {
|
||||
const navigate = useNavigate()
|
||||
|
||||
function onFinished() {
|
||||
navigate(ROUTES.STAMPS)
|
||||
navigate(ROUTES.ACCOUNT_STAMPS)
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,13 +9,7 @@ import { SwarmTextInput } from '../../components/SwarmTextInput'
|
||||
import { Context as BeeContext } from '../../providers/Bee'
|
||||
import { Context as SettingsContext } from '../../providers/Settings'
|
||||
import { Context as StampsContext } from '../../providers/Stamps'
|
||||
import {
|
||||
calculateStampPrice,
|
||||
convertAmountToSeconds,
|
||||
convertDepthToBytes,
|
||||
secondsToTimeString,
|
||||
waitUntilStampUsable,
|
||||
} from '../../utils'
|
||||
import { calculateStampPrice, convertAmountToSeconds, convertDepthToBytes, secondsToTimeString } from '../../utils'
|
||||
import { getHumanReadableFileSize } from '../../utils/file'
|
||||
|
||||
interface FormValues {
|
||||
@@ -88,8 +82,7 @@ export function PostageStampCreation({ onFinished }: Props): ReactElement {
|
||||
const amount = BigInt(values.amount)
|
||||
const depth = Number.parseInt(values.depth)
|
||||
const options = values.label ? { label: values.label } : undefined
|
||||
const batch = await beeDebugApi.createPostageBatch(amount.toString(), depth, options)
|
||||
await waitUntilStampUsable(batch, beeDebugApi)
|
||||
await beeDebugApi.createPostageBatch(amount.toString(), depth, options)
|
||||
actions.resetForm()
|
||||
await refresh()
|
||||
onFinished()
|
||||
@@ -107,7 +100,7 @@ export function PostageStampCreation({ onFinished }: Props): ReactElement {
|
||||
const depth = new BigNumber(values.depth)
|
||||
|
||||
if (!depth.isInteger()) errors.depth = 'Depth must be an integer'
|
||||
else if (depth.isLessThan(16)) errors.depth = 'Minimal depth is 16'
|
||||
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'
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export default function Stamp(): ReactElement {
|
||||
if (status.all === CheckState.ERROR) return <TroubleshootConnectionCard />
|
||||
|
||||
function navigateToNewStamp() {
|
||||
navigate(ROUTES.STAMPS_NEW)
|
||||
navigate(ROUTES.ACCOUNT_STAMPS_NEW)
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -34,7 +34,7 @@ interface Props {
|
||||
children: ReactChild
|
||||
}
|
||||
|
||||
function enrichStamp(postageBatch: PostageBatch): EnrichedPostageBatch {
|
||||
export function enrichStamp(postageBatch: PostageBatch): EnrichedPostageBatch {
|
||||
const { depth, bucketDepth, utilization } = postageBatch
|
||||
|
||||
const usage = utilization / Math.pow(2, depth - bucketDepth)
|
||||
|
||||
+29
-19
@@ -1,7 +1,9 @@
|
||||
import type { ReactElement } from 'react'
|
||||
import { Route, Routes } from 'react-router-dom'
|
||||
import Accounting from './pages/accounting'
|
||||
import Feeds from './pages/feeds'
|
||||
import { AccountChequebook } from './pages/account/chequebook/AccountChequebook'
|
||||
import { AccountFeeds } from './pages/account/feeds/AccountFeeds'
|
||||
import { AccountStamps } from './pages/account/stamps/AccountStamps'
|
||||
import { AccountWallet } from './pages/account/wallet/AccountWallet'
|
||||
import CreateNewFeed from './pages/feeds/CreateNewFeed'
|
||||
import { FeedSubpage } from './pages/feeds/FeedSubpage'
|
||||
import UpdateFeed from './pages/feeds/UpdateFeed'
|
||||
@@ -16,7 +18,6 @@ import Restart from './pages/restart/Restart'
|
||||
import Wallet from './pages/rpc'
|
||||
import Confirmation from './pages/rpc/Confirmation'
|
||||
import Settings from './pages/settings'
|
||||
import Stamps from './pages/stamps'
|
||||
import { CreatePostageStampPage } from './pages/stamps/CreatePostageStampPage'
|
||||
import Status from './pages/status'
|
||||
import { BankCardTopUpIndex } from './pages/top-up/BankCardTopUpIndex'
|
||||
@@ -32,15 +33,8 @@ export enum ROUTES {
|
||||
UPLOAD_IN_PROGRESS = '/files/upload/workflow',
|
||||
DOWNLOAD = '/files/download',
|
||||
HASH = '/files/hash/:hash',
|
||||
ACCOUNTING = '/accounting',
|
||||
SETTINGS = '/settings',
|
||||
STAMPS = '/stamps',
|
||||
STAMPS_NEW = '/stamps/new',
|
||||
STATUS = '/status',
|
||||
FEEDS = '/feeds',
|
||||
FEEDS_NEW = '/feeds/new',
|
||||
FEEDS_UPDATE = '/feeds/update/:hash',
|
||||
FEEDS_PAGE = '/feeds/:uuid',
|
||||
WALLET = '/wallet',
|
||||
CONFIRMATION = '/wallet/confirmation',
|
||||
TOP_UP_CRYPTO = '/top-up/crypto',
|
||||
@@ -49,30 +43,37 @@ export enum ROUTES {
|
||||
TOP_UP_BANK_CARD_SWAP = '/top-up/bank-card/swap',
|
||||
TOP_UP_GIFT_CODE = '/top-up/gift-code',
|
||||
TOP_UP_GIFT_CODE_FUND = '/top-up/gift-code/fund/:privateKeyString',
|
||||
GIFT_CODES = '/gift-codes',
|
||||
RESTART = '/restart',
|
||||
RESTART_LIGHT = '/light-mode-restart',
|
||||
ACCOUNT_WALLET = '/account/wallet',
|
||||
ACCOUNT_CHEQUEBOOK = '/account/chequebook',
|
||||
ACCOUNT_STAMPS = '/account/stamps',
|
||||
ACCOUNT_STAMPS_NEW = '/account/stamps/new',
|
||||
ACCOUNT_FEEDS = '/account/feeds',
|
||||
ACCOUNT_FEEDS_NEW = '/account/feeds/new',
|
||||
ACCOUNT_FEEDS_UPDATE = '/account/feeds/update/:hash',
|
||||
ACCOUNT_FEEDS_VIEW = '/account/feeds/:uuid',
|
||||
ACCOUNT_INVITATIONS = '/account/invitations',
|
||||
}
|
||||
|
||||
export const ACCOUNT_TABS = [
|
||||
ROUTES.ACCOUNT_WALLET,
|
||||
ROUTES.ACCOUNT_CHEQUEBOOK,
|
||||
ROUTES.ACCOUNT_STAMPS,
|
||||
ROUTES.ACCOUNT_FEEDS,
|
||||
]
|
||||
|
||||
const BaseRouter = (): ReactElement => (
|
||||
<Routes>
|
||||
<Route path={ROUTES.UPLOAD_IN_PROGRESS} element={<Upload />} />
|
||||
<Route path={ROUTES.UPLOAD} element={<UploadLander />} />
|
||||
<Route path={ROUTES.DOWNLOAD} element={<Download />} />
|
||||
<Route path={ROUTES.HASH} element={<Share />} />
|
||||
<Route path={ROUTES.ACCOUNTING} element={<Accounting />} />
|
||||
<Route path={ROUTES.SETTINGS} element={<Settings />} />
|
||||
<Route path={ROUTES.STAMPS} element={<Stamps />} />
|
||||
<Route path={ROUTES.STAMPS_NEW} element={<CreatePostageStampPage />} />
|
||||
<Route path={ROUTES.STATUS} element={<Status />} />
|
||||
<Route path={ROUTES.FEEDS} element={<Feeds />} />
|
||||
<Route path={ROUTES.FEEDS_NEW} element={<CreateNewFeed />} />
|
||||
<Route path={ROUTES.FEEDS_UPDATE} element={<UpdateFeed />} />
|
||||
<Route path={ROUTES.FEEDS_PAGE} element={<FeedSubpage />} />
|
||||
<Route path={ROUTES.INFO} element={<Info />} />
|
||||
<Route path={ROUTES.WALLET} element={<Wallet />} />
|
||||
<Route path={ROUTES.CONFIRMATION} element={<Confirmation />} />
|
||||
<Route path={ROUTES.GIFT_CODES} element={<GiftCards />} />
|
||||
<Route path={ROUTES.TOP_UP_CRYPTO} element={<CryptoTopUpIndex />} />
|
||||
<Route path={ROUTES.TOP_UP_CRYPTO_SWAP} element={<Swap header="Top-up with cryptocurrencies" />} />
|
||||
<Route path={ROUTES.TOP_UP_BANK_CARD} element={<BankCardTopUpIndex />} />
|
||||
@@ -81,6 +82,15 @@ const BaseRouter = (): ReactElement => (
|
||||
<Route path={ROUTES.TOP_UP_GIFT_CODE_FUND} element={<GiftCardFund />} />
|
||||
<Route path={ROUTES.RESTART} element={<Restart />} />
|
||||
<Route path={ROUTES.RESTART_LIGHT} element={<LightModeRestart />} />
|
||||
<Route path={ROUTES.ACCOUNT_WALLET} element={<AccountWallet />} />
|
||||
<Route path={ROUTES.ACCOUNT_CHEQUEBOOK} element={<AccountChequebook />} />
|
||||
<Route path={ROUTES.ACCOUNT_STAMPS} element={<AccountStamps />} />
|
||||
<Route path={ROUTES.ACCOUNT_STAMPS_NEW} element={<CreatePostageStampPage />} />
|
||||
<Route path={ROUTES.ACCOUNT_FEEDS} element={<AccountFeeds />} />
|
||||
<Route path={ROUTES.ACCOUNT_FEEDS_NEW} element={<CreateNewFeed />} />
|
||||
<Route path={ROUTES.ACCOUNT_FEEDS_UPDATE} element={<UpdateFeed />} />
|
||||
<Route path={ROUTES.ACCOUNT_FEEDS_VIEW} element={<FeedSubpage />} />
|
||||
<Route path={ROUTES.ACCOUNT_INVITATIONS} element={<GiftCards />} />
|
||||
</Routes>
|
||||
)
|
||||
|
||||
|
||||
+14
-8
@@ -1,5 +1,5 @@
|
||||
import { createTheme, Theme } from '@material-ui/core/styles'
|
||||
import { orange } from '@material-ui/core/colors'
|
||||
import { createTheme, Theme } from '@material-ui/core/styles'
|
||||
|
||||
declare module '@material-ui/core/styles/createPalette' {
|
||||
interface TypeBackground {
|
||||
@@ -186,23 +186,29 @@ export const theme = createTheme({
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontFamily: ['Work Sans', 'Montserrat', 'Nunito', 'Roboto', '"Helvetica Neue"', 'Arial', 'sans-serif'].join(','),
|
||||
fontFamily: ['iAWriterQuattroV', 'Roboto', '"Helvetica Neue"', 'Arial', 'sans-serif'].join(','),
|
||||
h1: {
|
||||
fontSize: '1.3rem',
|
||||
fontWeight: 500,
|
||||
fontSize: '1.1rem',
|
||||
fontWeight: 600,
|
||||
},
|
||||
h2: {
|
||||
fontSize: '1rem',
|
||||
fontWeight: 500,
|
||||
fontSize: '0.9rem',
|
||||
fontWeight: 600,
|
||||
},
|
||||
h3: {
|
||||
fontSize: '0.8rem',
|
||||
fontWeight: 500,
|
||||
},
|
||||
body1: {
|
||||
fontSize: '0.85rem',
|
||||
},
|
||||
body2: {
|
||||
fontFamily: '"IBM Plex Mono", monospace',
|
||||
fontFamily: '"iAWriterMonoV", monospace',
|
||||
fontWeight: 500,
|
||||
fontSize: '1rem',
|
||||
fontSize: '0.85rem',
|
||||
},
|
||||
button: {
|
||||
textTransform: 'none',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Bee, Reference } from '@ethersphere/bee-js'
|
||||
import { BatchId, Bee, BeeDebug, Reference } from '@ethersphere/bee-js'
|
||||
import Wallet from 'ethereumjs-wallet'
|
||||
import { uuidV4 } from '.'
|
||||
import { uuidV4, waitUntilStampUsable } from '.'
|
||||
import { Identity, IdentityType } from '../providers/Feeds'
|
||||
|
||||
export function generateWallet(): Wallet {
|
||||
@@ -88,6 +88,7 @@ export function getWalletFromPrivateKeyString(privateKey: string): Wallet {
|
||||
|
||||
export async function updateFeed(
|
||||
beeApi: Bee,
|
||||
beeDebugApi: BeeDebug | null,
|
||||
identity: Identity,
|
||||
hash: string,
|
||||
stamp: string,
|
||||
@@ -100,6 +101,10 @@ export async function updateFeed(
|
||||
}
|
||||
|
||||
const writer = beeApi.makeFeedWriter('sequence', '00'.repeat(32), wallet.getPrivateKeyString())
|
||||
|
||||
if (beeDebugApi) {
|
||||
await waitUntilStampUsable(stamp as BatchId, beeDebugApi)
|
||||
}
|
||||
await writer.upload(stamp, hash as Reference)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user