# Oracle Process Flow

## Creating Oracle request

An **Oracle contract** can be deployed on the Ontology **network** to send Oracle **requests** and fetch **data** from outside world and make it **accessible** to other **smart contracts**.

{% hint style="info" %}
In the future, **all** the deployed Oracle contracts will be **listed** on the **Oracle market**
{% endhint %}

The sample **Oracle contract** that we will be looking at here fetches sports statistics, i.e., match details.

Let's say the address of an example Oracle contract is as follows:

#### Test net - e0d635c7eb2c5eaa7d2207756a4c03a89790934a

#### Main net - a6ee997b142b002d49670ab73803403b09a23fa0

The structure of the Oracle **request** is of the form:

### httpGet

```yaml
operation = "CreateOracleRequest"
request = """{
		"scheduler": {
			"type": "runAfter",
			"params": "2018-06-15 08:37:18"
		},
		"tasks": [
			{
			  "type": "httpGet",
			  "params": {
				"url": "https://bitstamp.net/api/ticker/"
			  }
			},
			{
				"type": "jsonParse",
				"params":
				{
					"data":
					[
						{
							"type": "String",
							"path": ["timestamp"]
						},
						{
							"type": "String",
							"path": ["last"]
						},
						{
							"type": "Float",
							"decimal": 100,
							"path": ["open"]
						}
					 ]
				}
			}
		]
	}"""
args = [request, address]
```

The **response** is as follows:

```yaml
{
	"high": "5610.00000000",
	"last": "5518.70",
	"timestamp": "1542359479",
	"bid": "5518.12",
	"vwap": "5436.78",
	"volume": "16423.18407040",
	"low": "5199.80000000",
	"ask": "5518.69",
	"open": 5571.12
}
```

**Parameters:** `url`, **URL** of the **GET** request

### JsonParse

**JsonParse** will parse the `http` response with the parameter path list as **key**. The result will then be serialized to form a data structure, as defined by the user, and then finally written in the Oracle contract.\
Here is a list of the parameters:

| Parameter | Description                                                                                                                                |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| data      | Data structure defined by the user                                                                                                         |
| type      | Data type, support int, float(\* decimal as int), string, array, map, struct                                                               |
| sub\_type | Sub-type of the array, map and struct                                                                                                      |
| decimal   | decimal places of floating point value                                                                                                     |
| path      | Iterator list of **JSON** parse key, if data is `json`, write **key** in list, if data is **array**, write **index** as **string** in list |

Here's a complex **JsonParse** example:

```yaml
var request = """{
		"scheduler": {
			"type": "runAfter",
			"params": "2018-06-15 08:37:18"
		},
		"tasks": [
			{
			  "type": "httpGet",
			  "params": {
				"url": "http://data.nba.net/prod/v2/20181129/scoreboard.json"
			  }
			},
			{
				"type": "jsonParse",
				"params":
				{
					"data":
					[
						{
							"type": "Array",
							"path": ["games"],
							"sub_type":
							[
								{
									"type": "Struct",
									"sub_type":
									[
										{
											"type": "String",
											"path": ["gameId"]
										},
										{
											"type": "String",
											"path": ["vTeam", "teamId"]
										},
										{
											"type": "String",
											"path": ["vTeam", "score"]
										},
										{
											"type": "String",
											"path": ["hTeam", "teamId"]
										},
										{
											"type": "String",
											"path": ["hTeam", "score"]
										}
									]
								}
							]
						}
					]
				}
			}
		]
	}"""
```

A part of the raw `HTTP` response is:

```yaml
{
	"numGames": 3,
	"games": [{
			"gameId": "0021800316",
			"vTeam": {
				"teamId": "1610612744",
				"score": "128"
			},
			"hTeam": {
				"teamId": "1610612761",
				"score": "131"
			}
		},
		{
			"gameId": "0021800317",
			"vTeam": {
				"teamId": "2610612744",
				"score": "96"
			},
			"hTeam": {
				"teamId": "2610612761",
				"score": "131"
			}
		},
		{
			"gameId": "0021800318",
			"vTeam": {
				"teamId": "3610612744",
				"score": "128"
			},
			"hTeam": {
				"teamId": "3610612761",
				"score": "131"
			}
		}
	]
}
```

