# Supra

Lumia L2 integrates with Supra's high-performance oracle system to provide fast, reliable price feeds through their Distributed Oracle Agreement (DORA) protocol. This guide explains how to integrate Supra oracles into your dApps on Lumia L2.

### Overview

Supra provides two types of oracle implementations:

* **Pull Oracle**: On-demand price data with sub-second response time
* **Push Oracle**: Automated price updates with layer-1 security guarantees

This guide focuses on the Pull Oracle implementation, which gives you maximum control over when and how to fetch price data.

### Integration Process&#x20;

{% hint style="info" %}
Full list of feeds: <https://docs.supra.com/oracles/data-feeds/data-feeds-index>
{% endhint %}

#### 1. Smart Contract Setup

First, create your smart contract that will receive and process oracle data:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "@openzeppelin/contracts/access/Ownable.sol";

interface ISupraOraclePull {
    struct PriceData {
        uint256[] pairs;    // List of pairs
        uint256[] prices;   // prices[i] is the price of pairs[i]
        uint256[] decimals; // decimals[i] is the decimals of pairs[i]
    }

    function verifyOracleProof(bytes calldata _bytesproof) 
        external 
        returns (PriceData memory);
}

contract SupraPriceConsumer is Ownable {
    ISupraOraclePull internal oracle;
    
    // Store latest prices
    mapping(uint256 => uint256) public latestPrices;
    
    constructor(address oracle_) Ownable(msg.sender) {
        oracle = ISupraOraclePull(oracle_);
    }

    function deliverPriceData(bytes calldata _bytesProof) 
        external 
        onlyOwner 
    {
        ISupraOraclePull.PriceData memory prices = 
            oracle.verifyOracleProof(_bytesProof);
        
        // Store the latest prices
        for (uint256 i = 0; i < prices.pairs.length; i++) {
            latestPrices[prices.pairs[i]] = prices.prices[i];
        }
    }

    function updateOracleAddress(address oracle_) 
        external 
        onlyOwner 
    {
        oracle = ISupraOraclePull(oracle_);
    }
}
```

#### 2. Web2 Integration

You'll need a Node.js application to fetch price data from Supra's gRPC server and send it to your smart contract. Here's a basic implementation:

```javascript
const Web3 = require('web3');
const { PullServiceClient } = require('@supraoracles/sdk');

// Configuration
const config = {
    grpc: {
        address: "YOUR_GRPC_SERVER",
        pairIndexes: [1, 2, 3], // Asset pairs you want to track
        chainType: "EVM"
    },
    client: {
        rpcUrl: "https://testnet-rpc.lumia.org", // Lumia L2 RPC
        contractAddress: "YOUR_CONTRACT_ADDRESS",
        walletAddress: "YOUR_WALLET_ADDRESS",
        privateKey: "YOUR_PRIVATE_KEY"
    }
};

async function main() {
    // Initialize gRPC client
    const client = new PullServiceClient(
        config.grpc.address,
        config.grpc.pairIndexes,
        config.grpc.chainType
    );

    // Get price data
    const priceData = await client.getPrice();
    
    // Send to contract
    await sendToContract(priceData);
}

async function sendToContract(priceData) {
    const web3 = new Web3(config.client.rpcUrl);
    const contract = new web3.eth.Contract(ABI, config.client.contractAddress);
    
    const tx = {
        from: config.client.walletAddress,
        to: config.client.contractAddress,
        data: contract.methods.deliverPriceData(priceData).encodeABI(),
        gas: await contract.methods.deliverPriceData(priceData)
            .estimateGas({from: config.client.walletAddress})
    };

    const signedTx = await web3.eth.accounts.signTransaction(
        tx, 
        config.client.privateKey
    );
    
    await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
}

// Run price updates every minute
setInterval(main, 60000);
```

#### 3. Contract Deployment

Deploy your contract using your preferred method (Hardhat, Truffle, etc.) with the appropriate Supra Oracle address:

**Lumia Mainnet**

* Oracle Address: [0x16f70cAD28dd621b0072B5A8a8c392970E87C3dD](https://explorer.lumia.org/address/0x16f70cAD28dd621b0072B5A8a8c392970E87C3dD)

### Best Practices

1. **Error Handling**

```solidity
function deliverPriceData(bytes calldata _bytesProof) 
    external 
    onlyOwner 
{
    try oracle.verifyOracleProof(_bytesProof) returns (
        ISupraOraclePull.PriceData memory prices
    ) {
        for (uint256 i = 0; i < prices.pairs.length; i++) {
            latestPrices[prices.pairs[i]] = prices.prices[i];
        }
    } catch {
        revert("Invalid oracle proof");
    }
}
```

2. **Price Validation**

```solidity
function validatePrice(uint256 price, uint256 oldPrice) 
    internal 
    pure 
    returns (bool) 
{
    // Example: Reject prices that changed more than 50%
    if (oldPrice > 0) {
        uint256 change = price > oldPrice ? 
            price - oldPrice : oldPrice - price;
        if (change * 100 / oldPrice > 50) {
            return false;
        }
    }
    return true;
}
```

3. **Update Frequency**

* Consider implementing a minimum time between updates
* Use price deviation thresholds to optimize gas costs
* implement redundancy in your web2 infrastructure

### Technical Specifications

* **Response Time**: Sub-second for pull oracle
* **Data Sources**: 40+ sources aggregated
* **Security**: Byzantine Fault Tolerant consensus with DORA
* **Price Calculation**: Median-of-medians with coherent cluster validation
* **Update Frequency**: Customizable (recommended: 1-5 minutes)
* **Gas Optimization**: Batch price updates supported

### Support & Resources

* [Supra Documentation](https://docs.supra.com/)
