npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

chaingate

v0.2.1

Published

A complete TypeScript library for connecting to and making transactions on different blockchains

Downloads

397

Readme

🔗 ChainGate

A complete cryptocurrency TypeScript framework for connecting to and making transactions on different blockchains

Bitcoin • Ethereum • Binance • Avalanche • Polygon • Arbitrum • Boba

banner.png

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'  
  
// Initialize wallet from keystore  
const keystore = '{"cipher":"aes-128-ctr"...}'  
const wallet = await InitializeWallet.fromKeystore('API_KEY', keystore, 'password')  
  
//Initialize wallet from phrase  
const phrase = 'abandon abandon about ...'  
const wallet = await InitializeWallet.fromPhrase('API_KEY', phrase)  
  
//Initalize wallet from seed  
const wallet1 = await InitializeWallet.fromSeed('API_KEY', '676c4f62...')  
const wallet2 = await InitializeWallet.fromSeed('API_KEY', new Uint8Array([0x01, 0x02, 0x03]))  
  
//Initalize wallet from private key  
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')  
  
// Export phrase or seed  
const phrase : string = wallet.Phrase   //Phrase  
const seed : string = wallet.getSeed()  //Seed  
  
  
const wallet2 = await InitializeWallet.fromPrivateKey('API_KEY', '6b53aa40...')  
  
// Export private key of the wallet in various formats  
const privateKeyRaw : Uint8Array = wallet2.PrivateKey.raw  
const privateKeyHexa : string = wallet2.PrivateKey.hexa  
const privateKeyWIF : string = wallet2.PrivateKey.wif  
  
// Export public key of the wallet  
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')

//Default derivation path is used
const addressDefault = await wallet.currencies.bitcoin.getAddress()

//Change derivation path
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('')

// Verify your crypto addresses (in bitcoin and ethereum) to fund them
const bitcoinAddress = wallet.currencies.bitcoin.getAddress()
const ethereumAddress = wallet.currencies.ethereum.getAddress()

// Query the balance of Bitcoin
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}`)


// Query the balance of Ethereum
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}`)

//Get a resume of balances
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)

//Verify the address and balance of your wallet
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`)

//Prepare the transaction
const bitcoin = wallet.currencies.bitcoin
const transaction = await bitcoin.prepareTransfer(
        '1111111111111111111114oLvT2', //Destination address
        bitcoin.amount('1000 satoshi') //Amount (in Satoshi)
)

//We will use fast fees for transaction to confirm earlier
console.log(`We are going to use a fee of ${transaction.possibleFees['high']}`)

//Broadcast the transaction
const broadcasted = await transaction.confirm('high') //High confirmation fees
console.log(`Transaction is on the network :) The txid is ${broadcasted.txId}`)

//Wait until is confirmed
console.log('Wait for confirmation... This might take a while')
await broadcasted.isConfirmed()
console.log('The transaction is fully confirmed')


//You can also use native units:
const transaction2 = await bitcoin.prepareTransfer(
        '1111111111111111111114oLvT2', //Destination address
        bitcoin.amount('1 btc') //Amount (1 BTC)
)

const transaction3 = await bitcoin.prepareTransfer(
        '1111111111111111111114oLvT2', //Destination address
        bitcoin.amount('1') //Amount (1 BTC)
)

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')  
  
//Get transaction details  
const transactionDetails = (await apiClient.Bitcoin.transactionDetails('e9a66845...')).data  
  
//Get mempool transactions  
const mempool = (await apiClient.Ethereum.mempool()).data  
  
//Get block transactions  
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()  
  
//Initialize wallet  
const phrase = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'  
const wallet = await InitializeWallet.fromPhrase('API_KEY', phrase)

//Ask for password  
const walletPassword = prompt('Wallet password? ')  

//Encrypt wallet  
await wallet.encrypt(walletPassword)
//Prepare a transaction  
const transaction = await wallet.currencies.bitcoin.prepareTransfer(  
    '1111111111111111111114oLvT2', //Destination address  
    Units.Satoshis('1_000_000') //Amount (in Satoshi)  
)  
  
//Broadcast the transaction (need to acess the private key)  
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:

  1. Install the plugin:
npm install node-polyfill-webpack-plugin
  1. Update webpack.config.js:

Add the following code to your webpack.config.js file:

const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
    
module.exports = {
	// Other rules...
	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!