Developer Hub
🔮 For applications
Guides & Tutorials
deBridge cross-chain bets

deBridge cross-chain bets

The deBridge API (opens in a new tab) allows to execute bets on Polygon originating from different blockchains, such as Arbitrum.

⚠️

This feature works only for Prematch Bets in Supported Blockchains (opens in a new tab)

First of all, you need to get a list of supported blockchains and tokens.

Get supported blockchains

type SupportedChainsResponse = {
  chains: {
    chainId: number
    chainName: string
  }[]
}
 
const response = await fetch('https://api.dln.trade/v1.0/supported-chains-info')
const { chains }: SupportedChainsResponse = await response.json()

Get supported tokens

You can pick one of supported blockchains from previous step and get supported tokens:

type SupportedTokensResponse = {
  tokens: Record<string, {
    address: string
    symbol: string,
    decimals: number,
    name: string,
    logoURI: string,
    tags: Array<string>
  }>
}
 
const chainId = 42161 // Arbitrum for example
 
const response = await fetch(`https://api.dln.trade/v1.0/token-list?chainId=${chainId}`)
const { tokens }: SupportedTokensResponse = await response.json()
const supportedTokens = Object.values(tokens) // list of supported tokens

Create transaction and get quotes

Now you need to generate your referral code for deBridge. Go to deBridge (opens in a new tab) website and click the REFER button after that on GENERATE. Or you can go directly to https://app.debridge.finance/statistic/YOUR_WALLET_ADDRESS/referral.

ℹ️

For more information about bet transaction data check Place a Bet section.

import { encodeFunctionData } from 'viem'
 
type DeBridgeCreateTxResponse = {
  orderId: Hex
  estimation: {
    srcChainTokenIn: {
      address: Address
      name: string
      symbol: string
      decimals: number
      amount: string
      approximateOperatingExpense: string
      mutatedWithOperatingExpense: boolean
    },
    srcChainTokenOut: {
      address: Address
      name: string
      symbol: string
      decimals: number
      amount: string
      maxRefundAmount: string
    }
    dstChainTokenOut: {
      address: Address
      name: string
      symbol: string
      decimals: number
      amount: string
      recommendedAmount: string
      withoutAdditionalTakerRewardsAmount: string
      maxTheoreticalAmount: string
    },
    recommendedSlippage: number
    costsDetails: [ string ]
  }
  tx: {
    to: Address
    data: Hex
    value: bigint
  }
  order: {
    approximateFulfillmentDelay: number
  },
  prependedOperatingExpenseCost: string
  fixFee: string
  userPoints: number
  integratorPoints: number
}
 
const fromChainId = 42161 // Arbitrum for example
const fromTokenAddress = '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9' // USDT
const referralCode = '' // your deBridge referral code
 
const selections = [{...}] 
const rawAmount = '...'
const rawDeadline = '...'
const affiliate = '...'
const minOdds = '...'
const betData = 0x...
 
const params = new URLSearchParams({
  dstChainId: 137, // Polygon
  srcChainOrderAuthorityAddress: bettorAddress as string,
  prependOperatingExpenses: 'false',
  srcChainId: String(fromChainId),
  srcChainTokenIn: fromTokenAddress,
  srcChainTokenInAmount: 'auto',
  dstChainTokenOut: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f', // USDT in Polygon
  dstChainTokenOutAmount: String(rawAmount),
  dstChainTokenOutRecipient: bettorAddress as string,
  dstChainOrderAuthorityAddress: bettorAddress as string,
  externalCall: JSON.stringify({
    version: 'evm_1',
    fields: {
      to: lpAddress,
      data: encodeFunctionData({
        abi: lpAbi,
        functionName: 'betFor',
        args: [
          bettorAddress,
          coreAddress,
          rawAmount,
          rawDeadline,
          {
            affiliate,
            minOdds,
            data: betData,
          },
        ],
      }),
    },
  }),
  referralCode: String(referralCode), // your referral code
})
const deBridgeCreateTxResponse = await fetch(`https://api.dln.trade/v1.0/dln/order/create-tx?${params}`)
const { 
  orderId, // deBridge order id
  estimation, // information about gas expense, etc.
  tx, // transaction data
  fixFee // deBridge fixed fee in native tokens
}: DeBridgeCreateTxResponse = await deBridgeCreateTxResponse.json()
⚠️

