{"id":43223715,"url":"https://github.com/interledger-deprecated/ilp-plugin-payment-channel-framework","last_synced_at":"2026-02-01T09:17:47.325Z","repository":{"id":57156637,"uuid":"96447816","full_name":"interledger-deprecated/ilp-plugin-payment-channel-framework","owner":"interledger-deprecated","description":"Framework for creating payment-channel based ILP ledger plugins","archived":false,"fork":false,"pushed_at":"2017-12-28T19:16:30.000Z","size":611,"stargazers_count":2,"open_issues_count":11,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-26T07:58:15.281Z","etag":null,"topics":["bilateral-transfer-protocol","btp","ilp","interledger","ledger-plugin","payment-channel","trustline"],"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/interledger-deprecated.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}},"created_at":"2017-07-06T15:57:53.000Z","updated_at":"2018-10-29T19:37:08.000Z","dependencies_parsed_at":"2022-08-30T03:21:05.510Z","dependency_job_id":null,"html_url":"https://github.com/interledger-deprecated/ilp-plugin-payment-channel-framework","commit_stats":null,"previous_names":["interledgerjs/ilp-plugin-payment-channel-framework"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/interledger-deprecated/ilp-plugin-payment-channel-framework","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledger-deprecated%2Filp-plugin-payment-channel-framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledger-deprecated%2Filp-plugin-payment-channel-framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledger-deprecated%2Filp-plugin-payment-channel-framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledger-deprecated%2Filp-plugin-payment-channel-framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/interledger-deprecated","download_url":"https://codeload.github.com/interledger-deprecated/ilp-plugin-payment-channel-framework/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interledger-deprecated%2Filp-plugin-payment-channel-framework/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28974585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T08:16:14.655Z","status":"ssl_error","status_checked_at":"2026-02-01T08:06:51.373Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["bilateral-transfer-protocol","btp","ilp","interledger","ledger-plugin","payment-channel","trustline"],"created_at":"2026-02-01T09:17:46.599Z","updated_at":"2026-02-01T09:17:47.315Z","avatar_url":"https://github.com/interledger-deprecated.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ilp-plugin-payment-channel-framework [![npm][npm-image]][npm-url] [![circle][circle-image]][circle-url] [![codecov][codecov-image]][codecov-url]\n\n[npm-image]: https://img.shields.io/npm/v/ilp-plugin-virtual.svg?style=flat\n[npm-url]: https://npmjs.org/package/ilp-plugin-virtual\n[circle-image]: https://circleci.com/gh/interledgerjs/ilp-plugin-virtual.svg?style=shield\n[circle-url]: https://circleci.com/gh/interledgerjs/ilp-plugin-virtual\n[codecov-image]: https://codecov.io/gh/interledgerjs/ilp-plugin-virtual/branch/master/graph/badge.svg\n[codecov-url]: https://codecov.io/gh/interledgerjs/ilp-plugin-virtual\n\n\u003e ILP virtual ledger plugin for directly transacting connectors, including a\n\u003e framework for attaching on-ledger settlement mechanisms.\n\n## Installation\n\n``` sh\nnpm install --save ilp-plugin-payment-channel-framework\n```\n\n## Usage in ILP Kit\n\nThis section explains how to use `ilp-plugin-payment-channel-framework` for an asymmetric trustline in [ILP Kit](https://github.com/interledgerjs/ilp-kit/).\n\nTo setup an asymmetric trustline server, add the following to ILP Kit's configuration file (Note that all of the following configuration should go into a single line in your config file):\n\n\n```\nCONNECTOR_LEDGERS={\n  \"g.us.usd.myledger\": {\n      // your five-bells-ledger goes here\n    }\n  },\n  \"g.eur.mytrustline.\": {\n    \"currency\": \"EUR\",\n    \"plugin\": \"ilp-plugin-payment-channel-framework\",\n    \"options\": {\n      // listen for incoming connections\n      \"listener\": {\n        port: 1234,\n\n        // if a certificate is provided, the server will listen using TLS\n        // instead of plain websockets\n        cert: '/tmp/snakeoil.crt',\n        key: '/tmp/snakeoil.key',\n        ca: '/tmp/snakeoil-ca.crt'\n      },\n      \"incomingSecret\": \"shared_secret\", // auth_token which the server expects the client to send\n      // the server determines the properties of the trustline\n      \"maxBalance\": \"1000000000\",\n      \"prefix\": \"g.eur.mytrustline.\",\n      \"info\": {\n      \t\"currencyScale\": 9,\n      \t\"currencyCode\": \"EUR\",\n      \t\"prefix\": \"g.eur.mytrustline.\",\n      \t\"connectors\": [\"g.eur.mytrustline.server\"]\n      }\n    },\n    \"store\": true\n  }\n}\n```\n\nSimilarly, add the following to your ILP Kit's config to setup an asymmetric trustline client (as with the server config, all of the following should go on a single line in your config file):\n\n```\nCONNECTOR_LEDGERS={\n  \"g.us.usd.anotherledger\": {\n      // your five-bells-ledger goes here\n    }\n  },\n  \"g.eur.mytrustline.\": {\n    \"currency\": \"EUR\",\n    \"plugin\": \"ilp-plugin-payment-channel-framework\",\n    \"options\": {\n      \"server\": \"btp+wss://username:shared_secret@wallet1.example:1234/example_path\"\n    },\n    \"store\": false\n  }\n}\n```\n\n\u003e **Note:** You can provide both the `server` and `listener` properties in which\n\u003e case the BTP peers will automatically elect one of them to be the server and\n\u003e one of them to be the client.\n\n# ILP Plugin Payment Channel Framework\n\nThe plugin payment channel framework includes all the functionality of\n`ilp-plugin-virtual`, but wrapped around a [Payment Channel\nModule](#payment-channel-module-api). A payment channel module includes\nmethods for securing a trustline balance, whether by payment channel claims or\nby periodically sending unconditional payments. The common functionality, such\nas implementing the ledger plugin interface, logging transfers, keeping\nbalances, etc. are handled by the payment channel framework itself.\n\nILP Plugin virtual exposes a field called `makePaymentChannelPlugin`.  This function\ntakes a [Payment Channel Module](#payment-channel-module-api), and returns a\nLedgerPlugin class.\n\n- [Example Code (w/ Claims)](#example-code-with-claim-based-settlement)\n- [Example Code (w/ Payments)](#example-code-with-unconditional-payment-based-settlement)\n- [Extended Payment Channel Module API](#payment-channel-module-api)\n- [Plugin Context API](#plugin-context-api)\n\n\n## Minimal client-server config example\n```js\nconst ObjStore = require('./test/helpers/objStore')\nconst Plugin = require('.')\nconst port = 9000\nconst incomingSecret = 'pass'\n\nconst server = new Plugin({\n  listener: { port },\n  prefix: 'some.ledger.',\n  info: {},\n  incomingSecret,\n  maxBalance: '10000',\n  _store: new ObjStore()\n})\n\nconst client = new Plugin({\n  server: 'btp+ws://:' + incomingSecret + '@localhost:' + port,\n  maxBalance: '10000',\n  _store: new ObjStore()\n})\n\nserver.connect()\n  .then(() =\u003e client.connect())\n  .then(() =\u003e client.disconnect())\n  .then(() =\u003e server.disconnect())\n```\n\n## Example Code with Claim-Based Settlement\n\nClaim-based settlement is the simple case that this framework uses as its\nabstraction for settlement. Claim based settlement uses a unidirectional\npayment channel. You put your funds on hold, and give your peer signed claims\nfor more and more of the funds. These signed claims are passed off-ledger, and\nyour peer submits the highest claim when they want to get their funds.\n\nClaim based settlement has been implemented on ripple with the PayChan\nfunctionality, or on\n[bitcoin](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki) (and\nmany other blockchains) by signing transactions that pay out of some script\noutput.\n\n```js\nconst { makePaymentChannelPlugin } = require('ilp-plugin-virtual')\nconst { NotAcceptedError } = require('ilp-plugin-shared').Errors\nconst Network = require('some-example-network')\nconst BigNumber = require('bignumber.js')\n\nreturn makePaymentChannelPlugin({\n  // initialize fields and validate options in the constructor\n  constructor: function (ctx, opts) {\n    // we have one maxValueTracker to track the best incoming claim we've\n    // gotten so far. it starts with a value of '0', and contains no data.\n    ctx.state.bestClaim = ctx.backend.getMaxValueTracker('incoming_claim')\n\n    // the 'maxUnsecured' option is taken from the plugin's constructor.\n    // it defines how much the best incoming claim can differs from the amount\n    // of incoming transfers.\n    ctx.state.maxUnsecured = opts.maxUnsecured\n\n    // use some preconfigured secret for authentication\n    ctx.state.authToken = opts.authToken\n  },\n\n  // This token will be sent as a bearer token with outgoing requests, and used\n  // to authenticate the incoming requests. If the network you're using has a\n  // way to construct a shared secret, the authToken can be created\n  // automatically instead of being pre-shared and configured.\n  getAuthToken: (ctx) =\u003e (ctx.state.authToken),\n\n  // the connect function runs when the plugin is connected.\n  connect: async function (ctx) {\n    // network initiation should happen here. In a claim-based plugin, this\n    // would be the place to connect to the network and initiate payment\n    // channels if they don't exist already.\n    await Network.connectToNetwork()\n\n    // establish metadata during the connection phase\n    ctx.state.prefix = 'peer.network.' + (await Network.getChannelId()) + '.'\n\n    // create ILP addresses for self and peer by appending identifiers from the\n    // network onto the prefix.\n    ctx.state.account = ctx.state.prefix + (await Network.getChannelSource())\n    ctx.state.peer = ctx.state.prefix + (await Network.getChannelDestination())\n\n    ctx.state.info = {\n      prefix: ctx.state.prefix,\n      currencyScale: 6,\n      currencyCode: 'X??',\n      connectors: []\n    }\n  },\n\n  // Synchronous functions in order to get metadata. They won't be called until\n  // after the plugin is connected.\n  getAccount: (ctx) =\u003e (ctx.state.account),\n  getPeerAccount: (ctx) =\u003e (ctx.state.peer),\n  getInfo: (ctx) =\u003e (ctx.state.info),\n\n  // this function is called every time an incoming transfer has been prepared.\n  // throwing an error will stop the incoming transfer from being emitted as an\n  // event.\n  handleIncomingPrepare: async function (ctx, transfer) {\n    // we get the incomingFulfilledAndPrepared because it represents the most\n    // that can be owed to us, if all prepared transfers get fulfilled. The\n    // 'transfer' has already been applied to this balance.\n    const incoming = await ctx.transferLog.getIncomingFulfilledAndPrepared()\n    const bestClaim = await ctx.state.bestClaim.getMax() || { value: '0', data: null }\n\n    // make sure that if all incoming transfers are fulfilled (including the\n    // new one), it won't put us too far from the best incoming claim we've\n    // gotten.  'incoming - bestClaim.value' is the amount that our peer can\n    // default on, so it's important we limit it.\n    const exceeds = new BigNumber(incoming)\n      .minus(bestClaim.value)\n      .greaterThan(ctx.state.maxUnsecured)\n\n    if (exceeds) {\n      throw new NotAcceptedError(transfer.id + ' exceeds max unsecured balance')\n    }\n  },\n\n  // this function is called whenever the outgoingBalance changes by a\n  // significant amount. Exactly when and how often it will be called may\n  // become configurable or change in the future, so your code should not rely\n  // on it being called after every transfer.\n  createOutgoingClaim: async function (ctx, outgoingBalance) {\n    // create a claim for the total outgoing balance. This call is idempotent,\n    // because it's relating to the absolute amount owed, and doesn't modify\n    // anything.\n    const claim = Network.createClaim(outgoingBalance)\n\n    // return an object with the claim and the amount that the claim is for.\n    // this will be passed into your peer's handleIncomingClaim function.\n    return {\n      balance: outgoingBalance,\n      claim: claim\n    }\n  },\n\n  // this function is called right after the peer calls createOutgoingClaim.\n  handleIncomingClaim: async function (ctx, claimObject) {\n    const { balance, claim } = claimObject\n\n    if (Network.verify(claim, balance)) {\n      // if the incoming claim is valid and it's better than your previous best\n      // claim, set the bestClaim to the new one. If you already have a better\n      // claim this will leave it intact. It's important to use the backend's\n      // maxValueTracker here, because it will be shared across many processes.\n      await ctx.state.bestClaim.setIfMax({ value: balance, data: claim })\n    }\n  },\n\n  // called on plugin disconnect\n  disconnect: async function (ctx) {\n    const claim = await ctx.state.bestClaim.getMax()\n    if (!claim) {\n      return\n    }\n\n    // submit the best claim before disconnecting. This is the only time we\n    // have to wait on the underlying ledger.\n    await Network.submitClaim(claim)\n  }\n})\n```\n\n## Example Code with Unconditional Payment-Based Settlement\n\nUnconditional payment settlement secures a trustline balance by sending payments\non a system that doesn't support conditional transfers. Hashed timelock transfers\ngo through plugin virtual like a clearing layer, and every so often a settlement\nis sent to make sure the amount secured on the ledger doesn't get too far from\nthe finalized amount owed.\n\nUnlike creating a claim, sending a payment has side-effects (it alters an\nexternal system). Therefore, the code is slightly more complicated.\n\n```js\nconst { makePaymentChannelPlugin } = require('ilp-plugin-virtual')\nconst { NotAcceptedError } = require('ilp-plugin-shared').Errors\nconst Network = require('some-example-network')\nconst BigNumber = require('bignumber.js')\n\nreturn makePaymentChannelPlugin({\n  // initialize fields and validate options in the constructor\n  constructor: function (ctx, opts) {\n    // In this type of payment channel module, we create a log of incoming\n    // settlements to track all the transfers sent to us on the ledger we're\n    // using for settlement.  We use a transferLog in order to make sure a\n    // single transfer can't be added twice.\n    ctx.state.incomingSettlements = ctx.backend.getTransferLog('incoming_settlements')\n\n    // The amount settled is used to track how much we've paid out in total.\n    // We'll go deeper into how it's used in the `createOutgoingClaim`\n    // function.\n    ctx.state.amountSettled = ctx.backend.getMaxValueTracker('amount_settled')\n\n    // In this type of payment channel backend, the unsecured balance we want\n    // to limit is the total amount of incoming transfers minus the sum of all\n    // the settlement transfers we've received.\n    ctx.state.maxUnsecured = opts.maxUnsecured\n\n    // use some preconfigured secret for authentication\n    ctx.state.authToken = opts.authToken\n  },\n\n  getAuthToken: (ctx) =\u003e (ctx.state.authToken),\n\n  connect: async function (ctx, opts) {\n    await Network.connectToNetwork()\n\n    // establish metadata during the connection phase\n    ctx.state.prefix = 'peer.network.' + (await Network.getChannelId())\n    ctx.state.account = await Network.getChannelSource()\n    ctx.state.peer = await Network.getChannelDestination()\n    ctx.state.info = {\n      prefix: ctx.state.prefix,\n      currencyScale: 6,\n      currencyCode: 'X??',\n      connectors: []\n    }\n  },\n\n  // we don't need to define a disconnect handler in this case\n  disconnect: function () =\u003e Promise.resolve(),\n\n  // Synchronous functions in order to get metadata. They won't be called until\n  // after the plugin is connected.\n  getAccount: (ctx) =\u003e (ctx.state.prefix + ctx.state.account),\n  getPeerAccount: (ctx) =\u003e (ctx.state.prefix + ctx.state.peer),\n  getInfo: (ctx) =\u003e (ctx.state.info),\n\n  handleIncomingPrepare: async function (ctx, transfer) {\n    const incoming = await ctx.transferLog.getIncomingFulfilledAndPrepared()\n\n    // Instead of getting the best claim, we're getting the sum of all our\n    // incoming settlement transfers. This tells us how much incoming money has\n    // been secured.\n    const amountReceived = await ctx.state.incomingSettlements.getIncomingFulfilledAndPrepared()\n\n    // The peer can default on 'incoming - amountReceived', so we want to limit\n    // that amount.\n    const exceeds = new BigNumber(incoming)\n      .subtract(amountReceived)\n      .greaterThan(ctx.state.maxUnsecured)\n\n    if (exceeds) {\n      throw new NotAcceptedError(transfer.id + ' exceeds max unsecured balance')\n    }\n  },\n\n  // Even though this function is designed for creating a claim, we can\n  // very easily repurpose it to make a payment for settlement.\n  createOutgoingClaim: async function (ctx, outgoingBalance) {\n    // If a new max value is set, the maxValueTracker returns the previous max\n    // value. We tell the maxValueTracker that we're gonna pay the entire\n    // outgoingBalance we owe, and then look at the difference between the last\n    // balance and the outgoingBalance to determine how much to pay.\n    // If we've already paid out more than outgoingBalance, then it won't be the\n    // max value. The maxValueTracker will return outgoingBalance as the result,\n    // and outgoingBalance - outgoingBalance is 0. Therefore, we send no payment.\n    const lastPaid = await ctx.state.amountSettled.setIfMax({ value: outgoingBalance, data: null })\n    const diff = new BigNumber(outgoingBalance)\n      .sub(lastPaid.value)\n\n    if (diff.lessThanOrEqualTo('0')) {\n      return\n    }\n\n    // We take the transaction ID from the payment we send, and give it as an\n    // identifier so our peer can look it up on the network and verify that we\n    // paid them. Another approach could be to return nothing from this\n    // function, and have the peer automatically track all incoming payments\n    // they're notified of on the settlement ledger.\n    const txid = await Network.makePaymentToPeer(diff)\n\n    return { txid }\n  },\n\n  handleIncomingClaim: async function (ctx, claim) {\n    const { txid } = claim\n    const payment = await Network.getPayment(txid)\n\n    if (!payment) {\n      return\n    }\n\n    // It doesn't really matter whether this is fulfilled or not, we just need\n    // it to affect the incoming balance so we know how much has been received.\n    // We use the txid as the ID of the incoming payment, so it's impossible to\n    // apply the same incoming settlement transfer twice.\n    await ctx.state.incomingSettlements.prepare({\n      id: txid,\n      amount: payment.amount\n    }, true) // isIncoming: true\n  }\n\n}\n```\n\n## Backend API, with Extensions for Payment Channels\n\n-------\n\n### `getMaxValueTracker (opts)`\n\nGet a MaxValueTracker.\n\n#### Parameters\n\n- `opts.key` (String) name of this value tracker. Creating a new value tracker with the same key will load the data from the store. Must use the base64url character set.\n\n#### Returns\n\n- `return` (MaxValueTracker) max value tracker.\n\n-------\n\n### `getTransferLog (opts)`\n\nGet a TransferLog.\n\n#### Parameters\n\n- `opts.key` (String) Name of this transfer log. Creating a new transfer log with the same key will load the data from the store. Must use the base64url character set.\n- `opts.maximum` (String) The maximum sum of all transfers (including all incoming prepared transfers, but not outgoing prepared transfers) allowed in this transfer log. Default `Infinity`.\n- `opts.minimum` (String) The maximum sum of all transfers (including all outgoing prepared transfers, but not incoming prepared transfers) allowed in this transfer log. Default `-Infinity`.\n\n#### Returns\n\n- `return` (MaxValueTracker) max value tracker.\n\n-------\n\n### `async TransferLog.setMaximum (max)`\n\nSet the TransferLog's maximum balance.\n\n#### Parameters\n\n- `max` (Integer String) new maximum balance.\n\n-------\n\n### `async TransferLog.setMinimum (min)`\n\nSet the TransferLog's minimum balance.\n\n#### Parameters\n\n- `max` (Integer String) new minimum balance.\n\n-------\n\n### `async TransferLog.getMaximum ()`\n\nGet the TransferLog's maximum balance. This is as high as the balance can go,\nincluding all fulfilled transfers and incoming prepared transfers but not\nincluding outgoing prepared transfers.\n\n#### Returns\n\n- `return` (Integer String) maximum balance.\n\n-------\n\n### `async TransferLog.getMinimum ()`\n\nGet the TransferLog's minimum balance. This is as low as the balance can go,\nincluding all fulfilled transfers and outgoing prepared transfers but not\nincluding incoming prepared transfers.\n\n#### Returns\n\n- `return` (Integer String) minimum balance.\n\n-------\n\n### `async TransferLog.getBalance ()`\n\nGet the TransferLog's balance, including only fulfilled transfers. This\nfunction is best used for display purposes only. Validation should be done\nusing `getIncomingFulfilled`, `getIncomingFulfilledAndPrepared`,\n`getOutgoingFulfilled`, or `getOutgoingFulfilledAndPrepared`.\n\n#### Returns\n\n- `return` (Integer String) total fulfilled balance.\n\n-------\n\n### `async TransferLog.get (id)`\n\nGet a transfer with info from the transfer log.\n\n#### Parameters\n\n- `id` (UUID String) transfer ID.\n\n#### Returns\n\n- `return` (TransferWithInfo) transfer with additional info.\n- `return.transfer` ([Transfer](https://github.com/interledger/rfcs/blob/master/0004-ledger-plugin-interface/0004-ledger-plugin-interface.md#class-transfer)) transfer with ID of `id`.\n- `return.isIncoming` (Boolean) set to `true` if the transfer is incoming, and `false` if it's outgoing.\n- `return.state` (String) set to `prepared`, `fulfilled`, or `cancelled`.\n- `return.fulfillment` (String) transfer's fulfillment, present only if the state is `fulfilled`.\n\n-------\n\n### `async TransferLog.prepare (transfer, isIncoming)`\n\nGet a transfer from the transfer log. If the transfer would cause the balance to go over\nthe transfer log's maximum or under its minimum, this function will throw an error. If the\ntransfer cannot be applied for any other reason, an error will be thrown.\n\nIf a transfer with the same ID and the same contents as a previous transfer is added, it\nwill return successfully, without modifying the database. If a transfer with the same ID as\na previous transfer is added with different contents, an error will be thrown.\n\n#### Parameters\n\n- `transfer` ([Transfer](https://github.com/interledger/rfcs/blob/master/0004-ledger-plugin-interface/0004-ledger-plugin-interface.md#class-transfer)) the transfer to be prepared.\n- `isIncoming` (Boolean) set to `true` if the transfer is incoming, and `false` if it's outgoing.\n\n-------\n\n### `async TransferLog.fulfill (transferId, fulfillment)`\n\nFulfill a transfer currently in the prepared state. If the transfer's state is\nalready `fullfilled`, the function will return without error. If the transfer's\nstate is `cancelled`, the function will throw an error. If the transfer's state\nis `prepared`, it will be set to `fulfilled` and the fulfillment will be\nstored.\n\n**Important:** The TransferLog is concerned only with storage, and making sure\nthat the sum of the transfers does not exceed its given limits. As such, the\nfulfillment is not compared against the executionCondition of the transfer.\nThis allows more flexibility in how the TransferLog is used, but developers\nshould be careful to perform proper fulfillment validation in their own code.\nRemember that `SHA256(fulfillment)` must equal `executionCondition`, and the\nfulfillment should always be exactly 32 bytes.\n\n#### Parameters\n\n- `transferId` (UUID String) ID of the transfer to fulfill.\n- `fulfillment` (String) Fulfillment to store with the transfer.\n\n-------\n\n### `async TransferLog.cancel (transferId)`\n\nCancel a transfer currently in the prepared state. If the transfer's state is\nalready `cancelled`, the function will return without error. If the transfer's\nstate is `fulfilled`, an error will be thrown. If the transfer's state is\n`prepared`, it will be set to `cancelled`.\n\n#### Parameters\n\n- `transferId` (UUID String) ID of the transfer to cancel.\n\n-------\n\n### `async TransferLog.getIncomingFulfilled ()`\n\nGet the sum of all incoming payments in the `fulfilled` state.\n\n#### Returns\n\n- `return` (Integer String) incoming balance.\n\n-------\n\n### `async TransferLog.getIncomingFulfilledAndPrepared ()`\n\nGet the sum of all incoming payments, including those which are in the `prepared` state.\n\n#### Returns\n\n- `return` (Integer String) highest incoming balance.\n\n-------\n\n### `async TransferLog.getOutgoingFulfilled ()`\n\nGet the sum of all outgoing payments in the `fulfilled` state.\n\n#### Returns\n\n- `return` (Integer String) outgoing balance.\n\n-------\n\n### `async TransferLog.getOutgoingFulfilledAndPrepared ()`\n\nGet the sum of all outgoing payments, including those which are in the `prepared` state.\n\n#### Returns\n\n- `return` (Integer String) highest outgoing balance.\n\n-------\n\n### `async MaxValueTracker.setIfMax (entry)`\n\nPut `entry` into the MaxValueTracker. If `entry.value` is larger than the\nprevious entry's value, then `entry` becomes the new max entry, and the\nprevious max entry is returned. If `entry.value` is not larger than the\nprevious max entry's value, then the max entry remains the same and `entry` is\nreturned back.\n\n#### Parameters\n\n- `entry` (Object) entry to add to the max value tracker.\n- `entry.value` (Integer String) value to compare to the current max value.\n- `entry.data` (Object) data to attach to the entry.\n\n#### Return\n\n- `return` (Object) previous max entry or `entry`.\n- `return.value` (Integer String) value of returned entry.\n- `return.data` (Object) data attached to returned entry.\n\n-------\n\n### `async MaxValueTracker.getMax ()`\n\nReturns the max value tracker's maximum entry.\n\n#### Return\n\n- `return` (Object) max entry of the max value tracker.\n- `return.value` (Integer String) value of returned entry.\n- `return.data` (Object) data attached to returned entry.\n\n-------\n\n## Plugin Context API\n\nThe PluginContext is a bundle of objects passed into the Payment Channel\nBackend methods, in order to access useful plugin state.\n\n| Field | Type | Description |\n|:--|:--|:--|\n| `state` | Object | Object to keep Payment Channel Module state. Persists between function calls, but not if the plugin is restarted. |\n| `rpc` | RPC | RPC object for this plugin. Can be used to call methods on peer. |\n| `backend` | ExtendedPluginBackend | Plugin backend, for creating TransferLogs and MaxValueTrackers. |\n| `transferLog` | TransferLog | Plugin's TransferLog, containing all its ILP transfers. |\n| `plugin` | LedgerPlugin | Plugin object. Only LedgerPlugin Interface functions should be accessed. |\n\n## Payment Channel Module API\n\nCalling `makePaymentChannelPlugin` with an object containing all of the\nfunctions defined below will return a class. This new class will perform all\nthe functionality of ILP Plugin Virtual, and additionally use the supplied\ncallbacks to handle settlement.\n\nAside from `connect` and `disconnect`, the functions below might be called\nduring the flow of an RPC request, so they should run fast. Any of these calls\nSHOULD NOT take longer than 500 ms if `await`-ed. If a slower operation\nis required, it should be run in the background so it doesn't block the flow of\nthe function.\n\n------\n\n### `pluginName`\n\nThis optional field defines the type of this plugin. For instance, if it is set\nto `example`, the class name will become `PluginExample`, and debug statements\nwill be printed as `ilp-plugin-example`.\n\n#### Type\n\nString\n\n-------\n\n### `constructor (ctx, opts)`\n\nCalled when the plugin is constructed.\n\n#### Parameters\n\n- `ctx` (PluginContext) current plugin context.\n- `opts` (Object) options passed into plugin constructor.\n\n-------\n\n### `async connect (ctx, opts)`\n\nCalled when `plugin.connect()` is called.\n\n#### Parameters\n\n- `ctx` (PluginContext) current plugin context.\n\n-------\n\n### `getInfo (ctx)`\n\nReturn the\n[LedgerInfo](https://github.com/interledger/rfcs/blob/master/0004-ledger-plugin-interface/0004-ledger-plugin-interface.md#class-ledgerinfo)\nof this payment channel. This function will not be called until after the\nplugin is connected. The prefix must be deterministic, as the connector\nrequires plugin prefixes to be preconfigured.\n\nThe framework code will automatically create a deep clone of the return value\nbefore returning to the plugin user.\n\n#### Parameters\n\n- `ctx` (PluginContext) current plugin context.\n\n-------\n\n### `getAccount (ctx)`\n\nReturn the ILP address of this account on the payment channel. The ILP prefix\nmust match `getInfo().prefix`. This function will not be called until\nafter the plugin is connected.\n\n\n#### Parameters\n\n- `ctx` (PluginContext) current plugin context.\n\n-------\n\n### `getPeerAccount (ctx)`\n\nReturn the ILP address of the peer's account on the payment channel. The ILP\nprefix must match `getInfo().prefix`. This function will not be called until\nafter the plugin is connected.\n\n#### Parameters\n\n- `ctx` (PluginContext) current plugin context.\n\n-------\n\n### `async disconnect (ctx)`\n\nCalled when `plugin.disconnect()` is called.\n\n#### Parameters\n\n- `ctx` (PluginContext) current plugin context.\n\n-------\n\n### `async handleIncomingPrepare (ctx, transfer)`\n\nCalled when an incoming transfer is being processed, but has not yet been\nprepared. If this function throws an error, the transfer will not be prepared\nand the error will be passed back to the peer.\n\n#### Parameters\n\n- `ctx` (PluginContext) current plugin context.\n- `transfer` (Transfer) incoming transfer.\n\n-------\n\n### `async createOutgoingClaim (ctx, balance)`\n\nCalled when settlement is triggered. This may occur in the flow of a single payment,\nor it may occur only once per several payments. The return value of this function is\npassed to the peer, and into their `handleIncomingClaim()` function. The return value must\nbe stringifiable to JSON.\n\n#### Parameters\n\n- `ctx` (PluginContext) current plugin context.\n- `balance` (Integer String) sum of all outgoing fulfilled transfers. This value is strictly increasing.\n\n-------\n\n### `async handleIncomingClaim (ctx, claim)`\n\nCalled after peer's `createOutgoingClaim()` function is called.\n\n#### Parameters\n\n- `ctx` (PluginContext) current plugin context.\n- `claim` (Object) return value of peer's `createOutgoingClaim()` function.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterledger-deprecated%2Filp-plugin-payment-channel-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finterledger-deprecated%2Filp-plugin-payment-channel-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterledger-deprecated%2Filp-plugin-payment-channel-framework/lists"}