diff --git a/dist/index.html b/dist/index.html index cd3dc8d..0e5b96d 100644 --- a/dist/index.html +++ b/dist/index.html @@ -12,20 +12,26 @@ #result { white-space: pre; } - + #localNode { + width: 210px; + }

dmap

- - - +
+ + +
-
+
+ + + +
- - +
diff --git a/dmap.js b/dmap.js index 69f9fa7..8462126 100644 --- a/dmap.js +++ b/dmap.js @@ -1,9 +1,6 @@ const ebnf = require('ebnf') -const multiformats = require('multiformats') - const ethers = require('ethers') -const { b32 } = require('minihat'); - +const multiformats = require('multiformats') const abi = require('./artifacts/core/dmap.sol/Dmap.json').abi const dmap_i = new ethers.utils.Interface(abi) @@ -91,11 +88,11 @@ lib.walk = async (dmap, path) => { if (zone === '0x' + '00'.repeat(20)) { fail(`zero register`) } - const fullname = '0x' + lib._strToHex(step.name) + '00'.repeat(32-step.name.length); + const fullname = '0x' + Buffer.from(step.name).toString('hex') + '00'.repeat(32-step.name.length); [meta, data] = await lib.get(dmap, zone, fullname) if (step.locked) { need(ctx.locked, `Encountered ':' in unlocked subpath`) - need((lib._hexToArrayBuffer(meta)[0] & lib.FLAG_LOCK) !== 0, `Entry is not locked`) + need((Buffer.from(meta.slice(2), 'hex')[0] & lib.FLAG_LOCK) !== 0, `Entry is not locked`) ctx.locked = true } ctx.locked = step.locked @@ -118,8 +115,8 @@ lib.prepareCID = (cidStr, lock) => { } lib.unpackCID = (metaStr, dataStr) => { - const meta = lib._hexToArrayBuffer(metaStr) - const data = lib._hexToArrayBuffer(dataStr) + const meta = Buffer.from(metaStr.slice(2), 'hex') + const data = Buffer.from(dataStr.slice(2), 'hex') const prefixLen = meta[prefLenIndex] const specs = multiformats.CID.inspectBytes(meta.slice(-prefixLen)) const hashLen = specs.digestSize @@ -135,15 +132,3 @@ lib.readCID = async (dmap, path) => { const packed = await lib.walk(dmap, path) return lib.unpackCID(packed.meta, packed.data) } - -lib._hexToArrayBuffer = hex => { - const bytes = [] - for (let c = 2; c < hex.length; c += 2) - bytes.push(parseInt(hex.slice(c, c + 2), 16)) - return new Uint8Array(bytes) -} - -lib._strToHex = str => { - let codes = str.split('').map(c => c.charCodeAt(0)) - return codes.map(c => c.toString(16)).join('') -} diff --git a/package.json b/package.json index 1ec1dcd..ffa6759 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "@nomiclabs/hardhat-ethers": "^2.0.5", "@types/mocha": "^9.0.0", "hardhat": "^2.8.3", + "ipfs-http-client": "^56.0.2", "minihat": "^0.0.5", - "v8": "^0.1.0", "web3-utils": "^1.7.1", "webpack": "^5.70.0", "webpack-cli": "^4.9.2" diff --git a/view/app.js b/view/app.js index 2947660..7d9eb7f 100644 --- a/view/app.js +++ b/view/app.js @@ -1,13 +1,50 @@ import { ethers } from 'ethers' -const dpack = require('@etherpacks/dpack') +import { CID } from 'multiformats/cid' +import { sha256 } from 'multiformats/hashes/sha2' const dmap = require('../dmap.js') const dmapAddress = '0x7fA88e1014B0640833a03ACfEC71F242b5fBDC85' const dmapArtifact = require('../artifacts/core/dmap.sol/Dmap.json') +const IPFS = require('ipfs-http-client') -window.onload =()=> { - const $ = document.querySelector.bind(document); - const result = $('#result') +const gateways = ['https://ipfs.fleek.co/ipfs/', + 'https://gateway.pinata.cloud/ipfs/', + 'https://cloudflare-ipfs.com/ipfs/', + 'https://storry.tv/ipfs/', + 'https://ipfs.io/ipfs/', + 'https://hub.textile.io/ipfs/'] + +const resolveCID = async (cid, targetDigest, nodeAddress) => { + const verify = async bytes => { + const hash = await sha256.digest(bytes) + const resultDigest = JSON.stringify(hash.digest) + return targetDigest === resultDigest + } + const node = IPFS.create(nodeAddress) + const catResponse = await node.cat(cid) + // initially handle only single chunk verification and sha256 + try { + const chunk = await catResponse.next() + if(await verify(chunk.value)) { + return chunk.value + } + } catch(e) {} + for (const gateway of gateways) { + const url = gateway + cid + try { + const response = await fetch(url); + const reader = response.body.getReader(); + let readRes = await reader.read(); + if (await verify(readRes.value)) { + return readRes.value + } + } catch (e) {} + } + throw 'unable to resolve cid' +} + +window.onload = async() => { + const $ = document.querySelector.bind(document); const line =s=> { $('#result').textContent += s + '\n' } $('#btnGet').addEventListener('click', async () => { @@ -32,18 +69,18 @@ window.onload =()=> { } try { - // display json content from a CID if we can - const cidResult = dmap.unpackCID(walkResult.meta, walkResult.data) - line(`ipfs: ${cidResult}`) - const ipfsResult = await dpack.getIpfsJson(cidResult) - line(JSON.stringify(ipfsResult, null, 4)) + // display ipfs content from a CID if we can, otherwise display as text + const cid = dmap.unpackCID(walkResult.meta, walkResult.data) + line(`ipfs: ${cid}`) + const targetDigest = JSON.stringify(CID.parse(cid).multihash.digest) + const resolved = await resolveCID(cid, targetDigest, $('#localNode').value) + let utf8decoder = new TextDecoder() + line(utf8decoder.decode(resolved)) } catch(e){ - // otherwise show text let utf8decoder = new TextDecoder() - const bytes = dmap._hexToArrayBuffer(walkResult.data) - let i - for (i = 0; i < bytes.length; i++) { + const bytes = Buffer.from(walkResult.data.slice(2), 'hex') + for (var i = 0; i < bytes.length; i++) { if (bytes[bytes.length -1 - i] !== 0) { break } diff --git a/webpack.config.js b/webpack.config.js index f74ce27..427efd1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,4 +1,5 @@ const path = require('path'); +const webpack = require('webpack'); module.exports = { mode: 'production', @@ -9,6 +10,11 @@ module.exports = { path: path.resolve(__dirname, 'dist'), filename: '[name].js', }, + plugins: [ + new webpack.ProvidePlugin({ + Buffer: ['buffer', 'Buffer'], + }) + ], optimization: { minimize: false, splitChunks: {