In order to ensure easy integration with third party applications, Overtime API is created. API returns all main data available on Overtime. Using Overtime API endpoints someone can get data about:
Overtime sports
Overtime collaterals
Overtime markets
Overtime market
User Overtime positions
User Overtime transactions
Single quote
Parlay quote
More details about each API endpoint with request/response examples can be found under .
Contract integration
Once all data are fetched from API, the next step is integration with Overtime contracts. Depending on whether someone wants to buy a single or a parlay, integration should be done with or .
The next sections describe integration with Overtime API and Overtime contracts together with JS code examples.
Buy a single
Let's say someone wants to buy positional tokens on Chelsea for the game Chelsea - Liverpool with a buy-in amount of 100 sUSD.
Integration with Overtime API and Sports AMM contract should include the following steps:
Get a quote for a single market from Overtime API
Create Sports AMM contract instance
Call buyFromAmm method on Sports AMM contract with input parameters fetched from Overtime 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 sportsAMMContractAbi from "./SportsAMMContractAbi.js"; // SportsAMM contract ABI
dotenv.config();
const API_URL = "https://overtimemarketsv2.xyz"; // base API URL
const NETWORK_ID = 10; // optimism network ID
const NETWORK = "optimism"; // optimism network
const SPORTS_AMM_CONTRACT_ADDRESS =
"0x170a5714112daEfF20E798B6e92e25B86Ea603C1"; // SportsAMM contract address on optimism
const MARKET_ADDRESS = "0xb157e64720d3ff251023119a5f6557067763b08a"; // address od market Chelsea - Liverpool
const POSITION = 0; // select Chelsea position
const BUY_IN = 100; // 100 sUSD
const SLIPPAGE = 0.02; // slippage 2%
// create instance of Infura provider for optimism network
const provider = new ethers.providers.InfuraProvider(
{ chainId: Number(NETWORK_ID), name: NETWORK },
process.env.INFURA
);
// create wallet instance for provided private key and provider
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
// create instance of Sports AMM contract
const sportsAMM = new ethers.Contract(
SPORTS_AMM_CONTRACT_ADDRESS,
sportsAMMContractAbi,
wallet
);
const buyFromAmm = async () => {
try {
// get a quote from Overtime API for provided market, position and buy-in amount on optimism network
const quoteResponse = await axios.get(
`${API_URL}/overtime/networks/${NETWORK_ID}/markets/${MARKET_ADDRESS}/quote?position=${POSITION}&buyIn=${BUY_IN}`
);
const quoteData = quoteResponse.data;
console.log("Quote data", quoteData);
// convert payout got from API to BigNumber
const parsedPayout = 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
const parsedActualBuyInCollateralAmount = ethers.utils.parseEther(
quoteData.actualBuyInCollateralAmount.toString()
);
// convert slippage tolerance to BigNumber
const parsedSlippage = ethers.utils.parseEther(SLIPPAGE.toString());
// call buyFromAMM method on Sports AMM contract
const tx = await sportsAMM.buyFromAMM(
MARKET_ADDRESS,
POSITION,
parsedPayout,
parsedActualBuyInCollateralAmount,
parsedSlippage,
{
type: 2,
maxPriorityFeePerGas: w3utils.toWei("0.00000000000000001"),
}
);
// wait for the result
const txResult = await tx.wait();
console.log(
`Successfully bought from AMM. Transaction hash: ${txResult.transactionHash}`
);
} catch (e) {
console.log("Failed to buy from AMM", e);
}
};
buyFromAmm();
Buy a parlay
Let's say someone wants to buy a 4-game parlay with a buy-in amount of 100 sUSD.
Get a quote for a parlay from Overtime API
Create Parlay AMM contract instance
Call buyFromParlay method on Parlay AMM contract with input parameters fetched from Overtime 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 parlayAMMContractAbi from "./parlayAMMContractAbi.js"; // ParlayAMM contract ABI
dotenv.config();
const API_URL = "https://overtimemarketsv2.xyz"; // base API URL
const NETWORK_ID = 10; // optimism network ID
const NETWORK = "optimism"; // optimism network
const PARLAY_AMM_CONTRACT_ADDRESS =
"0x82B3634C0518507D5d817bE6dAb6233ebE4D68D9"; // ParlayAMM contract address on optimism
const MARKETS = [
"0xb157e64720d3ff251023119a5f6557067763b08a",
"0xbf1e460b82308cb76d5918377eb03ac7a3c33a43",
"0xa73553b23799ae0e8743771a79d26cb196eca892",
"0x91300647b7bc3b698fd2e841d26cdfc61a4145ed",
]; // market addresses
const POSITIONS = [0, 1, 0, 0]; // market positions
const BUY_IN = 100; // 100 sUSD
const SLIPPAGE = 0.02; // slippage 2%
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; // pass as a differentRecipient parameter for the buyFromParlay method
// create instance of Infura provider for optimism network
const provider = new ethers.providers.InfuraProvider(
{ chainId: Number(NETWORK_ID), name: NETWORK },
process.env.INFURA
);
// create wallet instance for provided private key and provider
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
// create instance of Parlay AMM contract
const parlayAMM = new ethers.Contract(
PARLAY_AMM_CONTRACT_ADDRESS,
parlayAMMContractAbi,
wallet
);
const buyFromParlay = async () => {
try {
// get a quote from Overtime API for provided market addresses, market positions and buy-in amount on optimism network
const quoteResponse = await axios.get(
`${API_URL}/overtime/networks/${NETWORK_ID}/parlay/quote?markets=${MARKETS.join(
","
)}&positions=${POSITIONS.join(",")}&buyIn=${BUY_IN}`
);
const quoteData = quoteResponse.data;
console.log("Quote data", quoteData);
// convert payout got from API to BigNumber
const parsedPayout = ethers.utils.parseEther(quoteData.payout.toString());
// convert buy-in amount to BigNumber
const parsedBuyInAmount = ethers.utils.parseEther(BUY_IN.toString());
// convert slippage tolerance to BigNumber
const parsedSlippage = ethers.utils.parseEther(SLIPPAGE.toString());
// call buyFromParlay method on Parlay AMM contract
const tx = await parlayAMM.buyFromParlay(
MARKETS,
POSITIONS,
parsedBuyInAmount,
parsedSlippage,
parsedPayout,
ZERO_ADDRESS,
{
type: 2,
maxPriorityFeePerGas: w3utils.toWei("0.00000000000000001"),
}
);
// wait for the result
const txResult = await tx.wait();
console.log(
`Successfully bought from Parlay AMM. Transaction hash: ${txResult.transactionHash}`
);
} catch (e) {
console.log("Failed to buy from Parlay AMM", e);
}
};
buyFromParlay();
Get a Sports AMM contract address for a specific network from
Get a Sports AMM contract ABI from Overtime contract repository
Get a Parlay AMM contract address for a specific network from
Get a Parlay AMM contract ABI from Overtime contract repository