Release: 0x.js 2.0.0 Things you need to know

Hey everyone!

We’ve recently published 0x.js 2.0.0, order-utils 2.0.0 and web3-wrapper 3.1.0.

Below are a list of major changes, but be sure to read through the general CHANGELOG for the exhaustive list of changes.

Moved to a new NPM organisation

Our packages have moved to a new NPM organisation. Where previously you would use @0xproject from this release onwards new versions will now be published under @0x.

@0x/web3-wrapper
@0x/order-utils
@0x/subproviders
@0x/types
// etc

EIP712 Sign Typed Data

This had brought eth_signTypedData support to our packages, which means your users can now start to see the data they are signing. Currently this is supported in the latest version of Metamask 4.14.0.

With this release there are a few changes to the way signing behaves.

Firstly, we are introducing MetamaskSubprovider which is exported from 0x.js and the subproviders package. This is a compatibility wrapper for Metamask, so if your users use Metamask, you must use the MetamaskSubprovider.

This removes the previous SignerType where you would need to supply either SignerType.Metamask or SignerType.Default.

So, if you’re used to using web3.currentProvider whenever an order needs to be signed, this will need to be wrapped in MetamaskSubprovider.

Example - Signing with Metamask

// If metamask, wrap in the compatibility wrapper (due to bugs in Metamask)
const provider = new MetamaskSubprovider(web3.currentProvider)
const contractWrappers = new ContractWrappers(provider, { networkId });
....
const signedOrder = await signatureUtils.ecSignOrderAsync(provider, order, makerAddress);

Example - Handling multiple web3 browsers (like Coinbase Wallet)

Only the Metamask injected Web3 needs to be wrapped, other web3 browsers and wallets behave correctly.

// If metamask, wrap in the compatibility wrapper (due to bugs in Metamask)
const provider = (web3.currentProvider as any).isMetaMask
                    ? new MetamaskSubprovider(web3.currentProvider)
                    : web3.currentProvider;
const contractWrappers = new ContractWrappers(provider, { networkId });
....
const signedOrder = await signatureUtils.ecSignOrderAsync(provider, order, makerAddress);

Example - Provider Engine and multiple web3 browsers

const providerEngine = new Web3ProviderEngine();
const signer = (web3.currentProvider as any).isMetaMask
                    ? new MetamaskSubprovider(web3.currentProvider)
                    : new SignerSubprovider(web3.currentProvider);

const rpcProvider = new RPCSubprovider(rpcURI);
// Add the signer first, all account based requests are handled by the signer
providerEngine.addProvider(signer);
// Add the data provider, all logs, data fetching are handled by the rpcProvider
providerEngine.addProvider(rpcProvider);
providerEngine.start();

const provider = providerEngine;
const web3Wrapper = new Web3Wrapper(provider);
const contractWrappers = new ContractWrappers(provider, { networkId });

New ways to Sign

Since there will be intermittent support of eth_signTypedData from the various web3 wallets and browsers, we have provided a helper function ecSignOrderAsync. It will first attempt eth_signTypedData and then fall back to the previous eth_sign of the order hash. This function returns a SignedOrder.

const signedOrder = await signatureUtils.ecSignOrderAsync(provider, order, makerAddress);

If you would like to use eth_signTypedData only, this can be done by using ecSignTypedDataOrderAsync.

// EIP712 signTypedData ONLY
const signedOrder = await signatureUtils.ecSignTypedDataOrderAsync(provider, order, makerAddress);

We have renamed ecSignOrderHashAsync to ecSignHashAsync as this function can be used to sign more than just an order hash (like 0x transactions or any hash data). SignerType has been removed (so remember to wrap Metamask web3 in the compatibility wrapper). This uses eth_sign implementation and behaves as it did in previous versions.

const signature = await signatireUtils.ecSignHashAsync(provider, hash, makerAddress);

Resolving contract addresses

A new package @0x/contract-addresses has been published and contains a lookup for the deployed contracts on a given network. Previous functions for resolving addresses have been removed form contract-wrappers. Though they can be found as properties on the contract, or via a lookup.

// Removed
contractWrappers.etherToken.getContractAddressIfExists()

// Added
import { ContractAddresses, getContractAddressesForNetworkOrThrow } from '@0x/contract-addresses';
const contractAddresses = getContractAddressesForNetworkOrThrow(networkId);
contractAddresses.etherToken
// Some addresses are now properties in contract-wrappers
contractWrappers.exchange.address

Be sure to read through the general CHANGELOG for the exhaustive list of changes.

Any questions bugs or problems, reach out in this Github issue or in our Rocket chat.