diff --git a/loyalty-program/README.md b/loyalty-program/README.md index be3499c..ba88656 100644 --- a/loyalty-program/README.md +++ b/loyalty-program/README.md @@ -1,8 +1,6 @@ # Hyperledger Fabric Quant Sandbox Tutorial - A Loyalty Program Use Case -## Requirements -We will need to have an mDApp registered with Quant. We can register one [here](https://developer.quant.network/login). - +## Introduction This short tutorial will guide us on how to create a simple contract interaction flow for a loyalty program use case. In the Hyperledger Fabric Quant sandbox, we have deployed two extended QRC Tier 1 smart contracts. @@ -38,368 +36,231 @@ Here is a list of the most useful QRC-721 functions to us | Read | name | Returns the name of the QRC-721 token as a string | N | | | Read | symbol | Returns the symbol of the QRC-721 token as a string | N | | - -A comprehensive list of all the parameters for each function of the QRC-20 & QRC-721 contracts will be made available soon. - - -## Loyalty Program Use Case +## Loyalty Program - Step by Step Tutorial Applications interact with the contracts in the following manner: - 100 Loyalty Point tokens are requested by calling the "requestTokens" function in the QRC-20 contract - 1 Flight Reward token is redeemed in exchange for 100 Loyalty Points by calling the "redeemToken" function in the QRC-721 contract -## Step by Step Tutorial +In this step by step tutorial, we will go through a simple flow: + +1. Create an Identity +2. Request Loyalty Point tokens +3. Check account balances for the amount of Loyalty Points we own +4. Redeem Flight Rewards for Loyalty Points -To get an account created on the Hyperledger Fabric sandbox network, we need to register a new Application on the [Overledger Dashboard](https://developer.quant.network/login). The clientId assigned to the application will be automatically enrolled as the identity of the application on the sandbox network. Any previously registered application within the Overledger Dashboard will already have their clientId enrolled on the Hyperledger Fabric Quant Sandbox. +### 1. Create an Identity -In this tutorial, we will go through a simple flow +There are currently two Quant Sandbox networks for Hyperledger Fabric: +- Quant Sandbox +- Quant Oracle Sandbox Testnet -1. Request Loyalty Point tokens -2. Check account balances for the amount of Loyalty Points we own -3. Redeem Flight Rewards for Loyalty Points +Before being able to use any of the networks, you must register a new Application in [Quant Connect](https://connect.quant.network). -Each of the following sections follows a "preparation->execution" pattern which Overledger works by. For each API call, we will first prepare a request, then validate the response and finally execute the request. +An identity in the 'Quant Sandbox' network is automatically enrolled when creating an Application. The identity name will equal the clientId associated with the Application. -### 1. Request Loyalty Points +To enroll an identity in the 'Quant Oracle Sandbox Testnet' you must manually call the [Create Account](https://developers.quant.network/reference/createaccountfororaclefabric) endpoint. An identity with the name of the clientId that calls the endpoint will be enrolled in the network. You can only call the endpoint once per Application/clientId. + +### 2. Request Loyalty Points As we use our clientId and access token for authentication and Hyperledger Fabric is a permissioned technology, we do not require client side management of private keys. -To claim loyalty Point tokens, we can construct a REST API request such as the following. +To claim loyalty Point tokens, we use Overledgers Smart Contract API. The `smartContractId` field is set to `loyaltypoint` which is the id for the chaincode representing the Loyalty Point tokens. + +> See the [Quant Developer Hub](https://developers.quant.network/reference/how-to-access-overledger-apis) for additional API documentation. -Note: the `destinationId` field is set to `loyaltypoint` which is the id for the contract representing the Loyalty Point tokens. +> Note that the URLs for interacting with the 'Quant Sandbox' and 'Quant Oracle Sandbox Testnet' are different. While the 'Quant Sandbox' network is available through the Overledger APIs, the 'Quant Oracle Sandbox Testnet' is available through Overledger Beta APIs. Preparation Request: -POST `https://api.sandbox.overledger.io/v2/preparation/transaction` + +- Quant Sandbox: POST `https://api.sandbox.overledger.io/api/preparations/transactions/smart-contracts/write` - [docs](https://developers.quant.network/reference/preparesmartcontractwrite) +- Quant Oracle Sandbox Testnet: POST `https://hook.eu2.make.com/qbtbxaze4rxiforl3sw2gs0tdx2mtw80` - [docs](https://developers.quant.network/reference/preparesmartcontractwritefororaclefabric) ``` { - "type": "Contract Invoke", - "location": { - "technology": "Hyperledger Fabric", - "network": "Quant Sandbox" - }, - "urgency": "normal", - "requestDetails": { - "origin": [ - { - "originId": "" - } - ], - "destination": [ - { - "destinationId": "loyaltypoint", - "smartContract": { - "function": { - "name": "requestTokens", - "inputParameters": [ - ] - } - } - } - ] - } + "location": { + "technology": "Hyperledger Fabric", + "network": "Quant Sandbox" + }, + "signingAccountId": "", + "smartContractId": "loyaltypoint", + "functionName": "requestTokens", + "inputParameters": [] } ``` Preparation Response: ``` { - "requestId": "a58e0a1f-2251-407c-8e4b-2bf5efa092ec", - "gatewayFee": { - "amount": "0", - "unit": "QNT" - }, - "dltFee": { - "amount": "0", - "unit": "N/A" - }, - "nativeData": { - "origin": [ - { - "originId": "" - } - ], - "destination": [ - { - "destinationId": "loyaltypoint", - "smartContract": { - "function": { - "name": "requestTokens", - "inputParameters": [] - } - } - } - ] - } + "requestId": "a58e0a1f-2251-407c-8e4b-2bf5efa092ec", + "gatewayFee": { + "amount": "0", + "unit": "QNT" + }, + "dltFee": { + "amount": "0", + "unit": "N/A" + }, + "nativeData": {} } ``` -The body of the API prepare request contains the following parameters: - -| Parameters | Definition| -|---|---| -|type |Request type| -|location| The network to which we submit the transaction| -|urgency| A value that defines how fast a transaction is processed on a network. For Hyperledger Fabric, the value is normal| -|originId| Unique Identifier of the origin/sender| -|destinationId| The name of the token that we invoke a function of| -|name | [within the function object] This is the function name that Overledger will invoke on the contract| - - Now that we have prepared a transaction, we get a confirmation of the prepared request and its assigned requestId. We can execute the transaction by posting the requestId to the execution API. Execution Request: -POST `https://api.sandbox.overledger.io/v2/execution/transaction` +- Quant Sandbox: POST `https://api.sandbox.overledger.io/api/executions/transactions` - [docs](https://developers.quant.network/reference/executesignedrequest) +- Quant Oracle Sandbox Testnet: POST `https://hook.eu2.make.com/jd77jtwdg4lm3gt6f23cn1ds5qh9xgdf` - [docs](https://developers.quant.network/reference/executesignedwritetransactionfororaclefabric) ``` { - "requestId": "a58e0a1f-2251-407c-8e4b-2bf5efa092ec" + "requestId": "a58e0a1f-2251-407c-8e4b-2bf5efa092ec" } ``` Execution Response: ``` { - "requestId": "a58e0a1f-2251-407c-8e4b-2bf5efa092ec", - "overledgerTransactionId": "0dfef426-40ef-4c8f-85fc-d573ed8830a9", - "transactionId": "8b93b3662a0a467c08537131e60cac0a8fef0f6335a44cc0568d49f350cd29fd", - "type": "contract invoke", - "location": { - "technology": "Hyperledger Fabric", - "network": "Quant Sandbox" - }, - "urgency": "normal", - "status": { - "value": "SUCCESSFUL", - "code": "TXN1002", - "description": "Transaction successful", - "message": "Transaction successful", - "timestamp": "1656937087" - } + "location": { + "technology": "Hyperledger Fabric", + "network": "Quant Sandbox" + }, + "requestId": "a58e0a1f-2251-407c-8e4b-2bf5efa092ec", + "transactionId": "8b93b3662a0a467c08537131e60cac0a8fef0f6335a44cc0568d49f350cd29fd", + "status": { + "description": "Transaction successful", + "value": "SUCCESSFUL" + }, + "timestamp": "1656937087" } ``` Please note that this function can only be invoked as long as the account does not hold any Loyalty Point tokens. -### 2. Check Account Balances +### 3. Check Account Balances Now that we have our Loyalty Point tokens, we can query our account balance to check how many tokens we have received. The requestTokens function has been configured to deliver 100 tokens, and we can verify by calling the Smart Contract Read API. The only input parameter required is the clientId. -Preparation Request: -POST `https://api.sandbox.overledger.io/v2/preparation/search/smartcontract` +Smart Contract Read Request: +- Quant Sandbox: POST `https://api.sandbox.overledger.io/api/smart-contracts/read` - [docs](https://developers.quant.network/reference/readsmartcontract) +- Quant Oracle Sandbox Testnet: POST `https://hook.eu2.make.com/9af8outacmb6bakbxmgq6t9qkt3v49ky` - [docs](https://developers.quant.network/reference/smartcontractreadfororaclefabric) ``` { - "location": { - "technology": "Hyperledger Fabric", - "network": "Quant Sandbox" - }, - "requestDetails": { - "destination": [ - { - "smartContract": { - "smartContractId": "loyaltypoint", - "function": { - "name": "balanceOf", - "inputParameters": [ - { - "type": "identity", - "value": "" - } - ], - "outputParameters": [ - ] - } - } - } - ] + "location": { + "technology": "Hyperledger Fabric", + "network": "Quant Sandbox" + }, + "smartContractId": "loyaltypoint", + "functionName": "balanceOf", + "inputParameters": [ + { + "type": "identity", + "value": "" } -} -``` - -Preparation Response: -``` -{ - "requestId": "adbee021-43b6-431a-9f5a-d2bdc7118bf7", - "gatewayFee": { - "amount": "0", - "unit": "QNT" + ], + "outputParameters": [ + { + "type": "string" } + ] } ``` -| Parameters | Definition| -|---|---| -|location| The network to which we submit the transaction| -|smartContractId| The name of the token that we are making a search request for| -|name | [within the function object] This is the function name that Overledger will read| -|type| It defines the value type suplied in the request| -|value| In this example, it is the identity so that we can get our token balance| - -For the execution requestId, we provide the requestId we have received from the smart contract read preparation response. - -Execution Request: -POST `https://api.sandbox.overledger.io/v2/execution/search/smartcontract?requestId=adbee021-43b6-431a-9f5a-d2bdc7118bf7` -Execution Response: +Smart Contract Read Response: ``` { - "location": { - "technology": "Hyperledger Fabric", - "network": "Quant Sandbox" - }, - "smartContract": { - "smartContractId": "loyaltypoint", - "function": { - "functionId": "", - "name": "balanceOf", - "inputParameters": [ - { - "value": "", - "type": "identity" - } - ], - "outputParameters": [ - { - "value": "100", - "type": "string" - } - ] - } + "location": { + "technology": "Hyperledger Fabric", + "network": "Quant Sandbox" + }, + "smartContractId": "loyaltypoint", + "functionName": "balanceOf", + "outputParameters": [ + { + "type": "string", + "value": "100" } + ] } ``` As we can see, we got a balance of 100 tokens in the output parameters of the smart contract read response. We can now proceed to use these Loyalty point tokens to redeem a reward. -### 3. Redeem Flight Rewards +### 4. Redeem Flight Rewards -To redeem the rewards (which are represented by QRC-721 tokens), we interact with the QRC-721 contract. In order to do this, we need to change the destinationId,the function we are invoking and the input parameters we are passing in. +To redeem the rewards (which are represented by QRC-721 tokens), we interact with the QRC-721 contract deployed on the chain. To do this, we use the following parameters in the request: +- `flightreward` as the smartContractId. +- `redeemToken` as the functionName. -- For the destinationId (which is the contract id), we should set `flightreward` -- The function name is `redeemToken` -- The input parameters are: - - Parameter 1, which should be a stringified random non-negative integer less than 2^256 - this will be the ID assigned to the reward. - - Parameter 2, which can be any stringified JSON metadata - we have provided examples below +The inputParameters are: +1. A stringified random non-negative integer less than 2^256 - this will be the ID assigned to the reward. +2. Any stringified JSON metadata - we have provided examples below. Preparation Request: -POST `https://api.sandbox.overledger.io/v2/preparation/transaction` +- Quant Sandbox: POST `https://api.sandbox.overledger.io/api/preparations/transactions/smart-contracts/write` - [docs](https://developers.quant.network/reference/preparesmartcontractwrite) +- Quant Oracle Sandbox Testnet: POST `https://hook.eu2.make.com/qbtbxaze4rxiforl3sw2gs0tdx2mtw80` - [docs](https://developers.quant.network/reference/preparesmartcontractwritefororaclefabric) ``` { - "type": "Contract Invoke", - "location": { - "technology": "Hyperledger Fabric", - "network": "Quant Sandbox" + "location": { + "technology": "Hyperledger Fabric", + "network": "Quant Sandbox" + }, + "signingAccountId": "", + "smartContractId": "flightreward", + "functionName": "redeemToken", + "inputParameters": [ + { + "type": "string", + "value": "12345678" }, - "urgency": "normal", - "requestDetails": { - "origin": [ - { - "originId": "" - } - ], - "destination": [ - { - "destinationId": "flightreward", - "smartContract": { - "function": { - "name": "redeemToken", - "inputParameters": [ - { - "type": "string", - "value": "12345678" - }, - { - "type": "string", - "value": "{\"from\":\"London\",\"to\":\"Athens\",\"date\":\"1656938960\"}" - } - ] - } - } - } - ] + { + "type": "string", + "value": "{\"from\":\"London\",\"to\":\"Athens\",\"date\":\"1656938960\"}" } + ] } ``` Preparation Response: ``` { - "requestId": "a4f8ce0c-1be7-4f08-b924-685e48a29694", - "gatewayFee": { - "amount": "0", - "unit": "QNT" - }, - "dltFee": { - "amount": "0", - "unit": "N/A" - }, - "nativeData": { - "origin": [ - { - "originId": "" - } - ], - "destination": [ - { - "destinationId": "flightreward", - "smartContract": { - "function": { - "name": "redeemToken", - "inputParameters": [ - { - "value": "12345678", - "type": "string" - }, - { - "value": "{\"from\":\"London\",\"to\":\"Athens\",\"date\":\"1656938960\"}", - "type": "string" - } - ] - } - } - } - ] - } + "requestId": "a4f8ce0c-1be7-4f08-b924-685e48a29694", + "gatewayFee": { + "amount": "0", + "unit": "QNT" + }, + "dltFee": { + "amount": "0", + "unit": "N/A" + }, + "nativeData": {} } ``` -| Parameters | Definition| -|---|---| -|type |Request type| -|location| The network to which we submit the transaction| -|urgency| A value that defines how fast a transaction is processed on a network. For Hyperledger Fabric, the value is normal| -|originId| Unique Identifier of the origin/sender| -|destinationId| The name of the token that we invoke a function of| -|name | [within the function object] This is the function name that Overledger will invoke on the network| -|type| It defines the value type supplied in the request| -|value| In this example, it is the flight Reward reference and metadata| + Execution Request: -POST `https://api.sandbox.overledger.io/v2/execution/transaction` +- Quant Sandbox: POST `https://api.sandbox.overledger.io/api/executions/transactions` - [docs](https://developers.quant.network/reference/executesignedrequest) +- Quant Oracle Sandbox Testnet: POST `https://hook.eu2.make.com/jd77jtwdg4lm3gt6f23cn1ds5qh9xgdf` - [docs](https://developers.quant.network/reference/executesignedwritetransactionfororaclefabric) ``` { - "requestId": "a4f8ce0c-1be7-4f08-b924-685e48a29694" + "requestId": "a4f8ce0c-1be7-4f08-b924-685e48a29694" } ``` Execution Response: ``` { - "requestId": "a4f8ce0c-1be7-4f08-b924-685e48a29694", - "overledgerTransactionId": "d6795a5d-74d8-4583-b452-d90676c6c050", - "transactionId": "46c7ff69e6eec7039dbd911e67a4cde9cdcf4c93ee1580ed7f49d59540a99918", - "type": "contract invoke", - "location": { - "technology": "Hyperledger Fabric", - "network": "Quant Sandbox" - }, - "urgency": "normal", - "status": { - "value": "SUCCESSFUL", - "code": "TXN1002", - "description": "Transaction successful", - "message": "Transaction successful", - "timestamp": "1656939052" - } + "location": { + "technology": "Hyperledger Fabric", + "network": "Quant Sandbox" + }, + "requestId": "a4f8ce0c-1be7-4f08-b924-685e48a29694", + "transactionId": "46c7ff69e6eec7039dbd911e67a4cde9cdcf4c93ee1580ed7f49d59540a99918", + "status": { + "description": "Transaction successful", + "value": "SUCCESSFUL" + }, + "timestamp": "1656939052" } ```