From ee30f87d1532e8dad1256b4faa86539e34d96ccd Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Thu, 15 Feb 2024 12:34:59 +0100 Subject: [PATCH 01/16] chore: trying out bruno --- .../Create Outgoing Payment.bru | 62 +++++++++ .../Create Quote.bru | 93 ++++++++++++++ ...ate Receiver -remote Incoming Payment-.bru | 63 ++++++++++ .../Get Outgoing Payment.bru | 50 ++++++++ .../Create Outgoing Payment.bru | 62 +++++++++ .../Peer-to-Peer Payment/Create Quote.bru | 93 ++++++++++++++ ...ate Receiver -remote Incoming Payment-.bru | 63 ++++++++++ .../Get Outgoing Payment.bru | 50 ++++++++ .../Open Payments/Continuation Request.bru | 31 +++++ .../Open Payments/Create Incoming Payment.bru | 50 ++++++++ .../Open Payments/Create Outgoing Payment.bru | 42 +++++++ .../Examples/Open Payments/Create Quote.bru | 42 +++++++ .../Open Payments/Get Outgoing Payment.bru | 29 +++++ .../Get receiver wallet address.bru | 55 ++++++++ .../Get sender wallet address.bru | 61 +++++++++ .../Grant Request Incoming Payment.bru | 40 ++++++ .../Grant Request Outgoing Payment.bru | 55 ++++++++ .../Open Payments/Grant Request Quote.bru | 40 ++++++ .../Complete Incoming Payment.bru | 23 ++++ .../Create Incoming Payment.bru | 50 ++++++++ ...Get Incoming Payment -Unauthenticated-.bru | 27 ++++ .../Get Incoming Payment.bru | 29 +++++ .../List Incoming Payments.bru | 53 ++++++++ .../Create Outgoing Payment.bru | 43 +++++++ .../Get Outgoing Payment.bru | 29 +++++ .../List Outgoing Payments.bru | 53 ++++++++ .../Quotes/Create Quote.bru | 45 +++++++ .../Open Payments APIs/Quotes/Get Quote.bru | 30 +++++ .../Get Wallet Address Keys.bru | 17 +++ .../Wallet Address/Get a Wallet Address.bru | 44 +++++++ .../Grants/Continuation Request.bru | 31 +++++ .../Grants/Grant Request.bru | 69 ++++++++++ .../Tokens/Revoke Access Token.bru | 15 +++ .../Tokens/Rotate Access Token.bru | 25 ++++ .../Rafiki Admin APIs/Create Asset.bru | 46 +++++++ .../Create Incoming Payment.bru | 60 +++++++++ .../Create Or Update Peer By Url.bru | 47 +++++++ .../Create Outgoing Payment.bru | 87 +++++++++++++ .../Rafiki Admin APIs/Create Peer.bru | 56 +++++++++ .../Rafiki Admin APIs/Create Quote.bru | 103 +++++++++++++++ ...ate Receiver -remote Incoming Payment-.bru | 64 ++++++++++ .../Create Wallet Address Key.bru | 55 ++++++++ .../Create Wallet Address Withdrawal.bru | 46 +++++++ .../Create Wallet Address.bru | 61 +++++++++ .../Rafiki Admin APIs/Delete Peer.bru | 30 +++++ .../Deposit Asset Liquidity.bru | 34 +++++ .../Deposit Event Liquidity.bru | 31 +++++ .../Deposit Outgoing Payment Liquidity.bru | 32 +++++ .../Deposit Peer Liquidity.bru | 34 +++++ .../Rafiki Admin APIs/Get Asset.bru | 42 +++++++ .../Rafiki Admin APIs/Get Assets.bru | 57 +++++++++ .../Get Incoming Payment.bru | 40 ++++++ .../Get Outgoing Payment.bru | 68 ++++++++++ .../Rafiki Admin APIs/Get Payments.bru | 42 +++++++ .../Rafiki Admin APIs/Get Peer.bru | 28 +++++ .../Rafiki Admin APIs/Get Peers.bru | 38 ++++++ .../Rafiki Admin APIs/Get Quote.bru | 43 +++++++ ...Get Receiver -remote Incoming Payment-.bru | 41 ++++++ .../Rafiki Admin APIs/Get Wallet Address.bru | 55 ++++++++ .../Get Wallet Addresses.bru | 26 ++++ .../Rafiki Admin APIs/Get Webhook Events.bru | 41 ++++++ .../Post Liquidity Withdrawal.bru | 32 +++++ .../Revoke Wallet Address Key.bru | 35 ++++++ .../Interledger/Rafiki Admin APIs/Set Fee.bru | 46 +++++++ .../Trigger Wallet Address Events.bru | 30 +++++ .../Rafiki Admin APIs/Update Asset.bru | 43 +++++++ .../Rafiki Admin APIs/Update Peer.bru | 48 +++++++ .../Update Wallet Address.bru | 45 +++++++ .../Void Liquidity Withdrawal.bru | 32 +++++ .../Withdraw Asset Liquidity.bru | 34 +++++ .../Withdraw Event Liquidity.bru | 31 +++++ .../Withdraw Incoming Payment Liquidity.bru | 31 +++++ .../Withdraw Outgoing Payment Liquidity.bru | 31 +++++ .../Withdraw Peer Liquidity.bru | 34 +++++ .../Rafiki Admin Auth APIs/Get Grant.bru | 49 ++++++++ .../Rafiki Admin Auth APIs/Get Grants.bru | 73 +++++++++++ .../Rafiki Admin Auth APIs/Revoke Grant.bru | 29 +++++ postman/collections/Interledger/bruno.json | 9 ++ .../Local Playground Environment.bru | 119 ++++++++++++++++++ .../environments/Local Playground.bru | 82 ++++++++++++ .../environments/Remote Environment.bru | 84 +++++++++++++ 81 files changed, 3788 insertions(+) create mode 100644 postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru create mode 100644 postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru create mode 100644 postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru create mode 100644 postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru create mode 100644 postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru create mode 100644 postman/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru create mode 100644 postman/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Examples/Open Payments/Create Quote.bru create mode 100644 postman/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru create mode 100644 postman/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru create mode 100644 postman/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru create mode 100644 postman/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Incoming Payments/List Incoming Payments.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Quotes/Create Quote.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Quotes/Get Quote.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Wallet Address/Get Wallet Address Keys.bru create mode 100644 postman/collections/Interledger/Open Payments APIs/Wallet Address/Get a Wallet Address.bru create mode 100644 postman/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru create mode 100644 postman/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru create mode 100644 postman/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru create mode 100644 postman/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Create Peer.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Delete Peer.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Asset.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Assets.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Incoming Payment.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Outgoing Payment.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Payments.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Peer.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Peers.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Quote.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Receiver -remote Incoming Payment-.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Address.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Addresses.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Get Webhook Events.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Revoke Wallet Address Key.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Set Fee.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Trigger Wallet Address Events.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Update Asset.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Update Peer.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Update Wallet Address.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru create mode 100644 postman/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru create mode 100644 postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru create mode 100644 postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grants.bru create mode 100644 postman/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru create mode 100644 postman/collections/Interledger/bruno.json create mode 100644 postman/collections/Interledger/environments/Local Playground Environment.bru create mode 100644 postman/collections/Interledger/environments/Local Playground.bru create mode 100644 postman/collections/Interledger/environments/Remote Environment.bru diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru new file mode 100644 index 0000000000..12c4b8f9af --- /dev/null +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru @@ -0,0 +1,62 @@ +meta { + name: Create Outgoing Payment + type: graphql + seq: 3 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateOutgoingPayment($input: CreateOutgoingPaymentInput!) { + createOutgoingPayment(input: $input) { + code + message + payment { + createdAt + error + metadata + id + walletAddressId + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + sentAmount { + assetCode + assetScale + value + } + state + stateAttempts + } + success + } + } +} + +body:graphql:vars { + { + "input": { + "walletAddressId": "{{gfranklinWalletAddressId}}", + "quoteId": "{{quoteId}}" + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("outgoingPaymentId", body.data.createOutgoingPayment.payment.id); + // pm.expect(pm.environment.get("outgoingPaymentId")).to.be.a('string'); +} diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru new file mode 100644 index 0000000000..416dfc1f9d --- /dev/null +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru @@ -0,0 +1,93 @@ +meta { + name: Create Quote + type: graphql + seq: 2 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateQuote($input: CreateQuoteInput!) { + createQuote(input: $input) { + code + message + quote { + createdAt + expiresAt + highEstimatedExchangeRate + id + lowEstimatedExchangeRate + maxPacketAmount + minExchangeRate + walletAddressId + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + } + } + } +} + +body:graphql:vars { + { + "input": { + "walletAddressId": "{{gfranklinWalletAddressId}}", + "receiver": "{{receiverId}}" + } + } +} + +script:pre-request { + // + // const getWalletAddressesQuery = ` + // query GetWalletAddresses { + // walletAddresses { + // edges { + // cursor + // node { + // id + // publicName + // url + // } + // } + // } + // }` + // + // const postRequest = { + // url: `${pm.environment.get("RafikiGraphqlHost")}/graphql`, + // method: 'POST', + // body: { + // mode: 'graphql', + // graphql: { + // query:getWalletAddressesQuery + // } + // } + // }; + // + // + // pm.sendRequest(postRequest, (error, response) => { + // const body = response.json(); + // const gfranklinWalletAddressId = body.data.walletAddresses.edges.map(e => e.node).find(node => node.publicName === 'Grace Franklin')?.id + // + // pm.environment.set("gfranklinWalletAddressId", gfranklinWalletAddressId) + // }); +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("quoteId", body.data.createQuote.quote.id); + // pm.expect(pm.environment.get("quoteId")).to.be.a('string'); +} diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru new file mode 100644 index 0000000000..aae6bdd892 --- /dev/null +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru @@ -0,0 +1,63 @@ +meta { + name: Create Receiver -remote Incoming Payment- + type: graphql + seq: 1 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateReceiver($input: CreateReceiverInput!) { + createReceiver(input: $input) { + code + message + receiver { + completed + createdAt + expiresAt + metadata + id + incomingAmount { + assetCode + assetScale + value + } + walletAddressUrl + receivedAmount { + assetCode + assetScale + value + } + updatedAt + } + success + } + } +} + +body:graphql:vars { + { + "input": { + "metadata": { + "description": "cross-currency" + }, + "incomingAmount": { + "assetCode": "EUR", + "assetScale": 2, + "value": 500 + }, + "walletAddressUrl": "https://happy-life-bank-backend/accounts/lars" + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("receiverId", body.data.createReceiver.receiver.id); + // pm.expect(pm.environment.get("receiverId")).to.be.a('string'); +} diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru new file mode 100644 index 0000000000..2659d9ae8c --- /dev/null +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru @@ -0,0 +1,50 @@ +meta { + name: Get Outgoing Payment + type: graphql + seq: 4 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetOutgoingPayment($id: String!) { + outgoingPayment(id: $id) { + createdAt + error + metadata + id + walletAddressId + quote { + id + } + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + sentAmount { + assetCode + assetScale + value + } + state + stateAttempts + } + } +} + +body:graphql:vars { + { + "id": "{{outgoingPaymentId}}" + } +} diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru new file mode 100644 index 0000000000..12c4b8f9af --- /dev/null +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru @@ -0,0 +1,62 @@ +meta { + name: Create Outgoing Payment + type: graphql + seq: 3 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateOutgoingPayment($input: CreateOutgoingPaymentInput!) { + createOutgoingPayment(input: $input) { + code + message + payment { + createdAt + error + metadata + id + walletAddressId + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + sentAmount { + assetCode + assetScale + value + } + state + stateAttempts + } + success + } + } +} + +body:graphql:vars { + { + "input": { + "walletAddressId": "{{gfranklinWalletAddressId}}", + "quoteId": "{{quoteId}}" + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("outgoingPaymentId", body.data.createOutgoingPayment.payment.id); + // pm.expect(pm.environment.get("outgoingPaymentId")).to.be.a('string'); +} diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru new file mode 100644 index 0000000000..416dfc1f9d --- /dev/null +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru @@ -0,0 +1,93 @@ +meta { + name: Create Quote + type: graphql + seq: 2 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateQuote($input: CreateQuoteInput!) { + createQuote(input: $input) { + code + message + quote { + createdAt + expiresAt + highEstimatedExchangeRate + id + lowEstimatedExchangeRate + maxPacketAmount + minExchangeRate + walletAddressId + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + } + } + } +} + +body:graphql:vars { + { + "input": { + "walletAddressId": "{{gfranklinWalletAddressId}}", + "receiver": "{{receiverId}}" + } + } +} + +script:pre-request { + // + // const getWalletAddressesQuery = ` + // query GetWalletAddresses { + // walletAddresses { + // edges { + // cursor + // node { + // id + // publicName + // url + // } + // } + // } + // }` + // + // const postRequest = { + // url: `${pm.environment.get("RafikiGraphqlHost")}/graphql`, + // method: 'POST', + // body: { + // mode: 'graphql', + // graphql: { + // query:getWalletAddressesQuery + // } + // } + // }; + // + // + // pm.sendRequest(postRequest, (error, response) => { + // const body = response.json(); + // const gfranklinWalletAddressId = body.data.walletAddresses.edges.map(e => e.node).find(node => node.publicName === 'Grace Franklin')?.id + // + // pm.environment.set("gfranklinWalletAddressId", gfranklinWalletAddressId) + // }); +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("quoteId", body.data.createQuote.quote.id); + // pm.expect(pm.environment.get("quoteId")).to.be.a('string'); +} diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru new file mode 100644 index 0000000000..89b2d01b4b --- /dev/null +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru @@ -0,0 +1,63 @@ +meta { + name: Create Receiver -remote Incoming Payment- + type: graphql + seq: 1 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateReceiver($input: CreateReceiverInput!) { + createReceiver(input: $input) { + code + message + receiver { + completed + createdAt + expiresAt + metadata + id + incomingAmount { + assetCode + assetScale + value + } + walletAddressUrl + receivedAmount { + assetCode + assetScale + value + } + updatedAt + } + success + } + } +} + +body:graphql:vars { + { + "input": { + "metadata": { + "description": "For lunch!" + }, + "incomingAmount": { + "assetCode": "USD", + "assetScale": 2, + "value": 500 + }, + "walletAddressUrl": "https://happy-life-bank-backend/accounts/pfry" + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("receiverId", body.data.createReceiver.receiver.id); + // pm.expect(pm.environment.get("receiverId")).to.be.a('string'); +} diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru new file mode 100644 index 0000000000..2659d9ae8c --- /dev/null +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru @@ -0,0 +1,50 @@ +meta { + name: Get Outgoing Payment + type: graphql + seq: 4 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetOutgoingPayment($id: String!) { + outgoingPayment(id: $id) { + createdAt + error + metadata + id + walletAddressId + quote { + id + } + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + sentAmount { + assetCode + assetScale + value + } + state + stateAttempts + } + } +} + +body:graphql:vars { + { + "id": "{{outgoingPaymentId}}" + } +} diff --git a/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru b/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru new file mode 100644 index 0000000000..db658fb686 --- /dev/null +++ b/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru @@ -0,0 +1,31 @@ +meta { + name: Continuation Request + type: http + seq: 8 +} + +post { + url: {{senderOpenPaymentsAuthHost}}/continue/{{continueId}} + body: json + auth: none +} + +headers { + Authorization: GNAP {{continueToken}} +} + +body:json { + { + "interact_ref": "6d519566-234f-4c2e-b56f-6d4a305fc067" + } +} + +script:pre-request { + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // const body = pm.response.json(); + // pm.environment.set("accessToken", body.access_token.value); + // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) +} diff --git a/postman/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru b/postman/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru new file mode 100644 index 0000000000..80c449997f --- /dev/null +++ b/postman/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru @@ -0,0 +1,50 @@ +meta { + name: Create Incoming Payment + type: http + seq: 4 +} + +post { + url: {{receiverOpenPaymentsHost}}/incoming-payments + body: json + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} +} + +body:json { + { + "walletAddress": "{{receiverWalletAddress}}", + "incomingAmount": { + "value": "100", + "assetCode": "{{receiverAssetCode}}", + "assetScale": {{receiverAssetScale}} + }, + "expiresAt": "{{tomorrow}}", + "metadata": { + "description": "Free Money!" + } + } +} + +script:pre-request { + // pm.environment.set("tomorrow", (new Date(new Date().setDate(new Date().getDate() + 1))).toISOString()); + // + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) + // +} + +tests { + // pm.test("Status code is 201", function () { + // pm.response.to.have.status(201); + // }); + // + // const body = pm.response.json(); + // pm.environment.set("incomingPaymentId", body.id.split("/").pop()); + // +} diff --git a/postman/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru b/postman/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru new file mode 100644 index 0000000000..d4ecce7463 --- /dev/null +++ b/postman/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru @@ -0,0 +1,42 @@ +meta { + name: Create Outgoing Payment + type: http + seq: 9 +} + +post { + url: {{senderOpenPaymentsHost}}/outgoing-payments + body: json + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} +} + +body:json { + { + "walletAddress": "{{senderWalletAddress}}", + "quoteId": "{{senderWalletAddress}}/quotes/{{quoteId}}", + "metadata": { + "description": "Free Money!" + } + } +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // pm.test("Status code is 201", function () { + // pm.response.to.have.status(201); + // }); + // + // const body = pm.response.json(); + // pm.environment.set("outgoingPaymentId", body.id.split("/").pop()); + // +} diff --git a/postman/collections/Interledger/Examples/Open Payments/Create Quote.bru b/postman/collections/Interledger/Examples/Open Payments/Create Quote.bru new file mode 100644 index 0000000000..b60ff08684 --- /dev/null +++ b/postman/collections/Interledger/Examples/Open Payments/Create Quote.bru @@ -0,0 +1,42 @@ +meta { + name: Create Quote + type: http + seq: 6 +} + +post { + url: {{senderOpenPaymentsHost}}/quotes + body: json + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} +} + +body:json { + { + "walletAddress": "{{senderWalletAddress}}", + "receiver": "{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}", + "method": "ilp" + } +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // pm.test("Status code is 201", function () { + // pm.response.to.have.status(201); + // }); + // + // const body = pm.response.json(); + // pm.environment.set("quoteId", body.id.split("/").pop()); + // pm.environment.set("quoteDebitAmount", JSON.stringify(body.debitAmount)) + // pm.environment.set("quoteReceiveAmount", JSON.stringify(body.receiveAmount)) + // +} diff --git a/postman/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru b/postman/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru new file mode 100644 index 0000000000..8ee961f93a --- /dev/null +++ b/postman/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru @@ -0,0 +1,29 @@ +meta { + name: Get Outgoing Payment + type: http + seq: 10 +} + +get { + url: {{senderOpenPaymentsHost}}/outgoing-payments/{{outgoingPaymentId}} + body: none + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // pm.test("Status code is 200", function () { + // pm.response.to.have.status(200); + // }); + // +} diff --git a/postman/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru b/postman/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru new file mode 100644 index 0000000000..c949584080 --- /dev/null +++ b/postman/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru @@ -0,0 +1,55 @@ +meta { + name: Get receiver wallet address + type: http + seq: 2 +} + +get { + url: {{receiverWalletAddress}} + body: none + auth: none +} + +headers { + Accept: application/json +} + +script:pre-request { + // const url = require('url') + // + // const requestUrl = url.parse(request.url + // .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key))) + // + // pm.environment.set("receiverOpenPaymentsHost", requestUrl.protocol + '//' + requestUrl.host); + // + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } +} + +tests { + // const url = require('url') + // + // pm.test("Status code is 200", function () { + // pm.response.to.have.status(200); + // }); + // + // const body = pm.response.json(); + // pm.environment.set("receiverAssetCode", body?.assetCode) + // pm.environment.set("receiverAssetScale", body?.assetScale) + // + // const authUrl = url.parse(body?.authServer) + // if ( + // authUrl.hostname.includes('cloud-nine-wallet') || + // authUrl.hostname.includes('happy-life-bank') + // ){ + // const port = authUrl.hostname.includes('cloud-nine-wallet') + // ? authUrl.port + // : Number(authUrl.port) + 1000 + // pm.environment.set("receiverOpenPaymentsAuthHost", authUrl.protocol + '//localhost:' + port ); + // } else { + // pm.environment.set("receiverOpenPaymentsAuthHost", body?.authServer); + // } + // + // +} diff --git a/postman/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru b/postman/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru new file mode 100644 index 0000000000..3ceed25f2e --- /dev/null +++ b/postman/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru @@ -0,0 +1,61 @@ +meta { + name: Get sender wallet address + type: http + seq: 1 +} + +get { + url: {{senderWalletAddress}} + body: none + auth: none +} + +headers { + Accept: application/json +} + +script:pre-request { + const url = require('url') + + const requestUrl = url.parse(req.url + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key))) + + bru.setEnvVar("senderOpenPaymentsHost", requestUrl.protocol + '//' + requestUrl.host); + + // if(bru.getEnvVar('preRequestHost')){ + // eval(bru.getEnvVar('preRequestHost')) + // } + + if(requestUrl.hostname === 'localhost'){ + const hostHeader = requestUrl.port === '3000'? bru.getEnvVar('host3000'): bru.getEnvVar('host4000') + req.headers.host = hostHeader + } +} + +script:post-response { + const url = require('url') + + const body = res.body + bru.setEnvVar("senderAssetCode", body?.assetCode) + bru.setEnvVar("senderAssetScale", body?.assetScale) + + const authUrl = url.parse(body?.authServer) + if ( + authUrl.hostname.includes('cloud-nine-wallet') || + authUrl.hostname.includes('happy-life-bank') + ){ + const port = authUrl.hostname.includes('cloud-nine-wallet')? authUrl.port: Number(authUrl.port) + 1000 + bru.setEnvVar("senderOpenPaymentsAuthHost", authUrl.protocol + '//localhost:' + port ); + } else { + bru.setEnvVar("senderOpenPaymentsAuthHost", body?.authServer); + } + + + +} + +tests { + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); +} diff --git a/postman/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru b/postman/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru new file mode 100644 index 0000000000..959e094619 --- /dev/null +++ b/postman/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru @@ -0,0 +1,40 @@ +meta { + name: Grant Request Incoming Payment + type: http + seq: 3 +} + +post { + url: {{receiverOpenPaymentsAuthHost}}/ + body: json + auth: none +} + +body:json { + { + "access_token": { + "access": [ + { + "type": "incoming-payment", + "actions": [ + "create", "read", "list", "complete" + ] + } + ] + }, + "client": "{{clientWalletAddress}}" + } +} + +script:pre-request { + // eval(pm.environment.get('preRequestSignatures')) + // +} + +tests { + // const body = pm.response.json(); + // pm.environment.set("accessToken", body?.access_token?.value); + // pm.environment.set("continueToken", body.continue.access_token.value); + // pm.environment.set("continueId", body.continue.uri.split("/").pop()); + // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) +} diff --git a/postman/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru b/postman/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru new file mode 100644 index 0000000000..d19a7cc98b --- /dev/null +++ b/postman/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru @@ -0,0 +1,55 @@ +meta { + name: Grant Request Outgoing Payment + type: http + seq: 7 +} + +post { + url: {{senderOpenPaymentsAuthHost}}/ + body: json + auth: none +} + +body:json { + { + "access_token": { + "access": [ + { + "type": "outgoing-payment", + "actions": [ + "create", "read", "list" + ], + "identifier": "{{senderWalletAddress}}", + "limits": { + "debitAmount": {{quoteDebitAmount}}, + "receiveAmount": {{quoteReceiveAmount}} + } + } + ] + }, + "client": "{{clientWalletAddress}}", + "interact": { + "start": [ + "redirect" + ], + "finish": { + "method": "redirect", + "uri": "https://example.com", + "nonce": "456" + } + } + } + +} + +script:pre-request { + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // const body = pm.response.json(); + // pm.environment.set("accessToken", body?.access_token?.value); + // pm.environment.set("continueToken", body.continue.access_token.value); + // pm.environment.set("continueId", body.continue.uri.split("/").pop()); + // +} diff --git a/postman/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru b/postman/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru new file mode 100644 index 0000000000..21c058d403 --- /dev/null +++ b/postman/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru @@ -0,0 +1,40 @@ +meta { + name: Grant Request Quote + type: http + seq: 5 +} + +post { + url: {{senderOpenPaymentsAuthHost}}/ + body: json + auth: none +} + +body:json { + { + "access_token": { + "access": [ + { + "type": "quote", + "actions": [ + "create", "read" + ] + } + ] + }, + "client": "{{clientWalletAddress}}" + } + +} + +script:pre-request { + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // const body = pm.response.json(); + // pm.environment.set("accessToken", body?.access_token?.value); + // pm.environment.set("continueToken", body.continue.access_token.value); + // pm.environment.set("continueId", body.continue.uri.split("/").pop()); + // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) +} diff --git a/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru b/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru new file mode 100644 index 0000000000..4db9c28700 --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru @@ -0,0 +1,23 @@ +meta { + name: Complete Incoming Payment + type: http + seq: 5 +} + +post { + url: {{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}/complete + body: json + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} + ~Host: happy-life-bank-backend +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) +} diff --git a/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru b/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru new file mode 100644 index 0000000000..6cef2d19f6 --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru @@ -0,0 +1,50 @@ +meta { + name: Create Incoming Payment + type: http + seq: 1 +} + +post { + url: {{receiverOpenPaymentsHost}}/incoming-payments + body: json + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} +} + +body:json { + { + "walletAddress": "{{clientWalletAddress}}", + "incomingAmount": { + "value": "2000", + "assetCode": "USD", + "assetScale": 2 + }, + "expiresAt": "{{tomorrow}}", + "metadata": { + "description": "Incoming Payment on Own Account", + "externalRef": "INV-001" + } + } +} + +script:pre-request { + // pm.environment.set("tomorrow", (new Date(new Date().setDate(new Date().getDate() + 1))).toISOString()); + // + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // pm.test("Status code is 201", function () { + // pm.response.to.have.status(201); + // }); + // + // const body = pm.response.json(); + // pm.environment.set("incomingPaymentId", body.id.split("/").pop()); + // +} diff --git a/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru b/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru new file mode 100644 index 0000000000..89496daf6d --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru @@ -0,0 +1,27 @@ +meta { + name: Get Incoming Payment -Unauthenticated- + type: http + seq: 3 +} + +get { + url: {{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}} + body: none + auth: none +} + +headers { + Host: happy-life-bank-backend + ~Authorization: GNAP {{accessToken}} +} + +script:pre-request { + // +} + +tests { + // pm.test("Status code is 200", function () { + // pm.response.to.have.status(200); + // }); + // +} diff --git a/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru b/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru new file mode 100644 index 0000000000..d8433085df --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru @@ -0,0 +1,29 @@ +meta { + name: Get Incoming Payment + type: http + seq: 2 +} + +get { + url: {{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}} + body: none + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // pm.test("Status code is 200", function () { + // pm.response.to.have.status(200); + // }); + // +} diff --git a/postman/collections/Interledger/Open Payments APIs/Incoming Payments/List Incoming Payments.bru b/postman/collections/Interledger/Open Payments APIs/Incoming Payments/List Incoming Payments.bru new file mode 100644 index 0000000000..6669c06902 --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Incoming Payments/List Incoming Payments.bru @@ -0,0 +1,53 @@ +meta { + name: List Incoming Payments + type: http + seq: 4 +} + +get { + url: {{receiverOpenPaymentsHost}}/incoming-payments?first=10&wallet-address={{receiverWalletAddress}} + body: none + auth: none +} + +query { + first: 10 + wallet-address: {{receiverWalletAddress}} + ~cursor: ea3bf38f-2719-4473-a0f7-4ba967d1d81b +} + +headers { + Authorization: GNAP {{accessToken}} +} + +script:pre-request { + // request.url = request.url + // .replace(/{{(receiverWalletAddress)}}/g, (_, key) => pm.environment.get(key)) + // .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => + // key === '3' + // ? 'https://' + pm.environment.get('host3000') + // : 'https://' + pm.environment.get('host4000') + // ) + // console.log(request.url) + // + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) + // + // pm.request.url.query.idx(2).value = pm.request.url.query.idx(2).value + // .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) + // .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => + // key === '3' + // ? 'https://' + pm.environment.get('host3000') + // : 'https://' + pm.environment.get('host4000') + // ) + // +} + +tests { + // pm.test("Status code is 200", function () { + // pm.response.to.have.status(200); + // }); + // +} diff --git a/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru b/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru new file mode 100644 index 0000000000..e69a8c9211 --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru @@ -0,0 +1,43 @@ +meta { + name: Create Outgoing Payment + type: http + seq: 1 +} + +post { + url: {{senderOpenPaymentsHost}}/outgoing-payments + body: json + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} +} + +body:json { + { + "walletAddress": {{senderWalletAddress}}, + "quoteId": "{{senderOpenPaymentsHost}}/quotes/{{quoteId}}", + "metadata": { + "description": "yolo", + "externalRef": "INV-001" + } + } +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // pm.test("Status code is 201", function () { + // pm.response.to.have.status(201); + // }); + // + // const body = pm.response.json(); + // pm.environment.set("outgoingPaymentId", body.id.split("/").pop()); + // +} diff --git a/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru b/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru new file mode 100644 index 0000000000..58c1272b9b --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru @@ -0,0 +1,29 @@ +meta { + name: Get Outgoing Payment + type: http + seq: 2 +} + +get { + url: {{senderOpenPaymentsHost}}/outgoing-payments/{{outgoingPaymentId}} + body: none + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // pm.test("Status code is 200", function () { + // pm.response.to.have.status(200); + // }); + // +} diff --git a/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru b/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru new file mode 100644 index 0000000000..8c412c96c5 --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru @@ -0,0 +1,53 @@ +meta { + name: List Outgoing Payments + type: http + seq: 3 +} + +get { + url: {{senderOpenPaymentsHost}}/outgoing-payments?first=2&wallet-address={{senderWalletAddress}} + body: none + auth: none +} + +query { + first: 2 + wallet-address: {{senderWalletAddress}} + ~cursor: ea3bf38f-2719-4473-a0f7-4ba967d1d81b +} + +headers { + Authorization: GNAP {{accessToken}} +} + +script:pre-request { + // request.url = request.url + // .replace(/{{(senderWalletAddress)}}/g, (_, key) => pm.environment.get(key)) + // .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => + // key === '3' + // ? 'https://' + pm.environment.get('host3000') + // : 'https://' + pm.environment.get('host4000') + // ) + // console.log(request.url) + // + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) + // + // pm.request.url.query.idx(2).value = pm.request.url.query.idx(2).value + // .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) + // .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => + // key === '3' + // ? 'https://' + pm.environment.get('host3000') + // : 'https://' + pm.environment.get('host4000') + // ) + // +} + +tests { + // pm.test("Status code is 200", function () { + // pm.response.to.have.status(200); + // }); + // +} diff --git a/postman/collections/Interledger/Open Payments APIs/Quotes/Create Quote.bru b/postman/collections/Interledger/Open Payments APIs/Quotes/Create Quote.bru new file mode 100644 index 0000000000..92e55ba577 --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Quotes/Create Quote.bru @@ -0,0 +1,45 @@ +meta { + name: Create Quote + type: http + seq: 1 +} + +post { + url: {{senderOpenPaymentsHost}}/quotes + body: json + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} +} + +body:json { + { + "receiver": "{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}", + "walletAddress": "{{senderWalletAddress}}", + "debitAmount": { + "value": "1000", + "assetCode": "{{receiverAssetCode}}", + "assetScale": {{receiverAssetScale}} + }, + "method": "ilp" + } +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // pm.test("Status code is 201", function () { + // pm.response.to.have.status(201); + // }); + // + // const body = pm.response.json(); + // pm.environment.set("quoteId", body.id.split("/").pop()); + // +} diff --git a/postman/collections/Interledger/Open Payments APIs/Quotes/Get Quote.bru b/postman/collections/Interledger/Open Payments APIs/Quotes/Get Quote.bru new file mode 100644 index 0000000000..9abe2724e9 --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Quotes/Get Quote.bru @@ -0,0 +1,30 @@ +meta { + name: Get Quote + type: http + seq: 2 +} + +get { + url: {{senderOpenPaymentsHost}}/quotes/{{quoteId}} + body: none + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} + ~Host: cloud-nine-wallet-backend +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // pm.test("Status code is 200", function () { + // pm.response.to.have.status(200); + // }); + // +} diff --git a/postman/collections/Interledger/Open Payments APIs/Wallet Address/Get Wallet Address Keys.bru b/postman/collections/Interledger/Open Payments APIs/Wallet Address/Get Wallet Address Keys.bru new file mode 100644 index 0000000000..8910b303fe --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Wallet Address/Get Wallet Address Keys.bru @@ -0,0 +1,17 @@ +meta { + name: Get Wallet Address Keys + type: http + seq: 2 +} + +get { + url: {{receiverWalletAddress}}/jwks.json + body: none + auth: none +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } +} diff --git a/postman/collections/Interledger/Open Payments APIs/Wallet Address/Get a Wallet Address.bru b/postman/collections/Interledger/Open Payments APIs/Wallet Address/Get a Wallet Address.bru new file mode 100644 index 0000000000..95995c8320 --- /dev/null +++ b/postman/collections/Interledger/Open Payments APIs/Wallet Address/Get a Wallet Address.bru @@ -0,0 +1,44 @@ +meta { + name: Get a Wallet Address + type: http + seq: 1 +} + +get { + url: {{receiverWalletAddress}} + body: none + auth: none +} + +headers { + Accept: application/json +} + +script:pre-request { + // if(pm.environment.get('preRequestHost')){ + // eval(pm.environment.get('preRequestHost')) + // } +} + +tests { + // pm.test("Status code is 200", function () { + // pm.response.to.have.status(200); + // }); + // + // const body = pm.response.json(); + // pm.environment.set("receiverAssetCode", body?.assetCode) + // pm.environment.set("receiverAssetScale", body?.assetScale) + // + // const authUrl = url.parse(body?.authServer) + // if ( + // authUrl.hostname.includes('cloud-nine-wallet') || + // authUrl.hostname.includes('happy-life-bank') + // ){ + // const port = authUrl.hostname.includes('cloud-nine-wallet') + // ? authUrl.port + // : Number(authUrl.port) + 1000 + // pm.environment.set("receiverOpenPaymentsAuthHost", authUrl.protocol + '//localhost:' + port ); + // } else { + // pm.environment.set("receiverOpenPaymentsAuthHost", body?.authServer); + // } +} diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru b/postman/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru new file mode 100644 index 0000000000..59e1b630aa --- /dev/null +++ b/postman/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru @@ -0,0 +1,31 @@ +meta { + name: Continuation Request + type: http + seq: 2 +} + +post { + url: {{receiverOpenPaymentsAuthHost}}/continue/{{continueId}} + body: json + auth: none +} + +headers { + Authorization: GNAP {{continueToken}} +} + +body:json { + { + "interact_ref": "fdfa9202-3e68-4c2a-8049-25135704a1cb" + } +} + +script:pre-request { + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // const body = pm.response.json(); + // pm.environment.set("accessToken", body.access_token.value); + // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) +} diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru b/postman/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru new file mode 100644 index 0000000000..66fdbf2bf7 --- /dev/null +++ b/postman/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru @@ -0,0 +1,69 @@ +meta { + name: Grant Request + type: http + seq: 1 +} + +post { + url: {{receiverOpenPaymentsAuthHost}}/ + body: json + auth: none +} + +body:json { + { + "access_token": { + "access": [ + { + "type": "quote", + "actions": [ + "create", "read" + ] + }, + { + "type": "outgoing-payment", + "actions": [ + "create", "read", "list" + ], + "identifier": "{{senderWalletAddress}}", + "limits": { + "debitAmount": { + "value": "8000", + "assetCode": "USD", + "assetScale": 2 + }, + "receiveAmount": { + "value": "8000", + "assetCode": "USD", + "assetScale": 2 + } + } + } + ] + }, + "client": "{{clientWalletAddress}}", + "interact": { + "start": [ + "redirect" + ], + "finish": { + "method": "redirect", + "uri": "http://localhost:3030/mock-idp/fake-client", + "nonce": "123" + } + } + } + +} + +script:pre-request { + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // const body = pm.response.json(); + // pm.environment.set("accessToken", body?.access_token?.value); + // pm.environment.set("continueToken", body.continue.access_token.value); + // pm.environment.set("continueId", body.continue.uri.split("/").pop()); + // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) +} diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru b/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru new file mode 100644 index 0000000000..da702b8fd7 --- /dev/null +++ b/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru @@ -0,0 +1,15 @@ +meta { + name: Revoke Access Token + type: http + seq: 2 +} + +delete { + url: {{receiverOpenPaymentsAuthHost}}/token/{{tokenId}} + body: none + auth: none +} + +script:pre-request { + // eval(pm.environment.get('preRequestSignatures')) +} diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru b/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru new file mode 100644 index 0000000000..94f505a760 --- /dev/null +++ b/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru @@ -0,0 +1,25 @@ +meta { + name: Rotate Access Token + type: http + seq: 1 +} + +post { + url: {{receiverOpenPaymentsAuthHost}}/token/{{tokenId}} + body: none + auth: none +} + +headers { + Authorization: GNAP {{accessToken}} +} + +script:pre-request { + // eval(pm.environment.get('preRequestSignatures')) +} + +tests { + // const body = pm.response.json(); + // pm.environment.set("accessToken", body.access_token.value); + // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru new file mode 100644 index 0000000000..d8c14db015 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru @@ -0,0 +1,46 @@ +meta { + name: Create Asset + type: graphql + seq: 1 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateAsset($input: CreateAssetInput!) { + createAsset(input: $input) { + asset { + code + createdAt + id + scale + withdrawalThreshold + liquidityThreshold + } + code + message + success + } + } +} + +body:graphql:vars { + { + "input": { + "code": "USD", + "scale": 6, + "withdrawalThreshold": null, + "liquidityThreshold": "100000000" + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("assetId", body.data.createAsset.asset.id); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru new file mode 100644 index 0000000000..e22b7fb63d --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru @@ -0,0 +1,60 @@ +meta { + name: Create Incoming Payment + type: graphql + seq: 24 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateIncomingPayment ($input: CreateIncomingPaymentInput!) { + createIncomingPayment(input: $input) { + code + message + payment { + createdAt + expiresAt + metadata + id + incomingAmount { + assetCode + assetScale + value + } + walletAddressId + receivedAmount { + assetCode + assetScale + value + } + state + } + success + } + } +} + +body:graphql:vars { + { + "input": { + "expiresAt": null, + "metadata": { + "externalRef": null, + "description": "Hello World" + }, + "incomingAmount": null, + "walletAddressId": "{{walletAddressId}}" + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("incomingPaymentId", body.data.createIncomingPayment.payment.id); + // pm.expect(pm.environment.get("incomingPaymentId")).to.be.a('string'); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru new file mode 100644 index 0000000000..cf09d3dcae --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru @@ -0,0 +1,47 @@ +meta { + name: Create Or Update Peer By Url + type: graphql + seq: 9 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateOrUpdatePeerByUrl ($input: CreateOrUpdatePeerByUrlInput!) { + createOrUpdatePeerByUrl (input: $input) { + code + message + success + peer { + id + name + asset { + id + scale + code + withdrawalThreshold + } + } + } + } +} + +body:graphql:vars { + { + "input": { + "peerUrl": "http://happy-life-bank-backend:3005", + "assetId": "{{assetId}}", + "liquidityToDeposit": 100000 + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("peerId", body.data.createOrUpdatePeerByUrl.peer.id); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru new file mode 100644 index 0000000000..466ea9c381 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru @@ -0,0 +1,87 @@ +meta { + name: Create Outgoing Payment + type: graphql + seq: 31 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateOutgoingPayment($input: CreateOutgoingPaymentInput!) { + createOutgoingPayment(input: $input) { + code + message + payment { + createdAt + error + metadata + id + walletAddressId + quote { + createdAt + expiresAt + highEstimatedExchangeRate + id + lowEstimatedExchangeRate + maxPacketAmount + minExchangeRate + walletAddressId + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + } + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + sentAmount { + assetCode + assetScale + value + } + state + stateAttempts + } + success + } + } +} + +body:graphql:vars { + { + "input": { + "metadata": { + "description": null, + "externalRef": null + }, + "walletAddressId": "{{secondWalletAddressId}}", + "quoteId": "{{quoteId}}" + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("outgoingPaymentId", body.data.createOutgoingPayment.payment.id); + // pm.expect(pm.environment.get("outgoingPaymentId")).to.be.a('string'); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Peer.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Peer.bru new file mode 100644 index 0000000000..4c1dd1ea36 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Peer.bru @@ -0,0 +1,56 @@ +meta { + name: Create Peer + type: graphql + seq: 8 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreatePeer ($input: CreatePeerInput!) { + createPeer (input: $input) { + code + message + success + peer { + id + name + liquidity + liquidityThreshold + asset{ + id + scale + code + withdrawalThreshold + } + } + } + } +} + +body:graphql:vars { + { + "input": { + "name": "Wallet1", + "staticIlpAddress": "test.peer", + "http": { + "incoming": {"authTokens": ["test123abc"]}, + "outgoing": {"endpoint": "http://peer-backend:3002", "authToken": "test123abc"} + }, + "assetId": "{{assetId}}", + "maxPacketAmount": 1000, + "liquidityThreshold": 100000000, + "initialLiquidity": 200000000 + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("peerId", body.data.createPeer.peer.id); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru new file mode 100644 index 0000000000..a552410a98 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru @@ -0,0 +1,103 @@ +meta { + name: Create Quote + type: graphql + seq: 29 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateQuote($input: CreateQuoteInput!) { + createQuote(input: $input) { + code + message + quote { + createdAt + expiresAt + highEstimatedExchangeRate + id + lowEstimatedExchangeRate + maxPacketAmount + minExchangeRate + walletAddressId + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + } + } + } +} + +body:graphql:vars { + { + "input": { + "walletAddressId": "{{secondWalletAddressId}}", + "receiveAmount": null, + "receiver": "{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}", + "debitAmount": { + "assetCode": "USD", + "assetScale": 6, + "value": 5000000 + } + } + } +} + +script:pre-request { + // // Create an additional wallet address to represent the account that will be sending money + // + // // Reset the uniqueWalletAddress value + // pm.environment.set("uniqueWalletAddress", Math.floor(Math.random() * (1001))); + // + // const initialRequest = pm.environment.get("createWalletAddressRequest"); + // + // const postRequest = { + // url: initialRequest.url, + // method: initialRequest.method, + // body: { + // mode: 'graphql', + // graphql: { + // query: initialRequest.body.graphql.query, + // variables: JSON.stringify({ + // "input": { + // "assetId": pm.environment.get("assetId"), + // "url": "https://" + pm.environment.get("OpenPaymentsHost") + "/simon/" + pm.environment.get("uniqueWalletAddress"), + // "publicName": "Simon" + // } + // }) + // } + // } + // }; + // + // pm.sendRequest(postRequest, (error, response) => { + // if (error) { + // console.log(error); + // } + // const body = response.json(); + // pm.test('response should be okay to process', () => { + // pm.expect(error).to.equal(null); + // pm.expect(body.data.createWalletAddress.code).to.equal('200'); + // pm.expect(body.data.createWalletAddress.success).to.equal(true); + // }); + // pm.environment.set("secondWalletAddressId", body.data.createWalletAddress.walletAddress.id); + // }); +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("quoteId", body.data.createQuote.quote.id); + // pm.expect(pm.environment.get("quoteId")).to.be.a('string'); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru new file mode 100644 index 0000000000..31258c9594 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru @@ -0,0 +1,64 @@ +meta { + name: Create Receiver -remote Incoming Payment- + type: graphql + seq: 27 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateReceiver($input: CreateReceiverInput!) { + createReceiver(input: $input) { + code + message + receiver { + completed + createdAt + expiresAt + metadata + id + incomingAmount { + assetCode + assetScale + value + } + walletAddressUrl + receivedAmount { + assetCode + assetScale + value + } + updatedAt + } + success + } + } +} + +body:graphql:vars { + { + "input": { + "expiresAt": null, + "metadata": { + "description": "Hello my friend", + "externalRef": null + }, + "incomingAmount": { + "assetCode": "USD", + "assetScale": 2, + "value": 1002 + }, + "walletAddressUrl": "https://happy-life-bank-backend/accounts/pfry" + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("receiverId", body.data.createReceiver.receiver.id); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru new file mode 100644 index 0000000000..9f114c8849 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru @@ -0,0 +1,55 @@ +meta { + name: Create Wallet Address Key + type: graphql + seq: 22 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateWalletAddressKey ($input: CreateWalletAddressKeyInput!) { + createWalletAddressKey(input: $input) { + code + message + success + walletAddressKey { + id + revoked + walletAddressId + createdAt + jwk { + alg + crv + kid + kty + x + } + } + } + } +} + +body:graphql:vars { + { + "input": { + "walletAddressId": "{{walletAddressId}}", + "jwk": { + "alg": "EdDSA", + "crv": "Ed25519", + "kid": "kid_dad93e7f-f40b-484d-99d2-df12c8523176", + "kty": "OKP", + "x": "ubqoInifJ5sssIPPnQR1gVPfmoZnJtPhTkyMXNoJF_8" + } + } + } +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("walletAddressKeyId", body.data.createWalletAddressKey.walletAddressKey.id); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru new file mode 100644 index 0000000000..9737619f00 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru @@ -0,0 +1,46 @@ +meta { + name: Create Wallet Address Withdrawal + type: graphql + seq: 38 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateWalletAddressWithdrawal($input: CreateWalletAddressWithdrawalInput!) { + createWalletAddressWithdrawal(input: $input) { + code + error + message + success + withdrawal { + amount + id + walletAddress { + id + url + asset { + id + code + scale + withdrawalThreshold + } + } + } + } + } +} + +body:graphql:vars { + { + "input": { + "id": "02ac56f7-ae5d-4abb-8306-17bf2327b43c", + "walletAddressId": "{{walletAddressId}}", + "idempotencyKey":"{{$guid}}" + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru new file mode 100644 index 0000000000..e1b798674b --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru @@ -0,0 +1,61 @@ +meta { + name: Create Wallet Address + type: graphql + seq: 18 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateWalletAddres($input: CreateWalletAddressInput!) { + createWalletAddress(input: $input) { + code + success + message + walletAddress { + id + createdAt + publicName + url + status + asset { + code + createdAt + id + scale + withdrawalThreshold + } + } + } + } +} + +body:graphql:vars { + { + "input": { + "assetId": "{{assetId}}", + "url": "https://{{senderOpenPaymentsHost}}/timon/{{$randomInt}}", + "publicName": "Timon" + } + } +} + +script:pre-request { + // +} + +tests { + // const body = pm.response.json(); + // + // pm.environment.set("walletAddressId", body.data.createWalletAddress.walletAddress.id); + // pm.expect(pm.environment.get("walletAddressId")).to.be.a('string'); + // + // pm.environment.set("walletAddressUrl", body.data.createWalletAddress.walletAddress.url); + // pm.expect(pm.environment.get("walletAddressUrl")).to.be.a('string'); + // + // pm.environment.set("createWalletAddressRequest", pm.request); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Delete Peer.bru b/postman/collections/Interledger/Rafiki Admin APIs/Delete Peer.bru new file mode 100644 index 0000000000..beaee1b827 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Delete Peer.bru @@ -0,0 +1,30 @@ +meta { + name: Delete Peer + type: graphql + seq: 13 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation DeletePeer($input: DeletePeerInput!) { + deletePeer(input: $input) { + code + message + success + } + } + +} + +body:graphql:vars { + { + "input": { + "id": "{{peerId}}" + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru new file mode 100644 index 0000000000..eaf3dd9fed --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru @@ -0,0 +1,34 @@ +meta { + name: Deposit Asset Liquidity + type: graphql + seq: 5 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation DepositAssetLiquidity ($input: DepositAssetLiquidityInput!) { + depositAssetLiquidity(input: $input) { + code + success + message + error + } + } +} + +body:graphql:vars { + { + "input": { + "id": "3615a385-4c7e-43ec-9d66-f5d2e421108a", + "assetId": "{{assetId}}", + "amount": "1000000", + "idempotencyKey":"{{$guid}}" + } + } + +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru new file mode 100644 index 0000000000..d20f9a170a --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru @@ -0,0 +1,31 @@ +meta { + name: Deposit Event Liquidity + type: graphql + seq: 34 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation DepositEventLiquidity($input: DepositEventLiquidityInput!) { + depositEventLiquidity(input: $input) { + code + error + message + success + } + } +} + +body:graphql:vars { + { + "input": { + "eventId": "b4f85d5c-652d-472d-873c-4ba2a5e39052", + "idempotencyKey":"{{$guid}}" + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru new file mode 100644 index 0000000000..1b85f3a3b6 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru @@ -0,0 +1,32 @@ +meta { + name: Deposit Outgoing Payment Liquidity + type: graphql + seq: 35 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation DepositOutgoingPaymentLiquidity($input: DepositOutgoingPaymentLiquidityInput!) { + depositOutgoingPaymentLiquidity(input: $input) { + code + error + message + success + } + } + +} + +body:graphql:vars { + { + "input": { + "outgoingPaymentId": "{{outgoingPaymentId}}", + "idempotencyKey":"{{$guid}}" + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru new file mode 100644 index 0000000000..85195f7035 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru @@ -0,0 +1,34 @@ +meta { + name: Deposit Peer Liquidity + type: graphql + seq: 14 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation DepositPeerLiquidity ($input: DepositPeerLiquidityInput!) { + depositPeerLiquidity(input: $input) { + code + success + message + error + } + } +} + +body:graphql:vars { + { + "input": { + "id": "a09b730d-8610-4fda-98fa-ec7acb19c775", + "peerId": "{{peerId}}", + "amount": "1000000", + "idempotencyKey":"{{$guid}}" + } + } + +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Asset.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Asset.bru new file mode 100644 index 0000000000..93c7690159 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Asset.bru @@ -0,0 +1,42 @@ +meta { + name: Get Asset + type: graphql + seq: 3 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetAsset($id: String!) { + asset(id: $id) { + code + createdAt + id + scale + withdrawalThreshold + liquidityThreshold + sendingFee { + id + type + basisPoints + fixed + } + receivingFee { + id + type + basisPoints + fixed + } + } + } +} + +body:graphql:vars { + { + "id": "{{assetId}}" + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Assets.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Assets.bru new file mode 100644 index 0000000000..3e4f00fe7b --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Assets.bru @@ -0,0 +1,57 @@ +meta { + name: Get Assets + type: graphql + seq: 4 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetAssets($after: String, $before: String, $first: Int, $last: Int) { + assets(after: $after, before: $before, first:$first, last: $last) { + edges { + cursor + node { + code + createdAt + id + scale + withdrawalThreshold + liquidityThreshold + liquidity + sendingFee { + id + type + basisPoints + fixed + } + receivingFee { + id + type + basisPoints + fixed + } + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } +} + +body:graphql:vars { + { + "after": null, + "before": null, + "first": null, + "last": null + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Incoming Payment.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Incoming Payment.bru new file mode 100644 index 0000000000..6cfc959eae --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Incoming Payment.bru @@ -0,0 +1,40 @@ +meta { + name: Get Incoming Payment + type: graphql + seq: 25 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetIncomingPayment($id: String!) { + incomingPayment(id: $id) { + id + walletAddressId + state + expiresAt + incomingAmount { + value + assetCode + assetScale + } + receivedAmount { + value + assetCode + assetScale + } + metadata + createdAt + } + } +} + +body:graphql:vars { + { + "id": "{{incomingPaymentId}}" + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Outgoing Payment.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Outgoing Payment.bru new file mode 100644 index 0000000000..a953f0595f --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Outgoing Payment.bru @@ -0,0 +1,68 @@ +meta { + name: Get Outgoing Payment + type: graphql + seq: 32 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetOutgoingPayment($id: String!) { + outgoingPayment(id: $id) { + createdAt + error + metadata + id + walletAddressId + quote { + createdAt + expiresAt + highEstimatedExchangeRate + id + lowEstimatedExchangeRate + maxPacketAmount + minExchangeRate + walletAddressId + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + } + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + sentAmount { + assetCode + assetScale + value + } + state + stateAttempts + } + } +} + +body:graphql:vars { + { + "id": "{{outgoingPaymentId}}" + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Payments.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Payments.bru new file mode 100644 index 0000000000..8ee443d2b5 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Payments.bru @@ -0,0 +1,42 @@ +meta { + name: Get Payments + type: graphql + seq: 33 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query Payments($filter: PaymentFilter) { + payments(filter: $filter) { + edges { + node { + id + type + walletAddressId + state + metadata + createdAt + } + cursor + } + } + } +} + +body:graphql:vars { + { + "filter": { + "type": { + "in": ["OUTGOING"] + }, + "walletAddressId": { + "in": ["{{secondWalletAddressId}}"] + } + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Peer.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Peer.bru new file mode 100644 index 0000000000..b187c6567b --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Peer.bru @@ -0,0 +1,28 @@ +meta { + name: Get Peer + type: graphql + seq: 11 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetPeer { + peer (id: "{{peerId}}") { + id + name + http { + outgoing { + authToken + endpoint + } + } + liquidity + liquidityThreshold + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Peers.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Peers.bru new file mode 100644 index 0000000000..bf8cf85414 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Peers.bru @@ -0,0 +1,38 @@ +meta { + name: Get Peers + type: graphql + seq: 12 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetPeers { + peers { + edges { + cursor + node { + id + name + asset { + code + scale + } + liquidity + liquidityThreshold + staticIlpAddress + http { + outgoing { + authToken + endpoint + } + } + } + } + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Quote.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Quote.bru new file mode 100644 index 0000000000..731fddefcf --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Quote.bru @@ -0,0 +1,43 @@ +meta { + name: Get Quote + type: graphql + seq: 30 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetQuote($id: String!) { + quote(id: $id) { + createdAt + highEstimatedExchangeRate + expiresAt + id + lowEstimatedExchangeRate + maxPacketAmount + minExchangeRate + walletAddressId + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + } + } +} + +body:graphql:vars { + { + "id": "{{quoteId}}" + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Receiver -remote Incoming Payment-.bru new file mode 100644 index 0000000000..606e2303ce --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Receiver -remote Incoming Payment-.bru @@ -0,0 +1,41 @@ +meta { + name: Get Receiver -remote Incoming Payment- + type: graphql + seq: 28 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetReceiver($id: String!) { + receiver(id: $id) { + id + completed + expiresAt + metadata + incomingAmount { + assetCode + assetScale + value + } + walletAddressUrl + receivedAmount { + assetCode + assetScale + value + } + createdAt + updatedAt + } + } +} + +body:graphql:vars { + { + "id": "{{receiverId}}" + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Address.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Address.bru new file mode 100644 index 0000000000..9bb51e4072 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Address.bru @@ -0,0 +1,55 @@ +meta { + name: Get Wallet Address + type: graphql + seq: 20 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetWalletAddress($id: String!) { + walletAddress(id: $id) { + id + asset { + id + code + scale + withdrawalThreshold + createdAt + } + createdAt + incomingPayments { + edges { + node { + id + state + incomingAmount { + value + } + receivedAmount { + value + } + } + cursor + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + status + } + } +} + +body:graphql:vars { + { + "id": "{{walletAddressId}}" + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Addresses.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Addresses.bru new file mode 100644 index 0000000000..712c40d35f --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Addresses.bru @@ -0,0 +1,26 @@ +meta { + name: Get Wallet Addresses + type: graphql + seq: 21 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query GetWalletAddresses { + walletAddresses { + edges { + cursor + node { + id + publicName + url + } + } + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Webhook Events.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Webhook Events.bru new file mode 100644 index 0000000000..a7d29b9a60 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Webhook Events.bru @@ -0,0 +1,41 @@ +meta { + name: Get Webhook Events + type: graphql + seq: 40 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query WebhookEvents($after: String, $before: String, $first: Int, $last: Int, $filter: WebhookEventFilter) { + webhookEvents(after: $after, before: $before, first:$first, last: $last, filter: $filter) { + edges { + cursor + node { + createdAt + data + id + type + } + } + } + } +} + +body:graphql:vars { + { + "filter": { + "type": { + "in": [] + } + }, + "after": null, + "before": null, + "first": null, + "last": null + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru b/postman/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru new file mode 100644 index 0000000000..78dc6512e7 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru @@ -0,0 +1,32 @@ +meta { + name: Post Liquidity Withdrawal + type: graphql + seq: 16 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation PostLiquidityWithdrawal($input: PostLiquidityWithdrawalInput!) { + postLiquidityWithdrawal(input: $input) { + code + error + message + success + } + } +} + +body:graphql:vars { + { + "input": { + "withdrawalId": "421fae87-9a59-4217-9ff8-faf55ffab9c6", + "idempotencyKey":"{{$guid}}" + } + } + +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Revoke Wallet Address Key.bru b/postman/collections/Interledger/Rafiki Admin APIs/Revoke Wallet Address Key.bru new file mode 100644 index 0000000000..ae98271fd2 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Revoke Wallet Address Key.bru @@ -0,0 +1,35 @@ +meta { + name: Revoke Wallet Address Key + type: graphql + seq: 23 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation RevokeWalletAddressKey ($input: RevokeWalletAddressKeyInput!) { + revokeWalletAddressKey (input: $input) { + code + message + success + walletAddressKey { + id + revoked + walletAddressId + createdAt + } + } + } +} + +body:graphql:vars { + { + "input": { + "id": "{{walletAddressKeyId}}" + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Set Fee.bru b/postman/collections/Interledger/Rafiki Admin APIs/Set Fee.bru new file mode 100644 index 0000000000..71d7c7995e --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Set Fee.bru @@ -0,0 +1,46 @@ +meta { + name: Set Fee + type: graphql + seq: 7 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation SetFee($input: SetFeeInput!) { + setFee(input: $input) { + code + success + message + fee { + id + assetId + type + fixed + basisPoints + createdAt + } + } + } +} + +body:graphql:vars { + { + "input": { + "assetId": "{{assetId}}", + "type": "SENDING", + "fee": { + "fixed": 100, + "basisPoints": 100 + } + } + } +} + +tests { + // +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Trigger Wallet Address Events.bru b/postman/collections/Interledger/Rafiki Admin APIs/Trigger Wallet Address Events.bru new file mode 100644 index 0000000000..24502ab45b --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Trigger Wallet Address Events.bru @@ -0,0 +1,30 @@ +meta { + name: Trigger Wallet Address Events + type: graphql + seq: 39 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation TriggerWalletAddressEvents($input: TriggerWalletAddressEventsInput!) { + triggerWalletAddressEvents(input: $input) { + code + count + message + success + } + } +} + +body:graphql:vars { + { + "input": { + "limit": 5 + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Update Asset.bru b/postman/collections/Interledger/Rafiki Admin APIs/Update Asset.bru new file mode 100644 index 0000000000..c94d27f4b4 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Update Asset.bru @@ -0,0 +1,43 @@ +meta { + name: Update Asset + type: graphql + seq: 2 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation UpdateAsset($input: UpdateAssetInput!) { + updateAsset(input: $input) { + asset { + code + createdAt + id + scale + withdrawalThreshold + liquidityThreshold + } + code + message + success + } + } +} + +body:graphql:vars { + { + "input": { + "id": "{{assetId}}", + "withdrawalThreshold": 100, + "liquidityThreshold": 100 + } + } +} + +tests { + // +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Update Peer.bru b/postman/collections/Interledger/Rafiki Admin APIs/Update Peer.bru new file mode 100644 index 0000000000..597e814c6a --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Update Peer.bru @@ -0,0 +1,48 @@ +meta { + name: Update Peer + type: graphql + seq: 10 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation UpdatePeer ($input: UpdatePeerInput!){ + updatePeer(input: $input) { + code + success + message + peer { + id + name + http { + outgoing { + authToken + endpoint + } + } + liquidity + liquidityThreshold + } + } + } +} + +body:graphql:vars { + { + "input": { + "id": "{{peerId}}", + "name": "Wall-y", + "http": { + "incoming": {"authTokens": ["test-123"]}, + "outgoing": {"endpoint": "http://peer-backend:3002", "authToken": "test"} + }, + "maxPacketAmount": 1000, + "liquidityThreshold": 100 + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Update Wallet Address.bru b/postman/collections/Interledger/Rafiki Admin APIs/Update Wallet Address.bru new file mode 100644 index 0000000000..bfc0acadae --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Update Wallet Address.bru @@ -0,0 +1,45 @@ +meta { + name: Update Wallet Address + type: graphql + seq: 19 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation UpdateWalletAddress($input: UpdateWalletAddressInput!) { + updateWalletAddress(input: $input) { + code + message + walletAddress { + id + asset { + id + code + scale + withdrawalThreshold + createdAt + } + url + publicName + createdAt + status + } + success + } + } +} + +body:graphql:vars { + { + "input": { + "id": "{{walletAddressId}}", + "publicName": "New Name", + "status": "ACTIVE" + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru b/postman/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru new file mode 100644 index 0000000000..b37f8fc154 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru @@ -0,0 +1,32 @@ +meta { + name: Void Liquidity Withdrawal + type: graphql + seq: 17 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation VoidLiquidityWithdrawal($input: VoidLiquidityWithdrawalInput!) { + voidLiquidityWithdrawal(input: $input) { + code + error + message + success + } + } +} + +body:graphql:vars { + { + "input": { + "withdrawalId": "421fae87-9a59-4217-9ff8-faf55ffab9c6", + "idempotencyKey":"{{$guid}}" + } + } + +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru new file mode 100644 index 0000000000..2fd124377c --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru @@ -0,0 +1,34 @@ +meta { + name: Withdraw Asset Liquidity + type: graphql + seq: 6 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreateAssetLiquidityWithdrawal ($input: CreateAssetLiquidityWithdrawalInput!) { + createAssetLiquidityWithdrawal(input: $input) { + code + success + message + error + } + } +} + +body:graphql:vars { + { + "input": { + "id": "b97fd85a-126e-42ef-b40d-1a50a70ffa6f", + "assetId": "{{assetId}}", + "amount": "100", + "idempotencyKey":"{{$guid}}" + } + } + +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru new file mode 100644 index 0000000000..ab2a5f537b --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru @@ -0,0 +1,31 @@ +meta { + name: Withdraw Event Liquidity + type: graphql + seq: 37 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation WithdrawEventLiquidity($input: WithdrawEventLiquidityInput!) { + withdrawEventLiquidity(input: $input) { + code + error + message + success + } + } +} + +body:graphql:vars { + { + "input": { + "eventId": "b4f85d5c-652d-472d-873c-4ba2a5e39052", + "idempotencyKey":"{{$guid}}" + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru new file mode 100644 index 0000000000..17dd806a8b --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru @@ -0,0 +1,31 @@ +meta { + name: Withdraw Incoming Payment Liquidity + type: graphql + seq: 26 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation WithdrawIncomingPaymentLiquidity($input: WithdrawIncomingPaymentLiquidityInput!) { + withdrawIncomingPaymentLiquidity(input: $input) { + code + error + message + success + } + } +} + +body:graphql:vars { + { + "input": { + "incomingPaymentId": "{{incomingPaymentId}}", + "idempotencyKey":"{{$guid}}" + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru new file mode 100644 index 0000000000..b80c5a16c9 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru @@ -0,0 +1,31 @@ +meta { + name: Withdraw Outgoing Payment Liquidity + type: graphql + seq: 36 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation WithdrawOutgoingPaymentLiquidity($input: WithdrawOutgoingPaymentLiquidityInput!) { + withdrawOutgoingPaymentLiquidity(input: $input) { + code + error + message + success + } + } +} + +body:graphql:vars { + { + "input": { + "outgoingPaymentId": "{{outgoingPaymentId}}", + "idempotencyKey":"{{$guid}}" + } + } +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru new file mode 100644 index 0000000000..d7eefff238 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru @@ -0,0 +1,34 @@ +meta { + name: Withdraw Peer Liquidity + type: graphql + seq: 15 +} + +post { + url: {{RafikiGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation CreatePeerLiquidityWithdrawal ($input: CreatePeerLiquidityWithdrawalInput!) { + createPeerLiquidityWithdrawal(input: $input) { + code + success + message + error + } + } +} + +body:graphql:vars { + { + "input": { + "id": "421fae87-9a59-4217-9ff8-faf55ffab9c6", + "peerId": "{{peerId}}", + "amount": "100", + "idempotencyKey":"{{$guid}}" + } + } + +} diff --git a/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru b/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru new file mode 100644 index 0000000000..86d6312055 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru @@ -0,0 +1,49 @@ +meta { + name: Get Grant + type: graphql + seq: 1 +} + +post { + url: {{RafikiAuthGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query Grant($id: ID!) { + grant(id: $id) { + id + state + createdAt + client + access { + type + actions + createdAt + id + identifier + limits { + interval + receiveAmount { + assetCode + assetScale + value + } + receiver + debitAmount { + assetCode + assetScale + value + } + } + } + } + } +} + +body:graphql:vars { + { + "id": "056b3f93-7890-4005-9b24-2623d9cedab5" + } +} diff --git a/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grants.bru b/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grants.bru new file mode 100644 index 0000000000..91b6c97d55 --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grants.bru @@ -0,0 +1,73 @@ +meta { + name: Get Grants + type: graphql + seq: 2 +} + +post { + url: {{RafikiAuthGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + query Grants($after: String, $before: String, $first: Int, $last: Int, $filter: GrantFilter) { + grants(after: $after, before: $before, first: $first, last: $last, filter: $filter) { + edges { + cursor + node { + access { + createdAt + id + identifier + limits { + interval + receiveAmount { + assetScale + value + assetCode + } + receiver + debitAmount { + assetCode + assetScale + value + } + } + actions + type + } + client + createdAt + id + state + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } + +} + +body:graphql:vars { + { + "after": null, + "before": null, + "first": null, + "last": null, + "filter": { + "state": { + "in": ["PROCESSING", "PENDING", "APPROVED", "FINALIZED"] + }, + "finalizationReason": { + "notIn": ["REVOKED"] + } + } + } + +} diff --git a/postman/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru b/postman/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru new file mode 100644 index 0000000000..a06bbc4adf --- /dev/null +++ b/postman/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru @@ -0,0 +1,29 @@ +meta { + name: Revoke Grant + type: graphql + seq: 3 +} + +post { + url: {{RafikiAuthGraphqlHost}}/graphql + body: graphql + auth: none +} + +body:graphql { + mutation revokeGrant($input: RevokeGrantInput!) { + revokeGrant(input: $input) { + code + message + success + } + } +} + +body:graphql:vars { + { + "input": { + "grantId": "e6684d05-6cc5-4a0e-a490-7ed05923fa89" + } + } +} diff --git a/postman/collections/Interledger/bruno.json b/postman/collections/Interledger/bruno.json new file mode 100644 index 0000000000..32f0580340 --- /dev/null +++ b/postman/collections/Interledger/bruno.json @@ -0,0 +1,9 @@ +{ + "version": "1", + "name": "Interledger", + "type": "collection", + "ignore": [ + "node_modules", + ".git" + ] +} \ No newline at end of file diff --git a/postman/collections/Interledger/environments/Local Playground Environment.bru b/postman/collections/Interledger/environments/Local Playground Environment.bru new file mode 100644 index 0000000000..6e655ba7c8 --- /dev/null +++ b/postman/collections/Interledger/environments/Local Playground Environment.bru @@ -0,0 +1,119 @@ +vars { + host3000: cloud-nine-wallet-backend + host4000: happy-life-bank-backend + clientWalletAddress: http://localhost:4000/accounts/pfry + clientKeyId: keyid-97a3a431-8ee1-48fc-ac85-70e2f5eba8e5 + senderWalletAddress: http://localhost:3000/accounts/gfranklin + receiverWalletAddress: http://localhost:4000/accounts/asmith + RafikiGraphqlHost: http://localhost:3001 + RafikiAuthGraphqlHost: http://localhost:3003 + PeerGraphqlHost: http://localhost:4001 + PeerAuthGraphqlHost: http://localhost:4003 + preRequestHost: const url = require('url') + +const requestUrl = url.parse(request.url + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key))) + +if(requestUrl.hostname === 'localhost'){ + const hostHeader = requestUrl.port === '3000' + ? pm.environment.get('host3000') + : pm.environment.get('host4000') + pm.request.headers.add({ + key: 'Host', + value: hostHeader + }) + request.headers['host'] = hostHeader +} + preRequestSignatures: let requestUrl = request.url + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) + .replace(/localhost:([3,4])000/g, (_, key) => + key === '3' + ? pm.environment.get('host3000') + : pm.environment.get('host4000') + ) + +const requestBody = + request.method === 'POST' && Object.keys(request.data).length !== 0 + ? request.data + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) + .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => + key === '3' + ? 'https://' + pm.environment.get('host3000') + : 'https://' + pm.environment.get('host4000') + ) + : undefined +pm.request.body.raw = requestBody + +const requestHeaders = JSON.parse( + JSON.stringify(request.headers).replace(/{{([A-Za-z]\w+)}}/g, (_, key) => + pm.environment.get(key) + ) +) + +// Request Signature Headers +pm.sendRequest( + { + url: pm.environment.get('signatureUrl'), + method: 'POST', + header: { + 'content-type': 'application/json' + }, + body: { + mode: 'raw', + raw: JSON.stringify({ + keyId: pm.environment.get('clientKeyId'), + base64Key: pm.environment.get('clientPrivateKey'), + request: { + url: requestUrl, + method: request.method, + headers: requestHeaders, + body: requestBody + } + }) + } + }, + (_, res) => { + const headers = res.json() + for (let [key, value] of Object.entries(headers)) { + pm.request.headers.add({ key, value }) + } + } +) + + signatureUrl: https://kxu5d4mr4blcthphxomjlc4xk40rvdsx.lambda-url.eu-central-1.on.aws/ + accessToken: + continueToken: + continueId: + tomorrow: + incomingPaymentId: + quoteId: + quoteDebitAmountValue: + quoteReceiveAmountValue: + outgoingPaymentId: + receiverId: + senderOpenPaymentsHost: + senderAssetCode: + senderAssetScale: + senderOpenPaymentsAuthHost: + receiverOpenPaymentsHost: + receiverAssetCode: + receiverAssetScale: + receiverOpenPaymentsAuthHost: + quoteDebitAmount: + quoteReceiveAmount: + gfranklinWalletAddressId: + receiverHost: http://localhost:4000 + senderHost: http://localhost:3000 + assetId: + peerId: + walletAddressId: + walletAddressUrl: + createWalletAddressRequest: + walletAddressKeyId: + uniqueWalletAddress: + secondWalletAddressId: + tokenId: +} +vars:secret [ + clientPrivateKey +] diff --git a/postman/collections/Interledger/environments/Local Playground.bru b/postman/collections/Interledger/environments/Local Playground.bru new file mode 100644 index 0000000000..de66a7a4b7 --- /dev/null +++ b/postman/collections/Interledger/environments/Local Playground.bru @@ -0,0 +1,82 @@ +vars { + host3000: cloud-nine-wallet-backend + host4000: happy-life-bank-backend + clientWalletAddress: http://localhost:4000/accounts/pfry + clientKeyId: keyid-97a3a431-8ee1-48fc-ac85-70e2f5eba8e5 + senderWalletAddress: http://localhost:3000/accounts/gfranklin + receiverWalletAddress: http://localhost:4000/accounts/asmith + RafikiGraphqlHost: http://localhost:3001 + RafikiAuthGraphqlHost: http://localhost:3003 + PeerGraphqlHost: http://localhost:4001 + PeerAuthGraphqlHost: http://localhost:4003 + preRequestHost: const url = require('url') +const requestUrl = url.parse(request.url + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key))) +if(requestUrl.hostname === 'localhost'){ + const hostHeader = requestUrl.port === '3000' + ? pm.environment.get('host3000') + : pm.environment.get('host4000') + pm.request.headers.add({ + key: 'Host', + value: hostHeader + }) + request.headers['host'] = hostHeader +} + preRequestSignatures: let requestUrl = request.url + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) + .replace(/localhost:([3,4])000/g, (_, key) => + key === '3' + ? pm.environment.get('host3000') + : pm.environment.get('host4000') + ) +const requestBody = + request.method === 'POST' && Object.keys(request.data).length !== 0 + ? request.data + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) + .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => + key === '3' + ? 'https://' + pm.environment.get('host3000') + : 'https://' + pm.environment.get('host4000') + ) + : undefined +pm.request.body.raw = requestBody +const requestHeaders = JSON.parse( + JSON.stringify(request.headers).replace(/{{([A-Za-z]\w+)}}/g, (_, key) => + pm.environment.get(key) + ) +) +// Request Signature Headers +pm.sendRequest( + { + url: pm.environment.get('signatureUrl'), + method: 'POST', + header: { + 'content-type': 'application/json' + }, + body: { + mode: 'raw', + raw: JSON.stringify({ + keyId: pm.environment.get('clientKeyId'), + base64Key: pm.environment.get('clientPrivateKey'), + request: { + url: requestUrl, + method: request.method, + headers: requestHeaders, + body: requestBody + } + }) + } + }, + (_, res) => { + const headers = res.json() + for (let [key, value] of Object.entries(headers)) { + pm.request.headers.add({ key, value }) + } + } +) + + signatureUrl: https://kxu5d4mr4blcthphxomjlc4xk40rvdsx.lambda-url.eu-central-1.on.aws/ +} +vars:secret [ + clientPrivateKey +] diff --git a/postman/collections/Interledger/environments/Remote Environment.bru b/postman/collections/Interledger/environments/Remote Environment.bru new file mode 100644 index 0000000000..b23bc59b03 --- /dev/null +++ b/postman/collections/Interledger/environments/Remote Environment.bru @@ -0,0 +1,84 @@ +vars { + clientWalletAddress: https://ilp.rafiki.money/d99f0eee + clientKeyId: e9a47ee7-99b3-4656-b85f-12431dbc16b9 + senderWalletAddress: https://ilp.rafiki.money/d99f0eee + receiverWalletAddress: https://ilp.rafiki.money/f1475476 + signatureUrl: https://kxu5d4mr4blcthphxomjlc4xk40rvdsx.lambda-url.eu-central-1.on.aws/ + preRequestSignatures: let requestUrl = request.url + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) + .replace(/localhost:([3,4])000/g, (_, key) => + key === '3' + ? pm.environment.get('host3000') + : pm.environment.get('host4000') + ) + +const requestBody = + request.method === 'POST' && Object.keys(request.data).length !== 0 + ? request.data + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) + .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => + key === '3' + ? 'https://' + pm.environment.get('host3000') + : 'https://' + pm.environment.get('host4000') + ) + : undefined +pm.request.body.raw = requestBody + +const requestHeaders = JSON.parse( + JSON.stringify(request.headers).replace(/{{([A-Za-z]\w+)}}/g, (_, key) => + pm.environment.get(key) + ) +) + +// Request Signature Headers +pm.sendRequest( + { + url: pm.environment.get('signatureUrl'), + method: 'POST', + header: { + 'content-type': 'application/json' + }, + body: { + mode: 'raw', + raw: JSON.stringify({ + keyId: pm.environment.get('clientKeyId'), + base64Key: pm.environment.get('clientPrivateKey'), + request: { + url: requestUrl, + method: request.method, + headers: requestHeaders, + body: requestBody + } + }) + } + }, + (_, res) => { + const headers = res.json() + for (let [key, value] of Object.entries(headers)) { + pm.request.headers.add({ key, value }) + } + } +) + + senderOpenPaymentsHost: + senderOpenPaymentsAuthHost: + senderAssetCode: + senderAssetScale: + receiverOpenPaymentsHost: + receiverOpenPaymentsAuthHost: + receiverAssetCode: + receiverAssetScale: + accessToken: + continueToken: + continueId: + tomorrow: + incomingPaymentId: + quoteId: + quoteDebitAmount: + quoteReceiveAmount: + outgoingPaymentId: + tokenId: +} +vars:secret [ + clientPrivateKey +] From ff0c791e5fcd7064f2dc644171b020976fbcfcef Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Fri, 16 Feb 2024 12:51:13 +0100 Subject: [PATCH 02/16] chore: fix OP example --- .../Open Payments/Continuation Request.bru | 18 ++- .../Open Payments/Create Incoming Payment.bru | 30 ++--- .../Open Payments/Create Outgoing Payment.bru | 25 ++-- .../Examples/Open Payments/Create Quote.bru | 29 +++-- .../Open Payments/Get Outgoing Payment.bru | 16 +-- .../Get receiver wallet address.bru | 59 ++++----- .../Get sender wallet address.bru | 19 +-- .../Grant Request Incoming Payment.bru | 19 +-- .../Grant Request Outgoing Payment.bru | 18 ++- .../Open Payments/Grant Request Quote.bru | 18 ++- .../Local Playground Environment.bru | 119 ------------------ .../environments/Local Playground.bru | 66 ---------- .../environments/Remote Environment.bru | 84 ------------- .../Interledger/scripts/scripts.js | 94 ++++++++++++++ 14 files changed, 224 insertions(+), 390 deletions(-) delete mode 100644 postman/collections/Interledger/environments/Local Playground Environment.bru delete mode 100644 postman/collections/Interledger/environments/Remote Environment.bru create mode 100644 postman/collections/Interledger/scripts/scripts.js diff --git a/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru b/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru index db658fb686..a731d771d0 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru @@ -16,16 +16,24 @@ headers { body:json { { - "interact_ref": "6d519566-234f-4c2e-b56f-6d4a305fc067" + "interact_ref": "8c55602c-f777-44cf-bbe7-f4f6589d6aeb" } } script:pre-request { - // eval(pm.environment.get('preRequestSignatures')) + const scripts = require('./scripts/scripts'); + + await scripts.addSignatureHeaders(); +} + +script:post-response { + const body = res.getBody(); + bru.setEnvVar("accessToken", body.access_token.value); + bru.setEnvVar("tokenId", body.access_token.manage.split('/').pop()) } tests { - // const body = pm.response.json(); - // pm.environment.set("accessToken", body.access_token.value); - // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); } diff --git a/postman/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru b/postman/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru index 80c449997f..03637714cd 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru @@ -30,21 +30,23 @@ body:json { } script:pre-request { - // pm.environment.set("tomorrow", (new Date(new Date().setDate(new Date().getDate() + 1))).toISOString()); - // - // if(pm.environment.get('preRequestHost')){ - // eval(pm.environment.get('preRequestHost')) - // } - // eval(pm.environment.get('preRequestSignatures')) - // + const scripts = require('./scripts/scripts'); + + bru.setEnvVar("tomorrow", (new Date(new Date().setDate(new Date().getDate() + 1))).toISOString()); + + scripts.addHostHeader(); + + await scripts.addSignatureHeaders(); +} + +script:post-response { + const body = res.getBody(); + bru.setEnvVar("incomingPaymentId", body.id.split("/").pop()); + } tests { - // pm.test("Status code is 201", function () { - // pm.response.to.have.status(201); - // }); - // - // const body = pm.response.json(); - // pm.environment.set("incomingPaymentId", body.id.split("/").pop()); - // + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); } diff --git a/postman/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru b/postman/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru index d4ecce7463..ccef663dc9 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru @@ -25,18 +25,21 @@ body:json { } script:pre-request { - // if(pm.environment.get('preRequestHost')){ - // eval(pm.environment.get('preRequestHost')) - // } - // eval(pm.environment.get('preRequestSignatures')) + const scripts = require('./scripts/scripts'); + + scripts.addHostHeader(); + + await scripts.addSignatureHeaders(); +} + +script:post-response { + const body = res.getBody(); + bru.setEnvVar("outgoingPaymentId", body.id.split("/").pop()); + } tests { - // pm.test("Status code is 201", function () { - // pm.response.to.have.status(201); - // }); - // - // const body = pm.response.json(); - // pm.environment.set("outgoingPaymentId", body.id.split("/").pop()); - // + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); } diff --git a/postman/collections/Interledger/Examples/Open Payments/Create Quote.bru b/postman/collections/Interledger/Examples/Open Payments/Create Quote.bru index b60ff08684..2c4728bf5d 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Create Quote.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Create Quote.bru @@ -23,20 +23,23 @@ body:json { } script:pre-request { - // if(pm.environment.get('preRequestHost')){ - // eval(pm.environment.get('preRequestHost')) - // } - // eval(pm.environment.get('preRequestSignatures')) + const scripts = require('./scripts/scripts'); + + scripts.addHostHeader(); + + await scripts.addSignatureHeaders(); +} + +script:post-response { + const body = res.getBody(); + bru.setEnvVar("quoteId", body.id.split("/").pop()); + bru.setEnvVar("quoteDebitAmount", JSON.stringify(body.debitAmount)) + bru.setEnvVar("quoteReceiveAmount", JSON.stringify(body.receiveAmount)) + } tests { - // pm.test("Status code is 201", function () { - // pm.response.to.have.status(201); - // }); - // - // const body = pm.response.json(); - // pm.environment.set("quoteId", body.id.split("/").pop()); - // pm.environment.set("quoteDebitAmount", JSON.stringify(body.debitAmount)) - // pm.environment.set("quoteReceiveAmount", JSON.stringify(body.receiveAmount)) - // + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); } diff --git a/postman/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru b/postman/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru index 8ee961f93a..660afdbbbe 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru @@ -15,15 +15,15 @@ headers { } script:pre-request { - // if(pm.environment.get('preRequestHost')){ - // eval(pm.environment.get('preRequestHost')) - // } - // eval(pm.environment.get('preRequestSignatures')) + const scripts = require('./scripts/scripts'); + + scripts.addHostHeader(); + + await scripts.addSignatureHeaders(); } tests { - // pm.test("Status code is 200", function () { - // pm.response.to.have.status(200); - // }); - // + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); } diff --git a/postman/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru b/postman/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru index c949584080..7c7c8a588f 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru @@ -15,41 +15,32 @@ headers { } script:pre-request { - // const url = require('url') - // - // const requestUrl = url.parse(request.url - // .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key))) - // - // pm.environment.set("receiverOpenPaymentsHost", requestUrl.protocol + '//' + requestUrl.host); - // - // if(pm.environment.get('preRequestHost')){ - // eval(pm.environment.get('preRequestHost')) - // } + const scripts = require('./scripts/scripts'); + + scripts.addHostHeader("receiverOpenPaymentsHost"); +} + +script:post-response { + const url = require('url') + + const body = res.body + bru.setEnvVar("receiverAssetCode", body?.assetCode) + bru.setEnvVar("receiverAssetScale", body?.assetScale) + + const authUrl = url.parse(body?.authServer) + if ( + authUrl.hostname.includes('cloud-nine-wallet') || + authUrl.hostname.includes('happy-life-bank') + ){ + const port = authUrl.hostname.includes('cloud-nine-wallet')? authUrl.port: Number(authUrl.port) + 1000 + bru.setEnvVar("receiverOpenPaymentsAuthHost", authUrl.protocol + '//localhost:' + port ); + } else { + bru.setEnvVar("receiverOpenPaymentsAuthHost", body?.authServer); + } } tests { - // const url = require('url') - // - // pm.test("Status code is 200", function () { - // pm.response.to.have.status(200); - // }); - // - // const body = pm.response.json(); - // pm.environment.set("receiverAssetCode", body?.assetCode) - // pm.environment.set("receiverAssetScale", body?.assetScale) - // - // const authUrl = url.parse(body?.authServer) - // if ( - // authUrl.hostname.includes('cloud-nine-wallet') || - // authUrl.hostname.includes('happy-life-bank') - // ){ - // const port = authUrl.hostname.includes('cloud-nine-wallet') - // ? authUrl.port - // : Number(authUrl.port) + 1000 - // pm.environment.set("receiverOpenPaymentsAuthHost", authUrl.protocol + '//localhost:' + port ); - // } else { - // pm.environment.set("receiverOpenPaymentsAuthHost", body?.authServer); - // } - // - // + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); } diff --git a/postman/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru b/postman/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru index 3ceed25f2e..d088d2cf7c 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru @@ -15,21 +15,9 @@ headers { } script:pre-request { - const url = require('url') - - const requestUrl = url.parse(req.url - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key))) - - bru.setEnvVar("senderOpenPaymentsHost", requestUrl.protocol + '//' + requestUrl.host); - - // if(bru.getEnvVar('preRequestHost')){ - // eval(bru.getEnvVar('preRequestHost')) - // } + const scripts = require('./scripts/scripts'); - if(requestUrl.hostname === 'localhost'){ - const hostHeader = requestUrl.port === '3000'? bru.getEnvVar('host3000'): bru.getEnvVar('host4000') - req.headers.host = hostHeader - } + scripts.addHostHeader("senderOpenPaymentsHost"); } script:post-response { @@ -49,9 +37,6 @@ script:post-response { } else { bru.setEnvVar("senderOpenPaymentsAuthHost", body?.authServer); } - - - } tests { diff --git a/postman/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru b/postman/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru index 959e094619..692ab6886f 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru @@ -27,14 +27,19 @@ body:json { } script:pre-request { - // eval(pm.environment.get('preRequestSignatures')) - // + const scripts = require('./scripts/scripts'); + + await scripts.addSignatureHeaders(); +} + +script:post-response { + const scripts = require('./scripts/scripts'); + + scripts.storeTokenDetails(); } tests { - // const body = pm.response.json(); - // pm.environment.set("accessToken", body?.access_token?.value); - // pm.environment.set("continueToken", body.continue.access_token.value); - // pm.environment.set("continueId", body.continue.uri.split("/").pop()); - // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); } diff --git a/postman/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru b/postman/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru index d19a7cc98b..667e430252 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru @@ -43,13 +43,19 @@ body:json { } script:pre-request { - // eval(pm.environment.get('preRequestSignatures')) + const scripts = require('./scripts/scripts'); + + await scripts.addSignatureHeaders(); +} + +script:post-response { + const scripts = require('./scripts/scripts'); + + scripts.storeTokenDetails(); } tests { - // const body = pm.response.json(); - // pm.environment.set("accessToken", body?.access_token?.value); - // pm.environment.set("continueToken", body.continue.access_token.value); - // pm.environment.set("continueId", body.continue.uri.split("/").pop()); - // + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); } diff --git a/postman/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru b/postman/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru index 21c058d403..8b0033d63d 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru @@ -28,13 +28,19 @@ body:json { } script:pre-request { - // eval(pm.environment.get('preRequestSignatures')) + const scripts = require('./scripts/scripts'); + + await scripts.addSignatureHeaders(); +} + +script:post-response { + const scripts = require('./scripts/scripts'); + + scripts.storeTokenDetails(); } tests { - // const body = pm.response.json(); - // pm.environment.set("accessToken", body?.access_token?.value); - // pm.environment.set("continueToken", body.continue.access_token.value); - // pm.environment.set("continueId", body.continue.uri.split("/").pop()); - // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); } diff --git a/postman/collections/Interledger/environments/Local Playground Environment.bru b/postman/collections/Interledger/environments/Local Playground Environment.bru deleted file mode 100644 index 6e655ba7c8..0000000000 --- a/postman/collections/Interledger/environments/Local Playground Environment.bru +++ /dev/null @@ -1,119 +0,0 @@ -vars { - host3000: cloud-nine-wallet-backend - host4000: happy-life-bank-backend - clientWalletAddress: http://localhost:4000/accounts/pfry - clientKeyId: keyid-97a3a431-8ee1-48fc-ac85-70e2f5eba8e5 - senderWalletAddress: http://localhost:3000/accounts/gfranklin - receiverWalletAddress: http://localhost:4000/accounts/asmith - RafikiGraphqlHost: http://localhost:3001 - RafikiAuthGraphqlHost: http://localhost:3003 - PeerGraphqlHost: http://localhost:4001 - PeerAuthGraphqlHost: http://localhost:4003 - preRequestHost: const url = require('url') - -const requestUrl = url.parse(request.url - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key))) - -if(requestUrl.hostname === 'localhost'){ - const hostHeader = requestUrl.port === '3000' - ? pm.environment.get('host3000') - : pm.environment.get('host4000') - pm.request.headers.add({ - key: 'Host', - value: hostHeader - }) - request.headers['host'] = hostHeader -} - preRequestSignatures: let requestUrl = request.url - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) - .replace(/localhost:([3,4])000/g, (_, key) => - key === '3' - ? pm.environment.get('host3000') - : pm.environment.get('host4000') - ) - -const requestBody = - request.method === 'POST' && Object.keys(request.data).length !== 0 - ? request.data - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) - .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => - key === '3' - ? 'https://' + pm.environment.get('host3000') - : 'https://' + pm.environment.get('host4000') - ) - : undefined -pm.request.body.raw = requestBody - -const requestHeaders = JSON.parse( - JSON.stringify(request.headers).replace(/{{([A-Za-z]\w+)}}/g, (_, key) => - pm.environment.get(key) - ) -) - -// Request Signature Headers -pm.sendRequest( - { - url: pm.environment.get('signatureUrl'), - method: 'POST', - header: { - 'content-type': 'application/json' - }, - body: { - mode: 'raw', - raw: JSON.stringify({ - keyId: pm.environment.get('clientKeyId'), - base64Key: pm.environment.get('clientPrivateKey'), - request: { - url: requestUrl, - method: request.method, - headers: requestHeaders, - body: requestBody - } - }) - } - }, - (_, res) => { - const headers = res.json() - for (let [key, value] of Object.entries(headers)) { - pm.request.headers.add({ key, value }) - } - } -) - - signatureUrl: https://kxu5d4mr4blcthphxomjlc4xk40rvdsx.lambda-url.eu-central-1.on.aws/ - accessToken: - continueToken: - continueId: - tomorrow: - incomingPaymentId: - quoteId: - quoteDebitAmountValue: - quoteReceiveAmountValue: - outgoingPaymentId: - receiverId: - senderOpenPaymentsHost: - senderAssetCode: - senderAssetScale: - senderOpenPaymentsAuthHost: - receiverOpenPaymentsHost: - receiverAssetCode: - receiverAssetScale: - receiverOpenPaymentsAuthHost: - quoteDebitAmount: - quoteReceiveAmount: - gfranklinWalletAddressId: - receiverHost: http://localhost:4000 - senderHost: http://localhost:3000 - assetId: - peerId: - walletAddressId: - walletAddressUrl: - createWalletAddressRequest: - walletAddressKeyId: - uniqueWalletAddress: - secondWalletAddressId: - tokenId: -} -vars:secret [ - clientPrivateKey -] diff --git a/postman/collections/Interledger/environments/Local Playground.bru b/postman/collections/Interledger/environments/Local Playground.bru index de66a7a4b7..65dcc28169 100644 --- a/postman/collections/Interledger/environments/Local Playground.bru +++ b/postman/collections/Interledger/environments/Local Playground.bru @@ -9,72 +9,6 @@ vars { RafikiAuthGraphqlHost: http://localhost:3003 PeerGraphqlHost: http://localhost:4001 PeerAuthGraphqlHost: http://localhost:4003 - preRequestHost: const url = require('url') -const requestUrl = url.parse(request.url - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key))) -if(requestUrl.hostname === 'localhost'){ - const hostHeader = requestUrl.port === '3000' - ? pm.environment.get('host3000') - : pm.environment.get('host4000') - pm.request.headers.add({ - key: 'Host', - value: hostHeader - }) - request.headers['host'] = hostHeader -} - preRequestSignatures: let requestUrl = request.url - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) - .replace(/localhost:([3,4])000/g, (_, key) => - key === '3' - ? pm.environment.get('host3000') - : pm.environment.get('host4000') - ) -const requestBody = - request.method === 'POST' && Object.keys(request.data).length !== 0 - ? request.data - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) - .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => - key === '3' - ? 'https://' + pm.environment.get('host3000') - : 'https://' + pm.environment.get('host4000') - ) - : undefined -pm.request.body.raw = requestBody -const requestHeaders = JSON.parse( - JSON.stringify(request.headers).replace(/{{([A-Za-z]\w+)}}/g, (_, key) => - pm.environment.get(key) - ) -) -// Request Signature Headers -pm.sendRequest( - { - url: pm.environment.get('signatureUrl'), - method: 'POST', - header: { - 'content-type': 'application/json' - }, - body: { - mode: 'raw', - raw: JSON.stringify({ - keyId: pm.environment.get('clientKeyId'), - base64Key: pm.environment.get('clientPrivateKey'), - request: { - url: requestUrl, - method: request.method, - headers: requestHeaders, - body: requestBody - } - }) - } - }, - (_, res) => { - const headers = res.json() - for (let [key, value] of Object.entries(headers)) { - pm.request.headers.add({ key, value }) - } - } -) - signatureUrl: https://kxu5d4mr4blcthphxomjlc4xk40rvdsx.lambda-url.eu-central-1.on.aws/ } vars:secret [ diff --git a/postman/collections/Interledger/environments/Remote Environment.bru b/postman/collections/Interledger/environments/Remote Environment.bru deleted file mode 100644 index b23bc59b03..0000000000 --- a/postman/collections/Interledger/environments/Remote Environment.bru +++ /dev/null @@ -1,84 +0,0 @@ -vars { - clientWalletAddress: https://ilp.rafiki.money/d99f0eee - clientKeyId: e9a47ee7-99b3-4656-b85f-12431dbc16b9 - senderWalletAddress: https://ilp.rafiki.money/d99f0eee - receiverWalletAddress: https://ilp.rafiki.money/f1475476 - signatureUrl: https://kxu5d4mr4blcthphxomjlc4xk40rvdsx.lambda-url.eu-central-1.on.aws/ - preRequestSignatures: let requestUrl = request.url - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) - .replace(/localhost:([3,4])000/g, (_, key) => - key === '3' - ? pm.environment.get('host3000') - : pm.environment.get('host4000') - ) - -const requestBody = - request.method === 'POST' && Object.keys(request.data).length !== 0 - ? request.data - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) - .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => - key === '3' - ? 'https://' + pm.environment.get('host3000') - : 'https://' + pm.environment.get('host4000') - ) - : undefined -pm.request.body.raw = requestBody - -const requestHeaders = JSON.parse( - JSON.stringify(request.headers).replace(/{{([A-Za-z]\w+)}}/g, (_, key) => - pm.environment.get(key) - ) -) - -// Request Signature Headers -pm.sendRequest( - { - url: pm.environment.get('signatureUrl'), - method: 'POST', - header: { - 'content-type': 'application/json' - }, - body: { - mode: 'raw', - raw: JSON.stringify({ - keyId: pm.environment.get('clientKeyId'), - base64Key: pm.environment.get('clientPrivateKey'), - request: { - url: requestUrl, - method: request.method, - headers: requestHeaders, - body: requestBody - } - }) - } - }, - (_, res) => { - const headers = res.json() - for (let [key, value] of Object.entries(headers)) { - pm.request.headers.add({ key, value }) - } - } -) - - senderOpenPaymentsHost: - senderOpenPaymentsAuthHost: - senderAssetCode: - senderAssetScale: - receiverOpenPaymentsHost: - receiverOpenPaymentsAuthHost: - receiverAssetCode: - receiverAssetScale: - accessToken: - continueToken: - continueId: - tomorrow: - incomingPaymentId: - quoteId: - quoteDebitAmount: - quoteReceiveAmount: - outgoingPaymentId: - tokenId: -} -vars:secret [ - clientPrivateKey -] diff --git a/postman/collections/Interledger/scripts/scripts.js b/postman/collections/Interledger/scripts/scripts.js new file mode 100644 index 0000000000..cffbbb5998 --- /dev/null +++ b/postman/collections/Interledger/scripts/scripts.js @@ -0,0 +1,94 @@ +const fetch = require('node-fetch') +const url = require('url') + +const scripts = { + + sanitizeUrl: function() { + return req.getUrl() + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key)) + .replace(/localhost:([3,4])000/g, (_, key) => + key === '3' ? bru.getEnvVar('host3000') : bru.getEnvVar('host4000') + ) + }, + + sanitizeBody: function() { + let requestBody = req.getBody() + if (!(req.getMethod() === 'POST' && requestBody)) return undefined + if (typeof requestBody === 'object'){ + requestBody = JSON.stringify(requestBody) + } + return JSON.parse(requestBody + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key)) + .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => key === '3' + ? 'https://' + bru.getEnvVar('host3000') + : 'https://' + bru.getEnvVar('host4000')) + ) + }, + + sanitizeHeaders: function() { + return JSON.parse( + JSON.stringify(req.getHeaders()).replace(/{{([A-Za-z]\w+)}}/g, (_, key) => + bru.getEnvVar(key) + ) + ) + }, + + requestSigHeaders: async function(url, method, headers, body) { + const response = await fetch(bru.getEnvVar('signatureUrl'), { + method: 'post', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ + keyId: bru.getEnvVar('clientKeyId'), + base64Key: bru.getEnvVar('clientPrivateKey'), + request: { + url, + method, + headers, + body: JSON.stringify(body) + } + }) + }) + return await response.json() + }, + + setHeaders: function(headers) { + for (let [key, value] of Object.entries(headers)) { + req.setHeader(key, value) + } + }, + + addSignatureHeaders: async function() { + const url = this.sanitizeUrl() + const headers = this.sanitizeHeaders() + const body = this.sanitizeBody() + req.setBody(body) + const signatureHeaders = await this.requestSigHeaders(url, req.method, headers, body) + this.setHeaders(signatureHeaders) + }, + + addHostHeader: function(hostVarName) { + const requestUrl = url.parse(req.getUrl() + .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key))) + + if (hostVarName){ + bru.setEnvVar(hostVarName, requestUrl.protocol + '//' + requestUrl.host); + } + + if(requestUrl.hostname === 'localhost'){ + const hostHeader = requestUrl.port === '3000' + ? bru.getEnvVar('host3000') + : bru.getEnvVar('host4000') + req.headers.host = hostHeader + } + }, + + storeTokenDetails: function() { + const body = res.getBody(); + bru.setEnvVar("accessToken", body?.access_token?.value); + bru.setEnvVar("continueToken", body.continue.access_token.value); + bru.setEnvVar("continueId", body.continue.uri.split("/").pop()); + bru.setEnvVar("tokenId", body?.access_token?.manage.split('/').pop()) + } +} + +module.exports = scripts; \ No newline at end of file From d02aecae069ce2318d392635d9676a461c8207fa Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Fri, 16 Feb 2024 13:20:30 +0100 Subject: [PATCH 03/16] fix: admin API examples --- .../Create Outgoing Payment.bru | 17 ++++-- .../Create Quote.bru | 53 ++++++------------- ...ate Receiver -remote Incoming Payment-.bru | 17 ++++-- .../Get Outgoing Payment.bru | 6 +++ .../Create Outgoing Payment.bru | 17 ++++-- .../Peer-to-Peer Payment/Create Quote.bru | 53 ++++++------------- ...ate Receiver -remote Incoming Payment-.bru | 17 ++++-- .../Get Outgoing Payment.bru | 6 +++ .../Interledger/scripts/scripts.js | 30 ++++++++++- 9 files changed, 125 insertions(+), 91 deletions(-) diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru index 12c4b8f9af..7c58dd6138 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru @@ -54,9 +54,18 @@ body:graphql:vars { } } +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("outgoingPaymentId", body.data.createOutgoingPayment.payment.id); +} + tests { - // const body = pm.response.json(); - // - // pm.environment.set("outgoingPaymentId", body.data.createOutgoingPayment.payment.id); - // pm.expect(pm.environment.get("outgoingPaymentId")).to.be.a('string'); + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); + + test("Outgoing Payment id is string", function() { + expect(bru.getEnvVar("outgoingPaymentId")).to.be.a("string"); + }) } diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru index 416dfc1f9d..e908c42260 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru @@ -50,44 +50,23 @@ body:graphql:vars { } script:pre-request { - // - // const getWalletAddressesQuery = ` - // query GetWalletAddresses { - // walletAddresses { - // edges { - // cursor - // node { - // id - // publicName - // url - // } - // } - // } - // }` - // - // const postRequest = { - // url: `${pm.environment.get("RafikiGraphqlHost")}/graphql`, - // method: 'POST', - // body: { - // mode: 'graphql', - // graphql: { - // query:getWalletAddressesQuery - // } - // } - // }; - // - // - // pm.sendRequest(postRequest, (error, response) => { - // const body = response.json(); - // const gfranklinWalletAddressId = body.data.walletAddresses.edges.map(e => e.node).find(node => node.publicName === 'Grace Franklin')?.id - // - // pm.environment.set("gfranklinWalletAddressId", gfranklinWalletAddressId) - // }); + const scripts = require('./scripts/scripts'); + + await scripts.getWalletAddressId('RafikiGraphqlHost', 'Grace Franklin', 'gfranklinWalletAddressId'); +} + +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("quoteId", body.data.createQuote.quote.id); } tests { - // const body = pm.response.json(); - // - // pm.environment.set("quoteId", body.data.createQuote.quote.id); - // pm.expect(pm.environment.get("quoteId")).to.be.a('string'); + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); + + test("Quote id is string", function() { + expect(bru.getEnvVar("quoteId")).to.be.a("string"); + }) } diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru index aae6bdd892..ba82ff7d89 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru @@ -55,9 +55,18 @@ body:graphql:vars { } } +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("receiverId", body.data.createReceiver.receiver.id); +} + tests { - // const body = pm.response.json(); - // - // pm.environment.set("receiverId", body.data.createReceiver.receiver.id); - // pm.expect(pm.environment.get("receiverId")).to.be.a('string'); + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); + + test("Receiver id is string", function() { + expect(bru.getEnvVar("receiverId")).to.be.a("string"); + }) } diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru index 2659d9ae8c..c53b3c7f1f 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru @@ -48,3 +48,9 @@ body:graphql:vars { "id": "{{outgoingPaymentId}}" } } + +tests { + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); +} diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru index 12c4b8f9af..7c58dd6138 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru @@ -54,9 +54,18 @@ body:graphql:vars { } } +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("outgoingPaymentId", body.data.createOutgoingPayment.payment.id); +} + tests { - // const body = pm.response.json(); - // - // pm.environment.set("outgoingPaymentId", body.data.createOutgoingPayment.payment.id); - // pm.expect(pm.environment.get("outgoingPaymentId")).to.be.a('string'); + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); + + test("Outgoing Payment id is string", function() { + expect(bru.getEnvVar("outgoingPaymentId")).to.be.a("string"); + }) } diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru index 416dfc1f9d..e908c42260 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru @@ -50,44 +50,23 @@ body:graphql:vars { } script:pre-request { - // - // const getWalletAddressesQuery = ` - // query GetWalletAddresses { - // walletAddresses { - // edges { - // cursor - // node { - // id - // publicName - // url - // } - // } - // } - // }` - // - // const postRequest = { - // url: `${pm.environment.get("RafikiGraphqlHost")}/graphql`, - // method: 'POST', - // body: { - // mode: 'graphql', - // graphql: { - // query:getWalletAddressesQuery - // } - // } - // }; - // - // - // pm.sendRequest(postRequest, (error, response) => { - // const body = response.json(); - // const gfranklinWalletAddressId = body.data.walletAddresses.edges.map(e => e.node).find(node => node.publicName === 'Grace Franklin')?.id - // - // pm.environment.set("gfranklinWalletAddressId", gfranklinWalletAddressId) - // }); + const scripts = require('./scripts/scripts'); + + await scripts.getWalletAddressId('RafikiGraphqlHost', 'Grace Franklin', 'gfranklinWalletAddressId'); +} + +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("quoteId", body.data.createQuote.quote.id); } tests { - // const body = pm.response.json(); - // - // pm.environment.set("quoteId", body.data.createQuote.quote.id); - // pm.expect(pm.environment.get("quoteId")).to.be.a('string'); + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); + + test("Quote id is string", function() { + expect(bru.getEnvVar("quoteId")).to.be.a("string"); + }) } diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru index 89b2d01b4b..6cb0e3a032 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru @@ -55,9 +55,18 @@ body:graphql:vars { } } +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("receiverId", body.data.createReceiver.receiver.id); +} + tests { - // const body = pm.response.json(); - // - // pm.environment.set("receiverId", body.data.createReceiver.receiver.id); - // pm.expect(pm.environment.get("receiverId")).to.be.a('string'); + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); + + test("Receiver id is string", function() { + expect(bru.getEnvVar("receiverId")).to.be.a("string"); + }) } diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru index 2659d9ae8c..c53b3c7f1f 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru @@ -48,3 +48,9 @@ body:graphql:vars { "id": "{{outgoingPaymentId}}" } } + +tests { + test("Status code is 200", function() { + expect(res.getStatus()).to.equal(200); + }); +} diff --git a/postman/collections/Interledger/scripts/scripts.js b/postman/collections/Interledger/scripts/scripts.js index cffbbb5998..752320a04d 100644 --- a/postman/collections/Interledger/scripts/scripts.js +++ b/postman/collections/Interledger/scripts/scripts.js @@ -62,7 +62,7 @@ const scripts = { const headers = this.sanitizeHeaders() const body = this.sanitizeBody() req.setBody(body) - const signatureHeaders = await this.requestSigHeaders(url, req.method, headers, body) + const signatureHeaders = await this.requestSigHeaders(url, req.getMethod(), headers, body) this.setHeaders(signatureHeaders) }, @@ -88,6 +88,34 @@ const scripts = { bru.setEnvVar("continueToken", body.continue.access_token.value); bru.setEnvVar("continueId", body.continue.uri.split("/").pop()); bru.setEnvVar("tokenId", body?.access_token?.manage.split('/').pop()) + }, + + getWalletAddressId: async function(host, publicName, varName) { + const getWalletAddressesQuery = ` + query GetWalletAddresses { + walletAddresses { + edges { + cursor + node { + id + publicName + url + } + } + } + }` + + const postRequest = { + method: 'post', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({query: getWalletAddressesQuery}) + }; + + + const response = await fetch(`${bru.getEnvVar(host)}/graphql`, postRequest); + const body = await response.json(); + const walletAddressId = body.data.walletAddresses.edges.map(e => e.node).find(node => node.publicName === publicName)?.id + bru.setEnvVar(varName, walletAddressId) } } From 78eeec179bc0b9ab97d7d3cf0511c010a121dcbc Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Fri, 16 Feb 2024 15:12:18 +0100 Subject: [PATCH 04/16] chore: update backend admin api endpoints --- .../Create Outgoing Payment.bru | 4 - .../Create Quote.bru | 4 - ...ate Receiver -remote Incoming Payment-.bru | 4 - .../Get Outgoing Payment.bru | 6 -- .../Create Outgoing Payment.bru | 4 - .../Peer-to-Peer Payment/Create Quote.bru | 4 - ...ate Receiver -remote Incoming Payment-.bru | 4 - .../Get Outgoing Payment.bru | 6 -- .../Rafiki Admin APIs/Create Asset.bru | 8 +- .../Create Incoming Payment.bru | 13 +++- .../Create Outgoing Payment.bru | 13 +++- .../Rafiki Admin APIs/Create Peer.bru | 6 ++ .../Rafiki Admin APIs/Create Quote.bru | 74 ++++++++----------- ...ate Receiver -remote Incoming Payment-.bru | 8 +- .../Create Wallet Address Key.bru | 8 +- .../Create Wallet Address Withdrawal.bru | 2 +- .../Create Wallet Address.bru | 32 +++++--- .../Deposit Asset Liquidity.bru | 11 ++- .../Deposit Event Liquidity.bru | 2 +- .../Deposit Outgoing Payment Liquidity.bru | 8 +- .../Deposit Peer Liquidity.bru | 11 ++- .../Post Liquidity Withdrawal.bru | 10 ++- .../Rafiki Admin APIs/Update Asset.bru | 4 - .../Void Liquidity Withdrawal.bru | 10 ++- .../Withdraw Asset Liquidity.bru | 11 ++- .../Withdraw Event Liquidity.bru | 2 +- .../Withdraw Incoming Payment Liquidity.bru | 8 +- .../Withdraw Outgoing Payment Liquidity.bru | 8 +- .../Withdraw Peer Liquidity.bru | 11 ++- 29 files changed, 165 insertions(+), 131 deletions(-) diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru index 7c58dd6138..086939033f 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru @@ -61,10 +61,6 @@ script:post-response { } tests { - test("Status code is 200", function() { - expect(res.getStatus()).to.equal(200); - }); - test("Outgoing Payment id is string", function() { expect(bru.getEnvVar("outgoingPaymentId")).to.be.a("string"); }) diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru index e908c42260..ec94cdf460 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru @@ -62,10 +62,6 @@ script:post-response { } tests { - test("Status code is 200", function() { - expect(res.getStatus()).to.equal(200); - }); - test("Quote id is string", function() { expect(bru.getEnvVar("quoteId")).to.be.a("string"); }) diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru index ba82ff7d89..c2c9a76538 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru @@ -62,10 +62,6 @@ script:post-response { } tests { - test("Status code is 200", function() { - expect(res.getStatus()).to.equal(200); - }); - test("Receiver id is string", function() { expect(bru.getEnvVar("receiverId")).to.be.a("string"); }) diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru index c53b3c7f1f..2659d9ae8c 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru @@ -48,9 +48,3 @@ body:graphql:vars { "id": "{{outgoingPaymentId}}" } } - -tests { - test("Status code is 200", function() { - expect(res.getStatus()).to.equal(200); - }); -} diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru index 7c58dd6138..086939033f 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru @@ -61,10 +61,6 @@ script:post-response { } tests { - test("Status code is 200", function() { - expect(res.getStatus()).to.equal(200); - }); - test("Outgoing Payment id is string", function() { expect(bru.getEnvVar("outgoingPaymentId")).to.be.a("string"); }) diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru index e908c42260..ec94cdf460 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru @@ -62,10 +62,6 @@ script:post-response { } tests { - test("Status code is 200", function() { - expect(res.getStatus()).to.equal(200); - }); - test("Quote id is string", function() { expect(bru.getEnvVar("quoteId")).to.be.a("string"); }) diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru index 6cb0e3a032..7eaf73ac78 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru @@ -62,10 +62,6 @@ script:post-response { } tests { - test("Status code is 200", function() { - expect(res.getStatus()).to.equal(200); - }); - test("Receiver id is string", function() { expect(bru.getEnvVar("receiverId")).to.be.a("string"); }) diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru index c53b3c7f1f..2659d9ae8c 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru @@ -48,9 +48,3 @@ body:graphql:vars { "id": "{{outgoingPaymentId}}" } } - -tests { - test("Status code is 200", function() { - expect(res.getStatus()).to.equal(200); - }); -} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru index d8c14db015..11b19427ad 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru @@ -39,8 +39,8 @@ body:graphql:vars { } } -tests { - // const body = pm.response.json(); - // - // pm.environment.set("assetId", body.data.createAsset.asset.id); +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("assetId", body.data.createAsset.asset.id); } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru index e22b7fb63d..ead72840f7 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru @@ -52,9 +52,14 @@ body:graphql:vars { } } +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("incomingPaymentId", body.data.createIncomingPayment.payment.id); +} + tests { - // const body = pm.response.json(); - // - // pm.environment.set("incomingPaymentId", body.data.createIncomingPayment.payment.id); - // pm.expect(pm.environment.get("incomingPaymentId")).to.be.a('string'); + test("incomingPaymentId is string", function() { + expect(bru.getEnvVar("incomingPaymentId")).to.be.a("string"); + }) } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru index 466ea9c381..3b05e3e131 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru @@ -79,9 +79,14 @@ body:graphql:vars { } } +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("outgoingPaymentId", body.data.createOutgoingPayment.payment.id); +} + tests { - // const body = pm.response.json(); - // - // pm.environment.set("outgoingPaymentId", body.data.createOutgoingPayment.payment.id); - // pm.expect(pm.environment.get("outgoingPaymentId")).to.be.a('string'); + test("Outgoing Payment id is string", function() { + expect(bru.getEnvVar("outgoingPaymentId")).to.be.a("string"); + }) } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Peer.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Peer.bru index 4c1dd1ea36..042c9f2dae 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Peer.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Peer.bru @@ -49,6 +49,12 @@ body:graphql:vars { } } +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("peerId", body.data.createPeer.peer.id); +} + tests { // const body = pm.response.json(); // diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru index a552410a98..fc557b858d 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru @@ -56,48 +56,38 @@ body:graphql:vars { } script:pre-request { - // // Create an additional wallet address to represent the account that will be sending money - // - // // Reset the uniqueWalletAddress value - // pm.environment.set("uniqueWalletAddress", Math.floor(Math.random() * (1001))); - // - // const initialRequest = pm.environment.get("createWalletAddressRequest"); - // - // const postRequest = { - // url: initialRequest.url, - // method: initialRequest.method, - // body: { - // mode: 'graphql', - // graphql: { - // query: initialRequest.body.graphql.query, - // variables: JSON.stringify({ - // "input": { - // "assetId": pm.environment.get("assetId"), - // "url": "https://" + pm.environment.get("OpenPaymentsHost") + "/simon/" + pm.environment.get("uniqueWalletAddress"), - // "publicName": "Simon" - // } - // }) - // } - // } - // }; - // - // pm.sendRequest(postRequest, (error, response) => { - // if (error) { - // console.log(error); - // } - // const body = response.json(); - // pm.test('response should be okay to process', () => { - // pm.expect(error).to.equal(null); - // pm.expect(body.data.createWalletAddress.code).to.equal('200'); - // pm.expect(body.data.createWalletAddress.success).to.equal(true); - // }); - // pm.environment.set("secondWalletAddressId", body.data.createWalletAddress.walletAddress.id); - // }); + // Create an additional wallet address to represent the account that will be sending money + + const fetch = require('node-fetch') + + const randomInt = Math.floor(Math.random() * (1001)); + + const initialRequest = bru.getEnvVar("initialWalletAddressRequest"); + + console.log(initialRequest) + + const postRequest = { + method: 'post', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ + query: initialRequest.body.query, + variables: { + "input": { + "assetId": bru.getEnvVar("assetId"), + "url": "https://" + bru.getEnvVar("OpenPaymentsHost") + "/simon/" + randomInt, + "publicName": "Simon" + } + } + }) + }; + + const response = await fetch(`${initialRequest.url}`, postRequest); + const body = await response.json(); + bru.setEnvVar("secondWalletAddressId", body.data.createWalletAddress.walletAddress.id); } -tests { - // const body = pm.response.json(); - // - // pm.environment.set("quoteId", body.data.createQuote.quote.id); - // pm.expect(pm.environment.get("quoteId")).to.be.a('string'); +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("quoteId", body.data.createQuote.quote.id); } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru index 31258c9594..810c12b5bd 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru @@ -57,8 +57,8 @@ body:graphql:vars { } } -tests { - // const body = pm.response.json(); - // - // pm.environment.set("receiverId", body.data.createReceiver.receiver.id); +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("receiverId", body.data.createReceiver.receiver.id); } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru index 9f114c8849..18c841ae3c 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru @@ -48,8 +48,8 @@ body:graphql:vars { } } -tests { - // const body = pm.response.json(); - // - // pm.environment.set("walletAddressKeyId", body.data.createWalletAddressKey.walletAddressKey.id); +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("walletAddressKeyId", body.data.createWalletAddressKey.walletAddressKey.id); } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru index 9737619f00..fffa11bd39 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru @@ -40,7 +40,7 @@ body:graphql:vars { "input": { "id": "02ac56f7-ae5d-4abb-8306-17bf2327b43c", "walletAddressId": "{{walletAddressId}}", - "idempotencyKey":"{{$guid}}" + "idempotencyKey":"{{idempotencyKey}}" } } } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru index e1b798674b..32f46e1b3b 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru @@ -38,24 +38,34 @@ body:graphql:vars { { "input": { "assetId": "{{assetId}}", - "url": "https://{{senderOpenPaymentsHost}}/timon/{{$randomInt}}", + "url": "https://{{senderOpenPaymentsHost}}/timon/{{randomId}}", "publicName": "Timon" } } } script:pre-request { - // + const { nanoid } = require("nanoid"); + + bru.setVar('randomId', nanoid()); +} + +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("walletAddressId", body.data.createWalletAddress.walletAddress.id); + + bru.setEnvVar("walletAddressUrl", body.data.createWalletAddress.walletAddress.url); + + bru.setEnvVar('initialWalletAddressRequest',req) } tests { - // const body = pm.response.json(); - // - // pm.environment.set("walletAddressId", body.data.createWalletAddress.walletAddress.id); - // pm.expect(pm.environment.get("walletAddressId")).to.be.a('string'); - // - // pm.environment.set("walletAddressUrl", body.data.createWalletAddress.walletAddress.url); - // pm.expect(pm.environment.get("walletAddressUrl")).to.be.a('string'); - // - // pm.environment.set("createWalletAddressRequest", pm.request); + test("walletAddressId is string", function() { + expect(bru.getEnvVar("walletAddressId")).to.be.a("string"); + }) + test("walletAddressUrl is string", function() { + expect(bru.getEnvVar("walletAddressUrl")).to.be.a("string"); + }) + } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru index eaf3dd9fed..b8fac611e7 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru @@ -24,11 +24,18 @@ body:graphql { body:graphql:vars { { "input": { - "id": "3615a385-4c7e-43ec-9d66-f5d2e421108a", + "id": "{{transferId}}", "assetId": "{{assetId}}", "amount": "1000000", - "idempotencyKey":"{{$guid}}" + "idempotencyKey":"{{idempotencyKey}}" } } } + +script:pre-request { + const { v4: uuidv4 } = require('uuid'); + + bru.setVar("transferId",uuidv4()); + bru.setVar("idempotencyKey",uuidv4()); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru index d20f9a170a..e4410eadd7 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru @@ -25,7 +25,7 @@ body:graphql:vars { { "input": { "eventId": "b4f85d5c-652d-472d-873c-4ba2a5e39052", - "idempotencyKey":"{{$guid}}" + "idempotencyKey":"{{idempotencyKey}}" } } } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru index 1b85f3a3b6..b8f571bced 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru @@ -26,7 +26,13 @@ body:graphql:vars { { "input": { "outgoingPaymentId": "{{outgoingPaymentId}}", - "idempotencyKey":"{{$guid}}" + "idempotencyKey":"{{idempotencyKey}}" } } } + +script:pre-request { + const { v4: uuidv4 } = require('uuid'); + + bru.setVar("idempotencyKey",uuidv4()); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru index 85195f7035..29fe952b1c 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru @@ -24,11 +24,18 @@ body:graphql { body:graphql:vars { { "input": { - "id": "a09b730d-8610-4fda-98fa-ec7acb19c775", + "id": "{{transferId}}", "peerId": "{{peerId}}", "amount": "1000000", - "idempotencyKey":"{{$guid}}" + "idempotencyKey":"{{idempotencyKey}}" } } } + +script:pre-request { + const { v4: uuidv4 } = require('uuid'); + + bru.setVar("transferId",uuidv4()); + bru.setVar("idempotencyKey",uuidv4()); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru b/postman/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru index 78dc6512e7..f8bb4a66fe 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru @@ -24,9 +24,15 @@ body:graphql { body:graphql:vars { { "input": { - "withdrawalId": "421fae87-9a59-4217-9ff8-faf55ffab9c6", - "idempotencyKey":"{{$guid}}" + "withdrawalId": "{{withdrawalId}}", + "idempotencyKey":"{{idempotencyKey}}" } } } + +script:pre-request { + const { v4: uuidv4 } = require('uuid'); + + bru.setVar("idempotencyKey",uuidv4()); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Update Asset.bru b/postman/collections/Interledger/Rafiki Admin APIs/Update Asset.bru index c94d27f4b4..72b04ba972 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Update Asset.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Update Asset.bru @@ -37,7 +37,3 @@ body:graphql:vars { } } } - -tests { - // -} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru b/postman/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru index b37f8fc154..7319c4c194 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru @@ -24,9 +24,15 @@ body:graphql { body:graphql:vars { { "input": { - "withdrawalId": "421fae87-9a59-4217-9ff8-faf55ffab9c6", - "idempotencyKey":"{{$guid}}" + "withdrawalId": "{{withdrawalId}}", + "idempotencyKey":"{{idempotencyKey}}" } } } + +script:pre-request { + const { v4: uuidv4 } = require('uuid'); + + bru.setVar("idempotencyKey",uuidv4()); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru index 2fd124377c..ff563b7c5b 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru @@ -24,11 +24,18 @@ body:graphql { body:graphql:vars { { "input": { - "id": "b97fd85a-126e-42ef-b40d-1a50a70ffa6f", + "id": "{{transferId}}", "assetId": "{{assetId}}", "amount": "100", - "idempotencyKey":"{{$guid}}" + "idempotencyKey":"{{idempotencyKey}}" } } } + +script:pre-request { + const { v4: uuidv4 } = require('uuid'); + + bru.setVar("transferId",uuidv4()); + bru.setVar("idempotencyKey",uuidv4()); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru index ab2a5f537b..b962f03125 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru @@ -25,7 +25,7 @@ body:graphql:vars { { "input": { "eventId": "b4f85d5c-652d-472d-873c-4ba2a5e39052", - "idempotencyKey":"{{$guid}}" + "idempotencyKey":"{{idempotencyKey}}" } } } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru index 17dd806a8b..173388da95 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru @@ -25,7 +25,13 @@ body:graphql:vars { { "input": { "incomingPaymentId": "{{incomingPaymentId}}", - "idempotencyKey":"{{$guid}}" + "idempotencyKey":"{{idempotencyKey}}" } } } + +script:pre-request { + const { v4: uuidv4 } = require('uuid'); + + bru.setVar("idempotencyKey",uuidv4()); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru index b80c5a16c9..e674deb33b 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru @@ -25,7 +25,13 @@ body:graphql:vars { { "input": { "outgoingPaymentId": "{{outgoingPaymentId}}", - "idempotencyKey":"{{$guid}}" + "idempotencyKey":"{{idempotencyKey}}" } } } + +script:pre-request { + const { v4: uuidv4 } = require('uuid'); + + bru.setVar("idempotencyKey",uuidv4()); +} diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru index d7eefff238..aee29be57d 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru @@ -24,11 +24,18 @@ body:graphql { body:graphql:vars { { "input": { - "id": "421fae87-9a59-4217-9ff8-faf55ffab9c6", + "id": "{{withdrawalId}}", "peerId": "{{peerId}}", "amount": "100", - "idempotencyKey":"{{$guid}}" + "idempotencyKey":"{{idempotencyKey}}" } } } + +script:pre-request { + const { v4: uuidv4 } = require('uuid'); + + bru.setEnvVar("withdrawalId",uuidv4()); + bru.setVar("idempotencyKey",uuidv4()); +} From abb6ebc4d7bb2d65af850da670e57a9510cd58ef Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Mon, 19 Feb 2024 09:31:19 +0100 Subject: [PATCH 05/16] chore: remove console log --- .../collections/Interledger/Rafiki Admin APIs/Create Quote.bru | 2 -- 1 file changed, 2 deletions(-) diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru index fc557b858d..1530f4eab7 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru @@ -64,8 +64,6 @@ script:pre-request { const initialRequest = bru.getEnvVar("initialWalletAddressRequest"); - console.log(initialRequest) - const postRequest = { method: 'post', headers: {'Content-Type': 'application/json'}, From b7cd3c69d208bf11767bfb95dfbf174597ef0420 Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Mon, 19 Feb 2024 12:34:38 +0100 Subject: [PATCH 06/16] chore: finish transition to bruno --- .../Open Payments/Continuation Request.bru | 2 +- .../Grants/Continuation Request.bru | 10 +++++++++- .../Grants/Grant Request.bru | 14 +++++++------- .../Tokens/Revoke Access Token.bru | 4 +++- .../Tokens/Rotate Access Token.bru | 12 +++++++----- .../Rafiki Admin Auth APIs/Get Grant.bru | 2 +- .../Rafiki Admin Auth APIs/Revoke Grant.bru | 2 +- 7 files changed, 29 insertions(+), 17 deletions(-) diff --git a/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru b/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru index a731d771d0..7993ba5f87 100644 --- a/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru +++ b/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru @@ -16,7 +16,7 @@ headers { body:json { { - "interact_ref": "8c55602c-f777-44cf-bbe7-f4f6589d6aeb" + "interact_ref": "83d168de-e907-4056-b170-a0cd010f5090" } } diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru b/postman/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru index 59e1b630aa..9ea58a64bd 100644 --- a/postman/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru +++ b/postman/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru @@ -21,7 +21,15 @@ body:json { } script:pre-request { - // eval(pm.environment.get('preRequestSignatures')) + const scripts = require('./scripts/scripts'); + + await scripts.addSignatureHeaders(); +} + +script:post-response { + const scripts = require('./scripts/scripts'); + + scripts.storeTokenDetails(); } tests { diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru b/postman/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru index 66fdbf2bf7..328c79c5fe 100644 --- a/postman/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru +++ b/postman/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru @@ -57,13 +57,13 @@ body:json { } script:pre-request { - // eval(pm.environment.get('preRequestSignatures')) + const scripts = require('./scripts/scripts'); + + await scripts.addSignatureHeaders(); } -tests { - // const body = pm.response.json(); - // pm.environment.set("accessToken", body?.access_token?.value); - // pm.environment.set("continueToken", body.continue.access_token.value); - // pm.environment.set("continueId", body.continue.uri.split("/").pop()); - // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) +script:post-response { + const scripts = require('./scripts/scripts'); + + scripts.storeTokenDetails(); } diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru b/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru index da702b8fd7..f471101519 100644 --- a/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru +++ b/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru @@ -11,5 +11,7 @@ delete { } script:pre-request { - // eval(pm.environment.get('preRequestSignatures')) + const scripts = require('./scripts/scripts'); + + await scripts.addSignatureHeaders(); } diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru b/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru index 94f505a760..debc9c3f1f 100644 --- a/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru +++ b/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru @@ -15,11 +15,13 @@ headers { } script:pre-request { - // eval(pm.environment.get('preRequestSignatures')) + const scripts = require('./scripts/scripts'); + + await scripts.addSignatureHeaders(); } -tests { - // const body = pm.response.json(); - // pm.environment.set("accessToken", body.access_token.value); - // pm.environment.set("tokenId", body.access_token.manage.split('/').pop()) +script:post-response { + const scripts = require('./scripts/scripts'); + + scripts.storeTokenDetails(); } diff --git a/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru b/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru index 86d6312055..24b6e63d6b 100644 --- a/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru +++ b/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru @@ -44,6 +44,6 @@ body:graphql { body:graphql:vars { { - "id": "056b3f93-7890-4005-9b24-2623d9cedab5" + "id": "97de60d6-cafa-4c8c-a847-f63ca04eb3bf" } } diff --git a/postman/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru b/postman/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru index a06bbc4adf..cff9023698 100644 --- a/postman/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru +++ b/postman/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru @@ -23,7 +23,7 @@ body:graphql { body:graphql:vars { { "input": { - "grantId": "e6684d05-6cc5-4a0e-a490-7ed05923fa89" + "grantId": "97de60d6-cafa-4c8c-a847-f63ca04eb3bf" } } } From 1a34494ca1e665de8ffa1a3ee1b72c39efa14fe2 Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Mon, 19 Feb 2024 12:53:16 +0100 Subject: [PATCH 07/16] chore: add remote environment --- .../collections/Interledger/environments/Remote.bru | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 postman/collections/Interledger/environments/Remote.bru diff --git a/postman/collections/Interledger/environments/Remote.bru b/postman/collections/Interledger/environments/Remote.bru new file mode 100644 index 0000000000..6ae2760410 --- /dev/null +++ b/postman/collections/Interledger/environments/Remote.bru @@ -0,0 +1,10 @@ +vars { + clientWalletAddress: https://ilp.rafiki.money/d99f0eee + clientKeyId: e9a47ee7-99b3-4656-b85f-12431dbc16b9 + senderWalletAddress: https://ilp.rafiki.money/d99f0eee + receiverWalletAddress: https://ilp.rafiki.money/f1475476 + signatureUrl: https://kxu5d4mr4blcthphxomjlc4xk40rvdsx.lambda-url.eu-central-1.on.aws/ +} +vars:secret [ + clientPrivateKey +] From 725b307991546d47b6495bd0ed7286c240cc1b89 Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Mon, 19 Feb 2024 12:53:40 +0100 Subject: [PATCH 08/16] chore: remove postman stuff --- postman/collections/Interledger.json | 3544 ----------------- ...round Environment.postman_environment.json | 285 -- ...emote Environment.postman_environment.json | 159 - .../preRequestHostHeader.js | 17 - .../preRequestSignatures.js | 55 - 5 files changed, 4060 deletions(-) delete mode 100644 postman/collections/Interledger.json delete mode 100644 postman/environments/Local Playground Environment.postman_environment.json delete mode 100644 postman/environments/Remote Environment.postman_environment.json delete mode 100644 postman/pre-request-scripts/preRequestHostHeader.js delete mode 100644 postman/pre-request-scripts/preRequestSignatures.js diff --git a/postman/collections/Interledger.json b/postman/collections/Interledger.json deleted file mode 100644 index 2daddc16c3..0000000000 --- a/postman/collections/Interledger.json +++ /dev/null @@ -1,3544 +0,0 @@ -{ - "info": { - "_postman_id": "92761441-6d0c-4fc6-aa04-73eccf6afd4c", - "name": "Interledger", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_uid": "23674746-92761441-6d0c-4fc6-aa04-73eccf6afd4c" - }, - "item": [ - { - "name": "Rafiki Admin APIs", - "item": [ - { - "name": "Create Asset", - "event": [ - { - "listen": "test", - "script": { - "id": "f852a7a5-0e89-499a-9bff-c53a84d78773", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"assetId\", body.data.createAsset.asset.id);" - ], - "type": "text/javascript" - } - } - ], - "id": "7eeac689-1a11-4bf7-961c-ed2f51fccc62", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateAsset($input: CreateAssetInput!) {\n createAsset(input: $input) {\n asset {\n code\n createdAt\n id\n scale\n withdrawalThreshold\n liquidityThreshold\n }\n code\n message\n success\n }\n}", - "variables": "{\n \"input\": {\n \"code\": \"USD\",\n \"scale\": 6,\n \"withdrawalThreshold\": null,\n \"liquidityThreshold\": \"100000000\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Update Asset", - "event": [ - { - "listen": "test", - "script": { - "id": "e024410d-9eb8-41f5-9cab-691f76721bb6", - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "id": "68c26713-273b-4bee-88e6-8f38f1ed57b2", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation UpdateAsset($input: UpdateAssetInput!) {\n updateAsset(input: $input) {\n asset {\n code\n createdAt\n id\n scale\n withdrawalThreshold\n liquidityThreshold\n }\n code\n message\n success\n }\n}", - "variables": "{\n \"input\": {\n \"id\": \"{{assetId}}\",\n \"withdrawalThreshold\": 100,\n \"liquidityThreshold\": 100\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Asset", - "id": "1a43bdb1-ddcb-4c62-a446-470433751278", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetAsset($id: String!) {\n asset(id: $id) {\n code\n createdAt\n id\n scale\n withdrawalThreshold\n liquidityThreshold\n sendingFee {\n id\n type\n basisPoints\n fixed\n }\n receivingFee {\n id\n type\n basisPoints\n fixed\n }\n }\n}", - "variables": "{\n \"id\": \"{{assetId}}\"\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Assets", - "id": "88548a93-d444-492c-ab64-843ba4d8e9e6", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetAssets($after: String, $before: String, $first: Int, $last: Int) {\n assets(after: $after, before: $before, first:$first, last: $last) {\n edges {\n cursor\n node {\n code\n createdAt\n id\n scale\n withdrawalThreshold\n liquidityThreshold\n liquidity\n sendingFee {\n id\n type\n basisPoints\n fixed\n }\n receivingFee {\n id\n type\n basisPoints\n fixed\n }\n }\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}", - "variables": "{\n \"after\": null,\n \"before\": null,\n \"first\": null,\n \"last\": null\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Deposit Asset Liquidity", - "id": "64b586a1-d9a9-4d14-b756-42f9368ed519", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation DepositAssetLiquidity ($input: DepositAssetLiquidityInput!) {\n depositAssetLiquidity(input: $input) {\n code\n success\n message\n error\n }\n}", - "variables": "{\n \"input\": {\n \"id\": \"3615a385-4c7e-43ec-9d66-f5d2e421108a\",\n \"assetId\": \"{{assetId}}\",\n \"amount\": \"1000000\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}\n" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Withdraw Asset Liquidity", - "id": "26ae74ef-bb7d-4bca-88c7-c5d95695d1bd", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateAssetLiquidityWithdrawal ($input: CreateAssetLiquidityWithdrawalInput!) {\n createAssetLiquidityWithdrawal(input: $input) {\n code\n success\n message\n error\n }\n}", - "variables": "{\n \"input\": {\n \"id\": \"b97fd85a-126e-42ef-b40d-1a50a70ffa6f\",\n \"assetId\": \"{{assetId}}\",\n \"amount\": \"100\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}\n" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Set Fee", - "event": [ - { - "listen": "test", - "script": { - "id": "7d92e6c7-22e9-4f7a-92c8-a925d1e013f5", - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "id": "373dabae-5af5-44d8-a96c-cbafa4280f20", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation SetFee($input: SetFeeInput!) {\n setFee(input: $input) {\n code\n success\n message\n fee {\n id\n assetId\n type\n fixed\n basisPoints\n createdAt\n }\n }\n}", - "variables": "{\n \"input\": {\n \"assetId\": \"{{assetId}}\",\n \"type\": \"SENDING\",\n \"fee\": {\n \"fixed\": 100,\n \"basisPoints\": 100\n }\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Peer", - "event": [ - { - "listen": "test", - "script": { - "id": "8b5efee8-1414-4786-af23-49ffa323cbd1", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"peerId\", body.data.createPeer.peer.id);" - ], - "type": "text/javascript" - } - } - ], - "id": "af5fbfd3-a893-490c-914e-99b2866cf482", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreatePeer ($input: CreatePeerInput!) {\n createPeer (input: $input) {\n code\n message\n success\n peer {\n id\n name\n liquidity\n liquidityThreshold\n asset{\n id\n scale\n code\n withdrawalThreshold\n }\n }\n }\n}", - "variables": "{\n \"input\": {\n \"name\": \"Wallet1\",\n \"staticIlpAddress\": \"test.peer\",\n \"http\": {\n \"incoming\": {\"authTokens\": [\"test123abc\"]},\n \"outgoing\": {\"endpoint\": \"http://peer-backend:3002\", \"authToken\": \"test123abc\"}\n },\n \"assetId\": \"{{assetId}}\",\n \"maxPacketAmount\": 1000,\n \"liquidityThreshold\": 100000000,\n \"initialLiquidity\": 200000000\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Or Update Peer By Url", - "event": [ - { - "listen": "test", - "script": { - "id": "69d9415d-bcec-4a61-9592-9141c8a9c7e7", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"peerId\", body.data.createOrUpdatePeerByUrl.peer.id);" - ], - "type": "text/javascript" - } - } - ], - "id": "dc9a1002-453d-4037-bd38-deb18681d78a", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateOrUpdatePeerByUrl ($input: CreateOrUpdatePeerByUrlInput!) {\n createOrUpdatePeerByUrl (input: $input) {\n code\n message\n success\n peer {\n id\n name\n asset {\n id\n scale\n code\n withdrawalThreshold\n }\n }\n }\n}", - "variables": "{\n \"input\": {\n \"peerUrl\": \"http://happy-life-bank-backend:3005\",\n \"assetId\": \"{{assetId}}\",\n \"liquidityToDeposit\": 100000\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Update Peer", - "id": "206fa427-cf5e-4aa8-9c59-5ddb1b021720", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation UpdatePeer ($input: UpdatePeerInput!){ \n updatePeer(input: $input) {\n code\n success\n message\n peer {\n id\n name\n http {\n outgoing {\n authToken\n endpoint\n }\n }\n liquidity\n liquidityThreshold\n }\n }\n}", - "variables": "{\n \"input\": {\n \"id\": \"{{peerId}}\",\n \"name\": \"Wall-y\",\n \"http\": {\n \"incoming\": {\"authTokens\": [\"test-123\"]},\n \"outgoing\": {\"endpoint\": \"http://peer-backend:3002\", \"authToken\": \"test\"}\n },\n \"maxPacketAmount\": 1000,\n \"liquidityThreshold\": 100\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Peer", - "id": "a5f3d256-d435-4fdd-bc68-456c891e3fb7", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetPeer {\n peer (id: \"{{peerId}}\") {\n id\n name\n http {\n outgoing {\n authToken\n endpoint\n }\n }\n liquidity\n liquidityThreshold\n }\n}", - "variables": "" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Peers", - "id": "194c260e-a4cb-486d-9cfc-cee5bd00d36b", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetPeers {\n peers {\n edges {\n cursor\n node {\n id\n name\n asset {\n code\n scale\n }\n liquidity\n liquidityThreshold\n staticIlpAddress\n http {\n outgoing {\n authToken\n endpoint\n }\n }\n }\n }\n }\n}", - "variables": "" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Delete Peer", - "id": "3299f99c-72ba-42ea-8db5-93024e1328d6", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation DeletePeer($input: DeletePeerInput!) {\n deletePeer(input: $input) {\n code\n message\n success\n }\n}\n", - "variables": "{\n \"input\": {\n \"id\": \"{{peerId}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Deposit Peer Liquidity", - "id": "99935f5e-8ff6-48c4-8ba7-c69954dfbb5d", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation DepositPeerLiquidity ($input: DepositPeerLiquidityInput!) {\n depositPeerLiquidity(input: $input) {\n code\n success\n message\n error\n }\n}", - "variables": "{\n \"input\": {\n \"id\": \"a09b730d-8610-4fda-98fa-ec7acb19c775\",\n \"peerId\": \"{{peerId}}\",\n \"amount\": \"1000000\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}\n" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Withdraw Peer Liquidity", - "id": "b2a48f59-8e87-4153-8c1b-9f5a5be8c8d3", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreatePeerLiquidityWithdrawal ($input: CreatePeerLiquidityWithdrawalInput!) {\n createPeerLiquidityWithdrawal(input: $input) {\n code\n success\n message\n error\n }\n}", - "variables": "{\n \"input\": {\n \"id\": \"421fae87-9a59-4217-9ff8-faf55ffab9c6\",\n \"peerId\": \"{{peerId}}\",\n \"amount\": \"100\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}\n" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Post Liquidity Withdrawal", - "id": "49967c65-a0ba-43e2-b3f7-0e263300833a", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation PostLiquidityWithdrawal($input: PostLiquidityWithdrawalInput!) {\n postLiquidityWithdrawal(input: $input) {\n code\n error\n message\n success\n }\n}", - "variables": "{\n \"input\": {\n \"withdrawalId\": \"421fae87-9a59-4217-9ff8-faf55ffab9c6\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}\n" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Void Liquidity Withdrawal", - "id": "a8a366c0-dbcb-4e9f-80df-faef74da2872", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation VoidLiquidityWithdrawal($input: VoidLiquidityWithdrawalInput!) {\n voidLiquidityWithdrawal(input: $input) {\n code\n error\n message\n success\n }\n}", - "variables": "{\n \"input\": {\n \"withdrawalId\": \"421fae87-9a59-4217-9ff8-faf55ffab9c6\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}\n" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Wallet Address", - "event": [ - { - "listen": "test", - "script": { - "id": "dfb6c98c-9a4b-4466-85d9-84a81e24a966", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"walletAddressId\", body.data.createWalletAddress.walletAddress.id);", - "pm.expect(pm.environment.get(\"walletAddressId\")).to.be.a('string');", - "", - "pm.environment.set(\"walletAddressUrl\", body.data.createWalletAddress.walletAddress.url);", - "pm.expect(pm.environment.get(\"walletAddressUrl\")).to.be.a('string');", - "", - "pm.environment.set(\"createWalletAddressRequest\", pm.request);" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "941a61ee-9dd1-4c7c-a351-b67f96436970", - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "id": "b2bd6d8d-541e-4fd6-9f14-810179eda985", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateWalletAddres($input: CreateWalletAddressInput!) {\n createWalletAddress(input: $input) {\n code\n success\n message\n walletAddress {\n id\n createdAt\n publicName\n url\n status\n asset {\n code\n createdAt\n id\n scale\n withdrawalThreshold\n }\n }\n }\n}", - "variables": "{\n \"input\": {\n \"assetId\": \"{{assetId}}\",\n \"url\": \"https://{{senderOpenPaymentsHost}}/timon/{{$randomInt}}\",\n \"publicName\": \"Timon\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Update Wallet Address", - "id": "3ec1c9ca-4d14-4fe1-bbf7-d71be8e9454d", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation UpdateWalletAddress($input: UpdateWalletAddressInput!) {\n updateWalletAddress(input: $input) {\n code\n message\n walletAddress {\n id\n asset {\n id\n code\n scale\n withdrawalThreshold\n createdAt\n }\n url\n publicName\n createdAt\n status\n }\n success\n }\n}", - "variables": "{\n \"input\": {\n \"id\": \"{{walletAddressId}}\",\n \"publicName\": \"New Name\",\n \"status\": \"ACTIVE\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Wallet Address", - "id": "a2807507-b39a-498b-b2ec-514b53706a00", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetWalletAddress($id: String!) {\n walletAddress(id: $id) {\n id\n asset {\n id\n code\n scale\n withdrawalThreshold\n createdAt\n }\n createdAt\n incomingPayments {\n edges {\n node {\n id\n state\n incomingAmount {\n value\n }\n receivedAmount {\n value\n }\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n status\n }\n}", - "variables": "{\n \"id\": \"{{walletAddressId}}\"\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Wallet Addresses", - "id": "6d83b6a9-dd1d-40a7-a774-32747c7d9938", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetWalletAddresses {\n walletAddresses {\n edges {\n cursor\n node {\n id\n publicName\n url\n }\n }\n }\n}", - "variables": "" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Wallet Address Key", - "event": [ - { - "listen": "test", - "script": { - "id": "dfd63ef9-5ff6-4ec9-a296-9ddf249cd1f1", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"walletAddressKeyId\", body.data.createWalletAddressKey.walletAddressKey.id);" - ], - "type": "text/javascript" - } - } - ], - "id": "33546c8b-a254-4142-a50c-551725319c0c", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateWalletAddressKey ($input: CreateWalletAddressKeyInput!) {\n createWalletAddressKey(input: $input) {\n code\n message\n success\n walletAddressKey {\n id\n revoked\n walletAddressId\n createdAt\n jwk {\n alg\n crv\n kid\n kty\n x\n }\n }\n }\n}", - "variables": "{\n \"input\": {\n \"walletAddressId\": \"{{walletAddressId}}\",\n \"jwk\": {\n \"alg\": \"EdDSA\",\n \"crv\": \"Ed25519\",\n \"kid\": \"kid_dad93e7f-f40b-484d-99d2-df12c8523176\",\n \"kty\": \"OKP\", \n \"x\": \"ubqoInifJ5sssIPPnQR1gVPfmoZnJtPhTkyMXNoJF_8\"\n }\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Revoke Wallet Address Key", - "id": "15b344d9-16c7-40ee-96c4-0b8beb1667b2", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation RevokeWalletAddressKey ($input: RevokeWalletAddressKeyInput!) {\n revokeWalletAddressKey (input: $input) {\n code\n message\n success\n walletAddressKey {\n id\n revoked\n walletAddressId\n createdAt\n }\n }\n}", - "variables": "{\n \"input\": {\n \"id\": \"{{walletAddressKeyId}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Incoming Payment", - "event": [ - { - "listen": "test", - "script": { - "id": "b3d3cc11-7018-45af-b937-97b4f4eaa716", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"incomingPaymentId\", body.data.createIncomingPayment.payment.id);", - "pm.expect(pm.environment.get(\"incomingPaymentId\")).to.be.a('string');" - ], - "type": "text/javascript" - } - } - ], - "id": "50fb19dc-e5dc-4dbf-9f98-a142a9c016eb", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateIncomingPayment ($input: CreateIncomingPaymentInput!) {\n createIncomingPayment(input: $input) {\n code\n message\n payment {\n createdAt\n expiresAt\n metadata\n id\n incomingAmount {\n assetCode\n assetScale\n value\n }\n walletAddressId\n receivedAmount {\n assetCode\n assetScale\n value\n }\n state\n }\n success\n }\n}", - "variables": "{\n \"input\": {\n \"expiresAt\": null,\n \"metadata\": {\n \"externalRef\": null, \n \"description\": \"Hello World\"\n },\n \"incomingAmount\": null,\n \"walletAddressId\": \"{{walletAddressId}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Incoming Payment", - "id": "a7cab5ce-4459-4e34-be83-b8fdf8ab867f", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetIncomingPayment($id: String!) {\nincomingPayment(id: $id) {\n id\n walletAddressId\n state\n expiresAt\n incomingAmount {\n value\n assetCode\n assetScale\n }\n receivedAmount {\n value\n assetCode\n assetScale\n }\n metadata\n createdAt\n }\n}", - "variables": "{\n \"id\": \"{{incomingPaymentId}}\"\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Withdraw Incoming Payment Liquidity", - "id": "0119e113-d8b1-41f2-8021-a1549896a159", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation WithdrawIncomingPaymentLiquidity($input: WithdrawIncomingPaymentLiquidityInput!) { \n withdrawIncomingPaymentLiquidity(input: $input) { \n code \n error \n message \n success \n }\n}", - "variables": "{\n \"input\": {\n \"incomingPaymentId\": \"{{incomingPaymentId}}\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Receiver (remote Incoming Payment)", - "event": [ - { - "listen": "test", - "script": { - "id": "b1b39804-334e-458d-b03a-2db4e866d458", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"receiverId\", body.data.createReceiver.receiver.id);" - ], - "type": "text/javascript" - } - } - ], - "id": "c7f63ae6-c790-43f5-8c8e-163297708693", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateReceiver($input: CreateReceiverInput!) {\n createReceiver(input: $input) {\n code\n message\n receiver {\n completed\n createdAt\n expiresAt\n metadata\n id\n incomingAmount {\n assetCode\n assetScale\n value\n }\n walletAddressUrl\n receivedAmount {\n assetCode\n assetScale\n value\n }\n updatedAt\n }\n success\n }\n}", - "variables": "{\n \"input\": {\n \"expiresAt\": null,\n \"metadata\": {\n \"description\": \"Hello my friend\",\n \"externalRef\": null\n },\n \"incomingAmount\": {\n \"assetCode\": \"USD\",\n \"assetScale\": 2,\n \"value\": 1002\n },\n \"walletAddressUrl\": \"https://happy-life-bank-backend/accounts/pfry\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Receiver (remote Incoming Payment)", - "id": "d5db39cc-f511-4fdb-9200-52fd8d93a820", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetReceiver($id: String!) {\n receiver(id: $id) {\n id\n completed\n expiresAt\n metadata\n incomingAmount {\n assetCode\n assetScale\n value\n }\n walletAddressUrl\n receivedAmount {\n assetCode\n assetScale\n value\n }\n createdAt\n updatedAt\n }\n}", - "variables": "{\n \"id\": \"{{receiverId}}\"\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Quote", - "event": [ - { - "listen": "test", - "script": { - "id": "914fbff5-0d44-4c69-bc4d-3a0507af645a", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"quoteId\", body.data.createQuote.quote.id);", - "pm.expect(pm.environment.get(\"quoteId\")).to.be.a('string');" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "63c84a58-3a85-44dd-86cf-8446e0afce8c", - "exec": [ - "// Create an additional wallet address to represent the account that will be sending money", - "", - "// Reset the uniqueWalletAddress value", - "pm.environment.set(\"uniqueWalletAddress\", Math.floor(Math.random() * (1001)));", - "", - "const initialRequest = pm.environment.get(\"createWalletAddressRequest\");", - "", - "const postRequest = {", - " url: initialRequest.url,", - " method: initialRequest.method,", - " body: {", - " mode: 'graphql',", - " graphql: {", - " query: initialRequest.body.graphql.query,", - " variables: JSON.stringify({", - " \"input\": {", - " \"assetId\": pm.environment.get(\"assetId\"),", - " \"url\": \"https://\" + pm.environment.get(\"OpenPaymentsHost\") + \"/simon/\" + pm.environment.get(\"uniqueWalletAddress\"),", - " \"publicName\": \"Simon\"", - " }", - " })", - " }", - " }", - "};", - "", - "pm.sendRequest(postRequest, (error, response) => {", - " if (error) {", - " console.log(error);", - " }", - " const body = response.json();", - " pm.test('response should be okay to process', () => {", - " pm.expect(error).to.equal(null);", - " pm.expect(body.data.createWalletAddress.code).to.equal('200');", - " pm.expect(body.data.createWalletAddress.success).to.equal(true);", - " });", - " pm.environment.set(\"secondWalletAddressId\", body.data.createWalletAddress.walletAddress.id);", - "});" - ], - "type": "text/javascript" - } - } - ], - "id": "0bb53e01-0cc0-4295-aa4a-9b5663e578a0", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateQuote($input: CreateQuoteInput!) {\n createQuote(input: $input) {\n code\n message\n quote {\n createdAt\n expiresAt\n highEstimatedExchangeRate\n id\n lowEstimatedExchangeRate\n maxPacketAmount\n minExchangeRate\n walletAddressId\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n }\n }\n}", - "variables": "{\n \"input\": {\n \"walletAddressId\": \"{{secondWalletAddressId}}\",\n \"receiveAmount\": null,\n \"receiver\": \"{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}\",\n \"debitAmount\": {\n \"assetCode\": \"USD\",\n \"assetScale\": 6,\n \"value\": 5000000\n }\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Quote", - "id": "1b640182-9efb-4b06-b89d-1eaa520a7d97", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetQuote($id: String!) {\n quote(id: $id) {\n createdAt\n highEstimatedExchangeRate\n expiresAt\n id\n lowEstimatedExchangeRate\n maxPacketAmount\n minExchangeRate\n walletAddressId\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n }\n}", - "variables": "{\n \"id\": \"{{quoteId}}\"\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Outgoing Payment", - "event": [ - { - "listen": "test", - "script": { - "id": "7f9d8f1d-5af7-4b24-86e4-3c54f2223f32", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"outgoingPaymentId\", body.data.createOutgoingPayment.payment.id);", - "pm.expect(pm.environment.get(\"outgoingPaymentId\")).to.be.a('string');" - ], - "type": "text/javascript" - } - } - ], - "id": "74f060e1-01d6-43f1-9634-0a73d398c9da", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateOutgoingPayment($input: CreateOutgoingPaymentInput!) {\n createOutgoingPayment(input: $input) {\n code\n message\n payment {\n createdAt\n error\n metadata\n id\n walletAddressId\n quote {\n createdAt\n expiresAt\n highEstimatedExchangeRate\n id\n lowEstimatedExchangeRate\n maxPacketAmount\n minExchangeRate\n walletAddressId\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n }\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n sentAmount {\n assetCode\n assetScale\n value\n }\n state\n stateAttempts\n }\n success\n }\n}", - "variables": "{\n \"input\": {\n \"metadata\": {\n \"description\": null,\n \"externalRef\": null\n },\n \"walletAddressId\": \"{{secondWalletAddressId}}\",\n \"quoteId\": \"{{quoteId}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Outgoing Payment", - "id": "22ee3b50-8ac9-46ac-b4dd-e885fc8fe395", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetOutgoingPayment($id: String!) {\noutgoingPayment(id: $id) {\n createdAt\n error\n metadata\n id\n walletAddressId\n quote {\n createdAt\n expiresAt\n highEstimatedExchangeRate\n id\n lowEstimatedExchangeRate\n maxPacketAmount\n minExchangeRate\n walletAddressId\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n }\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n sentAmount {\n assetCode\n assetScale\n value\n }\n state\n stateAttempts\n }\n}", - "variables": "{\n \"id\": \"{{outgoingPaymentId}}\"\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Payments", - "id": "357ee69f-d258-49c5-a02b-072b566302d2", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query Payments($filter: PaymentFilter) {\n payments(filter: $filter) {\n edges {\n node {\n id\n type\n walletAddressId\n state\n metadata\n createdAt\n }\n cursor\n }\n }\n}", - "variables": "{ \n \"filter\": {\n \"type\": {\n \"in\": [\"OUTGOING\"]\n },\n \"walletAddressId\": {\n \"in\": [\"{{secondWalletAddressId}}\"]\n }\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Deposit Event Liquidity", - "id": "7c3afd23-2348-43d6-9cfa-895e54e05f9e", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation DepositEventLiquidity($input: DepositEventLiquidityInput!) {\n depositEventLiquidity(input: $input) {\n code\n error\n message\n success\n }\n}", - "variables": "{\n \"input\": {\n \"eventId\": \"b4f85d5c-652d-472d-873c-4ba2a5e39052\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Deposit Outgoing Payment Liquidity", - "id": "f50e3c66-f1c2-4cdc-9902-739f752b909c", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation DepositOutgoingPaymentLiquidity($input: DepositOutgoingPaymentLiquidityInput!) {\n depositOutgoingPaymentLiquidity(input: $input) {\n code\n error\n message\n success\n }\n}\n", - "variables": "{\n \"input\": {\n \"outgoingPaymentId\": \"{{outgoingPaymentId}}\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Withdraw Outgoing Payment Liquidity", - "id": "714d51c4-fe2e-4711-b297-97254b015acd", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation WithdrawOutgoingPaymentLiquidity($input: WithdrawOutgoingPaymentLiquidityInput!) { \n withdrawOutgoingPaymentLiquidity(input: $input) {\n code \n error \n message \n success \n }\n}", - "variables": "{\n \"input\": {\n \"outgoingPaymentId\": \"{{outgoingPaymentId}}\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Withdraw Event Liquidity", - "id": "2d788367-7019-4a9a-94c6-e0655e9200c7", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation WithdrawEventLiquidity($input: WithdrawEventLiquidityInput!) {\n withdrawEventLiquidity(input: $input) {\n code\n error\n message\n success\n }\n}", - "variables": "{\n \"input\": {\n \"eventId\": \"b4f85d5c-652d-472d-873c-4ba2a5e39052\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Wallet Address Withdrawal", - "id": "84fcddb6-efbf-43d6-a8c6-d3ea8c1bdc40", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateWalletAddressWithdrawal($input: CreateWalletAddressWithdrawalInput!) {\n createWalletAddressWithdrawal(input: $input) {\n code\n error\n message\n success\n withdrawal {\n amount\n id\n walletAddress {\n id\n url\n asset {\n id\n code\n scale\n withdrawalThreshold\n }\n }\n }\n }\n}", - "variables": "{\n \"input\": {\n \"id\": \"02ac56f7-ae5d-4abb-8306-17bf2327b43c\",\n \"walletAddressId\": \"{{walletAddressId}}\",\n \"idempotencyKey\":\"{{$guid}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Trigger Wallet Address Events", - "id": "9d7a602e-6025-475a-a4f4-13d99936fb74", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation TriggerWalletAddressEvents($input: TriggerWalletAddressEventsInput!) {\n triggerWalletAddressEvents(input: $input) {\n code\n count\n message\n success\n }\n}", - "variables": "{\n \"input\": {\n \"limit\": 5\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Webhook Events", - "id": "46009b2f-564c-41ca-8381-de63227f20c8", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query WebhookEvents($after: String, $before: String, $first: Int, $last: Int, $filter: WebhookEventFilter) {\n webhookEvents(after: $after, before: $before, first:$first, last: $last, filter: $filter) {\n edges {\n cursor\n node {\n createdAt\n data\n id\n type\n }\n }\n }\n}", - "variables": "{\n \"filter\": {\n \"type\": { \n \"in\": []\n }\n },\n \"after\": null,\n \"before\": null,\n \"first\": null,\n \"last\": null\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - } - ], - "id": "4b27bf1e-2769-47bd-a3a7-3f48322cc22d" - }, - { - "name": "Rafiki Admin Auth APIs", - "item": [ - { - "name": "Get Grant", - "id": "c63df0b8-457f-4c08-8ad1-601e6bab77d7", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query Grant($id: ID!) {\n grant(id: $id) {\n id\n state\n createdAt\n client\n access {\n type\n actions\n createdAt\n id\n identifier\n limits {\n interval\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n }\n }\n }\n}", - "variables": "{\n \"id\": \"056b3f93-7890-4005-9b24-2623d9cedab5\"\n}" - } - }, - "url": { - "raw": "{{RafikiAuthGraphqlHost}}/graphql", - "host": [ - "{{RafikiAuthGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Grants", - "id": "d7343301-19d2-4f53-b781-00cd07e52813", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query Grants($after: String, $before: String, $first: Int, $last: Int, $filter: GrantFilter) {\n grants(after: $after, before: $before, first: $first, last: $last, filter: $filter) {\n edges {\n cursor\n node {\n access {\n createdAt\n id\n identifier\n limits {\n interval\n receiveAmount {\n assetScale\n value\n assetCode\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n }\n actions\n type\n }\n client\n createdAt\n id\n state\n }\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n", - "variables": "{\n \"after\": null,\n \"before\": null,\n \"first\": null,\n \"last\": null,\n \"filter\": {\n \"state\": {\n \"in\": [\"PROCESSING\", \"PENDING\", \"APPROVED\", \"FINALIZED\"]\n },\n \"finalizationReason\": {\n \"notIn\": [\"REVOKED\"]\n }\n }\n}\n" - } - }, - "url": { - "raw": "{{RafikiAuthGraphqlHost}}/graphql", - "host": [ - "{{RafikiAuthGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Revoke Grant", - "id": "64389b1d-ebac-4f85-9e6a-e80b990949d0", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation revokeGrant($input: RevokeGrantInput!) {\n revokeGrant(input: $input) {\n code\n message\n success\n }\n}", - "variables": "{\n \"input\": {\n \"grantId\": \"e6684d05-6cc5-4a0e-a490-7ed05923fa89\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiAuthGraphqlHost}}/graphql", - "host": [ - "{{RafikiAuthGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - } - ], - "id": "11508f2c-5236-4b82-8976-0d1ab4acdbfc" - }, - { - "name": "Open Payments APIs", - "item": [ - { - "name": "Wallet Address", - "item": [ - { - "name": "Get a Wallet Address", - "event": [ - { - "listen": "test", - "script": { - "id": "6ab5eb8b-0600-438b-85f7-a551e1e3bced", - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "const body = pm.response.json();", - "pm.environment.set(\"receiverAssetCode\", body?.assetCode)", - "pm.environment.set(\"receiverAssetScale\", body?.assetScale)", - "", - "const authUrl = url.parse(body?.authServer)", - "if (", - " authUrl.hostname.includes('cloud-nine-wallet') || ", - " authUrl.hostname.includes('happy-life-bank')", - "){", - " const port = authUrl.hostname.includes('cloud-nine-wallet') ", - " ? authUrl.port", - " : Number(authUrl.port) + 1000", - " pm.environment.set(\"receiverOpenPaymentsAuthHost\", authUrl.protocol + '//localhost:' + port );", - "} else {", - " pm.environment.set(\"receiverOpenPaymentsAuthHost\", body?.authServer);", - "}" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "d995c69c-6797-4a59-92da-a6172785f541", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}" - ], - "type": "text/javascript" - } - } - ], - "id": "f4201fcf-3092-441f-8d54-1f9a8a55bdc0", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{receiverWalletAddress}}", - "host": [ - "{{receiverWalletAddress}}" - ] - } - }, - "response": [] - }, - { - "name": "Get Wallet Address Keys", - "event": [ - { - "listen": "prerequest", - "script": { - "id": "56d361b0-6b15-4126-9252-8400a389e57b", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}" - ], - "type": "text/javascript" - } - } - ], - "id": "841e3c01-87b1-4f6b-b750-d3c85130aa56", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{receiverWalletAddress}}/jwks.json", - "host": [ - "{{receiverWalletAddress}}" - ], - "path": [ - "jwks.json" - ] - } - }, - "response": [] - } - ], - "id": "eb2dba4c-bb3b-4e31-89d1-17e24a158638" - }, - { - "name": "Incoming Payments", - "item": [ - { - "name": "Create Incoming Payment", - "event": [ - { - "listen": "prerequest", - "script": { - "id": "1cc27496-656f-4510-b0e7-d8dee1fcfe67", - "exec": [ - "pm.environment.set(\"tomorrow\", (new Date(new Date().setDate(new Date().getDate() + 1))).toISOString());", - "", - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "id": "1255b160-fd99-4291-bbae-4e8dc51a566e", - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "const body = pm.response.json();", - "pm.environment.set(\"incomingPaymentId\", body.id.split(\"/\").pop());", - "" - ], - "type": "text/javascript" - } - } - ], - "id": "cdb889f0-90c3-4913-abed-b2848aa64b94", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"walletAddress\": \"{{clientWalletAddress}}\",\n \"incomingAmount\": {\n \"value\": \"2000\",\n \"assetCode\": \"USD\",\n \"assetScale\": 2\n },\n \"expiresAt\": \"{{tomorrow}}\",\n \"metadata\": {\n \"description\": \"Incoming Payment on Own Account\",\n \"externalRef\": \"INV-001\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{receiverOpenPaymentsHost}}/incoming-payments", - "host": [ - "{{receiverOpenPaymentsHost}}" - ], - "path": [ - "incoming-payments" - ] - } - }, - "response": [] - }, - { - "name": "Get Incoming Payment", - "event": [ - { - "listen": "test", - "script": { - "id": "de09e9f3-77e5-4796-937f-9949c27e3714", - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "fa238f32-5d3f-40bd-b5e8-8c81f5525378", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "23cfe940-068d-422c-928e-7c567e0ba4e1", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "url": { - "raw": "{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}", - "host": [ - "{{receiverOpenPaymentsHost}}" - ], - "path": [ - "incoming-payments", - "{{incomingPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "Get Incoming Payment (Unauthenticated)", - "event": [ - { - "listen": "test", - "script": { - "id": "836507d4-1c20-4b2c-ad6f-b374cb57d305", - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "96baae4b-4a6a-4265-b1f5-29d0f16e11ad", - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "id": "e53e9769-1a49-4d1d-a1f8-a94e54e4a4fd", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}", - "disabled": true - }, - { - "key": "Host", - "value": "happy-life-bank-backend" - } - ], - "url": { - "raw": "{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}", - "host": [ - "{{receiverOpenPaymentsHost}}" - ], - "path": [ - "incoming-payments", - "{{incomingPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "List Incoming Payments", - "event": [ - { - "listen": "test", - "script": { - "id": "b0545e02-d368-48b3-93d8-e8b0ac18e141", - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "bfdb9c3d-2a31-49f6-a835-e007bd2b09d2", - "exec": [ - "request.url = request.url", - " .replace(/{{(receiverWalletAddress)}}/g, (_, key) => pm.environment.get(key))", - " .replace(/http:\\/\\/localhost:([3,4])000/g, (_, key) =>", - " key === '3'", - " ? 'https://' + pm.environment.get('host3000')", - " : 'https://' + pm.environment.get('host4000')", - " )", - "console.log(request.url)", - "", - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))", - "", - "pm.request.url.query.idx(2).value = pm.request.url.query.idx(2).value", - " .replace(/{{([A-Za-z]\\w+)}}/g, (_, key) => pm.environment.get(key))", - " .replace(/http:\\/\\/localhost:([3,4])000/g, (_, key) =>", - " key === '3'", - " ? 'https://' + pm.environment.get('host3000')", - " : 'https://' + pm.environment.get('host4000')", - " )", - "" - ], - "type": "text/javascript" - } - } - ], - "id": "d318aae2-aae6-4a06-89ad-c56255e7dca0", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "url": { - "raw": "{{receiverOpenPaymentsHost}}/incoming-payments?first=10&wallet-address={{receiverWalletAddress}}", - "host": [ - "{{receiverOpenPaymentsHost}}" - ], - "path": [ - "incoming-payments" - ], - "query": [ - { - "key": "first", - "value": "10" - }, - { - "key": "cursor", - "value": "ea3bf38f-2719-4473-a0f7-4ba967d1d81b", - "disabled": true - }, - { - "key": "wallet-address", - "value": "{{receiverWalletAddress}}" - } - ] - } - }, - "response": [] - }, - { - "name": "Complete Incoming Payment", - "event": [ - { - "listen": "prerequest", - "script": { - "id": "33b93c8f-c93a-4475-95d8-f30d5f9f458d", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "c9e4b4a3-ead1-4422-b2cf-aef6a9b90a39", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - }, - { - "key": "Host", - "value": "happy-life-bank-backend", - "disabled": true - } - ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}/complete", - "host": [ - "{{receiverOpenPaymentsHost}}" - ], - "path": [ - "incoming-payments", - "{{incomingPaymentId}}", - "complete" - ] - } - }, - "response": [] - } - ], - "id": "bf50a9e8-4c18-4a40-beab-650d5cd91f24" - }, - { - "name": "Quotes", - "item": [ - { - "name": "Create Quote", - "event": [ - { - "listen": "test", - "script": { - "id": "b506250c-95d0-464e-93fe-2dea5070c404", - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "const body = pm.response.json();", - "pm.environment.set(\"quoteId\", body.id.split(\"/\").pop());", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "622fcc84-1b0e-4694-9e1b-77484f866e22", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "a1787244-2b57-4a04-8b24-c3dca6ab75cd", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"receiver\": \"{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}\",\n \"walletAddress\": \"{{senderWalletAddress}}\",\n \"debitAmount\": {\n \"value\": \"1000\",\n \"assetCode\": \"{{receiverAssetCode}}\",\n \"assetScale\": {{receiverAssetScale}}\n },\n \"method\": \"ilp\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{senderOpenPaymentsHost}}/quotes", - "host": [ - "{{senderOpenPaymentsHost}}" - ], - "path": [ - "quotes" - ] - } - }, - "response": [] - }, - { - "name": "Get Quote", - "event": [ - { - "listen": "test", - "script": { - "id": "d2fa6828-fdd6-4188-991b-bb927172952b", - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "2a070a42-071c-4456-b386-d870e96d871e", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "a559e657-9199-4469-92a6-0307ddaed245", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - }, - { - "key": "Host", - "value": "cloud-nine-wallet-backend", - "disabled": true - } - ], - "url": { - "raw": "{{senderOpenPaymentsHost}}/quotes/{{quoteId}}", - "host": [ - "{{senderOpenPaymentsHost}}" - ], - "path": [ - "quotes", - "{{quoteId}}" - ] - } - }, - "response": [] - } - ], - "id": "dfd44185-08c3-4162-b37f-4f5504f2a51d" - }, - { - "name": "Outgoing Payments", - "item": [ - { - "name": "Create Outgoing Payment", - "event": [ - { - "listen": "prerequest", - "script": { - "id": "a923fd64-cd17-4430-9939-81e7c5d3ed09", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "id": "11aea09d-d63a-4e6a-8439-bb74ba444810", - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "const body = pm.response.json();", - "pm.environment.set(\"outgoingPaymentId\", body.id.split(\"/\").pop());", - "" - ], - "type": "text/javascript" - } - } - ], - "id": "7256c6b4-7317-4792-8884-492f5d423296", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"walletAddress\": {{senderWalletAddress}},\n \"quoteId\": \"{{senderOpenPaymentsHost}}/quotes/{{quoteId}}\",\n \"metadata\": {\n \"description\": \"yolo\",\n \"externalRef\": \"INV-001\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{senderOpenPaymentsHost}}/outgoing-payments", - "host": [ - "{{senderOpenPaymentsHost}}" - ], - "path": [ - "outgoing-payments" - ] - } - }, - "response": [] - }, - { - "name": "Get Outgoing Payment", - "event": [ - { - "listen": "test", - "script": { - "id": "e933113e-9e67-4502-a821-cec5a159d074", - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "234f93c0-c1a9-455e-b772-e36e1a7ef0d4", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "1361b3c1-6e86-4b46-9112-f09fadd2137d", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "url": { - "raw": "{{senderOpenPaymentsHost}}/outgoing-payments/{{outgoingPaymentId}}", - "host": [ - "{{senderOpenPaymentsHost}}" - ], - "path": [ - "outgoing-payments", - "{{outgoingPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "List Outgoing Payments", - "event": [ - { - "listen": "test", - "script": { - "id": "0e684915-6a26-44ad-81b9-df2fad9ae96f", - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "dc5e8d6a-7834-405f-8198-465bb5795824", - "exec": [ - "request.url = request.url", - " .replace(/{{(senderWalletAddress)}}/g, (_, key) => pm.environment.get(key))", - " .replace(/http:\\/\\/localhost:([3,4])000/g, (_, key) =>", - " key === '3'", - " ? 'https://' + pm.environment.get('host3000')", - " : 'https://' + pm.environment.get('host4000')", - " )", - "console.log(request.url)", - "", - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))", - "", - "pm.request.url.query.idx(2).value = pm.request.url.query.idx(2).value", - " .replace(/{{([A-Za-z]\\w+)}}/g, (_, key) => pm.environment.get(key))", - " .replace(/http:\\/\\/localhost:([3,4])000/g, (_, key) =>", - " key === '3'", - " ? 'https://' + pm.environment.get('host3000')", - " : 'https://' + pm.environment.get('host4000')", - " )", - "" - ], - "type": "text/javascript" - } - } - ], - "id": "2f554db1-dde0-4e12-a8fc-b0c94efdc05f", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "url": { - "raw": "{{senderOpenPaymentsHost}}/outgoing-payments?first=2&wallet-address={{senderWalletAddress}}", - "host": [ - "{{senderOpenPaymentsHost}}" - ], - "path": [ - "outgoing-payments" - ], - "query": [ - { - "key": "first", - "value": "2" - }, - { - "key": "cursor", - "value": "ea3bf38f-2719-4473-a0f7-4ba967d1d81b", - "disabled": true - }, - { - "key": "wallet-address", - "value": "{{senderWalletAddress}}" - } - ] - } - }, - "response": [] - } - ], - "id": "f42e954e-9b66-4739-8aad-f1133f209cdb" - } - ], - "id": "7df0dc22-d369-4064-9447-0a60a70d2231" - }, - { - "name": "Open Payments Auth APIs", - "item": [ - { - "name": "Grants", - "item": [ - { - "name": "Grant Request", - "event": [ - { - "listen": "test", - "script": { - "id": "36b4bb00-8fe7-451a-b6b7-44ef0e698fc4", - "exec": [ - "const body = pm.response.json();", - "pm.environment.set(\"accessToken\", body?.access_token?.value);", - "pm.environment.set(\"continueToken\", body.continue.access_token.value);", - "pm.environment.set(\"continueId\", body.continue.uri.split(\"/\").pop());", - "pm.environment.set(\"tokenId\", body.access_token.manage.split('/').pop())" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "00122ab8-e9b8-4ba7-84d9-26002667994f", - "exec": [ - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "b1ec3d86-ed15-4d8e-8d61-52187f9861de", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"access_token\": {\n \"access\": [\n {\n \"type\": \"quote\",\n \"actions\": [\n \"create\", \"read\"\n ]\n },\n {\n \"type\": \"outgoing-payment\",\n \"actions\": [\n \"create\", \"read\", \"list\"\n ],\n \"identifier\": \"{{senderWalletAddress}}\",\n \"limits\": {\n \"debitAmount\": {\n \"value\": \"8000\",\n \"assetCode\": \"USD\",\n \"assetScale\": 2\n },\n \"receiveAmount\": {\n \"value\": \"8000\",\n \"assetCode\": \"USD\",\n \"assetScale\": 2\n }\n }\n }\n ]\n },\n \"client\": \"{{clientWalletAddress}}\",\n \"interact\": {\n \"start\": [\n \"redirect\"\n ],\n \"finish\": {\n \"method\": \"redirect\",\n \"uri\": \"http://localhost:3030/mock-idp/fake-client\",\n \"nonce\": \"123\"\n }\n }\n}\n", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{receiverOpenPaymentsAuthHost}}/", - "host": [ - "{{receiverOpenPaymentsAuthHost}}" - ], - "path": [ - "" - ] - } - }, - "response": [] - }, - { - "name": "Continuation Request", - "event": [ - { - "listen": "prerequest", - "script": { - "id": "df2f3bb0-7ab7-4a6b-aed8-a4d230622380", - "exec": [ - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "id": "924eb4d8-82ca-4926-b3bb-0d4269d6cf77", - "exec": [ - "const body = pm.response.json();", - "pm.environment.set(\"accessToken\", body.access_token.value);", - "pm.environment.set(\"tokenId\", body.access_token.manage.split('/').pop())" - ], - "type": "text/javascript" - } - } - ], - "id": "634fc4f7-b633-4354-94ff-6049a4f65558", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{continueToken}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"interact_ref\": \"fdfa9202-3e68-4c2a-8049-25135704a1cb\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{receiverOpenPaymentsAuthHost}}/continue/{{continueId}}", - "host": [ - "{{receiverOpenPaymentsAuthHost}}" - ], - "path": [ - "continue", - "{{continueId}}" - ] - } - }, - "response": [] - } - ], - "id": "91779d19-7d34-49a2-b1a9-27fadb99fde9" - }, - { - "name": "Tokens", - "item": [ - { - "name": "Rotate Access Token", - "event": [ - { - "listen": "prerequest", - "script": { - "id": "0c25f468-f385-4c4d-ae14-858056de4e8a", - "exec": [ - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "id": "39458cb2-2a4e-4ac8-b84f-8c3b09e98e20", - "exec": [ - "const body = pm.response.json();", - "pm.environment.set(\"accessToken\", body.access_token.value);", - "pm.environment.set(\"tokenId\", body.access_token.manage.split('/').pop())" - ], - "type": "text/javascript" - } - } - ], - "id": "26abda6c-a70d-4424-b663-60ba9df34c7c", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}", - "type": "text" - } - ], - "url": { - "raw": "{{receiverOpenPaymentsAuthHost}}/token/{{tokenId}}", - "host": [ - "{{receiverOpenPaymentsAuthHost}}" - ], - "path": [ - "token", - "{{tokenId}}" - ] - } - }, - "response": [] - }, - { - "name": "Revoke Access Token", - "event": [ - { - "listen": "prerequest", - "script": { - "id": "752de022-3dfb-4e44-9d32-117b6c2d33ae", - "exec": [ - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "68a5198d-0a96-4021-8e06-c26ef2d12b09", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "DELETE", - "header": [], - "url": { - "raw": "{{receiverOpenPaymentsAuthHost}}/token/{{tokenId}}", - "host": [ - "{{receiverOpenPaymentsAuthHost}}" - ], - "path": [ - "token", - "{{tokenId}}" - ] - } - }, - "response": [] - } - ], - "id": "48f943f1-abdf-4ad8-8470-a3525c8a869d" - } - ], - "id": "4e2e58bf-9087-49bc-99f8-0d6ea5bc8ae1" - }, - { - "name": "Examples", - "item": [ - { - "name": "Open Payments", - "item": [ - { - "name": "Get sender wallet address", - "event": [ - { - "listen": "test", - "script": { - "id": "6ab5eb8b-0600-438b-85f7-a551e1e3bced", - "exec": [ - "const url = require('url')", - "", - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "const body = pm.response.json();", - "pm.environment.set(\"senderAssetCode\", body?.assetCode)", - "pm.environment.set(\"senderAssetScale\", body?.assetScale)", - "", - "const authUrl = url.parse(body?.authServer)", - "if (", - " authUrl.hostname.includes('cloud-nine-wallet') || ", - " authUrl.hostname.includes('happy-life-bank')", - "){", - " const port = authUrl.hostname.includes('cloud-nine-wallet') ", - " ? authUrl.port", - " : Number(authUrl.port) + 1000", - " pm.environment.set(\"senderOpenPaymentsAuthHost\", authUrl.protocol + '//localhost:' + port );", - "} else {", - " pm.environment.set(\"senderOpenPaymentsAuthHost\", body?.authServer);", - "}", - "", - "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "30292208-a420-4e62-ae68-15720eb0862c", - "exec": [ - "const url = require('url')", - "", - "const requestUrl = url.parse(request.url", - " .replace(/{{([A-Za-z]\\w+)}}/g, (_, key) => pm.environment.get(key)))", - "", - "pm.environment.set(\"senderOpenPaymentsHost\", requestUrl.protocol + '//' + requestUrl.host);", - "", - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}" - ], - "type": "text/javascript" - } - } - ], - "id": "cb0d3229-10f6-4bdc-9bb7-dc46a55dd85d", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{senderWalletAddress}}", - "host": [ - "{{senderWalletAddress}}" - ] - } - }, - "response": [] - }, - { - "name": "Get receiver wallet address", - "event": [ - { - "listen": "test", - "script": { - "id": "6ab5eb8b-0600-438b-85f7-a551e1e3bced", - "exec": [ - "const url = require('url')", - "", - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "const body = pm.response.json();", - "pm.environment.set(\"receiverAssetCode\", body?.assetCode)", - "pm.environment.set(\"receiverAssetScale\", body?.assetScale)", - "", - "const authUrl = url.parse(body?.authServer)", - "if (", - " authUrl.hostname.includes('cloud-nine-wallet') || ", - " authUrl.hostname.includes('happy-life-bank')", - "){", - " const port = authUrl.hostname.includes('cloud-nine-wallet') ", - " ? authUrl.port", - " : Number(authUrl.port) + 1000", - " pm.environment.set(\"receiverOpenPaymentsAuthHost\", authUrl.protocol + '//localhost:' + port );", - "} else {", - " pm.environment.set(\"receiverOpenPaymentsAuthHost\", body?.authServer);", - "}", - "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "30292208-a420-4e62-ae68-15720eb0862c", - "exec": [ - "const url = require('url')", - "", - "const requestUrl = url.parse(request.url", - " .replace(/{{([A-Za-z]\\w+)}}/g, (_, key) => pm.environment.get(key)))", - "", - "pm.environment.set(\"receiverOpenPaymentsHost\", requestUrl.protocol + '//' + requestUrl.host);", - "", - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}" - ], - "type": "text/javascript" - } - } - ], - "id": "446306f2-5ccd-451f-a2f3-202fa283bcf7", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{receiverWalletAddress}}", - "host": [ - "{{receiverWalletAddress}}" - ] - } - }, - "response": [] - }, - { - "name": "Grant Request Incoming Payment", - "event": [ - { - "listen": "test", - "script": { - "id": "5df59811-f461-4288-856d-cea86377317d", - "exec": [ - "const body = pm.response.json();", - "pm.environment.set(\"accessToken\", body?.access_token?.value);", - "pm.environment.set(\"continueToken\", body.continue.access_token.value);", - "pm.environment.set(\"continueId\", body.continue.uri.split(\"/\").pop());", - "pm.environment.set(\"tokenId\", body.access_token.manage.split('/').pop())" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "bd902901-7842-42e2-876b-4ee0df449544", - "exec": [ - "eval(pm.environment.get('preRequestSignatures'))", - "" - ], - "type": "text/javascript" - } - } - ], - "id": "a4667ab2-7003-48e0-a585-d69236e5e6b8", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"access_token\": {\n \"access\": [\n {\n \"type\": \"incoming-payment\",\n \"actions\": [\n \"create\", \"read\", \"list\", \"complete\"\n ]\n }\n ]\n },\n \"client\": \"{{clientWalletAddress}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{receiverOpenPaymentsAuthHost}}/", - "host": [ - "{{receiverOpenPaymentsAuthHost}}" - ], - "path": [ - "" - ] - } - }, - "response": [] - }, - { - "name": "Create Incoming Payment", - "event": [ - { - "listen": "prerequest", - "script": { - "id": "9f41985b-eb00-4f2d-9c46-1cf76c1f80b0", - "exec": [ - "pm.environment.set(\"tomorrow\", (new Date(new Date().setDate(new Date().getDate() + 1))).toISOString());", - "", - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "id": "af700471-1ce1-4b8a-872b-5d7e7b65919c", - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "const body = pm.response.json();", - "pm.environment.set(\"incomingPaymentId\", body.id.split(\"/\").pop());", - "" - ], - "type": "text/javascript" - } - } - ], - "id": "94d76486-1c66-4377-917d-ab78ef51b13d", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"walletAddress\": \"{{receiverWalletAddress}}\",\n \"incomingAmount\": {\n \"value\": \"100\",\n \"assetCode\": \"{{receiverAssetCode}}\",\n \"assetScale\": {{receiverAssetScale}}\n },\n \"expiresAt\": \"{{tomorrow}}\",\n \"metadata\": {\n \"description\": \"Free Money!\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{receiverOpenPaymentsHost}}/incoming-payments", - "host": [ - "{{receiverOpenPaymentsHost}}" - ], - "path": [ - "incoming-payments" - ] - } - }, - "response": [] - }, - { - "name": "Grant Request Quote", - "event": [ - { - "listen": "test", - "script": { - "id": "382597ac-6d72-4318-830a-d6c22795da2c", - "exec": [ - "const body = pm.response.json();", - "pm.environment.set(\"accessToken\", body?.access_token?.value);", - "pm.environment.set(\"continueToken\", body.continue.access_token.value);", - "pm.environment.set(\"continueId\", body.continue.uri.split(\"/\").pop());", - "pm.environment.set(\"tokenId\", body.access_token.manage.split('/').pop())" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "0244823d-e3eb-4775-a60a-b0e20404b907", - "exec": [ - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "2349404f-91af-4a0a-a6db-be3852697763", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"access_token\": {\n \"access\": [\n {\n \"type\": \"quote\",\n \"actions\": [\n \"create\", \"read\"\n ]\n }\n ]\n },\n \"client\": \"{{clientWalletAddress}}\"\n}\n", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{senderOpenPaymentsAuthHost}}/", - "host": [ - "{{senderOpenPaymentsAuthHost}}" - ], - "path": [ - "" - ] - } - }, - "response": [] - }, - { - "name": "Create Quote", - "event": [ - { - "listen": "test", - "script": { - "id": "5b02c3c1-cc52-4772-900c-6dd24f2a6e46", - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "const body = pm.response.json();", - "pm.environment.set(\"quoteId\", body.id.split(\"/\").pop());", - "pm.environment.set(\"quoteDebitAmount\", JSON.stringify(body.debitAmount))", - "pm.environment.set(\"quoteReceiveAmount\", JSON.stringify(body.receiveAmount))", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "d2b13a64-4450-43b6-bd2d-212b99f7132f", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "4434550a-a0dc-4951-aec9-dd3212a6df33", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"walletAddress\": \"{{senderWalletAddress}}\",\n \"receiver\": \"{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}\",\n \"method\": \"ilp\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{senderOpenPaymentsHost}}/quotes", - "host": [ - "{{senderOpenPaymentsHost}}" - ], - "path": [ - "quotes" - ] - } - }, - "response": [] - }, - { - "name": "Grant Request Outgoing Payment", - "event": [ - { - "listen": "test", - "script": { - "id": "1ddabc8a-bdf4-4327-a426-40547ac9f16b", - "exec": [ - "const body = pm.response.json();", - "pm.environment.set(\"accessToken\", body?.access_token?.value);", - "pm.environment.set(\"continueToken\", body.continue.access_token.value);", - "pm.environment.set(\"continueId\", body.continue.uri.split(\"/\").pop());", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "44827563-e7dc-4ab9-a1e4-a741fba7ba82", - "exec": [ - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "97b7d4e5-aed0-49fc-8a04-f76ed20a8fc8", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"access_token\": {\n \"access\": [\n {\n \"type\": \"outgoing-payment\",\n \"actions\": [\n \"create\", \"read\", \"list\"\n ],\n \"identifier\": \"{{senderWalletAddress}}\",\n \"limits\": {\n \"debitAmount\": {{quoteDebitAmount}},\n \"receiveAmount\": {{quoteReceiveAmount}}\n }\n }\n ]\n },\n \"client\": \"{{clientWalletAddress}}\",\n \"interact\": {\n \"start\": [\n \"redirect\"\n ],\n \"finish\": {\n \"method\": \"redirect\",\n \"uri\": \"https://example.com\",\n \"nonce\": \"456\"\n }\n }\n}\n", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{senderOpenPaymentsAuthHost}}/", - "host": [ - "{{senderOpenPaymentsAuthHost}}" - ], - "path": [ - "" - ] - } - }, - "response": [] - }, - { - "name": "Continuation Request", - "event": [ - { - "listen": "test", - "script": { - "id": "cbd68480-1a0a-4de4-84cb-37b53dce4bb0", - "exec": [ - "const body = pm.response.json();", - "pm.environment.set(\"accessToken\", body.access_token.value);", - "pm.environment.set(\"tokenId\", body.access_token.manage.split('/').pop())" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "a576b935-3c6b-41ee-a563-fd46d26f9027", - "exec": [ - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "e008e270-6541-4210-ac01-cdbd56f3c2ef", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{continueToken}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"interact_ref\": \"6d519566-234f-4c2e-b56f-6d4a305fc067\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{senderOpenPaymentsAuthHost}}/continue/{{continueId}}", - "host": [ - "{{senderOpenPaymentsAuthHost}}" - ], - "path": [ - "continue", - "{{continueId}}" - ] - } - }, - "response": [] - }, - { - "name": "Create Outgoing Payment", - "event": [ - { - "listen": "prerequest", - "script": { - "id": "88dd263b-e89f-43ed-b116-1610d32a1c24", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "id": "0368224e-1d79-43f1-9320-d58bb1ce8885", - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "const body = pm.response.json();", - "pm.environment.set(\"outgoingPaymentId\", body.id.split(\"/\").pop());", - "" - ], - "type": "text/javascript" - } - } - ], - "id": "7fecea51-7730-45cd-b91f-0fe1a4c7c908", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"walletAddress\": \"{{senderWalletAddress}}\",\n \"quoteId\": \"{{senderWalletAddress}}/quotes/{{quoteId}}\",\n \"metadata\": {\n \"description\": \"Free Money!\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{senderOpenPaymentsHost}}/outgoing-payments", - "host": [ - "{{senderOpenPaymentsHost}}" - ], - "path": [ - "outgoing-payments" - ] - } - }, - "response": [] - }, - { - "name": "Get Outgoing Payment", - "event": [ - { - "listen": "test", - "script": { - "id": "fd38abe6-e8aa-4aaa-8eeb-6ae57a505fc7", - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "e8c3c9c1-5528-4d2b-9fe1-a20bd6842e08", - "exec": [ - "if(pm.environment.get('preRequestHost')){", - " eval(pm.environment.get('preRequestHost'))", - "}", - "eval(pm.environment.get('preRequestSignatures'))" - ], - "type": "text/javascript" - } - } - ], - "id": "cf41c13d-c319-4e66-89ee-f6a81a2ee73c", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "GNAP {{accessToken}}" - } - ], - "url": { - "raw": "{{senderOpenPaymentsHost}}/outgoing-payments/{{outgoingPaymentId}}", - "host": [ - "{{senderOpenPaymentsHost}}" - ], - "path": [ - "outgoing-payments", - "{{outgoingPaymentId}}" - ] - } - }, - "response": [] - } - ], - "id": "48f45cd9-c4dc-433d-b8b1-08fce2815e54" - }, - { - "name": "Admin API - only locally", - "item": [ - { - "name": "Peer-to-Peer Payment", - "item": [ - { - "name": "Create Receiver (remote Incoming Payment)", - "event": [ - { - "listen": "test", - "script": { - "id": "7dedf74a-2eb5-49dd-90c6-f2707b43ff8b", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"receiverId\", body.data.createReceiver.receiver.id);", - "pm.expect(pm.environment.get(\"receiverId\")).to.be.a('string');" - ], - "type": "text/javascript" - } - } - ], - "id": "76d1b135-f6a2-4211-b4dc-6bd1c3e4e895", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateReceiver($input: CreateReceiverInput!) {\n createReceiver(input: $input) {\n code\n message\n receiver {\n completed\n createdAt\n expiresAt\n metadata\n id\n incomingAmount {\n assetCode\n assetScale\n value\n }\n walletAddressUrl\n receivedAmount {\n assetCode\n assetScale\n value\n }\n updatedAt\n }\n success\n }\n}", - "variables": "{\n \"input\": {\n \"metadata\": {\n \"description\": \"For lunch!\"\n },\n \"incomingAmount\": {\n \"assetCode\": \"USD\",\n \"assetScale\": 2,\n \"value\": 500\n },\n \"walletAddressUrl\": \"https://happy-life-bank-backend/accounts/pfry\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Quote", - "event": [ - { - "listen": "test", - "script": { - "id": "ab40891a-2e51-485d-85a6-1258ae62ae77", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"quoteId\", body.data.createQuote.quote.id);", - "pm.expect(pm.environment.get(\"quoteId\")).to.be.a('string');" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "9a79a4d2-cc4b-4e62-8972-776be98fba47", - "exec": [ - "", - "const getWalletAddressesQuery = `", - "query GetWalletAddresses {", - " walletAddresses {", - " edges {", - " cursor", - " node {", - " id", - " publicName", - " url", - " }", - " }", - " }", - "}`", - "", - "const postRequest = {", - " url: `${pm.environment.get(\"RafikiGraphqlHost\")}/graphql`,", - " method: 'POST',", - " body: {", - " mode: 'graphql',", - " graphql: {", - " query:getWalletAddressesQuery", - " }", - " }", - "};", - "", - "", - "pm.sendRequest(postRequest, (error, response) => {", - " const body = response.json();", - " const gfranklinWalletAddressId = body.data.walletAddresses.edges.map(e => e.node).find(node => node.publicName === 'Grace Franklin')?.id", - "", - " pm.environment.set(\"gfranklinWalletAddressId\", gfranklinWalletAddressId)", - "});" - ], - "type": "text/javascript" - } - } - ], - "id": "ecdf8913-7153-4a48-bd92-709cacf42b9e", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateQuote($input: CreateQuoteInput!) {\n createQuote(input: $input) {\n code\n message\n quote {\n createdAt\n expiresAt\n highEstimatedExchangeRate\n id\n lowEstimatedExchangeRate\n maxPacketAmount\n minExchangeRate\n walletAddressId\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n }\n }\n}", - "variables": "{\n \"input\": {\n \"walletAddressId\": \"{{gfranklinWalletAddressId}}\",\n \"receiver\": \"{{receiverId}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Outgoing Payment", - "event": [ - { - "listen": "test", - "script": { - "id": "bfd48dd8-38f4-48d9-a621-47498a51078d", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"outgoingPaymentId\", body.data.createOutgoingPayment.payment.id);", - "pm.expect(pm.environment.get(\"outgoingPaymentId\")).to.be.a('string');" - ], - "type": "text/javascript" - } - } - ], - "id": "b91c0436-54f4-4245-b575-e10f6e1ea5e0", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateOutgoingPayment($input: CreateOutgoingPaymentInput!) {\n createOutgoingPayment(input: $input) {\n code\n message\n payment {\n createdAt\n error\n metadata\n id\n walletAddressId\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n sentAmount {\n assetCode\n assetScale\n value\n }\n state\n stateAttempts\n }\n success\n }\n}", - "variables": "{\n \"input\": {\n \"walletAddressId\": \"{{gfranklinWalletAddressId}}\",\n \"quoteId\": \"{{quoteId}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Outgoing Payment", - "id": "23a94dbe-5b18-46d6-81bb-0e5eba580412", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetOutgoingPayment($id: String!) {\noutgoingPayment(id: $id) {\n createdAt\n error\n metadata\n id\n walletAddressId\n quote {\n id\n }\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n sentAmount {\n assetCode\n assetScale\n value\n }\n state\n stateAttempts\n }\n}", - "variables": "{\n \"id\": \"{{outgoingPaymentId}}\"\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - } - ], - "id": "1820d241-9269-47c5-ad03-00b5ad04d186" - }, - { - "name": "Peer-to-Peer Cross Currency Payment", - "item": [ - { - "name": "Create Receiver (remote Incoming Payment)", - "event": [ - { - "listen": "test", - "script": { - "id": "a6ff97f8-f239-4d65-b062-abd8ec7f8869", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"receiverId\", body.data.createReceiver.receiver.id);", - "pm.expect(pm.environment.get(\"receiverId\")).to.be.a('string');" - ], - "type": "text/javascript" - } - } - ], - "id": "1f1424ed-ea1d-4f77-a9e8-43d75bceb133", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateReceiver($input: CreateReceiverInput!) {\n createReceiver(input: $input) {\n code\n message\n receiver {\n completed\n createdAt\n expiresAt\n metadata\n id\n incomingAmount {\n assetCode\n assetScale\n value\n }\n walletAddressUrl\n receivedAmount {\n assetCode\n assetScale\n value\n }\n updatedAt\n }\n success\n }\n}", - "variables": "{\n \"input\": {\n \"metadata\": {\n \"description\": \"cross-currency\"\n },\n \"incomingAmount\": {\n \"assetCode\": \"EUR\",\n \"assetScale\": 2,\n \"value\": 500\n },\n \"walletAddressUrl\": \"https://happy-life-bank-backend/accounts/lars\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Quote", - "event": [ - { - "listen": "test", - "script": { - "id": "72013d98-f06d-4658-9770-03200cb7112b", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"quoteId\", body.data.createQuote.quote.id);", - "pm.expect(pm.environment.get(\"quoteId\")).to.be.a('string');" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "id": "cc3ebb64-835d-4cd0-8e0f-4369049650de", - "exec": [ - "", - "const getWalletAddressesQuery = `", - "query GetWalletAddresses {", - " walletAddresses {", - " edges {", - " cursor", - " node {", - " id", - " publicName", - " url", - " }", - " }", - " }", - "}`", - "", - "const postRequest = {", - " url: `${pm.environment.get(\"RafikiGraphqlHost\")}/graphql`,", - " method: 'POST',", - " body: {", - " mode: 'graphql',", - " graphql: {", - " query:getWalletAddressesQuery", - " }", - " }", - "};", - "", - "", - "pm.sendRequest(postRequest, (error, response) => {", - " const body = response.json();", - " const gfranklinWalletAddressId = body.data.walletAddresses.edges.map(e => e.node).find(node => node.publicName === 'Grace Franklin')?.id", - "", - " pm.environment.set(\"gfranklinWalletAddressId\", gfranklinWalletAddressId)", - "});" - ], - "type": "text/javascript" - } - } - ], - "id": "7071aae0-a2d4-4b96-9eea-b9de0a7d3f6b", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateQuote($input: CreateQuoteInput!) {\n createQuote(input: $input) {\n code\n message\n quote {\n createdAt\n expiresAt\n highEstimatedExchangeRate\n id\n lowEstimatedExchangeRate\n maxPacketAmount\n minExchangeRate\n walletAddressId\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n }\n }\n}", - "variables": "{\n \"input\": {\n \"walletAddressId\": \"{{gfranklinWalletAddressId}}\",\n \"receiver\": \"{{receiverId}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Create Outgoing Payment", - "event": [ - { - "listen": "test", - "script": { - "id": "be762c93-0a02-44c6-bc23-e77a3e9d5e92", - "exec": [ - "const body = pm.response.json();", - "", - "pm.environment.set(\"outgoingPaymentId\", body.data.createOutgoingPayment.payment.id);", - "pm.expect(pm.environment.get(\"outgoingPaymentId\")).to.be.a('string');" - ], - "type": "text/javascript" - } - } - ], - "id": "82667b93-88c1-408f-b65c-051245419c54", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation CreateOutgoingPayment($input: CreateOutgoingPaymentInput!) {\n createOutgoingPayment(input: $input) {\n code\n message\n payment {\n createdAt\n error\n metadata\n id\n walletAddressId\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n sentAmount {\n assetCode\n assetScale\n value\n }\n state\n stateAttempts\n }\n success\n }\n}", - "variables": "{\n \"input\": {\n \"walletAddressId\": \"{{gfranklinWalletAddressId}}\",\n \"quoteId\": \"{{quoteId}}\"\n }\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "Get Outgoing Payment", - "id": "821014d9-ae89-4655-8d81-02fd6d379c45", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query GetOutgoingPayment($id: String!) {\noutgoingPayment(id: $id) {\n createdAt\n error\n metadata\n id\n walletAddressId\n quote {\n id\n }\n receiveAmount {\n assetCode\n assetScale\n value\n }\n receiver\n debitAmount {\n assetCode\n assetScale\n value\n }\n sentAmount {\n assetCode\n assetScale\n value\n }\n state\n stateAttempts\n }\n}", - "variables": "{\n \"id\": \"{{outgoingPaymentId}}\"\n}" - } - }, - "url": { - "raw": "{{RafikiGraphqlHost}}/graphql", - "host": [ - "{{RafikiGraphqlHost}}" - ], - "path": [ - "graphql" - ] - } - }, - "response": [] - } - ], - "id": "fc9ea025-1962-49c0-8607-19f46df7d03d" - } - ], - "id": "1e2e9b69-a5ed-4428-9cc7-4f6c484ff0fb" - } - ], - "id": "b5d95158-8dde-456b-9ce5-8dbca3b5983c" - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "id": "d9522e53-e5c6-40dd-bc77-076f1067d185", - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "id": "e4e1d1a9-db5b-4955-9fa0-0692dca69117", - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] -} \ No newline at end of file diff --git a/postman/environments/Local Playground Environment.postman_environment.json b/postman/environments/Local Playground Environment.postman_environment.json deleted file mode 100644 index 06754c932a..0000000000 --- a/postman/environments/Local Playground Environment.postman_environment.json +++ /dev/null @@ -1,285 +0,0 @@ -{ - "id": "49dfbe8f-301c-4482-89d7-39c2abb9a7f8", - "name": "Local Playground Environment", - "values": [ - { - "key": "host3000", - "value": "cloud-nine-wallet-backend", - "type": "default", - "enabled": true - }, - { - "key": "host4000", - "value": "happy-life-bank-backend", - "type": "default", - "enabled": true - }, - { - "key": "clientWalletAddress", - "value": "http://localhost:4000/accounts/pfry", - "type": "default", - "enabled": true - }, - { - "key": "clientPrivateKey", - "value": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1DNENBUUF3QlFZREsyVndCQ0lFSUVxZXptY1BoT0U4Ymt3TitqUXJwcGZSWXpHSWRGVFZXUUdUSEpJS3B6ODgKLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=", - "type": "secret", - "enabled": true - }, - { - "key": "clientKeyId", - "value": "keyid-97a3a431-8ee1-48fc-ac85-70e2f5eba8e5", - "type": "any", - "enabled": true - }, - { - "key": "senderWalletAddress", - "value": "http://localhost:3000/accounts/gfranklin", - "type": "default", - "enabled": true - }, - { - "key": "receiverWalletAddress", - "value": "http://localhost:4000/accounts/asmith", - "type": "default", - "enabled": true - }, - { - "key": "RafikiGraphqlHost", - "value": "http://localhost:3001", - "type": "default", - "enabled": true - }, - { - "key": "RafikiAuthGraphqlHost", - "value": "http://localhost:3003", - "type": "default", - "enabled": true - }, - { - "key": "PeerGraphqlHost", - "value": "http://localhost:4001", - "type": "default", - "enabled": true - }, - { - "key": "PeerAuthGraphqlHost", - "value": "http://localhost:4003", - "type": "default", - "enabled": true - }, - { - "key": "preRequestHost", - "value": "const url = require('url')\n\nconst requestUrl = url.parse(request.url\n .replace(/{{([A-Za-z]\\w+)}}/g, (_, key) => pm.environment.get(key)))\n\nif(requestUrl.hostname === 'localhost'){\n const hostHeader = requestUrl.port === '3000'\n ? pm.environment.get('host3000')\n : pm.environment.get('host4000')\n pm.request.headers.add({ \n key: 'Host', \n value: hostHeader\n })\n request.headers['host'] = hostHeader\n}", - "type": "default", - "enabled": true - }, - { - "key": "preRequestSignatures", - "value": "let requestUrl = request.url\n .replace(/{{([A-Za-z]\\w+)}}/g, (_, key) => pm.environment.get(key))\n .replace(/localhost:([3,4])000/g, (_, key) =>\n key === '3'\n ? pm.environment.get('host3000')\n : pm.environment.get('host4000')\n )\n\nconst requestBody =\n request.method === 'POST' && Object.keys(request.data).length !== 0\n ? request.data\n .replace(/{{([A-Za-z]\\w+)}}/g, (_, key) => pm.environment.get(key))\n .replace(/http:\\/\\/localhost:([3,4])000/g, (_, key) =>\n key === '3'\n ? 'https://' + pm.environment.get('host3000')\n : 'https://' + pm.environment.get('host4000')\n )\n : undefined\npm.request.body.raw = requestBody\n\nconst requestHeaders = JSON.parse(\n JSON.stringify(request.headers).replace(/{{([A-Za-z]\\w+)}}/g, (_, key) =>\n pm.environment.get(key)\n )\n)\n\n// Request Signature Headers\npm.sendRequest(\n {\n url: pm.environment.get('signatureUrl'),\n method: 'POST',\n header: {\n 'content-type': 'application/json'\n },\n body: {\n mode: 'raw',\n raw: JSON.stringify({\n keyId: pm.environment.get('clientKeyId'),\n base64Key: pm.environment.get('clientPrivateKey'),\n request: {\n url: requestUrl,\n method: request.method,\n headers: requestHeaders,\n body: requestBody\n }\n })\n }\n },\n (_, res) => {\n const headers = res.json()\n for (let [key, value] of Object.entries(headers)) {\n pm.request.headers.add({ key, value })\n }\n }\n)\n", - "type": "default", - "enabled": true - }, - { - "key": "signatureUrl", - "value": "https://kxu5d4mr4blcthphxomjlc4xk40rvdsx.lambda-url.eu-central-1.on.aws/", - "type": "any", - "enabled": true - }, - { - "key": "accessToken", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "continueToken", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "continueId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "tomorrow", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "incomingPaymentId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "quoteId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "quoteDebitAmountValue", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "quoteReceiveAmountValue", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "outgoingPaymentId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "receiverId", - "value": "", - "type": "default", - "enabled": true - }, - { - "key": "senderOpenPaymentsHost", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "senderAssetCode", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "senderAssetScale", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "senderOpenPaymentsAuthHost", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "receiverOpenPaymentsHost", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "receiverAssetCode", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "receiverAssetScale", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "receiverOpenPaymentsAuthHost", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "quoteDebitAmount", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "quoteReceiveAmount", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "gfranklinWalletAddressId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "receiverHost", - "value": "http://localhost:4000", - "type": "default", - "enabled": true - }, - { - "key": "senderHost", - "value": "http://localhost:3000", - "type": "default", - "enabled": true - }, - { - "key": "assetId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "peerId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "walletAddressId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "walletAddressUrl", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "createWalletAddressRequest", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "walletAddressKeyId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "uniqueWalletAddress", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "secondWalletAddressId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "tokenId", - "value": "", - "type": "any", - "enabled": true - } - ], - "_postman_variable_scope": "environment", - "_postman_exported_at": "2023-10-26T10:49:56.137Z", - "_postman_exported_using": "Postman/10.19.6" -} \ No newline at end of file diff --git a/postman/environments/Remote Environment.postman_environment.json b/postman/environments/Remote Environment.postman_environment.json deleted file mode 100644 index bc05bec3a3..0000000000 --- a/postman/environments/Remote Environment.postman_environment.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "id": "79daaf18-2b46-47f1-a155-8c3d4ffb008e", - "name": "Remote Environment", - "values": [ - { - "key": "clientWalletAddress", - "value": "https://ilp.rafiki.money/d99f0eee", - "type": "default", - "enabled": true - }, - { - "key": "clientKeyId", - "value": "e9a47ee7-99b3-4656-b85f-12431dbc16b9", - "type": "default", - "enabled": true - }, - { - "key": "clientPrivateKey", - "value": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1DNENBUUF3QlFZREsyVndCQ0lFSUUvMmFwQXduMlJPek5WNWd1L2ltZzdpT05rOWE1Ui9yakFxWVlUWHozZzgKLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQ==", - "type": "secret", - "enabled": true - }, - { - "key": "senderWalletAddress", - "value": "https://ilp.rafiki.money/d99f0eee", - "type": "default", - "enabled": true - }, - { - "key": "receiverWalletAddress", - "value": "https://ilp.rafiki.money/f1475476", - "type": "default", - "enabled": true - }, - { - "key": "signatureUrl", - "value": "https://kxu5d4mr4blcthphxomjlc4xk40rvdsx.lambda-url.eu-central-1.on.aws/", - "type": "default", - "enabled": true - }, - { - "key": "preRequestSignatures", - "value": "let requestUrl = request.url\n .replace(/{{([A-Za-z]\\w+)}}/g, (_, key) => pm.environment.get(key))\n .replace(/localhost:([3,4])000/g, (_, key) =>\n key === '3'\n ? pm.environment.get('host3000')\n : pm.environment.get('host4000')\n )\n\nconst requestBody =\n request.method === 'POST' && Object.keys(request.data).length !== 0\n ? request.data\n .replace(/{{([A-Za-z]\\w+)}}/g, (_, key) => pm.environment.get(key))\n .replace(/http:\\/\\/localhost:([3,4])000/g, (_, key) =>\n key === '3'\n ? 'https://' + pm.environment.get('host3000')\n : 'https://' + pm.environment.get('host4000')\n )\n : undefined\npm.request.body.raw = requestBody\n\nconst requestHeaders = JSON.parse(\n JSON.stringify(request.headers).replace(/{{([A-Za-z]\\w+)}}/g, (_, key) =>\n pm.environment.get(key)\n )\n)\n\n// Request Signature Headers\npm.sendRequest(\n {\n url: pm.environment.get('signatureUrl'),\n method: 'POST',\n header: {\n 'content-type': 'application/json'\n },\n body: {\n mode: 'raw',\n raw: JSON.stringify({\n keyId: pm.environment.get('clientKeyId'),\n base64Key: pm.environment.get('clientPrivateKey'),\n request: {\n url: requestUrl,\n method: request.method,\n headers: requestHeaders,\n body: requestBody\n }\n })\n }\n },\n (_, res) => {\n const headers = res.json()\n for (let [key, value] of Object.entries(headers)) {\n pm.request.headers.add({ key, value })\n }\n }\n)\n", - "type": "default", - "enabled": true - }, - { - "key": "senderOpenPaymentsHost", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "senderOpenPaymentsAuthHost", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "senderAssetCode", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "senderAssetScale", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "receiverOpenPaymentsHost", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "receiverOpenPaymentsAuthHost", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "receiverAssetCode", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "receiverAssetScale", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "accessToken", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "continueToken", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "continueId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "tomorrow", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "incomingPaymentId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "quoteId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "quoteDebitAmount", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "quoteReceiveAmount", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "outgoingPaymentId", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "tokenId", - "value": "", - "type": "any", - "enabled": true - } - ], - "_postman_variable_scope": "environment", - "_postman_exported_at": "2023-10-26T10:50:06.431Z", - "_postman_exported_using": "Postman/10.19.6" -} \ No newline at end of file diff --git a/postman/pre-request-scripts/preRequestHostHeader.js b/postman/pre-request-scripts/preRequestHostHeader.js deleted file mode 100644 index 099f382ffd..0000000000 --- a/postman/pre-request-scripts/preRequestHostHeader.js +++ /dev/null @@ -1,17 +0,0 @@ -const url = require('url') - -const requestUrl = url.parse( - request.url.replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) -) - -if (requestUrl.hostname === 'localhost') { - const hostHeader = - requestUrl.port === '3000' - ? pm.environment.get('host3000') - : pm.environment.get('host4000') - pm.request.headers.add({ - key: 'Host', - value: hostHeader - }) - request.headers['host'] = hostHeader -} diff --git a/postman/pre-request-scripts/preRequestSignatures.js b/postman/pre-request-scripts/preRequestSignatures.js deleted file mode 100644 index 3b90864ebe..0000000000 --- a/postman/pre-request-scripts/preRequestSignatures.js +++ /dev/null @@ -1,55 +0,0 @@ -let requestUrl = request.url - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) - .replace(/localhost:([3,4])000/g, (_, key) => - key === '3' - ? pm.environment.get('host3000') - : pm.environment.get('host4000') - ) - -const requestBody = - request.method === 'POST' && Object.keys(request.data).length !== 0 - ? request.data - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => pm.environment.get(key)) - .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => - key === '3' - ? 'https://' + pm.environment.get('host3000') - : 'https://' + pm.environment.get('host4000') - ) - : undefined -pm.request.body.raw = requestBody - -const requestHeaders = JSON.parse( - JSON.stringify(request.headers).replace(/{{([A-Za-z]\w+)}}/g, (_, key) => - pm.environment.get(key) - ) -) - -// Request Signature Headers -pm.sendRequest( - { - url: pm.environment.get('signatureUrl'), - method: 'POST', - header: { - 'content-type': 'application/json' - }, - body: { - mode: 'raw', - raw: JSON.stringify({ - keyId: pm.environment.get('clientKeyId'), - base64Key: pm.environment.get('clientPrivateKey'), - request: { - url: requestUrl, - method: request.method, - headers: requestHeaders, - body: requestBody - } - }) - } - }, - (_, res) => { - const headers = res.json() - for (let [key, value] of Object.entries(headers)) { - pm.request.headers.add({ key, value }) - } - } -) From 6048314be4b9bbefb3e2c6539942df82eb21ad3f Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Mon, 19 Feb 2024 14:47:17 +0100 Subject: [PATCH 09/16] chore: cleanup --- .github/workflows/postman-publish-main.yml | 18 ----------- .github/workflows/postman-publish-tag.yml | 15 ---------- .github/workflows/postman-publish.yml | 30 ------------------- .postman/api | 4 --- .../api_84fc90ca-3153-4865-8b49-b91218e5d574 | 20 ------------- 5 files changed, 87 deletions(-) delete mode 100644 .github/workflows/postman-publish-main.yml delete mode 100644 .github/workflows/postman-publish-tag.yml delete mode 100644 .github/workflows/postman-publish.yml delete mode 100644 .postman/api delete mode 100644 .postman/api_84fc90ca-3153-4865-8b49-b91218e5d574 diff --git a/.github/workflows/postman-publish-main.yml b/.github/workflows/postman-publish-main.yml deleted file mode 100644 index bf45ea8865..0000000000 --- a/.github/workflows/postman-publish-main.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Publish Postman API version (main) - -on: - push: - branches: - - main - paths: - - 'postman/**' - - '.postman/**' - -jobs: - postman-publish-main: - uses: ./.github/workflows/postman-publish.yml - with: - api-version: 'main' - release-notes: "APIs corresponding to Rafiki main branch" - branch: 'main' - secrets: inherit \ No newline at end of file diff --git a/.github/workflows/postman-publish-tag.yml b/.github/workflows/postman-publish-tag.yml deleted file mode 100644 index 80812b9f95..0000000000 --- a/.github/workflows/postman-publish-tag.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Publish Postman API version (tag) - -on: - push: - tags: - - '*' - -jobs: - postman-publish-main: - uses: ./.github/workflows/postman-publish.yml - with: - api-version: ${{github.ref_name}} - release-notes: "APIs corresponding to Rafiki version ${{github.ref_name}}" - branch: 'main' - secrets: inherit \ No newline at end of file diff --git a/.github/workflows/postman-publish.yml b/.github/workflows/postman-publish.yml deleted file mode 100644 index cd44d2ddeb..0000000000 --- a/.github/workflows/postman-publish.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Publish Postman API version - -on: - workflow_call: - inputs: - api-version: - required: true - type: string - release-notes: - required: true - type: string - branch: - required: true - type: string - -jobs: - postman-publish: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{inputs.branch}} - - name: Install Postman CLI - run: | - curl -o- "https://dl-cli.pstmn.io/install/linux64.sh" | sh - - name: Login to Postman CLI - run: postman login --with-api-key ${{ secrets.POSTMAN_API_KEY }} - - name: Publish Postman API - run: | - postman api publish 84fc90ca-3153-4865-8b49-b91218e5d574 --name ${{ inputs.api-version }} --release-notes ${{ inputs.release-notes }} --collections "postman/collections/Interledger.json" \ No newline at end of file diff --git a/.postman/api b/.postman/api deleted file mode 100644 index 40eb43257e..0000000000 --- a/.postman/api +++ /dev/null @@ -1,4 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY -apis[] = {"apiId":"84fc90ca-3153-4865-8b49-b91218e5d574"} -configVersion = 1.0.0 -type = api diff --git a/.postman/api_84fc90ca-3153-4865-8b49-b91218e5d574 b/.postman/api_84fc90ca-3153-4865-8b49-b91218e5d574 deleted file mode 100644 index 66ff287f22..0000000000 --- a/.postman/api_84fc90ca-3153-4865-8b49-b91218e5d574 +++ /dev/null @@ -1,20 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY -configVersion = 1.0.0 -type = apiEntityData - -[config] -id = 84fc90ca-3153-4865-8b49-b91218e5d574 - -[config.relations] - -[config.relations.collections] -rootDirectory = postman/collections -files[] = {"id":"23674746-92761441-6d0c-4fc6-aa04-73eccf6afd4c","path":"Interledger.json","metaData":{}} - -[config.relations.collections.metaData] - -[config.relations.apiDefinition] -rootDirectory = postman/schemas - -[config.relations.apiDefinition.metaData] -type = openapi:3 From d4d7cfe67c2a29353698946973ff835562e42f47 Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Tue, 20 Feb 2024 10:41:09 +0100 Subject: [PATCH 10/16] chore: renaming and bugfix --- .github/pull_request_template.md | 2 +- ....bru => Create Receiver (remote Incoming Payment).bru} | 2 +- .../Interledger/Rafiki Admin APIs/Create Asset.bru | 2 +- .../Rafiki Admin APIs/Create Or Update Peer By Url.bru | 8 ++++---- ....bru => Create Receiver (remote Incoming Payment).bru} | 2 +- ...nt-.bru => Get Receiver (remote Incoming Payment).bru} | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) rename postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/{Create Receiver -remote Incoming Payment-.bru => Create Receiver (remote Incoming Payment).bru} (95%) rename postman/collections/Interledger/Rafiki Admin APIs/{Create Receiver -remote Incoming Payment-.bru => Create Receiver (remote Incoming Payment).bru} (95%) rename postman/collections/Interledger/Rafiki Admin APIs/{Get Receiver -remote Incoming Payment-.bru => Get Receiver (remote Incoming Payment).bru} (92%) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 53ce02b70f..898b10d38d 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -28,4 +28,4 @@ Checklist items become clickable check boxes once the pull request is created. T - [ ] Tests added/updated - [ ] Documentation added - [ ] Make sure that all checks pass -- [ ] Postman collection updated +- [ ] Bruno collection updated diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver (remote Incoming Payment).bru similarity index 95% rename from postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru rename to postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver (remote Incoming Payment).bru index c2c9a76538..dd7d1f1b3e 100644 --- a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver -remote Incoming Payment-.bru +++ b/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver (remote Incoming Payment).bru @@ -1,5 +1,5 @@ meta { - name: Create Receiver -remote Incoming Payment- + name: Create Receiver (remote Incoming Payment) type: graphql seq: 1 } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru index 11b19427ad..440a862095 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru @@ -42,5 +42,5 @@ body:graphql:vars { script:post-response { const body = res.getBody(); - bru.setEnvVar("assetId", body.data.createAsset.asset.id); + bru.setEnvVar("assetId", body.data.createAsset.asset?.id); } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru index cf09d3dcae..0cc080a15c 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru @@ -40,8 +40,8 @@ body:graphql:vars { } } -tests { - // const body = pm.response.json(); - // - // pm.environment.set("peerId", body.data.createOrUpdatePeerByUrl.peer.id); +script:post-response { + const body = res.getBody(); + + bru.setEnvVar("peerId", body.data.createOrUpdatePeerByUrl?.peer.id); } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver (remote Incoming Payment).bru similarity index 95% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru rename to postman/collections/Interledger/Rafiki Admin APIs/Create Receiver (remote Incoming Payment).bru index 810c12b5bd..2e295579e5 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver -remote Incoming Payment-.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver (remote Incoming Payment).bru @@ -1,5 +1,5 @@ meta { - name: Create Receiver -remote Incoming Payment- + name: Create Receiver (remote Incoming Payment) type: graphql seq: 27 } diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Receiver -remote Incoming Payment-.bru b/postman/collections/Interledger/Rafiki Admin APIs/Get Receiver (remote Incoming Payment).bru similarity index 92% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Receiver -remote Incoming Payment-.bru rename to postman/collections/Interledger/Rafiki Admin APIs/Get Receiver (remote Incoming Payment).bru index 606e2303ce..cf422888b9 100644 --- a/postman/collections/Interledger/Rafiki Admin APIs/Get Receiver -remote Incoming Payment-.bru +++ b/postman/collections/Interledger/Rafiki Admin APIs/Get Receiver (remote Incoming Payment).bru @@ -1,5 +1,5 @@ meta { - name: Get Receiver -remote Incoming Payment- + name: Get Receiver (remote Incoming Payment) type: graphql seq: 28 } From 0a2b715bbddfdfb28dafc1ca2dc49b4da175e513 Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Thu, 22 Feb 2024 12:52:17 +0100 Subject: [PATCH 11/16] chore: update docs --- localenv/README.md | 65 +- localenv/cloud-nine-wallet/seed.yml | 6 +- .../drawio/localenv-architecture.drawio | 212 - .../localenv-architecture.excalidraw | 3833 +++++++++++++++++ localenv/happy-life-bank/seed.yml | 6 +- .../app/lib/parse_config.server.ts | 2 +- .../app/lib/run_seed.server.ts | 2 +- .../public/img/localenv-architecture.png | Bin 91266 -> 301994 bytes .../content/docs/playground/autopeering.md | 4 +- .../src/content/docs/playground/overview.md | 39 +- 10 files changed, 3894 insertions(+), 275 deletions(-) delete mode 100644 localenv/docs/assets/drawio/localenv-architecture.drawio create mode 100644 localenv/docs/assets/excalidraw/localenv-architecture.excalidraw diff --git a/localenv/README.md b/localenv/README.md index 8916426ca8..0338cf3e2a 100644 --- a/localenv/README.md +++ b/localenv/README.md @@ -1,6 +1,6 @@ # Local Playground -We have created a suite of packages that, together, mock an account servicing entity that has deployed Rafiki, exposing an [SPSP](https://rafiki.dev/reference/glossary/#simple-payments-setup-protocol-spsp) endpoint, the [Open Payments](https://rafiki.dev/concepts/open-payments/overview/) APIs with its required [GNAP](https://rafiki.dev/reference/glossary/#grant-negotiation-authorization-protocol) auth endpoints to request grants, a STREAM endpoint for receiving Interledger packets, and a UI to view and manage the Rafiki instance. Additionally, we provide a simple request signing service that is used by Postman to generate request signatures required by the Open Payments APIs. +We have created a suite of packages that, together, mock an account servicing entity that has deployed Rafiki, exposing an [SPSP](https://rafiki.dev/reference/glossary/#simple-payments-setup-protocol-spsp) endpoint, the [Open Payments](https://rafiki.dev/concepts/open-payments/overview/) APIs with its required [GNAP](https://rafiki.dev/reference/glossary/#grant-negotiation-authorization-protocol) auth endpoints to request grants, a STREAM endpoint for receiving Interledger packets, and a UI to view and manage the Rafiki instance. These packages include: @@ -29,35 +29,31 @@ This environment will set up an playground where you can use the Rafiki Admin AP (b) Admin API - accessible at http://localhost:3001/graphql -(c) Auth API - accessible at http://localhost:3003/graphql +(c) Open Payments API - accessible at http://localhost:3000 -(d) Open Payments API - accessible at http://localhost:3000 +(d) Admin UI - accessible at http://localhost:3010 -(e) Rafiki Admin - accessible at http://localhost:3010 +(e) Auth Admin API - accessible at http://localhost:3003/graphql (f) Open Payments Auth API - accessible at http://localhost:3006 -(g) Postman Signature Service - accessible at http://localhost:3040 - #### Happy Life Bank -(h) User Interface - accessible at http://localhost:3031 - -(i) Admin API - accessible at http://localhost:4001/graphql +(g) User Interface - accessible at http://localhost:3031 -(j) Auth API - accessible at http://localhost:4003/graphql +(h) Admin API - accessible at http://localhost:4001/graphql -(k) Open Payments API - accessible at http://localhost:4000 +(i) Open Payments API - accessible at http://localhost:4000 -(l) Rafiki Admin - accessible at http://localhost:4010 +(j) Admin UI - accessible at http://localhost:4010 -(m) Open Payments Auth API - accessible at http://localhost:4006 +(k) Auth Admin API - accessible at http://localhost:4003/graphql -(n) Postman Signature Service - accessible at http://localhost:3041 +(l) Open Payments Auth API - accessible at http://localhost:4006 #### Database -(m) Postgres Server - accessible at http://localhost:5432 +Postgres Server - accessible at http://localhost:5432 ### Exploring Accounts on Mock Account Servicing Entity @@ -77,7 +73,7 @@ When clicking on the Account Name, a list of Transactions appears. - [Rafiki local environment setup](../README.md#environment-setup) - [docker](https://docs.docker.com/get-docker/) -- [postman](https://www.postman.com/downloads/) +- [Bruno](https://www.usebruno.com/downloads) ### Setup @@ -103,8 +99,7 @@ pnpm localenv:compose:psql down --volumes The local environment consists of a primary Rafiki instance and a secondary Rafiki instance, each with its own docker compose files ([Cloud Nine Wallet](./cloud-nine-wallet/docker-compose.yml), [Happy Life Bank](./happy-life-bank/docker-compose.yml)). The primary Cloud Nine Wallet docker compose file (`./cloud-nine-wallet/docker-compose.yml`) includes the main Rafiki services `backend` and `auth`, as well -as the required data stores tigerbeetle (if enabled), redis, and postgres, so it can be run on its own. Furthermore, -both include the `local-signature-utils` signature generation app for Postman. +as the required data stores tigerbeetle (if enabled), redis, and postgres, so it can be run on its own. The secondary Happy Life Bank docker compose file (`./happy-life-bank/docker-compose.yml`) includes only the Rafiki services, not the data stores. It uses the data stores created by the primary Rafiki instance so it can't be run by itself. The `pnpm localenv:compose up` command starts both the primary instance and the secondary. @@ -124,12 +119,12 @@ Your local cloud nine rafiki instance will be peered automatically in this case The required services will be exposed externally using [tunnelmole](https://www.npmjs.com/package/tunnelmole) package. The exposed ports are 3000(open-payments), 3006(auth server), 3002(ilp connector). -To use the postman collection examples follow the steps: +To use the Bruno collection examples follow the steps: 1. run `docker logs rafiki-cloud-nine-mock-ase-1` 2. find the list of created wallet addresses 3. copy the url of one of the wallet addresses -4. set the url into `senderWalletAddress` postman variable in `Remote Environment` +4. set the url as `senderWalletAddress` variable in the Bruno `Remote` environment After stopping the script it is necessary to clear the environment using the command described in [Shutting down](#Shutting-down). This is necessary as on a new run of the scripts (with autopeering or not) the wallet address url will differ. @@ -162,26 +157,28 @@ pnpm localenv:compose down --volumes ### Usage -#### Postman & Open Payments APIs +#### Bruno & Open Payments APIs -The Open Payments APIs can be interacted with using the Postman collection ([Open Payments APIs](https://www.postman.com/interledger/workspace/interledger/folder/22855701-1b204bc1-c8e5-44d4-bab9-444d7204b15a?ctx=documentation) and [Open Payments Auth APIs](https://www.postman.com/interledger/workspace/interledger/folder/22855701-ae80b96d-4d25-42b9-94fa-8ed17f0e5ed9?ctx=documentation)). It is configured to use the default endpoints of the local environment. +The Open Payments APIs can be interacted with using the [Bruno collection](https://github.com/interledger/rafiki/main/bruno/collections/Interledger) and its ([Open Payments APIs](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20APIs) and [Open Payments Auth APIs](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20Auth%20APIs)). It is configured to use the default endpoints of the local environment. -The Examples folder in the Postman collection includes an [eCommerce example](https://www.postman.com/interledger/workspace/interledger/folder/22855701-e27838da-dd72-4b5e-9f1e-086ddfa4d098?ctx=documentation) that can be executed one by one. It +The Examples folder in the Bruno collection includes an [eCommerce example](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Examples/Open%20Payments) that can be executed one by one. It -1. requests a grant to create an incoming payment on Philip Fry's account -2. creates an incoming payment on Philip Fry's account -3. requests a grant to create (and read) a quote on Grace Franklin's account -4. creates a quote on Grace Franklin's account -5. requests a grant to create (and read) an outgoing payment on Grace Franklin's account -6. continues the grant request (via the interaction flow) -7. creates an outgoing payment on Grace Franklin's account -8. fetches the outgoing payment on Grace Franklin's account +1. requests the sender's wallet address +2. requests the receiver's wallet address +3. requests a grant to create an incoming payment on the receiver's account +4. creates an incoming payment on receiver's account +5. requests a grant to create (and read) a quote on the sender's account +6. creates a quote on the sender's account +7. requests a grant to create (and read) an outgoing payment on the sender's account +8. continues the grant request (via the interaction flow) +9. creates an outgoing payment on the sender's account +10. fetches the outgoing payment on the sender's account Note that one has to go through the interaction flow after requesting a grant for a outgoing payment. More information about the interaction flow can be found [here](../docs/grant-interaction.md). -Example walkthrough: + #### Admin UI @@ -189,7 +186,7 @@ In order to manage, and view information about the Rafiki instance(s) using a UI #### Admin APIs -In addition to the using the Admin UI for interacting with the Admin APIs, you can also use the Apollo explorer (on [`localhost:3001/graphql`](http://localhost:3001/graphql) and [`localhost:4001/graphql`](http://localhost:4001/graphql), respectively), and also via the [Postman collection](https://www.postman.com/interledger/workspace/interledger/folder/22855701-ba745403-c5e8-4893-9dff-bccb72ea0614?ctx=documentation). The Postman collection is configured to use the default endpoints of the local environment. +In addition to the using the Admin UI for interacting with the Admin APIs, you can also use the Apollo explorer (on [`localhost:3001/graphql`](http://localhost:3001/graphql) and [`localhost:4001/graphql`](http://localhost:4001/graphql), respectively), and also via the [Bruno collection](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Rafiki%20Admin%20APIs). The Bruno collection is configured to use the default endpoints of the local environment. #### SPSP diff --git a/localenv/cloud-nine-wallet/seed.yml b/localenv/cloud-nine-wallet/seed.yml index bdf6e825ec..d9a7aeb4ae 100644 --- a/localenv/cloud-nine-wallet/seed.yml +++ b/localenv/cloud-nine-wallet/seed.yml @@ -30,19 +30,19 @@ accounts: path: accounts/gfranklin id: 742ab7cd-1624-4d2e-af6e-e15a71638669 initialBalance: 50000 - postmanEnvVar: gfranklinWalletAddress + brunoEnvVar: gfranklinWalletAddress assetCode: USD - name: 'Bert Hamchest' id: a9adbe1a-df31-4766-87c9-d2cb2e636a9b initialBalance: 50000 path: accounts/bhamchest - postmanEnvVar: bhamchestWalletAddress + brunoEnvVar: bhamchestWalletAddress assetCode: USD - name: "World's Best Donut Co" id: 5726eefe-8737-459d-a36b-0acce152cb90 initialBalance: 2000 path: accounts/wbdc - postmanEnvVar: wbdcWalletAddress + brunoEnvVar: wbdcWalletAddress assetCode: USD rates: EUR: diff --git a/localenv/docs/assets/drawio/localenv-architecture.drawio b/localenv/docs/assets/drawio/localenv-architecture.drawio deleted file mode 100644 index 601cc2a7ae..0000000000 --- a/localenv/docs/assets/drawio/localenv-architecture.drawio +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/localenv/docs/assets/excalidraw/localenv-architecture.excalidraw b/localenv/docs/assets/excalidraw/localenv-architecture.excalidraw new file mode 100644 index 0000000000..65f3d13ad4 --- /dev/null +++ b/localenv/docs/assets/excalidraw/localenv-architecture.excalidraw @@ -0,0 +1,3833 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor", + "elements": [ + { + "type": "ellipse", + "version": 2052, + "versionNonce": 1130919223, + "isDeleted": false, + "id": "rtwsNKSqmCGVkhK1faQAe", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 0, + "angle": 0, + "x": 706.6213384181644, + "y": 250.62133841816438, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 116.75732316367123, + "height": 116.75732316367123, + "seed": 240476247, + "groupIds": [ + "v1asvEwJ3F360eXOybYhy" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1850, + "versionNonce": 1557058542, + "isDeleted": false, + "id": "JB3IjHMUCclwMw6C3Yj8a", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 721.176025390625, + "y": 332.857825616106, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 87.64794921875, + "height": 20, + "seed": 261438839, + "groupIds": [ + "v1asvEwJ3F360eXOybYhy" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410498, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Tigerbeetle", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Tigerbeetle", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "line", + "version": 1567, + "versionNonce": 1597158999, + "isDeleted": false, + "id": "zOn5pHwDflzjiwWuvcpOH", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 740.0871844731405, + "y": 283.6973301318022, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.903292935976054, + "height": 59.210922138681, + "seed": 1394374295, + "groupIds": [ + "zbHfZHt_PFFyz_rCsnD_K", + "v1asvEwJ3F360eXOybYhy" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 28.299530811487102 + ], + [ + 1.6417076378563409, + 33.443548076769844 + ], + [ + 7.442407958281753, + 38.0403294627672 + ], + [ + 15.650946147562784, + 40.667061683337124 + ], + [ + 26.157875029842657, + 40.33872015576604 + ], + [ + 35.1325434501233, + 36.72696335248227 + ], + [ + 41.042690946405656, + 32.458523494056095 + ], + [ + 42.356057056690666, + 27.31450622877327 + ], + [ + 42.79384576011894, + 10.569088322639786 + ], + [ + 42.903292935976054, + -5.847988055922443 + ], + [ + 42.574951408404885, + -11.648688376347728 + ], + [ + 37.6498284948362, + -15.5887867072027 + ], + [ + 26.70511090912805, + -18.54386045534388 + ], + [ + 14.994263092420281, + -18.434413279486808 + ], + [ + 5.910147496282524, + -15.917128234773912 + ], + [ + 1.09447175857095, + -11.86758272806195 + ], + [ + 0.10944717585711185, + -6.6141182869220145 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "line", + "version": 718, + "versionNonce": 1799077529, + "isDeleted": false, + "id": "qn0XdLnNqTDMHXfWvfDIW", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 740.4155260007118, + "y": 273.90924374502487, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.79384576011894, + "height": 8.865221244423617, + "seed": 1335856055, + "groupIds": [ + "zbHfZHt_PFFyz_rCsnD_K", + "v1asvEwJ3F360eXOybYhy" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 4.59678138599735, + 5.144017265282825 + ], + [ + 15.213157444134335, + 8.536879716852367 + ], + [ + 26.486216557413655, + 8.865221244423617 + ], + [ + 36.4459095604083, + 5.910147496282398 + ], + [ + 42.79384576011894, + 1.0944717585708237 + ] + ] + }, + { + "type": "line", + "version": 784, + "versionNonce": 1180160887, + "isDeleted": false, + "id": "2wOoNFXi7Np_wFcp4Ce_u", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 740.0641255518034, + "y": 283.17252389355707, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.79384576011894, + "height": 8.865221244423617, + "seed": 826473687, + "groupIds": [ + "zbHfZHt_PFFyz_rCsnD_K", + "v1asvEwJ3F360eXOybYhy" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 4.59678138599735, + 5.144017265282825 + ], + [ + 15.213157444134335, + 8.536879716852367 + ], + [ + 26.486216557413655, + 8.865221244423617 + ], + [ + 36.4459095604083, + 5.910147496282398 + ], + [ + 42.79384576011894, + 1.0944717585708237 + ] + ] + }, + { + "type": "line", + "version": 824, + "versionNonce": 1247445881, + "isDeleted": false, + "id": "ndnIEYewJ_zooKOU6xNO9", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 739.7633054112549, + "y": 289.88376900114434, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.79384576011894, + "height": 8.865221244423617, + "seed": 731597303, + "groupIds": [ + "zbHfZHt_PFFyz_rCsnD_K", + "v1asvEwJ3F360eXOybYhy" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 4.59678138599735, + 5.144017265282825 + ], + [ + 15.213157444134335, + 8.536879716852367 + ], + [ + 26.486216557413655, + 8.865221244423617 + ], + [ + 36.4459095604083, + 5.910147496282398 + ], + [ + 42.79384576011894, + 1.0944717585708237 + ] + ] + }, + { + "type": "ellipse", + "version": 2122, + "versionNonce": 18631831, + "isDeleted": false, + "id": "9JZPtGyN4vv9VzZXgrLuP", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 0, + "angle": 0, + "x": 706.6213384181644, + "y": 369.62133841816444, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 116.75732316367123, + "height": 116.75732316367123, + "seed": 1882314777, + "groupIds": [ + "myx-DdwfwXda-DDi2UlT9" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1919, + "versionNonce": 992684530, + "isDeleted": false, + "id": "Ay6wXrm_MzHgyW_MPbowm", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 744.5520172119141, + "y": 451.8578256161061, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 40.895965576171875, + "height": 20, + "seed": 1280404729, + "groupIds": [ + "myx-DdwfwXda-DDi2UlT9" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410498, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Redis", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Redis", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "line", + "version": 1637, + "versionNonce": 456434103, + "isDeleted": false, + "id": "wR4mRFjqZW-tEIJhN8bvD", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 740.0871844731405, + "y": 402.6973301318021, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.903292935976054, + "height": 59.210922138681, + "seed": 762013145, + "groupIds": [ + "urMdOQssyCQ0buF3aJrYI", + "myx-DdwfwXda-DDi2UlT9" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 28.299530811487102 + ], + [ + 1.6417076378563409, + 33.443548076769844 + ], + [ + 7.442407958281753, + 38.0403294627672 + ], + [ + 15.650946147562784, + 40.667061683337124 + ], + [ + 26.157875029842657, + 40.33872015576604 + ], + [ + 35.1325434501233, + 36.72696335248227 + ], + [ + 41.042690946405656, + 32.458523494056095 + ], + [ + 42.356057056690666, + 27.31450622877327 + ], + [ + 42.79384576011894, + 10.569088322639786 + ], + [ + 42.903292935976054, + -5.847988055922443 + ], + [ + 42.574951408404885, + -11.648688376347728 + ], + [ + 37.6498284948362, + -15.5887867072027 + ], + [ + 26.70511090912805, + -18.54386045534388 + ], + [ + 14.994263092420281, + -18.434413279486808 + ], + [ + 5.910147496282524, + -15.917128234773912 + ], + [ + 1.09447175857095, + -11.86758272806195 + ], + [ + 0.10944717585711185, + -6.6141182869220145 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "line", + "version": 788, + "versionNonce": 1495841081, + "isDeleted": false, + "id": "RB2J5GkGI3eD36ma8SGHS", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 740.4155260007117, + "y": 392.9092437450249, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.79384576011894, + "height": 8.865221244423617, + "seed": 1318273721, + "groupIds": [ + "urMdOQssyCQ0buF3aJrYI", + "myx-DdwfwXda-DDi2UlT9" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 4.59678138599735, + 5.144017265282825 + ], + [ + 15.213157444134335, + 8.536879716852367 + ], + [ + 26.486216557413655, + 8.865221244423617 + ], + [ + 36.4459095604083, + 5.910147496282398 + ], + [ + 42.79384576011894, + 1.0944717585708237 + ] + ] + }, + { + "type": "line", + "version": 854, + "versionNonce": 902124247, + "isDeleted": false, + "id": "-xMeLJ4aMorrbm00uoVhu", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 740.0641255518033, + "y": 402.1725238935571, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.79384576011894, + "height": 8.865221244423617, + "seed": 1013744537, + "groupIds": [ + "urMdOQssyCQ0buF3aJrYI", + "myx-DdwfwXda-DDi2UlT9" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 4.59678138599735, + 5.144017265282825 + ], + [ + 15.213157444134335, + 8.536879716852367 + ], + [ + 26.486216557413655, + 8.865221244423617 + ], + [ + 36.4459095604083, + 5.910147496282398 + ], + [ + 42.79384576011894, + 1.0944717585708237 + ] + ] + }, + { + "type": "line", + "version": 894, + "versionNonce": 1913596441, + "isDeleted": false, + "id": "fM7Bnb3I-iubYZ2_yRcig", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 739.763305411255, + "y": 408.8837690011444, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.79384576011894, + "height": 8.865221244423617, + "seed": 589998201, + "groupIds": [ + "urMdOQssyCQ0buF3aJrYI", + "myx-DdwfwXda-DDi2UlT9" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 4.59678138599735, + 5.144017265282825 + ], + [ + 15.213157444134335, + 8.536879716852367 + ], + [ + 26.486216557413655, + 8.865221244423617 + ], + [ + 36.4459095604083, + 5.910147496282398 + ], + [ + 42.79384576011894, + 1.0944717585708237 + ] + ] + }, + { + "type": "ellipse", + "version": 2200, + "versionNonce": 1499652087, + "isDeleted": false, + "id": "5GZekwurfJ14byEf-KlKY", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 0, + "angle": 0, + "x": 707.6213384181644, + "y": 479.62133841816444, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 116.75732316367123, + "height": 116.75732316367123, + "seed": 735200407, + "groupIds": [ + "lGipdOOi6eGCWOnFBn_Fw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 2005, + "versionNonce": 1072309806, + "isDeleted": false, + "id": "MP9ZkpSls_sBt77ATwvGS", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 731.2480316162109, + "y": 561.8578256161061, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 69.50393676757812, + "height": 20, + "seed": 1818991031, + "groupIds": [ + "lGipdOOi6eGCWOnFBn_Fw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410499, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Postgres", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Postgres", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "line", + "version": 1715, + "versionNonce": 135383319, + "isDeleted": false, + "id": "IHE-hz92qbEqHF4qm60Z8", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 741.0871844731405, + "y": 512.6973301318021, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.903292935976054, + "height": 59.210922138681, + "seed": 895306455, + "groupIds": [ + "gsG4-OnDPV2PiwlbxM8qg", + "lGipdOOi6eGCWOnFBn_Fw" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 28.299530811487102 + ], + [ + 1.6417076378563409, + 33.443548076769844 + ], + [ + 7.442407958281753, + 38.0403294627672 + ], + [ + 15.650946147562784, + 40.667061683337124 + ], + [ + 26.157875029842657, + 40.33872015576604 + ], + [ + 35.1325434501233, + 36.72696335248227 + ], + [ + 41.042690946405656, + 32.458523494056095 + ], + [ + 42.356057056690666, + 27.31450622877327 + ], + [ + 42.79384576011894, + 10.569088322639786 + ], + [ + 42.903292935976054, + -5.847988055922443 + ], + [ + 42.574951408404885, + -11.648688376347728 + ], + [ + 37.6498284948362, + -15.5887867072027 + ], + [ + 26.70511090912805, + -18.54386045534388 + ], + [ + 14.994263092420281, + -18.434413279486808 + ], + [ + 5.910147496282524, + -15.917128234773912 + ], + [ + 1.09447175857095, + -11.86758272806195 + ], + [ + 0.10944717585711185, + -6.6141182869220145 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "line", + "version": 866, + "versionNonce": 295450585, + "isDeleted": false, + "id": "rQXOGmMHzHWe9p84I7xNv", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 741.4155260007117, + "y": 502.9092437450249, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.79384576011894, + "height": 8.865221244423617, + "seed": 322689015, + "groupIds": [ + "gsG4-OnDPV2PiwlbxM8qg", + "lGipdOOi6eGCWOnFBn_Fw" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 4.59678138599735, + 5.144017265282825 + ], + [ + 15.213157444134335, + 8.536879716852367 + ], + [ + 26.486216557413655, + 8.865221244423617 + ], + [ + 36.4459095604083, + 5.910147496282398 + ], + [ + 42.79384576011894, + 1.0944717585708237 + ] + ] + }, + { + "type": "line", + "version": 932, + "versionNonce": 256282167, + "isDeleted": false, + "id": "-hbP0zY4wE1l0a_O0LaKR", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 741.0641255518033, + "y": 512.1725238935571, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.79384576011894, + "height": 8.865221244423617, + "seed": 202096919, + "groupIds": [ + "gsG4-OnDPV2PiwlbxM8qg", + "lGipdOOi6eGCWOnFBn_Fw" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 4.59678138599735, + 5.144017265282825 + ], + [ + 15.213157444134335, + 8.536879716852367 + ], + [ + 26.486216557413655, + 8.865221244423617 + ], + [ + 36.4459095604083, + 5.910147496282398 + ], + [ + 42.79384576011894, + 1.0944717585708237 + ] + ] + }, + { + "type": "line", + "version": 972, + "versionNonce": 1490670777, + "isDeleted": false, + "id": "tNhGgIuCQbVY7koHODJW6", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 740.763305411255, + "y": 518.8837690011444, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 42.79384576011894, + "height": 8.865221244423617, + "seed": 1900119607, + "groupIds": [ + "gsG4-OnDPV2PiwlbxM8qg", + "lGipdOOi6eGCWOnFBn_Fw" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 4.59678138599735, + 5.144017265282825 + ], + [ + 15.213157444134335, + 8.536879716852367 + ], + [ + 26.486216557413655, + 8.865221244423617 + ], + [ + 36.4459095604083, + 5.910147496282398 + ], + [ + 42.79384576011894, + 1.0944717585708237 + ] + ] + }, + { + "type": "rectangle", + "version": 53, + "versionNonce": 434483031, + "isDeleted": false, + "id": "pP-pkYxhs3zg8ZX4vihTI", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 508, + "y": 225, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145, + "height": 83, + "seed": 1593440249, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "iYnAmS5A3Y0dNIfCzL6et" + }, + { + "id": "R1UV0k7teUcPBs5sDUxjZ", + "type": "arrow" + } + ], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 21, + "versionNonce": 605083033, + "isDeleted": false, + "id": "iYnAmS5A3Y0dNIfCzL6et", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 528.9833335876465, + "y": 247.3, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 103.03333282470703, + "height": 38.4, + "seed": 1242093239, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "cloud-nine-\nwallet", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "pP-pkYxhs3zg8ZX4vihTI", + "originalText": "cloud-nine-wallet", + "lineHeight": 1.2, + "baseline": 34 + }, + { + "type": "rectangle", + "version": 154, + "versionNonce": 37989495, + "isDeleted": false, + "id": "pqrSSfcgYoS1DN_gnUve4", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 433.5, + "y": 330.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145, + "height": 83, + "seed": 694466071, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "369_BDFOvutskkEBDCcgQ" + }, + { + "id": "8jvnWOSGFFx9xWL0mnDGv", + "type": "arrow" + }, + { + "id": "774PQQiCjH8FNx_BM-cVF", + "type": "arrow" + } + ], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 29, + "versionNonce": 1987361401, + "isDeleted": false, + "id": "369_BDFOvutskkEBDCcgQ", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 440.43333435058594, + "y": 352.8, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 131.13333129882812, + "height": 38.4, + "seed": 1250421913, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "cloud-nine-\nwallet-backend", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "pqrSSfcgYoS1DN_gnUve4", + "originalText": "cloud-nine-wallet-backend", + "lineHeight": 1.2, + "baseline": 34 + }, + { + "type": "rectangle", + "version": 221, + "versionNonce": 1857960631, + "isDeleted": false, + "id": "qHbaiBqlodn5D78Bw1gbN", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 345.5, + "y": 436.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145, + "height": 83, + "seed": 1444843897, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "bj2RKXq_fr30BR48g-ETD" + } + ], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 35, + "versionNonce": 258027577, + "isDeleted": false, + "id": "bj2RKXq_fr30BR48g-ETD", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 361.79999923706055, + "y": 458.8, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 112.4000015258789, + "height": 38.4, + "seed": 45459385, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "cloud-nine-\nwallet-admin", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "qHbaiBqlodn5D78Bw1gbN", + "originalText": "cloud-nine-wallet-admin", + "lineHeight": 1.2, + "baseline": 34 + }, + { + "type": "rectangle", + "version": 314, + "versionNonce": 1991494615, + "isDeleted": false, + "id": "zfCldqZEkiU5qP5f-P71l", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 510.5, + "y": 543.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145, + "height": 83, + "seed": 1642128855, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "6DFyLZIAqvyjKRL3xSd_W" + }, + { + "id": "R1UV0k7teUcPBs5sDUxjZ", + "type": "arrow" + }, + { + "id": "774PQQiCjH8FNx_BM-cVF", + "type": "arrow" + } + ], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 26, + "versionNonce": 1478541593, + "isDeleted": false, + "id": "6DFyLZIAqvyjKRL3xSd_W", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 531.4833335876465, + "y": 565.8, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 103.03333282470703, + "height": 38.4, + "seed": 449318103, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "cloud-nine-\nwallet-auth", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "zfCldqZEkiU5qP5f-P71l", + "originalText": "cloud-nine-wallet-auth", + "lineHeight": 1.2, + "baseline": 34 + }, + { + "type": "rectangle", + "version": 117, + "versionNonce": 1209678071, + "isDeleted": false, + "id": "iGrkhKvPYw_ddRHTarXWQ", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 885.5, + "y": 229.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145, + "height": 83, + "seed": 225728281, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "zj5D3aPr_Rug74seLTwjX" + }, + { + "id": "ie0ZpZEIynmjJ1TCWl1RU", + "type": "arrow" + } + ], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 19, + "versionNonce": 142292473, + "isDeleted": false, + "id": "zj5D3aPr_Rug74seLTwjX", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 906.4833335876465, + "y": 251.8, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 103.03333282470703, + "height": 38.4, + "seed": 781210711, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "happy-life-\nbank", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "iGrkhKvPYw_ddRHTarXWQ", + "originalText": "happy-life-bank", + "lineHeight": 1.2, + "baseline": 34 + }, + { + "type": "rectangle", + "version": 177, + "versionNonce": 947257879, + "isDeleted": false, + "id": "X2EIhmfNXIt6j1mbz-Rwx", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 964.5, + "y": 332.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145, + "height": 83, + "seed": 1382054487, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "ZC-yDdbago2t4Rmu1W4wH" + }, + { + "id": "swYUI1z5tFcENyMDKuGFn", + "type": "arrow" + }, + { + "id": "RrFX1L4Nf8iUcczBq9b4i", + "type": "arrow" + } + ], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 27, + "versionNonce": 863243993, + "isDeleted": false, + "id": "ZC-yDdbago2t4Rmu1W4wH", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 980.7999992370605, + "y": 354.8, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 112.4000015258789, + "height": 38.4, + "seed": 482974233, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "happy-life-\nbank-backend", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "X2EIhmfNXIt6j1mbz-Rwx", + "originalText": "happy-life-bank-backend", + "lineHeight": 1.2, + "baseline": 34 + }, + { + "type": "rectangle", + "version": 228, + "versionNonce": 2025563959, + "isDeleted": false, + "id": "ZYzhRwtwqTM6Gk-IFNO31", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1052.5, + "y": 435.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145, + "height": 83, + "seed": 2037761817, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "cqxr7XBvpMLRJwOIS8Grc" + }, + { + "id": "nkGAfGK3lxFF8gyfVUwvm", + "type": "arrow" + } + ], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 25, + "versionNonce": 1067371449, + "isDeleted": false, + "id": "cqxr7XBvpMLRJwOIS8Grc", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1073.4833335876465, + "y": 457.8, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 103.03333282470703, + "height": 38.4, + "seed": 368953207, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "happy-life-\nbank-admin", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ZYzhRwtwqTM6Gk-IFNO31", + "originalText": "happy-life-bank-admin", + "lineHeight": 1.2, + "baseline": 34 + }, + { + "type": "rectangle", + "version": 327, + "versionNonce": 659531863, + "isDeleted": false, + "id": "EhHceIvOg6UjIQBP2TgLQ", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 897.5, + "y": 547.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145, + "height": 83, + "seed": 280506007, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "s48sdnyViOolkugUVRNQ3" + }, + { + "id": "RrFX1L4Nf8iUcczBq9b4i", + "type": "arrow" + }, + { + "id": "ie0ZpZEIynmjJ1TCWl1RU", + "type": "arrow" + } + ], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 40, + "versionNonce": 1964960921, + "isDeleted": false, + "id": "s48sdnyViOolkugUVRNQ3", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 918.4833335876465, + "y": 569.8, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 103.03333282470703, + "height": 38.4, + "seed": 1052338745, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "happy-life-\nbank-auth", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "EhHceIvOg6UjIQBP2TgLQ", + "originalText": "happy-life-bank-auth", + "lineHeight": 1.2, + "baseline": 34 + }, + { + "type": "arrow", + "version": 78, + "versionNonce": 570852727, + "isDeleted": false, + "id": "R1UV0k7teUcPBs5sDUxjZ", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 625, + "y": 311, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 4, + "height": 227, + "seed": 748550807, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": { + "elementId": "pP-pkYxhs3zg8ZX4vihTI", + "focus": -0.596956116341324, + "gap": 3 + }, + "endBinding": { + "elementId": "zfCldqZEkiU5qP5f-P71l", + "focus": 0.6394561915360784, + "gap": 5.5 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 4, + 227 + ] + ] + }, + { + "type": "arrow", + "version": 59, + "versionNonce": 1269297529, + "isDeleted": false, + "id": "8jvnWOSGFFx9xWL0mnDGv", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 550, + "y": 310, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 0, + "height": 19, + "seed": 2034540119, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": { + "elementId": "pqrSSfcgYoS1DN_gnUve4", + "focus": -0.6068965517241379, + "gap": 20.5 + }, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 0, + 19 + ] + ] + }, + { + "type": "arrow", + "version": 22, + "versionNonce": 405061271, + "isDeleted": false, + "id": "gNbuzAt0gQgFwiOipsoER", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 473, + "y": 413, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 1, + "height": 24, + "seed": 1803305879, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -1, + 24 + ] + ] + }, + { + "type": "arrow", + "version": 54, + "versionNonce": 2021481049, + "isDeleted": false, + "id": "774PQQiCjH8FNx_BM-cVF", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 545, + "y": 419, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 0, + "height": 122, + "seed": 1848619543, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": { + "elementId": "pqrSSfcgYoS1DN_gnUve4", + "focus": -0.5379310344827586, + "gap": 5.5 + }, + "endBinding": { + "elementId": "zfCldqZEkiU5qP5f-P71l", + "focus": -0.5241379310344828, + "gap": 2.5 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 0, + 122 + ] + ] + }, + { + "type": "arrow", + "version": 23, + "versionNonce": 1549718455, + "isDeleted": false, + "id": "swYUI1z5tFcENyMDKuGFn", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1001, + "y": 313, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 1, + "height": 19, + "seed": 901067289, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": { + "elementId": "X2EIhmfNXIt6j1mbz-Rwx", + "focus": 0.5250176180408738, + "gap": 19.5 + }, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -1, + 19 + ] + ] + }, + { + "type": "arrow", + "version": 20, + "versionNonce": 1014146873, + "isDeleted": false, + "id": "nkGAfGK3lxFF8gyfVUwvm", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1068, + "y": 416, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 1, + "height": 21, + "seed": 1100659033, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": { + "elementId": "ZYzhRwtwqTM6Gk-IFNO31", + "focus": 0.8043478260869564, + "gap": 19.5 + }, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -1, + 21 + ] + ] + }, + { + "type": "arrow", + "version": 97, + "versionNonce": 1993950423, + "isDeleted": false, + "id": "RrFX1L4Nf8iUcczBq9b4i", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 987.9959015696226, + "y": 417.00000000000006, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 1.0118814797934874, + "height": 126.99999999999994, + "seed": 1267538425, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": { + "elementId": "X2EIhmfNXIt6j1mbz-Rwx", + "focus": 0.6775445901085917, + "gap": 1.5 + }, + "endBinding": { + "elementId": "EhHceIvOg6UjIQBP2TgLQ", + "focus": 0.26590896303381534, + "gap": 3.5 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 1.0118814797934874, + 126.99999999999994 + ] + ] + }, + { + "type": "arrow", + "version": 130, + "versionNonce": 1911248921, + "isDeleted": false, + "id": "ie0ZpZEIynmjJ1TCWl1RU", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 922.0017324462225, + "y": 313.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 4.016767881046576, + "height": 231.5, + "seed": 231305561, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": { + "elementId": "iGrkhKvPYw_ddRHTarXWQ", + "focus": 0.5016994014497548, + "gap": 1 + }, + "endBinding": { + "elementId": "EhHceIvOg6UjIQBP2TgLQ", + "focus": -0.5902487442476012, + "gap": 2.5 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 4.016767881046576, + 231.5 + ] + ] + }, + { + "type": "line", + "version": 64, + "versionNonce": 1999147511, + "isDeleted": false, + "id": "NLleQaVJXXhp8sdBlap3t", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 577, + "y": 356, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 163, + "height": 60, + "seed": 1229196921, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 163, + -60 + ] + ] + }, + { + "type": "line", + "version": 51, + "versionNonce": 1524296953, + "isDeleted": false, + "id": "0izg-PaCMm-yyfzbc0DRq", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 581, + "y": 380, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 159, + "height": 40, + "seed": 1760682169, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 159, + 40 + ] + ] + }, + { + "type": "line", + "version": 37, + "versionNonce": 105986839, + "isDeleted": false, + "id": "P2Zvzrz2zAQ59UE0gVaLj", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 579, + "y": 395, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 162, + "height": 136, + "seed": 640347033, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 162, + 136 + ] + ] + }, + { + "type": "line", + "version": 94, + "versionNonce": 784655833, + "isDeleted": false, + "id": "qSSnAlGoI6Zk0JeqEkI6B", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 964, + "y": 356, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 179, + "height": 66, + "seed": 2096030265, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -179, + -66 + ] + ] + }, + { + "type": "line", + "version": 39, + "versionNonce": 952614967, + "isDeleted": false, + "id": "EmPz_gWwPk59L9kcsXi_4", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 965, + "y": 379, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 178, + "height": 41, + "seed": 1688607417, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -178, + 41 + ] + ] + }, + { + "type": "line", + "version": 65, + "versionNonce": 1757201081, + "isDeleted": false, + "id": "wtP6L0Nze_aejHmLkkZ-l", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 966, + "y": 392, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 182, + "height": 141, + "seed": 258581273, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -182, + 141 + ] + ] + }, + { + "type": "line", + "version": 47, + "versionNonce": 544252247, + "isDeleted": false, + "id": "EylAcC92aBfHprKz1RF_5", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 655, + "y": 587, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 85, + "height": 46, + "seed": 215353913, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 85, + -46 + ] + ] + }, + { + "type": "line", + "version": 61, + "versionNonce": 1432748953, + "isDeleted": false, + "id": "hT9_yeoiJInOB-KoGVz_4", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 896, + "y": 593, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 110, + "height": 52, + "seed": 88537497, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -110, + -52 + ] + ] + }, + { + "type": "line", + "version": 186, + "versionNonce": 928849465, + "isDeleted": false, + "id": "FmwUIJD908ILTNX0tKGt2", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 506.8043886455939, + "y": 265, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 15420089, + "groupIds": [ + "d6H00d3Tzs_UtfAnaRct9" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 137, + "versionNonce": 1328922071, + "isDeleted": false, + "id": "WBM06Oi_hLMzt0JGPZYBy", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 480.8043886455939, + "y": 262, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 1988332441, + "groupIds": [ + "d6H00d3Tzs_UtfAnaRct9" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 245, + "versionNonce": 913239833, + "isDeleted": false, + "id": "nr2hc9ZovHvobiKcHHWes", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 432.9398548655911, + "y": 355, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 609123865, + "groupIds": [ + "2JUqGprrWoV75ipZCMOPt" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 196, + "versionNonce": 1603136247, + "isDeleted": false, + "id": "8nmbkwjhVaLF1wqbqRk2s", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 406.9398548655911, + "y": 352, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 1642681081, + "groupIds": [ + "2JUqGprrWoV75ipZCMOPt" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 285, + "versionNonce": 416523257, + "isDeleted": false, + "id": "Kz4UYTAXsRYshOiQrYicf", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 432.84887232883136, + "y": 386, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 404950009, + "groupIds": [ + "LwJuo1VTXfLrIrMwXHlI9" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 236, + "versionNonce": 1252226071, + "isDeleted": false, + "id": "iJXE4dF1-HP50swcVOL-m", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 406.84887232883136, + "y": 383, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 1806771417, + "groupIds": [ + "LwJuo1VTXfLrIrMwXHlI9" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 327, + "versionNonce": 982432985, + "isDeleted": false, + "id": "KyuqLH_off8b6l3L6lG_7", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 343.00424749038655, + "y": 481, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 310545113, + "groupIds": [ + "kLCo8ZfaeTiXBKSdMu3yk" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 278, + "versionNonce": 141220151, + "isDeleted": false, + "id": "aI-SloglUSIl82PQmUov4", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 317.00424749038655, + "y": 478, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 796772281, + "groupIds": [ + "kLCo8ZfaeTiXBKSdMu3yk" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423440338, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 408, + "versionNonce": 1002580759, + "isDeleted": false, + "id": "FwCLcEmJsLKY6wrH2cs3K", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 508.83701377070975, + "y": 569, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 1223248185, + "groupIds": [ + "jFUYb3NShtdbRlQxy96lD" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423585767, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 359, + "versionNonce": 1922740279, + "isDeleted": false, + "id": "crKoJubjD4sxIXfRQc-VF", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 482.83701377070975, + "y": 566, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 993901081, + "groupIds": [ + "jFUYb3NShtdbRlQxy96lD" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423585767, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 556, + "versionNonce": 1121374615, + "isDeleted": false, + "id": "B2ZZS0a7LDv3n2w8Bd-oF", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1051.4844372342336, + "y": 273.047611015591, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 1573980249, + "groupIds": [ + "1WY5FmOBKsBYsKJjhtUd_" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423451819, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 507, + "versionNonce": 760645303, + "isDeleted": false, + "id": "jbBeg-SLqMR6hHVq5t1vC", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1052.291095445504, + "y": 269.5398403439697, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 1461753145, + "groupIds": [ + "1WY5FmOBKsBYsKJjhtUd_" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423451819, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 621, + "versionNonce": 251466999, + "isDeleted": false, + "id": "MW-MU_7lm-BrduUkAGn5l", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1130.8533272154782, + "y": 360.5077706716213, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 810592761, + "groupIds": [ + "aSqS2OUsdpn-dumcgHAqb" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423456638, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 572, + "versionNonce": 1453153815, + "isDeleted": false, + "id": "ewZBCzOMfIHpS0TgmrE-i", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1131.6599854267483, + "y": 357, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 679150297, + "groupIds": [ + "aSqS2OUsdpn-dumcgHAqb" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423456638, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 627, + "versionNonce": 1402524567, + "isDeleted": false, + "id": "Mz9k1lM5mm9x5jNv0zwpb", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1130.8158142967325, + "y": 388.5077706716213, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 2145538201, + "groupIds": [ + "Y1kurP6pLPd9O0e7IKgHz" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423461063, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 578, + "versionNonce": 445139127, + "isDeleted": false, + "id": "8dmjIfnrYWhhWryT8E9vC", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1131.6224725080026, + "y": 385, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 1885263225, + "groupIds": [ + "Y1kurP6pLPd9O0e7IKgHz" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423461063, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 637, + "versionNonce": 14804791, + "isDeleted": false, + "id": "sr8zq8S36j7ytQr9o21VW", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1218.7670858964248, + "y": 478.5077706716213, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 718571513, + "groupIds": [ + "H8etWlaQWYzUJJ0BbckhL" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423466751, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 588, + "versionNonce": 1353574487, + "isDeleted": false, + "id": "wo0eNRHii6QDIidNdlx-Y", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1219.5737441076953, + "y": 475, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 584261849, + "groupIds": [ + "H8etWlaQWYzUJJ0BbckhL" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423466751, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 715, + "versionNonce": 439279575, + "isDeleted": false, + "id": "jBcTDEs8F7RsvHbMbwOv2", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1063.6718081269364, + "y": 574.5077706716213, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 749935193, + "groupIds": [ + "F5Am2RWPWI1hZN1JTqJuf" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423758048, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 666, + "versionNonce": 1930611959, + "isDeleted": false, + "id": "GuebYiLNL7gPPr9Fqx2fg", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1064.478466338207, + "y": 571, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 1676699449, + "groupIds": [ + "F5Am2RWPWI1hZN1JTqJuf" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423758048, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 54, + "versionNonce": 668277682, + "isDeleted": false, + "id": "F_eMq3RBt1lk_yFMrm2ZB", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 320, + "y": 255, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 150.55990600585938, + "height": 20, + "seed": 1663983639, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410499, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(a) User Interface", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(a) User Interface", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "text", + "version": 45, + "versionNonce": 1080111214, + "isDeleted": false, + "id": "q1El7vy8TyPybHO8yCn0y", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 294, + "y": 344, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 106.67190551757812, + "height": 20, + "seed": 1004861689, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410499, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(b) Admin API", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(b) Admin API", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "text", + "version": 67, + "versionNonce": 1440404850, + "isDeleted": false, + "id": "9QgBVFv1GpL1ZlX8XdI-8", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 218, + "y": 374, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 182.431884765625, + "height": 20, + "seed": 1624166103, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410499, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(c) Open Payments API", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(c) Open Payments API", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "text", + "version": 103, + "versionNonce": 704443054, + "isDeleted": false, + "id": "wed3odwG8oJ0NuvujUaEL", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 211, + "y": 471, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 97.99992370605469, + "height": 20, + "seed": 1639436697, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410499, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(d) Admin UI", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(d) Admin UI", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "line", + "version": 410, + "versionNonce": 865363863, + "isDeleted": false, + "id": "y0R7HGaXVcxF_3HLHQoVA", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 509.8103112243814, + "y": 604, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 1279539321, + "groupIds": [ + "-k-L-TfBoJ8tpmiK_ldYB" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423588392, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 361, + "versionNonce": 502357175, + "isDeleted": false, + "id": "D908vFO6V7YAOQgiz2j4Z", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 483.8103112243814, + "y": 601, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 1274593625, + "groupIds": [ + "-k-L-TfBoJ8tpmiK_ldYB" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423588392, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 54, + "versionNonce": 914577202, + "isDeleted": false, + "id": "qlpdr5OF7mcl-2pRWBghV", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 365, + "y": 558, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 107.29591369628906, + "height": 20, + "seed": 1277453335, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410499, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(e) Admin API", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(e) Admin API", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "text", + "version": 77, + "versionNonce": 1734765806, + "isDeleted": false, + "id": "p0ufuQqyfSvt71g42w74z", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 248, + "y": 591, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 226.70384216308594, + "height": 20, + "seed": 313832697, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410499, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(f) Open Payments Auth API", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(f) Open Payments Auth API", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "text", + "version": 123, + "versionNonce": 2050334962, + "isDeleted": false, + "id": "mNRGxtYXhcSTSwQgDH1iE", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1076.716667175293, + "y": 263, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 147.90390014648438, + "height": 20, + "seed": 214161911, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410499, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(g) User Interface", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(g) User Interface", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "text", + "version": 118, + "versionNonce": 640065326, + "isDeleted": false, + "id": "jxesAgMsfOlZr8mIOI8vY", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1151.6666679382324, + "y": 353, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 106.44790649414062, + "height": 20, + "seed": 329689529, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410500, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(h) Admin API", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(h) Admin API", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "text", + "version": 140, + "versionNonce": 746107570, + "isDeleted": false, + "id": "FHrqASh0OVtbb0AMLIF2x", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1149.783332824707, + "y": 382, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 177.9038848876953, + "height": 20, + "seed": 1174584855, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410500, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(i) Open Payments API", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(i) Open Payments API", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "text", + "version": 159, + "versionNonce": 2057734510, + "isDeleted": false, + "id": "YFvJSs5yVYsy2vlZwWw2v", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1238, + "y": 470, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 94.1439208984375, + "height": 20, + "seed": 1079728697, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410500, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(j) Admin UI", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(j) Admin UI", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "line", + "version": 772, + "versionNonce": 1305278905, + "isDeleted": false, + "id": "pLRPD9KBlSR4FUQZuWYkw", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1063.7319764642557, + "y": 604.5077706716213, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 20, + "height": 0, + "seed": 1168063287, + "groupIds": [ + "NfuwnDhqo4n7YBq2ZI5at" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423766308, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -20, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 723, + "versionNonce": 962026137, + "isDeleted": false, + "id": "2Utnb7ATCtpq9cyRsaqrP", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.096664466840636, + "x": 1064.5386346755263, + "y": 601, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 6, + "height": 6, + "seed": 983612503, + "groupIds": [ + "NfuwnDhqo4n7YBq2ZI5at" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1708423766308, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 113, + "versionNonce": 1341361266, + "isDeleted": false, + "id": "fz_KecHQ2zgYU5mxnPxig", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1082.349998474121, + "y": 565, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 106.33590698242188, + "height": 20, + "seed": 1125766457, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410500, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(k) Admin API", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(k) Admin API", + "lineHeight": 1.25, + "baseline": 14 + }, + { + "type": "text", + "version": 142, + "versionNonce": 70200238, + "isDeleted": false, + "id": "YMZyHcqlsKmKPHvQYVQ5P", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1082.650001525879, + "y": 597, + "strokeColor": "#1e1e1e", + "backgroundColor": "#1e1e1e", + "width": 223.13584899902344, + "height": 20, + "seed": 777764567, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1708426410500, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "(l) Open Payments Auth API", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "(l) Open Payments Auth API", + "lineHeight": 1.25, + "baseline": 14 + } + ], + "appState": { + "gridSize": null, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/localenv/happy-life-bank/seed.yml b/localenv/happy-life-bank/seed.yml index e86869588b..8e163cce7f 100644 --- a/localenv/happy-life-bank/seed.yml +++ b/localenv/happy-life-bank/seed.yml @@ -30,19 +30,19 @@ accounts: path: accounts/pfry id: 97a3a431-8ee1-48fc-ac85-70e2f5eba8e5 initialBalance: 50000 - postmanEnvVar: pfryWalletAddress + brunoEnvVar: pfryWalletAddress assetCode: USD - name: 'PlanEx Corp' id: a455cc54-b583-455b-836a-e5275c5c05b7 initialBalance: 2000 path: accounts/planex - postmanEnvVar: planexWalletAddress + brunoEnvVar: planexWalletAddress assetCode: USD - name: 'Alice Smith' path: accounts/asmith id: f47ac10b-58cc-4372-a567-0e02b2c3d479 initialBalance: 500 - postmanEnvVar: asmithWalletAddress + brunoEnvVar: asmithWalletAddress skipWalletAddressCreation: true assetCode: USD - name: 'Lars' diff --git a/localenv/mock-account-servicing-entity/app/lib/parse_config.server.ts b/localenv/mock-account-servicing-entity/app/lib/parse_config.server.ts index ab1fdab20a..53b961b041 100644 --- a/localenv/mock-account-servicing-entity/app/lib/parse_config.server.ts +++ b/localenv/mock-account-servicing-entity/app/lib/parse_config.server.ts @@ -30,7 +30,7 @@ export interface Account { id: string initialBalance: bigint path: string - postmanEnvVar: string + brunoEnvVar: string assetCode: string skipWalletAddressCreation?: boolean } diff --git a/localenv/mock-account-servicing-entity/app/lib/run_seed.server.ts b/localenv/mock-account-servicing-entity/app/lib/run_seed.server.ts index c98d8107ef..562b353602 100644 --- a/localenv/mock-account-servicing-entity/app/lib/run_seed.server.ts +++ b/localenv/mock-account-servicing-entity/app/lib/run_seed.server.ts @@ -137,7 +137,7 @@ export async function setupFromSeed(config: Config): Promise { console.log(JSON.stringify(accountResponses, null, 2)) const hostname = new URL(CONFIG.publicHost).hostname const envVarStrings = config.seed.accounts.map((account) => { - return `${account.postmanEnvVar}: ${CONFIG.publicHost}/${account.path} hostname: ${hostname}` + return `${account.brunoEnvVar}: ${CONFIG.publicHost}/${account.path} hostname: ${hostname}` }) console.log(envVarStrings.join('\n')) } diff --git a/packages/documentation/public/img/localenv-architecture.png b/packages/documentation/public/img/localenv-architecture.png index 8073a383e0f1082157f9d7f3c9ac108207ebee31..62dab56685777bec5798edf2bcef97242e033fd1 100644 GIT binary patch literal 301994 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

t? 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 Ub{9G!ix2!c+PT>_SO=#34~R1e-T(jq diff --git a/packages/documentation/src/content/docs/playground/autopeering.md b/packages/documentation/src/content/docs/playground/autopeering.md index 645c3d924f..6091ece5c1 100644 --- a/packages/documentation/src/content/docs/playground/autopeering.md +++ b/packages/documentation/src/content/docs/playground/autopeering.md @@ -16,12 +16,12 @@ Your local Rafiki instance will be automatically peered with the remote [Rafiki. The required services will be exposed externally using the [tunnelmole](https://www.npmjs.com/package/tunnelmole) package. The exposed ports are 3000(open-payments), 3006(auth server), 3002(ILP connector). -To use the [Postman API examples](/playground/overview/#postman--open-payments-apis), follow these steps: +To use the [Bruno API examples](/playground/overview/#bruno--open-payments-apis), follow these steps: 1. run `docker logs rafiki-cloud-nine-mock-ase-1` (alternatively, check http://localhost:3030) 2. find the list of created wallet addresses 3. copy the url of one of the wallet addresses -4. set the `senderWalletAddress` variable in the Postman `Remote Environment` to that wallet address +4. set the `senderWalletAddress` variable in the Bruno `Remote` environment to that wallet address To shut down the connection and to clear the environment, run diff --git a/packages/documentation/src/content/docs/playground/overview.md b/packages/documentation/src/content/docs/playground/overview.md index 05dd7a2b54..38254b7be6 100644 --- a/packages/documentation/src/content/docs/playground/overview.md +++ b/packages/documentation/src/content/docs/playground/overview.md @@ -2,7 +2,7 @@ title: Overview --- -We have created a suite of packages that, together, mock an account servicing entity that has deployed Rafiki, exposing an [SPSP](/reference/glossary#simple-payments-setup-protocol-spsp) endpoint, the [Open Payments](/reference/glossary#open-payments) APIs with its required [GNAP](/reference/glossary#grant-negotiation-authorization-protocol) auth endpoints to request grants, a STREAM endpoint for receiving Interledger packets, and a UI to view and manage the Rafiki instance. Additionally, we provide a simple request signing service that is used by Postman to generate request signatures required by the Open Payments APIs. +We have created a suite of packages that, together, mock an account servicing entity that has deployed Rafiki, exposing an [SPSP](/reference/glossary#simple-payments-setup-protocol-spsp) endpoint, the [Open Payments](/reference/glossary#open-payments) APIs with its required [GNAP](/reference/glossary#grant-negotiation-authorization-protocol) auth endpoints to request grants, a STREAM endpoint for receiving Interledger packets, and a UI to view and manage the Rafiki instance. These packages include: @@ -33,11 +33,11 @@ This environment will set up a playground where you can use the Rafiki Admin API (c) Open Payments API - accessible at http://localhost:3000 -(d) Rafiki Admin - accessible at http://localhost:3010 +(d) Admin UI - accessible at http://localhost:3010 -(e) Open Payments Auth API - accessible at http://localhost:3006 +(e) Auth Admin API - accessible at http://localhost:3003/graphql -(f) DEPRECATED: ~~Postman Signature Service - accessible at http://localhost:3040~~ +(f) Open Payments Auth API - accessible at http://localhost:3006 #### Happy Life Bank @@ -47,15 +47,15 @@ This environment will set up a playground where you can use the Rafiki Admin API (i) Open Payments API - accessible at http://localhost:4000 -(j) Rafiki Admin - accessible at http://localhost:4010 +(j) Admin UI - accessible at http://localhost:4010 -(k) Open Payments Auth API - accessible at http://localhost:4006 +(k) Auth Admin API - accessible at http://localhost:4003/graphql -(l) DEPRECATED: ~~Postman Signature Service - accessible at http://localhost:3041~~ +(l) Open Payments Auth API - accessible at http://localhost:4006 #### Database -(m) Postgres Server - accessible at http://localhost:5432 +Postgres Server - accessible at http://localhost:5432 ### Exploring Accounts on Mock Account Servicing Entity @@ -75,7 +75,7 @@ When clicking on the Account Name, a list of Transactions appears. - [Rafiki local environment setup](https://github.com/interledger/rafiki/blob/main/README.md#environment-setup) - [docker](https://docs.docker.com/get-docker/) -- ([postman](https://www.postman.com/downloads/)) +- [Bruno](https://www.usebruno.com/downloads) ### Setup @@ -135,21 +135,22 @@ pnpm localenv:compose down --volumes ### Usage -#### Postman & Open Payments APIs +#### Bruno & Open Payments APIs -The Open Payments APIs can be interacted with using the [Postman API collection](https://www.postman.com/interledger/workspace/interledger/api/84fc90ca-3153-4865-8b49-b91218e5d574). You can either log into Postman and fork the collection or you can [import it from source](https://raw.githubusercontent.com/interledger/rafiki/main/postman/collections/Interledger.json). It requires you to either load the [Local Environment](https://raw.githubusercontent.com/interledger/rafiki/main/postman/environments/Local%20Playground%20Environment.postman_environment.json) or the [Remote Environment](https://raw.githubusercontent.com/interledger/rafiki/main/postman/environments/Remote%20Environment.postman_environment.json). +The Open Payments APIs can be interacted with using the [Bruno collection](https://github.com/interledger/rafiki/main/bruno/collections/Interledger) and its ([Open Payments APIs](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20APIs) and [Open Payments Auth APIs](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20Auth%20APIs)). It requires you to either load the [Local Environment](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/environments/Local%20Playground.bru) or the [Remote Environment](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/environments/Remote.bru). -The Examples folder in the Postman API collection includes an eCommerce (Open Payments) example that can be executed one by one. It +The Examples folder in the Bruno API collection includes an eCommerce (Open Payments) example that can be executed one by one. It -1. gets the sender's wallet address -2. gets the receiver's wallet address +1. requests the sender's wallet address +2. requests the receiver's wallet address 3. requests a grant to create an incoming payment on the receiver's account -4. creates an incoming payment on the receiver's account -5. requests a grant to create (and read) a quote on the senders's account +4. creates an incoming payment on receiver's account +5. requests a grant to create (and read) a quote on the sender's account 6. creates a quote on the sender's account 7. requests a grant to create (and read) an outgoing payment on the sender's account -8. creates an outgoing payment on the sender's account -9. fetches the outgoing payment on the sender's account +8. continues the grant request (via the interaction flow) +9. creates an outgoing payment on the sender's account +10. fetches the outgoing payment on the sender's account Note that one has to go through the interaction flow after requesting a grant for an outgoing payment. More information about the interaction flow can be found [here](/concepts/open-payments/grant-interaction). @@ -164,7 +165,7 @@ In order to manage, and view information about the Rafiki instance(s) using a UI #### Admin APIs -In addition to the using the Admin UI for interacting with the Admin APIs, you can also use the Apollo explorer (on [`localhost:3001/graphql`](http://localhost:3001/graphql) and [`localhost:4001/graphql`](http://localhost:4001/graphql), respectively), and also via the [Postman collection](https://www.postman.com/interledger/workspace/interledger/folder/22855701-ba745403-c5e8-4893-9dff-bccb72ea0614?ctx=documentation). The Postman collection is configured to use the default endpoints of the local environment. +In addition to the using the Admin UI for interacting with the Admin APIs, you can also use the Apollo explorer (on [`localhost:3001/graphql`](http://localhost:3001/graphql) and [`localhost:4001/graphql`](http://localhost:4001/graphql), respectively), and also via the [Bruno collection](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Rafiki%20Admin%20APIs). The Bruno collection is configured to use the default endpoints of the local environment. #### SPSP From 918d59f1466d2c90c6a9ed086c6ad70e6b3d45ea Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Thu, 22 Feb 2024 12:57:28 +0100 Subject: [PATCH 12/16] chore: enable prettier on bruno collection --- .prettierignore | 2 - postman/collections/Interledger/bruno.json | 7 +- .../Interledger/scripts/scripts.js | 93 +++++++++++-------- 3 files changed, 54 insertions(+), 48 deletions(-) diff --git a/.prettierignore b/.prettierignore index 5943306df0..6014a7ea47 100644 --- a/.prettierignore +++ b/.prettierignore @@ -14,7 +14,5 @@ build **/styles/*.css .docusaurus .cache-loader -postman -.postman packages/documentation/src/content/docs/apis .astro \ No newline at end of file diff --git a/postman/collections/Interledger/bruno.json b/postman/collections/Interledger/bruno.json index 32f0580340..a4d3d0e1a2 100644 --- a/postman/collections/Interledger/bruno.json +++ b/postman/collections/Interledger/bruno.json @@ -2,8 +2,5 @@ "version": "1", "name": "Interledger", "type": "collection", - "ignore": [ - "node_modules", - ".git" - ] -} \ No newline at end of file + "ignore": ["node_modules", ".git"] +} diff --git a/postman/collections/Interledger/scripts/scripts.js b/postman/collections/Interledger/scripts/scripts.js index 752320a04d..262c97e48f 100644 --- a/postman/collections/Interledger/scripts/scripts.js +++ b/postman/collections/Interledger/scripts/scripts.js @@ -2,30 +2,33 @@ const fetch = require('node-fetch') const url = require('url') const scripts = { - - sanitizeUrl: function() { - return req.getUrl() + sanitizeUrl: function () { + return req + .getUrl() .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key)) .replace(/localhost:([3,4])000/g, (_, key) => key === '3' ? bru.getEnvVar('host3000') : bru.getEnvVar('host4000') ) }, - sanitizeBody: function() { + sanitizeBody: function () { let requestBody = req.getBody() if (!(req.getMethod() === 'POST' && requestBody)) return undefined - if (typeof requestBody === 'object'){ + if (typeof requestBody === 'object') { requestBody = JSON.stringify(requestBody) } - return JSON.parse(requestBody + return JSON.parse( + requestBody .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key)) - .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => key === '3' - ? 'https://' + bru.getEnvVar('host3000') - : 'https://' + bru.getEnvVar('host4000')) + .replace(/http:\/\/localhost:([3,4])000/g, (_, key) => + key === '3' + ? 'https://' + bru.getEnvVar('host3000') + : 'https://' + bru.getEnvVar('host4000') + ) ) }, - sanitizeHeaders: function() { + sanitizeHeaders: function () { return JSON.parse( JSON.stringify(req.getHeaders()).replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key) @@ -33,10 +36,10 @@ const scripts = { ) }, - requestSigHeaders: async function(url, method, headers, body) { + requestSigHeaders: async function (url, method, headers, body) { const response = await fetch(bru.getEnvVar('signatureUrl'), { method: 'post', - headers: {'Content-Type': 'application/json'}, + headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ keyId: bru.getEnvVar('clientKeyId'), base64Key: bru.getEnvVar('clientPrivateKey'), @@ -51,46 +54,53 @@ const scripts = { return await response.json() }, - setHeaders: function(headers) { + setHeaders: function (headers) { for (let [key, value] of Object.entries(headers)) { req.setHeader(key, value) } }, - addSignatureHeaders: async function() { + addSignatureHeaders: async function () { const url = this.sanitizeUrl() const headers = this.sanitizeHeaders() const body = this.sanitizeBody() req.setBody(body) - const signatureHeaders = await this.requestSigHeaders(url, req.getMethod(), headers, body) + const signatureHeaders = await this.requestSigHeaders( + url, + req.getMethod(), + headers, + body + ) this.setHeaders(signatureHeaders) }, - - addHostHeader: function(hostVarName) { - const requestUrl = url.parse(req.getUrl() - .replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key))) - - if (hostVarName){ - bru.setEnvVar(hostVarName, requestUrl.protocol + '//' + requestUrl.host); + + addHostHeader: function (hostVarName) { + const requestUrl = url.parse( + req.getUrl().replace(/{{([A-Za-z]\w+)}}/g, (_, key) => bru.getEnvVar(key)) + ) + + if (hostVarName) { + bru.setEnvVar(hostVarName, requestUrl.protocol + '//' + requestUrl.host) } - - if(requestUrl.hostname === 'localhost'){ - const hostHeader = requestUrl.port === '3000' + + if (requestUrl.hostname === 'localhost') { + const hostHeader = + requestUrl.port === '3000' ? bru.getEnvVar('host3000') : bru.getEnvVar('host4000') - req.headers.host = hostHeader + req.headers.host = hostHeader } }, - storeTokenDetails: function() { - const body = res.getBody(); - bru.setEnvVar("accessToken", body?.access_token?.value); - bru.setEnvVar("continueToken", body.continue.access_token.value); - bru.setEnvVar("continueId", body.continue.uri.split("/").pop()); - bru.setEnvVar("tokenId", body?.access_token?.manage.split('/').pop()) + storeTokenDetails: function () { + const body = res.getBody() + bru.setEnvVar('accessToken', body?.access_token?.value) + bru.setEnvVar('continueToken', body.continue.access_token.value) + bru.setEnvVar('continueId', body.continue.uri.split('/').pop()) + bru.setEnvVar('tokenId', body?.access_token?.manage.split('/').pop()) }, - getWalletAddressId: async function(host, publicName, varName) { + getWalletAddressId: async function (host, publicName, varName) { const getWalletAddressesQuery = ` query GetWalletAddresses { walletAddresses { @@ -107,16 +117,17 @@ const scripts = { const postRequest = { method: 'post', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({query: getWalletAddressesQuery}) - }; - + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ query: getWalletAddressesQuery }) + } - const response = await fetch(`${bru.getEnvVar(host)}/graphql`, postRequest); - const body = await response.json(); - const walletAddressId = body.data.walletAddresses.edges.map(e => e.node).find(node => node.publicName === publicName)?.id + const response = await fetch(`${bru.getEnvVar(host)}/graphql`, postRequest) + const body = await response.json() + const walletAddressId = body.data.walletAddresses.edges + .map((e) => e.node) + .find((node) => node.publicName === publicName)?.id bru.setEnvVar(varName, walletAddressId) } } -module.exports = scripts; \ No newline at end of file +module.exports = scripts From 686e495843f16cadaa8ddb30ebe6e4f0e32dc3dc Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Wed, 28 Feb 2024 11:51:37 +0100 Subject: [PATCH 13/16] docs: update --- localenv/README.md | 15 ++++++++------- .../src/content/docs/playground/autopeering.md | 2 +- .../src/content/docs/playground/overview.md | 16 ++++++++-------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/localenv/README.md b/localenv/README.md index 0338cf3e2a..84c5e4d81a 100644 --- a/localenv/README.md +++ b/localenv/README.md @@ -73,7 +73,7 @@ When clicking on the Account Name, a list of Transactions appears. - [Rafiki local environment setup](../README.md#environment-setup) - [docker](https://docs.docker.com/get-docker/) -- [Bruno](https://www.usebruno.com/downloads) +- [Bruno](https://www.usebruno.com/downloads), an open source API client ### Setup @@ -159,9 +159,14 @@ pnpm localenv:compose down --volumes #### Bruno & Open Payments APIs -The Open Payments APIs can be interacted with using the [Bruno collection](https://github.com/interledger/rafiki/main/bruno/collections/Interledger) and its ([Open Payments APIs](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20APIs) and [Open Payments Auth APIs](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20Auth%20APIs)). It is configured to use the default endpoints of the local environment. +The Open Payments APIs can be interacted with using the [Bruno collection](https://github.com/interledger/rafiki/main/bruno/collections/Interledger) ([resource server endpoints](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20APIs) and [auth server endpoints](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20Auth%20APIs)). It requires you to -The Examples folder in the Bruno collection includes an [eCommerce example](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Examples/Open%20Payments) that can be executed one by one. It +1. load the collection into Bruno by clicking "Open Collection" +2. navigating to `/rafiki/main/bruno/collections/Interledger` on your machine and +3. clicking "Open" + Furthermore, you need to either load the [Local Environment](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/environments/Local%20Playground.bru) or the [Remote Environment](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/environments/Remote.bru). + +The Examples folder in the Bruno collection includes an [Open Payments](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Examples/Open%20Payments) example that can be executed one by one. It 1. requests the sender's wallet address 2. requests the receiver's wallet address @@ -176,10 +181,6 @@ The Examples folder in the Bruno collection includes an [eCommerce example](http Note that one has to go through the interaction flow after requesting a grant for a outgoing payment. More information about the interaction flow can be found [here](../docs/grant-interaction.md). - - #### Admin UI In order to manage, and view information about the Rafiki instance(s) using a UI, you can navigate to [`localhost:3010`](http://localhost:3010) (Cloud Nine Wallet) or [`localhost:4010`](http://localhost:4010) (Happy Life Bank). This is the `frontend` project which runs a Remix app for querying info and executing mutations against the Rafiki [Admin APIs](#admin-apis). diff --git a/packages/documentation/src/content/docs/playground/autopeering.md b/packages/documentation/src/content/docs/playground/autopeering.md index 6091ece5c1..d1ca36ce2b 100644 --- a/packages/documentation/src/content/docs/playground/autopeering.md +++ b/packages/documentation/src/content/docs/playground/autopeering.md @@ -21,7 +21,7 @@ To use the [Bruno API examples](/playground/overview/#bruno--open-payments-apis) 1. run `docker logs rafiki-cloud-nine-mock-ase-1` (alternatively, check http://localhost:3030) 2. find the list of created wallet addresses 3. copy the url of one of the wallet addresses -4. set the `senderWalletAddress` variable in the Bruno `Remote` environment to that wallet address +4. set the url as `senderWalletAddress` variable in the Bruno `Remote` environment To shut down the connection and to clear the environment, run diff --git a/packages/documentation/src/content/docs/playground/overview.md b/packages/documentation/src/content/docs/playground/overview.md index 38254b7be6..b79aba8734 100644 --- a/packages/documentation/src/content/docs/playground/overview.md +++ b/packages/documentation/src/content/docs/playground/overview.md @@ -75,7 +75,7 @@ When clicking on the Account Name, a list of Transactions appears. - [Rafiki local environment setup](https://github.com/interledger/rafiki/blob/main/README.md#environment-setup) - [docker](https://docs.docker.com/get-docker/) -- [Bruno](https://www.usebruno.com/downloads) +- [Bruno](https://www.usebruno.com/downloads), an open source API client ### Setup @@ -137,9 +137,14 @@ pnpm localenv:compose down --volumes #### Bruno & Open Payments APIs -The Open Payments APIs can be interacted with using the [Bruno collection](https://github.com/interledger/rafiki/main/bruno/collections/Interledger) and its ([Open Payments APIs](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20APIs) and [Open Payments Auth APIs](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20Auth%20APIs)). It requires you to either load the [Local Environment](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/environments/Local%20Playground.bru) or the [Remote Environment](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/environments/Remote.bru). +The Open Payments APIs can be interacted with using the [Bruno collection](https://github.com/interledger/rafiki/main/bruno/collections/Interledger) ([resource server endpoints](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20APIs) and [auth server endpoints](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20Auth%20APIs)). It requires you to -The Examples folder in the Bruno API collection includes an eCommerce (Open Payments) example that can be executed one by one. It +1. load the collection into Bruno by clicking "Open Collection" +2. navigating to `/rafiki/main/bruno/collections/Interledger` on your machine and +3. clicking "Open" + Furthermore, you need to either load the [Local Environment](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/environments/Local%20Playground.bru) or the [Remote Environment](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/environments/Remote.bru). + +The Examples folder in the Bruno collection includes an [Open Payments](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Examples/Open%20Payments) example that can be executed one by one. It 1. requests the sender's wallet address 2. requests the receiver's wallet address @@ -154,11 +159,6 @@ The Examples folder in the Bruno API collection includes an eCommerce (Open Paym Note that one has to go through the interaction flow after requesting a grant for an outgoing payment. More information about the interaction flow can be found [here](/concepts/open-payments/grant-interaction). - - - #### Admin UI In order to manage, and view information about the Rafiki instance(s) using a UI, you can navigate to [`localhost:3010`](http://localhost:3010) (Cloud Nine Wallet) or [`localhost:4010`](http://localhost:4010) (Happy Life Bank). This is the `frontend` project which runs a Remix app for querying info and executing mutations against the Rafiki [Admin APIs](#admin-apis). From dc2e04a7e36900deacfbba28717d605b5cf6d136 Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Wed, 28 Feb 2024 11:52:45 +0100 Subject: [PATCH 14/16] refactor: rename postman -> bruno --- .../Create Outgoing Payment.bru | 0 .../Peer-to-Peer Cross Currency Payment/Create Quote.bru | 0 .../Create Receiver (remote Incoming Payment).bru | 0 .../Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru | 0 .../Peer-to-Peer Payment/Create Outgoing Payment.bru | 0 .../Peer-to-Peer Payment/Create Quote.bru | 0 .../Create Receiver -remote Incoming Payment-.bru | 0 .../Peer-to-Peer Payment/Get Outgoing Payment.bru | 0 .../Interledger/Examples/Open Payments/Continuation Request.bru | 0 .../Examples/Open Payments/Create Incoming Payment.bru | 0 .../Examples/Open Payments/Create Outgoing Payment.bru | 0 .../Interledger/Examples/Open Payments/Create Quote.bru | 0 .../Interledger/Examples/Open Payments/Get Outgoing Payment.bru | 0 .../Examples/Open Payments/Get receiver wallet address.bru | 0 .../Examples/Open Payments/Get sender wallet address.bru | 0 .../Examples/Open Payments/Grant Request Incoming Payment.bru | 0 .../Examples/Open Payments/Grant Request Outgoing Payment.bru | 0 .../Interledger/Examples/Open Payments/Grant Request Quote.bru | 0 .../Incoming Payments/Complete Incoming Payment.bru | 0 .../Incoming Payments/Create Incoming Payment.bru | 0 .../Incoming Payments/Get Incoming Payment -Unauthenticated-.bru | 0 .../Open Payments APIs/Incoming Payments/Get Incoming Payment.bru | 0 .../Incoming Payments/List Incoming Payments.bru | 0 .../Outgoing Payments/Create Outgoing Payment.bru | 0 .../Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru | 0 .../Outgoing Payments/List Outgoing Payments.bru | 0 .../Interledger/Open Payments APIs/Quotes/Create Quote.bru | 0 .../Interledger/Open Payments APIs/Quotes/Get Quote.bru | 0 .../Open Payments APIs/Wallet Address/Get Wallet Address Keys.bru | 0 .../Open Payments APIs/Wallet Address/Get a Wallet Address.bru | 0 .../Open Payments Auth APIs/Grants/Continuation Request.bru | 0 .../Interledger/Open Payments Auth APIs/Grants/Grant Request.bru | 0 .../Open Payments Auth APIs/Tokens/Revoke Access Token.bru | 0 .../Open Payments Auth APIs/Tokens/Rotate Access Token.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Create Asset.bru | 0 .../Interledger/Rafiki Admin APIs/Create Incoming Payment.bru | 0 .../Rafiki Admin APIs/Create Or Update Peer By Url.bru | 0 .../Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Create Peer.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Create Quote.bru | 0 .../Create Receiver (remote Incoming Payment).bru | 0 .../Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru | 0 .../Rafiki Admin APIs/Create Wallet Address Withdrawal.bru | 0 .../Interledger/Rafiki Admin APIs/Create Wallet Address.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Delete Peer.bru | 0 .../Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru | 0 .../Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru | 0 .../Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru | 0 .../Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Get Asset.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Get Assets.bru | 0 .../Interledger/Rafiki Admin APIs/Get Incoming Payment.bru | 0 .../Interledger/Rafiki Admin APIs/Get Outgoing Payment.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Get Payments.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Get Peer.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Get Peers.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Get Quote.bru | 0 .../Rafiki Admin APIs/Get Receiver (remote Incoming Payment).bru | 0 .../Interledger/Rafiki Admin APIs/Get Wallet Address.bru | 0 .../Interledger/Rafiki Admin APIs/Get Wallet Addresses.bru | 0 .../Interledger/Rafiki Admin APIs/Get Webhook Events.bru | 0 .../Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru | 0 .../Interledger/Rafiki Admin APIs/Revoke Wallet Address Key.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Set Fee.bru | 0 .../Rafiki Admin APIs/Trigger Wallet Address Events.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Update Asset.bru | 0 .../collections/Interledger/Rafiki Admin APIs/Update Peer.bru | 0 .../Interledger/Rafiki Admin APIs/Update Wallet Address.bru | 0 .../Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru | 0 .../Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru | 0 .../Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru | 0 .../Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru | 0 .../Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru | 0 .../Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru | 0 .../collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru | 0 .../collections/Interledger/Rafiki Admin Auth APIs/Get Grants.bru | 0 .../Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru | 0 {postman => bruno}/collections/Interledger/bruno.json | 0 .../collections/Interledger/environments/Local Playground.bru | 0 .../collections/Interledger/environments/Remote.bru | 0 {postman => bruno}/collections/Interledger/scripts/scripts.js | 0 81 files changed, 0 insertions(+), 0 deletions(-) rename {postman => bruno}/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver (remote Incoming Payment).bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Open Payments/Continuation Request.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Open Payments/Create Quote.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Incoming Payments/List Incoming Payments.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Quotes/Create Quote.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Quotes/Get Quote.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Wallet Address/Get Wallet Address Keys.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments APIs/Wallet Address/Get a Wallet Address.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru (100%) rename {postman => bruno}/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Create Asset.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Create Peer.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Create Quote.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Create Receiver (remote Incoming Payment).bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Delete Peer.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Asset.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Assets.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Incoming Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Outgoing Payment.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Payments.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Peer.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Peers.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Quote.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Receiver (remote Incoming Payment).bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Wallet Address.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Wallet Addresses.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Get Webhook Events.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Revoke Wallet Address Key.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Set Fee.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Trigger Wallet Address Events.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Update Asset.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Update Peer.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Update Wallet Address.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin Auth APIs/Get Grants.bru (100%) rename {postman => bruno}/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru (100%) rename {postman => bruno}/collections/Interledger/bruno.json (100%) rename {postman => bruno}/collections/Interledger/environments/Local Playground.bru (100%) rename {postman => bruno}/collections/Interledger/environments/Remote.bru (100%) rename {postman => bruno}/collections/Interledger/scripts/scripts.js (100%) diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru b/bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru rename to bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Outgoing Payment.bru diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru b/bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru similarity index 100% rename from postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru rename to bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Quote.bru diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver (remote Incoming Payment).bru b/bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver (remote Incoming Payment).bru similarity index 100% rename from postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver (remote Incoming Payment).bru rename to bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Create Receiver (remote Incoming Payment).bru diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru b/bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru rename to bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Cross Currency Payment/Get Outgoing Payment.bru diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru b/bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru rename to bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Outgoing Payment.bru diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru b/bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru similarity index 100% rename from postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru rename to bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Quote.bru diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru b/bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru similarity index 100% rename from postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru rename to bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Create Receiver -remote Incoming Payment-.bru diff --git a/postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru b/bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru rename to bruno/collections/Interledger/Examples/Admin API - only locally/Peer-to-Peer Payment/Get Outgoing Payment.bru diff --git a/postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru b/bruno/collections/Interledger/Examples/Open Payments/Continuation Request.bru similarity index 100% rename from postman/collections/Interledger/Examples/Open Payments/Continuation Request.bru rename to bruno/collections/Interledger/Examples/Open Payments/Continuation Request.bru diff --git a/postman/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru b/bruno/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru similarity index 100% rename from postman/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru rename to bruno/collections/Interledger/Examples/Open Payments/Create Incoming Payment.bru diff --git a/postman/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru b/bruno/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru rename to bruno/collections/Interledger/Examples/Open Payments/Create Outgoing Payment.bru diff --git a/postman/collections/Interledger/Examples/Open Payments/Create Quote.bru b/bruno/collections/Interledger/Examples/Open Payments/Create Quote.bru similarity index 100% rename from postman/collections/Interledger/Examples/Open Payments/Create Quote.bru rename to bruno/collections/Interledger/Examples/Open Payments/Create Quote.bru diff --git a/postman/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru b/bruno/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru rename to bruno/collections/Interledger/Examples/Open Payments/Get Outgoing Payment.bru diff --git a/postman/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru b/bruno/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru similarity index 100% rename from postman/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru rename to bruno/collections/Interledger/Examples/Open Payments/Get receiver wallet address.bru diff --git a/postman/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru b/bruno/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru similarity index 100% rename from postman/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru rename to bruno/collections/Interledger/Examples/Open Payments/Get sender wallet address.bru diff --git a/postman/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru b/bruno/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru similarity index 100% rename from postman/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru rename to bruno/collections/Interledger/Examples/Open Payments/Grant Request Incoming Payment.bru diff --git a/postman/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru b/bruno/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru rename to bruno/collections/Interledger/Examples/Open Payments/Grant Request Outgoing Payment.bru diff --git a/postman/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru b/bruno/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru similarity index 100% rename from postman/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru rename to bruno/collections/Interledger/Examples/Open Payments/Grant Request Quote.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru b/bruno/collections/Interledger/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru rename to bruno/collections/Interledger/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru b/bruno/collections/Interledger/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru rename to bruno/collections/Interledger/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru b/bruno/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru rename to bruno/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru b/bruno/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru rename to bruno/collections/Interledger/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Incoming Payments/List Incoming Payments.bru b/bruno/collections/Interledger/Open Payments APIs/Incoming Payments/List Incoming Payments.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Incoming Payments/List Incoming Payments.bru rename to bruno/collections/Interledger/Open Payments APIs/Incoming Payments/List Incoming Payments.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru b/bruno/collections/Interledger/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru rename to bruno/collections/Interledger/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru b/bruno/collections/Interledger/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru rename to bruno/collections/Interledger/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru b/bruno/collections/Interledger/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru rename to bruno/collections/Interledger/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Quotes/Create Quote.bru b/bruno/collections/Interledger/Open Payments APIs/Quotes/Create Quote.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Quotes/Create Quote.bru rename to bruno/collections/Interledger/Open Payments APIs/Quotes/Create Quote.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Quotes/Get Quote.bru b/bruno/collections/Interledger/Open Payments APIs/Quotes/Get Quote.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Quotes/Get Quote.bru rename to bruno/collections/Interledger/Open Payments APIs/Quotes/Get Quote.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Wallet Address/Get Wallet Address Keys.bru b/bruno/collections/Interledger/Open Payments APIs/Wallet Address/Get Wallet Address Keys.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Wallet Address/Get Wallet Address Keys.bru rename to bruno/collections/Interledger/Open Payments APIs/Wallet Address/Get Wallet Address Keys.bru diff --git a/postman/collections/Interledger/Open Payments APIs/Wallet Address/Get a Wallet Address.bru b/bruno/collections/Interledger/Open Payments APIs/Wallet Address/Get a Wallet Address.bru similarity index 100% rename from postman/collections/Interledger/Open Payments APIs/Wallet Address/Get a Wallet Address.bru rename to bruno/collections/Interledger/Open Payments APIs/Wallet Address/Get a Wallet Address.bru diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru b/bruno/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru similarity index 100% rename from postman/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru rename to bruno/collections/Interledger/Open Payments Auth APIs/Grants/Continuation Request.bru diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru b/bruno/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru similarity index 100% rename from postman/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru rename to bruno/collections/Interledger/Open Payments Auth APIs/Grants/Grant Request.bru diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru b/bruno/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru similarity index 100% rename from postman/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru rename to bruno/collections/Interledger/Open Payments Auth APIs/Tokens/Revoke Access Token.bru diff --git a/postman/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru b/bruno/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru similarity index 100% rename from postman/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru rename to bruno/collections/Interledger/Open Payments Auth APIs/Tokens/Rotate Access Token.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Create Asset.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Asset.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Create Asset.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Create Incoming Payment.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Create Or Update Peer By Url.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Create Outgoing Payment.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Peer.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Create Peer.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Peer.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Create Peer.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Create Quote.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Quote.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Create Quote.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Receiver (remote Incoming Payment).bru b/bruno/collections/Interledger/Rafiki Admin APIs/Create Receiver (remote Incoming Payment).bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Receiver (remote Incoming Payment).bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Create Receiver (remote Incoming Payment).bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Key.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Create Wallet Address Withdrawal.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Create Wallet Address.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Delete Peer.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Delete Peer.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Delete Peer.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Delete Peer.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Deposit Asset Liquidity.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Deposit Event Liquidity.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Deposit Outgoing Payment Liquidity.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Deposit Peer Liquidity.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Asset.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Asset.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Asset.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Asset.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Assets.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Assets.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Assets.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Assets.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Incoming Payment.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Incoming Payment.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Incoming Payment.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Incoming Payment.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Outgoing Payment.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Outgoing Payment.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Outgoing Payment.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Outgoing Payment.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Payments.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Payments.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Payments.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Payments.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Peer.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Peer.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Peer.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Peer.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Peers.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Peers.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Peers.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Peers.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Quote.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Quote.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Quote.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Quote.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Receiver (remote Incoming Payment).bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Receiver (remote Incoming Payment).bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Receiver (remote Incoming Payment).bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Receiver (remote Incoming Payment).bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Address.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Wallet Address.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Address.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Wallet Address.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Addresses.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Wallet Addresses.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Wallet Addresses.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Wallet Addresses.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Get Webhook Events.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Get Webhook Events.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Get Webhook Events.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Get Webhook Events.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Post Liquidity Withdrawal.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Revoke Wallet Address Key.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Revoke Wallet Address Key.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Revoke Wallet Address Key.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Revoke Wallet Address Key.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Set Fee.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Set Fee.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Set Fee.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Set Fee.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Trigger Wallet Address Events.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Trigger Wallet Address Events.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Trigger Wallet Address Events.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Trigger Wallet Address Events.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Update Asset.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Update Asset.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Update Asset.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Update Asset.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Update Peer.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Update Peer.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Update Peer.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Update Peer.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Update Wallet Address.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Update Wallet Address.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Update Wallet Address.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Update Wallet Address.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Void Liquidity Withdrawal.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Withdraw Asset Liquidity.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Withdraw Event Liquidity.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Withdraw Incoming Payment Liquidity.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Withdraw Outgoing Payment Liquidity.bru diff --git a/postman/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru b/bruno/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru rename to bruno/collections/Interledger/Rafiki Admin APIs/Withdraw Peer Liquidity.bru diff --git a/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru b/bruno/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru rename to bruno/collections/Interledger/Rafiki Admin Auth APIs/Get Grant.bru diff --git a/postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grants.bru b/bruno/collections/Interledger/Rafiki Admin Auth APIs/Get Grants.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin Auth APIs/Get Grants.bru rename to bruno/collections/Interledger/Rafiki Admin Auth APIs/Get Grants.bru diff --git a/postman/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru b/bruno/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru similarity index 100% rename from postman/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru rename to bruno/collections/Interledger/Rafiki Admin Auth APIs/Revoke Grant.bru diff --git a/postman/collections/Interledger/bruno.json b/bruno/collections/Interledger/bruno.json similarity index 100% rename from postman/collections/Interledger/bruno.json rename to bruno/collections/Interledger/bruno.json diff --git a/postman/collections/Interledger/environments/Local Playground.bru b/bruno/collections/Interledger/environments/Local Playground.bru similarity index 100% rename from postman/collections/Interledger/environments/Local Playground.bru rename to bruno/collections/Interledger/environments/Local Playground.bru diff --git a/postman/collections/Interledger/environments/Remote.bru b/bruno/collections/Interledger/environments/Remote.bru similarity index 100% rename from postman/collections/Interledger/environments/Remote.bru rename to bruno/collections/Interledger/environments/Remote.bru diff --git a/postman/collections/Interledger/scripts/scripts.js b/bruno/collections/Interledger/scripts/scripts.js similarity index 100% rename from postman/collections/Interledger/scripts/scripts.js rename to bruno/collections/Interledger/scripts/scripts.js From 846f25f63b8f6843dc2bf5a64b9e7e8c128746fd Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Wed, 28 Feb 2024 11:53:50 +0100 Subject: [PATCH 15/16] chore: update ignore files --- .dockerignore | 3 +-- .eslintignore | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.dockerignore b/.dockerignore index 373a2f8005..9423372918 100644 --- a/.dockerignore +++ b/.dockerignore @@ -17,8 +17,7 @@ Dockerfile commitlint.config.js jest.config.base.js renovate.json -postman -.postman +bruno **/jest.config.js **/jest.setup.js diff --git a/.eslintignore b/.eslintignore index 139c39c7b1..c4fb878c56 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,6 +3,4 @@ public **/generated dist build -postman-scripts -postman -.postman \ No newline at end of file +bruno \ No newline at end of file From b7708c13903f84472de277d39ddb294929017b64 Mon Sep 17 00:00:00 2001 From: Sabine Schaller Date: Thu, 29 Feb 2024 11:33:27 +0100 Subject: [PATCH 16/16] fix: path Co-authored-by: Max Kurapov --- packages/documentation/src/content/docs/playground/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/documentation/src/content/docs/playground/overview.md b/packages/documentation/src/content/docs/playground/overview.md index b79aba8734..6be1679d1d 100644 --- a/packages/documentation/src/content/docs/playground/overview.md +++ b/packages/documentation/src/content/docs/playground/overview.md @@ -140,7 +140,7 @@ pnpm localenv:compose down --volumes The Open Payments APIs can be interacted with using the [Bruno collection](https://github.com/interledger/rafiki/main/bruno/collections/Interledger) ([resource server endpoints](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20APIs) and [auth server endpoints](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/Open%20Payments%20Auth%20APIs)). It requires you to 1. load the collection into Bruno by clicking "Open Collection" -2. navigating to `/rafiki/main/bruno/collections/Interledger` on your machine and +2. navigating to `/rafiki/bruno/collections/Interledger` on your machine and 3. clicking "Open" Furthermore, you need to either load the [Local Environment](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/environments/Local%20Playground.bru) or the [Remote Environment](https://github.com/interledger/rafiki/main/bruno/collections/Interledger/environments/Remote.bru).