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

ethanol

v0.3.0

Published

Humane wrappers around web3

Downloads

2

Readme

Ethyl

Humane JS wrappers around web3 and solc.

Defining an RPC endpoint

In most cases the work starts with obtaining for a Blockchain object:

const { Blockchain } = require("ethyl");
const bc = Blockchain.at("http://localhost:8545");

The argument to the at function is the URL of an RPC node representing the blockchain. Besides the http and https schemas the ipc schema can also be used:

const { Blockchain } = require("ethyl");
const bc = Blockchain.at("ipc:///home/john/geth/geth.ipc");

The blockchain object provides several query functions about the blockchain:

const latestBlockNumber = await bc.blockNumber();
const firstBlock = await bc.block(1);
const bobsBalance = await bc.balanceOf(
	"0x5e94baef74b60e98116b971e9240d914f4059e27"
);

User accounts

User accounts are obtained with the user function of the blockchain object:

const { Blockchain } = require("ethyl");
const bc = Blockchain.at("http://localhost:8545");
const alice = await bc.user();

If the blockchain is connected via IPC, then the local client's user will be assumed. If the interface is a remote RPC (JSON over HTTP), then a full user will be created on the fly.

The local user is typically an unlocked account that can send signed transactions. But a remote user by default can't sign transactions. In order to enable signing for a remote user a BIP44 mnemonic has to be provided as an option:

const { Blockchain } = require("ethyl");
const bc = Blockchain.at("http://localhost:8545");

const bob = await bc.user({
	mnemonic: "eeny meeny miny moe catch a tiger by the toe"
});

The user objects can report their address and balance, and can be used to transfer Ether (in Wei units):

const { Blockchain } = require("ethyl");
const bc = Blockchain.at("http://localhost:8545");

const alice = await bc.user({
	mnemonic: "eeny meeny miny moe catch a tiger by the toe"
});
const bob = await bc.user({ address: "0x..." });

const address = alice.address();
const balance = await alice.balance();

// Give 10 Wei to Bob
const transaction = await alice.give(bob, 10);

Transactions

Transaction objects are returned for contract calls and plain ether transfers:

const transaction1 = await alice.give(bob, 10);
const transaction2 = await alice.call(contract, "funcName");

The transaction's success function returns a promise which resolves when the transaction is mined successfully or rejects when the transaction is rejected:

const transaction = await alice.call(contract, "funcName");
try {
	await transaction.success();
} catch (error) {
	console.log("transaction failed:", error);
}

An often used shorthand for making a transaction and waiting for its completion is:

await alice.give(bob, 1).then(t => t.success());

This additional step has to be explicit because in an application one might need not to wait for an actual result for various reasons.

Contract call transactions, when mined successfully, can also return their event logs:

const transaction = await alice.call(contract, "funcName");
const logs = await transaction.logs();

Obtaining logs assumes waiting for the transaction to be mined, so it's not necessary to await for transaction.success in this case.

A transaction can also be obtained from a contract using a known hash value:

const transaction = await contract.transaction("0x1234abcd...");

The contract is necessary because it provides context (like an ABI definition) to the transaction so that the logs function will work. The transaction function will also verify the the transaction exists and belongs to the same contract.

Contracts

A contract image is a combination of abi and bin properties which have the corresponding outputs of a Solidity compiler. It will usually be obtained from files:

const abi = fs.readFileSync("hello-world.abi");
const bin = fs.readFileSync("hello-world.bin");
const image = { abi, bin };

Given an existing contract image, it can be deployed from a user's account:

const transaction = await user.deploy(image, [arg1, arg2]);
const contract = await transaction.contract();

The returned promise will turn into a DeployedContract instance which can be passed to read and call functions of users to statically read contract's variables, make dry function runs or make actual calls:

const val = await alice.read(contract, "variableName");
const result = await alice.read(contract, "functionName", ["arg1", "arg2"]);

Building contracts

A contract image can also be obtained by using the Compiler object:

const { Compiler } = require("ethyl");
const com = new Compiler();
const image = await com.compile("hello-world.sol");

The Compiler object will call the host system's solc compiler through the command line.

The constructor takes a map of compiler options which exactly correspond to command line options of the solc compiler. For example, to get binaries compatible with older versions of the blockchain:

const com = new Compiler({ "evm-version": "spuriousDragon" });
const image = await com.compile("hello-world.sol");

Running the tests

Execute yarn test. The tests require both geth and solc to be installed.