feat: lots
This commit is contained in:
parent
69d83ef95c
commit
b41e8c88f7
|
@ -125,7 +125,11 @@ const BottomMenu: FC<Props> = ({ className }) => {
|
|||
)}
|
||||
onClick={() => push('/receive/qr')}
|
||||
>
|
||||
<LoginIcon className="h-full text-purple-50 dark:text-gray-900 w-full -rotate-90" />
|
||||
<LoginIcon
|
||||
className={
|
||||
'h-full text-purple-50 dark:text-gray-900 w-full -rotate-child-90'
|
||||
}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -2,12 +2,14 @@ import { ClockIcon } from '@heroicons/react/outline'
|
|||
import { DownloadIcon, UploadIcon } from '@heroicons/react/solid'
|
||||
import clsx from 'clsx'
|
||||
import { tools } from 'nanocurrency-web'
|
||||
import type { FC } from 'react'
|
||||
import { FC, useCallback, useState } from 'react'
|
||||
|
||||
import { useCurrentAccount } from '../lib/context/accountContext'
|
||||
import useAccountHistory from '../lib/hooks/useAccountHistory'
|
||||
import useAccountReceivable from '../lib/hooks/useAccountReceivable'
|
||||
import useListenToConfirmations from '../lib/hooks/useListenToConfirmations'
|
||||
import useReceiveNano from '../lib/hooks/useReceiveNano'
|
||||
import { ConfirmationMessage } from '../lib/types'
|
||||
|
||||
const rawToNanoDisplay = (raw: string) =>
|
||||
Number(tools.convert(raw, 'RAW', 'NANO').slice(0, 20))
|
||||
|
@ -25,15 +27,15 @@ const RecentTransactions: FC<Props> = ({ className }) => {
|
|||
const {
|
||||
accountReceivable,
|
||||
blocksInfo: receivableBlocksInfo,
|
||||
loading: loadingReceivable,
|
||||
mutate,
|
||||
} = useAccountReceivable()
|
||||
const { accountHistory, loading: loadingHistory } = useAccountHistory()
|
||||
const { accountHistory } = useAccountHistory()
|
||||
|
||||
const account = useCurrentAccount()
|
||||
|
||||
const hasReceivable =
|
||||
!loadingReceivable && Object.keys(accountReceivable.blocks).length > 0
|
||||
const hasHistory = !loadingHistory && accountHistory.history.length > 0
|
||||
accountReceivable !== undefined &&
|
||||
Object.values(accountReceivable.blocks).some(account => account !== '')
|
||||
|
||||
const receivable = Object.entries(
|
||||
accountReceivable?.blocks[account?.address ?? ''] ?? {}
|
||||
|
@ -43,12 +45,69 @@ const RecentTransactions: FC<Props> = ({ className }) => {
|
|||
from: source,
|
||||
}))
|
||||
|
||||
const [listenedReceivables, setListenedReceivables] = useState<
|
||||
ConfirmationMessage[]
|
||||
>([])
|
||||
|
||||
const onConfirmation = useCallback(
|
||||
(confirmation: ConfirmationMessage) => {
|
||||
const alreadyHaveConfirmation =
|
||||
accountHistory?.history !== '' &&
|
||||
accountHistory?.history.some(
|
||||
txn => txn.hash === confirmation.message.hash
|
||||
) &&
|
||||
receivable.some(txn => txn.hash === confirmation.message.hash)
|
||||
if (!alreadyHaveConfirmation)
|
||||
setListenedReceivables(prev => [...prev, confirmation])
|
||||
},
|
||||
[accountHistory, receivable]
|
||||
)
|
||||
|
||||
useListenToConfirmations(onConfirmation)
|
||||
|
||||
console.log(listenedReceivables)
|
||||
|
||||
return (
|
||||
<div className={clsx('flex flex-col gap-6 w-full', className)}>
|
||||
{hasReceivable && (
|
||||
<section className="flex flex-col gap-3 w-full items-center">
|
||||
<h2 className="text-2xl font-semibold text-purple-50">receivable</h2>
|
||||
<ol className="flex flex-col gap-3 w-full">
|
||||
{listenedReceivables.map(({ message, time }) => (
|
||||
<li
|
||||
key={message.hash}
|
||||
className="bg-purple-50 shadow rounded px-3 py-3 flex items-center justify-between gap-2 text-black border-r-4 border-blue-500"
|
||||
>
|
||||
<button
|
||||
className="contents"
|
||||
onClick={() => receive(message.hash, message.amount)}
|
||||
>
|
||||
<ClockIcon className="w-6 flex-shrink-0 text-blue-500" />
|
||||
|
||||
<div className="overflow-hidden overflow-ellipsis text-left flex-1 whitespace-nowrap">
|
||||
{Intl.DateTimeFormat([], {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: '2-digit',
|
||||
}).format(Number(time) * 1000)}{' '}
|
||||
- {<span className="text-xs">{message.block.account}</span>}
|
||||
</div>
|
||||
<span className="flex-shrink-0 font-medium">
|
||||
Ӿ{' '}
|
||||
{rawToNanoDisplay(message.amount) === 'small' ? (
|
||||
'<.01'
|
||||
) : rawToNanoDisplay(message.amount).startsWith('0.') ? (
|
||||
<>
|
||||
<span className="text-sm font-semibold">0</span>
|
||||
{rawToNanoDisplay(message.amount).substring(1)}
|
||||
</>
|
||||
) : (
|
||||
rawToNanoDisplay(message.amount)
|
||||
)}
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
{receivable.map(receivable => (
|
||||
<li
|
||||
key={receivable.hash}
|
||||
|
@ -92,43 +151,29 @@ const RecentTransactions: FC<Props> = ({ className }) => {
|
|||
</ol>
|
||||
</section>
|
||||
)}
|
||||
{hasHistory && hasReceivable && <hr />}
|
||||
{hasHistory && (
|
||||
{accountHistory !== undefined &&
|
||||
accountHistory.history !== '' &&
|
||||
hasReceivable && <hr />}
|
||||
{accountHistory !== undefined && accountHistory.history !== '' && (
|
||||
<section className="flex flex-col gap-3 w-full items-center">
|
||||
<h2 className="text-2xl font-semibold text-purple-50">
|
||||
recent transactions
|
||||
</h2>
|
||||
<ol className="flex flex-col gap-3 w-full">
|
||||
{[
|
||||
{
|
||||
hash: 'string',
|
||||
send: 'string',
|
||||
receivable: true,
|
||||
amount: '0',
|
||||
account: '',
|
||||
timestamp: '',
|
||||
},
|
||||
].map(txn => (
|
||||
{accountHistory.history.map(txn => (
|
||||
<li
|
||||
key={txn.hash}
|
||||
className={clsx(
|
||||
'bg-purple-50 shadow rounded px-3 py-3 flex items-center justify-between gap-2 text-black border-r-4',
|
||||
txn.send
|
||||
? 'border-yellow-500'
|
||||
: txn.receivable
|
||||
? 'border-blue-500'
|
||||
: 'border-green-500'
|
||||
txn.type === 'send' ? 'border-yellow-500' : 'border-green-500'
|
||||
)}
|
||||
>
|
||||
<button className="contents" onClick={() => {}}>
|
||||
{txn.send ? (
|
||||
{txn.type === 'send' ? (
|
||||
<UploadIcon className="w-6 text-yellow-500 flex-shrink-0" />
|
||||
) : (
|
||||
<DownloadIcon
|
||||
className={clsx(
|
||||
'w-6 flex-shrink-0',
|
||||
txn.receivable ? 'text-blue-500' : 'text-green-500'
|
||||
)}
|
||||
className={clsx('w-6 flex-shrink-0 text-green-500')}
|
||||
/>
|
||||
)}
|
||||
<div className="overflow-hidden overflow-ellipsis text-left flex-1 whitespace-nowrap">
|
||||
|
@ -136,7 +181,7 @@ const RecentTransactions: FC<Props> = ({ className }) => {
|
|||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: '2-digit',
|
||||
}).format(Number(txn.timestamp) * 1000)}{' '}
|
||||
}).format(Number(txn.local_timestamp) * 1000)}{' '}
|
||||
- {<span className="text-xs">{txn.account}</span>}
|
||||
</div>
|
||||
<span className="flex-shrink-0 font-medium">
|
||||
|
@ -158,16 +203,17 @@ const RecentTransactions: FC<Props> = ({ className }) => {
|
|||
</ol>
|
||||
</section>
|
||||
)}
|
||||
{!hasReceivable && !hasHistory && (
|
||||
<div className="text-center pt-8 text-purple-50">
|
||||
<p className="pb-4">no transactions yet...</p>
|
||||
<p>
|
||||
get your first nano
|
||||
<br />
|
||||
to see something here!
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{!hasReceivable &&
|
||||
(accountHistory === undefined || accountHistory.history === '') && (
|
||||
<div className="text-center pt-8 text-purple-50">
|
||||
<p className="pb-4">no transactions yet...</p>
|
||||
<p>
|
||||
get your first nano
|
||||
<br />
|
||||
to see something here!
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{false && (
|
||||
<button
|
||||
className="bg-purple-200 py-2 px-4 rounded dark:text-gray-900 font-bold shadow"
|
||||
|
|
|
@ -4,11 +4,17 @@ import {
|
|||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react'
|
||||
|
||||
import computeWorkAsync from '../computeWorkAsync'
|
||||
import { addPrecomputedWork, getAllAccounts, putAccount } from '../db/accounts'
|
||||
import {
|
||||
addPrecomputedWork,
|
||||
consumePrecomputedWork,
|
||||
getAllAccounts,
|
||||
putAccount,
|
||||
} from '../db/accounts'
|
||||
import { AccountInfoCache } from '../types'
|
||||
import fetchAccountInfo from '../xno/fetchAccountInfo'
|
||||
|
||||
|
@ -25,15 +31,26 @@ const accountContext = createContext<AccountContextValue | undefined>(undefined)
|
|||
const refreshAccountFromNetwork = async (account: AccountInfoCache) => {
|
||||
const infoResponse = await fetchAccountInfo(account.address)
|
||||
|
||||
const frontier =
|
||||
'error' in infoResponse ? null : infoResponse.confirmed_frontier
|
||||
const representative =
|
||||
'error' in infoResponse ? null : infoResponse.confirmed_representative
|
||||
const balance =
|
||||
'error' in infoResponse ? null : infoResponse.confirmed_balance
|
||||
const freshAccountInfo = {
|
||||
...account,
|
||||
frontier: 'error' in infoResponse ? null : infoResponse.confirmed_frontier,
|
||||
representative:
|
||||
'error' in infoResponse ? null : infoResponse.confirmed_representative,
|
||||
balance: 'error' in infoResponse ? null : infoResponse.confirmed_balance,
|
||||
frontier,
|
||||
representative,
|
||||
balance,
|
||||
}
|
||||
putAccount(freshAccountInfo)
|
||||
return freshAccountInfo
|
||||
const diff =
|
||||
account.frontier !== frontier ||
|
||||
account.representative !== representative ||
|
||||
account.balance !== balance
|
||||
|
||||
if (diff) putAccount(freshAccountInfo)
|
||||
|
||||
return { freshAccountInfo, diff }
|
||||
}
|
||||
|
||||
export const useAccounts = () => {
|
||||
|
@ -70,31 +87,37 @@ export const AccountProvider: FC = ({ children }) => {
|
|||
useEffect(() => {
|
||||
const refreshAccountsFromNetwork = async (accounts: AccountInfoCache[]) =>
|
||||
accounts.forEach(async account => {
|
||||
const freshAccount = await refreshAccountFromNetwork(account)
|
||||
setAccount(freshAccount)
|
||||
const { freshAccountInfo, diff } = await refreshAccountFromNetwork(
|
||||
account
|
||||
)
|
||||
if (diff) setAccount(freshAccountInfo)
|
||||
})
|
||||
|
||||
const getAccountsFromIdb = async () => {
|
||||
const accountList = await getAllAccounts()
|
||||
const accounts: AccountContextValue['accounts'] = {}
|
||||
for (const account of accountList) {
|
||||
accountList.forEach(async account => {
|
||||
accounts[account.index] = account
|
||||
if (account.precomputedWork === null) {
|
||||
computeWorkAsync(account.frontier ?? account.address, {
|
||||
send: account.frontier !== null,
|
||||
}).then(work => {
|
||||
if (work !== null) {
|
||||
setAccounts(prev => ({
|
||||
...prev,
|
||||
[account.index]: {
|
||||
...prev[account.index],
|
||||
precomputedWork: work,
|
||||
},
|
||||
}))
|
||||
addPrecomputedWork(account.address, work)
|
||||
const work = await computeWorkAsync(
|
||||
account.frontier ?? account.publicKey,
|
||||
{
|
||||
send: account.frontier !== null,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
if (work !== null) {
|
||||
setAccounts(prev => ({
|
||||
...prev,
|
||||
[account.index]: {
|
||||
...prev[account.index],
|
||||
precomputedWork: work,
|
||||
},
|
||||
}))
|
||||
addPrecomputedWork(account.address, work)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
setAccounts(accounts)
|
||||
refreshAccountsFromNetwork(accountList)
|
||||
}
|
||||
|
@ -102,7 +125,10 @@ export const AccountProvider: FC = ({ children }) => {
|
|||
}, [setAccount])
|
||||
|
||||
const [currAccountIndex, setCurrAccountIndex] = useState<number>(0)
|
||||
const currAccount = accounts?.[currAccountIndex]
|
||||
const currAccount = useMemo(
|
||||
() => accounts?.[currAccountIndex],
|
||||
[currAccountIndex, accounts]
|
||||
)
|
||||
|
||||
const removeAccount = useCallback((index: number) => {
|
||||
setAccounts(prev => {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
import { useCurrentAccount } from '../context/accountContext'
|
||||
import type { AccountReceivableResponse, BlocksInfoResponse } from '../types'
|
||||
import fetchAccountReceivable from '../xno/fetchAccountReceivable'
|
||||
import fetchBlocksInfo from '../xno/fetchBlocksInfo'
|
||||
|
||||
type ReturnValue =
|
||||
type ReturnValue = (
|
||||
| {
|
||||
accountReceivable: undefined
|
||||
blocksInfo: undefined
|
||||
|
@ -16,6 +16,15 @@ type ReturnValue =
|
|||
blocksInfo: BlocksInfoResponse
|
||||
loading: false
|
||||
}
|
||||
) & {
|
||||
mutate: (prev: {
|
||||
accountReceivable: AccountReceivableResponse | undefined
|
||||
blocksInfo: BlocksInfoResponse | undefined
|
||||
}) => {
|
||||
accountReceivable: AccountReceivableResponse | undefined
|
||||
blocksInfo: BlocksInfoResponse | undefined
|
||||
}
|
||||
}
|
||||
|
||||
const useAccountReceivable = (): ReturnValue => {
|
||||
const [accountReceivableWithInfo, setAccountReceivableWithInfo] = useState<{
|
||||
|
@ -47,7 +56,11 @@ const useAccountReceivable = (): ReturnValue => {
|
|||
const loading =
|
||||
accountReceivableWithInfo.accountReceivable === undefined &&
|
||||
accountReceivableWithInfo.blocksInfo === undefined
|
||||
return { ...accountReceivableWithInfo, loading } as ReturnValue
|
||||
return {
|
||||
...accountReceivableWithInfo,
|
||||
loading,
|
||||
mutate: setAccountReceivableWithInfo,
|
||||
} as ReturnValue
|
||||
}
|
||||
|
||||
export default useAccountReceivable
|
||||
|
|
54
lib/hooks/useListenToConfirmations.ts
Normal file
54
lib/hooks/useListenToConfirmations.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { useEffect, useRef } from 'react'
|
||||
|
||||
import { useCurrentAccount } from '../context/accountContext'
|
||||
import type { ConfirmationMessage } from '../types'
|
||||
|
||||
/**
|
||||
* _please don't forget to memo `onConfirmation`_ :)
|
||||
* @param onConfirmation the callback to call with the new confirmation
|
||||
*/
|
||||
const useListenToConfirmations = (
|
||||
onConfirmation: (confirmation: ConfirmationMessage) => void
|
||||
) => {
|
||||
const account = useCurrentAccount()
|
||||
|
||||
const wsRef = useRef<WebSocket>()
|
||||
|
||||
useEffect(() => {
|
||||
wsRef.current = new WebSocket('wss://node.somenano.com/websocket')
|
||||
return () => wsRef.current?.close()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
account !== undefined &&
|
||||
wsRef.current !== undefined &&
|
||||
wsRef.current.readyState === WebSocket.OPEN
|
||||
) {
|
||||
wsRef.current!.send(
|
||||
JSON.stringify({
|
||||
action: 'subscribe',
|
||||
topic: 'confirmation',
|
||||
options: {
|
||||
accounts: [account.address],
|
||||
},
|
||||
})
|
||||
)
|
||||
wsRef.current!.addEventListener('message', ({ data }) => {
|
||||
const parsed = JSON.parse(data) as ConfirmationMessage
|
||||
if (parsed.topic !== 'confirmation') return
|
||||
onConfirmation(parsed)
|
||||
})
|
||||
|
||||
return () =>
|
||||
wsRef.current!.send(
|
||||
JSON.stringify({
|
||||
action: 'unsubscribe',
|
||||
topic: 'confirmation',
|
||||
})
|
||||
)
|
||||
}
|
||||
}, [account, onConfirmation])
|
||||
}
|
||||
|
||||
export default useListenToConfirmations
|
|
@ -1,35 +0,0 @@
|
|||
import { useEffect } from 'react'
|
||||
|
||||
import { useAccounts } from '../context/accountContext'
|
||||
import { ConfirmationMessage } from '../types'
|
||||
|
||||
const useListenToTxn = (
|
||||
onConfirmation: (confirmation: ConfirmationMessage) => void
|
||||
) => {
|
||||
const { accounts } = useAccounts()
|
||||
useEffect(() => {
|
||||
if (accounts !== undefined) {
|
||||
const ws = new WebSocket('wss://ws.mynano.ninja/')
|
||||
|
||||
ws.onopen = () => {
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
action: 'subscribe',
|
||||
topic: 'confirmation',
|
||||
options: {
|
||||
accounts: [accounts],
|
||||
},
|
||||
})
|
||||
)
|
||||
ws.addEventListener('message', ({ data }) => {
|
||||
const parsed = JSON.parse(data) as ConfirmationMessage
|
||||
onConfirmation(parsed)
|
||||
})
|
||||
}
|
||||
|
||||
return () => ws.close()
|
||||
}
|
||||
}, [accounts, onConfirmation])
|
||||
}
|
||||
|
||||
export default useListenToTxn
|
|
@ -1,15 +1,15 @@
|
|||
import { computeWork, hashBlock } from 'nanocurrency'
|
||||
import Big from 'bignumber.js'
|
||||
import { useCallback, useState } from 'react'
|
||||
|
||||
import computeWorkAsync from '../computeWorkAsync'
|
||||
import { useAccount } from '../context/accountContext'
|
||||
import { getPrecomputedWork } from '../db/accounts'
|
||||
import fetcher from '../fetcher'
|
||||
import { useAccount, useAccounts } from '../context/accountContext'
|
||||
import { consumePrecomputedWork, getPrecomputedWork } from '../db/accounts'
|
||||
import { zeroString } from '../xno/constants'
|
||||
import receiveNano from '../xno/receiveNano'
|
||||
|
||||
const useReceiveNano = () => {
|
||||
const account = useAccount()
|
||||
const { setAccount } = useAccounts()
|
||||
const [generatingWork, setGeneratingWork] = useState(false)
|
||||
|
||||
const receive = useCallback(
|
||||
|
@ -19,13 +19,13 @@ const useReceiveNano = () => {
|
|||
if (precomputedWork === null) {
|
||||
setGeneratingWork(true)
|
||||
precomputedWork = await computeWorkAsync(
|
||||
account.frontier ?? account.address,
|
||||
account.frontier ?? account.publicKey,
|
||||
{ send: false }
|
||||
)
|
||||
setGeneratingWork(false)
|
||||
}
|
||||
if (precomputedWork === null) throw new Error('couldnt_compute_work')
|
||||
await receiveNano(
|
||||
if (precomputedWork === null) throw new Error('cant_compute_work')
|
||||
const processResponse = await receiveNano(
|
||||
{
|
||||
transactionHash: hash,
|
||||
walletBalanceRaw: account.balance ?? '0',
|
||||
|
@ -37,8 +37,17 @@ const useReceiveNano = () => {
|
|||
},
|
||||
account.index
|
||||
)
|
||||
|
||||
await consumePrecomputedWork(account.address)
|
||||
const work = await computeWorkAsync(processResponse.hash, { send: false })
|
||||
setAccount({
|
||||
...account,
|
||||
frontier: processResponse.hash,
|
||||
balance: new Big(account.balance ?? 0).plus(new Big(amount)).toString(),
|
||||
...(work !== null ? { work } : {}),
|
||||
})
|
||||
},
|
||||
[account]
|
||||
[account, setAccount]
|
||||
)
|
||||
|
||||
return { receive, generatingWork }
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
import { hashBlock } from 'nanocurrency'
|
||||
import Big from 'bignumber.js'
|
||||
import { useCallback, useState } from 'react'
|
||||
|
||||
import computeWorkAsync from '../computeWorkAsync'
|
||||
import { useAccount } from '../context/accountContext'
|
||||
import {
|
||||
addPrecomputedWork,
|
||||
consumePrecomputedWork,
|
||||
getPrecomputedWork,
|
||||
} from '../db/accounts'
|
||||
import { useAccount, useAccounts } from '../context/accountContext'
|
||||
import { consumePrecomputedWork, getPrecomputedWork } from '../db/accounts'
|
||||
import sendNano from '../xno/sendNano'
|
||||
|
||||
const useSendNano = () => {
|
||||
const account = useAccount()
|
||||
const { setAccount } = useAccounts()
|
||||
const [generatingWork, setGeneratingWork] = useState(false)
|
||||
|
||||
const send = useCallback(
|
||||
|
@ -27,13 +24,14 @@ const useSendNano = () => {
|
|||
if (precomputedWork === null) {
|
||||
setGeneratingWork(true)
|
||||
precomputedWork = await computeWorkAsync(
|
||||
account.frontier ?? account.address,
|
||||
account.frontier ?? account.publicKey,
|
||||
{ send: true }
|
||||
)
|
||||
setGeneratingWork(false)
|
||||
}
|
||||
if (precomputedWork === null) throw new Error('couldnt_compute_work')
|
||||
await sendNano(
|
||||
if (precomputedWork === null) throw new Error('cant_compute_work')
|
||||
|
||||
const processResponse = await sendNano(
|
||||
{
|
||||
walletBalanceRaw: account.balance,
|
||||
fromAddress: account.address,
|
||||
|
@ -45,8 +43,17 @@ const useSendNano = () => {
|
|||
},
|
||||
account.index
|
||||
)
|
||||
|
||||
consumePrecomputedWork(account.address)
|
||||
const work = await computeWorkAsync(processResponse.hash, { send: false })
|
||||
setAccount({
|
||||
...account,
|
||||
frontier: processResponse.hash,
|
||||
balance: new Big(account.balance).minus(new Big(amount)).toString(),
|
||||
...(work !== null ? { work } : {}),
|
||||
})
|
||||
},
|
||||
[account]
|
||||
[account, setAccount]
|
||||
)
|
||||
|
||||
return { send, generatingWork }
|
||||
|
|
14
lib/types.ts
14
lib/types.ts
|
@ -18,12 +18,14 @@ export interface AccountHistoryResponse {
|
|||
|
||||
export interface AccountReceivableResponse {
|
||||
blocks: {
|
||||
[destinationAddress: string]: {
|
||||
[blockHash: string]: {
|
||||
amount: string
|
||||
source: string
|
||||
}
|
||||
}
|
||||
[destinationAddress: string]:
|
||||
| {
|
||||
[blockHash: string]: {
|
||||
amount: string
|
||||
source: string
|
||||
}
|
||||
}
|
||||
| ''
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,21 +18,22 @@ const sendNano = async (
|
|||
)
|
||||
|
||||
const signedBlock = block.receive(blockData, privateKey)
|
||||
fetcher<ProcessResponse>('https://mynano.ninja/api/node', {
|
||||
method: 'POST',
|
||||
headers: [['Content-Type', 'application/json']],
|
||||
body: JSON.stringify({
|
||||
action: 'process',
|
||||
json_block: 'true',
|
||||
subtype: 'receive',
|
||||
block: signedBlock,
|
||||
}),
|
||||
}).then(async data => {
|
||||
if ('error' in data) throw new Error()
|
||||
await consumePrecomputedWork(blockData.toAddress)
|
||||
const work = await computeWorkAsync(hashBlock(signedBlock), { send: false })
|
||||
if (work !== null) addPrecomputedWork(blockData.toAddress, work)
|
||||
})
|
||||
const processResponse = await fetcher<ProcessResponse>(
|
||||
'https://mynano.ninja/api/node',
|
||||
{
|
||||
method: 'POST',
|
||||
body: {
|
||||
action: 'process',
|
||||
json_block: 'true',
|
||||
subtype: 'receive',
|
||||
block: signedBlock,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if ('error' in processResponse) throw new Error()
|
||||
|
||||
return processResponse
|
||||
}
|
||||
|
||||
export default sendNano
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { hashBlock } from 'nanocurrency'
|
||||
import { block } from 'nanocurrency-web'
|
||||
|
||||
import computeWorkAsync from '../computeWorkAsync'
|
||||
|
@ -18,21 +17,22 @@ const sendNano = async (
|
|||
)
|
||||
|
||||
const signedBlock = block.send(blockData, privateKey)
|
||||
return fetcher<ProcessResponse>('https://mynano.ninja/api/node', {
|
||||
method: 'POST',
|
||||
headers: [['Content-Type', 'application/json']],
|
||||
body: JSON.stringify({
|
||||
action: 'process',
|
||||
json_block: 'true',
|
||||
subtype: 'send',
|
||||
block: signedBlock,
|
||||
}),
|
||||
}).then(async data => {
|
||||
if ('error' in data) throw new Error()
|
||||
await consumePrecomputedWork(blockData.fromAddress)
|
||||
const work = await computeWorkAsync(hashBlock(signedBlock), { send: true })
|
||||
if (work !== null) addPrecomputedWork(blockData.fromAddress, work)
|
||||
})
|
||||
const processResponse = await fetcher<ProcessResponse>(
|
||||
'https://mynano.ninja/api/node',
|
||||
{
|
||||
method: 'POST',
|
||||
body: {
|
||||
action: 'process',
|
||||
json_block: 'true',
|
||||
subtype: 'send',
|
||||
block: signedBlock,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if ('error' in processResponse) throw new Error()
|
||||
|
||||
return processResponse
|
||||
}
|
||||
|
||||
export default sendNano
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@heroicons/react": "^1.0.5",
|
||||
"bignumber.js": "^9.0.1",
|
||||
"cbor": "^8.1.0",
|
||||
"clsx": "^1.1.1",
|
||||
"crypto-js": "^4.1.1",
|
||||
|
@ -29,7 +30,7 @@
|
|||
"nanocurrency-web": "^1.3.5",
|
||||
"next": "latest",
|
||||
"prettier": "^2.4.1",
|
||||
"qrcode": "^1.4.4",
|
||||
"qrcode": "^1.5.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
},
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { AppProps } from 'next/app'
|
||||
import { FC } from 'react'
|
||||
import 'tailwindcss/tailwind.css'
|
||||
|
||||
import Layout from '../components/Layout'
|
||||
import MemCacheProvider from '../lib/context/memCacheContextProvider'
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
[
|
||||
"expand target gospel goose oppose acquire genius hurdle trade size huge pact square silk canal bar curve shallow pistol push crowd glory slice news",
|
||||
"81631b9773ab0f4ff0d61a0ae092ec564acc01912aedbd849c420e10b2c38c7edc2c5494f778d3122a5933261c3a09b17f1b1be33d3b068d3228529a24bf94b3"
|
||||
"81631b9773ab0f4ff0d61a0ae092ec564acc01912aedbd849c420e10b2c38c7edc2c5494f778d3122a5933261c3a09b17f1b1be33d3b068d3228529a24bf94b3",
|
||||
"738b5cb3315dd267fc882f1388911162ee9a241c800bf583c07c1bbbc34c64a9c2099e01b5d5e3ab217012717e3ecfbe3f735af431c7e105e1719eeb03476af5",
|
||||
"75edd150e09bada0f5c68fab14c0b385239cc396ef6600029dea0f7b66be63fa6a7d8ebe30aaff66634f583c4e68067c0de136e27dddc96be76d2ac5bb14ef71"
|
||||
]
|
||||
|
|
|
@ -4,3 +4,14 @@ body,
|
|||
html {
|
||||
font-family: Manrope;
|
||||
}
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer utilities {
|
||||
.-rotate-child-90 > * {
|
||||
transform: rotate(-90deg);
|
||||
transform-origin: center;
|
||||
}
|
||||
}
|
||||
|
|
175
yarn.lock
175
yarn.lock
|
@ -784,11 +784,6 @@ ansi-regex@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
|
||||
|
||||
ansi-regex@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
|
||||
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
|
@ -967,7 +962,7 @@ balanced-match@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9"
|
||||
integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==
|
||||
|
||||
base64-js@^1.0.2, base64-js@^1.3.1:
|
||||
base64-js@^1.0.2:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
@ -977,7 +972,7 @@ big.js@^5.2.2:
|
|||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
||||
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
|
||||
|
||||
bignumber.js@9.0.1, bignumber.js@^9.0.0:
|
||||
bignumber.js@9.0.1, bignumber.js@^9.0.0, bignumber.js@^9.0.1:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5"
|
||||
integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==
|
||||
|
@ -1110,29 +1105,6 @@ browserslist@^4.17.5:
|
|||
node-releases "^2.0.1"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
buffer-alloc-unsafe@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
|
||||
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
|
||||
|
||||
buffer-alloc@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
|
||||
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
|
||||
dependencies:
|
||||
buffer-alloc-unsafe "^1.1.0"
|
||||
buffer-fill "^1.0.0"
|
||||
|
||||
buffer-fill@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
|
||||
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
|
||||
|
||||
buffer-from@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||
|
||||
buffer-xor@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
|
||||
|
@ -1146,14 +1118,6 @@ buffer@5.6.0:
|
|||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
||||
buffer@^5.4.3:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
||||
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
||||
dependencies:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
builtin-status-codes@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||
|
@ -1347,14 +1311,14 @@ cli-truncate@^2.1.0:
|
|||
slice-ansi "^3.0.0"
|
||||
string-width "^4.2.0"
|
||||
|
||||
cliui@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
|
||||
integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==
|
||||
cliui@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
||||
integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
|
||||
dependencies:
|
||||
string-width "^3.1.0"
|
||||
strip-ansi "^5.2.0"
|
||||
wrap-ansi "^5.1.0"
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^6.2.0"
|
||||
|
||||
clone-regexp@^2.1.0:
|
||||
version "2.2.0"
|
||||
|
@ -1767,11 +1731,6 @@ elliptic@^6.5.3:
|
|||
minimalistic-assert "^1.0.1"
|
||||
minimalistic-crypto-utils "^1.0.1"
|
||||
|
||||
emoji-regex@^7.0.1:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
|
@ -1787,6 +1746,11 @@ emojis-list@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
|
||||
integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
|
||||
|
||||
encode-utf8@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda"
|
||||
integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==
|
||||
|
||||
encoding@0.1.13:
|
||||
version "0.1.13"
|
||||
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
|
||||
|
@ -2216,13 +2180,6 @@ find-up@^2.1.0:
|
|||
dependencies:
|
||||
locate-path "^2.0.0"
|
||||
|
||||
find-up@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
|
||||
integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
|
||||
dependencies:
|
||||
locate-path "^3.0.0"
|
||||
|
||||
find-up@^4.0.0, find-up@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
|
||||
|
@ -2621,7 +2578,7 @@ idb@^7.0.0:
|
|||
resolved "https://registry.yarnpkg.com/idb/-/idb-7.0.0.tgz#f349b418c128f625961147a7d6b0e4b526fd34ed"
|
||||
integrity sha512-jSx0WOY9Nj+QzP6wX5e7g64jqh8ExtDs/IAuOrOEZCD/h6+0HqyrKsDMfdJc0hqhSvh0LsrwqrkDn+EtjjzSRA==
|
||||
|
||||
ieee754@^1.1.13, ieee754@^1.1.4:
|
||||
ieee754@^1.1.4:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
@ -2795,11 +2752,6 @@ is-extglob@^2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||
|
||||
is-fullwidth-code-point@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
||||
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
|
@ -2933,11 +2885,6 @@ is-weakref@^1.0.1:
|
|||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
|
||||
isarray@^2.0.1:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
|
||||
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
|
@ -3130,14 +3077,6 @@ locate-path@^2.0.0:
|
|||
p-locate "^2.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
locate-path@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
|
||||
integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
|
||||
dependencies:
|
||||
p-locate "^3.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
locate-path@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
|
||||
|
@ -3650,7 +3589,7 @@ p-limit@^1.1.0:
|
|||
dependencies:
|
||||
p-try "^1.0.0"
|
||||
|
||||
p-limit@^2.0.0, p-limit@^2.2.0:
|
||||
p-limit@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
|
||||
integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
|
||||
|
@ -3664,13 +3603,6 @@ p-locate@^2.0.0:
|
|||
dependencies:
|
||||
p-limit "^1.1.0"
|
||||
|
||||
p-locate@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
|
||||
integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
|
||||
dependencies:
|
||||
p-limit "^2.0.0"
|
||||
|
||||
p-locate@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
|
||||
|
@ -3825,10 +3757,10 @@ platform@1.3.6:
|
|||
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7"
|
||||
integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
|
||||
|
||||
pngjs@^3.3.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
|
||||
integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
|
||||
pngjs@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb"
|
||||
integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==
|
||||
|
||||
postcss-js@^3.0.3:
|
||||
version "3.0.3"
|
||||
|
@ -3992,18 +3924,15 @@ purgecss@^4.0.3:
|
|||
postcss "^8.2.1"
|
||||
postcss-selector-parser "^6.0.2"
|
||||
|
||||
qrcode@^1.4.4:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83"
|
||||
integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==
|
||||
qrcode@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.0.tgz#95abb8a91fdafd86f8190f2836abbfc500c72d1b"
|
||||
integrity sha512-9MgRpgVc+/+47dFvQeD6U2s0Z92EsKzcHogtum4QB+UNd025WOJSHvn/hjk9xmzj7Stj95CyUAs31mrjxliEsQ==
|
||||
dependencies:
|
||||
buffer "^5.4.3"
|
||||
buffer-alloc "^1.2.0"
|
||||
buffer-from "^1.1.1"
|
||||
dijkstrajs "^1.0.1"
|
||||
isarray "^2.0.1"
|
||||
pngjs "^3.3.0"
|
||||
yargs "^13.2.4"
|
||||
encode-utf8 "^1.0.3"
|
||||
pngjs "^5.0.0"
|
||||
yargs "^15.3.1"
|
||||
|
||||
querystring-es3@0.2.1:
|
||||
version "0.2.1"
|
||||
|
@ -4525,15 +4454,6 @@ string-hash@1.1.3:
|
|||
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
|
||||
integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=
|
||||
|
||||
string-width@^3.0.0, string-width@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
|
||||
integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
|
||||
dependencies:
|
||||
emoji-regex "^7.0.1"
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^5.1.0"
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
|
@ -4603,13 +4523,6 @@ strip-ansi@^3.0.0:
|
|||
dependencies:
|
||||
ansi-regex "^2.0.0"
|
||||
|
||||
strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
|
||||
integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
|
||||
dependencies:
|
||||
ansi-regex "^4.1.0"
|
||||
|
||||
strip-ansi@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2"
|
||||
|
@ -5116,15 +5029,6 @@ word-wrap@^1.2.3:
|
|||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
|
||||
|
||||
wrap-ansi@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
|
||||
integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==
|
||||
dependencies:
|
||||
ansi-styles "^3.2.0"
|
||||
string-width "^3.0.0"
|
||||
strip-ansi "^5.0.0"
|
||||
|
||||
wrap-ansi@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
||||
|
@ -5178,10 +5082,10 @@ yaml@^1.10.0, yaml@^1.10.2:
|
|||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
|
||||
yargs-parser@^13.1.2:
|
||||
version "13.1.2"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
|
||||
integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
|
||||
yargs-parser@^18.1.2:
|
||||
version "18.1.3"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
|
||||
integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
|
||||
dependencies:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
@ -5191,21 +5095,22 @@ yargs-parser@^20.2.3, yargs-parser@^20.2.7:
|
|||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
||||
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
|
||||
|
||||
yargs@^13.2.4:
|
||||
version "13.3.2"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
|
||||
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
|
||||
yargs@^15.3.1:
|
||||
version "15.4.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
|
||||
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
|
||||
dependencies:
|
||||
cliui "^5.0.0"
|
||||
find-up "^3.0.0"
|
||||
cliui "^6.0.0"
|
||||
decamelize "^1.2.0"
|
||||
find-up "^4.1.0"
|
||||
get-caller-file "^2.0.1"
|
||||
require-directory "^2.1.1"
|
||||
require-main-filename "^2.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
string-width "^3.0.0"
|
||||
string-width "^4.2.0"
|
||||
which-module "^2.0.0"
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^13.1.2"
|
||||
yargs-parser "^18.1.2"
|
||||
|
||||
yocto-queue@^0.1.0:
|
||||
version "0.1.0"
|
||||
|
|
Reference in a new issue