Place a Bet
Place a single bet
All LP works with ERC20 tokens as a bet token
import { ethers } from 'ethers'
const data = ethers.utils.defaultAbiCoder.encode(
[ 'tuple(uint256, uint64)' ],
[ { conditionId, outcomeId } ]
)
lp.bet(
prematchCoreAddress,
rawAmount,
deadline,
{
affiliate: '0x...', // Your wallet address to earn rewards
data,
minOdds: rawMinOdds,
}
)
Note that the placing bets in ERC20 tokens requires users to make an approve of tokens spending.
Place bet using native token
Deprecated. Liquidity Pool in Gnosis chain works on WXDAI (wrapped ERC20 version of native token). To place bets in Gnosis chain suggest customers to wrap and unwrap tokens.
Wrap/unwrap WXDAI
// wagmi/viem example
txDto.to = '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d'
// XDAI -> WXDAI
if (isWrap) {
txDto.value = rawAmount
txDto.data = encodeFunctionData({
abi: erc20ABI,
functionName: 'deposit',
})
}
// WXDAI -> XDAI
else {
txDto.data = encodeFunctionData({
abi: erc20ABI,
functionName: 'withdraw',
args: [ rawAmount ],
})
}
sendTransaction(txDto)
Place a batch of single bets
To send a batch of single bets you should use ProxyFront contract.
Note that data structure differs from the structure of placing single bet on LP contract.
import { ethers } from 'ethers'
const data = ethers.utils.defaultAbiCoder.encode(
[ 'tuple(uint256, uint64)' ],
[ { conditionId, outcomeId } ]
)
const betData1 = {
core: prematchCoreAddress,
amount: rawAmount,
expiresAt: deadline,
extraData: {
affiliate: '0x...', // Your wallet address to earn rewards
data,
minOdds: rawMinOdds,
},
}
const betData2 = {...}
proxyFront.bet(
lpAddress,
[
betData1,
betData2,
],
)
Place a combo bet
To place a combo bet with several selections you can use any LP or ProxyFront contract.
The difference with single bet is just in data
field (array instead of single tuple) and core address.
import { ethers } from 'ethers'
const selections: { conditionId: string, outcomeId: string }[]
const data = ethers.utils.defaultAbiCoder.encode(
[ 'tuple(uint256, uint64)[]' ],
[ selections ]
)
lp.bet(
prematchCoreAddress,
rawAmount,
deadline,
{
affiliate: '0x...', // Your wallet address to earn rewards
data,
minOdds: rawMinOdds,
}
)
/* =============================== */
// OR via ProxyFrontContract
const betData = {
core: expressCoreAddress,
amount: rawAmount,
expiresAt: deadline,
extraData: {
affiliate: '0x...', // Your wallet address to earn rewards
data,
minOdds: rawMinOdds,
},
}
proxyFront.bet(
lpAddress,
[
betData,
// yes it's also possible to place a batch of combo bets 🙈
],
)
Some conditions have restrictions and cannot be used in a combo bet, for example, eSports conditions. To avoid this error you need check the isExpressForbidden
field in condition subgraph data, if this field is true
than you should forbid such combo bet and show warning notification in your UI.
Place a freebet
If you're using freebets feature, then customer may place a bet using available freebet. See details on structure and how to fetch in Use Freebets section.
To apply freebet, outcome.rawMinOdds
should be greater than freebet.minOdds
. The bet should be single - freebets aren't applicable to combo bets.
Please note that we provide you with the flexibility to distribute Freebets without a budget limitation. However, if your customers claim Freebets for an amount exceeding the freebet contract balance, they will encounter an error during the smart contract execution call.
import { ethers } from 'ethers'
if (BigInt(outcome.rawMinOdds) < BigInt(freebet.minOdds)) {
// outcome minOdds should be greater than freebet.minOdds
return
}
const data = ethers.utils.defaultAbiCoder.encode(
[ 'tuple(uint256, uint64)' ],
[ { conditionId, outcomeId } ]
)
const freebetContract = new Contract(freebet.contract.freebetContractAddress, freebetABI)
freebetContract.bet(
{
chainId: freebet.contract.chainId,
expiresAt: freebet.expiresAt,
amount: freebet.amount,
freeBetId: freebet.id,
minOdds: freebet.minOdds,
owner: account,
},
freebet.signature,
coreAddress,
conditionId,
outcomeId,
deadline,
outcome.rawMinOdds
)
Highlights
conditionId
& outcomeId
To clarify, conditionId
and outcomeId
values should be taken from the specific outcome that the user is placing
their bet on within the game. These ids can be obtained by iterating through the outcomes array of the Game object and
finding the relevant outcome that the user has selected.
Additionally, the prematchCoreAddress
value should be the address of the Core
contract that is associated with the LP
contract that the user is betting on. Each condition entity has prematchCoreAddress
field containing this value.
rawMinOdds
The minOdds
parameter is used to specify the minimum odds value at which the bet can be placed. If the current odds value is lower than the specified value, the bet cannot be placed and will be rejected by the contract.
To calculate the minimum odds, you can use the slippage factor. The slippage factor is the percentage by which the current odds can change in a smaller direction.
For example, if the current odds for an outcome is 2, and the user sets a slippage factor of 5%, then the minimum odds that the user will accept is 1.9 (2 * 0.95). This ensures that the user's bet is not accepted if the odds fall below the minimum acceptable value.
The slippage factor can be specified by the user in the interface and then passed as a parameter to the bet method.
const currentOdds = 1.5 // the odds value taken from contracts in the moment of bet placing
const slippage = 5 // 5%
const minOdds = 1 + (currentOdds - 1) * (100 - slippage) / 100
The betting methods accept BigNumberish
value for minOdds
.
const oddsDecimals = 12 // in current version of protocol odds has 12 decimals
const rawMinOdds = parseUnits(minOdds.toFixed(oddsDecimals), oddsDecimals)
deadline
This parameter specifies the deadline by which the transaction must be included in a block. If the transaction is not included in a block before the deadline, the transaction will revert. The value of this parameter should be passed in seconds.
const currentTime = Math.floor(Date.now() / 1000)
const deadline = currentTime + 2000 // the bet should be accepted within the next 2000 seconds
affiliate
This is the wallet address where the rewards will be distributed. Please be aware that the accumulation of rewards is predicated on them being associated with this specific wallet. To receive your rewards directly into this wallet, you must redeem them accordingly. Read about rewards distribution here.
Recommendations
It's important to ensure that the user has sufficient funds in their account before placing a bet, and to handle errors from contracts gracefully if the bet cannot be placed due to insufficient funds or other reasons.
Keeping the odds updated is essential for providing the best user experience to your customers. By subscribing to odds updates, you can keep the odds values up-to-date in real-time, which can help reduce the risk of user frustration or missed betting opportunities. Alternatively, you can fetch the odds values before a user submits a bet to ensure that the odds values are current at the time of the bet placement.