# Oracle: Call any API from a smart contract

## **Overview**

An oracle is a midpoint that makes HTTP requests from contracts to off-chain endpoints. Unlike traditional oracle networks - midpoints allow developers to define arbitrarily complex requests with components such as parameters/headers defined on-chain, multistep authentication workflows, private off-chain data for keys, and cross-chain functionality. &#x20;

We will create a contract to request a summary of any Wikipedia article. We will use the [startpoint-called](https://docs.midpointapi.com/midpoint-documentation/sources/startpoint-called "mention") source, the [make-http-request](https://docs.midpointapi.com/midpoint-documentation/tasks/make-http-request "mention") task, and the [transact-to-evm-function](https://docs.midpointapi.com/midpoint-documentation/tasks/transact-to-evm-function "mention") task.

**StartpointCalledSource:**&#x20;

1. Listens for the caller to send the title of a wikipedia article
2. Extracts the title and sends it to MakeHttpRequestTask

**MakeHttpRequestTask:**&#x20;

1. Makes a request to the Wikimedia API
2. Extracts the summary from the HTTP response
3. Sends the summary to the TranasctToEvmFunctionTask

**TransactToEvmFunctionTask:**

1. Submits the summary via a transaction to an on-chain function defined by the developer

## Midpoint

`$ npm install -g midpoint-cli`

`$ midpoint init blank my-oracle`

#### **1 . StartpointCalledSource**

`$ midpoint add-source startpointCalledSource oracle-source`

We define the [startpoint-called](https://docs.midpointapi.com/midpoint-documentation/sources/startpoint-called "mention") source so that contract can make a midpoint request.&#x20;

```json
{
    "startpointCalledSource": {
        "whitelist": [
            {
                "chainId": "5",
                "contractAddress": "0xDDb539E3c742f3DFA8eB3cf0f7122214f805B962"
            }
        ],
        "variables": [
            {
                "name": "article",
                "datatype": "string"
            }
        ],
        "extracts": [
            {
              "name": "Midpoint_ID",
              "from": "Midpoint_ID"
            },
            {
              "name": "Request_ID",
              "from": "Request_ID"
            }
        ]
    }
}
```

**2.  MakeHTTPRequestTask**

`$ midpoint add-task makeHttpRequest call-wikipedia`

We define the [make-http-request](https://docs.midpointapi.com/midpoint-documentation/tasks/make-http-request "mention") Task to make the call to the Wikipedia endpoint.

```json
{
    "makeHttpRequest": {
        "method": "GET",
        "urlRaw": "https://en.wikipedia.org/api/rest_v1/page/summary/{{article}}",
        "urlType": "raw",
        "extracts": [
            {
                "name": "wikipediaSummary",
                "from": "body.extract"
            }
        ]
    }
}
```

#### **3.  TransactToEVMFunction**&#x20;

`$ midpoint add-task transactToEvmFunctionTestnet callback`

We define the [transact-to-evm-function](https://docs.midpointapi.com/midpoint-documentation/tasks/transact-to-evm-function "mention")Task to send the summary back to the contract. &#x20;

```json
{
   "transactToEvmFunctionTestnet":{
      "chainId":"5",
      "contractAddress":"0xDDb539E3c742f3DFA8eB3cf0f7122214f805B962",
      "functionName":"requestedWikipediaSummary",
      "arguments":[
         {
            "name":"midpointId",
            "datatype":"uint64",
            "value":"{{Midpoint_ID}}"
         },
         {
            "name":"requestId",
            "datatype":"uint64",
            "value":"{{Request_ID}}"
         },
         {
            "name":"wikipediaSummary",
            "datatype":"string",
            "value":"{{wikipediaSummary}}"
         }
      ]
   }
}
```

#### **4.  Define Path**

We define our path file.&#x20;

```
oracle-source => call-wikipedia
call-wikipedia => callback
```

#### **5.  Deploy Contract**

```solidity
/*
 * SPDX-License-Identifier: MIT
 * Midpoint Sample Storage Contract v3.0.0
 *
 * This is a contract generated at 2023-02-28 20:07:34 for testing requests to midpoint 160. 
 * This contract is intended to serve as a guide for interfacing with a midpoint and should not be used
 * as is in a production environment.
 * For more information on setting up a midpoint and using this contract see docs.midpointapi.com
 */

pragma solidity>=0.8.0;

interface IMidpoint {
    function callMidpoint(uint64 midpointId, bytes calldata _data) external returns(uint64 requestId);
}

contract TestMidpointOracleContract {
    // These events can be removed without impacting the functionality of your midpoint
    event RequestForWikipediaSummaryMade(string article);
    event WikipediaSummaryReceived(uint64 Request_ID, uint64 Midpoint_ID, string wikipedia_summary);
    
    // A verified startpoint for Goerli Testnet
    address constant startpointAddress = 0x795c5292b9630d473d568079b73850F29344403c;
    
    // A verified midpoint transact to EVM function EOA for Goerli Testnet
    address constant whitelistedCallbackAddress = 0xC0FFEE4a3A2D488B138d090b8112875B90b5e6D9;
    
    // The globally unique identifier for your midpoint
    uint64 constant midpointID = 160;
    
    // Mapping of Request ID to a flag that is checked when the request is satisfied
    // This can be removed without impacting the functionality of your midpoint
    mapping(uint64 => bool) public request_id_satisfied;
    
    // Mappings from Request ID to each of your results
    // This can be removed without impacting the functionality of your midpoint
    mapping(uint64 => string) public request_id_to_wikipedia_summary;
    
    /*
     * This function makes a call to your midpoint with On-Chain Variables specified as function inputs. 
     * 
     * Note that this is a public function and will allow any address or contract to call midpoint 160.
     * Configure your midpoint to permit calls from this contract when testing. Before using your midpoint
     * in a production environment, ensure that calls to 'callMidpoint' are protected.
     * Any call to 'callMidpoint' from a whitelisted contract will make a call to your midpoint;
     * there may be multiple places in this contract that call the midpoint or multiple midpoints called by the same contract.
     */ 

    function getWikipediaSummary(string memory article) public {
        // This packs together all of the On-Chain Variables for your midpoint into a single bytestring
        bytes memory args = abi.encodePacked(article, bytes1(0x00));
        
        // This makes the call to your midpoint
        uint64 requestId = IMidpoint(startpointAddress).callMidpoint(midpointID, args);

        // This logs that the call has been made, and can be removed without impacting your midpoint
        emit RequestForWikipediaSummaryMade(article);
        request_id_satisfied[requestId] = false;
    }
    
   /*
    * This function is the callback target specified in your midpoint callback definition. 
    * Note that the callback is placed in the same contract as the call to callMidpoint for simplicity when testing.
    * The callback does not need to be defined in the same contract as the request or live on the same chain.
    */

   function requestedWikipediaSummary(uint64 midpointId, uint64 requestId, string memory wikipediaSummary) public {
       // Only allow a verified callback address to submit information for your midpoint.
       require(tx.origin == whitelistedCallbackAddress, "Invalid callback address");
       // Only allow requests that came from your midpoint ID
       require(midpointID == midpointId, "Invalid Midpoint ID");
       
       // This stores each of your response variables. This is where you would place any logic associated with your callback.
       // Your midpoint can transact to a callback with arbitrary execution and gas cost.
       request_id_to_wikipedia_summary[requestId] = wikipediaSummary;
       
       // This logs that a response has been received, and can be removed without impacting your midpoint
       emit WikipediaSummaryReceived(requestId, midpointId, wikipediaSummary);
       request_id_satisfied[requestId] = true;
   }
}
```

#### **6.  Publish Midpoint**

`$ midpoint publish`
