This is the JavaScript client library for the Identity.com Marketplace. It provides an interface for all capabilities on the blockchain, including accessing smart contract data, sending transactions (modifying blockchain data, smart contract state), exchanging CVC tokens and exchanging ETH (aka platform coin).
We use the standard Identity.com terms for roles on the network:
-
IDR: ID requester
-
IDV: ID validator
-
Scope request ID: The UUID for PII request made by IDR to IDV, on the blockchain represented by a bytes32 string (64 hex chars)
-
Credential Item: Single piece of PII, can be claim (atom) or credential (molecule)
-
Credential Item Internal ID: Credential items are identified by external or internal ID. The Internal ID is stored in the blockchain (bytes32 string of 64 hex chars) and is the keccak256 of the external ID.
-
Credential Item External ID: The External ID consists of
Type, Name and Version
, using dash as a separator, e.g.credential-ProofOfIdentity-v1.0
.
For development, fetch the library from github: https://github.com/identity-com/marketplace-tx-js
The library is not yet listed on npmjs.org.
Integrate with your application using:
const MarketplaceTx = require('marketplace-tx');
The library uses ES2017 features therefore it may need to be transpiled before it can be used in browser.
If you are using Babel, you need to use the env preset (or similar).
Add the correct preset to your .babelrc
config.
{
"presets": ["env"]
}
In order to integrate the MarketplaceTx into your React application you might use react-app-rewired library. It allows to tweak the create-react-app webpack config without using 'eject' and without creating a fork of the react-scripts.
First add the correct presets to your .baberc
config.
{
"presets": ["env", "react"]
}
Then add the config-overrides.js
file and tweak the Babel loader as following:
const path = require('path');
const fs = require('fs');
const rewireBabelLoader = require('react-app-rewire-babel-loader');
const { getBabelLoader } = require('react-app-rewired');
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
module.exports = function override(config, env) {
// Make Babel loader read the configuration from .babelrc file.
const babelLoader = getBabelLoader(config.module.rules);
babelLoader.options.babelrc = true;
config = rewireBabelLoader.include(
config,
resolveApp('node_modules/marketplace-tx')
);
return config;
};
MarketplaceTx is currently not compatible with Infura, as it requires access to the txpool
Ethereum RPC API for nonce management.
The library returns a Promise
on any async call. Use async/await
or .then().catch()
according to your environment.
Before using the library, you should:
const MarketplaceTx = require('marketplace-tx');
const marketplaceTx = new MarketplaceTx({web3});
Where web3
is a valid web3 object connected to a node.
MarketplaceTx is configured by the file config/.json, where STAGE is passed in as an environment variable.
Alternatively, it is possible to pass in config to the constructor:
The MarketplaceTx constructor accepts two arguments:
- context - to inject dependencies, like web3, logger, etc.
- config - to provide configuration parameters
const context = { web3 };
const config = { ... };
const marketplaceTx = new MarketplaceTx(context, config);
MarketplaceTx will log automatically to the console. To use your own logger:
const logger = winston();
const marketplaceTx = new MarketplaceTx({web3, logger}, config);
MarketplaceTx requires contract artifacts - JSON files produced by [https://github.com/identity-com/smart-contracts](Marketplace Smart Contracts library) containing contract name, ABI, addresses on specified networks. You can specify the path to to the artifacts directory by passing it to the config upon the initialisation:
const config = { contracts: { dir: 'contracts/' } };
const marketplaceTx = new MarketplaceTx(context, config);
It is also possible to refer the artifacts by providing absolute URL:
const config = { contracts: { url: 'https://s3.amazonaws.com/<bucket>' } };
const marketplaceTx = new MarketplaceTx(context, config);
The library is structured into these sub-modules:
See the API Documentation for more details
marketplaceTx.escrow
for placing tokens into and releasing them from the escrow contract
marketplaceTx.idv-registry
for adding and managing registered IDVs
marketplaceTx.ontology
for managing the ontology of attestation types
marketplaceTx.pricing
for contributing and querying prices
marketplaceTx.token
for transferring tokens and querying balances
marketplaceTx.asserts
containing input validation functions
marketplaceTx.nonce
for managing nonces for externally signed transactions
marketplaceTx.tx
for creating transactions on smart contracts (used by other submodules, discouraged to use directly)
marketplaceTx.sender
for sending transactions to the blockchain (used by other submodules, discouraged to use directly)
marketplaceTx.coin
for transferring platform coin and querying balances
marketplaceTx.transactionDetails
for looking up specific transaction details
marketplaceTx.util
utilities for handling conversion between types, etc.
Transaction object (rawTx) can be created by the marketplaceTx.tx
module.
Nonce management is done by the marketplaceTx.nonce
module. It respects the ethereum node's txpool
and uses a nonce acquire/release mechanism to allow sequential chains of transactions
in case you require strict order of execution.
Note - to use the nonce manager, the node needs access to the ethereum `txpool RPC interface.
Typically with web3
, transactions are signed by a local ethereum client node (with private keys being stored in the node).
For phone and distributed apps, this is not ideal.
We have elected to sign transactions in the library before submitting the transactions to a cluster of nodes.
The library makes no assumption about how this will be done. Functions that need to sign a transaction take a function that must return a promise:
const signingFunction = (address, rawTx) => {....};
Parameter address
is the address that should sign, rawTx
is a JSON transactions (or array of JSON transactions)
This function asynchronously signs the transaction and returns it through the promise (if rawTx
is an array, then the return type is an array of signed transactions). The returned value(s) will be passed to web3.eth.sendRawTransaction
. A typical implementation is:
const EthTx = require('ethereumjs-tx')
// const rawTx = {nonce: <>, gasLimit: <>, to: <>, value: <>, ....}
const signingFunction = (address, rawTx) => {
return new Promise ((resolve, reject) => {
const ethtx = new EthTx(rawTx)
ethtx.sign(Buffer.from(privateKey, 'hex'))
const hex = ethtx.serialize().toString('hex');
resolve(hex);
});
}
marketplaceTx.sender
module is responsible for sending transactions. It accepts an object with tx parameters and uses marketplaceTx.tx
to create transaction. If an optional signTx parameter is passed, tx will be signed externally. send
function returns a promise which resolves to tx hash and rejects in case something went wrong (i.e. signing failed, chainID is wrong, insufficient wei etc.).
marketplaceTx.tx.waitForMine
function can be used to check that a transaction was successfully mined. It expects a promise which resolves to a tx hash (a return value of marketplaceTx.sender.send
could be used) and polls the blockchain each 0.5 sec for 2 minutes until the tx receipt is returned. Then it asserts that the tx status is a success.