Oracle Quickstart

What is an Oracle?

Within blockchain and smart contract ecosystems, an oracle acts as a gateway, bridging on-chain actions with off-chain information. By offering data that smart contracts inherently lack access to, oracles facilitate these contracts to interact and adapt based on real-world occurrences.

Upshot Oracle

The Upshot Oracle is tailored to fetch signed asset valuations. Given the unique demands of NFTs and other blockchain assets, having a reliable and secure method for getting appraisals is crucial.

On Ethereum mainnet, the Upshot Oracle can be found at address: 0x7fcac70760debe52e705b70cd9fd5f85b2b19501

Key Offerings

  • Signed Asset Appraisals
  • Signed Index Prices

Implementation Guide

  1. Make a request to the Upshot API for a specific set of assets using the API's signed asset appraisals endpoint.
  2. The result will be an array of authenticated messages from the API that you can then use to construct a verifiable transaction on-chain using the UpshotOracle.sol contract.
  3. Using your client contract, call the decodeTokenPrices function on the upshot Oracle
const sdk = require('api')('@upshot/v1.0#2io9j2lll40n04q');

sdk.auth('api_key');
sdk.getSignedAssetAppraisals({asset_ids: '0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb%2F1'})
  .then(({ data }) => console.log(data))
  .catch(err => console.error(err));
pragma solidity ^0.8.0;

struct PriceData { 
    bytes signature;
    uint256 nonce;
    address nft; 
    uint96 timestamp;
    address token; 
    uint96 expiration;
    uint256 nftId;
    uint256 price; 
    bytes extraData;
}

interface IUpshotOracle {
    error UpshotOracleInvalidPriceTime();
    error UpshotOracleInvalidSigner();
    /**
     * @notice Decode the token prices from the encoded upshot price data
     */
    function decodeTokenPrices(
        PriceData[] calldata priceData
    ) external returns (uint256[] memory tokenPrices);
}


contract YourContract {
    IUpshotOracle public upshotOracle;

    constructor(address _upshotOracleAddress) {
        upshotOracle = IUpshotOracle(_upshotOracleAddress);
    }

    function yourFunction(PriceData[] calldata p) external {
      // ... do some stuff

      try upshotOracle.decodeTokenPrices(p) returns (uint256[] memory tokenPrices) {
        // if the code gets to here then the data is valid
        // and the tokenPrices array contains the signed prices from the PriceData[]
        // in the items in the same order as the data in the PriceData[] array
        // ... do something with tokenPrices
        
        	uint256 example = tokenPrices[0];
        
        } catch (bytes memory reason)  {
            bytes4 errCode = bytes4(reason);
            if (errCode == IUpshotOracle.UpshotOracleInvalidPriceTime.selector) {
                // ... handle error that the price appraisal has expired its validity
            } else if (errCode == IUpshotOracle.UpshotOracleInvalidSigner.selector) {
                // ... handle error that the price appraisal either was not formatted correctly
                // or the signature was not signed by the real price appraiser API
            }
        }
    }
}