@thru/bridge
v0.4.1
Published
TypeScript SDK for Polygon-to-Thru bridge deposits and withdrawals.
Maintainers
Readme
@thru/bridge
TypeScript SDK for Polygon-to-Thru bridge deposits and withdrawals.
Setup
import { createBridgeClient } from '@thru/bridge';
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!,
},
});Config is chain-scoped:
polygon.polygonBridgeAddress: Polygon Bridge contract address.polygon.signer: Polygon transaction signer and fee payer.thru.thruBridgeProgramAddress: Thru bridge program address.thru.tokenProgramAddress: optional Token deployment override; defaults to the SDK's canonicaltaTOKENKRgcl3vO0yVhftATDbXuhgWcfaaxv9xpEEdMdUEfor freshly bootstrapped networks. Set this explicitly for a different deployed network.thru.signer.feePayerAddress: Thru fee payer/depositor account (ta...).thru.signer.feePayerPrivateKey: Thru Ed25519 private key (32-byte hex).
Approve + Deposit Example
Approve first:
const approve = await bridge.approvePolygonToken({
polygonTokenAddress: '0xYourPolygonTokenAddress',
rawAmount: 1_000_000n,
});Then deposit:
const result = await bridge.depositPolygonToThru({
thruRecipient: 'taXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
polygonTokenAddress: '0xYourPolygonTokenAddress',
rawAmount: 1_000_000n,
});
console.log(result.polygonTxHash, result.polygonDepositEvent?.sequence.toString());Metadata by token address:
const metadata = await bridge.getPolygonTokenMetadata('0xYourPolygonTokenAddress');
console.log(metadata.name, metadata.symbol, metadata.decimals);Thru -> Polygon Example
Check if a Thru mint is actually a Polygon-bridged token:
const route = await bridge.getThruPolygonTokenRoute('taYourThruTokenMint');
if (!route.isPolygonBridgedToken) {
throw new Error('mint is not bridged from Polygon');
}
console.log(route.polygonTokenAddress);Deposit back to Polygon:
const result = await bridge.depositThruToPolygon({
thruTokenMintAddress: 'taYourThruTokenMint',
polygonRecipientAddress: '0xYourPolygonRecipient',
rawAmount: 1_000_000n,
});
console.log(result.thruSignature);Fixed Chain IDs
thru = 1polygon = 2
Available Functions
Top-level exports:
createBridgeClient(config)POLYGON_BRIDGE_ABIPOLYGON_ERC20_ABITHRU_POLYGON_CHAIN_IDSTHRU_TOKEN_PROGRAM_ADDRESS
BridgeClient methods:
getPolygonTokenMetadata(polygonTokenAddress)approvePolygonToken({ polygonTokenAddress, rawAmount })depositPolygonToThru({ thruRecipient, polygonTokenAddress, rawAmount })getPolygonDepositFromTx(txHash)getThruPolygonTokenRoute(thruTokenMintAddress)depositThruToPolygon({ thruTokenMintAddress, polygonRecipientAddress, rawAmount, thruTokenAccountAddress?, payloadHex? })
Recipient address conversion is handled internally by depositPolygonToThru(...).
Amount Rules
rawAmountisbigintonly.rawAmountis validated asu64(0..18446744073709551615).- Submitted deposit amount must be
> 0.
Allowance Requirement
depositPolygonToThru(...)checks ERC20 allowance and throws if insufficient.- Call
approvePolygonToken(...)before deposit (or approve externally).
