Skip to main content
This page is for teams integrating the bridge between Polygon and Thru.

Bridge Chain IDs

ChainBridge Chain ID
Thru1
Polygon2
These IDs are bridge-protocol IDs (not EVM chainId values).

Integration Resources

ResourceValue
Polygon bridge contract addressTBD_POLYGON_BRIDGE_ADDRESS
Thru bridge program addressTBD_THRU_BRIDGE_PROGRAM_ADDRESS
Polygon RPC URLTBD_POLYGON_RPC_URL
Thru RPC URLTBD_THRU_BASE_URL
Publish mainnet/testnet contract and program addresses in this table when finalized.

TypeScript SDK (@thru/bridge-sdk)

Setup

import { createBridgeClient } from '@thru/bridge-sdk';

const bridge = createBridgeClient({
  polygon: {
    signer: {
      privateKey: process.env.POLYGON_PRIVATE_KEY!,
      rpcUrl: process.env.POLYGON_RPC_URL!,
    },
    polygonBridgeAddress: process.env.POLYGON_BRIDGE_ADDRESS!,
  },
  thru: {
    signer: {
      baseUrl: process.env.THRU_BASE_URL!,
      feePayerAddress: process.env.THRU_FEE_PAYER_ADDRESS!,
      feePayerPrivateKey: process.env.THRU_FEE_PAYER_PRIVATE_KEY!,
    },
    thruBridgeProgramAddress: process.env.THRU_BRIDGE_PROGRAM_ADDRESS!,
  },
});

Polygon -> Thru example

const approve = await bridge.approvePolygonToken({
  polygonTokenAddress: '0xYourPolygonTokenAddress',
  rawAmount: 1_000_000n,
});

const result = await bridge.depositPolygonToThru({
  thruRecipient: 'taXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
  polygonTokenAddress: '0xYourPolygonTokenAddress',
  rawAmount: 1_000_000n,
});

console.log(approve.polygonTxHash);
console.log(result.polygonTxHash, result.polygonDepositEvent?.sequence.toString());

Thru -> Polygon example

const route = await bridge.getThruPolygonTokenRoute('taYourThruTokenMint');
if (!route.isPolygonBridgedToken) {
  throw new Error('mint is not bridged from Polygon');
}

const result = await bridge.depositThruToPolygon({
  thruTokenMintAddress: 'taYourThruTokenMint',
  polygonRecipientAddress: '0xYourPolygonRecipient',
  rawAmount: 1_000_000n,
});

console.log(route.polygonTokenAddress, result.thruSignature);

Fixed constants

  • THRU_POLYGON_CHAIN_IDS.thru = 1
  • THRU_POLYGON_CHAIN_IDS.polygon = 2
  • THRU_TOKEN_PROGRAM_ADDRESS = taAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqq

SDK functions

Client Methods

getPolygonTokenMetadata

getPolygonTokenMetadata(polygonTokenAddress: string): Promise<PolygonTokenMetadata>
Reads name, symbol, and decimals from a Polygon ERC20 token.

approvePolygonToken

approvePolygonToken({
  polygonTokenAddress,
  rawAmount,
}): Promise<PolygonTokenApprovalResult>
Sends ERC20 approval so the Polygon bridge can spend rawAmount.

depositPolygonToThru

depositPolygonToThru({
  thruRecipient,
  polygonTokenAddress,
  rawAmount,
}): Promise<PolygonToThruDepositResult>
Executes a Polygon -> Thru deposit and parses the deposit event from the Polygon receipt.

getPolygonDepositFromTx

getPolygonDepositFromTx(txHash: string): Promise<PolygonDepositEvent | null>
Fetches and parses a historical Polygon Deposit event from a transaction hash.

getThruPolygonTokenRoute

getThruPolygonTokenRoute(
  thruTokenMintAddress: string
): Promise<ThruPolygonTokenRoute>
Checks whether a Thru mint is mapped to a Polygon-origin bridged token and returns route metadata.

depositThruToPolygon

depositThruToPolygon({
  thruTokenMintAddress,
  polygonRecipientAddress,
  rawAmount,
  thruTokenAccountAddress?,
  payloadHex?,
}): Promise<ThruToPolygonDepositResult>
Executes a Thru -> Polygon deposit for a valid Polygon-bridged token route. Amount rules:
  • rawAmount is bigint (raw token units)
  • Validated as u64 (0..18446744073709551615)
  • Deposit amount must be greater than 0

Direct Polygon Contract Integration (EVM side)

The SDK exports:
  • POLYGON_BRIDGE_ABI
  • POLYGON_ERC20_ABI
Polygon bridge entrypoint:
function deposit(address token, uint256 amount, bytes32 recipient) external;
Deposit event:
event Deposit(
  uint256 indexed sequence,
  uint16 sourceChainId,
  uint16 destChainId,
  address token,
  address depositor,
  bytes32 recipient,
  uint256 amount,
  string tokenName,
  string tokenSymbol,
  uint8 tokenDecimals
);
Required Polygon call flow:
  1. Convert Thru recipient (ta...) to bytes32.
  2. Call ERC20 approve(bridgeAddress, amountRaw).
  3. Call bridge deposit(token, amountRaw, recipientBytes32).
Bytes32 conversion example for direct EVM integration:
import { Pubkey } from '@thru/thru-sdk';

const recipientBytes32 = `0x${Pubkey.from(thruRecipient).toHex()}`;
Expected bridge route values for Polygon -> Thru events:
  • sourceChainId = 2
  • destChainId = 1

Bridge Configuration Specification (Coming Soon)

Configuration specs for bridge/guardian/relayer setup (addresses, endpoints, keys, and example config files) will be documented here in a future update.