Let's talk about IPFS now.

Let's talk about IPFS now.

Instantiate IPFS node

const node = new Ipfs({ repo: 'ipfs-pluto', pass: 'cutedoll',
      EXPERIMENTAL: {
        pubsub: "true",
        relay: {
          enabled: true,
          hop: {
            enabled: true,
            active: true
          }
        }
      }
    })
 
  

IPFS instance will provide DAG api to create nodes that are addressable based on its content

pass option is required to do key management if you want to export the private key that holds identity proof of content created by this IPFS instance useful when used in combination with a peer-to-peer database like Orbit-DB.

node.dag.put(yourObject, opts, callback)

IPFS JS api provides option to write JS objects directly to IPFS and gets back the content addressable hash

With this, one can create a Linked List (let me call it as 'A Peer To Peer, Distributed, De-centralized, Zero Transaction fee, No Consensus, Private Blockchain without a 120 lines of ERC20 solidity code that has a fixed total supply and a mint() function that can increase the fixed total supply.')

Let's write an API to play with this.

when McAfee runs for President, we need a function to initiate our list which gets stored in planets away and write details to it.

const api = {

  put (obj) {
    let promise = new Promise((res, rej) => {
      let putObj = {}
      putObj[this.link || 'init'] = obj
      node.dag.put(putObj, { format: 'dag-cbor', hashAlg: 'sha2-256' }, (e, r) => 
        { localStorage.setItem('link', r.toBaseEncodedString())
          return e ? rej(e) : res({...api, link: r.toBaseEncodedString(), value: obj })
        })   
    })
    return promise
  }


}
 
  

Our put() will check if current put() operation is on top of a existing list or this is going to be the first node in list. If current node is existing node, we will have a instance variable link. We also store the latest node hash to localStorage so that we can always iterate and go back deep down to initial node by checking if current object link field in equal to one we hard coded when initiating the list.

And then we need a function that would fetch the data using a content hash that was written as a node to IPFS.

let api = {

  get () {
    let promise = new Promise((res, rej) => {
      if(!this.link) {
        return res(this)
      }
      node.dag.get(this.link, (e, r) => 
         {
          if(e) return rej(e)
          return res({...api, 
                         link: Object.keys(r.value)[0], 
                         value: Object.values(r.value)[0]
                     })
        })          
    })
    return promise
  }

}

 
  

Our API stores new Node's data as value for the key which references to content hash of previous node. get() function finds the data from IPFS using current link field and gives an object that has a link field which is content hash of previous node.

now we can iterate with this structure,

let api = {

  async iter (fn) {
    let meta = this
    let promise = new Promise(async (res, rej) => {
      var self = await meta.get()
      do {
        fn(self.value)
        self = await self.get()
      } while (self.link !== 'init')
      res(true)
    })
    return promise
  }

}
 
  

it's weirdo when we use do .. while() but I'm not thinking about it right now.

  async all () {
    let meta = this
    let promise = new Promise(async (res, rej) => {
      let chain = []
      await meta.iter((value) => chain.push(value))
      res(chain)
    })

    return promise
  }
 
  

all() function can be used to download the chain. (told you! it's a BlooockChain where your schizophrenia is the only consensus)

we can have a init() function to initialize the list.

  async init (meta={}) {
    if(!this.link) {
      let init = await api.put({
        author: "Shanth", 
        email: '[email protected]', 
        ...meta
      })
      this.link = init.link
    }
  },
 
  

maybe one might want to write an array of objects,

  async putArray (array) {
    return array.reduce(async (api, obj) => {
      let stream = await api;
      return stream.put(obj)
    }, this)
  }      
 
  

and finally,

let api = {
  get () {
    let promise = new Promise((res, rej) => {
      if(!this.link) {
        return res(this)
      }
      node.dag.get(this.link, (e, r) => 
         {
          if(e) return rej(e)
          return res({...api, 
                         link: Object.keys(r.value)[0], 
                         value: Object.values(r.value)[0]
                     })
        })          
    })
    return promise
  },

  put (obj) {
    let promise = new Promise((res, rej) => {
      let putObj = {}
      putObj[this.link || 'init'] = obj
      node.dag.put(putObj, { format: 'dag-cbor', hashAlg: 'sha2-256' }, (e, r) => 
        { localStorage.setItem('link', r.toBaseEncodedString())
          return e ? rej(e) : res({...api, link: r.toBaseEncodedString(), value: obj })
        })   
    })
    return promise
  },

  async iter (fn) {
    let meta = this
    let promise = new Promise(async (res, rej) => {
      var self = await meta.get()
      do {
        fn(self.value)
        self = await self.get()
      } while (self.link !== 'init')
      res(true)
    })
    return promise
  },

  async all () {
    let meta = this
    let promise = new Promise(async (res, rej) => {
      let chain = []
      await meta.iter((value) => chain.push(value))
      res(chain)
    })

    return promise
  },

  async init (meta={}) {
    if(!this.link) {
      let init = await api.put({
        author: "Shanth", 
        email: '[email protected]', 
        ...meta
      })
      this.link = init.link
    }
  },

  async putArray (array) {
    return array.reduce(async (api, obj) => {
      let stream = await api;
      return stream.put(obj)
    }, this)
  }      
}
 
  

let's write Pokémons to IPFS using our API

let test = async () => {
  let resp = await fetch("https://pokeapi.co/api/v2/ability/4/")
  let json = await resp.json()
  return api.putArray(json.pokemon)
}

and iterate()

works as expected!

ok. If there is no 51% attack between my curiosity and laziness, I will try to experiment IPFS with Orbit-DB and dump everything here in yet another post.


要查看或添加评论,请登录

Shanthakumar `的更多文章

社区洞察

其他会员也浏览了