{"id":25716301,"url":"https://github.com/interledgerjs/ilp-plugin-payment","last_synced_at":"2026-06-13T08:33:05.870Z","repository":{"id":57271879,"uuid":"129154106","full_name":"interledgerjs/ilp-plugin-payment","owner":"interledgerjs","description":"Settle an ILP connection using XRP payments. Intended as a reference for other integrations.","archived":false,"fork":false,"pushed_at":"2023-04-24T00:17:49.000Z","size":45,"stargazers_count":1,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-05-26T01:48:39.724Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/interledgerjs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2018-04-11T21:05:33.000Z","updated_at":"2019-06-06T16:50:03.000Z","dependencies_parsed_at":"2023-07-25T18:45:52.082Z","dependency_job_id":null,"html_url":"https://github.com/interledgerjs/ilp-plugin-payment","commit_stats":null,"previous_names":["sharafian/ilp-plugin-payment"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/interledgerjs/ilp-plugin-payment","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledgerjs%2Filp-plugin-payment","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledgerjs%2Filp-plugin-payment/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledgerjs%2Filp-plugin-payment/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledgerjs%2Filp-plugin-payment/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/interledgerjs","download_url":"https://codeload.github.com/interledgerjs/ilp-plugin-payment/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledgerjs%2Filp-plugin-payment/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34278153,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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:49.208Z","updated_at":"2026-06-13T08:33:05.854Z","avatar_url":"https://github.com/interledgerjs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ILP Plugin Payment\n\n- [Overview](#overview)\n- [Configuration](#configuration)\n  - [Client/Peer](#client-peer)\n  - [Server](#server)\n- [Integrating Other Systems](#integrating-other-systems)\n  - [connectPayment](#connectpayment)\n  - [getPaymentDetails](#getpaymentdetails)\n  - [sendPayment](#sendpayment)\n  - [Event: Money](#event-money)\n\n## Overview\n\nILP Plugin Payment is a base class that can be extended to integrate different\npayment systems. These integrations are assumed to be payment-based, in that\none side sends a payment to the other side and then the other side detects the\nincoming settlement.\n\n## Configuration\n\n- If you want anybody to be able to connect to you without updating your\n  configuration, run the [Server](#server) plugin. Pass `\"role\": \"server\"` into\n  the plugin opts.\n\n- If you're peering 1:1 or are connecting to someone running a server plugin,\n  use the [Client/Peer](#client-peer) plugin. Pass `\"role\": \"client\"` or no `\"role\"`\n  field into the plugin opts.\n\nThe examples below will not work with the base class, but will work with the\nderived classes.\n\n### Client/Peer\n\n```js\nconst PluginPayment = require('ilp-plugin-payment')\n\nconst plugin = new PluginPayment({\n  role: 'client',\n  server: 'btp+ws://example.com:1234',\n  /* ... */\n})\n```\n\n### Server\n\n```js\nconst PluginPayment = require('ilp-plugin-payment')\nconst plugin = new PluginPayment({\n  role: 'server',\n  port: 1234,\n  /* ... */\n})\n```\n\n## Integrating Other Systems\n\nThe following methods and events must be implemented in order to integrate a\nnew payment system via this plugin.\n\nFor a blank starter, you can copy the snippet below. If you want to work off of\nan XRP ledger integration, use [the XRP example\ncode](./examples/ilp-plugin-xrp-payment.js).\n\n```js\nclass MyPaymentPlugin extends PluginPayment {\n  constructor (opts) {\n    super(opts)\n  }\n\n  // You must also have a method in here somewhere which calls\n  // this.emit('money', userId, amount) on incoming payments.\n\n  async connectPayment () {\n  }\n\n  async sendPayment (details, amount) {\n  }\n\n  async getPaymentDetails (userId) {\n  }\n}\n```\n\n### connectPayment\n\n`async connectPayment () -\u003e Promise\u003cvoid\u003e`\n\nConnect to the settlement network. For example, [on XRP](./examples/ilp-plugin-xrp-payment.js):\n\n```js\nasync connect () {\n  await this._api.connect()\n  await this._api.connection.request({\n    command: 'subscribe',\n    accounts: [ this._address ]\n  })\n\n  // This is how we detect an incoming transaction. You'll need some equivalent of this\n  // that calls this._handleMoney whenever a payment destined for this plugin comes in.\n  this._api.connection.on('transaction', ev =\u003e {\n    if (ev.validated \u0026\u0026 ev.transaction \u0026\u0026\n      ev.transaction.TransactionType === 'Payment' \u0026\u0026\n      ev.transaction.Destination === this._address \u0026\u0026\n      ev.transaction.Amount.currency === 'XRP') {\n      const userId = this._destinationTagToUserId(ev.transaction.DestinationTag)\n      const value = new BigNumber(ev.transaction.Amount.value).times(1e6).toString()\n      this.emitAsync('money', userId, value)\n    }\n  })\n}\n```\n\n### getPaymentDetails\n\n`async getPaymentDetails (userId: String) -\u003e Promise\u003cObject\u003e `\n\nCreate payment details associated with a given `userId`. There may be any\nnumber of different `userId`s, so the details given should be able to\ndifferentiate incoming payments from each other.\n\nIn the `connectPayment` example [for\nXRP](./examples/ilp-plugin-xrp-payment.js), for instance, the destinationTag is\nused to look up the userId for an incoming payment.\n\nThe result of this function will be passed into the peer's `sendPayment`\nfunction. On XRP, this function would be implemented like so:\n\n```js\nasync getPaymentDetails (userId) {\n  return {\n    address: this._address,\n    destinationTag: this._userIdToDestinationTag(userId)\n  }\n}\n```\n\n\n### sendPayment\n\n`async sendPayment (details: Object, amount: String) -\u003e Promise\u003cObject\u003e`\n\nBefore `sendPayment` is called, a `get_payment_details` RPC call is made. This\ncalls the `getPaymentDetails` function on the peer's plugin, and returns the\nresult. The result is passed into `sendPayment` as the `details` argument.\n\nThe amount is a a string-integer denominated in base ledger units. These base\nledger units can be anything you want (so long as they're used consistently),\nbut are typically the lowest divisible unit of the ledger.  For example, XRP\nwould use drops and Bitcoin would use Satoshis.\n\n[On XRP](./examples/ilp-plugin-xrp-payment.js), the sendPayment function would\nlook like this:\n\n```js\nasync sendMoney (details, amount) {\n  const xrpAmount = new BigNumber(amount).div(1e6).toString()\n\n  await this._txSubmitter('preparePayment', {\n    source: {\n      address: this._address,\n      maxAmount: {\n        value: xrpAmount,\n        currency: 'XRP'\n      }\n    },\n    destination: {\n      address: details.address,\n      tag: details.destinationTag,\n      amount: {\n        value: xrpAmount,\n        currency: 'XRP'\n      }\n    }\n  })\n}\n```\n\n### Event: Money\n\n`event 'money' (userId: String, amount: String)`\n\nThis event is emitted when incoming funds are detected.\n\nIf the details resulting from `getPaymentDetails(userId)` are passed (as\n`details`) into your peer's `sendPayment(details, amount)`, then you MUST\nbe able to detect the incoming payment and emit it as `userId, amount`.\n\nYou can see how this is implemented [in the example XRP\nplugin](./examples/ilp-plugin-xrp-payment.js):\n\n```js\nthis._api.connection.on('transaction', ev =\u003e {\n  if (ev.validated \u0026\u0026 ev.transaction \u0026\u0026\n    ev.transaction.TransactionType === 'Payment' \u0026\u0026\n    ev.transaction.Destination === this._address \u0026\u0026\n    ev.transaction.Amount.currency === 'XRP') {\n    const userId = this._destinationTagToUserId(ev.transaction.DestinationTag)\n    const value = new BigNumber(ev.transaction.Amount.value).times(1e6).toString()\n    this.emitAsync('money', userId, value)\n  }\n})\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterledgerjs%2Filp-plugin-payment","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finterledgerjs%2Filp-plugin-payment","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterledgerjs%2Filp-plugin-payment/lists"}