Skip to main content

ChainGate 1.1.1 — Address validation, custom UTXO transactions & fewer dependencies

· 3 min read

This release adds address validation across all networks, custom UTXO transactions with explicit inputs and outputs, improvements to the fee API, and removes heavy third-party dependencies in favor of native implementations.

Address validation​

Every network descriptor now exposes isValidAddress() — check whether a string is a valid address for that specific network before creating a transaction:

cg.networks.bitcoin.isValidAddress('bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4') // true
cg.networks.ethereum.isValidAddress('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045') // true
cg.networks.bitcoincash.isValidAddress('bitcoincash:qq...') // true

Works on all network types: UTXO, EVM, Bitcoin Cash, and custom EVM RPC networks. EVM validation includes EIP-55 checksum verification for mixed-case addresses.

Combine with identifyAddressType()​

On UTXO networks, identifyAddressType() pairs well with isValidAddress() — it returns the specific script type of a valid address:

cg.networks.bitcoin.identifyAddressType('bc1q...')
// → 'segwit-p2wpkh'

cg.networks.bitcoin.identifyAddressType('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa')
// → 'legacy-p2pkh'

cg.networks.bitcoin.identifyAddressType('bc1p...')
// → 'taproot-p2tr'

Returns 'unknown' for unrecognized formats. Full list of possible types in the documentation.


Custom UTXO transactions​

The new createTransaction() method on UTXO connectors lets you build transactions with explicit inputs and outputs — useful for UTXO consolidation, coin selection, batch payments, or any scenario where transfer() is too opinionated:

const bitcoin = cg.connect(cg.networks.bitcoin, wallet)

const tx = bitcoin.createTransaction({
inputs: [
{ txid: 'abc123...', index: 0, amount: cg.networks.bitcoin.amount('0.001'), script: '0014...' }
],
outputs: [
{ address: 'bc1qRecipient...', amount: cg.networks.bitcoin.amount('0.0009') }
]
})

// Fee is implicitly: inputs - outputs
console.log('Fee:', tx.fee().base(), tx.fee().symbol)

const broadcasted = await tx.signAndBroadcast()

Full API​

  • Inspect: inputs(), outputs(), fee(), estimatedSizeBytes()
  • Mutate: addInput(), removeInput(), addOutput(), removeOutput()
  • Change handling: setChangeAddress(address, fee) — auto-computes the change output with dust threshold handling
  • Fee estimation: recommendedFees() — fetches network fee rates for the current transaction
  • Broadcast: signAndBroadcast()

Listing UTXOs​

A new addressUtxos() method on UTXO connectors makes it easy to find UTXOs to spend:

const utxos = await bitcoin.addressUtxos()

Works on Bitcoin, Litecoin, Dogecoin, Bitcoin Cash, and Bitcoin Testnet. Full guide in the custom UTXO transactions documentation.


Fee API changes​

setFee() accepts tier objects from recommendedFees(), not string tier names:

const tx = await connector.transfer(amount, to)
const fees = tx.recommendedFees()

// Pass the tier object
tx.setFee(fees.high)

// Or pass custom fee parameters
tx.setFee({ feePerKbSat: 15_000n }) // UTXO
tx.setFee({ maxFeePerGas: 30_000_000_000n, // EVM
maxPriorityFeePerGas: 2_000_000_000n })

UTXO transaction size estimation​

estimatedSizeBytes() returns the virtual size in vbytes at the current fee rate:

const size = tx.estimatedSizeBytes()
console.log(size, 'vbytes')

Removed third-party dependencies​

We've eliminated heavy third-party libraries and replaced them with native implementations:

  • bitcore-lib-cash — Bitcoin Cash transaction signing is now implemented from scratch. This removes bitcore-lib-cash and its entire transitive dependency tree (bn.js, elliptic, and others that required version pinning).
  • bchaddrjs — CashAddr encoding and decoding is now a self-contained implementation. Address conversion between CashAddr (bitcoincash:qq...) and legacy Base58Check formats no longer requires an external library.
  • patch-package — No longer needed since there are no third-party packages to patch.

The result is a smaller bundle, fewer transitive dependencies, and no more overrides needed in your package.json.


Migration guide from 1.0​

setFee() — use tier objects instead of strings​

// 1.0 (incorrect — was documented but never worked with strings)
tx.setFee('normal')
tx.setFee('high')

// 1.1.1 (correct)
const fees = tx.recommendedFees()
tx.setFee(fees.normal)
tx.setFee(fees.high)

Full changelog​

FeatureDescription
isValidAddress()Validate addresses on all network types
createTransaction()Build custom UTXO transactions with explicit inputs/outputs
addressUtxos()List UTXOs for a wallet's address on UTXO connectors
estimatedSizeBytes()Get virtual transaction size for UTXO transactions
setFee() APIAccepts tier objects from recommendedFees()
Removed bitcore-lib-cashBCH transaction signing reimplemented natively
Removed bchaddrjsCashAddr encoding/decoding reimplemented natively
Removed patch-packageNo third-party packages require patching