# 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](/midpoint-documentation/sources/startpoint-called.md) source, the [Make HTTP Request](/midpoint-documentation/tasks/make-http-request.md) task, and the [Transact to EVM Function](/midpoint-documentation/tasks/transact-to-evm-function.md) 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](/midpoint-documentation/sources/startpoint-called.md) 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](/midpoint-documentation/tasks/make-http-request.md) 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](/midpoint-documentation/tasks/transact-to-evm-function.md)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`


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.midpointapi.com/midpoint-documentation/get-started/sample-midpoints/oracle-call-any-api-from-a-smart-contract.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
