> For the complete documentation index, see [llms.txt](https://docs.endless.link/endless/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.endless.link/endless/bridge/developer-integration/server-side-integration/example-of-token-cross-chain-js.md).

# 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
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
