Example of Token Cross-Chain (JS)

  1. EVM to ENDLESS


`First===>: Estimated gas`
//Gas Estimation Method
const getGasPrice = async (chain: ChainData) => {
    const provider = getProvider(chain.rpc_url)
    const feeData = await provider.getFeeData()
    return feeData.gasPrice?.toString() || '0'
}

const contract = await getContract(tokenAddress, IBridgePoolAbi, toChain.rpc_url)
const maxFeePerGasWei = await getGasPrice(toChain) //Get gas through 1559
const arg1 = {
    msg_header: _msgHead,
    msg_body: `0x${msg_body}`,
}

const amount = await contract.getLpFeeAndFinalAmount(
    combainChain(chain).toString(),
    sourceToken,
    BigInt(toChainNumber(bridgeData.amount, toToken.decimals)).toString(),
    ) //Get the payment amount by calling the contract
    useTokenStore.getState().updateReceiveAmount([...amount][1])

const gaslimit = await contract.processMsg.estimateGas(arg1, [], {
    from: '0x0000000000000000000000000000000000000001',
    })  //Get gasLimit

const estimatedGasCost = BigNumber(maxFeePerGasWei)
    .times(gaslimit.toString())
    .div(10 ** toChain.token_decimal)
    .toFixed()

`Second===>: Cross-chain`

//Cross-chain method
const bridgeTo = async () => {

  const gasFee = useBridgeStore.getState().gasFee
  let addr_bridge_token = toChain.addr_bridge_token

  const chain_type = getChainType(toChain.id)
  const chain_id = toChain.id.split('-')[1]
  const chain = new Uint8Array(9)
  chain.set(numberToU8(chain_type), 0)
  chain.set(numberToU64(Number(chain_id)), 1)

  const config = new EndlessConfig({
    network: EndlessNetwork,
  })
  const endless = new Endless(config)
 let feeAuto = BigInt(BigNumber(toChainNumber(gasFee, fromChain.token_decimal)).toFixed() || 0)

const functionArguments = [
    AccountAddress.fromBs58String(fromToken.address),
    chain,
    stringToBytes32(addr_bridge_token),
    stringToBytes32(receiveAddress),
    BigInt(toChainNumber(bridgeData.amount, fromToken.decimals)),
    feeAuto,
  ]

  const transferData: EndlessSignAndSubmitTransactionInput = {
    payload: {
      function: `${getBytes32Address(fromChain.id, fromChain.addr_bridge_token)}::execute::bridge_proposal`,
      functionArguments: functionArguments,
      typeArguments: [],
    },
  }
  const transactionRes = await useEndlessStore.getState()?.jssdk?.signAndSubmitTransaction(transferData)
  useTokenStore.getState().updateProgress(1)
  if (transactionRes?.status === UserResponseStatus.APPROVED) {
    const result = await endless.waitForTransaction({ transactionHash: transactionRes.args.hash })
    if (result.success) {
      return {
        txhash: transactionRes.args.hash,
        bridgeData: {},
      }
    } else {
      throw transactionRes
    }
    } else {
    throw transactionRes
   }
 }

2、ENDLESS to EVM

## EDS to ETH

`First===>: Estimated gas`

