This document assumes that you are running both the primary and secondary instances
of rafiki using the docker compose files in this directory. It describes the process for
setting up peering between them. If at any time your Rafiki instances become misconfigured,
the only way to get back to a working state covered in this document is to destroy the
docker compose stacks and their associated database volumes (e.g.
with pnpm localenv:compose down --volumes
).
The graphql playground is the UI for sending graphql requests to the backend
services.
The graphql playground for the primary Rafiki instance
is on port 3001 on localhost. The graphql playground for the secondary instance
is on port 4001.
This section describes the process for setting up peering between the instances. The commands to run on each instance are subtly different; make sure you are running the correct command against the correct instance. If you make a mistake, the best thing is to delete the docker compose stacks and database volumes and start over.
Each graphql request has two parts: a query and an object containing query variables.
To make a request, put the query in the top input box on the graphql playground.
Open the query variables input by clicking the words "QUERY VARIABLES" at the bottom of the screen.
If the lower input bow is already open, make sure that "QUERY VARIABLES" is highlighted.
Add the query variables for the request to the query variables box, then press the
"play" button in the center of the screen. The right side of the screen will display
the response, which should always contain "success": true
if things are working.
On the primary instance, execute the following query to create an asset:
Query:
mutation CreateAsset ($input: CreateAssetInput!) {
createAsset(input: $input) {
code
success
message
asset {
id
code
scale
}
}
}
Query Variables:
{
"input": {
"code": "USD",
"scale": 2
}
}
Example Successful Response
{
"data": {
"createAsset": {
"code": "200",
"success": true,
"message": "Created Asset",
"asset": {
"id": "b3dffeda-1e0e-47d4-82a3-69b1a622eeb9",
"code": "USD",
"scale": 2
}
}
}
}
Next, execute the following query to create a peer record for the secondary instance:
Query:
mutation CreatePeer ($input: CreatePeerInput!) {
createPeer (input: $input) {
code
success
message
peer {
id
asset {
code
scale
}
staticIlpAddress
}
}
}
Query Variables (substitute the asset ID from the "create asset" response for INSERT_ASSET_ID
):
{
"input": {
"staticIlpAddress": "test.peer",
"http": {
"incoming": {"authTokens": ["test"]},
"outgoing": {"endpoint": "peer-backend:3002", "authToken": "test"}
},
"assetId": "INSERT_ASSET_ID"
}
}
Example Successful Response
{
"data": {
"createPeer": {
"code": "200",
"success": true,
"message": "Created ILP Peer",
"peer": {
"id": "480ef339-7842-4501-a905-923fc1339cef",
"asset": {
"code": "USD",
"scale": 2
},
"staticIlpAddress": "test.peer"
}
}
}
}
Next, run the following query to deposit liquidity for the secondary instance
Query:
mutation DepositPeerLiquidity ($input: DepositPeerLiquidityInput!) {
depositPeerLiquidity(input: $input) {
code
success
message
error
}
}
Query Variables (substitute the peer ID from the "create peer" response for INSERT_PEER_ID
):
{
"input": {
"peerId": "INSERT_PEER_ID",
"amount": "10000",
"id": "a09b730d-8610-4fda-98fa-ec7acb19c775"
}
}
Example successful response:
{
"data": {
"depositPeerLiquidity": {
"code": "200",
"success": true,
"message": "Deposited peer liquidity",
"error": null
}
}
}
Next, run the reciprocal commands on the secondary instance. These commands are similar but are directed from the secondary instance to the primary instance, so if you simply copy the commands above it will not work.
Execute the following query to create an asset:
Query:
mutation CreateAsset ($input: CreateAssetInput!) {
createAsset(input: $input) {
code
success
message
asset {
id
code
scale
}
}
}
Query Variables:
{
"input": {
"code": "USD",
"scale": 2
}
}
Example Successful Response
{
"data": {
"createAsset": {
"code": "200",
"success": true,
"message": "Created Asset",
"asset": {
"id": "c79fedc0-f062-4992-b539-e7f4c125180c",
"code": "USD",
"scale": 2
}
}
}
}
Next, execute the following query to create a peer record for the primary instance:
Query:
mutation CreatePeer ($input: CreatePeerInput!) {
createPeer (input: $input) {
code
success
message
peer {
id
asset {
code
scale
}
staticIlpAddress
}
}
}
Query Variables (substitute the asset ID from the "create asset" response for INSERT_ASSET_ID
):
{
"input": {
"staticIlpAddress": "test.rafiki",
"http": {
"incoming": {"authTokens": ["test"]},
"outgoing": {"endpoint": "backend:3002", "authToken": "test"}
},
"assetId": "INSERT_ASSET_ID"
}
}
Example successful response:
"data": {
"createPeer": {
"code": "200",
"success": true,
"message": "Created ILP Peer",
"peer": {
"id": "b282a8f7-1874-4d53-8135-32c23058268f",
"asset": {
"code": "USD",
"scale": 2
},
"staticIlpAddress": "test.rafiki"
}
}
}
}
Next, run the following query to deposit liquidity for the primary instance
Query:
mutation DepositPeerLiquidity ($input: DepositPeerLiquidityInput!) {
depositPeerLiquidity(input: $input) {
code
success
message
error
}
}
Query Variables (substitute the ID from the "create peer" response for INSERT_PEER_ID
):
{
"input": {
"peerId": "INSERT_PEER_ID",
"amount": "10000",
"id": "b09b734d-8610-4fda-98fa-ec7acb19c775"
}
}
Example successful response:
{
"data": {
"depositPeerLiquidity": {
"code": "200",
"success": true,
"message": "Deposited peer liquidity",
"error": null
}
}
}
In this step we will provision wallet addresses on the primary and secondary Rafiki instances. Wallet addresses are not accounts. Rafiki operators must supply their own "account servicing entity" service for actually "holding" currency. Rafiki provides wallet addresses--addresses within the ILP network to which other nodes on the network can send payments, which will then be routed to the account servicing entity's system and into the appropriate account.
At the end of this step, we will have two wallet address IDs: one provisioned on the primary instance and one provisioned on the secondary instance. We will use these wallet address IDs in subsequent steps to send payments between the Rafiki instances.
On the primary instance execute the following command to create a wallet address ID:
Query
mutation CreateWalletAddress ($input: CreateAccountInput!) {
createWalletAddress(input: $input) {
code
success
message
walletAddress {
id
asset {
id
code
scale
withdrawalThreshold
}
}
}
}
Query Variables (substitute the asset ID from the "create asset" response for INSERT_ASSET_ID
):
{
"input": {
"assetId": "INSERT_ASSET_ID",
"publicName": "test-primary"
}
}
Example successful response
{
"data": {
"createWalletAddress": {
"code": "200",
"success": true,
"message": "Created Account",
"walletAddress": {
"id": "afb2b1de-d819-4e85-b901-859c27445936",
"asset": {
"id": "5a27f8ec-17a5-4388-8d1e-8243d1926778",
"code": "USD",
"scale": 2,
"withdrawalThreshold": null
}
}
}
}
}
On the secondary instance execute the following command to create a wallet address ID:
Query
mutation CreateWalletAddress ($input: CreateAccountInput!) {
createWalletAddress(input: $input) {
code
success
message
walletAddress {
id
asset {
id
code
scale
withdrawalThreshold
}
}
}
}
Query Variables (substitute the asset ID from the "create asset" response for INSERT_ASSET_ID
):
{
"input": {
"assetId": "INSERT_ASSET_ID",
"publicName": "test-secondary"
}
}
Example successful response
{
"data": {
"createWalletAddress": {
"code": "200",
"success": true,
"message": "Created Account",
"walletAddress": {
"id": "7e8b99f5-0861-49bd-95ab-e871c021d84d",
"asset": {
"id": "209fe717-bf02-4deb-826f-b7ed4f179713",
"code": "USD",
"scale": 2,
"withdrawalThreshold": null
}
}
}
}
}
The data.createWalletAddress.walletAddress.id
field in the response is the wallet address ID, which we will
use in the next steps. In this example, the primary wallet address ID is afb2b1de-d819-4e85-b901-859c27445936
,
and the secondary wallet address ID is 7e8b99f5-0861-49bd-95ab-e871c021d84d
.