Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29b138346e | |||
| b5b0d37e94 | |||
| b3137fbef1 | |||
| e6f882d7e1 |
@@ -1,5 +1,23 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.35.1](https://github.com/ethersphere/bee-dashboard/compare/v0.35.0...v0.35.1) (2026-04-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- [`cb6854e`](https://github.com/ethersphere/bee-dashboard/commit/cb6854eb68ffe3064a39a171bc1e23f628ee93bb) fix: swap error caused by invalid id and batchcount
|
||||||
|
- [`bb93d5c`](https://github.com/ethersphere/bee-dashboard/commit/bb93d5c26fa5414c6423b87a3992e0f2e410e515) fix: enhance creation messages for admin drive and user drives [(#238)](https://github.com/ethersphere/bee-dashboard/issues/238)
|
||||||
|
- [`c08bf8a`](https://github.com/ethersphere/bee-dashboard/commit/d65da143d2200db653fe7a80a7891dacf4c2937e) fix: identity and wallet creation [(#240)](https://github.com/ethersphere/bee-dashboard/pull/240)
|
||||||
|
- [`d65da14`](https://github.com/ethersphere/bee-dashboard/commit/d65da143d2200db653fe7a80a7891dacf4c2937e) fix: ui display changes [(#239)](https://github.com/ethersphere/bee-dashboard/issues/239)
|
||||||
|
- [`c890f7c`](https://github.com/ethersphere/bee-dashboard/commit/c890f7c1e8e4d21f8d252b3e1a9c783982459adf) fix: stamp buy and dilute [(#242)](https://github.com/ethersphere/bee-dashboard/issues/242)
|
||||||
|
- [`b33b663`](https://github.com/ethersphere/bee-dashboard/commit/b33b6630c2b5830b0fdbfbcf14cadc3fa1225190) fix: standard mode postage stamp purchase [(#243)](https://github.com/ethersphere/bee-dashboard/issues/243)
|
||||||
|
- [`f943f7a`](https://github.com/ethersphere/bee-dashboard/commit/f943f7ad666de15ef780cb5adf736b533902eef7) fix: add syncing message for bee node and update page state [(#244)](https://github.com/ethersphere/bee-dashboard/pull/244)
|
||||||
|
- [`056188a`](https://github.com/ethersphere/bee-dashboard/commit/056188abedf3a8ac828b8eb10a71a3b823cd5e6e) fix: duplicated ttl (time to live) information [(#245)](https://github.com/ethersphere/bee-dashboard/issues/245)
|
||||||
|
- [`8b36556`](https://github.com/ethersphere/bee-dashboard/commit/8b36556502d316ac5bd7dba49ce34b594857d449) fix: misleading "bee node is syncing" message for ultra-light nodes in file manager [(#246)](https://github.com/ethersphere/bee-dashboard/pull/246)
|
||||||
|
- [`9732170`](https://github.com/ethersphere/bee-dashboard/commit/97321706c33fb02abe7e067e6d865a046051d68b) fix: validate stamp before every upgrade click [(#247)](https://github.com/ethersphere/bee-dashboard/issues/247)
|
||||||
|
- [`f52ed4a`](https://github.com/ethersphere/bee-dashboard/commit/f52ed4abb2bb5274b33430c1e8efadae6b3fa795) fix: use tochecksum() and toplurbigint for ethers v6 compatibility [(#248)](https://github.com/ethersphere/bee-dashboard/pull/248)
|
||||||
|
|
||||||
|
|
||||||
## [0.35.0](https://github.com/ethersphere/bee-dashboard/compare/v0.34.0...v0.35.0) (2026-04-02)
|
## [0.35.0](https://github.com/ethersphere/bee-dashboard/compare/v0.34.0...v0.35.0) (2026-04-02)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ethersphere/bee-dashboard",
|
"name": "@ethersphere/bee-dashboard",
|
||||||
"version": "0.35.0",
|
"version": "0.35.1",
|
||||||
"description": "An app which helps users to setup their Bee node and do actions like cash out cheques",
|
"description": "An app which helps users to setup their Bee node and do actions like cash out cheques",
|
||||||
"homepage": ".",
|
"homepage": ".",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
allowBuilds:
|
||||||
|
'@parcel/watcher': false
|
||||||
|
esbuild: false
|
||||||
|
puppeteer: false
|
||||||
|
unrs-resolver: false
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { BZZ, DAI, RedistributionState } from '@ethersphere/bee-js'
|
||||||
|
import { useContext, useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
import { Context } from '../providers/Settings'
|
||||||
|
|
||||||
|
import ExpandableListItem from './ExpandableListItem'
|
||||||
|
|
||||||
|
export function Redistribution() {
|
||||||
|
const { beeApi } = useContext(Context)
|
||||||
|
const [redistributionState, setRedistributionState] = useState<RedistributionState | null>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
if (!beeApi) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
beeApi.getRedistributionState().then(setRedistributionState).catch(console.error) // eslint-disable-line
|
||||||
|
}, 3_000)
|
||||||
|
|
||||||
|
return () => clearInterval(interval)
|
||||||
|
})
|
||||||
|
|
||||||
|
const formatDurationSeconds = (s?: number) => {
|
||||||
|
if (s === null || s === undefined) {
|
||||||
|
return '-'
|
||||||
|
} else {
|
||||||
|
return `${s} s`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatBzzAmount = (amount?: BZZ) => {
|
||||||
|
if (amount === null || amount === undefined) {
|
||||||
|
return '-'
|
||||||
|
} else {
|
||||||
|
return `${amount.toSignificantDigits(4)} xBZZ`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatDaiAmount = (amount?: DAI) => {
|
||||||
|
if (amount === null || amount === undefined) {
|
||||||
|
return '-'
|
||||||
|
} else {
|
||||||
|
return `${amount.toSignificantDigits(4)} xDAI`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ExpandableListItem
|
||||||
|
label="Has sufficient funds"
|
||||||
|
value={redistributionState?.hasSufficientFunds?.toString() ?? '-'}
|
||||||
|
/>
|
||||||
|
<ExpandableListItem label="Fully synced" value={redistributionState?.isFullySynced?.toString() ?? '-'} />
|
||||||
|
<ExpandableListItem label="Frozen" value={redistributionState?.isFrozen?.toString() ?? '-'} />
|
||||||
|
<ExpandableListItem label="Phase" value={redistributionState?.phase ?? '-'} />
|
||||||
|
<ExpandableListItem label="Round" value={redistributionState?.round?.toString() ?? '-'} />
|
||||||
|
<ExpandableListItem
|
||||||
|
label="Last selected round"
|
||||||
|
value={redistributionState?.lastSelectedRound.toString() ?? '-'}
|
||||||
|
/>
|
||||||
|
<ExpandableListItem label="Last played round" value={redistributionState?.lastPlayedRound.toString() ?? '-'} />
|
||||||
|
<ExpandableListItem label="Last round won" value={redistributionState?.lastWonRound.toString() ?? '-'} />
|
||||||
|
<ExpandableListItem label="Last frozen round" value={redistributionState?.lastFrozenRound.toString() ?? '-'} />
|
||||||
|
<ExpandableListItem
|
||||||
|
label="Last sample duration"
|
||||||
|
value={formatDurationSeconds(redistributionState?.lastSampleDurationSeconds)}
|
||||||
|
/>
|
||||||
|
<ExpandableListItem label="Reward" value={formatBzzAmount(redistributionState?.reward)} />
|
||||||
|
<ExpandableListItem label="Fees" value={formatDaiAmount(redistributionState?.fees)} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import { ReactElement, useContext, useState } from 'react'
|
|||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import FilesIcon from 'remixicon-react/ArrowUpDownLineIcon'
|
import FilesIcon from 'remixicon-react/ArrowUpDownLineIcon'
|
||||||
import DocsIcon from 'remixicon-react/BookOpenLineIcon'
|
import DocsIcon from 'remixicon-react/BookOpenLineIcon'
|
||||||
|
import ExchangeDollarLineIcon from 'remixicon-react/ExchangeDollarLineIcon'
|
||||||
import ExternalLinkIcon from 'remixicon-react/ExternalLinkLineIcon'
|
import ExternalLinkIcon from 'remixicon-react/ExternalLinkLineIcon'
|
||||||
import FileManagerIcon from 'remixicon-react/FolderOpenLineIcon'
|
import FileManagerIcon from 'remixicon-react/FolderOpenLineIcon'
|
||||||
import GithubIcon from 'remixicon-react/GithubFillIcon'
|
import GithubIcon from 'remixicon-react/GithubFillIcon'
|
||||||
@@ -147,6 +148,11 @@ export default function SideBar(): ReactElement {
|
|||||||
icon: AccountIcon,
|
icon: AccountIcon,
|
||||||
pathMatcherSubstring: '/account/',
|
pathMatcherSubstring: '/account/',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Redistribution',
|
||||||
|
path: ROUTES.REDISTRIBUTION,
|
||||||
|
icon: ExchangeDollarLineIcon,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Settings',
|
label: 'Settings',
|
||||||
path: ROUTES.SETTINGS,
|
path: ROUTES.SETTINGS,
|
||||||
|
|||||||
+18
-2
@@ -1,9 +1,10 @@
|
|||||||
import { PostageBatch } from '@ethersphere/bee-js'
|
import { Bee, PostageBatch } from '@ethersphere/bee-js'
|
||||||
import { DriveInfo, FileInfo } from '@solarpunkltd/file-manager-lib'
|
import { DriveInfo, FileInfo } from '@solarpunkltd/file-manager-lib'
|
||||||
import { ReactElement, useEffect, useMemo, useState } from 'react'
|
import { ReactElement, useEffect, useMemo, useState } from 'react'
|
||||||
import { createPortal } from 'react-dom'
|
import { createPortal } from 'react-dom'
|
||||||
import AlertIcon from 'remixicon-react/AlertLineIcon'
|
import AlertIcon from 'remixicon-react/AlertLineIcon'
|
||||||
|
|
||||||
|
import { validateStampStillExists } from '../../utils/bee'
|
||||||
import { getDaysLeft } from '../../utils/common'
|
import { getDaysLeft } from '../../utils/common'
|
||||||
import { Button } from '../Button/Button'
|
import { Button } from '../Button/Button'
|
||||||
import { UpgradeDriveModal } from '../UpgradeDriveModal/UpgradeDriveModal'
|
import { UpgradeDriveModal } from '../UpgradeDriveModal/UpgradeDriveModal'
|
||||||
@@ -16,19 +17,23 @@ import '../../styles/global.scss'
|
|||||||
const EXPIRING_ITEMS_PAGE_SIZE = 3
|
const EXPIRING_ITEMS_PAGE_SIZE = 3
|
||||||
|
|
||||||
interface ExpiringNotificationModalProps {
|
interface ExpiringNotificationModalProps {
|
||||||
|
bee: Bee
|
||||||
stamps: PostageBatch[]
|
stamps: PostageBatch[]
|
||||||
drives: DriveInfo[]
|
drives: DriveInfo[]
|
||||||
files: FileInfo[]
|
files: FileInfo[]
|
||||||
onCancelClick: () => void
|
onCancelClick: () => void
|
||||||
setErrorMessage?: (error: string) => void
|
setErrorMessage?: (error: string) => void
|
||||||
|
setShowError: (show: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ExpiringNotificationModal({
|
export function ExpiringNotificationModal({
|
||||||
|
bee,
|
||||||
stamps,
|
stamps,
|
||||||
drives,
|
drives,
|
||||||
files,
|
files,
|
||||||
onCancelClick,
|
onCancelClick,
|
||||||
setErrorMessage,
|
setErrorMessage,
|
||||||
|
setShowError,
|
||||||
}: ExpiringNotificationModalProps): ReactElement {
|
}: ExpiringNotificationModalProps): ReactElement {
|
||||||
const [showUpgradeDriveModal, setShowUpgradeDriveModal] = useState(false)
|
const [showUpgradeDriveModal, setShowUpgradeDriveModal] = useState(false)
|
||||||
const [actualStamp, setActualStamp] = useState<PostageBatch | undefined>(undefined)
|
const [actualStamp, setActualStamp] = useState<PostageBatch | undefined>(undefined)
|
||||||
@@ -75,7 +80,18 @@ export function ExpiringNotificationModal({
|
|||||||
files={files}
|
files={files}
|
||||||
currentPage={currentPage}
|
currentPage={currentPage}
|
||||||
index={index}
|
index={index}
|
||||||
onUpgradeClick={(stamp, drive) => {
|
onUpgradeClick={async (stamp, drive) => {
|
||||||
|
const isStampValid = await validateStampStillExists(bee, stamp.batchID)
|
||||||
|
|
||||||
|
if (!isStampValid) {
|
||||||
|
setErrorMessage?.(
|
||||||
|
`Drive ${drive.name} has expired. Please clear the browser cache and reload the page.`,
|
||||||
|
)
|
||||||
|
setShowError(true)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
setActualStamp(stamp)
|
setActualStamp(stamp)
|
||||||
setActualDrive(drive)
|
setActualDrive(drive)
|
||||||
setShowUpgradeDriveModal(true)
|
setShowUpgradeDriveModal(true)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import React, {
|
|||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
|
import { createPortal } from 'react-dom'
|
||||||
|
|
||||||
import { useSearch } from '../../../../pages/filemanager/SearchContext'
|
import { useSearch } from '../../../../pages/filemanager/SearchContext'
|
||||||
import { useView } from '../../../../pages/filemanager/ViewContext'
|
import { useView } from '../../../../pages/filemanager/ViewContext'
|
||||||
@@ -87,7 +88,9 @@ function ErrorModalBlock({
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return <ErrorModal label={label} onClick={onOk} />
|
const modalRoot = document.querySelector('.fm-main') || document.body
|
||||||
|
|
||||||
|
return createPortal(<ErrorModal label={label} onClick={onOk} />, modalRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
const extractFilesFromClipboardEvent = (e: React.ClipboardEvent): File[] => {
|
const extractFilesFromClipboardEvent = (e: React.ClipboardEvent): File[] => {
|
||||||
@@ -431,8 +434,10 @@ export function FileBrowser({ errorMessage, setErrorMessage }: FileBrowserProps)
|
|||||||
if (rafIdRef.current) {
|
if (rafIdRef.current) {
|
||||||
cancelAnimationFrame(rafIdRef.current)
|
cancelAnimationFrame(rafIdRef.current)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setShowError(false)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [setShowError])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let title = currentDrive?.name || ''
|
let title = currentDrive?.name || ''
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export function NotificationBar({ setErrorMessage }: NotificationBarProps): Reac
|
|||||||
const [stampsToExpire, setStampsToExpire] = useState<PostageBatch[]>([])
|
const [stampsToExpire, setStampsToExpire] = useState<PostageBatch[]>([])
|
||||||
const [drivesToExpire, setDrivesToExpire] = useState<DriveInfo[]>([])
|
const [drivesToExpire, setDrivesToExpire] = useState<DriveInfo[]>([])
|
||||||
const { beeApi } = useContext(SettingsContext)
|
const { beeApi } = useContext(SettingsContext)
|
||||||
const { drives, files, adminDrive } = useContext(FMContext)
|
const { drives, files, adminDrive, setShowError } = useContext(FMContext)
|
||||||
|
|
||||||
const showExpiration = stampsToExpire.length > 0
|
const showExpiration = stampsToExpire.length > 0
|
||||||
|
|
||||||
@@ -109,8 +109,9 @@ export function NotificationBar({ setErrorMessage }: NotificationBarProps): Reac
|
|||||||
<div className="fm-notification-bar fm-red-font" onClick={() => setShowExpiringModal(true)}>
|
<div className="fm-notification-bar fm-red-font" onClick={() => setShowExpiringModal(true)}>
|
||||||
{stampsToExpire.length} drive{stampsToExpire.length > 1 ? 's' : ''} expiring soon <UpIcon size="16px" />
|
{stampsToExpire.length} drive{stampsToExpire.length > 1 ? 's' : ''} expiring soon <UpIcon size="16px" />
|
||||||
</div>
|
</div>
|
||||||
{showExpiringModal && (
|
{showExpiringModal && beeApi && (
|
||||||
<ExpiringNotificationModal
|
<ExpiringNotificationModal
|
||||||
|
bee={beeApi}
|
||||||
stamps={stampsToExpire}
|
stamps={stampsToExpire}
|
||||||
drives={drivesToExpire}
|
drives={drivesToExpire}
|
||||||
files={files}
|
files={files}
|
||||||
@@ -118,6 +119,7 @@ export function NotificationBar({ setErrorMessage }: NotificationBarProps): Reac
|
|||||||
setShowExpiringModal(false)
|
setShowExpiringModal(false)
|
||||||
}}
|
}}
|
||||||
setErrorMessage={setErrorMessage}
|
setErrorMessage={setErrorMessage}
|
||||||
|
setShowError={setShowError}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { BeeModes } from '@ethersphere/bee-js'
|
||||||
import { DriveInfo, FileManagerBase } from '@solarpunkltd/file-manager-lib'
|
import { DriveInfo, FileManagerBase } from '@solarpunkltd/file-manager-lib'
|
||||||
import { ReactElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
|
import { ReactElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
|
|
||||||
@@ -44,6 +45,18 @@ function InitializationErrorBlock({ onOk }: { onOk: () => void }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function UltraLightNodeErrorBlock() {
|
||||||
|
return (
|
||||||
|
<div className="fm-main">
|
||||||
|
<div className="fm-loading">
|
||||||
|
<div className="fm-loading-title">
|
||||||
|
File Manager is not available with an Ultra-light node. Please upgrade to a Light node to continue.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function ResetModalBlock({ cacheHelpUrl, onConfirm }: { cacheHelpUrl: string; onConfirm: () => void }) {
|
function ResetModalBlock({ cacheHelpUrl, onConfirm }: { cacheHelpUrl: string; onConfirm: () => void }) {
|
||||||
return (
|
return (
|
||||||
<div className="fm-main">
|
<div className="fm-main">
|
||||||
@@ -169,6 +182,7 @@ function FileManagerMainContent(props: {
|
|||||||
|
|
||||||
enum PageState {
|
enum PageState {
|
||||||
Connecting = 'connecting', // still warming up — show nothing / loader
|
Connecting = 'connecting', // still warming up — show nothing / loader
|
||||||
|
UltraLightNode = 'ultra-light-node', // ultra-light node — file manager not available
|
||||||
NoPrivateKey = 'no-pk', // private key not set
|
NoPrivateKey = 'no-pk', // private key not set
|
||||||
Loading = 'loading', // bee ready, pk present, FM init in progress
|
Loading = 'loading', // bee ready, pk present, FM init in progress
|
||||||
Reset = 'reset', // STATE_INVALID emitted and user has not yet acknowledged
|
Reset = 'reset', // STATE_INVALID emitted and user has not yet acknowledged
|
||||||
@@ -189,7 +203,7 @@ export function FileManagerPage(): ReactElement {
|
|||||||
const [connectionErrorDismissed, setConnectionErrorDismissed] = useState<boolean>(false)
|
const [connectionErrorDismissed, setConnectionErrorDismissed] = useState<boolean>(false)
|
||||||
const [cacheHelpUrl, setCacheHelpUrl] = useState<string>(cacheClearUrls[BrowserPlatform.Chrome])
|
const [cacheHelpUrl, setCacheHelpUrl] = useState<string>(cacheClearUrls[BrowserPlatform.Chrome])
|
||||||
|
|
||||||
const { status, chainState } = useContext(BeeContext)
|
const { status, chainState, nodeInfo } = useContext(BeeContext)
|
||||||
const { fm, initDone, shallReset, adminDrive, initializationError, notifyPkSaved } = useContext(FMContext)
|
const { fm, initDone, shallReset, adminDrive, initializationError, notifyPkSaved } = useContext(FMContext)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -228,6 +242,8 @@ export function FileManagerPage(): ReactElement {
|
|||||||
|
|
||||||
if (!isBeeReady && !initDone) return PageState.Connecting
|
if (!isBeeReady && !initDone) return PageState.Connecting
|
||||||
|
|
||||||
|
if (nodeInfo?.beeMode === BeeModes.ULTRA_LIGHT) return PageState.UltraLightNode
|
||||||
|
|
||||||
if (!hasPk) return PageState.NoPrivateKey
|
if (!hasPk) return PageState.NoPrivateKey
|
||||||
|
|
||||||
if (!initDone) return PageState.Loading
|
if (!initDone) return PageState.Loading
|
||||||
@@ -259,6 +275,7 @@ export function FileManagerPage(): ReactElement {
|
|||||||
adminDrive,
|
adminDrive,
|
||||||
isCreationInProgress,
|
isCreationInProgress,
|
||||||
chainState,
|
chainState,
|
||||||
|
nodeInfo?.beeMode,
|
||||||
])
|
])
|
||||||
|
|
||||||
const handlePrivateKeySaved = useCallback(() => {
|
const handlePrivateKeySaved = useCallback(() => {
|
||||||
@@ -274,6 +291,10 @@ export function FileManagerPage(): ReactElement {
|
|||||||
const loading = !fm?.adminStamp || !adminDrive
|
const loading = !fm?.adminStamp || !adminDrive
|
||||||
const isFormbricksActive = Boolean(fm && fm.adminStamp && adminDrive && !loading)
|
const isFormbricksActive = Boolean(fm && fm.adminStamp && adminDrive && !loading)
|
||||||
|
|
||||||
|
if (pageState === PageState.UltraLightNode) {
|
||||||
|
return <UltraLightNodeErrorBlock />
|
||||||
|
}
|
||||||
|
|
||||||
if (pageState === PageState.Connecting || pageState === PageState.Loading) {
|
if (pageState === PageState.Connecting || pageState === PageState.Loading) {
|
||||||
return <LoadingBlock />
|
return <LoadingBlock />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import NodeInfoCard from './NodeInfoCard'
|
|||||||
import { WalletInfoCard } from './WalletInfoCard'
|
import { WalletInfoCard } from './WalletInfoCard'
|
||||||
|
|
||||||
export default function Status(): ReactElement {
|
export default function Status(): ReactElement {
|
||||||
const { beeVersion, status, topology, nodeInfo, walletBalance } = useContext(BeeContext)
|
const { beeVersion, status, topology, nodeInfo, nodeStatus, walletBalance } = useContext(BeeContext)
|
||||||
const { isDesktop, desktopUrl } = useContext(SettingsContext)
|
const { isDesktop, desktopUrl } = useContext(SettingsContext)
|
||||||
const { beeDesktopVersion } = useBeeDesktop(isDesktop, desktopUrl)
|
const { beeDesktopVersion } = useBeeDesktop(isDesktop, desktopUrl)
|
||||||
const { newBeeDesktopVersion } = useNewBeeDesktopVersion(isDesktop, desktopUrl, false)
|
const { newBeeDesktopVersion } = useNewBeeDesktopVersion(isDesktop, desktopUrl, false)
|
||||||
@@ -40,7 +40,10 @@ export default function Status(): ReactElement {
|
|||||||
<div style={{ height: '2px' }} />
|
<div style={{ height: '2px' }} />
|
||||||
<ExpandableListItem label="Connected peers" value={topology?.connected ?? '-'} />
|
<ExpandableListItem label="Connected peers" value={topology?.connected ?? '-'} />
|
||||||
<ExpandableListItem label="Population" value={topology?.population ?? '-'} />
|
<ExpandableListItem label="Population" value={topology?.population ?? '-'} />
|
||||||
|
<ExpandableListItem label="Pullsync rate" value={nodeStatus?.pullsyncRate} />
|
||||||
<ExpandableListItem label="Depth" value={topology?.depth ?? '-'} />
|
<ExpandableListItem label="Depth" value={topology?.depth ?? '-'} />
|
||||||
|
<ExpandableListItem label="Neighborhood size" value={nodeStatus?.neighborhoodSize} />
|
||||||
|
<ExpandableListItem label="Node is reachable" value={nodeStatus?.isReachable?.toString()} />
|
||||||
<ChainSync />
|
<ChainSync />
|
||||||
|
|
||||||
<div style={{ height: '16px' }} />
|
<div style={{ height: '16px' }} />
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import CircularProgress from '@mui/material/CircularProgress'
|
||||||
|
import { ReactElement, useContext } from 'react'
|
||||||
|
|
||||||
|
import ExpandableList from '../../components/ExpandableList'
|
||||||
|
import { Redistribution } from '../../components/Redistribution'
|
||||||
|
import { Context as SettingsContext } from '../../providers/Settings'
|
||||||
|
|
||||||
|
export default function RedistributionPage(): ReactElement {
|
||||||
|
const { isLoading } = useContext(SettingsContext)
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div style={{ textAlign: 'center', width: '100%' }}>
|
||||||
|
<CircularProgress />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ExpandableList label="Redistribution" defaultOpen>
|
||||||
|
<Redistribution />
|
||||||
|
</ExpandableList>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -191,7 +191,6 @@ export function PostageStampStandardCreation({ onFinished }: Props): ReactElemen
|
|||||||
<Grid container justifyContent="space-between">
|
<Grid container justifyContent="space-between">
|
||||||
<Typography>Corresponding TTL (Time to live)</Typography>
|
<Typography>Corresponding TTL (Time to live)</Typography>
|
||||||
<Typography>{amountInput ? getTtl(amountInput) : '-'}</Typography>
|
<Typography>{amountInput ? getTtl(amountInput) : '-'}</Typography>
|
||||||
<Typography>{amountInput ? getTtl(amountInput) : '-'}</Typography>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
<Box display="flex" justifyContent={'right'} mt={0.5}>
|
<Box display="flex" justifyContent={'right'} mt={0.5}>
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ import {
|
|||||||
ChainState,
|
ChainState,
|
||||||
ChequebookAddressResponse,
|
ChequebookAddressResponse,
|
||||||
ChequebookBalanceResponse,
|
ChequebookBalanceResponse,
|
||||||
|
DebugStatus,
|
||||||
LastChequesResponse,
|
LastChequesResponse,
|
||||||
NodeAddresses,
|
NodeAddresses,
|
||||||
NodeInfo,
|
NodeInfo,
|
||||||
Peer,
|
Peer,
|
||||||
PeerBalance,
|
PeerBalance,
|
||||||
|
RedistributionState,
|
||||||
Topology,
|
Topology,
|
||||||
WalletBalance,
|
WalletBalance,
|
||||||
} from '@ethersphere/bee-js'
|
} from '@ethersphere/bee-js'
|
||||||
@@ -61,6 +63,7 @@ interface ContextInterface {
|
|||||||
apiHealth: boolean
|
apiHealth: boolean
|
||||||
nodeAddresses: NodeAddresses | null
|
nodeAddresses: NodeAddresses | null
|
||||||
nodeInfo: NodeInfo | null
|
nodeInfo: NodeInfo | null
|
||||||
|
nodeStatus: DebugStatus | null
|
||||||
topology: Topology | null
|
topology: Topology | null
|
||||||
chequebookAddress: ChequebookAddressResponse | null
|
chequebookAddress: ChequebookAddressResponse | null
|
||||||
peers: Peer[] | null
|
peers: Peer[] | null
|
||||||
@@ -71,6 +74,7 @@ interface ContextInterface {
|
|||||||
settlements: AllSettlements | null
|
settlements: AllSettlements | null
|
||||||
chainState: ChainState | null
|
chainState: ChainState | null
|
||||||
walletBalance: WalletBalance | null
|
walletBalance: WalletBalance | null
|
||||||
|
redistributionState: RedistributionState | null
|
||||||
latestBeeRelease: LatestBeeRelease | null
|
latestBeeRelease: LatestBeeRelease | null
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
lastUpdate: number | null
|
lastUpdate: number | null
|
||||||
@@ -91,6 +95,7 @@ const initialValues: ContextInterface = {
|
|||||||
apiHealth: false,
|
apiHealth: false,
|
||||||
nodeAddresses: null,
|
nodeAddresses: null,
|
||||||
nodeInfo: null,
|
nodeInfo: null,
|
||||||
|
nodeStatus: null,
|
||||||
topology: null,
|
topology: null,
|
||||||
chequebookAddress: null,
|
chequebookAddress: null,
|
||||||
stake: null,
|
stake: null,
|
||||||
@@ -101,6 +106,7 @@ const initialValues: ContextInterface = {
|
|||||||
settlements: null,
|
settlements: null,
|
||||||
chainState: null,
|
chainState: null,
|
||||||
walletBalance: null,
|
walletBalance: null,
|
||||||
|
redistributionState: null,
|
||||||
latestBeeRelease: null,
|
latestBeeRelease: null,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
lastUpdate: null,
|
lastUpdate: null,
|
||||||
@@ -199,6 +205,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
const [isWarmingUp, setIsWarmingUp] = useState<boolean>(true)
|
const [isWarmingUp, setIsWarmingUp] = useState<boolean>(true)
|
||||||
const [nodeAddresses, setNodeAddresses] = useState<NodeAddresses | null>(null)
|
const [nodeAddresses, setNodeAddresses] = useState<NodeAddresses | null>(null)
|
||||||
const [nodeInfo, setNodeInfo] = useState<NodeInfo | null>(null)
|
const [nodeInfo, setNodeInfo] = useState<NodeInfo | null>(null)
|
||||||
|
const [nodeStatus, setNodeStatus] = useState<DebugStatus | null>(null)
|
||||||
const [topology, setNodeTopology] = useState<Topology | null>(null)
|
const [topology, setNodeTopology] = useState<Topology | null>(null)
|
||||||
const [chequebookAddress, setChequebookAddress] = useState<ChequebookAddressResponse | null>(null)
|
const [chequebookAddress, setChequebookAddress] = useState<ChequebookAddressResponse | null>(null)
|
||||||
const [peers, setPeers] = useState<Peer[] | null>(null)
|
const [peers, setPeers] = useState<Peer[] | null>(null)
|
||||||
@@ -209,6 +216,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
const [settlements, setSettlements] = useState<AllSettlements | null>(null)
|
const [settlements, setSettlements] = useState<AllSettlements | null>(null)
|
||||||
const [chainState, setChainState] = useState<ChainState | null>(null)
|
const [chainState, setChainState] = useState<ChainState | null>(null)
|
||||||
const [walletBalance, setWalletBalance] = useState<WalletBalance | null>(null)
|
const [walletBalance, setWalletBalance] = useState<WalletBalance | null>(null)
|
||||||
|
const [redistributionState, setRedistributionState] = useState<RedistributionState | null>(null)
|
||||||
const [startedAt, setStartedAt] = useState(() => Date.now())
|
const [startedAt, setStartedAt] = useState(() => Date.now())
|
||||||
|
|
||||||
const { latestBeeRelease } = useLatestBeeRelease()
|
const { latestBeeRelease } = useLatestBeeRelease()
|
||||||
@@ -257,6 +265,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
walletResult,
|
walletResult,
|
||||||
chequebookBalanceResult,
|
chequebookBalanceResult,
|
||||||
stakeResult,
|
stakeResult,
|
||||||
|
redistributionStateResult,
|
||||||
peerBalancesResult,
|
peerBalancesResult,
|
||||||
settlementsResult,
|
settlementsResult,
|
||||||
] = await Promise.allSettled([
|
] = await Promise.allSettled([
|
||||||
@@ -272,6 +281,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
beeApi.getWalletBalance({ timeout: TIMEOUT }),
|
beeApi.getWalletBalance({ timeout: TIMEOUT }),
|
||||||
beeApi.getChequebookBalance({ timeout: TIMEOUT }),
|
beeApi.getChequebookBalance({ timeout: TIMEOUT }),
|
||||||
beeApi.getStake({ timeout: TIMEOUT }),
|
beeApi.getStake({ timeout: TIMEOUT }),
|
||||||
|
beeApi.getRedistributionState({ timeout: TIMEOUT }),
|
||||||
beeApi.getAllBalances({ timeout: TIMEOUT }),
|
beeApi.getAllBalances({ timeout: TIMEOUT }),
|
||||||
beeApi.getAllSettlements(),
|
beeApi.getAllSettlements(),
|
||||||
])
|
])
|
||||||
@@ -282,6 +292,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
setApiHealth(Boolean(health))
|
setApiHealth(Boolean(health))
|
||||||
|
|
||||||
setIsWarmingUp(getFulfilledValue(statusResult)?.isWarmingUp ?? false)
|
setIsWarmingUp(getFulfilledValue(statusResult)?.isWarmingUp ?? false)
|
||||||
|
setNodeStatus(getFulfilledValue(statusResult))
|
||||||
setNodeAddresses(getFulfilledValue(nodeAddressesResult))
|
setNodeAddresses(getFulfilledValue(nodeAddressesResult))
|
||||||
setNodeInfo(getFulfilledValue(nodeInfoResult))
|
setNodeInfo(getFulfilledValue(nodeInfoResult))
|
||||||
setNodeTopology(getFulfilledValue(topologyResult))
|
setNodeTopology(getFulfilledValue(topologyResult))
|
||||||
@@ -292,6 +303,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
setWalletBalance(getFulfilledValue(walletResult))
|
setWalletBalance(getFulfilledValue(walletResult))
|
||||||
setChequebookBalance(getFulfilledValue(chequebookBalanceResult))
|
setChequebookBalance(getFulfilledValue(chequebookBalanceResult))
|
||||||
setStake(getFulfilledValue(stakeResult))
|
setStake(getFulfilledValue(stakeResult))
|
||||||
|
setRedistributionState(getFulfilledValue(redistributionStateResult))
|
||||||
setPeerBalances(getFulfilledValue(peerBalancesResult)?.balances ?? null)
|
setPeerBalances(getFulfilledValue(peerBalancesResult)?.balances ?? null)
|
||||||
setSettlements(getFulfilledValue(settlementsResult))
|
setSettlements(getFulfilledValue(settlementsResult))
|
||||||
setError(null)
|
setError(null)
|
||||||
@@ -332,6 +344,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
setNodeAddresses(null)
|
setNodeAddresses(null)
|
||||||
setNodeTopology(null)
|
setNodeTopology(null)
|
||||||
setNodeInfo(null)
|
setNodeInfo(null)
|
||||||
|
setNodeStatus(null)
|
||||||
setPeers(null)
|
setPeers(null)
|
||||||
setChequebookAddress(null)
|
setChequebookAddress(null)
|
||||||
setChequebookBalance(null)
|
setChequebookBalance(null)
|
||||||
@@ -339,6 +352,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
setPeerCheques(null)
|
setPeerCheques(null)
|
||||||
setSettlements(null)
|
setSettlements(null)
|
||||||
setChainState(null)
|
setChainState(null)
|
||||||
|
setRedistributionState(null)
|
||||||
|
|
||||||
if (beeApi !== null) {
|
if (beeApi !== null) {
|
||||||
refresh()
|
refresh()
|
||||||
@@ -381,6 +395,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
apiHealth,
|
apiHealth,
|
||||||
nodeAddresses,
|
nodeAddresses,
|
||||||
nodeInfo,
|
nodeInfo,
|
||||||
|
nodeStatus,
|
||||||
topology,
|
topology,
|
||||||
chequebookAddress,
|
chequebookAddress,
|
||||||
peers,
|
peers,
|
||||||
@@ -391,6 +406,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
settlements,
|
settlements,
|
||||||
chainState,
|
chainState,
|
||||||
walletBalance,
|
walletBalance,
|
||||||
|
redistributionState,
|
||||||
latestBeeRelease,
|
latestBeeRelease,
|
||||||
isLoading,
|
isLoading,
|
||||||
lastUpdate,
|
lastUpdate,
|
||||||
@@ -405,6 +421,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
apiHealth,
|
apiHealth,
|
||||||
nodeAddresses,
|
nodeAddresses,
|
||||||
nodeInfo,
|
nodeInfo,
|
||||||
|
nodeStatus,
|
||||||
topology,
|
topology,
|
||||||
chequebookAddress,
|
chequebookAddress,
|
||||||
peers,
|
peers,
|
||||||
@@ -415,6 +432,7 @@ export function Provider({ children }: Props): ReactElement {
|
|||||||
settlements,
|
settlements,
|
||||||
chainState,
|
chainState,
|
||||||
walletBalance,
|
walletBalance,
|
||||||
|
redistributionState,
|
||||||
latestBeeRelease,
|
latestBeeRelease,
|
||||||
isLoading,
|
isLoading,
|
||||||
lastUpdate,
|
lastUpdate,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { UploadLander } from './pages/files/UploadLander'
|
|||||||
import GiftCards from './pages/giftCode'
|
import GiftCards from './pages/giftCode'
|
||||||
import Info from './pages/info'
|
import Info from './pages/info'
|
||||||
import PageNotFound from './pages/notFound/PageNotFound'
|
import PageNotFound from './pages/notFound/PageNotFound'
|
||||||
|
import RedistributionPage from './pages/redistribution'
|
||||||
import LightModeRestart from './pages/restart/LightModeRestart'
|
import LightModeRestart from './pages/restart/LightModeRestart'
|
||||||
import Settings from './pages/settings'
|
import Settings from './pages/settings'
|
||||||
import { CreatePostageStampPage } from './pages/stamps/CreatePostageStampAdvancedPage'
|
import { CreatePostageStampPage } from './pages/stamps/CreatePostageStampAdvancedPage'
|
||||||
@@ -38,6 +39,7 @@ export enum ROUTES {
|
|||||||
UPLOAD_IN_PROGRESS = '/files/upload/workflow',
|
UPLOAD_IN_PROGRESS = '/files/upload/workflow',
|
||||||
DOWNLOAD = '/files/download',
|
DOWNLOAD = '/files/download',
|
||||||
HASH = '/files/hash/:hash',
|
HASH = '/files/hash/:hash',
|
||||||
|
REDISTRIBUTION = '/redistribution',
|
||||||
SETTINGS = '/settings',
|
SETTINGS = '/settings',
|
||||||
STATUS = '/status',
|
STATUS = '/status',
|
||||||
TOP_UP = '/account/wallet/top-up',
|
TOP_UP = '/account/wallet/top-up',
|
||||||
@@ -82,6 +84,7 @@ const BaseRouter = (): ReactElement => {
|
|||||||
<Route path={ROUTES.SETTINGS} element={<Settings />} />
|
<Route path={ROUTES.SETTINGS} element={<Settings />} />
|
||||||
<Route path={ROUTES.STATUS} element={<Status />} />
|
<Route path={ROUTES.STATUS} element={<Status />} />
|
||||||
<Route path={ROUTES.INFO} element={<Info />} />
|
<Route path={ROUTES.INFO} element={<Info />} />
|
||||||
|
<Route path={ROUTES.REDISTRIBUTION} element={<RedistributionPage />} />
|
||||||
<Route path={ROUTES.TOP_UP} element={<TopUp />} />
|
<Route path={ROUTES.TOP_UP} element={<TopUp />} />
|
||||||
<Route path={ROUTES.TOP_UP_CRYPTO} element={<CryptoTopUpIndex />} />
|
<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_CRYPTO_SWAP} element={<Swap header="Top-up with cryptocurrencies" />} />
|
||||||
|
|||||||
+2
-2
@@ -84,7 +84,7 @@ export async function sendNativeTransaction(
|
|||||||
const feedData = await signer.provider.getFeeData()
|
const feedData = await signer.provider.getFeeData()
|
||||||
const gasPrice = externalGasPrice ?? DAI.fromWei(feedData.gasPrice?.toString() || '0')
|
const gasPrice = externalGasPrice ?? DAI.fromWei(feedData.gasPrice?.toString() || '0')
|
||||||
const transaction = await signer.sendTransaction({
|
const transaction = await signer.sendTransaction({
|
||||||
to: to.toHex(),
|
to: to.toChecksum(),
|
||||||
value: BigInt(value.toWeiString()),
|
value: BigInt(value.toWeiString()),
|
||||||
gasPrice: BigInt(gasPrice.toWeiString()),
|
gasPrice: BigInt(gasPrice.toWeiString()),
|
||||||
gasLimit: BigInt(21000),
|
gasLimit: BigInt(21000),
|
||||||
@@ -117,7 +117,7 @@ export async function sendBzzTransaction(
|
|||||||
const feeData = await signer.provider.getFeeData()
|
const feeData = await signer.provider.getFeeData()
|
||||||
const gasPrice = feeData.gasPrice || BigInt(0)
|
const gasPrice = feeData.gasPrice || BigInt(0)
|
||||||
const bzz = new Contract(BZZ_TOKEN_ADDRESS, bzzABI, signer)
|
const bzz = new Contract(BZZ_TOKEN_ADDRESS, bzzABI, signer)
|
||||||
const transaction = await bzz.transfer(to.toChecksum(), value, { gasPrice })
|
const transaction = await bzz.transfer(to.toChecksum(), value.toPLURBigInt(), { gasPrice })
|
||||||
const receipt = await transaction.wait(1)
|
const receipt = await transaction.wait(1)
|
||||||
|
|
||||||
if (!receipt) {
|
if (!receipt) {
|
||||||
|
|||||||
+52
-4
@@ -1,6 +1,6 @@
|
|||||||
import { BZZ } from '@ethersphere/bee-js'
|
import { BZZ, DAI } from '@ethersphere/bee-js'
|
||||||
|
|
||||||
import { sendBzzTransaction } from '../../src/utils/rpc'
|
import { sendBzzTransaction, sendNativeTransaction } from '../../src/utils/rpc'
|
||||||
|
|
||||||
interface MockProvider {
|
interface MockProvider {
|
||||||
getFeeData: jest.Mock
|
getFeeData: jest.Mock
|
||||||
@@ -11,12 +11,14 @@ const mockWait = jest.fn()
|
|||||||
const mockTransfer = jest.fn()
|
const mockTransfer = jest.fn()
|
||||||
const mockGetFeeData = jest.fn()
|
const mockGetFeeData = jest.fn()
|
||||||
const mockGetNetwork = jest.fn()
|
const mockGetNetwork = jest.fn()
|
||||||
|
const mockSendTransaction = jest.fn()
|
||||||
const mockProvider: MockProvider = {
|
const mockProvider: MockProvider = {
|
||||||
getFeeData: mockGetFeeData,
|
getFeeData: mockGetFeeData,
|
||||||
getNetwork: mockGetNetwork,
|
getNetwork: mockGetNetwork,
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = BZZ.fromDecimalString('1')
|
const bzzValue = BZZ.fromDecimalString('1')
|
||||||
|
const daiValue = DAI.fromDecimalString('1')
|
||||||
const privateKey = 'FFFF000000000000000000000000000000000000000000000000000000000000'
|
const privateKey = 'FFFF000000000000000000000000000000000000000000000000000000000000'
|
||||||
const jsonRpcProvider = 'http://mock-json-rpc-provider'
|
const jsonRpcProvider = 'http://mock-json-rpc-provider'
|
||||||
|
|
||||||
@@ -39,6 +41,7 @@ jest.mock('ethers', () => {
|
|||||||
|
|
||||||
class Wallet {
|
class Wallet {
|
||||||
provider: MockProvider
|
provider: MockProvider
|
||||||
|
sendTransaction = mockSendTransaction
|
||||||
|
|
||||||
constructor(_privateKey: string, provider: MockProvider) {
|
constructor(_privateKey: string, provider: MockProvider) {
|
||||||
this.provider = provider
|
this.provider = provider
|
||||||
@@ -64,8 +67,53 @@ describe('sendBzzTransaction', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it.each(addresses)('sendBzzTransaction to address: %s', async (address: string) => {
|
it.each(addresses)('sendBzzTransaction to address: %s', async (address: string) => {
|
||||||
await sendBzzTransaction(privateKey, address, value, jsonRpcProvider)
|
await sendBzzTransaction(privateKey, address, bzzValue, jsonRpcProvider)
|
||||||
const to = mockTransfer.mock.calls[0][0] as string
|
const to = mockTransfer.mock.calls[0][0] as string
|
||||||
expect(to.startsWith('0x')).toBe(true)
|
expect(to.startsWith('0x')).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('passes BZZ value as bigint (not BZZ object)', async () => {
|
||||||
|
await sendBzzTransaction(privateKey, '0x52908400098527886e0f7030069857d2e4169ee7', bzzValue, jsonRpcProvider)
|
||||||
|
const transferredValue = mockTransfer.mock.calls[0][1]
|
||||||
|
expect(typeof transferredValue).toBe('bigint')
|
||||||
|
expect(transferredValue).toBe(bzzValue.toPLURBigInt())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('sendNativeTransaction', () => {
|
||||||
|
const addresses = ['52908400098527886e0f7030069857d2e4169ee7', '0x52908400098527886e0f7030069857d2e4169ee7']
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
mockWait.mockResolvedValue({ status: 1 })
|
||||||
|
mockSendTransaction.mockResolvedValue({ wait: mockWait })
|
||||||
|
mockGetFeeData.mockResolvedValue({ gasPrice: BigInt(1) })
|
||||||
|
mockGetNetwork.mockResolvedValue({ chainId: BigInt(100) })
|
||||||
|
})
|
||||||
|
|
||||||
|
it.each(addresses)('sendNativeTransaction to address: %s passes 0x-prefixed address', async (address: string) => {
|
||||||
|
await sendNativeTransaction(privateKey, address, daiValue, jsonRpcProvider)
|
||||||
|
const tx = mockSendTransaction.mock.calls[0][0] as { to: string }
|
||||||
|
expect(tx.to.startsWith('0x')).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('passes DAI value as bigint', async () => {
|
||||||
|
await sendNativeTransaction(privateKey, '0x52908400098527886e0f7030069857d2e4169ee7', daiValue, jsonRpcProvider)
|
||||||
|
const tx = mockSendTransaction.mock.calls[0][0] as { value: bigint }
|
||||||
|
expect(typeof tx.value).toBe('bigint')
|
||||||
|
expect(tx.value).toBe(BigInt(daiValue.toWeiString()))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('uses externalGasPrice when provided', async () => {
|
||||||
|
const externalGasPrice = DAI.fromWei('9999')
|
||||||
|
await sendNativeTransaction(
|
||||||
|
privateKey,
|
||||||
|
'0x52908400098527886e0f7030069857d2e4169ee7',
|
||||||
|
daiValue,
|
||||||
|
jsonRpcProvider,
|
||||||
|
externalGasPrice,
|
||||||
|
)
|
||||||
|
const tx = mockSendTransaction.mock.calls[0][0] as { gasPrice: bigint }
|
||||||
|
expect(tx.gasPrice).toBe(BigInt(externalGasPrice.toWeiString()))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user