QR code mechanism

Scanning QR codes

This section serves to illustrate how wallets can employ the QR code scanning feature to carry out tasks such as login, smart contract invocation, and other services.

There are two parties that are involved in the process:

  • The dApp : Blanket term that representsdApps developed for the users of Ontology ecosystem.

  • The Provider: Wallets that support dAPI , and adhere to it's specifications.

Interaction process

A dApp provides a QR code and the user scans it using the wallet. The QR code mechanism currently supports two functions: login and contract invocation.

Login by scanning QR code

The process flow is as follows-

  1. Wallet scans the QR code provided by the dApp.

  2. Provider fetches the callback URL and the verification message, carries out user authentication and signature, and the transaction is carries out using the dApps callback address.

  3. The dApp back end carries out signature verification and returns the result to the wallet.

Invoke smart contract using QR code

The process flow is as follows-

  1. Wallet scans the QR code provided by the dApp.

  2. Wallet initiates a transaction, the user signs it, the transaction is pre-executed, the user provides confirmation, the information is transmitted on to the chain, and finally the transaction hash is returned to the dApp back end using the callback address provided.

  3. dApp back end uses the transaction hash to query the successful contract execution and transaction details.

dAPI protocol usage

The following scenarios can be realized by integrating the dAPI -

Login

Authentication is carried out by scanning the QR code from the wallet. The wallet fetches login parameters, carries out signature authorization and sends them to the dApp back end.

{
    "action": "login",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "params": {
        "type": "ontid or address",
        "dappName": "dapp Name",
        "dappIcon": "dapp Icon",
        "message": "helloworld",
        "expire": 1546415363, # QR Code expire time
        "callback": "http://101.132.193.149:4027/blockchain/v1/common/test-onto-login"
    }
}

dApp back end's return interface

Here's the post method message structure:

# method:post
{
    "action": "login",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "params": {
        "type": "ontid or address",
        "user": "did:ont:AUEKhXNsoAT27HJwwqFGbpRy8QLHUMBMPz or AUEKhXNsoAT27HJwwqFGbpRy8QLHUMBMPz",
        "message": "helloworld",
        "publickey": "0205c8fff4b1d21f4b2ec3b48cf88004e38402933d7e914b2a0eda0de15e73ba61",
        "signature": "01abd7ea9d79c857cd838cabbbaad3efb44a6fc4f5a5ef52ea8461d6c055b8a7cf324d1a58962988709705cefe40df5b26e88af3ca387ec5036ec7f5e6640a1754"
    }
}

If the transaction was successful, the success message is sent in response.

{
  "action": "login",
  "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
  "error": 0,
  "desc": "SUCCESS",
  "result": true
}

Otherwise, the failure message is sent in response.

{
  "action": "login",
  "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
  "error": 80001,
  "desc": "PARAMS ERROR",
  "result": 1
}

Message Signature

Message signature is essentially the same as login protocol, except that the dApp name and the icon are not a part of the request that is sent.

The structure of the signature request sent by the dApp after URI and Base64 encoding are as follows:

{
    "action": "signMessage",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "params": {
        "type": "ontid or address",
        "message": "helloworld",
        "ishex": false
        "callback": "http://101.132.193.149:4027/blockchain/v1/common/test-onto-login"
    }
}

Or when multiple messages are signed:

{
    "action": "signMultiMessage",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "params": {
        "type": "ontid or address",
        "message": ["aabbccdd"],
        "ishex": true
        "callback": "http://101.132.193.149:4027/blockchain/v1/common/test-onto-login"
    }
}

The response that the wallet sends back to the dApp, after URI and Base 64 encoding, is structured as follows:

