{"id":22608978,"url":"https://github.com/bitfinexcom/dazaar","last_synced_at":"2025-04-11T06:15:05.561Z","repository":{"id":38360469,"uuid":"152634868","full_name":"bitfinexcom/dazaar","owner":"bitfinexcom","description":null,"archived":false,"fork":false,"pushed_at":"2022-12-06T23:28:21.000Z","size":462,"stargazers_count":46,"open_issues_count":14,"forks_count":8,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-10-16T11:32:15.324Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bitfinexcom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-11T18:09:12.000Z","updated_at":"2024-09-24T11:38:18.000Z","dependencies_parsed_at":"2023-01-24T06:15:35.131Z","dependency_job_id":null,"html_url":"https://github.com/bitfinexcom/dazaar","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinexcom%2Fdazaar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinexcom%2Fdazaar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinexcom%2Fdazaar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinexcom%2Fdazaar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitfinexcom","download_url":"https://codeload.github.com/bitfinexcom/dazaar/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247276043,"owners_count":20912286,"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-12-08T15:10:25.234Z","updated_at":"2025-04-11T06:15:05.530Z","avatar_url":"https://github.com/bitfinexcom.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dazaar\n\n![Dazaar logo](docs/logo.png)\n\n\u003e Marketplace for selling and buying `hypercores`\n\n```\nnpm install dazaar\n```\n\nLearn more about Dazaar in our [intro blogpost](https://blog.dazaar.com/2020/09/12/introducing-dazaar/) and [whitepaper](./docs/whitepaper.md).\n\n## Usage\n\nFirst setup a seller\n\n```js\nconst hypercore = require('hypercore')\nconst pump = require('pump')\nconst market = require('dazaar')\n\nconst m = market('./tmp')\n\nconst feed = hypercore('./tmp/data')\n\nfeed.append('valuable')\n\nconst seller = m.sell(feed, {\n  validate (remoteKey, cb) {\n    console.log('this key wants our hypercore', remoteKey)\n    cb(null)\n  }\n})\n\nseller.ready(function (err) {\n  if (err) throw err // Do proper error handling\n  console.log('seller key pair fully loaded ...')\n\n  const buyer = m.buy(seller.key)\n\n  buyer.on('feed', function () {\n    console.log('got the feed!')\n    buyer.feed.get(0, function (err, data) {\n      if (err) throw err // Do proper error handling\n      console.log('first feed entry: ' + data)\n    })\n  })\n\n  buyer.on('validate', function () {\n    console.log('remote validated us')\n  })\n\n  const stream = seller.replicate()\n\n  pump(stream, buyer.replicate(), stream, function (err) {\n    console.log('replication ended', err)\n  })\n})\n```\n\n## API\n\n#### `const market = dazaar(storage, [options])`\n\nCreate a new dazaar instance. Pass a `string` if you want to use the default\nfile storage or a [`random-access-storage`][ras] compatible `storage`.\nExamples include (but not limited to):\n - [`random-access-file` (`raf`)][raf]\n - [`random-access-memory` (`ram`)][ram]\n - [`random-access-web` (`raw`)][raw]\n\nOptions include:\n\n```js\n{\n  masterKey: \u003c32-byte-master-key\u003e\n}\n```\n\nIf you set the master key all future key pairs, hypercore keys will be derived deterministicly from\nthat.\n\n#### `const masterKey = dazaar.masterKey()`\n\nGenerate a new master key.\n\n#### `const seller = market.sell(feed, options)`\n\nSell a [`hypercore`][hypercore] by creating a new `seller`.\n\nOptions include:\n\n```js\n{\n   // Predicate whether a remote key can get replicate this feed,\n   // remoteKey being a Buffer to check and cb being a callback which can be\n   // passed an error as the first argument, causing replication to fail, ie.\n   // the buyer has not paid. The err.message will be passed back to the buyer\n   // and can be used to specify a reason for the rejection\n   // If you pass a info object to the callback when succesfully validating\n   // the buyer, this object will be forwarded to the buyer (see the 'valid' event).\n  validate (remoteKey, cb) {},\n  // How often to call the above validate function in milliseconds.\n  // Default is 1000ms\n  validateInterval: 1000,\n  // Set uniqueFeed to false to generate the same Hypercore feed for each\n  // buyer. Should only be used for free Hypercores (defaults to true)\n  uniqueFeed: true,\n  // Set the Dazaar card you use here (minus the id) to have it be persisted\n  // inside the Dazaar instance. Useful if you wanna see it later when listing buyers etc.\n}\n```\n\nYou can use [`random-access-corestore` (`rac`)][rac] to manage multiple\nnamed feeds.\n\nFor more info on how to implement a validator see the [\"Writing your own payment validator\" section](#writing-your-own-payment-validator)\n\n#### `seller.buyers(cb)`\n\nGet a list of all the buyers of this feed\n\n#### `seller.on('ready')`\n\nEmitted when the seller is fully ready and has loaded it's keypair\n\n#### `seller.ready(cb)`\n\nCall `cb` when the `seller` object is fully initialised, optionally with an\n`error`. Similar to the event, but will call immediately if the event has\nalready fired.\n\n#### `seller.card`\n\nThe persisted Dazaar card for the seller. Updated after ready.\n\n#### `seller.on('buyer-validate', remoteKey)`\n\nEvent when the seller receives a `remoteKey`, but before the the `validate`\nfunction is called. `remoteKey` a Buffer, and the same reference passed to\n`validate`.\n\n#### `seller.on('buyer-valid', remoteKey, info)`\n\nEmitted every time we succesfully validate a buyer.\n\n#### `seller.on('buyer-invalid', remoteKey, error)`\n\nEmitted when we invalidate a remote buyer.\n\n#### `seller.on('valid', info, stream)`\n\nEmitted when a remote buyer validates the seller.\nNote that this is only relevant if the seller does buyer validation.\n\nThe stream is the replication stream associated with the session.\nSee `stream.remotePublicKey` to get the public key of the buyer.\n\n#### `seller.on('invalid', info, stream)`\n\nEmitted when a remote buyer invalidates the seller.\nNote that this is only relevant if the seller does buyer validation.\n\nThe stream is the replication stream associated with the session.\nSee `stream.remotePublicKey` to get the public key of the buyer.\n\n#### `seller.discoveryKey`\n\nA hash of the sellers public key that can be used for discovery purposes, eg.\npeer discovery on a DHT. See the [Swarm](#swarm) section below.\n\n#### `seller.key`\n\nThe public key of this seller. Must be communicated to potential buyers, as\nthis is needed in the handshake to buy the data.\n\n#### `seller.broadcast(type, message)`\n\nSend a custom message to all the buying peers you are connected to.\n\n#### `seller.send(type, message, streamOrBuyerKey)`\n\nSend a custom message to a specific buyer you are connected to.\n\nYou specify the peer by either providing the replication stream or the public key identifying the buyer.\n\n#### `seller.connectedBuyers`\n\nA list of all the buyers (their public keys) you are currently connected to.\n\n#### `seller.receive(type, onmessage)`\n\nSetup a handler to be called when a buying peer sends a message of a specific type.\n`onmessage` is called with `message` which is the message the remote send and `stream`\nwhich represents the stream it was sent on.\n\nUse `stream.remotePublicKey` to get the remotes buyer key out.\n\n#### `seller.destroy([cb])`\n\nDestroy the seller instance. Closes the attached Hypercore and any open replication streams.\nWill unannounce from any attached swarm as well.\n\n#### `seller.on('peer-add', stream)`\n\nEmitted when a remote peer is authenticated and has been connected.\n\n#### `seller.on('peer-remove', stream)`\n\nEmitted when a remote peer has disconnected.\n\n#### `seller.peers`\n\nAn array of all remote connected peers.\n\n#### `const buyer = market.buy(sellerKey|dazaarCard, [options])`\n\nBuy a hypercore by creating a buyer instance.\nIt is expected that the remote seller can verify that you purchased\nthe data through a third party some how.\n\nIf a `sellerKey` is used, it must be a Buffer.\n\nOptions include:\n\n``` js\n{\n  // Set this to true if you do not want to download all data but only\n  // the data you as for\n  sparse: false\n  // In case you want to optionally validate the seller before downloading\n  // any data you can pass in a validate function similar to above as well.\n  validate (remoteKey, cb) {},\n  // How often to call the above validate function in milliseconds.\n  // Default is 1000ms\n  validateInterval: 1000\n}\n```\n\n#### `buyer.on('ready')`\n\nEmitted when the buyer is fully ready and has fully loaded it's keypair.\n\n#### `buyer.key`\n\nThe buyer static public key. A `dazaar` instance uses the same public key for all\n`.buy` calls. This is the remote key the seller sees in the validate function.\nIf you want to use multiple different identities you must have multiple `dazaar`\ninstances backed by different storage.\n\n#### `buyer.seller`\n\nThe seller public key.\n\n#### `buyer.discoveryKey`\n\nA hash of the seller public key that can be used to discover the seller on a\nnetwork. See the [Swarm](#swarm) section below.\n\n#### `buyer.on('feed', feed)`\n\nEmitted when we have a feed.\nIf we previously successfully validated, this is triggered right away.\nOtherwise it is triggered after the first remote validation.\n\n#### `buyer.on('validated')`\n\nEmitted first time a remote seller validates us.\n\n#### `buyer.on('valid', info, stream)`\n\nEmitted everytime the remote seller sends us some updated info about our valid subscription.\n\n#### `buyer.on('invalid', err, stream)`\n\nEmitted when a remote seller invalidates us with the error they provided.\n\n#### `buyer.on('seller-validate', remoteKey)`\n\nEvent when the buyer receives a `remoteKey`, but before the the `validate`\nfunction is called. `remoteKey` a Buffer, and the same reference passed to\n`validate`. Only emitted if you pass in a `validate` function in the constructor.\n\n#### `buyer.on('seller-valid', remoteKey, info)`\n\nEmitted every time we succesfully validate a buyer.\n\n#### `buyer.on('seller-invalid', remoteKey, error)`\n\nEmitted when we invalidate a remote buyer.\n\n#### `buyer.feed`\n\nThe feed we bought.\n\n#### `buyer.broadcast(type, message)`\n\nSend a custom message to the selling peers you are connected to.\n\n#### `buyer.send(type, message, streamOrPublicKey)`\n\nSend a custom message to a specific selling peer you are connected to.\n\nYou specify the peer by either providing the replication stream or the public key identifying the seller.\n\n#### `buyer.receive(type, onmessage)`\n\nSetup a handler to be called when a selling peer sends a message of a specific type.\n`onmessage` is called with `message` which is the message the remote send and `stream`\nwhich represents the stream it was sent on.\n\nUse `stream.remotePublicKey` to get the remotes buyer key out.\n\n#### `buyer.destroy([cb])`\n\nDestroy the buyer instance. Closes the attached Hypercore and any open replication streams.\nWill unannounce from any attached swarm as well.\n\n#### `buyer.on('peer-add', stream)`\n\nEmitted when a remote peer is authenticated and has been connected.\n\n#### `buyer.on('peer-remove', stream)`\n\nEmitted when a remote peer has disconnected.\n\n#### `buyer.peers`\n\nAn array of all remote connected peers.\n\n#### `market.selling(callback)`\n\nGet a list of the hypercores and their corresponding sales key you are selling (since you created the market).\n\n#### `market.sales(feedKey, callback)`\n\nGet a list of sales you did for a specific feed. Similar to doing `seller.buyers`.\nNote that \"free\" feeds, ie a seller with uniqueFeed turned off will not track the sales.\n\n#### `const bool = market.isSeller(instance)`\n\nHelper to determine if an instance is a seller.\n\n#### `market.buying(callback)`\n\nGet a list of hypercores and their corresponding sales key you are buying (since you created the market).\n\n#### `const bool = market.isBuyer(instance)`\n\nHelper to determine if an instance is a buyer.\n\n#### `const { publicKey, secretKey } = market.deriveHypercoreKeyPair(id)`\n\nDerive a ED25519 keypair that can uses for a hypercore off the master key.\n\n#### `market.destroy([cb])`\n\nDestroy the market instance. Closes internal state needed for the buyer and sellers.\n\n## Swarm\n\nA network swarm based on [`hyperswarm`][hyperswarm] is included as\n`dazaar/swarm`\n\n```js\nconst swarm = require('dazaar/swarm')\n\nswarm(buyer) // swarms the buyer\nswarm(seller) // swarms the seller\n```\n\n#### `const sw = swarm(buyerOrSeller, [onerror], [opts])`\n\nCreate a new [`hyperswarm`][hyperswarm] for a `buyer` or `seller`, optionally\npassing a `onerror` handling function and `opts` to pass to `hyperswarm`.\n\n## Writing your own payment validator\n\nTo write your own payment validator you need to implement the validate function that is passed\nto the Dazaar seller or buyer instance. This function is called every ~1s to validate whether\nor not the current remote buyer or seller is valid.\n\nThe validate function is called with the following signature\n\n```js\nfunction validate (remotePublicKey, done) {\n  // call done(null) if the public is valid\n  // otherwise call done(err)\n}\n```\n\nBasically inside the validate function you should validate against your payment processor\nor however you want to validate that that the session identified by your public key (i.e. `seller.key`) and\nthe remote public key is currently valid.\n\nAs an example if using a blockchain that supports adding metadata to a payment then\nyou can include the following metadata to indicate that this payment was for this session:\n\n```\ndazaar: \u003cseller-public-key-in-hex\u003e \u003cbuyer-public-key-in-hex\u003e\n```\n\nThen in the validate function you'd list all payments matching the above metadata, and\ntrack when they were performed. If you add them together in relation with the their relative\ntimestamps and substract the current pricing in terms of \"stream cost per time interval\",\nthen you can calcuate whether or not their current session is paid for or if the other side\nneeds to perform a payment.\n\nIf paid for, again you indicate that by calling `validate(null)` and if not `validate(new Error('Needs payment'))`\nor a similar error.\n\nThis simple system makes Dazaar flexible in regards to payments. You can choose to validate the peers\nany way you want. For example even a scheme like payment through Twitter posts could be enabled.\n\nThere is a series of implemented payment providers available through the [@dazaar/payment] module as well.\nYou can read more about that [here](https://github.com/bitfinexcom/dazaar-payment).\n\n## CLI\n\nThere is a small CLI available as well to help you buy, sell, and replicate Hypercores\nusing the command line with a couple of payment options bundled in.\n\nYou can read more about it in the CLI repo, https://github.com/bitfinexcom/dazaar-cli\n\n```\nnpm install -g @dazaar/cli\n```\n\n## License\n\nMIT\n\n[hypercore]: https://github.com/mafintosh/hypercore\n[ras]: https://github.com/random-access-storage/random-access-storage\n[raf]: https://github.com/random-access-storage/random-access-file\n[ram]: https://github.com/random-access-storage/random-access-memory\n[raw]: https://github.com/random-access-storage/random-access-web\n[rac]: https://github.com/andrewosh/random-access-corestore\n[hyperswarm]: https://github.com/hyperswarm/hyperswarm\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitfinexcom%2Fdazaar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitfinexcom%2Fdazaar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitfinexcom%2Fdazaar/lists"}