{"id":25716308,"url":"https://github.com/interledgerjs/web-monetization-receiver","last_synced_at":"2025-05-05T20:45:06.750Z","repository":{"id":67177226,"uuid":"149496339","full_name":"interledgerjs/web-monetization-receiver","owner":"interledgerjs","description":"Server-side library for advanced Web Monetization functionality","archived":false,"fork":false,"pushed_at":"2019-11-19T22:58:35.000Z","size":234,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-30T23:31:34.652Z","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":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/interledgerjs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-09-19T18:40:51.000Z","updated_at":"2024-10-11T12:11:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"e3b8fea2-40e4-4f59-83df-e5df9a08057f","html_url":"https://github.com/interledgerjs/web-monetization-receiver","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledgerjs%2Fweb-monetization-receiver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledgerjs%2Fweb-monetization-receiver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledgerjs%2Fweb-monetization-receiver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledgerjs%2Fweb-monetization-receiver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/interledgerjs","download_url":"https://codeload.github.com/interledgerjs/web-monetization-receiver/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252574222,"owners_count":21770356,"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":"2025-02-25T14:52:54.154Z","updated_at":"2025-05-05T20:45:06.741Z","avatar_url":"https://github.com/interledgerjs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Web Monetization Receiver\n\u003e Server-side library for advanced Web Monetization integrations\n\n- [Overview](#overview)\n- [Examples](#examples)\n- [API](#api)\n  - [`Monetizer`](#monetizer)\n  - [`Monetizer.koa`](#monetizerkoa)\n  - [`Monetizer.generateSPSPResponse`](#monetizergeneratespspresponse)\n  - [`Monetizer.listen`](#monetizerlisten)\n  - [`Monetizer.getBucket`](#monetizergetbucket)\n  - [`Bucket`](#bucket)\n  - [`Bucket.fund`](#bucketfund)\n  - [`Bucket.spend`](#bucketspend)\n  - [`Bucket.awaitBalance`](#bucketawaitbalance)\n  - [`Bucket.awaitAndSpend`](#bucketawaitandspend)\n  - [`Bucket.monetizeStream`](#bucketmonetizestream)\n  - [`Payer`](#payer)\n  - [`Payer.pay`](#payerpay)\n\n## Overview\n\nLots of sites can benefit from [Web Monetization](https://webmonetization.org).\nMost of the time, you can add a little bit of javascript that causes Web\nMonetization enabled users to donate to you ([The scripts are available\nhere](https://github.com/interledgerjs/web-monetization-scripts)).\n\nSome sites might want to do more than this. For example, an image gallery might\nwant to offer some images only to its Web Monetization enabled users. Or a\nvideo site might charge per second of video streamed.\n\nThis repository contains tools which aim to make these advanced integrations easier.\n\n## Examples\n\nRun `npm install` in this repository's root, then follow the README of the\nexample you want to run.\n\n- [Serve Paid Images](https://github.com/sharafian/web-monetization-receiver/tree/master/examples/paid-resources-images)\n- [Serve Paid Video](https://github.com/sharafian/web-monetization-receiver/tree/master/examples/paid-resources-video)\n\n## API\n\n### `Monetizer`\n\n```js\nconst { Monetizer } = require('web-monetization-receiver')\nconst monetizer = new Monetizer()\n```\n\nCreates a \"Monetizer\" that wraps an [ILP/STREAM\nserver](https://github.com/interledgerjs/ilp-protocol-stream) and exposes an\neasy to use API.\n\nYou can use Monetizer to charge for different actions on your server using Web\nMonetization. It's best suited for web apps where your user is browsing your\nsite and paying continuously with Web Monetization.\n\n#### Parameters\n\n- `opts: Object` - (Optional) Options for this Monetizer.\n\n- `opts.plugin: IlpPlugin`  - (Optional) ILP Plugin to listen for payments\n  with. By default, Monetizer creates a plugin to your local `moneyd` server.\n\n- `opts.buckets: Object` - (Optional) Options regarding buckets of payment that\n  have been received by different site users.\n\n- `opts.buckets.timeout: Number` - (Optional) How long to wait before clearing\n  an unused bucket.\n\n- `opts.buckets.capacity: Number` - (Optional) Maximum amount of payment to\n  accumulate in a single bucket.\n\n### `Monetizer.koa`\n\n```js\napp.use(monetizer.koa())\n```\n\nConnects this Monetizer instance to a [Koa](https://koajs.com/) app.\n\n- Adds an\n  [SPSP](https://github.com/interledger/rfcs/tree/master/0009-simple-payment-setup-protocol)\nreceiver to the server (responds to requests with `Accept: application/spsp4+json`)\n\n- Sets a `webMonetization` cookie on every client that hits the site. This is\n  then used to associate each client with a bucket of payment, so that they can\nrequest paid resources from the server.\n\n- Adds `ctx.webMonetization` to the server, with the payment bucket associate\n  with the current client. This can be used to charge for requests server-side.\nLook at the [Examples](#examples) section to see some ways to use it, or keep\nreading the API.\n\n#### Parameters\n\n- `opts: Object` - (Optional) Additional options for the receiver\n\n- `opts.spsp: boolean` - (Optional) (Default `true`) Whether to respond to SPSP\n  requests. If this is set to false, you must write an SPSP receiver endpoint\nyourself using the `generateSPSPResponse` function.\n\n#### Return\n\n- Async middleware function for use by Koa.\n\n### `Monetizer.generateSPSPResponse`\n\n```js\nconst jsonResponse = await monetizer.generateSPSPResponse(tag)\n```\n\nReturns an SPSP response that allows a client to pay us. If you're using the\n`monetizer.koa()` you don't need to call this function anywhere. If you're not\nusing Koa, then return `await monetizer.generateSPSPResponse(tag)` for any\nrequest that has `Accept` of `application/spsp4+json`. The `tag` should be a\ncookie that identifies the user.\n\n#### Parameters\n\n- `tag: string` - (Optional) Tag corresponding to this user.\n\n#### Return\n\n- `response: Object` - SPSP details that let your client pay you over\n  Interledger.  If they pay to these details, then their payment will\naccumulate in a bucket identified by their `tag`.\n\n- `response.destination_account: string` - ILP address for the client to pay\n  to.\n\n- `response.shared_secret: string` - Shared secret used for authentication and\n  encryption of data passed over Interledger.\n\n### `Monetizer.listen`\n\n```js\nawait monetizer.listen()\n```\n\nInitializes the STREAM server of this Monetizer. If you use\n`generateSPSPResponse` then it will call this function automatically.\n\n#### Parameters\n\n- None\n\n#### Return\n\n- Promise to null, resolves when server is initialized.\n\n### `Monetizer.getBucket`\n\n```js\nconst bucket = monetizer.getBucket(tag)\n```\n\nGets a bucket associated with a given tag. If you're using the Koa middleware\nthen on any route you can access `ctx.webMonetization` to access the current user's\nbucket (equivalent of `monetizer.getBucket(ctx.cookie.get('webMonetization'))`).\n\nIf no money has been paid into the bucket, you'll just get an empty bucket.\n\nAfter a timeout (configurable via `opts.buckets.timeout` in the Monetizer\nconstructor) any bucket that hasn't been used will be cleaned up.\n\n#### Parameters \n\n- `tag: string` - Tag corresponding to this user.\n\n#### Return\n\n- `bucket: Bucket` - [Bucket](#bucket) of payment for this user\n\n### `Bucket`\n\nA bucket represents the payment received by the server from a specific user.\nYou can use a bucket object to add/spend funds.\n\nThe bucket constructor shouldn't be called directly, instead you should get it\nfrom `monetizer.getBucket` (or from `ctx.webMonetization` if you're using Koa).\n\n### `Bucket.fund`\n\n```js\nbucket.fund('1000')\n```\n\nThis function adds the given number of units to the bucket. There usually is no\nreason to call this directly, because the Monetizer's SPSP server will\nautomatically fund the necessary buckets whenever payments are received.\n\n#### Parameters\n\n- `amount: string` - Amount of units (denominated in the units of your\n  plugin/local moneyd) to add to this bucket.\n\n#### Return\n\nNone\n\n### `Bucket.spend`\n\n```js\nif (bucket.spend('300')) {\n  return paidContent\n} else {\n  throw new Error('insufficient funds')\n}\n```\n\nSubtracts funds from the bucket. Returns `true` if there were enough funds,\nand `false` otherwise.\n\n#### Parameters\n\n- `amount: string` - Amount of units (denominated in the units of your\n  plugin/local moneyd) to subtract from this bucket.\n\n#### Return\n\n- `success: boolean` - Whether the bucket had enough funds and was subtracted\n  from.\n\n### `Bucket.awaitBalance`\n\n```js\nawait bucket.awaitBalance('1000')\nconsole.log('user can spend 1000 units')\n```\n\nWaits until the user has accumulated a certain number of units in their bucket.\nThis is useful for a web server where the client attempts to load all resources\nimmediately but will take some time to pay for all of them (See [Examples](#examples)).\n\nThis represents an absolute amount. If you `awaitBalance('1000')` it waits for\nthe user to have 1000 units total, not 1000 units more than they did when the\nfunction was called.\n\n#### Parameters\n\n- `amount: string` - Amount of units (denominated in the units of your\n  plugin/local moneyd) to wait for.\n\n#### Return\n\n- Promise to void which resolves when the amount is reached.\n\n### `Bucket.awaitAndSpend`\n\n```js\nawait bucket.awaitAndSpend('1000')\nreturn paidContent\n```\n\nCombines `awaitBalance` and `spend` into an atomic operation. First the balance\nis awaited, and then it is spent. If the spend fails, the await is repeated.\n\n#### Parameters\n\n- `amount: string` - Amount of units (denominated in the units of your\n  plugin/local moneyd) to wait for and then spend.\n\n#### Return\n\n- Promise to void which resolves when the amount is reached and spent.\n\n### `Bucket.monetizeStream`\n\n```js\nconst stream = fs.createReadStream('video.webm')\nreturn bucket.monetizeStream(stream)\n```\n\n```js\nconst stream = fs.createReadStream('video.webm')\nreturn bucket.monetizeStream(stream, {\n  freeBytes: 10000,\n  costPerByte: (1 / 5000)\n})\n```\n\nTurns a boring regular stream into a cool paid stream. Whenever a chunk of data\nis ready on the stream being read from, `chunk.length * costPerByte` units are\nsubtracted from the bucket. If the bucket hasn't got sufficient funds, the read\nstream is paused. Once the bucket gets sufficient funds, the stream is resumed.\n\nYou can use `freeBytes` to send a certain amount of data upfront without requiring\npayment (useful for buffering video quickly). `costPerByte` lets you fine-tune how\nmuch payment bandwidth is required to keep up with the stream.\n\nTo see an example of usage, refer to the [video example](#examples).\n\n#### Parameters\n\n- `stream: ReadableStream` - [Node.js Readable\n  Stream](https://nodejs.org/api/stream.html#stream_readable_streams) which is\nbeing monetized.\n\n- `opts: Object` - (Optional) Options to fine-tune the payment for this stream.\n\n- `opts.freeBytes: Number` - (Optional) How many free bytes to send up front.\n  Default `0`.\n\n- `opts.costPerByte: Number` - (Optional) How much to charge per byte sent over\n  this stream.  Default `1 / 5000` (on a typical [Coil](https://coil.com) plan,\n  this represents a rate of 500Kb/s)\n\n#### Return\n\n- `stream: ReadableStream` - Transformed stream which will charge for money as\n  it goes. This stream also implements a special `money` event which fires\n  whenever payment is charged for data going through the stream.\n\n### `Payer`\n\n```js\nconst payer = new Payer({\n  streamOpts: {\n    minExchangeRatePrecision: 2\n  }\n})\n```\n\nCreates a `Payer` object. A Payer can be used to efficiently pay out to many different\nSPSP receivers. It keeps connections to each of the receivers cached until they time out\nin order to minimize the amount of connection re-establishment.\n\n#### Parameters\n\n- `opts: Object` - (Optional) additional options for this payer\n- `opts.streamOpts: Object` - (Optional) additional override object for\n  `IlpStream.createConnection` calls. [You can read about the format\nhere.](https://interledgerjs.github.io/ilp-protocol-stream/interfaces/_connection_.connectionopts.html)\n\n#### Return\n\n- `payer: Payer` - Payer object\n\n### `Payer.pay`\n\n```js\nawait payer.pay('$twitter.xrptipbot.com/interledger', '100')\n```\n\nSends some money to a payment pointer. If a STREAM connection to this payment\npointer already exists then the money is sent over that connection. If no\nSTREAM connection to this payment pointer exists, then one is created.\n\nIf the STREAM connection does not exist and cannot be established then this\nfunction will reject.\n\n#### Parameters\n\n- `pointer: string` - Payment pointer to send funds to.\n\n- `amount: string` - Amount of units (denominated in the units of your\n  plugin/local moneyd) to send.\n\n#### Returns\n\n- Promise to void. Rejects if SPSP details cannot be loaded or the STREAM\n  connection fails.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterledgerjs%2Fweb-monetization-receiver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finterledgerjs%2Fweb-monetization-receiver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterledgerjs%2Fweb-monetization-receiver/lists"}