Here, the raw `HTTP` response is parsed and then a structure is created based on the data structure, which is then serialized.

An **application** smart **contract** calls the **Oracle contract** to fetch the result and then **deserializes** it as follows:

```yaml
[
    [
        ["0021800316", "1610612744", "128", "1610612761", "131"],
        ["0021800317", "2610612744", "128", "2610612761", "131"],
        ["0021800318", "3610612744", "128", "3610612761", "131"]
    ]
]
```

### Scheduler

This option is used to fix the time when a contract or task will be executed. It's format is as follows:

```yaml
{
    "type": "",
    "params": "",
}
```

Currently it only supports one execution method, **runAfter.**&#x20;

**runAfter** is used to specify a time when the task is to be run. For example, this can be used to send scores to the user after a game has ended. If the `type` field is left **empty**, the task will be run **immediately**. While the `params` field is used to specify the time in this format: **`YYYY-MM-DD HH:MM:SS`**\
Example - **"2018-06-15 08:37:18"**

### **httpPost**

The request format is as follows:

```yaml
operation = "CreateOracleRequest"
request = """{
        "scheduler": {
            "type": "runAfter",
            "params": "2018-06-15 08:37:18"
        },
        "tasks":[
            {
              "type": "httpPost",
              "params": {
                "url": "https://api.random.org/json-rpc/1/invoke",
                "contentType": "application/json-rpc",
                "body": "{\\"jsonrpc\\": \\"2.0\\",\\"method\\": \\"generateSignedIntegers\\",\\"params\\": {\\"apiKey\\": \\"c7511065-c88d-4f28-af4f-293c91ad20d9\\",\\"n\\": 6,\\"min\\": 1,\\"max\\": 10,\\"replacement\\": false,\\"base\\": 10},\\"id\\": 1}"
              }
            },
            {
                "type": "jsonParse",
                "params":
                {
                    "data":
                    [
                        {
                            "type": "Array",
                            "path": ["result", "random", "data"],
                            "sub_type":
                                [
                                    {
                                        "type": "Int"
                                    }
                                ]
                        }
                    ]
                }
            }
        ]
    }"""
args = [request, address]
```

The raw `HTTP` response is:

```yaml
{
    "jsonrpc": "2.0",
    "result": {
        "random": {
            "method": "generateSignedIntegers",
            "hashedApiKey": "oT3AdLMVZKajz0pgW/8Z+t5sGZkqQSOnAi1aB8Li0tXgWf8LolrgdQ1wn9sKx1ehxhUZmhwUIpAtM8QeRbn51Q==",
            "n": 6,
            "min": 1,
            "max": 6,
            "replacement": true,
            "base": 10,
            "data": [
                2,
                4,
                4,
                1,
                5,
                3
            ],
            "completionTime": "2013-09-30 14:58:03Z",
            "serialNumber": 69260
        },
        "signature": "BxHxajeRg7Q+XGjBdFS1c7wkZbJgJlverfZ5TVDyzCKqo2K5A4pD+54EMqmysRYwkL3w2NS2DFLVrsyO1o96bW9BGp5zjjrEegz9mB+04iOTaRwmdQnLJAj/m3WRptA+qzodPCTaqud8YWBifqWCM34q98XwjX+nlahyHVHT9vf5KO0YVkD/yRI1WN5M/qX21chVvSxhWdmIrdCkrovGnysFq8SzCRNhpYx+/1P+YT2IKsH8jth9z82IAz1ANVh918H/UdpuD1dR7TD6nk3ntRgGrIiu2qqVzFi8A7/6viVgRqtffE4KVZY6O9mUJ+sGkF5Ohayms7LHSFy1VC8wMbMgwod+A8nr5yzjAC4SCUkT1bKAyWNF3SdVcLtvWdcf97Ew6RjohzCW4Vs3jUlh6jF/pj3b3++U3lBHCh43IIonw8MQ7afwpqP12yvyDym1isNjhMKYjmzWRerSvnsMyQIH8xFW7IHt2g/0qnzJgABFmUNBRKJPCD9CMgjh60sSwW7EyrGMy7/qisfE0IU74P/F7KCty/g1jIlXX5/O1lQjwY34wnoP0NXL08QteukRZZUfJQnscx1NGE+HX1c9bMBI8LC0ZFYFk+uY6ib/0rCV5OcLLE9PihCdC8WoI1x3bobr8tbtfgnXMTjogxwVXiiSN1TMnTIWlJ+KM5eSWrw=",
        "bitsUsed": 16,
        "bitsLeft": 932400,
        "requestsLeft": 199991,
        "advisoryDelay": 1000
    },
    "id": 1
}
```

