🔗 ChainGate
A complete cryptocurrency TypeScript framework for connecting to and making transactions on different blockchains
Bitcoin • Ethereum • Binance • Avalanche • Polygon • Arbitrum • Boba
Install ChainGate by executing npm i chaingate
Get your API key now for free on https://chaingate.dev
- 💻❤️🌐 NodeJS & Browser
- 🔌 Plug and Play wallet:
- 🆕 Create new wallet from phrase
- 📥 Import any wallet: BIP39, private keys, seeds
- 🗺️ HDWallets: Supports BIP32 derivation paths
- 📜 Import wallet from phrase (BIP39)
- 🌱 Raw format seeds
- 🔐 Keystores: Ethereum-like keystore, DEX-like keystores
- 🔗 Cross-Chain Functionality
- 🔄 Access to a wide range of blockchain RPCs
- 💱 Balance Querying: Retrieve balances across any currency
- 📡 Easy transaction creation and broadcasting
- 📏 Blockchain Information: Block height, status, transaction details
- 🔮 Gas station: Predict accurately the fees of a transaction
⚠️ USE OF THIS BLOCKCHAIN LIBRARY IS AT YOUR OWN RISK; NO WARRANTIES OR LIABILITIES ARE ASSUMED, AND DATA ACCURACY IS NOT GUARANTEED
Create or import a wallet
Wallet creation
You can create a new wallet by calling:
import {InitializeWallet} from 'chaingate'
const wallet = await InitializeWallet.create('API_KEY')
Import a wallet
Additionally, you can import a wallet created with another software or library:
import { InitializeWallet } from 'chaingate'
const keystore = '{"cipher":"aes-128-ctr"...}'
const wallet = await InitializeWallet.fromKeystore('API_KEY', keystore, 'password')
const phrase = 'abandon abandon about ...'
const wallet = await InitializeWallet.fromPhrase('API_KEY', phrase)
const wallet1 = await InitializeWallet.fromSeed('API_KEY', '676c4f62...')
const wallet2 = await InitializeWallet.fromSeed('API_KEY', new Uint8Array([0x01, 0x02, 0x03]))
const wallet1 = await InitializeWallet.fromPrivateKey('API_KEY', '6b53aa40...')
const wallet2 = await InitializeWallet.fromPrivateKey('API_KEY', new Uint8Array([0xab, 0xcd, 0xed]))
Keys and exporting
You can access the seed phrase or private keys of the wallet you have just created or imported:
import { InitializeWallet } from 'chaingate'
const wallet = await InitializeWallet.create('API_KEY')
const phrase : string = wallet.Phrase
const seed : string = wallet.getSeed()
const wallet2 = await InitializeWallet.fromPrivateKey('API_KEY', '6b53aa40...')
const privateKeyRaw : Uint8Array = wallet2.PrivateKey.raw
const privateKeyHexa : string = wallet2.PrivateKey.hexa
const privateKeyWIF : string = wallet2.PrivateKey.wif
const publicKey = await wallet2.PrivateKey.getPublicKey()
const publicKeyCompressed = publicKey.compressed
const publicKeyUncompressed = publicKey.uncompressed
Addresses
Additionally, to obtain addresses of different blockchains:
import { InitializeWallet } from 'chaingate'
const wallet = await InitializeWallet.create('API_KEY')
const bitcoinAddress = await wallet.currencies.bitcoin.getAddress()
const ethereumAddress = await wallet.currencies.ethereum.getAddress()
const polygonAddress = await wallet.currencies.polygon.getAddress()
Derivation paths
If you import using a phrase or seed, you can utilize derivation paths in any currency. By default, the derivation path used is the default for the currency.
To change the derivation path, call setDerivationPath() as follows:
import { InitializeWallet } from 'chaingate'
const wallet = await InitializeWallet.create('API_KEY')
const addressDefault = await wallet.currencies.bitcoin.getAddress()
await wallet.currencies.bitcoin.setDerivationPath('m/44\'/0\'/0\'/1/3')
const addressNonDefaultDerivationPath = await wallet.currencies.bitcoin.getAddress()
Query balances
To initiate a transaction or operate on the blockchain, you need to fund your addresses. After funding your wallet's addresses, you can query their balances to confirm you possess the corresponding crypto:
import { InitializeWallet } from 'chaingate'
const wallet = await InitializeWallet.create('')
const bitcoinAddress = wallet.currencies.bitcoin.getAddress()
const ethereumAddress = wallet.currencies.ethereum.getAddress()
const bitcoinBalance = await wallet.currencies.bitcoin.getBalance()
console.log(`Confirmed balance in BTC: ${bitcoinBalance.confirmed.baseAmount}`)
console.log(`Confirmed balance in satoshi: ${bitcoinBalance.confirmed.minimalUnitAmount}`)
const ethereumBalance = await wallet.currencies.ethereum.getBalance()
console.log(`Confirmed balance in ETH: ${ethereumBalance.confirmed.baseAmount}`)
console.log(`Confirmed balance in wei: ${ethereumBalance.confirmed.minimalUnitAmount}`)
const allBalances = await wallet.getAllBalances()
for(const b of allBalances)
console.log(`Your ${b.currency.name} wallet amount is ${b.balance.confirmed.baseAmount} ${b.balance.confirmed.baseSymbol}`)
Create and broadcast a transaction
Transferring crypto is easy with ChainGate. You can prepare a transaction, query the possible fees, confirm it, and broadcast it to the network:
import { InitializeWallet } from 'chaingate'
const phrase = 'abandon abandon about...'
const wallet = await InitializeWallet.fromPhrase('API_KEY', phrase)
const bitcoinAddress = wallet.currencies.bitcoin.getAddress()
const bitcoinBalance = await wallet.currencies.bitcoin.getBalance()
console.log(`The Bitcoin address of your wallet is ${bitcoinAddress}`)
console.log(`You currently have ${bitcoinBalance} BTC`)
const bitcoin = wallet.currencies.bitcoin
const transaction = await bitcoin.prepareTransfer(
'1111111111111111111114oLvT2',
bitcoin.amount('1000 satoshi')
)
console.log(`We are going to use a fee of ${transaction.possibleFees['high']}`)
const broadcasted = await transaction.confirm('high')
console.log(`Transaction is on the network :) The txid is ${broadcasted.txId}`)
console.log('Wait for confirmation... This might take a while')
await broadcasted.isConfirmed()
console.log('The transaction is fully confirmed')
const transaction2 = await bitcoin.prepareTransfer(
'1111111111111111111114oLvT2',
bitcoin.amount('1 btc')
)
const transaction3 = await bitcoin.prepareTransfer(
'1111111111111111111114oLvT2',
bitcoin.amount('1')
)
Query RPCs
If you're using libraries such as Web3.js or Ethers, or need to work with code not directly supported by ChainGate, you can leverage ChainGate's reliable RPC endpoints for various cryptocurrencies, including:
- Arbitrum
- Avalanche C-Chain
- Binance Smart Chain
- Bitcoin
- Boba Network
- Ethereum
- Fantom Opera
- Polygon
- zkSync
To access these RPCs, query the API URL, which can be found in the ChainGate API Documentation RPCs.
When using Web3.js or Ethers, include your API KEY in the URL within the 'apiKey' parameter:
import Web3 from 'web3'
const chainGateApiKey = 'API_KEY'
const web3 = new Web3(`https://api.chaingate.dev/rpc/binance?api_key=${chainGateApiKey}`)
const latestBlock = await web3.eth.getBlock('latest')
console.log(latestBlock)
import { JsonRpcProvider } from 'ethers'
const chainGateApiKey = 'API_KEY'
const ethers = new JsonRpcProvider(`https://api.chaingate.dev/rpc/binance?api_key=${chainGateApiKey}`)
const latestBlock = await ethers.getBlock('latest')
console.log(latestBlock)
Query the API directly
ChainGate offers a ChainGate API with REST endpoints, providing advanced features and information on supported blockchains.
API documentation: ChainGate API Documentation
Key features of the API include:
- Transaction details
- Mempool
- Block transactions
- (...)
Access the API through a ApiClient instance:
import { ApiClient } from 'chaingate'
const apiClient = new ApiClient('API_KEY')
const transactionDetails = (await apiClient.Bitcoin.transactionDetails('e9a66845...')).data
const mempool = (await apiClient.Ethereum.mempool()).data
const blockTransactions = (await apiClient.Bitcoin.blockTransactions(1000)).data
Why am I receiving the message "You are running with an unencrypted wallet..."
Occasionally, you may receive the following message through the console:
You are running with an unencrypted wallet. This should only be done for development purposes.
If you intend to use it in production, call encrypt(password) after it is created,
and run functions that require the usage of private key with runUnencrypted(password, ...)
Software wallets face a significant problem: the private key is stored unencrypted in the memory. If someone gains access to the computer's memory (e.g., through a debugger), the wallet's private key can be compromised.
The solution that ChainGate proposes is to encrypt the wallet with a password (using AES encryption) and ask the user for the password every time the private key needs to be accessed (such as when building a transaction or exporting the private key).
To implement this, encrypt the wallet initially and, for every code that outputs the message, prompt the user for the password and run the code with runUnencrypted(password, ...)
. Here's an example:
import { InitializeWallet } from 'chaingate'
import p from 'prompt-sync'
import {Units} from 'chaingate'
const prompt = p()
const phrase = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
const wallet = await InitializeWallet.fromPhrase('API_KEY', phrase)
const walletPassword = prompt('Wallet password? ')
await wallet.encrypt(walletPassword)
const transaction = await wallet.currencies.bitcoin.prepareTransfer(
'1111111111111111111114oLvT2',
Units.Satoshis('1_000_000')
)
const password = prompt('What is the wallet password? ')
await wallet.runUnencrypted(password, async () => {
await transaction.confirm('normal')
})
To remove this message safely, set the variable process.env.I_AM_SURE_I_AM_NOT_IN_PRODUCTION
to a truthy value.
Why I am receiving the message "You have exhausted your API tier limit..."
If you encounter the message:
You have exhausted your API tier limit, and ChainGate is operating beyond its capacity. Consider upgrading to a higher tier.
it indicates that you have reached the limit of your current API tier with ChainGate. As a result, you may experience delays or slower performance when using the API. To resolve this issue, you should consider upgrading to a higher tier or paying for a ChainGate subscription.
You can upgrade your tier or manage your subscription by visiting the ChainGate application at https://app.chaingate.dev.
To remove this message safely, set the variable process.env.DISABLE_EXHAUSTED_TIER_MESSAGE
to a truthy value.
I can't build my web app: "webpack < 5 used to include polyfills for node.js core modules by default"
What's the issue?
Webpack versions below 5 automatically included polyfills for certain Node.js core modules. These polyfills make those modules work in browser environments. With Webpack 5, this behavior changed, and you might need to configure polyfills manually.
Why does ChainGate need polyfills?
ChainGate uses some native libraries that aren't available directly in browsers. Polyfills provide browser-compatible versions of these libraries.
Solution: Using node-polyfill-webpack-plugin
To fix this, you can use a helpful plugin called node-polyfill-webpack-plugin
.
Here's how to integrate it:
- Install the plugin:
npm install node-polyfill-webpack-plugin
- Update
webpack.config.js
:
Add the following code to your webpack.config.js
file:
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
module.exports = {
plugins: [
new NodePolyfillPlugin(),
],
};
This code imports the plugin and adds it to the plugins
array in your Webpack configuration.
Special thanks to Richienb for creating this amazing module!