feat: add identity and feed management (#272)

* feat(wip): add basic feed operations

* ci: bump checks

* ci: bump checks

* feat: rework stamps and add feed functionalities

* refactor: polish and fixes

* feat(wip): add formulas

* feat: show bzz.link for websites

* feat: add stamp empty states and formatBzz

* feat: add feed download

* chore: update manifest-js version

* feat: dev mode support with bee-js 3.1.0 (#273)

* feat: dev mode support with bee-js 3.1.0

* fix: added missing package-lock.json file

* build: remove PR preview

* style: work on design

* feat: add TroubleshootConnectionCard

* build: remove depcheck

Co-authored-by: Attila Gazso <agazso@gmail.com>
This commit is contained in:
Cafe137
2021-12-21 10:58:54 +01:00
committed by GitHub
parent d7c59a1495
commit 25b65c3fb7
46 changed files with 4354 additions and 6378 deletions
+16
View File
@@ -30,6 +30,18 @@ export function detectIndexHtml(files: SwarmFile[]): string | false {
}
export function getHumanReadableFileSize(bytes: number): string {
if (bytes >= 1e15) {
return (bytes / 1e15).toFixed(2) + ' PB'
}
if (bytes >= 1e12) {
return (bytes / 1e12).toFixed(2) + ' TB'
}
if (bytes >= 1e9) {
return (bytes / 1e9).toFixed(2) + ' GB'
}
if (bytes >= 1e6) {
return (bytes / 1e6).toFixed(2) + ' MB'
}
@@ -65,6 +77,10 @@ export function convertManifestToFiles(files: Record<string, string>): SwarmFile
}
export function getAssetNameFromFiles(files: SwarmFile[]): string {
if (!files.length) {
return 'Unknown'
}
if (files.length === 1) {
return files[0].name
}
+110
View File
@@ -0,0 +1,110 @@
import { Bee, Reference } from '@ethersphere/bee-js'
import Wallet from 'ethereumjs-wallet'
import { uuidV4 } from '.'
import { Identity, IdentityType } from '../providers/Feeds'
export function generateWallet(): Wallet {
const buffer = new Uint8Array(32)
crypto.getRandomValues(buffer)
const wallet = new Wallet(Buffer.from(buffer))
return wallet
}
export function persistIdentity(identities: Identity[], identity: Identity): void {
const existingIndex = identities.findIndex(x => x.uuid === identity.uuid)
if (existingIndex !== -1) {
identities.splice(existingIndex, 1)
}
identities.unshift(identity)
localStorage.setItem('feeds', JSON.stringify(identities))
}
export function persistIdentitiesWithoutUpdate(identities: Identity[]): void {
localStorage.setItem('feeds', JSON.stringify(identities))
}
export async function convertWalletToIdentity(
identity: Wallet,
type: IdentityType,
name: string,
password?: string,
): Promise<Identity> {
if (type === 'V3' && !password) {
throw Error('V3 passwords require password')
}
const identityString =
type === 'PRIVATE_KEY' ? identity.getPrivateKeyString() : await identity.toV3String(password as string)
return {
uuid: uuidV4(),
name,
type: password ? 'V3' : 'PRIVATE_KEY',
address: identity.getAddressString(),
identity: identityString,
}
}
export async function importIdentity(name: string, data: string): Promise<Identity | null> {
if (data.length === 64) {
const wallet = await getWallet('PRIVATE_KEY', data)
return {
uuid: uuidV4(),
name,
type: 'PRIVATE_KEY',
identity: data,
address: wallet.getAddressString(),
}
}
if (data.length === 66 && data.toLowerCase().startsWith('0x')) {
const wallet = await getWallet('PRIVATE_KEY', data.slice(2))
return { uuid: uuidV4(), name, type: 'PRIVATE_KEY', identity: data, address: wallet.getAddressString() }
}
try {
const { address } = JSON.parse(data)
return { uuid: uuidV4(), name, type: 'V3', identity: data, address }
} catch {
return null
}
}
function getWalletFromIdentity(identity: Identity, password?: string): Promise<Wallet> {
return getWallet(identity.type, identity.identity, password)
}
async function getWallet(type: IdentityType, data: string, password?: string): Promise<Wallet> {
return type === 'PRIVATE_KEY'
? Wallet.fromPrivateKey(Buffer.from(trimHexString(data), 'hex'))
: await Wallet.fromV3(data, password as string)
}
export async function updateFeed(
beeApi: Bee,
identity: Identity,
hash: string,
stamp: string,
password?: string,
): Promise<void> {
const wallet = await getWalletFromIdentity(identity, password)
if (!identity.feedHash) {
identity.feedHash = await beeApi.createFeedManifest(stamp, 'sequence', '00'.repeat(32), wallet.getAddressString())
}
const writer = beeApi.makeFeedWriter('sequence', '00'.repeat(32), wallet.getPrivateKeyString())
await writer.upload(stamp, hash as Reference)
}
function trimHexString(string: string): string {
if (string.toLowerCase().startsWith('0x')) {
return string.slice(2)
}
return string
}
+77
View File
@@ -112,3 +112,80 @@ export function extractSwarmHash(string: string): string | null {
return (matches && matches[0]) || null
}
export function uuidV4(): string {
const pattern = '10000000-1000-4000-8000-100000000000'
return pattern.replace(/[018]/g, (s: string) => {
const c = parseInt(s, 10)
return (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
})
}
export function formatEnum(string: string): string {
return (string.charAt(0).toUpperCase() + string.slice(1).toLowerCase()).replaceAll('_', ' ')
}
export function secondsToTimeString(seconds: number): string {
let unit = seconds
if (unit < 120) {
return `${seconds} seconds`
}
unit /= 60
if (unit < 120) {
return `${Math.round(unit)} minutes`
}
unit /= 60
if (unit < 48) {
return `${Math.round(unit)} hours`
}
unit /= 24
if (unit < 14) {
return `${Math.round(unit)} days`
}
unit /= 7
if (unit < 52) {
return `${Math.round(unit)} weeks`
}
unit /= 52
return `${unit.toFixed(1)} years`
}
export function formatBzz(amount: number): string {
const asString = amount.toFixed(16)
let indexOfSignificantDigit = -1
let reachedDecimalPoint = false
for (let i = 0; i < asString.length; i++) {
const char = asString[i]
if (char === '.') {
reachedDecimalPoint = true
} else if (reachedDecimalPoint && char !== '0') {
indexOfSignificantDigit = i
break
}
}
return asString.slice(0, indexOfSignificantDigit + 4)
}
export function convertDepthToBytes(depth: number): number {
return 2 ** depth * 4096
}
export function convertAmountToSeconds(amount: number): number {
return amount / 10 / 1
}
export function calculateStampPrice(depth: number, amount: number): number {
return (amount * 2 ** (depth - 16) * 2) / 1e16
}