# 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])) || ''
} 
​
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.endless.link/endless/bridge/developer-integration/server-side-integration/example-of-token-cross-chain-js.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
