/ [USD|ETH]"" pairs. For example: "UNI / USD"
- // addresses are not available
- const isTokenSupported = function (address) {
- // vesper is registered as "Vesper Finance TVL" - see https://docs.chain.link/docs/ethereum-addresses/#Ethereum%20Mainnet
- const symbol = findToken(address, 1)?.symbol.toLowerCase()
- if (!symbol) {
- return false
- }
- const name = symbol === 'vsp' ? 'vesper' : symbol
- return tokens.some(({ pair }) => pair.toLowerCase().startsWith(name))
- }
-
- const streamingTime =
- timeUtils.yearsToSeconds(years) +
- timeUtils.daysToSeconds(days) +
- timeUtils.hoursToSeconds(hours)
- const canSubmit =
- active &&
- isAddress(payee) &&
- account !== payee &&
- ZERO_ADDRESS !== payee &&
- usdAmount.length > 0 &&
- !isNaN(Number.parseInt(usdAmount)) &&
- new Big(usdAmount).gt('0') &&
- isAddress(tokenInput.value) &&
- streamingTime > 0 &&
- isTokenSupported(tokenInput.value) &&
- !isCreating
-
- const submit = function (e) {
- e.preventDefault()
- if (!canSubmit) {
- return
- }
- setIsCreating(true)
- const now = Math.floor(new Date().getTime() / 1000)
- const endTime = now + streamingTime
- const { emitter } = paymentStreamsLib.createStream(
- payee,
- new Big(toUnit(usdAmount, 18)).toFixed(0),
- tokenInput.value,
- endTime
- )
-
- emitter
- .on('transactions', function (transactions) {
- addTransactionStatus({
- expectedFee: fromUnit(transactions.expectedFee),
- operation: 'add-stream',
- opId: now,
- suffixes: transactions.suffixes,
- transactionStatus: 'created'
- })
- transactions.suffixes.forEach(function (suffix, i) {
- emitter.on(`transactionHash-${suffix}`, function (transactionHash) {
- addTransactionStatus({
- opId: now,
- transactionStatus: 'in-progress',
- [`transactionHash-${i}`]: transactionHash,
- [`transactionStatus-${i}`]: 'waiting-to-be-mined'
- })
- })
- emitter.on(`receipt-${suffix}`, function ({ receipt }) {
- addTransactionStatus({
- currentTransaction: i + 1,
- opId: now,
- [`transactionHash-${i}`]: receipt.transactionHash,
- [`transactionStatus-${i}`]: receipt.status
- ? 'confirmed'
- : 'canceled'
- })
- })
- })
- })
- .on('result', function ({ fees, status }) {
- addTransactionStatus({
- actualFee: fromUnit(fees),
- opId: now,
- transactionStatus: status ? 'confirmed' : 'canceled'
- })
- setIsCreating(false)
- mutate()
- router.push('/payment-streams')
- })
- .on('error', function (err) {
- setIsCreating(false)
- addTransactionStatus({
- message: err.message,
- opId: now,
- transactionStatus: 'error'
- })
- })
- }
-
- let captionColor = tokenInput.captionColor
- let tokenInputCaption = tokenInput.caption
- if (isAddress(tokenInput.value) && !isTokenSupported(tokenInput.value)) {
- captionColor = 'text-red-600'
- tokenInputCaption = t('token-not-approved-for-streams')
- }
-
- return (
-
- )
-}
-
-export default CreateStream
diff --git a/site/components/payment-streams/EditStream.js b/site/components/payment-streams/EditStream.js
deleted file mode 100644
index 7575c7f..0000000
--- a/site/components/payment-streams/EditStream.js
+++ /dev/null
@@ -1,313 +0,0 @@
-import { useWeb3React } from '@web3-react/core'
-import Big from 'big.js'
-import { useRouter } from 'next/router'
-import { useTranslations } from 'next-intl'
-import { useContext, useEffect, useState, useMemo } from 'react'
-import { isAddress } from 'web3-utils'
-
-import { useStreams } from '../../hooks/useStreams'
-import { useRouter as useIntlRouter } from '../../navigation'
-import { fromUnit, toUnit } from '../../utils'
-import { updateStreamInfo } from '../../utils/streams'
-import * as timeUtils from '../../utils/time'
-import Button from '../Button'
-import TransactionsContext from '../context/Transactions'
-import Input from '../Input'
-
-import EndTime from './EndTime'
-import { PaymentStreamsLibContext } from './PaymentStreamsLib'
-
-const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
-
-const EditRate = function ({ stream }) {
- const { active, account } = useWeb3React()
- const {
- query: { id: streamId }
- } = useRouter()
- const router = useIntlRouter()
- const t = useTranslations('payment-streams-util')
- const tCommon = useTranslations()
-
- const paymentStreamsLib = useContext(PaymentStreamsLibContext)
- const { addTransactionStatus } = useContext(TransactionsContext)
-
- const { mutate } = useStreams()
- const [newUsdAmount, setNewUsdAmount] = useState('')
- const [years, setYears] = useState(0)
- const [days, setDays] = useState(0)
- const [hours, setHours] = useState(0)
-
- const originalUsdAmount = stream?.usdAmount
- const streamingTime =
- timeUtils.yearsToSeconds(years) +
- timeUtils.daysToSeconds(days) +
- timeUtils.hoursToSeconds(hours)
-
- useEffect(
- function () {
- if (newUsdAmount || !originalUsdAmount) {
- return
- }
- setNewUsdAmount(fromUnit(originalUsdAmount, 18))
- },
- [newUsdAmount, setNewUsdAmount, originalUsdAmount]
- )
-
- const canSubmit =
- active &&
- newUsdAmount.length > 0 &&
- !isNaN(newUsdAmount) &&
- Big(newUsdAmount).gt('0') &&
- streamingTime > 0
-
- const updateFundRate = function (e) {
- e.preventDefault()
- const now = Math.floor(new Date().getTime() / 1000)
- const newEndTime = now + streamingTime
- const { emitter } = paymentStreamsLib.updateFundingRate(
- streamId,
- Big(toUnit(newUsdAmount, 18)).toFixed(0),
- newEndTime
- )
-
- emitter
- .on('transactions', function (transactions) {
- addTransactionStatus({
- expectedFee: fromUnit(transactions.expectedFee),
- operation: 'update-funding-rate',
- opId: now,
- suffixes: transactions.suffixes,
- transactionStatus: 'created'
- })
- transactions.suffixes.forEach(function (suffix, i) {
- emitter.on(`transactionHash-${suffix}`, function (transactionHash) {
- addTransactionStatus({
- opId: now,
- transactionStatus: 'in-progress',
- [`transactionHash-${i}`]: transactionHash,
- [`transactionStatus-${i}`]: 'waiting-to-be-mined'
- })
- })
- emitter.on(`receipt-${suffix}`, function ({ receipt }) {
- addTransactionStatus({
- currentTransaction: i + 1,
- opId: now,
- [`transactionHash-${i}`]: receipt.transactionHash,
- [`transactionStatus-${i}`]: receipt.status
- ? 'confirmed'
- : 'canceled'
- })
- })
- })
- })
- .on('result', function ({ fees, status }) {
- addTransactionStatus({
- actualFee: fromUnit(fees),
- opId: now,
- transactionStatus: status ? 'confirmed' : 'canceled'
- })
- updateStreamInfo({
- account,
- id: streamId,
- lib: paymentStreamsLib,
- streamsView: 'outgoing'
- })
- .then(() => mutate())
- .catch(console.error)
- router.push('/payment-streams')
- })
- .on('error', function (err) {
- addTransactionStatus({
- message: err.message,
- opId: now,
- transactionStatus: 'error'
- })
- })
- }
-
- return (
-
- )
-}
-
-const EditFundingAddress = function ({ stream }) {
- const { active, account } = useWeb3React()
- const t = useTranslations('payment-streams-util')
- const { addTransactionStatus } = useContext(TransactionsContext)
- const paymentStreamsLib = useContext(PaymentStreamsLibContext)
- const [newFundingAddress, setNewFundingAddress] = useState('')
- const {
- query: { id: streamId }
- } = useRouter()
- const router = useIntlRouter()
- const { mutate } = useStreams()
-
- const originalFundingAddress = stream.fundingAddress
- const { payee } = stream
-
- useEffect(
- function () {
- if (newFundingAddress || !originalFundingAddress) {
- return
- }
- setNewFundingAddress(originalFundingAddress)
- },
- [newFundingAddress, setNewFundingAddress, originalFundingAddress]
- )
-
- const updateFundAddress = function (e) {
- e.preventDefault()
- const now = Math.floor(new Date().getTime() / 1000)
- const { emitter } = paymentStreamsLib.updateFundingAddress(
- streamId,
- newFundingAddress
- )
-
- emitter
- .on('transactions', function (transactions) {
- addTransactionStatus({
- expectedFee: fromUnit(transactions.expectedFee),
- operation: 'update-funding-address',
- opId: now,
- suffixes: transactions.suffixes,
- transactionStatus: 'created'
- })
- transactions.suffixes.forEach(function (suffix, i) {
- emitter.on(`transactionHash-${suffix}`, function (transactionHash) {
- addTransactionStatus({
- opId: now,
- transactionStatus: 'in-progress',
- [`transactionHash-${i}`]: transactionHash,
- [`transactionStatus-${i}`]: 'waiting-to-be-mined'
- })
- })
- emitter.on(`receipt-${suffix}`, function ({ receipt }) {
- addTransactionStatus({
- currentTransaction: i + 1,
- opId: now,
- [`transactionHash-${i}`]: receipt.transactionHash,
- [`transactionStatus-${i}`]: receipt.status
- ? 'confirmed'
- : 'canceled'
- })
- })
- })
- })
- .on('result', function ({ fees, status }) {
- addTransactionStatus({
- actualFee: fromUnit(fees),
- opId: now,
- transactionStatus: status ? 'confirmed' : 'canceled'
- })
- // eslint-disable-next-line promise/catch-or-return
- updateStreamInfo({
- account,
- id: streamId,
- lib: paymentStreamsLib,
- streamsView: 'outgoing'
- }).then(() => mutate())
- router.push('/payment-streams')
- })
- .on('error', function (err) {
- addTransactionStatus({
- message: err.message,
- opId: now,
- transactionStatus: 'error'
- })
- })
- }
-
- const canSubmit =
- active &&
- isAddress(newFundingAddress) &&
- originalFundingAddress !== newFundingAddress &&
- newFundingAddress !== ZERO_ADDRESS &&
- newFundingAddress !== payee
- return (
-
- )
-}
-
-const EditStream = function () {
- const {
- query: { id: streamId }
- } = useRouter()
- const router = useIntlRouter()
- const { active } = useWeb3React()
- const t = useTranslations('payment-streams-util')
- const { streams = { outgoing: [] }, isLoading } = useStreams()
-
- const stream = useMemo(
- () => streams.outgoing.find(s => s.id === streamId),
- [streamId, streams.outgoing]
- )
-
- useEffect(
- function redirectToPaymentStreams() {
- if (!active || !stream) {
- router.push('/payment-streams')
- }
- },
- [active, router, stream]
- )
-
- if (isLoading) {
- return {t('loading-stream', { streamId })}
- }
-
- return (
- <>
-
-
- {t('update-rate')}
-
-
-
-
-
- {t('update-funding-address')}
-
-
-
- >
- )
-}
-
-export default EditStream
diff --git a/site/components/payment-streams/EndTime.js b/site/components/payment-streams/EndTime.js
deleted file mode 100644
index 5c22121..0000000
--- a/site/components/payment-streams/EndTime.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import { useTranslations } from 'next-intl'
-
-import { daysToSeconds, hoursToSeconds, yearsToSeconds } from '../../utils/time'
-import { InputTitle } from '../Input'
-const EndTime = function ({
- onYearsChange,
- onDaysChange,
- onHoursChange,
- years,
- days,
- hours
-}) {
- const t = useTranslations('payment-streams-util')
- const now = new Date().getTime()
- const deltaDate =
- (hoursToSeconds(hours) + daysToSeconds(days) + yearsToSeconds(years)) * 1000
- const endDate = new Date(now + deltaDate)
- const dateFormatter = new Intl.DateTimeFormat('default', {
- day: 'numeric',
- hour: 'numeric',
- minute: 'numeric',
- month: 'numeric',
- year: 'numeric'
- })
- return (
-
- {t('for-how-long')}
-
- onYearsChange(parseInt(e.target.value, 10))}
- value={years}
- >
- {[...Array(11).keys()].map(year => (
-
- {t('count-years', { count: year })}
-
- ))}
-
- onDaysChange(parseInt(e.target.value, 10))}
- value={days}
- >
- {[...Array(365).keys()].map(day => (
-
- {t('count-days', { count: day })}
-
- ))}
-
- onHoursChange(parseInt(e.target.value, 10))}
- value={hours}
- >
- {[...Array(24).keys()].map(hour => (
-
- {t('count-hours', { count: hour })}
-
- ))}
-
-
-
- {t('stream-ends-in', { date: dateFormatter.format(endDate) })}
-
-
- )
-}
-
-export default EndTime
diff --git a/site/components/payment-streams/PaymentStreamsLib.js b/site/components/payment-streams/PaymentStreamsLib.js
deleted file mode 100644
index c346061..0000000
--- a/site/components/payment-streams/PaymentStreamsLib.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { useWeb3React } from '@web3-react/core'
-import createPaymentStreams from 'pf-payment-streams'
-import { createContext, useEffect, useMemo } from 'react'
-
-import utilsConfig from '../../utils/utilsConfig.json'
-
-export const PaymentStreamsLibContext = createContext({})
-const PaymentStreamsLibContextProvider = function ({ children }) {
- const { account, active, library, chainId } = useWeb3React()
- const lib = useMemo(
- () =>
- active && library
- ? createPaymentStreams(library, {
- from: account,
- ...utilsConfig[chainId].paymentStreams
- })
- : undefined,
- [active, library, account, chainId]
- )
-
- useEffect(
- function () {
- window.paymentStreamsLib = lib
- },
- [lib]
- )
-
- return (
-
- {children}
-
- )
-}
-
-export default PaymentStreamsLibContextProvider
diff --git a/site/components/payment-streams/StreamsTable.js b/site/components/payment-streams/StreamsTable.js
deleted file mode 100644
index 442a09b..0000000
--- a/site/components/payment-streams/StreamsTable.js
+++ /dev/null
@@ -1,486 +0,0 @@
-import { useWeb3React } from '@web3-react/core'
-import Big from 'big.js'
-import { useTranslations } from 'next-intl'
-import { useContext, useEffect, useState } from 'react'
-
-import Button from '../../components/Button'
-import WithTooltip from '../../components/WithTooltip'
-import { useStreams } from '../../hooks/useStreams'
-import { Link, useRouter } from '../../navigation'
-import { bigToCrypto, fromUnit } from '../../utils'
-import { updateStreamInfo } from '../../utils/streams'
-import TransactionsContext from '../context/Transactions'
-import { ExplorerLink } from '../ExplorerLink'
-import SvgContainer from '../svg/SvgContainer'
-import Tabs from '../Tabs'
-
-import { PaymentStreamsLibContext } from './PaymentStreamsLib'
-
-const StreamsTable = function () {
- const { active, account, chainId } = useWeb3React()
- const t = useTranslations('payment-streams-util')
- const router = useRouter()
- const connected = !!(active && account)
- const paymentStreamsLib = useContext(PaymentStreamsLibContext)
- const { addTransactionStatus, currentTransactions } =
- useContext(TransactionsContext)
- const [streamsView, setStreamsView] = useState('incoming')
- const [claimingId, setClaimingId] = useState(undefined)
- const {
- streams = { incoming: [], outgoing: [] },
- futureStreamValues,
- isLoading,
- mutate
- } = useStreams()
-
- const futureStreamClaimable = futureStreamValues?.[streamsView]?.find(
- futureStream => futureStream.id === claimingId
- )?.tokenClaimable
- const claimingStream = streams[streamsView].find(s => s.id === claimingId)
-
- // This effect runs only while the tx modal is shown when claiming. It will update the
- // estimation of tokens to be received once per second.
- useEffect(
- function () {
- const lastTransactionStatus =
- currentTransactions[currentTransactions.length - 1]
- if (!claimingStream || !lastTransactionStatus) {
- return
- }
- const newClaimableValue = bigToCrypto(
- fromUnit(futureStreamClaimable, claimingStream.token.decimals)
- )
- // assumption here: You can only stream one token
- if (
- Big(newClaimableValue).eq(Big(lastTransactionStatus.received[0].value))
- ) {
- return
- }
- // take the last transaction status, and clone it, but using the new updated estimation.
- addTransactionStatus({
- ...lastTransactionStatus,
- received: [
- {
- symbol: claimingStream.token.symbol,
- value: newClaimableValue
- }
- ]
- })
- },
- [
- claimingStream,
- addTransactionStatus,
- currentTransactions,
- futureStreamClaimable
- ]
- )
-
- if (!connected) {
- return {t('connect-your-wallet')}
- }
-
- if (isLoading) {
- return {t('loading-streams')}
- }
-
- const totalStreams = streams.incoming.length + streams.outgoing.length
- if (totalStreams.length === 0) {
- return {t('no-streams')}
- }
-
- const isIncomingDisabled = streamsView === 'incoming'
- const isOutgoingDisabled = streamsView === 'outgoing'
-
- const streamsList = streams[streamsView]
-
- const pause = function (id) {
- const { emitter } = paymentStreamsLib.pauseStream(id)
- const now = Math.floor(new Date().getTime() / 1000)
- emitter
- .on('transactions', function (transactions) {
- addTransactionStatus({
- expectedFee: fromUnit(transactions.expectedFee),
- operation: 'pause-stream',
- opId: now,
- suffixes: transactions.suffixes,
- transactionStatus: 'created'
- })
- transactions.suffixes.forEach(function (suffix, i) {
- emitter.on(`transactionHash-${suffix}`, function (transactionHash) {
- addTransactionStatus({
- opId: now,
- transactionStatus: 'in-progress',
- [`transactionHash-${i}`]: transactionHash,
- [`transactionStatus-${i}`]: 'waiting-to-be-mined'
- })
- })
- emitter.on(`receipt-${suffix}`, function ({ receipt }) {
- addTransactionStatus({
- currentTransaction: i + 1,
- opId: now,
- [`transactionHash-${i}`]: receipt.transactionHash,
- [`transactionStatus-${i}`]: receipt.status
- ? 'confirmed'
- : 'canceled'
- })
- })
- })
- })
- .on('result', function ({ fees, status }) {
- addTransactionStatus({
- actualFee: fromUnit(fees),
- opId: now,
- transactionStatus: status ? 'confirmed' : 'canceled'
- })
- // eslint-disable-next-line promise/catch-or-return
- updateStreamInfo({
- account,
- id,
- lib: paymentStreamsLib,
- streamsView
- }).then(() => mutate())
- })
- .on('error', function (err) {
- addTransactionStatus({
- message: err.message,
- opId: now,
- transactionStatus: 'error'
- })
- })
- }
-
- const resume = function (id) {
- const now = Math.floor(new Date().getTime() / 1000)
- const { emitter } = paymentStreamsLib.resumeStream(id)
- emitter
- .on('transactions', function (transactions) {
- addTransactionStatus({
- expectedFee: fromUnit(transactions.expectedFee),
- operation: 'unpause-stream',
- opId: now,
- suffixes: transactions.suffixes,
- transactionStatus: 'created'
- })
- transactions.suffixes.forEach(function (suffix, i) {
- emitter.on(`transactionHash-${suffix}`, function (transactionHash) {
- addTransactionStatus({
- opId: now,
- transactionStatus: 'in-progress',
- [`transactionHash-${i}`]: transactionHash,
- [`transactionStatus-${i}`]: 'waiting-to-be-mined'
- })
- })
- emitter.on(`receipt-${suffix}`, function ({ receipt }) {
- addTransactionStatus({
- currentTransaction: i + 1,
- opId: now,
- [`transactionHash-${i}`]: receipt.transactionHash,
- [`transactionStatus-${i}`]: receipt.status
- ? 'confirmed'
- : 'canceled'
- })
- })
- })
- })
- .on('result', function ({ fees, status }) {
- addTransactionStatus({
- actualFee: fromUnit(fees),
- opId: now,
- transactionStatus: status ? 'confirmed' : 'canceled'
- })
- // eslint-disable-next-line promise/catch-or-return
- updateStreamInfo({
- account,
- id,
- lib: paymentStreamsLib,
- streamsView
- }).then(() => mutate())
- })
- .on('error', function (err) {
- addTransactionStatus({
- message: err.message,
- opId: now,
- transactionStatus: 'error'
- })
- })
- }
-
- const claim = function (id) {
- const stream = streamsList.find(s => s.id === id)
- if (stream.paused) {
- return
- }
- const now = Math.floor(new Date().getTime() / 1000)
- const { emitter } = paymentStreamsLib.claim(id)
-
- emitter
- .on('transactions', function (transactions) {
- addTransactionStatus({
- expectedFee: fromUnit(transactions.expectedFee),
- operation: 'claim',
- opId: now,
- received: [
- {
- symbol: stream.token.symbol,
- value: bigToCrypto(
- fromUnit(stream.tokenClaimable, stream.token.decimals)
- )
- }
- ],
- suffixes: transactions.suffixes,
- transactionStatus: 'created'
- })
- transactions.suffixes.forEach(function (suffix, i) {
- emitter.on(`transactionHash-${suffix}`, function (transactionHash) {
- addTransactionStatus({
- opId: now,
- transactionStatus: 'in-progress',
- [`transactionHash-${i}`]: transactionHash,
- [`transactionStatus-${i}`]: 'waiting-to-be-mined'
- })
- })
- emitter.on(`receipt-${suffix}`, function ({ receipt }) {
- addTransactionStatus({
- currentTransaction: i + 1,
- opId: now,
- [`transactionHash-${i}`]: receipt.transactionHash,
- [`transactionStatus-${i}`]: receipt.status
- ? 'confirmed'
- : 'canceled'
- })
- })
- })
- })
- .on('result', function ({ result, fees, status }) {
- setClaimingId(undefined)
- addTransactionStatus({
- actualFee: fromUnit(fees),
- opId: now,
- received: status
- ? [
- {
- symbol: stream.token.symbol,
- value: bigToCrypto(
- fromUnit(result.tokenAmount, stream.token.decimals)
- )
- }
- ]
- : [],
- transactionStatus: status ? 'confirmed' : 'canceled'
- })
- // eslint-disable-next-line promise/catch-or-return
- updateStreamInfo({
- account,
- id,
- lib: paymentStreamsLib,
- streamsView
- }).then(() => mutate())
- })
- .on('error', function (err) {
- setClaimingId(undefined)
- addTransactionStatus({
- message: err.message,
- opId: now,
- transactionStatus: 'error'
- })
- })
- setClaimingId(id)
- }
-
- const canClaim = function (id) {
- const stream = streamsList.find(s => s.id === id)
- return (
- !stream.paused &&
- Big(stream.tokenBalance).gt(stream.tokenClaimable) &&
- Big(stream.tokenAllowance).gt(stream.tokenClaimable)
- )
- }
-
- const getClaimTip = function (id) {
- const stream = streamsList.find(s => s.id === id)
- if (stream.paused) {
- return t('stream-is-paused')
- }
- if (Big(stream.tokenClaimable).gt(Big(stream.tokenBalance))) {
- return t('not-enough-funds-in-stream')
- }
- return t('not-enough-allowance-in-stream')
- }
-
- return (
-
-
- {t('create-stream')}
-
- setStreamsView('incoming'),
- selected: isIncomingDisabled
- },
- {
- label: t('outgoing-streams'),
- onClick: () => setStreamsView('outgoing'),
- selected: isOutgoingDisabled
- }
- ]}
- />
- {streamsList.length === 0 && {t('no-streams')}
}
- {streamsList.length > 0 && (
-
-
-
- {t('status')}
-
- {t(streamsView === 'incoming' ? 'payer' : 'payee')}
-
- {streamsView === 'outgoing' && (
- {t('funding-address')}
- )}
- {/* {t('start-date')} */}
- {t('end-date')}
- {t('token')}
- {t('usd-amount')}
- {t('claimed')}
- {t('claimable')}
- {t('actions')}
-
-
-
- {streamsList.map(function ({
- id,
- payee,
- payer,
- fundingAddress,
- startTime,
- secs,
- token,
- claimed,
- claimable,
- usdAmount,
- paused
- }) {
- const endDate = new Date(
- (parseInt(startTime, 10) + parseInt(secs, 10)) * 1000
- )
- const now = new Date().getTime()
- const dateFormatter = new Intl.DateTimeFormat('default', {
- day: 'numeric',
- hour: 'numeric',
- minute: 'numeric',
- month: 'numeric',
- year: 'numeric'
- })
- const futureValue = futureStreamValues?.[streamsView]?.find(
- futureStream => futureStream.id === id
- )
- const isFinished = endDate.getTime() < now
- const status = isFinished
- ? t('finished')
- : paused
- ? t('paused')
- : t('streaming')
- return (
-
-
- {status}
-
-
-
-
- {streamsView === 'outgoing' && (
-
-
-
- )}
- {/* {dateFormatter.format(startDate)} */}
- {dateFormatter.format(endDate)}
- {token.symbol}
-
- $ {fromUnit(usdAmount ?? 0, 18, 4)}
-
-
- $ {fromUnit(claimed ?? 0, 18, 4)}
-
-
- ${' '}
- {fromUnit(
- isFinished ? claimable : futureValue?.claimable ?? 0,
- 18,
- 4
- )}
-
-
- {streamsView === 'outgoing' && (
- <>
- {paused && (
- resume(id)}
- width="w-28"
- >
- {t('resume')}
-
- )}
- {!paused && (
- pause(id)}
- width="w-28"
- >
- {t('pause')}
-
- )}
-
-
- {t('edit')}
-
-
- >
- )}
- {streamsView === 'incoming' && (
-
- claim(id)}
- width="w-28"
- >
- {t('claim')}
- {canClaim(id) ? null : (
-
- )}
-
-
- )}
-
-
- )
- })}
-
-
- )}
-
- )
-}
-
-export default StreamsTable
diff --git a/site/messages/zh.json b/site/messages/zh.json
index 5803c02..4ae9d5f 100644
--- a/site/messages/zh.json
+++ b/site/messages/zh.json
@@ -100,6 +100,7 @@
"total": "全部的",
"transaction-hash": "交易哈希",
"transaction": "交易",
+ "tools": "工具",
"unlimited": "无限",
"update-funding-address": "Update Funding Address",
"update-funding-rate": "Update Funding Rate",
diff --git a/site/package.json b/site/package.json
index 6157813..9b61a76 100644
--- a/site/package.json
+++ b/site/package.json
@@ -17,25 +17,19 @@
"autoprefixer": "10.4.0",
"big.js": "6.1.1",
"chain-list": "1.0.0",
- "dp-auctions-lib": "1.0.0",
"erc-20-lib": "1.0.0",
"eslint-config-next": "14.1.3",
"lodash.debounce": "4.0.8",
- "lodash.orderby": "4.6.0",
- "luxon": "2.1.1",
"next": "14.1.3",
"next-intl": "3.9.4",
"next-secure-headers": "2.2.0",
"patch-package": "8.0.0",
- "pf-payment-streams": "1.0.0",
"pure-finance-lib": "1.0.0",
"react": "18.2.0",
"react-dom": "18.2.0",
- "react-tooltip": "4.2.21",
"swr": "2.2.5",
"tailwindcss": "2.2.19",
"token-list": "1.0.0",
- "victory": "36.9.2",
"wallet-watch-asset": "1.0.0",
"web3": "1.3.6",
"web3-utils": "1.3.6"
diff --git a/site/pages/[locale]/dp-auctions/auctions/index.js b/site/pages/[locale]/dp-auctions/auctions/index.js
deleted file mode 100644
index 0928b56..0000000
--- a/site/pages/[locale]/dp-auctions/auctions/index.js
+++ /dev/null
@@ -1,439 +0,0 @@
-import { useWeb3React } from '@web3-react/core'
-import { useRouter } from 'next/router'
-import { useTranslations } from 'next-intl'
-import { useContext, useEffect, useState } from 'react'
-import useSWR from 'swr'
-import { VictoryAxis, VictoryChart, VictoryLine, VictoryScatter } from 'victory'
-import watchAsset from 'wallet-watch-asset'
-
-import Button from '../../../../components/Button'
-import TransactionsContext from '../../../../components/context/Transactions'
-import { DPAuctionsContext } from '../../../../components/DPAuctionsContext'
-import { ExplorerLink } from '../../../../components/ExplorerLink'
-import DPAuctionsLayout from '../../../../components/layout/DPAuctionsLayout'
-import TokenAmount from '../../../../components/TokenAmount'
-import Transactions from '../../../../components/Transactions'
-import { fromUnit } from '../../../../utils'
-
-const ETH_BLOCK_TIME = 13 // Average block time in Ethereum
-
-const numberFromUnit = (number, decimals) =>
- Number.parseFloat(fromUnit(number, decimals))
-
-// The price chart shows the evolution of the price and the current or ending
-// point of the auction, depending on the state.
-//
-// There are 6 possible states:
-//
-// [running, won, stopped] x [descending, floored]
-//
-// When still descending, the chart looks like this:
-//
-// \
-// .
-// \
-//
-// When floored, the chart looks like this:
-//
-// \_.
-//
-// In addition, when running, the current state is shown as a circle while when
-// stopped or won is shown as a full disc.
-const DPAuctionPriceChart = function ({ auction }) {
- const t = useTranslations()
-
- const startPoint = {
- block: auction.startBlock,
- price: auction.ceiling
- }
- const endPoint = {
- block: auction.endBlock,
- price: auction.floor
- }
- const currentPoint = {
- block: auction.currentBlock,
- price: auction.currentPrice
- }
- const winningPoint = {
- block: auction.winningBlock,
- price: auction.winningPrice
- }
- const stoppingPoint = {
- block: auction.stoppingBlock,
- price: auction.stoppingPrice
- }
-
- const basePlotData =
- auction.status === 'running'
- ? [startPoint, currentPoint, endPoint]
- : auction.status === 'stopped'
- ? [startPoint, stoppingPoint, endPoint]
- : auction.status === 'won'
- ? [startPoint, winningPoint, endPoint]
- : [startPoint, currentPoint, endPoint]
-
- const plotData = basePlotData
- .map(({ block, price }) => ({
- block: Number.parseInt(block),
- price: numberFromUnit(price, auction.paymentToken.decimals)
- }))
- .sort((a, b) => a.block - b.block)
-
- // Calculating the x-axis ticks manually prevents x-labels to overlap, to
- // repeat or to show decimal block numbers. And since the auctions can be live
- // for many blocks or just a few, black math magic is required.
- //
- // First, start by defining the start, end blocks and the domain length.
- const xStart = plotData[0].block
- const xEnd = plotData[2].block
- const xLen = xEnd - xStart
- // Then split the domain length in 3 to have at most 4 ticks. Since the chart
- // is relatively small and the block numbers are large, having just a few
- // ticks is ok.
- // Finally force the steps to be a whole number and force it to be at least 1.
- const xStep = Math.max(Math.floor(xLen / 3), 1)
- // Once the steps are defined, calculate how many ticks fit in the domain. Sum
- // one to add the "ending" tick. Otherwise only the start and "inner" ticks
- // will be shown.
- const xTicks = Math.floor(xLen / xStep) + 1
- // Finally create an array of that length whose values will be one step
- // appart. To get a better look, start from the end, subtract one step at a
- // time and then revert the array. That way the end tick will always match the
- // end block.
- const xTickValues = new Array(Math.max(xTicks, 1))
- .fill(null)
- .map((_, i) => xEnd - xStep * i)
- .reverse()
-
- return (
-
-
- tick.toString()}
- tickValues={xTickValues}
- />
-
-
-
-
-
-
- )
-}
-
-const DPAuctionContentsRow = ({ paymentToken, token }) => (
-
-
-
-
-
-
-
-
-)
-
-const DPAuctionTokens = function ({ auction }) {
- const t = useTranslations()
-
- return (
-
-
-
- {t('token')}
- {t('value')}
-
-
-
- {auction.tokens.map(token => (
-
- ))}
-
-
-
- {t('total')}
-
-
-
-
-
-
- )
-}
-
-const DPAuctionBuyControl = function ({ auction }) {
- const t = useTranslations()
- const { account, active } = useWeb3React()
- const { addTransactionStatus } = useContext(TransactionsContext)
- const dpa = useContext(DPAuctionsContext)
-
- const [canBid, setCanBid] = useState(false)
- useEffect(
- function () {
- if (!active || !dpa || account === auction.payee) {
- setCanBid(false)
- return
- }
- // eslint-disable-next-line promise/catch-or-return
- dpa
- .canBidAuction(account, auction.id)
- .catch(function () {
- console.warn('Could not check if user can bid')
- return false
- })
- .then(setCanBid)
- },
- [account, auction, active, dpa]
- )
-
- const handleBuyAuctionClick = function () {
- const opId = Date.now()
-
- const { emitter } = dpa.bidAuction(auction.id, { from: account })
-
- emitter
- .on('transactions', function (transactions) {
- addTransactionStatus({
- expectedFee: fromUnit(transactions.expectedFee),
- operation: 'bid',
- opId,
- received: auction.tokens.map(token => ({
- symbol: token.symbol,
- value: fromUnit(token.amount, token.decimals)
- })),
- sent: fromUnit(auction.currentPrice, auction.paymentToken.decimals),
- sentSymbol: auction.paymentToken.symbol,
- suffixes: transactions.suffixes,
- transactionStatus: 'created'
- })
- transactions.suffixes.forEach(function (suffix, i) {
- emitter.on(`transactionHash-${suffix}`, function (transactionHash) {
- addTransactionStatus({
- opId,
- transactionStatus: 'in-progress',
- [`transactionHash-${i}`]: transactionHash,
- [`transactionStatus-${i}`]: 'waiting-to-be-mined'
- })
- })
- emitter.on(`receipt-${suffix}`, function ({ receipt }) {
- addTransactionStatus({
- currentTransaction: i + 1,
- opId,
- [`transactionHash-${i}`]: receipt.transactionHash,
- [`transactionStatus-${i}`]: receipt.status
- ? 'confirmed'
- : 'canceled'
- })
- })
- })
- })
- .on('result', function ({ fees, status, price }) {
- addTransactionStatus({
- actualFee: fromUnit(fees),
- opId,
- sent: fromUnit(price, auction.paymentToken.decimals),
- transactionStatus: status ? 'confirmed' : 'canceled'
- })
- auction.tokens.forEach(function (token) {
- watchAsset({ account, token })
- })
- })
- .on('error', function (err) {
- addTransactionStatus({
- message: err.message,
- opId,
- transactionStatus: 'error'
- })
- })
- }
-
- return (
-
- {!auction.stopped ? (
- <>
-
-
{t('current-price')}:
-
-
-
-
- (
- {(
- (100n * BigInt(auction.currentPrice)) /
- BigInt(auction.currentValue)
- ).toString()}
- % {t('of-value')})
-
-
-
-
- {t('buy-auction')}
-
-
- >
- ) : (
-
{t('auction-ended')}
- )}
-
- )
-}
-
-// This component shows the end status of the auction.
-const DPAuctionEndStatus = function ({ auction }) {
- const { chainId } = useWeb3React()
- const t = useTranslations()
-
- return auction.status === 'won' ? (
- <>
-
- {t('won-by')}:{' '}
-
-
-
- {t('winning-price')}:{' '}
-
-
- >
- ) : auction.status === 'stopped' ? (
- {t('auction-stopped')}
- ) : null
-}
-
-// This component renders the details view of an auction.
-const DPAuction = function ({ auction }) {
- const { chainId } = useWeb3React()
- const t = useTranslations()
-
- if (!auction) {
- return null
- }
- return (
- <>
-
-
-
-
-
-
- {t('seller')}:{' '}
-
-
-
-
-
-
- >
- )
-}
-
-// This is the main app component. It holds all the views like the auctions
-// list, the auction detail, etc.
-export default function DPAuctionsDetails({ initialData, error }) {
- const t = useTranslations()
- const {
- query: { id: auctionId = 0 }
- } = useRouter()
- const dpa = useContext(DPAuctionsContext)
-
- const { data: auction } = useSWR(
- `dp-auctions-${auctionId}`,
- () =>
- dpa.getAuction(auctionId, true).catch(function (err) {
- console.warn('Could not get auction', auctionId, err.message)
- return null
- }),
- { fallbackData: initialData, refreshInterval: ETH_BLOCK_TIME * 1000 }
- )
-
- return (
-
-
-
- {t('auction')} {auctionId}
-
- {auction ? (
-
- ) : (
- <>
-
{t('error-getting-auction')}:
-
{error}
- >
- )}
-
-
-
- )
-}
-
-export { getStaticProps, getStaticPaths } from '../../../../utils/staticProps'
diff --git a/site/pages/[locale]/dp-auctions/collections/index.js b/site/pages/[locale]/dp-auctions/collections/index.js
deleted file mode 100644
index 35b956a..0000000
--- a/site/pages/[locale]/dp-auctions/collections/index.js
+++ /dev/null
@@ -1,230 +0,0 @@
-import orderBy from 'lodash.orderby'
-import { DateTime } from 'luxon'
-import { useRouter } from 'next/router'
-import { useLocale, useTranslations } from 'next-intl'
-import { useContext, useState } from 'react'
-import useSWR from 'swr'
-
-import { DPAuctionsContext } from '../../../../components/DPAuctionsContext'
-import Dropdown from '../../../../components/Dropdown'
-import DPAuctionsLayout from '../../../../components/layout/DPAuctionsLayout'
-import UtilFormBox from '../../../../components/layout/UtilFormBox'
-import SvgContainer from '../../../../components/svg/SvgContainer'
-import TokenAmount from '../../../../components/TokenAmount'
-import { useUpdatingState } from '../../../../hooks/useUpdatingState'
-import { Link } from '../../../../navigation'
-
-const ETH_BLOCK_TIME = 13 // Average block time in Ethereum
-
-// This component renders an auction row. When clicked, the view changes to the
-// auction details page.
-//
-// The remaining time is shown in minutes. So every 10 seconds the remaining
-// time is re-calculated.
-const DPAuctionsRow = function ({ auction }) {
- const locale = useLocale()
- const t = useTranslations()
-
- const calcEndTime = () =>
- Date.now() +
- (auction.endBlock - auction.currentBlock) * ETH_BLOCK_TIME * 1000
- const endTime = useUpdatingState(calcEndTime, 10000, [auction.currentBlock]) // 10s
-
- return (
-
-
- {auction.id}
-
- {auction.tokens.map(token => (
-
-
-
- ))}
-
-
- {auction.status === 'won' || auction.status === 'stopped' ? (
- '-'
- ) : (
-
- )}
-
-
- {t(auction.status)}
- {auction.status === 'running' &&
- ` (${t('ends')} ${DateTime.fromMillis(endTime).toRelative({
- locale
- })})`}
-
-
-
- )
-}
-
-// This component renders the list of auctions.
-const DPAuctionsTable = function ({ auctions }) {
- const t = useTranslations()
- const [showEnded, setShowEnded] = useState(false)
-
- const sortedAuctions = orderBy(
- auctions.filter(auction => showEnded || !auction.stopped),
- ['endBlock', 'id'],
- ['asc', 'desc']
- )
-
- return (
- <>
- {sortedAuctions.length ? (
-
-
-
- {t('id')}
- {t('contains')}
- {t('price')}
- {t('status')}
-
-
-
- {sortedAuctions.map(auction => (
-
- ))}
-
-
- ) : (
- {t('no-auctions')}
- )}
- {auctions.length ? (
-
- setShowEnded(!showEnded)}
- type="checkbox"
- />
- {t('show-ended-auctions')}
-
- ) : null}
- >
- )
-}
-
-// To allow the Dropdown component to send open/close status and keep track of
-// what collection is selected, the selector component has to be created on the
-// fly keeping the selected collection in the closure.
-const createCollectionSelector = collectionId =>
- function CollectionSelector({ isOpen }) {
- const t = useTranslations()
-
- const rotate = isOpen ? 'transform rotate-180' : ''
- return (
-
- {t('collection', { collectionId })}
-
-
- )
- }
-
-// Use a Dropdown component to allow selecting another existing collection.
-const DPAuctionsCollectionSelector = function ({ count, collectionId }) {
- const t = useTranslations()
-
- const Selector = createCollectionSelector(collectionId)
-
- return (
-
-
-
- {new Array(count).fill(null).map((_, i) =>
- Number.parseInt(collectionId) === i ? (
-
- {t('collection', { collectionId: i })}
-
- ) : (
-
- {t('collection', { collectionId: i })}
-
- )
- )}
-
-
-
- )
-}
-
-// This is the main app component. It holds all the views like the auctions
-// list, the auction detail, etc.
-export default function DPAuctions({
- initialCount = 0,
- initialAuctions = [],
- error
-}) {
- const t = useTranslations()
- const {
- query: { id: collectionId = process.env.NEXT_PUBLIC_DEFAULT_COLLECTION_ID }
- } = useRouter()
-
- const dpa = useContext(DPAuctionsContext)
-
- // The amount of collections is managed by SWR. It is set to revalidate aprox.
- // every block (15 seconds).
- const { data: count } = useSWR(
- `dp-auctions-collections-count`,
- () =>
- dpa.getTotalCollections().catch(function (err) {
- console.warn('Could not get collection count', err.message)
- return ''
- }),
- { fallbackData: initialCount, refreshInterval: ETH_BLOCK_TIME * 1000 }
- )
-
- // The list of auctions in the collection is managed by SWR. It is set to
- // revalidate aprox. every block (15 seconds).
- const { data: auctions } = useSWR(
- `dp-auctions-collections-${collectionId}`,
- () =>
- dpa.getCollectionAuctions(collectionId).catch(function (err) {
- console.warn(
- 'Could not get auctions in collection',
- collectionId,
- err.message
- )
- return []
- }),
- { fallbackData: initialAuctions, refreshInterval: ETH_BLOCK_TIME * 1000 }
- )
-
- return (
-
-
-
-
- {error ? (
-
- {t('error-getting-auctions')}: {error}
-
- ) : (
-
- )}
-
-
-
- )
-}
-
-export { getStaticProps, getStaticPaths } from '../../../../utils/staticProps'
diff --git a/site/pages/[locale]/dp-auctions/index.js b/site/pages/[locale]/dp-auctions/index.js
deleted file mode 100644
index 3150aaf..0000000
--- a/site/pages/[locale]/dp-auctions/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { useEffect } from 'react'
-
-import { useRouter } from '../../../navigation'
-
-function DpAuctionsIndex() {
- const router = useRouter()
-
- useEffect(
- function redirectToDefaultCollection() {
- router.replace(
- `/dp-auctions/collections?id=${process.env.NEXT_PUBLIC_DEFAULT_COLLECTION_ID}`
- )
- },
- [router]
- )
-
- return null
-}
-
-export default DpAuctionsIndex
diff --git a/site/pages/[locale]/payment-streams/edit.js b/site/pages/[locale]/payment-streams/edit.js
deleted file mode 100644
index 79d1e1d..0000000
--- a/site/pages/[locale]/payment-streams/edit.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { useTranslations } from 'next-intl'
-
-import PaymentStreamsLayout from '../../../components/layout/PaymentStreamsLayout'
-import UtilFormBox from '../../../components/layout/UtilFormBox'
-import EditStream from '../../../components/payment-streams/EditStream'
-
-const PaymentStreamsEdit = () => {
- const t = useTranslations()
- return (
-
-
-
-
-
- )
-}
-
-export { getStaticProps, getStaticPaths } from '../../../utils/staticProps'
-export default PaymentStreamsEdit
diff --git a/site/pages/[locale]/payment-streams/index.js b/site/pages/[locale]/payment-streams/index.js
deleted file mode 100644
index 0f20211..0000000
--- a/site/pages/[locale]/payment-streams/index.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { useTranslations } from 'next-intl'
-
-import PaymentStreamsLayout from '../../../components/layout/PaymentStreamsLayout'
-import UtilFormBox from '../../../components/layout/UtilFormBox'
-import StreamsTable from '../../../components/payment-streams/StreamsTable'
-
-const PaymentStreams = () => {
- const t = useTranslations()
- return (
-
-
-
-
-
- )
-}
-
-export { getStaticProps, getStaticPaths } from '../../../utils/staticProps'
-export default PaymentStreams
diff --git a/site/pages/[locale]/payment-streams/new.js b/site/pages/[locale]/payment-streams/new.js
deleted file mode 100644
index 31ec0a2..0000000
--- a/site/pages/[locale]/payment-streams/new.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { useTranslations } from 'next-intl'
-
-import PaymentStreamsLayout from '../../../components/layout/PaymentStreamsLayout'
-import UtilFormBox from '../../../components/layout/UtilFormBox'
-import CreateStream from '../../../components/payment-streams/CreateStream'
-
-const PaymentStreamsCreate = () => {
- const t = useTranslations()
- return (
-
-
-
-
-
- )
-}
-
-export { getStaticProps, getStaticPaths } from '../../../utils/staticProps'
-export default PaymentStreamsCreate