Machinomy is a library for ETH and ERC20 micropayments. The library could be freely embedded into your software both in browser and server environments.
The library implements unidirectional payment channel pattern. It works like a bar tab. A sender opens a channel and deposits the funds there. Over time she sends promised payments to a receiver. A promised payment is a signed data structure that the receiver could redeem at the smart contract.
Work with Machinomy starts with constructor.
import Machinomy from 'machinomy'
const machinomy = new Machinomy(account, web3, options)
Arguments:
Argument | Type | Description |
---|---|---|
account |
string |
Ethereum address for the acting party, that will send or receive the funds. |
web3 |
Web3 |
Instance of web3 object, note 0.20.x is supported only. |
options? |
MachinomyOptions |
Optional arguments. |
MachinomyOptions
is a hash with the following fields:
Field | Type | Description |
---|---|---|
databaseUrl |
string |
URL to connect to database. For example, postgresql://localhost:5432/database . Supported database protocols are nedb , sqlite , postgresql . |
minimumChannelAmount |
`number | BigNumber` |
minimumSettlementPeriod |
number |
If settlement period for a proposed channel is less than minimumSettlementPeriod , that channel is refused. |
settlementPeriod |
number |
Period of dispute resolution, in blocks. |
closeOnInvalidPayment |
boolean |
If set to true , a receiver reacts on invalid payment with closing a corresponding channel. |
migrate |
`silent | raise` |
The functions related to payments operate on ancillary interfaces for parameters and outputs.
BuyOptions
:
import { BuyOptions } from 'machinomy'
Field | Type | Description |
---|---|---|
receiver |
string |
Ethereum address of the receiver. |
price |
`number | BigNumber` |
gateway |
string |
Endpoint for offchain payment to send. |
meta |
string |
Optional free-form data to accompany the payment. |
Payment
:
import { Payment } from 'machinomy'
Field | Type | Description |
---|---|---|
channelId |
string |
Identifier of the channel, as hex string. |
sender |
string |
Ethereum address of the sender, as hex string. |
receiver |
string |
Ethereum address of the receiver, as hex string. |
price |
BigNumber |
Amount of the payment. |
value |
BigNumber |
Total amount to be paid. Remember, single payment in Unidirectional channel represents the total redeemable amount. |
signature |
Signature |
Signature of the payment by the sender. |
meta |
string |
Optional free-form data to accompany the payment. |
tokenContract |
string |
Token contract address. |
createdAt |
number |
When the payment was created, as unix timestamp. |
token |
string |
Unique identifier of the payment. |
BuyResult
:
import { BuyResult } from 'machinomy'
Field | Type | Description |
---|---|---|
channelId |
string |
Identifier of the channel, as hex string. |
token |
string |
Token to be vaidated against a gateway. |
NextPaymentResult
:
import { NextPaymentResult } from 'machinomy'
Field | Type | Description |
---|---|---|
payment |
object |
Serialised Payment. |
machinomy.payment (options: BuyOptions): Promise<NextPaymentResult>
Returns the payment to be sent over the wire. Stores the payment in a local database.
machinomy.buy (options: BuyOptions): Promise<BuyResult>
Prepares a payment, and sends it to a gateway. Gateway then responds back with a token. It is up to a user to send the token to the content server, or receiver. The receiver then calls the gateway to verify if the token is valid or not. The scenario is revealed fully in client example.
machinomy.paymentById (token): Promise<Payment | null>
Returns a Payment
with the specified token
identifier.
machinomy.acceptPayment (req): Promise<AcceptPaymentResponse>
Accept serialised payment, and issue a token.
req
structure:
Field | Type | Description |
---|---|---|
payment |
JSON-serialised Payment |
Payment that is sent over the wire. |
purchaseMeta |
object & {type: string} |
JSON-serialised object that accompanies the payment. |
Structure of AcceptPaymentResponse
:
Field | Type | Description |
---|---|---|
token |
string |
Unique identifier of the payment, that can be checked against the Gateway. |
machinomy.acceptToken (req): Promise<AcceptTokenResponse>
Accept and verify the token that was issued in response to payment being sent.
Structure of req
argument:
Field | Type | Description |
---|---|---|
token |
string |
Unique identifier of the payment, that can be checked against the Gateway. |
Structure of AcceptTokenResponse
:
Field | Type | Description |
---|---|---|
status |
boolean |
true means the token is ok, false is for invalid token, i.e. for invalid payment. |
Here come functions related to channels. Basic PaymentChannel
structure is described below:
Field | Type | Description |
---|---|---|
sender |
string |
Ethereum address of the channel sender party. |
receiver |
string |
Ethereum address of the channel receiver party. |
channelId |
string |
Identifier of the channel, as hex string. |
value |
BigNumber |
Amount of funds deposited to the channel by the sender. |
spent |
BigNumber |
Amount of funds spent on the channel, that is redeemable by the receiver. |
state |
number |
State of the channel: 0 - open, 1 - settling, 2 - closed or non-existing. |
tokenContract |
string |
Token contract address. |
Opens a channel. It is a lower level function. One probably would not ever need to invoke the function. buy
or payment
both open a channel for you, if it is not present yet.
machinomy.open (receiver, value, channelId?, tokenContract?): Promise<PaymentChannel>
Parameters:
Argument | Type | Description |
---|---|---|
receiver |
string |
Ethereum address of the channel receiver. |
value |
`BigNumber | number` |
channelId? |
string |
Proposed identifier of the channel. |
tokenContract? |
string |
Token contract address. |
Deposit more funds to the channel. One might use it after the channel is depleted, that is the funds are fully moved to the receiver side. It returns result of transaction execution, as returned by usual Truffle calls.
machinomy.deposit (channelId, value): Promise<TransactionResult>
Parameters:
Argument | Type | Description |
---|---|---|
channelId |
string |
Identifier of the channel. |
value |
`BigNumber | number` |
Share the money between sender and reciver according to payments made.
For example a channel was opened with 10 Ether. Sender makes 6 purchases, 1 Ether each. Total value transferred is 6 Ether. If a party closes the channel, the money deposited to the channel are split. The receiver gets 6 Ether. 4 unspent Ethers return to the sender.
A channel can be closed in two ways, according to what party initiates that. The method nicely abstracts over that, so you do not need to know what is really going on under the hood. For more details on how payment channels work refer to a website.
machinomy.close(channelId): Promise<TransactionResult>
Parameters:
Argument | Type | Description |
---|---|---|
channelId |
string |
Identifier of the channel to close. |
machinomy.channels(): Promise<Array<PaymentChannel>>
machinomy.openChannels(): Promise<Array<PaymentChannel>>
machinomy.settlingChannels(): Promise<Array<PaymentChannel>>
machinomy.channelById(channelId): Promise<Array<PaymentChannel>>
Parameters:
Argument | Type | Description |
---|---|---|
channelId |
string |
Identifier of the channel to close. |
As Machinomy uses a database inside, it might be necessary to tear down a connection to the database. We recommend invoking machinomy.shutdown()
after work is done.
Interface:
machinomy.shutdown(): Promise<void>