// This method can get the message body and message head required for cross-chain
const getBodyAndHead = (params: IBodyAndHead) => {
const { bridgeData, nonceMap, fromChain, toChain, fromToken, sourceToken, fromWho, toWho } = params
const gas = new BN(bridgeData.feeAuto)
const gasByte = gas.toArray('le', 16)

const nonce = new BN(BigNumber(nonceMap).plus(1).toString())
const nonceByte = nonce.toArray('le', 8)

const msgType = new BN(0)
const msgTypeByte = msgType.toArray('be', 1)

const from_chain_type = new BN(getChainType(fromChain.id))
const from_chain_typeByte = from_chain_type.toArray('be', 1)

const allAmountBN = new BN(BigInt(toChainNumber(bridgeData.amount, fromToken.decimals)).toString())

const allAmountByte = allAmountBN.toArray('be', 16)

const to_chain_type = new BN(getChainType(toChain.id))
const to_chain_typeByte = to_chain_type.toArray('be', 1)

const to_chain_id = new BN(toChain.id.split('-')[1])
const to_chain_idByte = to_chain_id.toArray('le', 8)

const from_chain_id = new BN(fromChain.id.split('-')[1])
const from_chain_idByte = from_chain_id.toArray('le', 8)

const head = msgTypeByte.concat(
    Array.from(nonceByte),
    Array.from(from_chain_typeByte),
    Array.from(from_chain_idByte),
    hexToArray(
    getBytes32Address(
        fromChain.id,
        getChainType(fromChain.id) === ChainType.TRX
        ? base58ToHex(fromChain.addr_bridge_token)
        : fromChain.addr_bridge_token,
    ),
    ),
    Array.from(to_chain_typeByte),
    Array.from(to_chain_idByte),
    hexToArray(
    getBytes32Address(
        toChain.id,
        getChainType(toChain.id) === ChainType.TRX ? base58ToHex(toChain.addr_bridge_token) : toChain.addr_bridge_token,
    ),
    ),
    Array.from(gasByte),
)

const body = hexToArray(cusHex(sourceToken)).concat(
    Array.from(allAmountByte),
    hexToArray(cusHex(fromWho)),
    hexToArray(cusHex(toWho)),
)

return { body, head }
}

const { body, head } = getBodyAndHead({
        bridgeData: bridgeData,
        nonceMap: res,
        fromChain: fromChain,
        toChain: toChain,
        fromToken: fromToken,
        sourceToken: sourceToken,
        fromWho: fromWho,
        toWho: toWho,
    })

getEstimateGas(head, body)

// Get gas from to chain
const getEstimateGas = async (mesHead: number[], mesBody: number[]) => {

const txn = await endless.transaction.build.simple({
    sender: ENDLESS_SIMULATE_SENDER,
    data: {
    function: `${ENDLESS_CONTRACT}::execute::bridge_finish_estimate_gas`,
    functionArguments: [mesHead, mesBody, [], []],
    },
})

const account = new Ed25519PublicKey(ENDLESS_SIMULATE_PUBLICKEY)

const transactionRes = await endless.transaction.simulate.simple({
    signerPublicKey: account,
    transaction: txn,
    feePayerPublicKey: account,
})

const gasFee = BigNumber(transactionRes[0].gas_used || 0)
.times(transactionRes[0].gas_unit_price)
.div(10 ** 8)
.toFixed()
}

`Second===>: Cross-chain`
//Cross-chain method
const bridgeTo = async () => {
   await approveErc20({
      token: fromToken.address,
      spender: fromChain.addr_bridge_token,
      decimal: fromToken.decimals,
      payAmount: bridgeData.amount,
      rpc: fromChain.rpc_url,
      nativeToken: fromChain.native_token,
      approveAmount: bridgeData.amount,
    })

    let value = BigNumber(0)

    value = value.plus(BigNumber(toChainNumber(gasFee, fromChain.token_decimal) || 0))

    if (bridgeData.feeFrom) {
      value = value.plus(bridgeData.feeFrom || 0)
    }
    if (fromToken.address.toLocaleLowerCase() === fromChain.native_token.toLocaleLowerCase()) {
      value = value.plus(toChainNumber(bridgeData.amount, fromChain.token_decimal))
    }

    if (collFee) {
      value = value.plus(collFee.toString())
    }
// value is composed of gas + platform fee + amount + collect fee
     const _bridgeData = [
      getBytes32Address(fromChain.id, fromToken.address),
      {
        chain_type: getChainType(toChain.id),
        chain_id: toChain.id.split('-')[1],
      },
      getBytes32Address(toChain.id, receiveAddress),
      getBytes32Address(toChain.id, toChain.addr_bridge_token),
      BigInt(toChainNumber(bridgeData.amount, fromToken.decimals)),
      BigInt(BigNumber(toChainNumber(gasFee, fromChain.token_decimal)).toFixed()),
    ]

    const params = {
      from: address,
      to: fromChain.addr_bridge_token,
      value: numberToHexString(value.toString()),
      data: new ethers.Interface(IBridgePoolAbi).encodeFunctionData('bridgeToken', _bridgeData),
    }
    await estimateGas({ params, rpc: fromChain.rpc_url })
    const txhash = (await sendTransaction([params])) || ''
} 

Last updated