feat(cid2json): Got basic functionality in place, no tests yet, known issues

This commit is contained in:
Chris Troutner
2025-02-09 05:52:48 -07:00
parent 1bf28cbc21
commit 9ae5e890ae
4 changed files with 100 additions and 4 deletions
+31 -1
View File
@@ -39,6 +39,7 @@ class IpfsRESTControllerLib {
this.getService = this.getService.bind(this)
this.getFileInfo = this.getFileInfo.bind(this)
this.getPins = this.getPins.bind(this)
this.cid2json = this.cid2json.bind(this)
}
/**
@@ -220,7 +221,7 @@ class IpfsRESTControllerLib {
ctx.body = metadata
} catch (err) {
// wlogger.error('Error in ipfs/controller.js/viewFile(): ', err)
console.log('Error in ipfs/controller.js/getService(): ', err)
console.log('Error in ipfs/controller.js/getFileInfo(): ', err)
this.handleError(ctx, err)
}
}
@@ -253,8 +254,36 @@ class IpfsRESTControllerLib {
}
}
/**
* @api {get} /ipfs/cid2json/:cid Given a CID, retrieve a JSON object
* @apiPermission public
* @apiName GetCid2Json
* @apiGroup REST IPFS
* @apiDescription Given a CID, retrieve a JSON object.
* If the CID does not resolves to a JSON file, then an error is thrown.
*
* @apiExample Example usage:
* curl -H "Content-Type: application/json" -X GET localhost:5015/ipfs/cid2json/bafkreigbgrvpagnmrqz2vhofifrqobigsxkdvnvikf5iqrkrbwrzirazhm
*
*/
async cid2json (ctx) {
try {
const { cid } = ctx.params
const json = await this.useCases.ipfs.cid2json({ cid })
ctx.body = json
} catch (err) {
// wlogger.error('Error in ipfs/controller.js/viewFile(): ', err)
console.log('Error in ipfs/controller.js/cid2json(): ', err.message)
this.handleError(ctx, err)
}
}
// DRY error handler
handleError (ctx, err) {
console.log('handleError() err.status: ', err.status)
console.log('handleError() err.message: ', err.message)
// If an HTTP status is specified by the buisiness logic, use that.
if (err.status) {
if (err.message) {
@@ -263,6 +292,7 @@ class IpfsRESTControllerLib {
ctx.throw(err.status)
}
} else {
console.log(`handleError() err.message: ${err.message}`)
// By default use a 422 error if the HTTP status is not specified.
ctx.throw(422, err.message)
}
+1
View File
@@ -60,6 +60,7 @@ class IpfsRouter {
this.router.get('/service', this.ipfsRESTController.getService)
this.router.get('/file-info/:cid', this.ipfsRESTController.getFileInfo)
this.router.get('/pins', this.ipfsRESTController.getPins)
this.router.get('/cid2json/:cid', this.ipfsRESTController.cid2json)
// Attach the Controller routes to the Koa app.
app.use(this.router.routes())
+65
View File
@@ -33,6 +33,7 @@ class IpfsUseCases {
this.downloadCid = this.downloadCid.bind(this)
// this.downloadCid2 = this.downloadCid2.bind(this)
this.getWritePrice = this.getWritePrice.bind(this)
this.cid2json = this.cid2json.bind(this)
// State
this.lastWritePriceUpdate = null // Used to periodically update write price.
@@ -151,6 +152,70 @@ class IpfsUseCases {
}
}
// Given a CID, this function will retrieve a JSON object from the
// ipfs-file-pin-service, using the IPFS JSON-RPC.
async cid2json (inObj = {}) {
try {
const { cid } = inObj
console.log('cid2json() cid: ', cid)
// Throw an error if ipfs-bch-wallet-consumer has not yet connected to an instance of ipfs-file-pin-service.
const ipfsFileProvider = this.adapters.ipfs.ipfsCoordAdapter.state.selectedIpfsFileProvider
if (!ipfsFileProvider) {
throw new Error('No IPFS File Provider Service is available yet. Try again in a few seconds.')
}
// Throw an error if ipfs-bch-wallet-consumer can not communicate with the ipfs-file-pin-service.
const ipfsFiles = this.adapters.ipfsFiles
const metadata = await ipfsFiles.getFileMetadata({ cid })
if (metadata.success === false) {
throw new Error(`Could not communicate with instance of ipfs-file-pin-service ${ipfsFileProvider}. Try again in a few seconds.`)
}
// Throw an error if the file is not pinned.
const fileMetadata = metadata.fileMetadata
if (!fileMetadata.dataPinned) {
throw new Error(`CID ${cid} has not been pinned by ipfs-file-pin-service instance ${ipfsFileProvider}`)
}
console.log('fileMetadata: ', fileMetadata)
// Throw an error if this is not a JSON file
const filename = fileMetadata.filename
if (!filename.endsWith('.json')) {
throw new Error(`CID ${cid} does not resolve to a JSON file.`)
}
console.log('ping01')
// Retrieve the CID content and store it in a Buffer.
const helia = this.adapters.ipfs.ipfs
const fileChunks = []
console.log('ping02')
for await (const chunk of helia.fs.cat(cid)) {
fileChunks.push(chunk)
}
console.log('ping03')
const fileBuf = Buffer.concat(fileChunks)
console.log('ping04')
// Convert the Buffer into a string.
const jsonStr = fileBuf.toString()
console.log('ping05')
// Parse the string into a JSON object.
let json = null
try {
json = JSON.parse(jsonStr)
} catch (err) {
throw new Error(`CID ${cid} does not resolve to a valid JSON object.`)
}
return {
success: true,
json
}
} catch (err) {
console.error('Error in ipfs-use-cases.js/cid2json(): ', err.message)
throw err
}
}
// async downloadCid2 (inObj = {}) {
// try {
// const { cid } = inObj