Artifact Content
Not logged in

Artifact f4afc81a3c88d4d2d5138683c34337039b6f1f89:



ILP

The Javascript client library for Interledger


npm standard circle codecov snyk

The ILP module includes:

Installation

npm install --save ilp ilp-plugin-bells

Note that ledger plugins must be installed alongside this module

Simple Payment Setup Protocol (SPSP)

If you are sending to an SPSP receiver with a user@example.com identifier, the SPSP module provides a high-level interface:

'use strict'

import { SPSP } from 'ilp'
import FiveBellsLedgerPlugin from 'ilp-plugin-bells'

const plugin = new FiveBellsLedgerPlugin({
  account: 'https://red.ilpdemo.org/ledger/accounts/alice',
  password: 'alice'
})

(async function () {
  const payment = await SPSP.quote(plugin, {
    receiver: 'bob@blue.ilpdemo.org',
    sourceAmount: '1'
  })

  console.log('got SPSP payment details:', payment)

  // we can attach an arbitrary JSON object to the payment if we want it
  // to be sent to the receiver.
  payment.memo = { message: 'hello!' }

  await SPSP.sendPayment(plugin, payment)
  console.log('receiver claimed funds!')
})()

Pre-Shared Key (PSK) Transport Protocol

This is a non-interactive protocol in which the sender chooses the payment amount and generates the condition without communicating with the recipient.

PSK uses a secret shared between the sender and receiver. The key can be generated by the receiver and retrieved by the sender using a higher-level protocol such as SPSP, or any other method. In the example below, the pre-shared key is simply passed to the sender inside javascript.

When sending a payment using PSK, the sender generates an HMAC key from the PSK, and HMACs the payment to get the fulfillment, which is hashed to get the condition. The sender also encrypts their optional extra data using AES. On receipt of the payment, the receiver decrypts the extra data, and HMACs the payment to get the fulfillment.

In order to receive payments using PSK, the receiver must also register a reviewPayment handler. reviewPayment is a callback that returns either a promise or a value, and will prevent the receiver from fulfilling a payment if it throws an error. This callback is important, because it stops the receiver from getting unwanted funds.

PSK Sending and Receiving Example

'use strict'

import 'uuid'
import ILP from 'ilp'
import FiveBellsLedgerPlugin from 'ilp-plugin-bells'

const sender = new FiveBellsLedgerPlugin({
  account: 'https://red.ilpdemo.org/ledger/accounts/alice',
  password: 'alice'
})

const receiver = new FiveBellsLedgerPlugin({
  account: 'https://blue.ilpdemo.org/ledger/accounts/bob',
  password: 'bobbob'
})

const receiverSecret = Buffer.from('secret_seed')
const { sharedSecret, destinationAccount } = ILP.PSK.generateParams({
  destinationAccount: receiver,
  receiverSecret
})

// Note the user of this module must implement the method for
// communicating sharedSecret and destinationAccount from the recipient
// to the sender

(async function () {
  const stopListening = await ILP.PSK.listen(receiver, { receiverSecret }, (params) => {
    console.log('got transfer:', params.transfer)

    console.log('fulfilling.')
    return params.fulfill()
  })

  // the sender can generate these, via the sharedSecret and destinationAccount
  // given to them by the receiver.
  const { packet, condition } = ILP.PSK.createPacketAndCondition({
    sharedSecret,
    destinationAccount,
    destinationAmount: '10', // denominated in the ledger's base unit
  })

  const quote = await ILP.ILQP.quoteByPacket(sender, packet)
  console.log('got quote:', quote)

  await sender.sendTransfer({
    id: uuid(),
    to: quote.connectorAccount,
    amount: quote.sourceAmount,
    expiresAt: quote.expiresAt,
    executionCondition: condition,
    ilp: packet
  })

  sender.on('outgoing_fulfill', (transfer, fulfillment) => {
    console.log(transfer.id, 'was fulfilled with', fulfillment)
    stopListening()
  })
})()

Interledger Payment Request (IPR) Transport Protocol

This protocol uses recipient-generated Interledger Payment Requests, which include the condition for the payment. This means that the recipient must first generate a payment request, which the sender then fulfills.

This library handles the generation of payment requests, but not the communication of the request details from the recipient to the sender. In some cases, the sender and receiver might be HTTP servers, in which case HTTP would be used. In other cases, they might be using a different medium of communication.

IPR Sending and Receiving Example

'use strict'

import 'uuid'
import ILP from 'ilp'
import FiveBellsLedgerPlugin from 'ilp-plugin-bells'

const sender = new FiveBellsLedgerPlugin({
  account: 'https://red.ilpdemo.org/ledger/accounts/alice',
  password: 'alice'
})

const receiver = new FiveBellsLedgerPlugin({
  account: 'https://blue.ilpdemo.org/ledger/accounts/bob',
  password: 'bobbob'
})

(async function () {
  const stopListening = await ILP.IPR.listen(receiver, {
    receiverSecret: Buffer.from('secret', 'utf8')
  }, async function ({ transfer, fulfill }) {
    console.log('got transfer:', transfer)

    console.log('claiming incoming funds...')
    await fulfill()
    console.log('funds received!')
  })

  // `ipr` is a buffer with the encoded IPR
  const ipr = ILP.IPR.createIPR({
    receiverSecret: Buffer.from('secret', 'utf8'),
    destinationAccount: receiver.getAccount(),
    // denominated in the ledger's base unit
    destinationAmount: '10',
  })

  // Note the user of this module must implement the method for communicating
  // packet and condition from the recipient to the sender.

  // In practice, The rest of this example would happen on the sender's side.

  const { packet, condition } = ILP.IPR.decodeIPR(ipr)
  const quote = await ILP.ILQP.quoteByPacket(sender, packet)
  console.log('got quote:', quote)

  await sender.sendTransfer({
    id: uuid(),
    to: quote.connectorAccount,
    amount: quote.sourceAmount,
    expiresAt: quote.expiresAt,
    executionCondition: condition,
    ilp: packet
  })

  sender.on('outgoing_fulfill', (transfer, fulfillment) => {
    console.log(transfer.id, 'was fulfilled with', fulfillment)
  })
})()

API Reference

{{#module name="SPSP"~}} {{>body~}} {{>members~}} {{/module}}

{{#module name="ILQP"~}} {{>body~}} {{>members~}} {{/module}}

{{#module name="PSK"~}} {{>body~}} {{>members~}} {{/module}}

{{#module name="IPR"~}} {{>body~}} {{>members~}} {{/module}}