{"id":19123009,"url":"https://github.com/digitalbazaar/bedrock-ledger-node","last_synced_at":"2025-10-05T09:15:31.762Z","repository":{"id":46220547,"uuid":"75493592","full_name":"digitalbazaar/bedrock-ledger-node","owner":"digitalbazaar","description":"A Bedrock module that supports the creation and management of decentralized ledgers.","archived":false,"fork":false,"pushed_at":"2021-11-11T20:58:37.000Z","size":1199,"stargazers_count":5,"open_issues_count":26,"forks_count":4,"subscribers_count":11,"default_branch":"main","last_synced_at":"2024-10-05T00:21:50.943Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/digitalbazaar.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-12-03T18:51:41.000Z","updated_at":"2024-01-25T00:59:15.000Z","dependencies_parsed_at":"2022-09-16T09:12:54.051Z","dependency_job_id":null,"html_url":"https://github.com/digitalbazaar/bedrock-ledger-node","commit_stats":null,"previous_names":["digitalbazaar/bedrock-ledger"],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fbedrock-ledger-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fbedrock-ledger-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fbedrock-ledger-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fbedrock-ledger-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/digitalbazaar","download_url":"https://codeload.github.com/digitalbazaar/bedrock-ledger-node/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223788282,"owners_count":17202949,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T05:23:55.852Z","updated_at":"2025-10-05T09:15:31.699Z","avatar_url":"https://github.com/digitalbazaar.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bedrock Ledger Node\n\n[![Bedrock Node.js CI](https://github.com/digitalbazaar/bedrock-ledger-node/workflows/Bedrock%20Node.js%20CI/badge.svg)](https://github.com/digitalbazaar/bedrock-ledger-node/actions?query=workflow%3A%22Bedrock+Node.js+CI%22)\n\nA [bedrock][] module for the creation and management of\n[Web Ledgers](https://w3c.github.io/web-ledger/).\nThe Web Ledger ecosystem consists of Ledger Agents,\nLedger Nodes, Ledgers, Blocks, and Events. This API\nenables the management of ledger nodes, ledgers,\nblocks, and events.\n\n![An image of the Web Ledger ecosystem](https://w3c.github.io/web-ledger/diagrams/ecosystem.svg)\n\n## The Ledger Node API\n\n* Ledger Node API\n  * api.add(actor, options, (err, ledgerNode))\n  * api.get(actor, ledgerId, options, (err, ledgerNode))\n  * api.remove(actor, ledgerId, options, callback(err))\n  * api.getNodeIterator(actor, options, callback(err, iterator))\n* Ledger Node Metadata API\n  * ledgerNode.meta.get(options, (err, ledgerMeta))\n* Ledger Node Blocks API\n  * ledgerNode.blocks.get(blockId, options, callback(err, block))\n* Ledger Node Config API\n  * ledgerNode.config.change(ledgerConfiguration, options, (err))\n* Ledger Node Events API\n  * ledgerNode.events.get(eventId, options, (err, event))\n* Ledger Node Operations API\n  * ledgerNode.operations.add(operation, options, (err))\n* Ledger State Machine API\n  * ledgerNode.stateMachine.get(objectId, options, (err, object))\n* Ledger Node Plugin API\n  * api.use(options, mongodbStorageApi)\n\n## Quick Examples\n\n```\nnpm install bedrock-ledger-node bedrock-ledger-storage-mongodb bedrock-ledger-validator-signature\n```\n\n```js\nconst brLedgerNode = require('bedrock-ledger-node');\nrequire('bedrock-ledger-storage-mongodb');\nrequire('bedrock-ledger-validator-signature');\n\nconst actor = 'admin';\nconst ledgerId = 'did:v1:eb8c22dc-bde6-4315-92e2-59bd3f3c7d59';\n\nbrLedgerNode.get(actor, ledgerId, options, (err, ledgerNode) =\u003e {\n  ledgerNode.operations.add( /* new ledger operation details go here */);\n    /* ... do other operations on the ledger */\n  });\n});\n```\n\n## Configuration\n\nFor documentation on configuration, see [config.js](./lib/config.js).\n\n## Ledger Node API\n\n### Create a Ledger Node\n\nCreates a new ledger node. The given options will determine if the ledger\nnode will become the first node for a new ledger or if it will mirror\nand existing ledger.\n\nIf **options.ledgerConfiguration** is given, then a new ledger will be created\nand the ledger node will be its first member.\n\nIf a **options.genesisBlock** is given, then an existing ledger will be\nmirrored by the new ledger node.\n\n\n* actor - the actor performing the action.\n* options - a set of options used when creating the ledger.\n  *   configEvent - the configuration event for a brand new ledger.\n  *   genesisBlock - the genesis block for an existing ledger.\n  *   peerLedgerAgents - a list of Web Ledger Agent peer URLs to associate\n  *     with the ledger node; these may be optionally used by a consensus\n  *     method.\n  * storage - the storage subsystem for the ledger (default: 'mongodb').\n  * owner - the owner of the ledger node (default: **undefined**, anyone\n      can access the node).\n* callback(err, ledger) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise\n  * ledgerNode - the ledger node associated with the ledger.\n\n```javascript\nconst ledgerConfiguration = {\n  '@context': 'https://w3id.org/webledger/v1',\n  type: 'WebLedgerConfiguration',\n  ledger: 'did:v1:eb8c22dc-bde6-4315-92e2-59bd3f3c7d59',\n  consensusMethod: 'UnilateralConsensus2017',\n  ledgerConfigurationValidator: [{\n    type: 'SignatureValidator2017',\n    validatorFilter: [{\n      type: 'ValidatorFilterByType',\n      validatorFilterByType: ['WebLedgerConfiguration']\n    }],\n    approvedSigner: [\n      'did:v1:53ebca61-5687-4558-b90a-03167e4c2838/keys/144'\n    ],\n    minimumSignaturesRequired: 1\n  }],\n  operationValidator: [{\n    type: 'SignatureValidator2017',\n    validatorFilter: [{\n      type: 'ValidatorFilterByType',\n      validatorFilterByType: ['CreateWebLedgerRecord']\n    }],\n    approvedSigner: [\n      'did:v1:53ebca61-5687-4558-b90a-03167e4c2838/keys/144'\n    ],\n    minimumSignaturesRequired: 1\n  }],\n  proof: {\n    type: 'RsaSignature2018',\n    created: '2017-10-24T05:33:31Z',\n    creator: 'did:v1:53ebca61-5687-4558-b90a-03167e4c2838/keys/144',\n    domain: 'example.com',\n    jws: 'eyiOiJJ0eXAK...EjXkgFWFO'\n  }\n};\nconst options = {\n  ledgerConfiguration,\n  owner: 'https://example.com/i/123'\n};\n\nbrLedgerNode.add(actor, options, (err, ledgerNode) =\u003e {\n  if(err) {\n    throw new Error('Failed to create ledger node:', err);\n  }\n\n  console.log('Ledger node and new ledger created:', ledgerNode.ledger);\n});\n```\n\n### Get a Specific Ledger Node\n\nGets a ledger node given a ledgerId and a set of options.\n\n* actor - the actor performing the action.\n* ledgerId - the URI of the ledger.\n* options - a set of options used when creating the ledger.\n  * storage - the storage subsystem for the ledger (default 'mongodb').\n* callback(err, ledgerNode) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise\n  * ledgerNode - A ledger node that can be used to\n    perform actions on the ledger.\n\n```javascript\nconst actor = 'admin';\nconst ledgerId = 'did:v1:eb8c22dc-bde6-4315-92e2-59bd3f3c7d59';\nconst options = {};\n\nledger.get(actor,  ledgerId, options, (err, ledgerNode) =\u003e {\n  if(err) {\n    throw new Error('Failed to create ledger:', err);\n  }\n\n  console.log('Ledger created', ledgerNode.ledgerId);\n});\n```\n\n### Delete a Ledger\n\nDelete an existing ledger given a ledgerId and a set of options.\n\n* actor - the actor performing the action.\n* ledgerId - the URI of the ledger.\n* options - a set of options used when deleting the ledger.\n* callback(err) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise\n\n```javascript\nconst ledgerId = 'did:v1:eb8c22dc-bde6-4315-92e2-59bd3f3c7d59';\nconst options = {};\n\nledger.remove(actor, ledgerId, options, err =\u003e {\n  if(err) {\n    throw new Error('Failed to delete ledger:', err);\n  }\n\n  console.log('Ledger deleted.');\n});\n```\n\n### Iterate Through All Ledgers\n\nGets an iterator that will iterate over all ledgers in the system.\nThe iterator will return a ledgerNodeMeta which contains an\nid that can be passed to the api.get() call to fetch an\ninstance of the ledgerNode storage for the associated ledger.\n\n* actor - the actor performing the action.\n* options - a set of options to use when retrieving the list.\n* callback(err, iterator) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise\n  * iterator - An iterator that returns ledgerNodeMeta objects.\n\n```javascript\nconst actor = 'admin';\nconst options = {};\n\nbedrockLedger.getNodeIterator(actor, options, (err, iterator) =\u003e {\n  if(err) {\n    throw new Error('Failed to fetch iterator for ledger nodes:', err);\n  }\n\n  for(let ledgerNodeMeta of iterator) {\n    console.log('Ledger node:',  ledgerNodeMeta);\n  }\n});\n```\n\n## Metadata API\n\n### Get Ledger Metadata\n\nGets metadata associated with the ledger, such as most recent\nconfiguration block and latest consensus block,\ngiven a set of options.\n\n* options - a set of options used when retrieving the ledger metadata.\n* callback(err) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise.\n  * ledgerMeta - metadata about the ledger.\n\n```javascript\nledgerNode.meta.get(options, (err, ledgerMeta) =\u003e {\n  if(err) {\n    throw new Error('Ledger metadata retrieval failed:', err);\n  }\n\n  console.log('Ledger metadata:', ledgerMeta);\n});\n```\n\n## Blocks API\n\n### Get a Ledger Block\n\nGets a block from the ledger given a blockID and a set of options.\n\n* blockId - the URI of the block to fetch.\n* options - a set of options used when retrieving the block.\n* callback(err) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise.\n\n```javascript\nconst blockId = 'did:v1:eb8c22dc-bde6-4315-92e2-59bd3f3c7d59/blocks/1';\nconst options = {};\n\nledgerNode.blocks.get(blockId, options, (err, block) =\u003e {\n  if(err) {\n    throw new Error('Block retrieval failed:', err);\n  }\n\n  console.log('Retrieved block:', blocks);\n});\n```\n\n### Gets the genesis block\n\nGets the genesis block from a ledger given a set of options.\n\n* options - a set of options used when retrieving the block.\n* callback(err) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise.\n  * result - the genesis block from the ledger.\n\n```javascript\nconst options = {};\n\nledgerNode.blocks.getGenesis(options, (err, result) =\u003e {\n  if(err) {\n    throw new Error('Block retrieval failed:', err);\n  }\n\n  console.log('Retrieved genesis block:',\n    result.genesisBlock.block, result.genesisBlock.meta);\n});\n```\n\n### Gets the latest blocks\n\nGets the latest blocks from a ledger given a set of options.\n\n* options - a set of options used when retrieving the block.\n* callback(err) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise.\n  * result - the latest blocks from the ledger.\n\n```javascript\nconst options = {};\n\nledgerNode.blocks.getLatest(options, (err, result) =\u003e {\n  if(err) {\n    throw new Error('Block retrieval failed:', err);\n  }\n\n  console.log('Retrieved latest block:',\n    result.latest.block, result.latest.meta);\n});\n```\n\n## Config API\n\n### Change a Ledger's configuration\n\nSchedules a change to the ledger's configuration. The particular consensus\nmechanism for the ledger will determine what event to place the new\n`ledgerConfiguration` in and when that event achieves consensus. Different\nconsensus mechanisms will behave differently. Once the event containing the\noperation achieves consensus, the new configuration will be applied via the\nledger's state machine if it is considered valid at that time.\n\n* ledgerConfiguration - the new ledger configuration to use.\n* options - a set of options used when adding the ledger configuration.\n* callback(err) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise.\n\n```javascript\nconst ledgerConfiguration = {\n  '@context': 'https://w3id.org/webledger/v1',\n  type: 'WebLedgerConfiguration',\n  ledger: 'did:v1:eb8c22dc-bde6-4315-92e2-59bd3f3c7d59',\n  consensusMethod: 'UnilateralConsensus2017',\n  ledgerConfigurationValidator: [{\n    type: 'SignatureValidator2017',\n    validatorFilter: [{\n      type: 'ValidatorFilterByType',\n      validatorFilterByType: ['WebLedgerConfiguration']\n    }],\n    approvedSigner: [\n      'did:v1:53ebca61-5687-4558-b90a-03167e4c2838/keys/144'\n    ],\n    minimumSignaturesRequired: 1\n  }],\n  operationValidator: [{\n    type: 'SignatureValidator2017',\n    validatorFilter: [{\n      type: 'ValidatorFilterByType',\n      validatorFilterByType: ['CreateWebLedgerRecord']\n    }],\n    approvedSigner: [\n      'did:v1:53ebca61-5687-4558-b90a-03167e4c2838/keys/144'\n    ],\n    minimumSignaturesRequired: 1\n  }],\n  proof: {\n    type: 'RsaSignature2018',\n    created: '2017-10-24T05:33:31Z',\n    creator: 'did:v1:53ebca61-5687-4558-b90a-03167e4c2838/keys/144',\n    domain: 'example.com',\n    jws: 'eyiOiJJ0eXAK...EjXkgFWFO'\n  }\n};\nconst options = {};\n\nledgerNode.config.change(ledgerConfiguration, options, err =\u003e {\n  if(err) {\n    throw new Error('Failed to change the configuration:', err);\n  }\n\n  console.log('Ledger configuration change scheduled.');\n});\n```\n\n## Operations API\n\n### Add a Ledger Operation\n\nAdds an operation to mutate the state of the ledger. The particular consensus\nmechanism for the ledger will determine what event to place the operation in\nand when that event achieves consensus. Different consensus mechanisms will\nbehave differently. Once the event containing the operation achieves consensus,\nthe operation will be applied via the ledger's state machine if it is\nconsidered valid at that time.\n\n* operation - the operation to perform.\n* options - a set of options used when adding the operation.\n* callback(err) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise.\n\n```javascript\nconst operation = {\n  '@context': 'https://w3id.org/webledger/v1',\n  type: 'CreateWebLedgerRecord',\n  record: {\n    '@context': 'https://schema.org/',\n    id: 'https://example.com/events/123456',\n    type: 'Concert',\n    name: 'Big Band Concert in New York City',\n    startDate: '2017-07-14T21:30',\n    location: 'https://example.org/the-venue',\n    offers: {\n      type: 'Offer',\n      price: '13.00',\n      priceCurrency: 'USD',\n      url: 'https://www.ticketfly.com/purchase/309433'\n    }\n  },\n  proof: {\n    type: 'RsaSignature2018',\n    created: '2017-05-10T19:47:15Z',\n    creator: 'https://www.ticketfly.com/keys/789',\n    jws: 'JoS27wqa...BFMgXIMw=='\n  }\n};\nconst options = {};\n\nledgerNode.operations.add(operation, options, err =\u003e {\n  if(err) {\n    throw new Error('Failed to add the operation:', err);\n  }\n\n  console.log('Operation addition successful.');\n});\n```\n\n## Events API\n\n### Get a Ledger Event\n\nGets an event associated with the ledger given an eventID\nand a set of options.\n\n* eventId - the event to fetch from the ledger.\n* options - a set of options used when retrieving the event.\n* callback(err) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise.\n  * event - the event that was retrieved from the database.\n\n```javascript\nconst eventId = 'ni:///sha-256;cGBSKHn2cBJ563oSt3SAf4OxZXXfwtSxj1xFO5LtkGkW';\n\nledgerNode.events.get(eventId, options, (err, event) =\u003e {\n  if(err) {\n    throw new Error('Event retrieval failed:', err);\n  }\n\n  console.log('Event retrieval successful:', events);\n});\n```\n\n## State Machine API\n\n### Get an Object\n\nGets an object associated with the state machine of\nledger given an objectId and a set of options.\n\n* objectId - the object to fetch from the state machine.\n* options - a set of options used when retrieving the object.\n* callback(err) - the callback to call when finished.\n  * err - An Error if an error occurred, null otherwise.\n  * object - the object that was retrieved from the database.\n\n```javascript\nconst objectId = 'https://example.com/objects/1234';\n\nledgerNode.stateMachne.get(objectId, options, (err, object) =\u003e {\n  if(err) {\n    throw new Error('Object retrieval failed:', err);\n  }\n\n  console.log('Object retrieval successful:', object);\n});\n```\n\n## Ledger Plugin Registration API\n\nRegisters or retrieves a ledger plugin.\n\nA plugin can be registered to extend the capabilities of the ledger\nsubsystem by adding new storage, consensus, and authorization mechanisms.\n\n* capabilityName (required) - the name of the capability\n* [capabilityValue | callback] - either the value of the capability or\n  a callback function to receive the value when used as an asynchronous\n  getter. A capabilityValue must be an object with these properties:\n  * type - type type of plugin (e.g. 'storage', 'authorization', 'consensus')\n  * api - the javascript API for the plugin\n\nReturns the capabilityValue when used as a synchronous getter (no callback\nfunction is passed as the second parameter).\n\n```javascript\n// this code would be executed in a plugin\nconst brLedgerNode = require('bedrock-ledger-node');\n\n// register a plugin\nbrLedgerNode.use('mongodb', {\n  type: 'storage',\n  api: mongodbStorageApi\n});\n\n// get a plugin synchronously\nconst plugin = brLedgerNode.use('mongodb');\n// plugin.type\n// plugin.api\n```\n\n[bedrock]: https://github.com/digitalbazaar/bedrock\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalbazaar%2Fbedrock-ledger-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigitalbazaar%2Fbedrock-ledger-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalbazaar%2Fbedrock-ledger-node/lists"}