# method: post
{
    "action": "signMessage",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "error": 0,
    "desc": "SUCCESS",
    "result": {
        "type": "ontid or address",
        "user": "did:ont:AUEKhXNsoAT27HJwwqFGbpRy8QLHUMBMPz or AUEKhXNsoAT27HJwwqFGbpRy8QLHUMBMPz",
        "message": "helloworld",
        "publickey": "0205c8fff4b1d21f4b2ec3b48cf88004e38402933d7e914b2a0eda0de15e73ba61",
        "signature": "01abd7ea9d79c857cd838cabbbaad3efb44a6fc4f5a5ef52ea8461d6c055b8a7cf324d1a58962988709705cefe40df5b26e88af3ca387ec5036ec7f5e6640a1754"
    }
}

If the action is "multimessage" the response sent back to the dApp is an array

Contract Invocation

A payment operation also falls under the category of contract invocation, adopting a uniform protocol standard. The standard can be defined as follows:

{
    "action": "invoke",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "params": {
        "login": true,
        "callback": "http://101.132.193.149:4027/invoke/callback",
        "qrcodeUrl": "http://101.132.193.149:4027/qrcode/AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ"
    }
}

The data obtained from the qrcodeURL link's GET method is as follows-

{
    "action": "invoke",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "params": {
        "invokeConfig": {
            "contractHash": "16edbe366d1337eb510c2ff61099424c94aeef02",
            "functions": [{
                "operation": "method name",
                "args": [{
                    "name": "arg0-list",
                    "value": [true, 100, "Long:100000000000", "Address:AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ", "ByteArray:aabb", "String:hello", [true, 100], {
                        "key": 6
                    }]
                }, {
                    "name": "arg1-map",
                    "value": {
                        "key": "String:hello",
                        "key1": "ByteArray:aabb",
                        "key2": "Long:100000000000",
                        "key3": true,
                        "key4": 100,
                        "key5": [100],
                        "key6": {
                            "key": 6
                        }
                    }
                }, {
                    "name": "arg2-str",
                    "value": "String:test"
                }]
            }],
            "payer": "AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ",
            "gasLimit": 20000,
            "gasPrice": 500
        }
    }
}

Base58 addresses such as AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ can be assigned to the %address parameter, and the wallet will automatically assign it as the wallet's asset address. If the parameters contain an %ontid, the wallet will also automatically assign it to the wallet's ONT ID address.

The wallet initiates a transaction, the user authenticates and signs it, the transaction is pre-executed, issued, and then the transaction hash is sent to the callback URL using POST method.

The success message has the following structure:

{
  "action": "invoke",
  "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
  "error": 0,
  "desc": "SUCCESS",
  "result": "tx hash"
}

And the failure message is as follows:

{
  "action": "invoke",
  "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
  "error": 80001,
  "desc": "SEND TX ERROR",
  "result": 1
}

Pre-executing a transaction

Pre-executing a transaction is optional. One of the main functions is serves is informing the user how much ONT or ONG is involved in a particular transaction. The Notify message that is returned upon pre-execution can deliver the information regarding the amount of ONT/ONG the user will spend for a particular transaction in terms of transaction costs.

The Notify message needs to be parsed to make a judgement, because a transaction may have multiple transfer or smart contract events. If the other contract events don't need to handled, then the nature of transferred tokens can be judged from the address i.e. ONT/ONG and the transfer method along with the sender.

It is also advised that the the sender and amount should be displayed on the UI. There is a transaction fee which roughly equals to 0.01ONG

If the pre-execution is a success the response from the node is:

{
  "Action": "sendrawtransaction",
  "Desc": "SUCCESS",
  "Error": 0,
  "Result": {
                "Notify": [{
                    "States": ["transfer", "AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ", "AecaeSEBkt5GcBCxwz1F41TvdjX3dnKBkJ", 1],
                    "ContractAddress": "0100000000000000000000000000000000000000"
                }],
                "State": 1,
                "Gas": 20000,
                "Result": "01"
   },
  "Version": "1.0.0"
}

But if it fails, the Error value would be greater than 0.

Code for reference

Last updated