
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
A js object to IPFS merkle dag mapper
Merkling is a small library for interacting with the IPLD directed acyclic graph (DAG) in js as if it were an in-memory data structure. The idea is to introduce an exciting new impedance mismatch to the world.
This is alpha software
At this stage Merkling is only an exploration of different IPLD api.
IPLD (Interplanetary Linked Data) is the graph data strucuture that underpins IPFS and its file sharing capabilities. In IPFS it is used for modelling a filesystem, but it is capable of modelling more fine grained data structures.
Being able to store and syncronise a complex graph of data between many clients with the trust guarantees that content addressing provides makes IPLD an attractive option for building dapps. However the IPLD api is low level.
Merkling is an attempt at a different api borrowing from the world of ORMs (nothing could possibly go wrong). The idea is to use ES6 proxies to seamlessly confuse developers with the illusion that IPLD blocks are JS objects and that edges from IPLD block to IPLD block are JS object references.
See the usage section for an example.
npm install --save merkling@alpha
Merkling requires pulling an ipfs instance, either through js-ipfs or ipfs-http-client
const Merkling = require('merkling')
var ipfsClient = require('ipfs-http-client')
var ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001')
const main = async () => {
const merkling = new Merkling({ ipfs })
// Create an IPLD graph
let feedCid
await merkling.withSession(async session => {
// Create an IPLD block in-memory
// (so not persisted to IPFS)
const feed = session.create({
title: 'Thoughts',
author: 'anon',
posts: []
})
// ... and create a few more IPLD blocks
const post1 = session.create({
text: 'A beginning'
})
const post2 = session.create({
text: 'A middle'
})
const post3 = session.create({
text: 'An end'
})
// Manipulate and create relationships between
// them as if they were JS objects
post1.next = post2
post2.next = post3
feed.posts = [post1, post2, post3]
// Persist all IPLD blocks in the session
// in the right order and with their links
// [feed] --> [post1]
// | |
// |------> [post2]
// | |
// |------> [post3]
await session.save()
// Print the CID of the root IPLD block
// of the graph
feedCid = Merkling.cid(feed)
console.log(`Original Feed CID: ${feedCid.toBaseEncodedString()}`)
})
// Update the IPLD graph, we persisted in a
// new session
let updateFeedCid
await merkling.withSession(async session => {
// Read the root IPLD block from IPFS,
// its linked IPLD nodes will be unloaded
// proxies
const savedFeed = await session.get(feedCid)
// Force the loading from IPFS of the linked posts
for (const post of savedFeed.posts) {
await Merkling.resolve(post)
}
// Update a subnode of the root
savedFeed.posts[1].text = 'A longer middle'
// Persist the changes
await session.save()
// Print the updated CID of the Root IPLD block
updateFeedCid = Merkling.cid(savedFeed)
console.log(`Updated Feed CID: ${updateFeedCid.toBaseEncodedString()}`)
})
// Print the new updated graph
await merkling.withSession(async session => {
const savedFeed = await session.get(updateFeedCid)
console.log('')
console.log(`Title: ${savedFeed.title} by ${savedFeed.author}`)
console.log('---------------------')
for (const post of savedFeed.posts) {
await Merkling.resolve(post)
console.log(post.text)
}
console.log('')
})
}
main()
Which will produce the output:
Feed CID: zBwWX9pGzXr5vkRELYnJGvcmtK2JcH2Cw43JJB8XZywzq2eRKiP6W31yuSjb43K7TvY9bBm2WHqLCQNbscxPmkUsJWtqV
Updated Feed CID: zBwWX54YgyC83zywoo9E63i7k3DAx72KMCEK6ZXrweEg6BECnjg7eszhH6gfzuGrkRKA7YHBmLnNMRdHhpPiL5Trc87UC
Title: Thoughts by anon
---------------------
A beginning
A longer middle
An end
The core IPLD access client.
options IMerklingOptionsCreate a new merkling session to act as an intermediary with the IPFS node.
Returns MerklingSession a new merkling session
Run an action in the form of a callback over a new session that is disposed of afterwards.
sessionAction function (session: MerklingSession): void an action func that operates on the new sessionReturns Promise<void> a promise that completes after the session action
Retrieve the CID for given proxy. Will returned undefined if the passed object is not a Merkling proxy and will return null if the proxy is dirty.
proxy Proxy the object to get the CID forReturns (ICid | null | undefined) the CID or undefined if the object will never have a CID or null if it is currently dirty
Asynchronously force the retrieval of the state stored in IPFS of the IPLD block the proxy represents.
proxy Proxy An IPLD block proxyReturns Promise<Proxy> the given proxy now loaded and clean.
Retreive the stored state that the Merkling proxy is representing. This will include references to other Merkling proxies.
proxy Proxy the proxy to inspectReturns {} the internal state of the IPLD block being represented
Determine whether a given object is a tracked Merkling proxy.
potentialProxy ProxyReturns boolean the answer
Determine whether a given object is a Merkling proxy representing an IPLD block.
potentialIpldNode ProxyReturns boolean the answer
Determine if a proxy has unsaved changes. Will return true if the passed object is not a proxy.
proxy Proxy the object to testReturns boolean the answer
$0 {ipfs: IIpfsNode}
$0.ipfsCreate a new dirty Merkling proxy that can be manipulated before later being persisted.
objState T a js object of the state for the IPLD blockReturns T a proxy representing the given state as an IPLD block
Get an IPLD block from IPFS and return it as a tracked Merkling proxy.
hashOrCid (string | ICid) a CID or base encoded versionReturns Promise<any> a clean proxy with the state loaded and accessible
hash (string | ICid)Returns IMerklingProxyState
Save all proxies that are currently marked as dirty, and any proxies that depend on them.
Returns Promise<void>
Merkling requires ES6 Proxies to do its black magic, hence requires a recent version of node or an ever green browser.
PRs accepted.
Small note: If editing the README, please conform to the standard-readme specification.
MIT © 2019 John Kane
FAQs
JS Object to IPLD mapping layer
We found that merkling demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.