In order to ensure easy integration with external partners Thales API is created. API returns all main data available on Thales. Using Thales API endpoints someone can get data about:
Thales collaterals
Thales markets
Thales market
User Thales positions
User Thales transactions
Buy quote
Sell quote
More details about each API endpoint with request/response examples can be found under Postman documentation.
Contract integration
Once all data are fetched from API, the next step is integration with Thales contracts. Depending on whether someone wants to buy a position on Tokenized Positional Markets or Tokenized Ranged Markets integration should be done with ThalesAMM or RangedAMM contract.
The next sections describe integration with Thales API and Thales contracts together with JS code examples.
Buy a UP/DOWN position
Let's say someone wants to buy UP positional tokens on the BTC market with a strike price of 35000 on 7th November 2023 with a buy-in amount of 100 sUSD:
Integration with Thales API and Thales AMM contract should include the following steps:
Get a buy quote for the market from Thales API
Get a Thales AMM contract address for a specific network from Thales contracts
Get a Thales AMM contract ABI from Thales contract repository contract repository
Create Thales AMM contract instance
Call buyFromAmm method on Thales AMM contract with input parameters fetched from Thales API in step #1
The JS code snippet below implements these steps:
import { ethers } from"ethers";import w3utils from"web3-utils";import axios from"axios";import dotenv from"dotenv";import ammContractAbi from"./ammContractAbi.js"; // ThalesAMM contract ABIdotenv.config();constAPI_URL="https://overtimemarketsv2.xyz"; // base API URLconstNETWORK_ID=10; // optimism network IDconstNETWORK="optimism"; // optimism networkconstAMM_CONTRACT_ADDRESS="0x278B5A44397c9D8E52743fEdec263c4760dc1A1A"; // ThalesAMM contract address on optimismconst MARKET_ADDRESS = "0x150Faf51367770DEfF9e004773B73A9387d9EB58"; // address of BTC market with strike price 35000 at 2023-11-07
constPOSITION=0; // select UP positionconstBUY_IN=100; // 100 sUSDconstSLIPPAGE=0.02; // slippage 2%// create instance of Infura provider for optimism networkconstprovider=newethers.providers.InfuraProvider( { chainId:Number(NETWORK_ID), name:NETWORK },process.env.INFURA);// create wallet instance for provided private key and providerconstwallet=newethers.Wallet(process.env.PRIVATE_KEY, provider);// create instance of Thales AMM contractconstamm=newethers.Contract(AMM_CONTRACT_ADDRESS, ammContractAbi, wallet);constbuyFromAmm=async () => {try {// get a buy quote from Thales API for provided market, position and buy-in amount on optimism networkconstquoteResponse=awaitaxios.get( `${API_URL}/thales/networks/${NETWORK_ID}/markets/${MARKET_ADDRESS}/buy-quote?position=${POSITION}&buyIn=${BUY_IN}`
);constquoteData=quoteResponse.data;console.log("Quote data", quoteData);// convert payout got from API to BigNumberconstparsedPayout=ethers.utils.parseEther(quoteData.payout.toString());// convert actual buy-in amount got from API to BigNumber // actualBuyInCollateralAmount is different from BUY_IN due to the contract architecture having positions amount as input and not buy-in amount
constparsedActualBuyInCollateralAmount=ethers.utils.parseEther(quoteData.actualBuyInCollateralAmount.toString() );// convert slippage tolerance to BigNumberconstparsedSlippage=ethers.utils.parseEther(SLIPPAGE.toString());// call buyFromAMM method on Thales AMM contractconsttx=awaitamm.buyFromAMM(MARKET_ADDRESS,POSITION, parsedPayout, parsedActualBuyInCollateralAmount, parsedSlippage, { type:2, maxPriorityFeePerGas:w3utils.toWei("0.00000000000000001"), } );// wait for the resultconsttxResult=awaittx.wait();console.log(`Successfully bought from AMM. Transaction hash: ${txResult.transactionHash}` ); } catch (e) {console.log("Failed to buy from AMM", e); }};buyFromAmm();
Buy a IN/OUT position
Let's say someone wants to buy IN positional tokens on the BTC market with a range 34000-38000 on 7th November 2023 with a buy-in amount of 100 sUSD:
Integration with Thales API and Ranged AMM contract should include the following steps:
Get a buy quote for the market from Thales API
Get a Ranged AMM contract address for a specific network from Thales contracts
Get a Ranged AMM contract ABI from Thales contract repository contract repository
Create Ranged AMM contract instance
Call buyFromAmm method on Ranged AMM contract with input parameters fetched from Thales API in step #1
The JS code snippet below implements these steps:
import { ethers } from"ethers";import w3utils from"web3-utils";import axios from"axios";import dotenv from"dotenv";import rangedAmmContractAbi from"./rangedAmmContractAbi.js"; // RangedAMM contract ABIdotenv.config();constAPI_URL="https://overtimemarketsv2.xyz"; // base API URLconstNETWORK_ID=10; // optimism network IDconstNETWORK="optimism"; // optimism networkconstRANGED_AMM_CONTRACT_ADDRESS="0x2d356b114cbCA8DEFf2d8783EAc2a5A5324fE1dF"; // RangedAMM contract address on optimismconst MARKET_ADDRESS = "0x5a268e454D7877F73531b54FF81Cd0C329C4b97e"; // address of BTC market with range 34000-38000 at 2023-11-07
constPOSITION=1; // select OUT positionconstBUY_IN=100; // 100 sUSDconstSLIPPAGE=0.02; // slippage 2%// create instance of Infura provider for optimism networkconstprovider=newethers.providers.InfuraProvider( { chainId:Number(NETWORK_ID), name:NETWORK },process.env.INFURA);// create wallet instance for provided private key and providerconstwallet=newethers.Wallet(process.env.PRIVATE_KEY, provider);// create instance of Ranged AMM contractconstrangedAMM=newethers.Contract(RANGED_AMM_CONTRACT_ADDRESS, rangedAmmContractAbi, wallet);constbuyFromRangedAmm=async () => {try {// get a buy quote from Thales API for provided market, position and buy-in amount on optimism networkconstquoteResponse=awaitaxios.get( `${API_URL}/thales/networks/${NETWORK_ID}/markets/${MARKET_ADDRESS}/buy-quote?position=${POSITION}&buyIn=${BUY_IN}`
);constquoteData=quoteResponse.data;console.log("Quote data", quoteData);// convert payout got from API to BigNumberconstparsedPayout=ethers.utils.parseEther(quoteData.payout.toString());// convert actual buy-in amount got from API to BigNumber // actualBuyInCollateralAmount is different from BUY_IN due to the contract architecture having positions amount as input and not buy-in amount
constparsedActualBuyInCollateralAmount=ethers.utils.parseEther(quoteData.actualBuyInCollateralAmount.toString() );// convert slippage tolerance to BigNumberconstparsedSlippage=ethers.utils.parseEther(SLIPPAGE.toString());// call buyFromAMM method on Ranged AMM contractconsttx=awaitrangedAMM.buyFromAMM(MARKET_ADDRESS,POSITION, parsedPayout, parsedActualBuyInCollateralAmount, parsedSlippage, { type:2, maxPriorityFeePerGas:w3utils.toWei("0.00000000000000001"), } );// wait for the resultconsttxResult=awaittx.wait();console.log(`Successfully bought from Ranged AMM. Transaction hash: ${txResult.transactionHash}` ); } catch (e) {console.log("Failed to buy from Ranged AMM", e); }};buyFromRangedAmm();