Skip to content

Commit

Permalink
basic query builder, cache, and polling fns
Browse files Browse the repository at this point in the history
  • Loading branch information
jackyzha0 committed Jan 22, 2022
1 parent f6181ea commit 36ce06b
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 13 deletions.
109 changes: 96 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const ArweaveLib = require('arweave')
const { LRUMap } = require('lru_map')
const { backOff } = require('exponential-backoff')
const fetch = require('cross-fetch')

const DEFAULT_OPTIONS = {
host: 'arweave.net',
Expand All @@ -14,8 +16,9 @@ class Document {
data
txID
client
synced
posted

// Creates a new document. Not synced by default!
constructor(parentClient, content, version, name, meta) {
this.client = parentClient
this.data = {
Expand All @@ -25,16 +28,33 @@ class Document {
meta,
}
this.txID = undefined
this.synced = false
this.posted = false
}

update(partialDocument) {
this.synced = false
// Update document with a partial version of its fields.
// Automatically bumps version field unless explicitly defined.
async update(partialDocument) {
this.posted = false
this.data = {
...this.data,
version: this.data.version + 1,
...partialDocument,
}
await this.client.updateDocument(this).then(() => this.posted = true)
}

// Wait until block is confirmed as mined using exponential retry-backoff
async pollForConfirmation(maxRetries = 10) {
if (!(this.posted && this.txID)) {
return Promise.reject("Document has not been posted! Use .update() first")
}

return await backOff(async () => {
const txStatus = await this.client.transactions.getStatus(this.txID)
return txStatus.status !== 200 ? Promise.reject(txStatus.status) : Promise.resolve()
}, {
numOfAttempts: maxRetries
})
}
}

Expand All @@ -52,7 +72,7 @@ class ArweaveClient {

// Construct a new client given the address of the admin account,
// keys to the wallet, and a set of options for connecting to an Arweave network.
// Options are identical to the ones supported by the official arweave-js library
// Options are identical to the ones supported by the official `arweave-js` library
constructor(adminAddress, key, cache_size = 500, options = DEFAULT_OPTIONS) {
this.#key = key
this.adminAddr = adminAddress
Expand All @@ -78,7 +98,6 @@ class ArweaveClient {

// success, update doc data, add to cache
doc.txID = tx.id
doc.synced = true
this.cache.set(doc.data.name, doc)

return {
Expand All @@ -87,21 +106,85 @@ class ArweaveClient {
}
}

async updateDocument(content, version, meta) {
// Internal function to see if given document is cached.
// Optionally define desired version to match against.
isCached(documentName, desiredVersion) {
const inCache = this.cache.has(documentName)
if (!inCache) {
return false
}

const cached = this.cache.get(documentName)
const versionMatch = desiredVersion ? cached.version === desiredVersion : true
return cached.synced && versionMatch
}

async getDocumentByName(name) {
// check if doc is in cache and entry is up to date
if (this.cache.has(name) && this.cache.get(name).synced) {
// take document with changes and update
async updateDocument(document) {
// check if doc is in cache and not dirty
if (this.isCached(name)) {
return Promise.resolve()
}

// fetch latest

}

// Internal fn for building GraphQL queries for fetching data.
// Both names and versions are arrays. Use `verifiedOnly = false` to include
// all submitted TXs (including ones from non-admin wallet accounts)
#queryBuilder(names, versions, verifiedOnly = true) {
const tags = [{
name: NAME,
values: names,
}]

// versions is an optional field
if (versions && versions.length > 0) {
tags.push({
name: VERSION,
values: versions,
})
}

return {
query: `
query {
transactions(
tags: ${JSON.stringify(tags)},
${verifiedOnly ? `owners: ["${this.adminAddr}"]` : ""}
) {
edges {
node {
id
owner {
address
}
tags {
name
value
}
}
}
}
}
`
}
}

async getDocumentByName(name, version) {
// check if doc is in cache and entry is up to date (and correct version)
if (this.isCached(name, version)) {
return this.cache.get(name)
}

// otherwise, fetch latest to cache
// otherwise, fetch latest to cache and overwrite

// return
return this.cache.get(name)
}

// get document by specific version and hash

async getDocumentByTxId(txId) {
const txStatus = await this.client.transactions.getStatus(txId);
}
}
93 changes: 93 additions & 0 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"homepage": "https://github.com/verses-xyz/ar-wrapper#readme",
"dependencies": {
"arweave": "^1.10.23",
"cross-fetch": "^3.1.5",
"exponential-backoff": "^3.1.0",
"lru_map": "^0.4.1"
}
}

0 comments on commit 36ce06b

Please sign in to comment.