Pisa API Integration Guide

Deployed Preproduction Services

The Pisa Fees public API documentation can be found here: https://mlabs-haskell.github.io/pisa-fees/pisa-api/web-socket-api.html

Pisa Balancer

wss://server-ws-api.pisa-fees.staging.mlabs.city/ws

The Pisa balancer is a WebSocket service that can accept CBOR of an unbalanced transaction and Pisa Fees position. It balances the transaction in such a way that the fee will be paid by the Asset that the position has liquidity for, instead of Ada. The exact Assets to use for balancing are chosen by the user.

Pisa Indexer

wss://indexer-server.pisa-fees.staging.mlabs.city/ws

The Pisa indexer tracks active Pisa positions and provides an API to query active positions.

Pisa Events Stream

wss://indexer-follower.pisa-fees.staging.mlabs.city/pisa-events

This service broadcasts changes in Pisa positions in real-time via WebSocket. As soon as the chain follower receives a new block from the Cardano node and detects new or closed positions in the block, a message will be sent to the socket. It also sends corresponding messages in case of rollback.

Making Transactions with Pisa

Making a transaction with Pisa Fees swap is a four-step process:

Step 1: Create Unbalanced Transaction

Create an unbalanced transaction or transaction body and serialize it to CBOR. This can be done with cardano-cli or transaction builder frameworks.

For example, with cardano-cli, it can be done as follows:

cardano-cli conway transaction build-raw [ins, outs and other required args] --out-file tx.draft

The transaction body CBOR can then be obtained from the tx.draft file - specifically from the cborHex JSON field.

cardano-transaction-lib also provides a straightforward way of building unbalanced transactions using Contract, for example:

unbalancedTx <- buildTx
    [ Pay ...
    ]

The CBOR can then be obtained by calling the encodeCbor function on unbalancedTx.

Step 2: Get Suitable Pisa Fees Position

Pisa Fees positions can be queried via the Pisa indexer: wss://indexer-server.pisa-fees.staging.mlabs.city/ws.

The Public WebSocket API provides a list of available queries.

For example, the following query will return all currently active positions, allowing the user to select one with suitable tokens:

{
  "requestId": "6fb8473d-807c-40b6-b4ca-478664b96ef4",
  "queryType": "getAllPositions",
  "payload": null
}

Note that requestId (UUID) should be generated and supplied by the caller to match responses with requests during WebSocket communication.

The response might look like this:

{
  "status": "success",
  "data": {
    "requestId": "6fb8473d-807c-40b6-b4ca-478664b96ef4",
    "response": {
      "allPositions": [
        {
          "owner": "a989a5ddd49a85d9d23509037cf5b1d6eacfdf8e3518b52b29c5edc6",
          "positionRef": "42085b8b6635404bc2ac13e65c5a5c729deb3fa689c3eb841c28685b25bd67c8#0",
          "rates": [
            {
              "assetClass": "9f30db07c6ae78fe003eee54cac942401a0f0e5fd4eef3b7d5bf9ba0.536f6d65546f6b656e",
              "rate": {
                "denominator": 10,
                "numerator": 1
              }
            }
          ]
        },
        ...
      ]
    }
  }
}

In the rates field of the position object, we can see all assets available for swap in the current position, along with their exchange rates. The assetClass field represents [minting-policy-id].[hex-encoded-token-name].

The transaction output reference of the position UTxO from the positionRef field will be required to perform balancing with the Pisa balancer service.

Step 3: Balance Transaction with Pisa Balancer

Now, with the transaction CBOR obtained in Step 1 and the position out ref obtained in Step 2, you can execute a balancing request to the Pisa balancer.

A balance request looks like this:

{
  "requestId": "6fb8473d-807c-40b6-b4ca-478664b96ef4",
  "requestType": "balanceCbor",
  "payload": {
    "positionRef": "42085b8b6635404bc2ac13e65c5a5c729deb3fa689c3eb841c28685b25bd67c8#0",
    "swapAssets": [
      "9f30db07c6ae78fe003eee54cac942401a0f0e5fd4eef3b7d5bf9ba0.536f6d65546f6b656e"
    ],
    "unbalancedTxCbor": "[CBOR from step 1]",
    "userAddresses": [
      "addr_test1..."
    ],
    "userChangeAddress": "addr_test1...",
    "userCollateral": null
  }
}

Important notes:

In response, the Pisa balancer will return the following JSON:

{
  "status": "success",
  "data": {
    "balancedCbor": "[CBOR hex of balanced transaction]",
    "requestId": "6fb8473d-807c-40b6-b4ca-478664b96ef4"
  }
}

Step 4: Sign and Submit Transaction Returned by Pisa Balancer

