Getting started tutorial
Getting Started with Quex
Introduction
Quex provides a protocol and infrastructure for decentralized data transfer based on confidential computing. The most simple of these for developers is data oracle, and that's what we'll be learning about today. In this guide, we'll explore two examples that demonstrate different aspects of using Quex: a basic parametric emission token that uses public API data, and an advanced integration with OpenAI API that requires secure authentication.
Document Structure
This tutorial is organized into the following sections:
Introduction: Provides an overview of Quex and explains what we're building.
Example 1: TVL-Based Token Emission: A complete example demonstrating how to build a token that mints based on DeFi protocol TVL data.
Try it Out: Quick start instructions to deploy and run the provided example.
Let's Create a Quex-based Contract: Step-by-step instructions to set up your environment and implement smart contracts leveraging Quex.
Prepare Environment: How to configure your development environment.
Token Emission: Detailed implementation of ERC-20 token emission logic.
Create Flow: Defines how data requests are structured and handled by Quex oracle pools.
Deploy and Run: Guide to deploying the contracts and executing the request to mint tokens.
Example 2: OpenAI API Integration: An advanced example showing how to integrate with APIs that require authentication using encrypted private headers.
Try it Out: Quick start instructions for the OpenAI integration example.
Let's Build an AI Integration Contract: Step-by-step guide to integrating OpenAI API with Quex.
Prepare Environment: Setting up dependencies and API credentials.
OpenAI Integration Contract: Implementation of a contract that fetches AI-generated sentiment scores.
Create Flow with Private Headers: How to securely pass API keys using Trust Domain encryption.
Deploy and Run: Guide to deploying and testing the OpenAI integration.
Next Steps: Recommendations on further exploration and advanced use cases.
Example 1: TVL-Based Token Emission
What Are We Building?
Let's begin by clearly defining what we're building and why. Imagine you're issuing a token for a DeFi protocol and want to design tokenomics that incentivize the foundation to actively increase the protocol's Total Value Locked (TVL). One effective approach is awarding the foundation tokens proportional to the protocol's TVL, as reported by DeFiLlama.
Specifically, we'll design a token where the foundation receives freshly minted tokens daily, equal in number to the USD-denominated TVL of the protocol across all supported chains and protocol versions. For clarity and practical demonstration, we'll use TVL data from the DyDx protocol. Fortunately, DeFiLlama provides an API endpoint that returns exactly this number. However, because this data is provided off-chain, achieving our goal requires an oracle to securely transfer the data on-chain.
Try it Out
The codebase for this example, including a prepared Foundry environment, is available in our examples repository. You can easily explore it by cloning the repository and installing its dependencies:
This repository also provides scripts that help you deploy the contracts and make requests to the Quex data oracle, triggering token minting. To deploy these contracts, you’ll need the private key of a wallet holding sufficient gas tokens for your chosen network. Set your private key as an environment variable for convenience:
Build and Deploy Contracts
Run the DeployTVLEmissionScript to build and deploy the ERC-20 token, the token emission contract, and to set up the data flow for verifiable Quex HTTPS responses:
You’ll need the deployed contract address for making requests. Store the deployed contract’s address as an environment variable:
Make a Request
Next, make a request using the provided script:
Check Your Balance
Now, verify your wallet balance—you should receive freshly minted TVLT tokens, equal in amount to the current TVL of the DyDx protocol!
Congratulations! You've successfully deployed your first contract that relies on confidential computing proofs to bring off-chain data to your contract. In the following sections, we'll provide a detailed explanation of what's happening under the hood of our contracts. This will give you insights and ideas for building your own Quex-based smart contracts.
Let's Create a Quex-based Contract for TVL Emission!
Prepare Environment
We'll build our example using Foundry (Forge)—ensure it's correctly installed and up to date. Update Foundry by running:
We’ll also use the ERC-20 implementation from OpenZeppelin and Quex libraries to simplify our development:
Token emission
Next, let's create a new contract ParametricToken.sol in src folder with the following code:
As you can see, this is a standard ERC-20 token with one modification: only the contract owner can mint new tokens. In our scenario, ownership of this token contract will belong to another contract.
Let’s create that contract, TVLEmission.sol, next:
Let’s briefly summarize what’s happening here:
The contract imports and inherits from
QuexRequestManager, which simplifies interactions with Quex oracle pools and performs the necessary response verification.The constructor is initialized with addresses for the token treasury, Quex core, and the HTTPS oracle pool. We also deploy the
ParametricTokencontract within the constructor, becoming its owner and gaining the ability to mint tokens.The
processResponsemethod is implemented as a callback, which securely processes responses from the Quex oracle. It includes a cooldown period to limit request frequency and uses theverifyResponsemodifier to protect against oracle manipulation attacks.
At this point, we should make a side note regarding Quex architecture. Although Quex supports classic pull- and push-based data oracles, under the hood, all of them rely on callback mechanics. In our example, we use the fastest and most cost-efficient callback scenario, particularly useful when you need to process data directly upon receiving it.
However, though we've defined a processResponse function to verify proofs and process responses, we haven't yet defined the data flow—the exact HTTPS request the oracle pool should perform and the necessary supporting information. We'll cover this in the next section.
Create Flow
In Quex terminology, a Flow is a combination of the recipient contract address, recipient contract callback, callback gas limit, oracle pool address, and the ID of the action to be performed by the oracle. While there are multiple ways to define a Flow, for clarity in our example, we'll define it directly within our contract. For more options, explore Flow creation section of this documentation.
To achieve this, create a setUpFlow() function as follows and invoke it from the constructor:
Let's go through the setUpFlow() method step by step. We'll use the FlowBuilder helper here, which simplifies flow registration by asking us to define only the necessary fields.
First, we define the HTTPS request we’d like to perform—in our case, it's https://api.llama.fi/tvl/dydx, which returns the USD-denominated TVL of the DyDx protocol required for our task. Although our example is straightforward, Quex supports more advanced requests: you can specify headers, parameters, HTTP methods, and request bodies as needed. Additionally, Quex allows the use of private data (such as API credentials) by passing encrypted data securely to our oracles. While we don't directly demonstrate these advanced features in this tutorial, you can explore them in a dedicated section of our documentation. These additional options provide flexibility when working with more complex APIs.
Second, we define a filter—a script written in the jq programming language—for response post-processing. The DeFiLlama API from the previous step returns a floating-point number, e.g., 284291310.4518468. However, standard ERC20 tokens follow a convention where token amounts are represented as integers, scaled by 1e18. To achieve this, the jq script ". * 1000000000000000000 | round" multiplies the response by 1e18 and rounds it to an integer.
Third, we define a response schema—this is the format for encoding the oracle response. In our example, the response (an unsigned numeric value) can be easily encoded as a Solidity uint256. However, you're not limited by this choice and can define more complex schemas if needed, learn more at our shemas page. If you wish to explore example using more complex data structures, check out this tutorial.
Finally, we need to define what happens when the response is ready. We do this using three fields: the oracle pool's address (consumer), the callback function (callback) to handle the incoming data, and a gasLimit for executing the callback. After defining these parameters, we call createFlow() to register our flow in the Quex registry, and store the returned identifier via setFlowId() for verifying incoming data later.
Set up subscription
To simplify the money flow during request creation and fulfillment, Quex uses subscriptions - pre-deposited native tokens managed by the IDepositManager contract, which handle covering all necessary fees when fulfilling requests. QuexRequestManager already has a built-in createSubscription() method, which performs the necessary steps to create and set up a subscription. The only parameter you need to provide is the initial deposit amount. You can always replenish the subscription using the deposit() method from IDepositManager or withdraw remaining funds using the withdraw() method. For more details, you can refer to Subscription management section of this documentation.
Deploy and Run
That's it!
Now, all you need is to deploy the TVLEmission contract and call the built-in request() method to fetch your data and mint tokens. You can do this using any tools you prefer—particularly, you may use our prepared Foundry scripts available in the examples repository.
Example 2: OpenAI API Integration
Now that you've built a contract using public API data, let's explore a more advanced use case: integrating with APIs that require authentication. In this example, we'll build a contract that uses OpenAI's API to perform sentiment analysis and store the results on-chain.
What Are We Building?
Imagine you want to create a DeFi protocol that adjusts its parameters based on market sentiment. To achieve this, you need to fetch sentiment analysis from an AI service like OpenAI and use that data in your smart contracts. However, OpenAI's API requires authentication via an API key, which must be kept secure and never exposed on-chain.
Quex solves this challenge by allowing you to encrypt sensitive data (like API keys) using Trust Domain encryption. The encrypted credentials are securely passed to the oracles, which can decrypt and use them within the confidential computing environment, ensuring your API keys never appear in plaintext on-chain.
In this example, we'll build a contract that:
Sends POST requests to OpenAI's chat completions API
Uses encrypted private headers to securely pass the API key
Extracts sentiment scores (0-100) from OpenAI responses
Stores the latest sentiment score on-chain
Emits events when new responses are received
Try it Out
The codebase for this example is available in our examples repository. You can explore it by cloning the repository and installing its dependencies:
To deploy these contracts, you'll need:
A wallet with gas tokens on your chosen network (e.g., Arbitrum Sepolia)
An OpenAI API key
A Trust Domain (TD) address and private key that you can find here
Set your private key as an environment variable:
Important: Before deploying, you need to:
Encrypt your OpenAI API key with a Trust Domain public key to get the encrypted API key
Update the
TRUST_DOMAINconstant inscript/DeployOpenAIScript.s.solwith actual TD address (see here)Set the encrypted API key as an environment variable (as hex string):
To encrypt your API key, use our sensitive data encryption tool as follows:
Build and Deploy Contracts
Run the DeployOpenAIScript to build and deploy the OpenAI integration contract and create a data flow:
You'll need the deployed contract address for making requests. Store the deployed contract's address as an environment variable:
Make a Request
After deployment, make a request using the provided script:
This will send a request to OpenAI API through Quex oracles. The contract will receive the response and store the sentiment score.
Check the Response
You can check the stored sentiment score by calling the contract's view functions using Foundry's cast tool:
Congratulations! You've successfully integrated OpenAI API with Quex, demonstrating how to securely use authenticated APIs in your smart contracts.
Let's Build an AI Integration Contract!
Prepare Environment
We'll build our example using Foundry (Forge)—ensure it's correctly installed and up to date. Update Foundry by running:
We'll use the Quex libraries to simplify our development:
OpenAI Integration Contract
Let's create a new contract OpenAIIntegration.sol in the src folder:
This contract:
Inherits from
QuexRequestManagerfor simplified interactions with Quex oracle poolsStores the latest sentiment score and timestamp
Implements
processResponseas a callback to securely process responses from the Quex oracleValidates that sentiment scores are between 0-100
Emits events when new responses are received
Create Flow with Private Headers
Now, let's add the setUp() function that configures the flow with encrypted private headers. This is the key difference from our first example—we'll use Trust Domain encryption to securely pass the API key:
Let's break down the key differences from our first example:
POST Method: Unlike the TVL example which uses GET, we specify
RequestMethod.Postsince OpenAI's chat completions API requires POST requests.Request Body: We include a JSON body with the prompt asking OpenAI to analyze sentiment and return a numeric score.
Private Headers: This is the crucial security feature. We use
withPrivateHeaders()to pass the encrypted API key. TheRequestHeaderPatchstructure contains:key: The header name ("Authorization")ciphertext: The encrypted API key (format: "Bearer sk-..." encrypted by the Trust Domain)
Trust Domain Address: We specify the Trust Domain address using
withTdAddress(), which tells Quex which Trust Domain should decrypt the private headers.jq Filter: The filter
.choices[0].message.content | tonumber | roundextracts the numeric response from OpenAI's JSON structure and converts it to an integer.
The encrypted API key is never exposed on-chain—it's only decrypted within the confidential computing environment of the Quex oracles, ensuring your credentials remain secure.
Deploy and Run
That's it! Now you can deploy the OpenAIIntegration contract and call the built-in request() method to fetch sentiment analysis from OpenAI. You can use our prepared Foundry scripts available in the examples repository.
Next Steps
Congratulations on deploying your very first contract that relies on data secured by confidential computing proofs! You can explore further by visiting other sections of our documentation to learn how to build more complex examples and create the next generation of DApps connected to real-world data.
Also, join our Community to stay updated on Quex developments and engage with other developers!
Last updated

