Skip to content

Commit

Permalink
Merge pull request #102 from art-by-city/99-query-publications
Browse files Browse the repository at this point in the history
Adds Querying Publications
  • Loading branch information
jim-toth authored Nov 16, 2023
2 parents c811be0 + af694f7 commit 61ac193
Show file tree
Hide file tree
Showing 23 changed files with 799 additions and 701 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"@types/uuid": "^9.0.6",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"arlocal": "^1.1.62",
"chai": "^4.3.8",
"chai-as-promised": "^7.1.1",
"eslint": "^8.47.0",
Expand Down
32 changes: 29 additions & 3 deletions src/arfs/arfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import Arweave from 'arweave'
import ArDB from 'ardb'
import ArdbTransaction from 'ardb/lib/models/transaction'

import TransactionsModule from '../common/transactions'
import { ArFSFileMetadata } from './'

export default class ArFSClient {
private readonly ardb!: ArDB
protected readonly transactions!: TransactionsModule

constructor(
arweave: Arweave
) {
constructor(arweave: Arweave) {
this.ardb = new ArDB(arweave)
this.transactions = new TransactionsModule(arweave)
}

/**
Expand Down Expand Up @@ -44,4 +47,27 @@ export default class ArFSClient {

return null
}

async getFileMetadataTransaction(
fileId: string
): Promise<ArdbTransaction | null> {
const txs = await this.ardb
.search('transactions')
.sort('HEIGHT_DESC')
.limit(1)
.tag('File-Id', fileId)
.find() as ArdbTransaction[]

return txs[0] || null
}

async getFileMetadata(fileId: string) {
const tx = await this.getFileMetadataTransaction(fileId)

if (!tx) {
throw new Error(`ArFS file not found: ${fileId}`)
}

return this.transactions.getData<ArFSFileMetadata>(tx.id)
}
}
2 changes: 1 addition & 1 deletion src/arfs/authenticated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { generateArFSDriveTags, generateArFSFolderTags } from './'
import TransactionsModule from '../common/transactions'

export default class AuthenticatedArFSClient extends ArFSClient {
private readonly transactions!: TransactionsModule
declare protected readonly transactions: TransactionsModule

constructor(
arweave: Arweave,
Expand Down
27 changes: 20 additions & 7 deletions src/arfs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import { Tag } from 'warp-contracts'
export { default as ArFSClient } from './arfs'
export { default as AuthenticatedArFSClient } from './authenticated'

export interface ArFSOpts {
address: string
driveId: string
folderId: string
unixTime: string
}

export function generateArFSDriveTags(opts: {
driveId: string,
drivePrivacy: 'public',
Expand Down Expand Up @@ -43,19 +50,25 @@ export function generateArFSFolderTags(opts: {
return tags
}

export function generateArFSFileTags(opts: {
driveId: string,
parentFolderId: string,
unixTime: string
}) {
export function generateArFSFileTags(opts: ArFSOpts & { fileId?: string }) {
return [
new Tag('Client', '@artbycity/sdk'),
new Tag('ArFS', '0.13'),
new Tag('Content-Type', 'application/json'),
new Tag('Drive-Id', opts.driveId),
new Tag('Entity-Type', 'file'),
new Tag('File-Id', uuidv4()),
new Tag('Parent-Folder-Id', opts.parentFolderId),
new Tag('File-Id', opts.fileId || uuidv4()),
new Tag('Parent-Folder-Id', opts.folderId),
new Tag('Unix-Time', opts.unixTime)
]
}

export interface ArFSFileMetadata {
name: string
size: number
lastModifiedDate: number
dataTxId: string
dataContentType: string
title?: string
description?: string
}
1 change: 1 addition & 0 deletions src/cache/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as MemoryCache } from './memory-cache'
11 changes: 11 additions & 0 deletions src/cache/memory-cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default class MemoryCache<T> {
private readonly cache: { [key: string]: T } = {}

get(key: string): T | null {
return this.cache[key] || null
}

put(key: string, thing: T) {
this.cache[key] = thing
}
}
2 changes: 1 addition & 1 deletion src/client/authenticated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ export default class AuthenticatedArtByCityClient extends BaseArtByCityClient {
this.signer
)
this.publications = new AuthenticatedArtByCityPublications(
this.config,
this.arweave,
this.arfs,
this.config,
this.signer
)
}
Expand Down
9 changes: 8 additions & 1 deletion src/client/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ArtByCityCurations } from '../curations'
import { ArtByCityUsernames } from '../usernames'
import { ArFSClient } from '../arfs'
import TransactionsModule from '../common/transactions'
import { ArtByCityPublications } from '../publications'

export default class ArtByCity {
public readonly arweave!: Arweave
Expand All @@ -22,6 +23,7 @@ export default class ArtByCity {
public readonly usernames!: ArtByCityUsernames
public readonly arfs!: ArFSClient
public readonly transactions!: TransactionsModule
public readonly publications!: ArtByCityPublications

constructor(arweave?: Arweave, config?: Partial<ArtByCityConfig>) {
const environment = config?.environment || 'production'
Expand All @@ -39,7 +41,7 @@ export default class ArtByCity {
? WarpFactory.forMainnet({ inMemory: true, dbLocation: '.art-by-city' })
: WarpFactory.forLocal()
this.warp = this.warp.use(new DeployPlugin())
this.legacy = new ArtByCityLegacy(this.arweave, this.warp, this.config)
this.legacy = new ArtByCityLegacy(this.arweave, this.config)
this.curations = new ArtByCityCurations(
this.arweave,
this.warp,
Expand All @@ -51,5 +53,10 @@ export default class ArtByCity {
)
this.arfs = new ArFSClient(this.arweave)
this.transactions = new TransactionsModule(this.arweave)
this.publications = new ArtByCityPublications(
this.arweave,
this.arfs,
this.config
)
}
}
2 changes: 1 addition & 1 deletion src/common/data-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default class DataItemFactory {

async createAndSign(
data: string | Uint8Array,
tags: Tag[]
tags?: Tag[]
): Promise<DataItem> {
const dataItem = createData(data, this.signer, { tags })
await dataItem.sign(this.signer)
Expand Down
20 changes: 20 additions & 0 deletions src/common/tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,23 @@ export function generateAtomicLicenseTags(
new Tag('Init-State', initState)
]
}

export function generatePrimaryAssetTags(
opts: PublicationOptions,
atomicLicenseContractSrcId: string,
atomicLicenseInitialState: string
) {
const tags = [
...generateAns110Tags(opts),
...generateAtomicLicenseTags(
atomicLicenseContractSrcId,
atomicLicenseInitialState
)
]

if (opts.slug) {
tags.push(new Tag('Slug', opts.slug))
}

return tags
}
42 changes: 39 additions & 3 deletions src/common/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@ import ArdbTransaction from 'ardb/lib/models/transaction'
import Arweave from 'arweave'
import axios from 'axios'

import { MemoryCache } from '../cache'

const bundlerBase = `https://node2.irys.xyz`

export default class TransactionsModule {
protected readonly ardb!: ArDB
private readonly gatewayRoot!: string

private readonly txCache = new MemoryCache<ArdbTransaction>()

constructor(arweave: Arweave) {
constructor(arweave: Arweave, private readonly cacheEnabled: boolean = true) {
this.ardb = new ArDB(arweave)
const { protocol, host, port } = arweave.api.getConfig()
this.gatewayRoot = `${protocol}://${host}:${port}`
}

async dispatch(data: Buffer) {
Expand All @@ -24,13 +31,42 @@ export default class TransactionsModule {
}
}

async get(id: string): Promise<ArdbTransaction | null> {
async get(
id: string,
useCache: boolean = true
): Promise<ArdbTransaction | null> {
if (this.cacheEnabled && useCache) {
const cached = this.txCache.get(id)
if (cached) { return cached }
}

const txs = await this.ardb
.search('transactions')
.ids([ id ])
.sort('HEIGHT_DESC')
.find() as ArdbTransaction[]

return txs[0] || null
const tx = txs.at(0) || null

if (tx && this.cacheEnabled && useCache) {
this.txCache.put(id, tx)
}

return tx
}

/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
async getData<T = any>(id: string): Promise<T> {
const {
data,
status,
statusText
} = await axios.get<T>(`${this.gatewayRoot}/${id}`)

if (status >= 400) {
throw new Error(`Error fetching tx data: ${status} ${statusText}`)
}

return data
}
}
2 changes: 0 additions & 2 deletions src/legacy/legacy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Arweave from 'arweave'
import { Warp } from 'warp-contracts'

import { ArtByCityConfig } from '../config'
import VerifiedCreators from './verified-creators.json'
Expand Down Expand Up @@ -40,7 +39,6 @@ export default class ArtByCityLegacy {

constructor(
arweave: Arweave,
warp: Warp,
private readonly config: ArtByCityConfig
) {
this.transactions = new LegacyTransactions(arweave, config.environment)
Expand Down
Loading

0 comments on commit 61ac193

Please sign in to comment.