The CBOR from the balancer response will contain an unsigned balanced transaction body. Typically, transaction builder frameworks provide a way to build a transaction body from CBOR. The parsed body can then be signed and submitted in the way the framework handles it.

A concrete example using cardano-cli is available in the section below.

Pisa Integrations

Cardano Transaction Library (CTL)

A CTL fork with Pisa integration is available here in the pisa-ws-integration branch.

An example of a Contract that performs balancing via Pisa balancer is available in the examples directory in the PisaBalance.purs module. Using this Contract, users can send tokens to another address and use the same or other tokens to pay for transaction fees and the minimum required Ada by performing balancing via the Pisa Fees backend.

lucid-evolution

A lucid-evolution fork with Pisa integration is available here in the pisa branch.

For examples, see the documentation for the Pisa object and completeWithPisa method.

Atlas

For Atlas, we provide library-level integration, as Pisa Fees off-chain and backend are powered by Atlas. This means that the Pisa Fees off-chain package can be used directly as a dependency in any Atlas project.

Example: Making Transaction with cardano-cli

Below is the set of commands that can be used to build, balance, and submit a transaction using cardano-cli and the deployed Pisa Fees services, step by step (note that assets and addresses will need to be adjusted for your specific setup):

1. Get wallet UTxO to build draft transaction

cardano-cli query utxo --testnet-magic 1 --socket-path cardano-node.socket --address addr_test1qqa0rdmen6qcyskexlmzm6ljy8qv7xl06k73l34vcceds2luyj98ldkjdkmnketfz5stjmrzehk8mqumegev9r5tu3lsgta7l4

2. Build draft transaction

cardano-cli conway transaction build-raw \
  --tx-in [input-from-previous-step] \
  --tx-out addr_test1qrp6w67kh762fkt9myhx54u64x2wmlyjr83trhqjlw3z9cpak3rw8tjnlxevmp2qkl0j4zurdkm2gzksxl7kdjef925q6pz0nc+"1 1b650ba85f6590eebebe138cce94d96c62fcc332bbcfb3d9b3a11f33.53656e64546f6b656e4f6e65" \
  --fee 0 \
  --out-file swap-tx.draft

The CBOR of the unbalanced transaction will be in the cborHex field of the JSON in the swap-tx.draft file.

3. Call Pisa indexer API and pick position for swap

Pisa Indexer: wss://indexer-server.pisa-fees.staging.mlabs.city/ws

{
  "requestId": "6fb8473d-807c-40b6-b4ca-478664b96ef4",
  "queryType": "getAllPositions",
  "payload": null
}

Select a suitable position from the response (the value of the specific positionRef will be required for the next step).

4. Make balancing request to Pisa balancer API

Pisa Balancer: wss://server-ws-api.pisa-fees.staging.mlabs.city/ws

The request will need: - CBOR of the transaction draft from step 2 - Position out ref selected in step 3

Balancing request template:

{
  "requestId": "c2cc10e1-57d6-4b6f-9899-38d972112d8c",
  "requestType": "balanceCbor",
  "payload": {
    "positionRef": "TODO: position ref from indexer",
    "swapAssets": [
      "TODO: asset class for swap"
    ],
    "unbalancedTxCbor": "TODO: cbor of unbalanced transaction]",
    "userAddresses": [
      "addr_test1qqa0rdmen6qcyskexlmzm6ljy8qv7xl06k73l34vcceds2luyj98ldkjdkmnketfz5stjmrzehk8mqumegev9r5tu3lsgta7l4"
    ],
    "userChangeAddress": "addr_test1qqa0rdmen6qcyskexlmzm6ljy8qv7xl06k73l34vcceds2luyj98ldkjdkmnketfz5stjmrzehk8mqumegev9r5tu3lsgta7l4",
    "userCollateral": null
  }
}

5. Create transaction envelope file with balanced CBOR

Take the balanced CBOR from the Pisa balancer response (balancedCbor field) and create a transaction envelope to sign with cardano-cli.

Balancer response example:

{
  "status": "success",
  "data": {
    "balancedCbor": "[cbor hex]",
    "requestId": "6fb8473d-807c-40b6-b4ca-478664b96ef4"
  }
}

cardano-cli transaction envelope template:

{
  "type": "Unwitnessed Tx ConwayEra",
  "description": "Ledger Cddl Format",
  "cborHex": "[cbor of balanced transaction]"
}

6. Sign transaction and submit

cardano-cli conway transaction sign --testnet-magic 1 --signing-key-file /TODO/path/to/key.skey --tx-file [envelope file] --out-file [signed-tx-file]
cardano-cli conway transaction submit --testnet-magic 1 --socket-path cardano-node.socket --tx-file [signed-tx-file]

To get the transaction ID:

cardano-cli conway transaction txid --tx-file [signed-tx-file]