@vidy-dev/ethereum-connect
v1.0.22
Published
Easy connection to the backend ethereum node load balancer
Downloads
29
Readme
ethereum-connect
Quick connection to ethereum nodes, including RPC configuration and internal service detection.
connecting
To create a connection with default settings, use:
const ethereumConnect = require('@vidy-dev/ethereum-connect')
const connection = await ethereumConnect()
Connection configuration is inferred from environmental context and, optionally, a config/{environment}.js
config file readable with the config
module. Alternatively, configurations can be overridden by providing an options argument, like:
const ethereumConnect = require('@vidy-dev/ethereum-connect')
const connection = await ethereumConnect({logging: true, rpc: {port: 1337}})
caching
Usage of ethereumConnect
as an object constructor will create a fresh connection every time it is called; it is the user's responsibility to manage the transfer of this connection object between uses.
Alternatively, the module provides connection caching based on input arguments:
const ethereumConnect = require('@vidy-dev/ethereum-connect')
const connection1 = await ethereumConnect.getConnection({logging: true})
...
const connection2 = await ethereumConnect.getConnection({logging: true})
In this example, both connection1
and connection2
refer to the same object. If the input configuration is meaningfully changed, a new connection would be returned instead. This allows different files or function invocations to use the same connection (saving time and remote calls) so long as they share configuration arguments. ethereumConnect.reset()
clears this cache.
config / options
The environment configuration file is checked for these keys:
{
"ethereum": {
"contracts": [],
"logging": false,
"rpc": {
"address": "www.google.com",
"port": 8545
}
}
}
when provided as function arguments, the same format may be used, or the subobject named ethereum
.
ethereum node
ethereumConnect
automates the complexity of discovering the Vidy backend ethereum service domain name, connecting to the load balancer, testing the connection, etc. To this end, functions that create connections (the constructor ethereumConnect()
and caching ethereumConnect.getConnection()
function) will raise exceptions if an active Ethereum node cannot be found.
The ethereum node location can be specified as the rpc.address
and rpc.port
options. If the address is omitted, the normal discovery process will be used; if the port is omitted, 8545 is the default.
ethereum node address discovery
ethereumConnect
is intended for three use cases:
- The service is running on the Google Cloud backend, in a project using our
ethereum-node
load balancing service. - The service is running on a developer's local workstation, with an active port-tunnelling connection to the ethereum middleman (see the
ethereum-tools
repo). - The service is running on an instance with an active ethereum node.
To handle the first case, Google's metadata domain names are queried for the current project and zone; from these, the associated ethereum-node
fully-qualified-domain-name can be determined. This address is sent a simple RPC request (net_version
) to confirm that it is active and accepting RPC connections. If the connection fails, ethereumConnect
reverts to the default region us-central1
and tries again. If both fail, a connection to localhost
is connected.
The first of these three connection attempts to succeed is the one used for the connection. If none succeed, the connection attempt fails and an exception will be thrown.
contracts
Solidity smart contracts, as build output .json
files, can be discovered and loaded by the connection. Contracts loaded by it will be wrapped in the truffle-contract
interface and preconfigured with a default account for transaction signing. See the truffle-contract
implementation or other examples for usage of the contracts themselves, once loaded.
Contract discovery allows users to specify contracts without their fully scoped module paths. For example, if the VidyCoin contract is included in your project (with npm install @vidy-dev/ethereum-vidycoin
) you can reference it directly with await connection.getContract('@vidy-dev/ethereum-vidycoin/build/contracts/VidyCoin.json')
-- but it could also be located with simpler queries, such as await connection.getContract('ethereum-vidycoin/VidyCoin.json')
or even await connection.getContract('VidyCoin')
. It is an error (an exception will be thrown) to request a contract that cannot be found, or a query string that is ambiguous (discovers multiple contracts).
As a security measure, contracts located in your project's node_modules
paths will only be discoverable if they exist in the @vidy-dev
scope (this prevents 3rd party libraries from attacking by providing conflicting contract definitions). However, if you need custom contracts that are not provided by modules in that scope, their directories can be specified with the ethereum.contracts
config option.
connections
Connections created by ethereumConnect
provide these functions:
await connection.getConfig()
: provides the fully populated configuration object, combining environment configuration, construction options, node discovery, and default values.
await connection.getWeb3()
: provides the ethereum web3
instance used for the connection, preconfigured with a default account for transaction signing. Useful for any web3
operation: checking block numbers, sync status, account balances, etc.
await connection.getContractFinder()
: provides the internal helper used to locate Solidity contracts when getContract()
or createContract
is used.
await connection.getContract(contract)
: discovers, loads, and configures a truffle-contract
instance for the specified contract
, which is a string or file path uniquely identifying a discoverable contract .json
file. To save time, the output is cached; multiple calls with the same input query will retrieve exactly the same contract instance (you should not rely on this caching for any reason other than efficiency; e.g. you should not build code on the assumption that the same instance is provided every time).
await connection.createContract(contract)
: identical to getContract
, except no caching is done; a fresh truffle-contract
instance is provided with each call.
example
Below is a short usage example, taken from the KYC reference implementation. The specific functions supported by the contract itself are contract-dependent.
'use strict';
const web3 = require('../lib/web3');
const ethereumConnect = require('@vidy-dev/ethereum-connect')
exports.isOnWhitelist = async function(req, res) {
try {
// get a connection (cached; only the first call is expensive)
const connection = await ethereumConnect.getConnection();
// get a contract interface for the public whitelist (cached)
const PublicICOWhitelist = await connection.getContract('PublicIcoWhitelist');
// get an interface for the instance deployed on this ethereum network
const publicIcoWhitelist = await PublicICOWhitelist.deployed();
// query whether the given address is on the whitelist
const result = await publicIcoWhitelist.whitelist.call(req.params.address);
if (!result) {
res.status(404).send({address: `address ${req.params.address} is not on the whitelist`, success: false});
} else {
res.json({success:result});
}
} catch (err) {
console.log(err);
res.status(500).send({success:false, message: err.message})
}
};
exports.addToWhitelist = async function(req, res) {
try {
// get a connection (cached; only the first call is expensive)
const connection = await ethereumConnect.getConnection();
// get a contract interface for the public whitelist (cached)
const PublicICOWhitelist = await connection.getContract('PublicIcoWhitelist');
// get an interface for the instance deployed on this ethereum network
const publicIcoWhitelist = await PublicICOWhitelist.deployed();
// make the change on the Ethereum blockchain through the contract interface
await publicIcoWhitelist.addAddressToWhitelist(req.params.address);
res.json({"success":true});
} catch (err) {
console.log(err);
res.status(500).send({success:false, message: err.message})
}
};