An application contract **deserializes** the result as follows:

```yaml
[
    [
        2,
        4,
        4,
        1,
        5,
        3
    ]
]
```

The `HTTP` post example above fetches a random number from **random.org.** This Ontology Oracle packages a more convenient method **`randomOrg`** to get a **signed random number**.

The request is as follows:

```yaml
operation = "CreateOracleRequest"
request = """{
        "scheduler": {
            "type": "runAfter",
            "params": "2018-06-15 08:37:18"
        },
        "tasks": [
            {
              "type": "randomOrg",
              "params": {
                "method": "GenerateSignedIntegers",
                "n": 10,
                "min": 1,
                "max": 10,
                "replacement": false
              }
            },
            {
                "type": "jsonParse",
                "params":
                {
                    "data":
                    [
                        {
                            "type": "Array",
                            "path": ["data"],
                            "sub_type":
                                [
                                    {
                                        "type": "Int"
                                    }
                                ]
                        },
                        {
                            "type": "String",
                            "path": ["signature"]
                        }
                    ]
                }
            }
        ]
    }"""
args = [request, address]
```

Here is the list of parameters:

| Parameter   | Description                                                                         |
| ----------- | ----------------------------------------------------------------------------------- |
| n           | Number of random numbers                                                            |
| min         | Lower limit for random numbers                                                      |
| max         | Upper limit for random numbers                                                      |
| replacement | **`true`**: random number can occur multiple times, **`false`**: numbers are unique |

The response is:

```go
type SignedIntegerData struct {
	Raw          json.RawMessage `json:"raw"`
	HashedApiKey string          `json:"hashedApiKey"`
	SerialNumber int             `json:"serialNumber"`
	Data         []int           `json:"data"`
	Signature    string          `json:"signature"`
}
```

**Unsigned random numbers** can also be generated as follows:

```yaml
operation = "{
        "scheduler": {
            "type": "runAfter",
            "params": "2018-06-15 08:37:18"
        },
        "tasks": [
            {
              "type": "randomOrg",
              "params": {
                "method": "GenerateIntegers",
                "n": 10,
                "min": 1,
                "max": 10,
                "replacement": false
              }
            },
            {
                "type": "jsonParse",
                "params":
                {
                    "data":
                    [
                        {
                            "type": "Array",
                            "path": ["data"],
                            "sub_type":
                                [
                                    {
                                        "type": "Int"
                                    }
                                ]
                        },
                        {
                            "type": "String",
                            "path": ["completionTime"]
                        }
                    ]
                }
            }
        ]
    }"""
args = [request, address]
```

| Parameter   | Description                                                                         |
| ----------- | ----------------------------------------------------------------------------------- |
| n           | Number of random numbers                                                            |
| min         | Lower limit for random numbers                                                      |
| max         | Upper limit for random numbers                                                      |
| replacement | **`true`**: random number can occur multiple times, **`false`**: numbers are unique |

The response is as follows:

```go
type IntegerData struct {
	Data           []interface{} `json:"data"`
	CompletionTime string        `json:"completionTime"`
}
```

## Result of Oracle request

The transaction hash `txhash` can be used to fetch the **result** of the on-chain Oracle **request**. The request format is:

```yaml
operation = "GetOracleOutcome"
args = txhash
```

## Sample Code

Please follow [**this**](https://github.com/ontio/ontology-oracle/blob/master/smartcontract/oracle.py) link to refer to **Oracle contract** template.

Please follow [**this**](https://github.com/ontio/ontology-oracle/blob/master/smartcontract/app.py) link to refer to an **application contract** that uses **Oracle**.
