A low-level JS Interledger sender/receiver library
This is a low-level interface to ILP, largely intended for building ILP into other Application layer protocols.
- Interledger Payment Request (IPR) Transport Protocol, an interactive protocol in which the receiver specifies the payment details, including the condition
- Pre-Shared Key (PSK) Transport Protocol, a non-interactive protocol in which the sender creates the payment details and uses a shared secret to generate the conditions
- Interledger Quoting and the ability to send through multiple ledger types using Ledger Plugins
- Account discovery
- Amount negotiation
- Communication of requests from recipient to sender
npm install --save ilp ilp-plugin-bells
Note that ledger plugins must be installed alongside this module
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.
'use strict'
const co = require('co')
const ILP = require('ilp')
const FiveBellsLedgerPlugin = require('ilp-plugin-bells')
const sender = ILP.createSender({
_plugin: FiveBellsLedgerPlugin,
prefix: 'ilpdemo.red.',
account: 'https://red.ilpdemo.org/ledger/accounts/alice',
password: 'alice'
})
const receiver = ILP.createReceiver({
_plugin: FiveBellsLedgerPlugin,
prefix: 'ilpdemo.blue.',
account: 'https://blue.ilpdemo.org/ledger/accounts/bob',
password: 'bobbob'
})
co(function * () {
yield receiver.listen()
receiver.on('incoming', (transfer, fulfillment) => {
console.log('received transfer:', transfer)
console.log('fulfilled transfer hold with fulfillment:', fulfillment)
})
const request = receiver.createRequest({
amount: '10',
})
console.log('request:', request)
// Note the user of this module must implement the method for
// communicating payment requests from the recipient to the sender
const paymentParams = yield sender.quoteRequest(request)
console.log('paymentParams', paymentParams)
const result = yield sender.payRequest(paymentParams)
console.log('sender result:', result)
}).catch((err) => {
console.log(err)
})
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.
'use strict'
const co = require('co')
const ILP = require('.')
const FiveBellsLedgerPlugin = require('ilp-plugin-bells')
const sender = ILP.createSender({
_plugin: FiveBellsLedgerPlugin,
account: 'https://localhost/ledger/accounts/alice',
password: 'alice'
})
const receiver = ILP.createReceiver({
_plugin: FiveBellsLedgerPlugin,
account: 'https://localhost/ledger/accounts/bob',
password: 'bobbob',
// A callback can be specified to review incoming payments.
// This is required when using PSK.
reviewPayment: (payment, transfer) => {
if (+transfer.amount > 100) {
return Promise.reject(new Error('payment is too big!'))
}
}
})
co(function * () {
yield receiver.listen()
receiver.on('incoming', (transfer, fulfillment) => {
console.log('received transfer:', transfer)
console.log('fulfilled transfer hold with fulfillment:', fulfillment)
})
// The user of this module is responsible for communicating the
// PSK parameters from the recipient to the sender
const pskParams = receiver.generatePskParams()
// Note the payment is created by the sender
const request = sender.createRequest({
destinationAmount: '10',
destinationAccount: pskParams.destinationAccount,
sharedSecret: pskParams.sharedSecret
})
console.log('request:', request)
const paymentParams = yield sender.quoteRequest(request)
console.log('paymentParams', paymentParams)
const result = yield sender.payRequest(paymentParams)
console.log('sender result:', result)
}).catch((err) => {
console.log(err)
})
SPSP Client
Kind: inner class of SPSP
- ~Client
- new Client(opts)
- .quoteSource ⇒
Promise.<SpspPayment>
- .quoteDestination ⇒
Promise.<SpspPayment>
- .sendPayment ⇒
Promise.<PaymentResult>
- .query ⇒
Object
Create an SPSP client.
Param | Type | Description |
---|---|---|
opts | Object |
plugin options |
opts._plugin | function |
(optional) plugin constructor. Defaults to PluginBells |
Get payment params via SPSP query and ILQP quote, based on source amount
Kind: instance property of Client
Returns: Promise.<SpspPayment>
- Resolves with the parameters that can be passed to sendPayment
Param | Type | Description |
---|---|---|
receiver | String |
webfinger identifier of receiver |
sourceAmount | String |
Amount that you will send |
Get payment params via SPSP query and ILQP quote, based on destination amount
Kind: instance property of Client
Returns: Promise.<SpspPayment>
- Resolves with the parameters that can be passed to sendPayment
Param | Type | Description |
---|---|---|
receiver | String |
webfinger identifier of receiver |
destinationAmount | String |
Amount that the receiver will get |
Sends a payment using the PaymentParams
Kind: instance property of Client
Returns: Promise.<PaymentResult>
- Returns payment result
Param | Type | Description |
---|---|---|
payment | SpspPayment |
params, returned by quoteSource or quoteDestination |
Queries an SPSP endpoint
Kind: instance property of Client
Returns: Object
- result Result from SPSP endpoint
Param | Type | Description |
---|---|---|
receiver | String |
A URL or an account |
Parameters for an SPSP payment
Kind: inner typedef of SPSP
Properties
Name | Type | Description |
---|---|---|
id | id |
UUID to ensure idempotence between calls to sendPayment |
source_amount | string |
Decimal string, representing the amount that will be paid on the sender's ledger. |
destination_amount | string |
Decimal string, representing the amount that the receiver will be credited on their ledger. |
destination_account | string |
Receiver's ILP address. |
connector_account | string |
The connector's account on the sender's ledger. The initial transfer on the sender's ledger is made to this account. |
spsp | string |
SPSP response object, containing details to contruct transfers. |
data | string |
extra data to attach to transfer. |
Returns an ILP Sender to quote and pay for payment requests.
Kind: inner method of Sender
Param | Type | Default | Description |
---|---|---|---|
opts._plugin | LedgerPlugin |
Ledger plugin used to connect to the ledger, passed to ilp-core | |
opts | Objct |
Plugin parameters, passed to ilp-core | |
[opts.client] | ilp-core.Client |
create a new instance with the plugin and opts |
ilp-core Client, which can optionally be supplied instead of the previous options |
[opts.connectors] | Array |
[] |
Array of connectors to use, specified by account name on the local ledger (e.g. "connie"). Some ledgers provide recommended connectors while others do not, in which case this would be required to send Interledger payments. |
[opts.maxHoldDuration] | Number |
10 |
Maximum time in seconds to allow money to be held for |
[opts.defaultRequestTimeout] | Number |
30 |
Default time in seconds that requests will be valid for |
[opts.uuidSeed] | Buffer |
crypto.randomBytes(32) |
Seed to use for generating transfer UUIDs |
- ~createSender(opts) ⇒
Sender
- ~quoteSourceAmount(destinationAddress, sourceAmount) ⇒
Promise.<String>
- ~quoteDestinationAmount(destinationAddress, destinationAmount) ⇒
Promise.<String>
- ~quoteRequest(paymentRequest) ⇒
Promise.<PaymentParams>
- ~payRequest(paymentParams) ⇒
Promise.<String>
- ~createRequest(params) ⇒
Object
- ~stopListening() ⇒
Promise.<null>
- ~quoteSourceAmount(destinationAddress, sourceAmount) ⇒
Get a fixed source amount quote
Kind: inner method of createSender
Returns: Promise.<String>
- destinationAmount
Param | Type | Description |
---|---|---|
destinationAddress | String |
ILP Address of the receiver |
sourceAmount | String | Number |
Amount the sender wants to send |
Get a fixed destination amount quote
Kind: inner method of createSender
Returns: Promise.<String>
- sourceAmount
Param | Type | Description |
---|---|---|
destinationAddress | String |
ILP Address of the receiver |
destinationAmount | String |
Amount the receiver should recieve |
Quote a request from a receiver
Kind: inner method of createSender
Returns: Promise.<PaymentParams>
- Resolves with the parameters that can be passed to payRequest
Param | Type | Description |
---|---|---|
paymentRequest | Object |
Payment request generated by an ILP Receiver |
Pay for a payment request. Uses a determinstic transfer id so that paying is idempotent (as long as ledger plugins correctly reject multiple transfers with the same id)
Kind: inner method of createSender
Returns: Promise.<String>
- Resolves with the condition fulfillment
Param | Type | Description |
---|---|---|
paymentParams | PaymentParams |
Respose from quoteRequest |
Create a payment request using a Pre-Shared Key (PSK).
Kind: inner method of createSender
Returns: Object
- Payment request
Param | Type | Default | Description |
---|---|---|---|
params | Object |
Parameters for creating payment request | |
params.destinationAmount | String |
Amount that should arrive in the recipient's account | |
params.destinationAccount | String |
Target account's ILP address | |
params.sharedSecret | String |
Shared secret for PSK protocol | |
[params.id] | String |
uuid.v4() |
Unique ID for the request (used to ensure conditions are unique per request) |
[params.expiresAt] | String |
30 seconds from now |
Expiry of request |
[params.data] | Object |
|
Additional data to include in the request |
Disconnect from the ledger and stop listening for events.
Kind: inner method of createSender
Returns: Promise.<null>
- Resolves when the sender is disconnected.
Returns an ILP Receiver to create payment requests, listen for incoming transfers, and automatically fulfill conditions of transfers paying for the payment requests created by the Receiver.
Kind: inner method of Receiver
Param | Type | Default | Description |
---|---|---|---|
opts._plugin | LedgerPlugin |
Ledger plugin used to connect to the ledger, passed to ilp-core | |
opts | Object |
Plugin parameters, passed to ilp-core | |
[opts.client] | ilp-core.Client |
create a new instance with the plugin and opts |
ilp-core Client, which can optionally be supplied instead of the previous options |
[opts.hmacKey] | Buffer |
crypto.randomBytes(32) |
32-byte secret used for generating request conditions |
[opts.defaultRequestTimeout] | Number |
30 |
Default time in seconds that requests will be valid for |
[opts.allowOverPayment] | Boolean |
false |
Allow transfers where the amount is greater than requested |
[opts.roundingMode] | String |
|
Round request amounts with too many decimal places, possible values are "UP", "DOWN", "HALF_UP", "HALF_DOWN" as described in https://mikemcl.github.io/bignumber.js/#constructor-properties |
[opts.connectionTimeout] | Number |
10 |
Time in seconds to wait for the ledger to connect |
[opts.reviewPayment] | reviewPaymentCallback |
called before fulfilling any incoming payments. The receiver doesn't fulfill the payment if reviewPayment rejects. PSK will not be used if reviewPayment is not provided. |
- ~createReceiver(opts) ⇒
Receiver
- ~getAddress() ⇒
String
- ~createRequest() ⇒
Object
- ~generatePskParams() ⇒
PskParams
- ~listen() ⇒
Promise.<null>
- ~stopListening() ⇒
Promise.<null>
- ~getAddress() ⇒
Get ILP address
Kind: inner method of createReceiver
Create a payment request
Kind: inner method of createReceiver
Param | Type | Default | Description |
---|---|---|---|
params.amount | String |
Amount to request. It will throw an error if the amount has too many decimal places or significant digits, unless the receiver option roundRequestsAmounts is set | |
[params.account] | String |
client.getAccount() |
Optionally specify an account other than the one the receiver would get from the connected plugin |
[params.id] | String |
uuid.v4() |
Unique ID for the request (used to ensure conditions are unique per request) |
[params.expiresAt] | String |
30 seconds from now |
Expiry of request |
[params.data] | Object |
|
Additional data to include in the request |
[params.roundingMode] | String |
receiver.roundingMode |
Round request amounts with too many decimal places, possible values are "UP", "DOWN", "HALF_UP", "HALF_DOWN" as described in https://mikemcl.github.io/bignumber.js/#constructor-properties |
Generate shared secret for Pre-Shared Key (PSK) transport protocol.
Kind: inner method of createReceiver
Listen for incoming transfers and automatically fulfill conditions for transfers corresponding to requests this receiver created.
Kind: inner method of createReceiver
Returns: Promise.<null>
- Resolves when the receiver is connected
Emits: incoming
, incoming:<requestid>
, incoming:psk:<token>
Disconnect from the ledger and stop listening for events.
Kind: inner method of createReceiver
Returns: Promise.<null>
- Resolves when the receiver is disconnected.
IncomingTransfer from the ledger plugin and the fulfillment string
Kind: event emitted by Receiver
IncomingTransfer from the ledger plugin and the fulfillment string for a specific request
Kind: event emitted by Receiver
IncomingTransfer from the ledger plugin and the fulfillment string for a specific token
Kind: event emitted by Receiver
Kind: inner typedef of Receiver
Returns: Promise.<null>
| null
- cancels the payment if it rejects/throws an error.
Param | Type | Description |
---|---|---|
payment | PaymentRequest |
payment request object |
transfer | Transfer |
transfer object for the payment being reviewed |
Kind: inner typedef of Receiver
Properties
Name | Type | Description |
---|---|---|
destinationAccount | string |
Receiver's ILP address |
sharedSecret | string |
Base64Url-encoded shared secret |