fix: postage stamp price and TTL calculation (#305)
* fix: postage stamp price and TTL calculation * chore: removed logs and fixed linter issues
This commit is contained in:
@@ -57,4 +57,25 @@ export class Token {
|
|||||||
toFixedDecimal(digits = 7): string {
|
toFixedDecimal(digits = 7): string {
|
||||||
return this.toDecimal.toFixed(digits)
|
return this.toDecimal.toFixed(digits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toSignificantDigits(digits = 4): string {
|
||||||
|
const asString = this.toDecimal.toFixed(16)
|
||||||
|
|
||||||
|
let indexOfSignificantDigit = -1
|
||||||
|
let reachedDecimalPoint = false
|
||||||
|
|
||||||
|
for (let i = 0; i < asString.length; i++) {
|
||||||
|
const char = asString[i]
|
||||||
|
|
||||||
|
if (char === '.') {
|
||||||
|
reachedDecimalPoint = true
|
||||||
|
indexOfSignificantDigit = i + 1
|
||||||
|
} else if (reachedDecimalPoint && char !== '0') {
|
||||||
|
indexOfSignificantDigit = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return asString.slice(0, indexOfSignificantDigit + digits)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,14 @@ import { Box, Grid, Typography } from '@material-ui/core'
|
|||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
import { Form, Formik, FormikHelpers } from 'formik'
|
import { Form, Formik, FormikHelpers } from 'formik'
|
||||||
import { useSnackbar } from 'notistack'
|
import { useSnackbar } from 'notistack'
|
||||||
import React, { ReactElement, useContext } from 'react'
|
import { ReactElement, useContext } from 'react'
|
||||||
import { Check } from 'react-feather'
|
import { Check } from 'react-feather'
|
||||||
import { SwarmButton } from '../../components/SwarmButton'
|
import { SwarmButton } from '../../components/SwarmButton'
|
||||||
import { SwarmTextInput } from '../../components/SwarmTextInput'
|
import { SwarmTextInput } from '../../components/SwarmTextInput'
|
||||||
import { Context as BeeContext } from '../../providers/Bee'
|
import { Context as BeeContext } from '../../providers/Bee'
|
||||||
import { Context as SettingsContext } from '../../providers/Settings'
|
import { Context as SettingsContext } from '../../providers/Settings'
|
||||||
import { Context as StampsContext } from '../../providers/Stamps'
|
import { Context as StampsContext } from '../../providers/Stamps'
|
||||||
import {
|
import { calculateStampPrice, convertAmountToSeconds, convertDepthToBytes, secondsToTimeString } from '../../utils'
|
||||||
calculateStampPrice,
|
|
||||||
convertAmountToSeconds,
|
|
||||||
convertDepthToBytes,
|
|
||||||
formatBzz,
|
|
||||||
secondsToTimeString,
|
|
||||||
} from '../../utils'
|
|
||||||
import { getHumanReadableFileSize } from '../../utils/file'
|
import { getHumanReadableFileSize } from '../../utils/file'
|
||||||
|
|
||||||
interface FormValues {
|
interface FormValues {
|
||||||
@@ -50,24 +44,27 @@ export function PostageStampCreation({ onFinished }: Props): ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getTtl(amount: number): string {
|
function getTtl(amount: number): string {
|
||||||
if (isNaN(amount) || amount <= 0) {
|
|
||||||
return '-'
|
|
||||||
}
|
|
||||||
|
|
||||||
return secondsToTimeString(convertAmountToSeconds(amount))
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPrice(depth: number, amount: number): string {
|
|
||||||
const hasInvalidInput = isNaN(amount) || amount <= 0 || isNaN(depth) || depth < 17 || depth > 255
|
|
||||||
const isCurrentPriceAvailable = chainState && chainState.currentPrice
|
const isCurrentPriceAvailable = chainState && chainState.currentPrice
|
||||||
|
|
||||||
if (hasInvalidInput || !isCurrentPriceAvailable) {
|
if (amount <= 0 || !isCurrentPriceAvailable) {
|
||||||
return '-'
|
return '-'
|
||||||
}
|
}
|
||||||
|
|
||||||
const price = calculateStampPrice(depth, amount, chainState.currentPrice)
|
const pricePerBlock = Number.parseInt(chainState.currentPrice, 10)
|
||||||
|
|
||||||
return `${formatBzz(price)} BZZ`
|
return `${secondsToTimeString(convertAmountToSeconds(amount, pricePerBlock))} (with price of 0 per block)`
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrice(depth: number, amount: bigint): string {
|
||||||
|
const hasInvalidInput = amount <= 0 || isNaN(depth) || depth < 17 || depth > 255
|
||||||
|
|
||||||
|
if (hasInvalidInput) {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
const price = calculateStampPrice(depth, amount)
|
||||||
|
|
||||||
|
return `${price.toSignificantDigits()} BZZ`
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -136,7 +133,7 @@ export function PostageStampCreation({ onFinished }: Props): ReactElement {
|
|||||||
<Box mt={0.25} sx={{ bgcolor: '#f6f6f6' }} p={2}>
|
<Box mt={0.25} sx={{ bgcolor: '#f6f6f6' }} p={2}>
|
||||||
<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>{getTtl(parseInt(values.amount || '0', 10))}</Typography>
|
<Typography>{getTtl(Number.parseInt(values.amount || '0', 10))}</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -146,7 +143,7 @@ export function PostageStampCreation({ onFinished }: Props): ReactElement {
|
|||||||
<Box mb={4} sx={{ bgcolor: '#fcf2e8' }} p={2}>
|
<Box mb={4} sx={{ bgcolor: '#fcf2e8' }} p={2}>
|
||||||
<Grid container justifyContent="space-between">
|
<Grid container justifyContent="space-between">
|
||||||
<Typography>Indicative Price</Typography>
|
<Typography>Indicative Price</Typography>
|
||||||
<Typography>{getPrice(parseInt(values.depth || '0', 10), parseInt(values.amount || '0', 10))}</Typography>
|
<Typography>{getPrice(parseInt(values.depth || '0', 10), BigInt(values.amount || '0'))}</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
<SwarmButton
|
<SwarmButton
|
||||||
|
|||||||
+10
-27
@@ -1,5 +1,5 @@
|
|||||||
import { NumberString } from '@ethersphere/bee-js'
|
|
||||||
import { BigNumber } from 'bignumber.js'
|
import { BigNumber } from 'bignumber.js'
|
||||||
|
import { Token } from '../models/Token'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if value is an integer
|
* Test if value is an integer
|
||||||
@@ -159,38 +159,21 @@ export function secondsToTimeString(seconds: number): string {
|
|||||||
return `${unit.toFixed(1)} years`
|
return `${unit.toFixed(1)} years`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatBzz(amount: number): string {
|
|
||||||
const asString = amount.toFixed(16)
|
|
||||||
|
|
||||||
let indexOfSignificantDigit = -1
|
|
||||||
let reachedDecimalPoint = false
|
|
||||||
|
|
||||||
for (let i = 0; i < asString.length; i++) {
|
|
||||||
const char = asString[i]
|
|
||||||
|
|
||||||
if (char === '.') {
|
|
||||||
reachedDecimalPoint = true
|
|
||||||
} else if (reachedDecimalPoint && char !== '0') {
|
|
||||||
indexOfSignificantDigit = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return asString.slice(0, indexOfSignificantDigit + 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function convertDepthToBytes(depth: number): number {
|
export function convertDepthToBytes(depth: number): number {
|
||||||
return 2 ** depth * 4096
|
return 2 ** depth * 4096
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertAmountToSeconds(amount: number): number {
|
export function convertAmountToSeconds(amount: number, pricePerBlock: number): number {
|
||||||
return amount / 10 / 1
|
// TODO: blocktime should come directly from the blockchain as it may differ between different networks
|
||||||
|
const blockTime = 5 // On mainnet there is 5 seconds between blocks
|
||||||
|
|
||||||
|
// See https://github.com/ethersphere/bee/blob/66f079930d739182c4c79eb6008784afeeba1096/pkg/debugapi/postage.go#L410-L413
|
||||||
|
return (amount * blockTime) / pricePerBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateStampPrice(depth: number, amount: number, currentPrice: NumberString): number {
|
export function calculateStampPrice(depth: number, amount: bigint): Token {
|
||||||
const price = parseInt(currentPrice, 10)
|
// See https://github.com/ethersphere/bee/blob/66f079930d739182c4c79eb6008784afeeba1096/pkg/debugapi/postage.go#L410-L413
|
||||||
|
return new Token(amount * BigInt(2 ** depth)) // FIXME: the 2 ** depth should be performed on bigint already
|
||||||
return (amount * 2 ** (depth - 16) * price) / 1e16
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shortenText(text: string, length = 20, separator = '[…]'): string {
|
export function shortenText(text: string, length = 20, separator = '[…]'): string {
|
||||||
|
|||||||
Reference in New Issue
Block a user