README
PISA API Client
A thin client for the PISA API.
The client library supports relay and event triggered appointments. If no event information is provided when generating an appointment request then a relay appointment will be created.
See the API docs at /docs.html of the API for the complete list of parameters that are expected from the PISA API endpoint, including the parameters that are generated by this API client, whose description is here omitted.
Hosted instances
Ropsten: https://alpha.pisa.watch
Ropsten contract instance: 0xA02C7260c0020343040A504Ef24252c120be60b9
Ropsten API docs: https://alpha.pisa.watch/docs.html
PisaClient
The API exports a single class called PisaClient
, whose constructor takes two parameters: the url of the PISA API server, and the address of the PISA contract.
const PISA_API_URL = "https://alpha.pisa.watch";
const PISA_CONTRACT_ADDRESS = "0xA02C7260c0020343040A504Ef24252c120be60b9";
const pisaClient = new PisaClient(PISA_API_URL, PISA_CONTRACT_ADDRESS);
The pisaClient
object exposes a generateAndExecuteRequest
method to call the PISA API and interpret the response.
generateAndExecuteRequest
generateAndExecuteRequest(
signer: (digest: string) => Promise<string>,
customerAddress: string,
id: string,
nonce: number,
startBlock: number,
endBlock: number,
contractAddress: string,
data: string,
gasLimit: number,
challengePeriod: number,
eventAddress?: string,
topics?: (string | null)[]
): Promise<AppointmentReceipt>
This method creates a requests for an appointment and calls the PISA endpoint. The return value is a Promise that resolves to an AppointmentReceipt
if the request was successful, or is rejected in case of error.
signer
: a callback function that is given a digest of the encoded appointment, and must return the customer's signature.customerAddress
: the checksummed address of the customer.id
: a unique id chosen by the customer.nonce
: a counter that can be incremented by the customer in order to replace a previous appointment with the given id.startBlock
: the block when the appointment starts.endBlock
: the block when the appointment ends.contractAddress
: the address of the external contract to which the data will be submitted by PISAdata
: an ABI encoded function and arguments that will be executed at the contract address by PISA when the event specified by the appointment is observed.gasLimit
: the amount of gas that will be supplied when calling the external contract. The maximum value is 2 million.challengePeriod
: the number of blocks that PISA has to respond from the block height where an event is observed. It must be at least 100.
If eventAddress
and topics
are omitted, the request is for a ''relay'' appointment and PISA wil respond without waiting for a trigger. Otherwise:
eventAddress
: The address from which the trigger event is emitted.topics
: An array of up to 4 elements. Each element is either a topic that must match for the event to be considered a trigger, ornull
if the corresponding log entry (if any) is to obe ignored.
generateRequest and executeRequest
The pisaClient
object also exports lower level methods generateRequest
and executeRequest
.
generateRequest
has the same parameters as generateAndExecuteRequest
, but returns a SignedAppointmentRequest
instead of calling the PISA API. The returned signed appointment request can then be send to PISA by calling executeRequest
with the signed appointment request.
Simple example with ethers.js
In this example we use an ethers.js wallet to sign the digest.
const PISA_API_URL = "https://alpha.pisa.watch";
const PISA_CONTRACT_ADDRESS = "0xA02C7260c0020343040A504Ef24252c120be60b9";
// metadata info
const userWallet; // an ethersjs wallet
const appointmentId = "0x61f307f9dc16833ff12d511e22a20ac2a4d0adaa2f48292ebad9e0c80a2bb75d";
const nonce = 0;
const startBlock; // current block height just retrieved from a provider
const endBlock = startBlock + 200;
// response info
const responseAddress = "0x81b7e08f65bdf5648606c89998a9cc8164397647";
const responseData = "0x28fbdf0d000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000";
const gasLimit = 100000;
const challengePeriod = 200;
// event info
const eventAddress = "0x9e64b53b935602cd0657343C69Fe200fb3cD05c8";
const topics = ["0x73ea0ff8e52eea08c37acf9b1de68b2f0039fd344d83d2563e2b266b073a93d4", null, "0x0000000000000000000000000000000000000000000000000000000000000001"];
const pisaClient = new PisaClient(PISA_API_URL, PISA_CONTRACT_ADDRESS);
const receipt = await pisaClient.generateAndExecuteRequest(
digest => userWallet.signMessage(arrayify(digest)),
userWallet.address,
appointmentId,
nonce,
startBlock,
endBlock,
responseAddress,
responseData,
gasLimit,
challengePeriod,
eventAddress,
topics
);