It's necessary to use the betFor function rather than the bet function to ensure that the bettor can redeem their bet.

Send transaction and order checking

⚠️

Don't forget allowance checks and tokens spending approve:

import { useWriteContract, useReadContract } from 'wagmi'
import { erc20Abi, maxUint256, zeroAddress } from 'viem'
 
const isNative = estimation?.srcChainTokenIn?.address === zeroAddress
 
const allowanceTx = useReadContract({
  chainId: fromChainId,
  address: estimation?.srcChainTokenIn.address,
  abi: erc20Abi,
  functionName: 'allowance',
  args: [
    bettorAddress!,
    tx?.to as Address,
  ],
  query: {
    enabled: !isNative && Boolean(bettorAddress),
    refetchOnWindowFocus: false,
  },
})
 
const isApproveRequired = Boolean(
  allowanceTx.data !== undefined
  && allowanceTx.data < BigInt(estimation?.srcChainTokenIn?.amount || 0)
)
 
const approveTx = useWriteContract()
approveTx.writeContract({
  address: estimation?.srcChainTokenIn.address!,
  abi: erc20Abi,
  chainId: fromChainId,
  functionName: 'approve',
  args: [
    tx?.to as Address,
    maxUint256,
  ],
})

Send transaction from another step and checking order fulfilment in interval:

enum DeBridgeOrderStatus {
  None = 'None',
  Created = 'Created',
  Fulfilled = 'Fulfilled',
  SentUnlock = 'SentUnlock',
  OrderCancelled = 'OrderCancelled',
  SentOrderCancel = 'SentOrderCancel',
  ClaimedUnlock = 'ClaimedUnlock',
  ClaimedOrderCancel = 'ClaimedOrderCancel',
}
 
enum DeBridgeExternalCallStatus {
  NoExtCall = 'NoExtCall',
  AwaitingOrderFulfillment = 'AwaitingOrderFulfillment',
  AwaitingExecution = 'AwaitingExecution',
  Executing = 'Executing',
  Completed = 'Completed',
  Failed = 'Failed',
  Cancelled = 'Cancelled',
}
 
type DeBridgeOrderStatusResponse = {
  orderId: Hex
  status: DeBridgeOrderStatus
  externalCallState: DeBridgeExternalCallStatus
}
 
type DeBridgeOrderTxResponse = {
  fulfilledDstEventMetadata: {
    transactionHash: {
      stringValue: string
    }
  }
}
 
await sendTransaction(tx) // send transaction
 
/*
txHash - bet transaction hash in Polygon
*/
const txHash = await new Promise<Hex>((res, rej) => {
  const interval = setInterval(async () => {
    const orderResponse = await fetch(`https://api.dln.trade/v1.0/dln/order/${orderId}`)
    const order: DeBridgeOrderStatusResponse = await orderResponse.json()
    const {
      status: orderStatus,
      externalCallState: betPlacingStatus,
    } = order
 
    const isBetPlaced = betPlacingStatus === DeBridgeExternalCallStatus.Completed
    const isOrderFulfilled = isBetPlaced || orderStatus === DeBridgeOrderStatus.Fulfilled || orderStatus === DeBridgeOrderStatus.ClaimedUnlock
 
    if (isOrderFulfilled) {
      clearInterval(interval)
 
      const orderTxResponse = await fetch(`https://stats-api.dln.trade/api/orders/${orderId}`)
      const { fulfilledDstEventMetadata }: DeBridgeOrderTxResponse = await orderTxResponse.json()
 
      res(fulfilledDstEventMetadata?.transactionHash?.stringValue as Hex)
    }
 
    let error = ''
 
    if (betPlacingStatus === DeBridgeExternalCallStatus.Cancelled) {
      error = DeBridgeExternalCallStatus.Cancelled
    }
 
    if (betPlacingStatus === DeBridgeExternalCallStatus.Failed) {
      error = DeBridgeExternalCallStatus.Failed
    }
 
    if (orderStatus === DeBridgeOrderStatus.SentOrderCancel) {
      error = DeBridgeOrderStatus.SentOrderCancel
    }
 
    if (orderStatus === DeBridgeOrderStatus.OrderCancelled) {
      error = DeBridgeOrderStatus.OrderCancelled
    }
 
    if (error) {
      clearInterval(interval)
      rej(error)
    }
  }, 5000)
})
ℹ️

More api information you can find in deBridge Swagger (opens in a new tab)