diff --git a/site/components/layout/DPAuctionsLayout.js b/site/components/layout/DPAuctionsLayout.js deleted file mode 100644 index 15f4f06..0000000 --- a/site/components/layout/DPAuctionsLayout.js +++ /dev/null @@ -1,23 +0,0 @@ -import { useTranslations } from 'next-intl' - -import { TransactionsContextProvider } from '../context/Transactions' -import DPAuctionsContextProvider from '../DPAuctionsContext' -import Transactions from '../Transactions' - -import ToolsLayout from './ToolsLayout' - -function DPAuctionsLayout({ children }) { - const t = useTranslations() - return ( - - - - {children} - - - - - ) -} - -export default DPAuctionsLayout diff --git a/site/components/layout/PaymentStreamsLayout.js b/site/components/layout/PaymentStreamsLayout.js deleted file mode 100644 index 7d9de67..0000000 --- a/site/components/layout/PaymentStreamsLayout.js +++ /dev/null @@ -1,23 +0,0 @@ -import { useTranslations } from 'next-intl' - -import { TransactionsContextProvider } from '../context/Transactions' -import PaymentStreamsLibContextProvider from '../payment-streams/PaymentStreamsLib' -import Transactions from '../Transactions' - -import ToolsLayout from './ToolsLayout' - -function PaymentStreamsLayout({ children }) { - const t = useTranslations() - return ( - - - - {children} - - - - - ) -} - -export default PaymentStreamsLayout diff --git a/site/components/payment-streams/CreateStream.js b/site/components/payment-streams/CreateStream.js deleted file mode 100644 index 0b5b540..0000000 --- a/site/components/payment-streams/CreateStream.js +++ /dev/null @@ -1,209 +0,0 @@ -import { useWeb3React } from '@web3-react/core' -import Big from 'big.js' -import { useTranslations } from 'next-intl' -import { findToken } from 'pf-payment-streams/src/token-list' -import { useContext, useState } from 'react' -import useSWR from 'swr' -import { isAddress } from 'web3-utils' - -import Button from '../../components/Button' -import Input from '../../components/Input' -import EndTime from '../../components/payment-streams/EndTime' -import { useStreams } from '../../hooks/useStreams' -import { useTokenInput } from '../../hooks/useTokenInput' -import { useRouter } from '../../navigation' -import { fromUnit, toUnit } from '../../utils' -import fetchJson from '../../utils/fetch-json' -import * as timeUtils from '../../utils/time' -import TransactionsContext from '../context/Transactions' - -import { PaymentStreamsLibContext } from './PaymentStreamsLib' - -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' - -// To create a payment stream, the payment token has to have a ChainLink feed! -const useSupportedTokens = function () { - const { data, error } = useSWR('supported-tokens', () => - fetchJson('https://cl-docs-addresses.web.app/addresses.json').then( - json => - json?.['ethereum-addresses'].networks.find( - ({ name }) => name === 'Ethereum Mainnet' - )?.proxies ?? [] - ) - ) - - return { - error, - isLoading: data === undefined && error === undefined, - tokens: data - } -} - -const CreateStream = function () { - const { active, account } = useWeb3React() - const t = useTranslations('payment-streams-util') - const tCommon = useTranslations() - const router = useRouter() - const paymentStreamsLib = useContext(PaymentStreamsLibContext) - const { addTransactionStatus } = useContext(TransactionsContext) - const { mutate } = useStreams() - const { tokens = [] } = useSupportedTokens() - const [payee, setPayee] = useState('') - const [usdAmount, setUsdAmount] = useState('') - const [years, setYears] = useState(0) - const [days, setDays] = useState(0) - const [hours, setHours] = useState(0) - const [isCreating, setIsCreating] = useState(false) - const tokenInput = useTokenInput() - - // tokens are in the list in the form of " / [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 ( -
- setPayee(e.target.value)} - title={t('payee')} - value={payee} - /> - setUsdAmount(e.target.value)} - suffix="USD" - title={tCommon('value')} - value={usdAmount} - /> - - -
- - -
- - ) -} - -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 ( -
- setNewUsdAmount(e.target.value)} - suffix="USD" - title={tCommon('value')} - value={newUsdAmount} - /> - -
- -
- - ) -} - -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 ( -
- setNewFundingAddress(e.target.value)} - title={t('funding-address')} - value={newFundingAddress} - /> -
- -
-
- ) -} - -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')} -
- - - -
-

- {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 ( -
- - setStreamsView('incoming'), - selected: isIncomingDisabled - }, - { - label: t('outgoing-streams'), - onClick: () => setStreamsView('outgoing'), - selected: isOutgoingDisabled - } - ]} - /> - {streamsList.length === 0 &&

{t('no-streams')}

} - {streamsList.length > 0 && ( - - - - - - {streamsView === 'outgoing' && ( - - )} - {/* */} - - - - - - - - - - {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 ( - - - - {streamsView === 'outgoing' && ( - - )} - {/* */} - - - - - - - - ) - })} - -
{t('status')} - {t(streamsView === 'incoming' ? 'payer' : 'payee')} - {t('funding-address')}{t('start-date')}{t('end-date')}{t('token')}{t('usd-amount')}{t('claimed')}{t('claimable')}{t('actions')}
- {status} - - - - - {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 && ( - - )} - {!paused && ( - - )} - - - - - )} - {streamsView === 'incoming' && ( - - - - )} -
- )} -
- ) -} - -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 ( - - - - - - - - - {auction.tokens.map(token => ( - - ))} - - - - - - - -
{t('token')}{t('value')}
{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('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 ? ( - - - - - - - - - - - {sortedAuctions.map(auction => ( - - ))} - -
{t('id')}{t('contains')}{t('price')}{t('status')}
- ) : ( -
{t('no-auctions')}
- )} - {auctions.length ? ( -
- setShowEnded(!showEnded)} - type="checkbox" - /> - -
- ) : 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