Created mdx folder for new docs. Moved indexing into the new folder.

This commit is contained in:
Piotr Janosz
2019-07-28 18:18:14 +02:00
committed by fabioberger
parent b666ca0271
commit 3133dde3a3
16 changed files with 1277 additions and 136 deletions

View File

@@ -1,52 +0,0 @@
Welcome to the 0x smart contracts documentation! This documentation is intended for dApp developers who want to integrate 0x exchange functionality directly into their own smart contracts.
## Exchange
Some text about the exchange
### executeTransaction
```
/// @param salt Arbitrary number to ensure uniqueness of transaction hash.
/// @param signerAddress Address of transaction signer.
/// @param data AbiV2 encoded calldata.
/// @param signature Proof of signer transaction by signer.
function executeTransaction(
uint256 salt,
address signerAddress,
bytes calldata data,
bytes calldata signature
)
```
<CodeTabs tabs={['Typescript', 'Python', 'Solidity']}>
```typescript
import { provider, networkId, signerAddress, salt, signature, senderAddress } from '@0x/browser-examples';
const exchange = new ExchangeContract(provider, networkId);
const txnReceipt = await exchange.executeTransaction.awaitTransactionSuccessAsync(
salt,
signerAddress,
data,
signature,
{ from: senderAddress },
);
```
```python
import { TruffleArtifactAdapter } from '@0x/sol-coverage';
const projectRoot = '.';
const solcVersion = '0.5.0';
const artifactAdapter = new TruffleArtifactAdapter(projectRoot, solcVersion);
```
```solidity
import { TruffleArtifactAdapter } from '@0x/sol-coverage';
const projectRoot = '.';
const solcVersion = '0.5.0';
const artifactAdapter = new TruffleArtifactAdapter(projectRoot, solcVersion);
```
</CodeTabs>

View File

@@ -1,38 +0,0 @@
## Introduction
0x is a protocol that facilitates the peer-to-peer exchange of Ethereum-based assets. The protocol serves as an open standard and common building block for any developer needing exchange functionality. Developers can integrate with 0x at the smart contract level, or on an application level, taking advantage of its audited, secure smart contracts, the many developer tools built for the 0x ecosystem and its shared liquidity pool.
## A conceptual overview of 0x
This section will give you a conceptual overview of 0x protocol. Future sections will give you the necessary Ethereum background to then dive into the technical details of the current implementation of 0x.
### The 0x order message format
At the core of 0x is a standard order message format. The order message format describes one partys commmitment to trade assets at very specific terms with another party. By defining a standard message format for orders, 0x allows anyone who adheres to the standard to use 0x for settlement, and build their application using the many open-source tools designed to work with 0x orders.
A 0x order has the following fields:
| Parameter | Description |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| makerAddress | Address that created the order. The maker is one of the two parties that will be involved in the trade if the order gets filled. |
| takerAddress | Address that is allowed to fill the order. If set to 0, anyone is allowed to fill the order. This field allows makers to decide who can fill an order, rendering it useless to eavesdroppers or outside parties. |
| feeRecipientAddress | The address that will receive the fees stipulated by the order. This is typically used to incentivize off-chain order relay. |
| makerAssetData | `makerAssetData` makerAssetData contains all the identifying information about the asset the order maker is trying to sell. Since 0x supports arbitrary token standards, this value has a very specific encoding. |
The 0x order message format is rigid enough to enforce the necessary conditions the order maker requires to enter into a trade, and yet flexible enough to represent many different kinds of trades. Currently, 0x supports trading:
- Fungible tokens (Those conforming to the ERC20 standard)
- Non-fungible tokens (Those conforming to the ERC721 standard)
- Bundles of assets (Trade one-to-many, many-to-one or many-to-many funglible & non-fungible assets with a single order)
And we are constantly adding support for new token standards and different ways to trade them due to the modular nature of 0xs design. If you are curious about proposed additions to 0x protocol, browse through the ZEIPs (0x improvement proposals).
### Cryptography used by 0x protocol
Once an order maker has decided on all the details of the trade they wish to make, the last step is for them to cryptographically commit to the trade. 0x uses two fundamental building blocks of cryptography to make this happen. This section will introduce these building blocks and how 0x uses them.
#### Cryptographic hash function
A cryptographic hash function is a function that maps an input of arbitrary size to an output of fixed size (a hash). It is a one-way function meaning that it is infeasible to invert. The input data is typically called the message and the output the message digest. 0x uses a hash function to create an order digest (order hash) that uniquely identifies all the order fields chosen by the maker. Changing any of the fields of the order, will cause the order hash to change. Thanks to this property of hash functions, the order hash can be used as the unique identifier for an order. Another nice aspect of using a hash function is that all order hashes will have the same fixed length, regardless of the complexity or size of the order fields. We now have a unique, fixed-length identifier we can generate for every single permutation of a 0x order. The next step is to allow a maker to cryptographically commit to this representation of their 0x order.

View File

@@ -0,0 +1,18 @@
const algoliasearch = require('algoliasearch');
const algoliaAppId = 'T7V7WKELRY';
const algoliaAdminKey = 'ccc472dee2aa991ca4bc935975e76b5d';
const adminClient = algoliasearch(algoliaAppId, algoliaAdminKey);
const sharedSettings = {
distinct: true,
attributeForDistinct: 'id',
attributesToSnippet: ['description', 'textContent:20'], // attribute:nbWords (number of words to show in a snippet)
searchableAttributes: ['title', 'textContent', 'description'],
snippetEllipsisText: '…',
};
module.exports = {
adminClient,
sharedSettings,
};

View File

@@ -0,0 +1,13 @@
const { adminClient, sharedSettings } = require('./constants');
const { indexFiles, setIndexSettings } = require('./helpers');
const index = adminClient.initIndex('0x_guides_test');
const dirName = 'guides';
const settings = {
...sharedSettings,
attributesForFaceting: ['topics', 'difficulty'],
};
setIndexSettings(index, settings);
indexFiles(index, dirName);

View File

@@ -0,0 +1,89 @@
export const meta = {
id: 3523532,
title: 'Build a relayer',
description:
'A relayer is any party or entity which hosts an off-chain orderbook.',
tags: ['Relayer', 'Trader', 'Protocol Developer'],
topics: ['Coordinator Model', 'Mesh'],
difficulty: 'Advanced'
};
They provide a way for users to add, remove and update this orderbook through an API, GUI or both. In doing so, relayers help traders discover counter-parties and ferry cryptographically signed orders between them. Once two parties agree on the terms of an order, the order is settled directly on the Ethereum blockchain via the 0x protocol smart contracts.
### Advantages of decentralized exchange
There are many advantages to a decentralized exchange over centralized exchange. One of the largest problems with centralized Exchanges is that they must hold and secure the funds of all the traders on their platform. This causes there to be a single point of failure that if hacked or mismanaged, means that all these traders could lose their funds. Hundreds of millions have already been stolen in this way. With a decentralized exchange, traders do not need to deposit funds with a centralized entity, but instead can trade directly from their individual wallets (including hardware wallets!). This means the user is in control of their funds at all times, eliminating this single point of failure from the equation.
### 0x protocol overview
In 0x protocol, orders are transported off-chain over any arbitrary medium, massively reducing gas costs and reducing blockchain bloat. Relayers help broadcast orders and can choose to collect a fee each time they facilitate a transaction. Anyone can build a relayer.
The simplest example of a relayer is a website allowing users to create, discover and fill orders. The relayer must build out a UI and host a backend database to provide this functionality.
<div align="center">
<img
src="https://s3.eu-west-2.amazonaws.com/0x-wiki-images/relayer_diagram.png"
style="padding-bottom: 20px; padding-top: 20px; max-width: 342px;"
width="80%"
/>
</div>
To simplify the process of interacting with the 0x protocol, we have written a Javascript/Typescript library called [0x.js](http://0x.org/docs/0x.js). This library helps relayers interact with the 0x protocol smart contracts through a higher-level, easier to use interface. It also provides many useful utilities for hashing, signing, validating, and serializing 0x orders. Additionally, we have built the [0x-launch-kit](https://github.com/0xproject/0x-launch-kit), an open-source, free-to-use API-only 0x relayer template that you can use as a starting point for your own project.
Before getting started with [0x.js](http://0x.org/docs/0x.js), [0x-launch-kit](https://github.com/0xproject/0x-launch-kit) or the 0x protocol, it is helpful to introduce a few concepts. There are two parties involved in every trade, a maker and a taker. The maker creates an order for an amount of TokenA in exchange for an amount of TokenB. The maker then submits these to a relayer. Takers discover orders via a relayer and fill them by sending them directly to the 0x protocol smart contracts. The 0x protocol smart contracts performs an atomic swap, exchanging the maker and taker tokens.
### Order
Below is an interface description of the 0x protocol order format:
```typescript
interface Order {
senderAddress: string;
// Ethereum address of the Maker
makerAddress: string;
// Ethereum address of the Taker. If no address specified, anyone can fill the order.
takerAddress: string;
// How many ZRX the Maker will pay as a fee to the relayer
makerFee: BigNumber;
// How many ZRX the Taker will pay as a fee to the relayer
takerFee: BigNumber;
// The amount of an asset the Maker is offering to exchange
makerAssetAmount: BigNumber;
// The amount of an asset the Maker is willing to accept in return
takerAssetAmount: BigNumber;
// The identifying data about the asset the Maker is offering
makerAssetData: string;
// The identifying data about the asset the Maker is requesting in return
takerAssetData: string;
// A salt to guarantee OrderHash uniqueness. Usually a milisecond timestamp of when order was made
salt: BigNumber;
// The address of the 0x protocol exchange smart contract
exchangeAddress: string;
// The address (user or smart contract) that will receive the fees
feeRecipientAddress: string;
// When the order will expire (unix timestamp in seconds)
expirationTimeSeconds: BigNumber;
}
```
It is a relayer's job to collect cryptographically signed versions of these orders into an off-chain database. This collection of orders is what we refer to as an orderbook. A relayer displays their orderbook to potential takers. The incentive here is for a relayer to collect fees from the orders they host. By specifying themselves as the fee recipient, relayers can earn fees in ZRX tokens.
Check out this tutorial on how to [Create, Validate, and Fill Orders](https://0x.org/wiki#Create,-Validate,-Fill-Order). If you want to jump straight into a working relayer codebase, check out [0x-launch-kit](https://github.com/0xProject/0x-launch-kit/).
If you want to take a deep-dive into the 0x protocol, take a look at the [0x Protocol Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
### Relayer strategies
The 0x protocol leaves room for some flexibility on how exactly relayers operate. There are a few different strategies relayers have employed so far, each with their respective advantages and drawbacks. You can read more about the different strategies in the [Relayer Strategies](https://0x.org/wiki#Matching) section of the wiki to discover the strategy that suits your needs the best.
### Shared liquidity
Because all relayers represent orders using the 0x protocol order format, an order created on one relayer (using the open-orderbook strategy) can be filled by users on another relayer. What this means is that rather than each relayer having a siloed liquidity pool, they can share orders to create a shared liquidity pool. New relayers can bootstrap their liquidity off of existing relayers, immediately becoming an interesting place to trade. It is important to note that fees always go to the relayer where the order was first submitted. We have defined a [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) to help relayers share liquidity and to simplify the integration process for market makers, providing a unified interface for them to build against.
### Pruning your orderbooks
Over time, orders may expire, partially filled, cancelled or no longer fillable. It is best to keep your orderbook free of expired or unfillable orders. Iterating over the orderbook periodically and checking each order's validity is a simple way to accomplish this. For a more advanced and efficient approach, you could use an [OrderWatcher](https://0x.org/wiki#0x-OrderWatcher). [0x-launch-kit](https://github.com/0xProject/0x-launch-kit/) is built using OrderWatcher out-of-the-box.
### Next steps
Now that you have a high level idea of what a relayer does, it's time to get started learning how they work. Check out [0x-launch-kit](https://github.com/0xProject/0x-launch-kit/) for a fully-working relayer example, or dive into the [Create, Validate, and Fill Orders](https://0x.org/wiki#Create,-Validate,-Fill-Order) tutorial to master the basics of dealing with 0x orders. You may also want to decide on a [Relayer Strategy](https://0x.org/wiki#Open-Orderbook). We recommend the open orderbook strategy. If you're looking for more orders to add to your orderbook, take a look at the [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) and [0x Connect](https://0x.org/docs/connect). There are several relayers that have already implemented it and are broadcasting orders. Remember to keep your orderbook free of stale orders by using an [OrderWatcher](https://0x.org/wiki#0x-OrderWatcher).

View File

@@ -0,0 +1,68 @@
export const meta = {
id: '513',
title: 'Develop on Ethereum',
description:
'Welcome to the exciting world of building applications on the Ethereum Blockchain',
tags: ['Relayer', 'Trader'],
topics: ['Mesh', 'Protocol Developer'],
difficulty: 'Beginner'
};
# Ethereum Intro
Welcome to the exciting world of building applications on the [Ethereum Blockchain](https://www.ethereum.org/). With Ethereum you can deploy applications or "Smart Contracts" that perform operations and persist state using a decentralized network of computers. Ethereum is often described as a platform for programming digital money. A transaction executes and is confirmed and verified by hundreds of different machines (nodes) distributed around the world. If you want to understand the how blockchains fundamentally work checkout [this visual explanation](https://anders.com/blockchain/). If you'd like to read more about Ethereum specifically, visit this [beginners guide to Ethereum](https://blog.coinbase.com/a-beginners-guide-to-ethereum-46dd486ceecf).
Now that you have a basic understanding of what Ethereum is and does, let's talk about tokens. Fungible tokens (commonly referred to as [ERC20](https://github.com/ethereum/EIPs/issues/20)) are simple smart contracts that track the transfer of a unit of account. You can request this smart contract to [transfer](https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/ERC20/BasicToken.sol#L31) tokens from your account to anyone else's. Others may also transfer tokens from their account to you. All of these requests are transactions on the Ethereum blockchain and cost a small transaction fee. For more information check out the [beginner's guide to Ethereum Tokens](https://blog.coinbase.com/a-beginners-guide-to-ethereum-tokens-fbd5611fe30b).
### 0x protocol
The 0x Protocol extends on this functionality by performing multiple balance transfers in a single atomic operation. If Alice wants to exchange 100 units of TokenA for 200 units of TokenB with Bob, Alice would want to make sure Bob was going to keep his end of the deal. Rather than Alice sending her amount of TokenA to Bob and hoping Bob will send TokenB to Alice sometime in the future, the 0x Protocol performs this exchange in a guaranteed atomic operation. So Alice and Bob will get exactly what they expect. The 0x Protocol is designed to minimize the amount of transactions (and fees) required for Alice and Bob to successfully exchange tokens. 0x protocol uses a process involving off-chain orders with on-chain settlement. You can find more information on the 0x Protocol by reading our [whitepaper](https://0x.org/pdfs/0x_white_paper.pdf) or the [beginners guide to 0x](https://blog.0xproject.com/a-beginners-guide-to-0x-81d30298a5e0).
### Interacting with the Ethereum blockchain
As web browsers do not natively support interacting with the Ethereum Blockchain, a browser extension called [Metamask](https://metamask.io/) is one way to fill that gap. Metamask will handle the users private keys and allow them to submit transactions to the network via an Ethereum node. Metamask communicates with the sites a user visits by injecting a Javascript object through which the site can communicate with the wallet and blockchain. For mobile users there are applications like [Coinbase Wallet](https://wallet.coinbase.com/) and [Cipher Browser](https://www.cipherbrowser.com/) that do the same thing on mobile.
In order to interact with dApps (distributed applications) a user must have Ether in a wallet they control. The user cannot interact with dApps from an exchange such as Coinbase. They must control the private keys associated with their Ethereum address.
### Development
<div align="center">
<a
href="https://codesandbox.io/s/github/0xproject/0x-codesandbox"
target="_blank"
rel="Sandbox">
<img
src="https://s3.eu-west-2.amazonaws.com/0x-wiki-images/sandbox.png"
style="padding-bottom: 20px; padding-top: 20px; max-width: 761px;"
width="80%"
/>
</a>
</div>
#### Test networks
Development and testing are aided by running in your own local test Ethereum node. This allows you to quickly deploy and interact with contracts without spending real ETH. [Ganache](https://github.com/trufflesuite/ganache) simulates an Ethereum node locally and provides the same JSON RPC interface as a real node. Since there can still be small differences between it and a real Ethereum node (e.g [Geth](https://github.com/ethereum/go-ethereum) or [Parity](https://github.com/paritytech/parity-ethereum)) so we recommend you also test your application on a live testnet (i.e Kovan, Rinkeby, or Ropsten) before deploying on to the main Ethereum network.
Rather than spinning up your own Ethereum node infrastructure to connect to the network, many developers use [INFURA](https://infura.io/). They provide public, scalable Ethereum nodes as a service. Since Ethereum nodes were not designed to handle thousands of requests per second, Infura has built out infrastructure around the nodes to make them more performant.
It can be difficult to get a sufficient amount of test Ether to deploy your contracts on test networks and begin testing them. Because of this, we have created a faucet which can dispense small amounts of Ether to your account. Navigate over to the [0x Portal](https://0x.org/portal/balances) with Metamask installed and click "Request" to receive some free test Ether (make sure you're connected to a testnet)!
<div align="center">
<a href="https://0x.org/portal/balances">
<img
src="https://s3.eu-west-2.amazonaws.com/0x-wiki-images/network_screenshot.png"
style="padding-bottom: 20px; padding-top: 20px; max-width: 761px;"
width="80%"
/>
</a>
</div>
### Wrapped ETH
By now you are likely familiar with the ERC20 standard, Ether (aka ETH) and the plethora of ERC20 tokens out there. Unfortunately, ETH is not an ERC20 token and because of this cannot interact directly with the 0x protocol. What we can do however, is deposit ETH into an ERC20-compliant smart contract which credits your account with the same amount of WETH (wrapped Ether) tokens as the amount of ETH you deposited. These tokens are also redeemable 1-to-1 for Ether. In this ERC20-compliant form, Ether can be traded for other tokens using 0x protocol. This work-around for Ether is becoming increasingly common in the entire ecosystem. More information on WETH and how it works can be found [here](https://weth.io/).
Now that you have a high-level overview of Ethereum Blockchain development, it is time to check out our other tutorials and examples. Be sure to try out our [Sandbox](https://codesandbox.io/s/1qmjyp7p5j) which provides a development environment ready for you to experiment with.
### Next steps
Now that you've got a basic understanding of what is involved when developing on Ethereum, you're now ready to go onto the next step of [Building a Relayer](#Build-A-Relayer). If you'd rather jump right in, you can skip straight to learning how to [Create, Validate and Fill Orders](https://0x.org/wiki#Create,-Validate,-Fill-Order) on 0x.

View File

@@ -0,0 +1,339 @@
export const meta = {
id: '242325',
title: 'Use networked liquidity',
description:
'In this tutorial, we will show you how you can use the @0x/connect package in conjunction with 0x.js in order to',
tags: ['Protocol Developer'],
topics: ['Mesh'],
difficulty: 'Intermediate'
};
In this tutorial, we will show you how you can use the [@0x/connect](https://github.com/0xProject/0x.js/tree/development/packages/connect) package in conjunction with [0x.js](https://github.com/0xProject/0x.js/tree/development/packages/0x.js) in order to:
- ask a relayer for fee information
- submit signed orders to a relayer with appropriate fees
- ask a relayer for a ZRX/WETH orderbook
- find the best orders in the orderbook
- fill orders from the orderbook using `0x.js`
You can find all the `@0x/connect` documentation [here](https://0x.org/docs/connect).
You can find a list of relayers that comply with the Standard Relayer API [here](https://github.com/0xProject/0x-relayer-registry)
### Setup
Since 0x.js helps you build apps that interface with Ethereum, you will need to use it in conjunction with an Ethereum node. For development, we recommend using [Ganache CLI](https://github.com/trufflesuite/ganache-cli). Since there is some setup required to getting started with Ganache and the 0x smart contracts, we are going to use a [0x starter project](https://github.com/0xProject/0x-starter-project) which handles a lot of this for us.
Clone the repo:
```
git clone https://@github.com/0xProject/0x-starter-project.git
```
Install all the dependencies (we use Yarn: `brew install yarn --without-node`):
```
yarn install
```
Pull the latest Ganache 0x snapshot with all the 0x contracts pre-deployed and an account with ZRX balance:
```
yarn download_snapshot
```
In a separate terminal, navigate to the project directory and start TestRPC:
```
yarn ganache-cli
```
In another terminal, navigate to the project directory and start a local http server that conforms to a portion of the standard relayer API, listening to port 3000:
```
yarn fake_sra_server
```
You can now run the code we are going to walk you through in the rest of this tutorial:
```
yarn scenario:fill_order_sra
```
### Importing packages
The first step to interacting with `@0x/connect` is to import the following relevant packages:
```javascript
import {
assetDataUtils,
BigNumber,
ContractWrappers,
generatePseudoRandomSalt,
Order,
orderHashUtils,
signatureUtils
} from '0x.js';
import { HttpClient, OrderbookRequest, OrderConfigRequest } from '@0x/connect';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { getContractAddressesForNetworkOrThrow } from '@0x/contract-addresses';
```
**0x.js** is a package that pulls in a number of underlying 0x packages and exposes their respective functionality. You can choose to pull these packages directly without using 0x.js. These packages allow you to interact with the 0x smart contracts (contract wrappers) and create, sign and validate orders (order utils).
**BigNumber** is a JavaScript library for arbitrary-precision decimal and non-decimal arithmetic.
**HttpClient** is a Standard Relayer API client implementation that allows you to easily query any Standard Relayer API endpoint.
**Web3Wrapper** is a package for interacting with an Ethereum node, retrieving account information. This is an optional package and you can choose to use alternatives like Web3.js or Ethers.js.
**contract-addresses** is a package where we have our deployed contract addresses for the various networks. This also includes an address for a deployed Wrapped Ether contract.
### Instantiating a Provider and ContractWrappers
First, we need to instantiate an instance of ContractWrappers and a Provider. In our case, since we are using our local node (ganache), we will use **http://localhost:8545**. You can read about what providers are [here](#Web3-Provider-Explained).
```typescript
import { RPCSubprovider, Web3ProviderEngine } from '0x.js';
export const providerEngine = new Web3ProviderEngine();
providerEngine.addProvider(new RPCSubprovider('http://localhost:8545'));
providerEngine.start();
// Instantiate ContractWrappers with the provider
const contractWrappers = new ContractWrappers(providerEngine, {
networkId: NETWORK_CONFIGS.networkId
});
```
### Retreiving Accounts from the Provider
We will use Web3Wrapper to retrieve accounts from the provider. The first account will the the maker, and the second account will be the taker for the purposes of this tutorial.
```typescript
const web3Wrapper = new Web3Wrapper(providerEngine);
const [maker, taker] = await web3Wrapper.getAvailableAddressesAsync();
```
### Declaring decimals and addresses
Since we are dealing with a few contracts, we will specify them now to reduce the syntax load. Fortunately for us, `0x.js` library comes with a couple of contract addresses that can be useful to have at hand. One thing that is important to remember is that there are no decimals in the Ethereum virtual machine (EVM), which means you always need to keep track of how many "decimals" each token possesses. Since we will sell some ZRX for some ETH and since they both have 18 decimals, we can use a shared constant.
```javascript
// Token Addresses
const contractAddresses = getContractAddressesForNetworkOrThrow(
NETWORK_CONFIGS.networkId
);
const zrxTokenAddress = contractAddresses.zrxToken;
const etherTokenAddress = contractAddresses.etherToken;
```
0x Protocol uses the ABI encoding scheme for asset data. For example, the ERC20 Token address which is being traded on 0x needs to be encoded. Encoding the address informs the 0x smart contracts on which type of asset is being traded (e.g ERC20 or ERC721) and has optional parameters for different token types (e.g ERC721 token id). In this tutorial we are trading 5 ZRX (ERC20) for 0.1 WETH (ERC20).
```typescript
const makerAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress);
const takerAssetData = assetDataUtils.encodeERC20AssetData(etherTokenAddress);
// the amount the maker is selling of maker asset
const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(
new BigNumber(5),
DECIMALS
);
// the amount the maker wants of taker asset
const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(
new BigNumber(0.1),
DECIMALS
);
```
### Approvals and WETH Balance
To trade on 0x, the participants (maker and taker) require a small amount of initial set up. They need to approve the 0x smart contracts to move funds on their behalf. In order to give 0x protocol smart contract access to funds, we need to set _allowances_ (you can read about allowances [here](https://tokenallowance.io/)). In this tutorial the taker is using WETH (or Wrapper ETH), as ETH is not an ERC20 token it must first be converted into WETH to be used on 0x. Concretely, "converting" ETH to WETH means that we will deposit some ETH in a smart contract acting as a ERC20 wrapper. In exchange of depositing ETH, we will get some ERC20 compliant tokens called WETH at a 1:1 conversion rate. For example, depositing 10 ETH will give us back 10 WETH and we can revert the process at any time. The ContractWrappers package has helpers for general ERC20 tokens as well as the WETH token.
```typescript
// Allow the 0x ERC20 Proxy to move ZRX on behalf of makerAccount
const makerZRXApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
zrxTokenAddress,
maker
);
await web3Wrapper.awaitTransactionSuccessAsync(makerZRXApprovalTxHash);
// Allow the 0x ERC20 Proxy to move WETH on behalf of takerAccount
const takerWETHApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
etherTokenAddress,
taker
);
await web3Wrapper.awaitTransactionSuccessAsync(takerWETHApprovalTxHash);
// Convert ETH into WETH for taker by depositing ETH into the WETH contract
const takerWETHDepositTxHash = await contractWrappers.etherToken.depositAsync(
etherTokenAddress,
takerAssetAmount,
taker
);
await web3Wrapper.awaitTransactionSuccessAsync(takerWETHDepositTxHash);
```
At this point, it is worth mentioning why we need to await all those transactions. Calling an 0x.js function returns immediately after submitting a transaction with a transaction hash, so the user interface (UI) might show some useful information to the user before the transaction is mined (it sometimes takes long time). In our use-case we just want it to be confirmed, which happens immediately on ganache. It is nevertheless a good habit to interact with the blockchain with these async/await calls.
## Creating an HttpClient
Next, we create an `HttpClient` instance with a url pointing to a local standard relayer api http server running at **http://localhost:3000**. The `HttpClient` is our programmatic gateway to any relayer that conforms to the standard relayer api http standard.
```javascript
// Instantiate relayer client pointing to a local server on port 3000
const relayerApiUrl = 'http://localhost:3000/v2';
const relayerClient = new HttpClient(relayerApiUrl);
```
### Getting configuration information
Before creating an order to submit to a relayer, it is necessary to understand the requirements a relayer may have to host the order on their orderbook. This is what the `/order_config` endpoint is for.
Create a partial order (or `OrderConfigRequest`) and query the API using `getOrderConfigAsync`:
```javascript
// Generate and expiration time and find the exchange smart contract address
const randomExpiration = getRandomFutureDateInSeconds();
const exchangeAddress = contractAddresses.exchange;
// Ask the relayer about the parameters they require for the order
const orderConfigRequest: OrderConfigRequest = {
exchangeAddress,
makerAddress: maker,
takerAddress: NULL_ADDRESS,
expirationTimeSeconds: randomExpiration,
makerAssetAmount,
takerAssetAmount,
makerAssetData,
takerAssetData
};
const orderConfig = await httpClient.getOrderConfigAsync(orderConfigRequest);
```
Here are the fields in an order config request:
- **makerAddress** : Ethereum address of our **Maker**.
- **takerAddress** : Ethereum address of our **Taker**.
- **makerAssetData**: The token address the **Maker** is offering.
- **takerAssetData**: The token address the **Maker** is requesting from the **Taker**.
- **exchangeAddress** : The Exchange address.
- **makerAssetAmount**: The amount of token the **Maker** is offering.
- **takerAssetAmount**: The amount of token the **Maker** is requesting from the **Taker**.
- **expirationTimeSeconds**: When will the order expire (in unix time).
Here are the fields that are provided in the order config response:
- **senderAddress** : Ethereum address of a required **Sender** (none for now).
- **feeRecipientAddress** : Ethereum address of our **Relayer** (none for now).
- **makerFee**: How many ZRX the **Maker** will pay as a fee to the **Relayer**.
- **takerFee** : How many ZRX the **Taker** will pay as a fee to the **Relayer**.
You can see that together they form a full Order object, except for the salt.
### Creating an order
Now that we have the configuration information, we can create a full order.
```javascript
// Create the order
const order: Order = {
salt: generatePseudoRandomSalt(),
...orderConfigRequest,
...orderConfig
};
```
### Signing the order
Now that we created an order as a **Maker**, we need to prove that we actually own the address specified as `makerAddress`. After all, we could always try pretending to be someone else just to annoy an exchange and other traders! To do so, we will sign the orders with the corresponding private key and append the signature to our order.
```javascript
// Generate the order hash and sign it
const orderHashHex = orderHashUtils.getOrderHashHex(order);
const signature = await signatureUtils.ecSignHashAsync(
providerEngine,
orderHashHex,
maker
);
const signedOrder = { ...order, signature };
```
With this, anyone can verify that the signature is authentic and this will prevent any change to the order by a third party. If the order is changed by even a single bit, then the hash of the order will be different and therefore invalid when compared to the signed hash.
Now let's actually verify whether the order we created is valid
```javascript
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder);
```
If something was wrong with our order, this function would throw an informative error. If it passes, then the order is currently fillable. A relayer should constantly be [pruning their orderbook](#0x-OrderWatcher) of invalid orders using this method.
### Submitting the order to the relayer
We can finally submit our signed order to the relayer for them to host on their orderbook.
```javascript
// Submit the order to the SRA Endpoint
await httpClient.submitOrderAsync(signedOrder, { networkId: NETWORK_CONFIGS.networkId };
```
### Requesting an orderbook
If in an application we need exchange functionality between two assets, we can find a suitable order for our needs using the `getOrderbookAsync()` method of `HttpClient`. In this example, we use the addresses of the ZRX and WETH tokens we retrieved earlier and use them to generate an `OrderbookRequest` to send to the relayerClient. In response, we get an `OrderbookResponse` containing orders that correspond with the provided `quoteAssetData` and `baseAssetData` (learn more about the quote/base token terminology [here](https://en.wikipedia.org/wiki/Currency_pair)).
```javascript
// Taker queries the Orderbook from the Relayer
const orderbookRequest: OrderbookRequest = {
baseAssetData: makerAssetData,
quoteAssetData: takerAssetData
};
const response = await httpClient.getOrderbookAsync(orderbookRequest, {
networkId: NETWORK_CONFIGS.networkId
});
if (response.asks.total === 0) {
throw new Error('No orders found on the SRA Endpoint');
}
```
### Filling an order
`OrderbookResponse` contains two fields, `bids` and `asks`. `Bids` is a [`PaginatedCollection`](https://0x.org/docs/connect#types-PaginatedCollection) of [`APIOrder`](https://0x.org/docs/connect#types-APIOrder)s where for each order, the `makerAssetData` field is equal to the `quoteAssetData` provided by the `OrderbookRequest` and the `takerAssetData` field is equal to `baseAssetData`. `Asks` is the opposite of `bids`. For each order, the `makerAssetData` field is equal to the `baseAssetData` and the `takerAssetData` field is equal to `quoteAssetData`.
The Standard Relayer API guarantees that the orders are sorted by price, and then by _taker fee price_ which is defined as the `takerFee` divided by `takerAmount`. After _taker fee price_, orders are to be sorted by expiration in ascending order.
Given the above, we can just pick an order from the top of the asks paginated collection and fill it:
```javascript
const sraOrder = response.asks.records[0].order;
```
Now we validate the order is fillable given the maker and taker. This checks the balances and allowances of both the Maker and Taker, this way if there are any issues we do not waste gas on a failed transaction.
```javascript
await contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync(
sraOrder,
takerAssetAmount,
taker
);
```
Now that the order is validated we submit it to the blockchain by calling fillOrder.
```javascript
txHash = await contractWrappers.exchange.fillOrderAsync(
sraOrder,
takerAssetAmount,
taker,
{
gasLimit: TX_DEFAULTS.gas
}
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
```
### Wrapping up
Through this tutorial we learned how to:
- ask a relayer for fee information
- submit signed orders to a relayer with appropriate fees
- ask a relayer for a ZRX/WETH orderbook
- find the best orders in the orderbook
- fill orders from the orderbook using `0x.js`
While all of these tasks were performed using Ganache and a local standard relayer api compliant HTTP server, you can start using [@0x/connect](https://www.npmjs.com/package/@0x/connect) in conjunction with Radar Relay's standard relayer api HTTP url: https://api.radarrelay.com/0x/v2/ for executing trades on the main Ethereum network. For more information on how to use `0x.js`, go [here](https://0x.org/docs/0x.js).

View File

@@ -0,0 +1,106 @@
const fs = require('fs');
const path = require('path');
const { read } = require('to-vfile');
const remark = require('remark');
const mdx = require('remark-mdx');
const filter = require('unist-util-filter');
const { selectAll } = require('unist-util-select');
const extractMdxMeta = require('extract-mdx-metadata');
function processContentTree(tree, url, meta, index) {
const filteredTree = filter(tree, node => {
return node => node.type === 'heading' || node.type === 'paragraph';
});
const textNodes = selectAll('text', filteredTree);
if (textNodes) {
const formattedTextNodes = formatTextNodes(textNodes);
const content = getContent(meta, url, formattedTextNodes);
pushObjectsToAlgolia(index, content);
}
}
function setIndexSettings(index, settings) {
index.setSettings(settings, (err, content) => {
if (err) console.error(`Error: ${err}`);
});
}
function pushObjectsToAlgolia(index, content) {
index
.saveObjects(content)
.then(({ objectIDs }) =>
console.log(
'Pushed content to Algolia with Object IDs:' + objectIDs.join(', ')
)
)
.catch(err => console.error(`Error: ${err}`));
}
function getContent(meta, url, formattedTextNodes) {
// META SHAPE TOOLS // const { description, difficulty, id, isCommunity, tags, title, type } = meta;
// META SHAPE GUIDES // const { description, difficulty, id, tags, title, topics } = meta;
let content = [];
formattedTextNodes.forEach((node, index) => {
content.push({
...meta,
url,
textContent: node.textContent,
objectID: `${meta.id}_${index}`
});
});
return content;
}
function formatTextNodes(textNodes) {
const formattedTextNodes = []; // array structure: [ { line: [LINE_NUMBER], textContent: [MERGED_TEXT_VALUE] } ]
textNodes.map(textNode => {
const { position, value } = textNode;
const { line } = position.start; // Line at which textnode starts (and for paragraphs, headings, ends).
const nodeIndex = formattedTextNodes.findIndex(node => node.line === line);
const indexExists = nodeIndex > -1;
if (indexExists) {
formattedTextNodes[nodeIndex].textContent += value; // Merge value with existing text at the given line
} else {
formattedTextNodes.push({ line, textContent: value }); // Create text and its start line
}
});
return formattedTextNodes;
}
async function processMdx(index, dirName, fileName) {
const filePath = `${dirName}/${fileName}`;
const { name } = path.parse(filePath); // Name without file extension
const url = `/docs/${dirName}/${name}`;
const rawContent = fs.readFileSync(filePath);
const file = await read(filePath);
const meta = await extractMdxMeta(rawContent);
await remark()
.use(mdx)
.use(() => tree => processContentTree(tree, url, meta, index))
.process(file);
}
async function indexFiles(index, dirName) {
fs.readdir(dirName, async (err, items) => {
for (var i = 0; i < items.length; i++) {
const fileName = items[i];
await processMdx(index, dirName, fileName);
}
});
}
module.exports = {
indexFiles,
setIndexSettings
};

View File

@@ -0,0 +1,13 @@
const { adminClient, sharedSettings } = require('./constants');
const { indexFiles, setIndexSettings } = require('./helpers');
const index = adminClient.initIndex('0x_tools_test');
const dirName = 'tools';
const settings = {
...sharedSettings,
attributesForFaceting: ['type', 'tags', 'difficulty', 'isCommunity'],
};
setIndexSettings(index, settings);
indexFiles(index, dirName);

View File

@@ -0,0 +1,68 @@
export const meta = {
id: 1,
title: '0x launch kit',
description:
'Launch a 0x relayer API backend in under a minute with Launch Kit. 0x-launch-kit-backend is an open-source, free-to-use 0x relayer template that you can use as a starting point for your own project.',
difficulty: 'Beginner',
isCommunity: true,
isFeatured: true,
tags: ['Relayer'],
type: 'Docker images'
};
# Title
We designed the 0x protocol to be extensible exchange infrastructure for the entire crypto economy. 0x's functionality can be extended through extension contracts, which broaden how 0x orders can be filled. There are a variety ways to build extension contracts. An Extension contract can perform work on the users behalf. They can validate that users belong to a specific group. Extension contracts can even be written to join multiple Decentralised Finance projects together.
0x allows for contracts to perform 0x operations, though before version 2 of the protocol there was no way to enforce that an order executed via a specific contract. The 0x order format now contains a field senderAddress. When this is defaulted to empty it is completely open for any anyone to fill. The Forwarder uses open orders with an unspecified sender address to perform a fill on behalf of the user. When the sender address is specified the 0x protocol ensures the operation originates from this address. For example it's possible to create a KYC (Know Your Customer) orderbook. This orderbook contains orders specifying the sender address as the KYC attestation contract. 0x protocol enforces all operations originate from the KYC contract in which all addresses have been validated by this contract.
# Forwarder Contract
Wrapping ETH into ERC-20 compliant wETH has been a large barrier to adoption for the greater Decentralised Finance ecosystem. The 0x core team wrote and deployed a Forwarder contract to address these issues. You have used the Forwarder Contract if you have purchased tokens through 0x Instant. The Forwarder is an example of an extension which performs work on the users behalf.
Users send ETH and a set of orders to the Forwarder contract and these funds are used to trade on 0x. The Forwarder deposits the incoming ETH into wrapped ETH. It then calls fill order with the supplied orders, using the wrapped ETH as its source of funding. Finally it transfers all traded tokens back to the user.
The Forwarder extends the behavior of trading on 0x. It presents a different interface where the user can specify the amount of tokens they wish to buy and use ETH to buy them. This is an improved user experience to interacting with the lower level 0x Exchange contract. From a user's perspective it appears as if they are buying tokens using ETH directly.
Projects can use the Forwarder contract and a Relayers orders in their own integrations. We've seen great adoption of 0x Instant, which uses the Forwarder under the hood. These projects are able to use the affiliate fee in the Forwarder to collect fees in ETH for the trades they originate.
# Dutch Auction Contract
The price of an asset decreases over time and the buyer submits a matching order when they believe the asset is appropriately priced. The Dutch Auction contract guarantees the asset is exchanged for the current price, given the block time. The Dutch Auction contract is an example of an extension which validates some state before matching two orders.
The Dutch Auction contract is powered by the 0x Exchange contracts matchOrders function and extends the order format to include additional data. When using match orders, two orders are passed in as parameters, known as the sell order and the buy order. The seller of the asset creates an order for the asset at the lowest price. When a buyer decides the asset is at an acceptable price, they create a matching order for that amount. The buyer submits both the sell order and the buy order to the Dutch Auction contract.
# Cryptography used by 0x protocol
Once an order maker has decided on all the details of the trade they wish to make, the last step is for them to cryptographically commit to the trade. 0x uses two fundamental building blocks of cryptography to make this happen. This section will introduce these building blocks and how 0x uses them.
## Cryptographic hash function
A cryptographic hash function is a function that maps an input of arbitrary size to an output of fixed size (a hash). It is a one-way function meaning that it is infeasible to invert. The input data is typically called the message and the output the message digest.
0x uses a hash function to create an order digest (order hash) that uniquely identifies all the order fields chosen by the maker. Changing any of the fields of the order, will cause the order hash to change. Thanks to this property of hash functions, the order hash can be used as the unique identifier for an order. Another nice aspect of using a hash function is that all order hashes will have the same fixed length, regardless of the complexity or size of the order fields.
We now have a unique, fixed-length identifier we can generate for every single permutation of a 0x order. The next step is to allow a maker to cryptographically commit to this representation of their 0x order.
A digital signature is a mathematical scheme for verifying the authenticity and integrity of a digital message.
- Authenticity - Was the message really authored by who we think?
- Integrity - Are we sure the message wasnt altered in transit
0x uses a digital signature to allow order makers to cryptographically commit to the 0x order they authored. In this way, they can rest assured that they cannot be forced into filling any order except for the ones theyve authored, and potential counter-parties can verify that the maker did indeed author the 0x order(s).
In order for a 0x order to be considered valid and fillable, it must have all the stipulated fields listed above, and come with a digital signature from the maker attesting to all the field values. At this point, the 0x order is ready to be shared with potential counter-parties.
# Off-chain relay, on-chain settlement
Up until this point, the 0x order was created and is sitting on the order makers computer. In order to find a counter-party for the order, where does it need to go? Unlike other decentralized exchanges, 0x does not store orders on the blockchain. Instead orders are stored off-chain, and only trade settlement occurs on-chain.
If the maker already knows their desired counter-party, they can simply send the 0x order directly to them (i.e., via email or an over-the-counter platform). If the maker doesnt know of a counter-party willing to take the other side of the trade, the order can be submitted to a 0x relayer in hopes of finding a counter-party. A “relayer” is any entity that helps traders create, find and fill. Existing relayers can be found by browsing the Explore 0x page. Anyone can build a 0x relayer and begin earning fees for every 0x trade they facilitate.
Once someone finds and wishes to fill the 0x order authored by the maker, they are able to fill it by submitting the order, along with the amount they wish to fill it for, to the blockchain. The 0x protocols settlement logic will verify the makers digital signature and that all the conditions of the trade are satisfied. If so, the assets involved will be atomically swapped between the maker and taker. If any of the orders conditions are not met, the fill request is rejected.
<Component>Another component</Component>
```solidity
Source code
```

View File

@@ -0,0 +1,67 @@
export const meta = {
id: 2,
title: '0x smart contracts',
description:
'Reference documentation for the 0x smart contracts. Helpful for dApp developer wanting to integrate 0x at the smart contract level.',
difficulty: 'Beginner',
isFeatured: true,
tags: ['Trader'],
type: 'Starter projects'
};
# Title
We designed the 0x protocol to be extensible exchange infrastructure for the entire crypto economy. 0x's functionality can be extended through extension contracts, which broaden how 0x orders can be filled. There are a variety ways to build extension contracts. An Extension contract can perform work on the users behalf. They can validate that users belong to a specific group. Extension contracts can even be written to join multiple Decentralised Finance projects together.
0x allows for contracts to perform 0x operations, though before version 2 of the protocol there was no way to enforce that an order executed via a specific contract. The 0x order format now contains a field senderAddress. When this is defaulted to empty it is completely open for any anyone to fill. The Forwarder uses open orders with an unspecified sender address to perform a fill on behalf of the user. When the sender address is specified the 0x protocol ensures the operation originates from this address. For example it's possible to create a KYC (Know Your Customer) orderbook. This orderbook contains orders specifying the sender address as the KYC attestation contract. 0x protocol enforces all operations originate from the KYC contract in which all addresses have been validated by this contract.
# Forwarder Contract
Wrapping ETH into ERC-20 compliant wETH has been a large barrier to adoption for the greater Decentralised Finance ecosystem. The 0x core team wrote and deployed a Forwarder contract to address these issues. You have used the Forwarder Contract if you have purchased tokens through 0x Instant. The Forwarder is an example of an extension which performs work on the users behalf.
Users send ETH and a set of orders to the Forwarder contract and these funds are used to trade on 0x. The Forwarder deposits the incoming ETH into wrapped ETH. It then calls fill order with the supplied orders, using the wrapped ETH as its source of funding. Finally it transfers all traded tokens back to the user.
The Forwarder extends the behavior of trading on 0x. It presents a different interface where the user can specify the amount of tokens they wish to buy and use ETH to buy them. This is an improved user experience to interacting with the lower level 0x Exchange contract. From a user's perspective it appears as if they are buying tokens using ETH directly.
Projects can use the Forwarder contract and a Relayers orders in their own integrations. We've seen great adoption of 0x Instant, which uses the Forwarder under the hood. These projects are able to use the affiliate fee in the Forwarder to collect fees in ETH for the trades they originate.
# Dutch Auction Contract
The price of an asset decreases over time and the buyer submits a matching order when they believe the asset is appropriately priced. The Dutch Auction contract guarantees the asset is exchanged for the current price, given the block time. The Dutch Auction contract is an example of an extension which validates some state before matching two orders.
The Dutch Auction contract is powered by the 0x Exchange contracts matchOrders function and extends the order format to include additional data. When using match orders, two orders are passed in as parameters, known as the sell order and the buy order. The seller of the asset creates an order for the asset at the lowest price. When a buyer decides the asset is at an acceptable price, they create a matching order for that amount. The buyer submits both the sell order and the buy order to the Dutch Auction contract.
# Cryptography used by 0x protocol
Once an order maker has decided on all the details of the trade they wish to make, the last step is for them to cryptographically commit to the trade. 0x uses two fundamental building blocks of cryptography to make this happen. This section will introduce these building blocks and how 0x uses them.
## Cryptographic hash function
A cryptographic hash function is a function that maps an input of arbitrary size to an output of fixed size (a hash). It is a one-way function meaning that it is infeasible to invert. The input data is typically called the message and the output the message digest.
0x uses a hash function to create an order digest (order hash) that uniquely identifies all the order fields chosen by the maker. Changing any of the fields of the order, will cause the order hash to change. Thanks to this property of hash functions, the order hash can be used as the unique identifier for an order. Another nice aspect of using a hash function is that all order hashes will have the same fixed length, regardless of the complexity or size of the order fields.
We now have a unique, fixed-length identifier we can generate for every single permutation of a 0x order. The next step is to allow a maker to cryptographically commit to this representation of their 0x order.
A digital signature is a mathematical scheme for verifying the authenticity and integrity of a digital message.
- Authenticity - Was the message really authored by who we think?
- Integrity - Are we sure the message wasnt altered in transit
0x uses a digital signature to allow order makers to cryptographically commit to the 0x order they authored. In this way, they can rest assured that they cannot be forced into filling any order except for the ones theyve authored, and potential counter-parties can verify that the maker did indeed author the 0x order(s).
In order for a 0x order to be considered valid and fillable, it must have all the stipulated fields listed above, and come with a digital signature from the maker attesting to all the field values. At this point, the 0x order is ready to be shared with potential counter-parties.
# Off-chain relay, on-chain settlement
Up until this point, the 0x order was created and is sitting on the order makers computer. In order to find a counter-party for the order, where does it need to go? Unlike other decentralized exchanges, 0x does not store orders on the blockchain. Instead orders are stored off-chain, and only trade settlement occurs on-chain.
If the maker already knows their desired counter-party, they can simply send the 0x order directly to them (i.e., via email or an over-the-counter platform). If the maker doesnt know of a counter-party willing to take the other side of the trade, the order can be submitted to a 0x relayer in hopes of finding a counter-party. A “relayer” is any entity that helps traders create, find and fill. Existing relayers can be found by browsing the Explore 0x page. Anyone can build a 0x relayer and begin earning fees for every 0x trade they facilitate.
Once someone finds and wishes to fill the 0x order authored by the maker, they are able to fill it by submitting the order, along with the amount they wish to fill it for, to the blockchain. The 0x protocols settlement logic will verify the makers digital signature and that all the conditions of the trade are satisfied. If so, the assets involved will be atomically swapped between the maker and taker. If any of the orders conditions are not met, the fill request is rejected.
<Component>Another component</Component>
```solidity
Source code
```

View File

@@ -0,0 +1,66 @@
export const meta = {
id: 3,
title: '0x.js',
description:
'A library for interacting with the 0x protocol. It is a high level package which combines a number of smaller specific-purpose packages such as order-utils and contract-wrappers.',
difficulty: 'Beginner',
tags: ['Protocol Developer'],
type: 'Command-line tools'
};
# Title
We designed the 0x protocol to be extensible exchange infrastructure for the entire crypto economy. 0x's functionality can be extended through extension contracts, which broaden how 0x orders can be filled. There are a variety ways to build extension contracts. An Extension contract can perform work on the users behalf. They can validate that users belong to a specific group. Extension contracts can even be written to join multiple Decentralised Finance projects together.
0x allows for contracts to perform 0x operations, though before version 2 of the protocol there was no way to enforce that an order executed via a specific contract. The 0x order format now contains a field senderAddress. When this is defaulted to empty it is completely open for any anyone to fill. The Forwarder uses open orders with an unspecified sender address to perform a fill on behalf of the user. When the sender address is specified the 0x protocol ensures the operation originates from this address. For example it's possible to create a KYC (Know Your Customer) orderbook. This orderbook contains orders specifying the sender address as the KYC attestation contract. 0x protocol enforces all operations originate from the KYC contract in which all addresses have been validated by this contract.
# Forwarder Contract
Wrapping ETH into ERC-20 compliant wETH has been a large barrier to adoption for the greater Decentralised Finance ecosystem. The 0x core team wrote and deployed a Forwarder contract to address these issues. You have used the Forwarder Contract if you have purchased tokens through 0x Instant. The Forwarder is an example of an extension which performs work on the users behalf.
Users send ETH and a set of orders to the Forwarder contract and these funds are used to trade on 0x. The Forwarder deposits the incoming ETH into wrapped ETH. It then calls fill order with the supplied orders, using the wrapped ETH as its source of funding. Finally it transfers all traded tokens back to the user.
The Forwarder extends the behavior of trading on 0x. It presents a different interface where the user can specify the amount of tokens they wish to buy and use ETH to buy them. This is an improved user experience to interacting with the lower level 0x Exchange contract. From a user's perspective it appears as if they are buying tokens using ETH directly.
Projects can use the Forwarder contract and a Relayers orders in their own integrations. We've seen great adoption of 0x Instant, which uses the Forwarder under the hood. These projects are able to use the affiliate fee in the Forwarder to collect fees in ETH for the trades they originate.
# Dutch Auction Contract
The price of an asset decreases over time and the buyer submits a matching order when they believe the asset is appropriately priced. The Dutch Auction contract guarantees the asset is exchanged for the current price, given the block time. The Dutch Auction contract is an example of an extension which validates some state before matching two orders.
The Dutch Auction contract is powered by the 0x Exchange contracts matchOrders function and extends the order format to include additional data. When using match orders, two orders are passed in as parameters, known as the sell order and the buy order. The seller of the asset creates an order for the asset at the lowest price. When a buyer decides the asset is at an acceptable price, they create a matching order for that amount. The buyer submits both the sell order and the buy order to the Dutch Auction contract.
# Cryptography used by 0x protocol
Once an order maker has decided on all the details of the trade they wish to make, the last step is for them to cryptographically commit to the trade. 0x uses two fundamental building blocks of cryptography to make this happen. This section will introduce these building blocks and how 0x uses them.
## Cryptographic hash function
A cryptographic hash function is a function that maps an input of arbitrary size to an output of fixed size (a hash). It is a one-way function meaning that it is infeasible to invert. The input data is typically called the message and the output the message digest.
0x uses a hash function to create an order digest (order hash) that uniquely identifies all the order fields chosen by the maker. Changing any of the fields of the order, will cause the order hash to change. Thanks to this property of hash functions, the order hash can be used as the unique identifier for an order. Another nice aspect of using a hash function is that all order hashes will have the same fixed length, regardless of the complexity or size of the order fields.
We now have a unique, fixed-length identifier we can generate for every single permutation of a 0x order. The next step is to allow a maker to cryptographically commit to this representation of their 0x order.
A digital signature is a mathematical scheme for verifying the authenticity and integrity of a digital message.
- Authenticity - Was the message really authored by who we think?
- Integrity - Are we sure the message wasnt altered in transit
0x uses a digital signature to allow order makers to cryptographically commit to the 0x order they authored. In this way, they can rest assured that they cannot be forced into filling any order except for the ones theyve authored, and potential counter-parties can verify that the maker did indeed author the 0x order(s).
In order for a 0x order to be considered valid and fillable, it must have all the stipulated fields listed above, and come with a digital signature from the maker attesting to all the field values. At this point, the 0x order is ready to be shared with potential counter-parties.
# Off-chain relay, on-chain settlement
Up until this point, the 0x order was created and is sitting on the order makers computer. In order to find a counter-party for the order, where does it need to go? Unlike other decentralized exchanges, 0x does not store orders on the blockchain. Instead orders are stored off-chain, and only trade settlement occurs on-chain.
If the maker already knows their desired counter-party, they can simply send the 0x order directly to them (i.e., via email or an over-the-counter platform). If the maker doesnt know of a counter-party willing to take the other side of the trade, the order can be submitted to a 0x relayer in hopes of finding a counter-party. A “relayer” is any entity that helps traders create, find and fill. Existing relayers can be found by browsing the Explore 0x page. Anyone can build a 0x relayer and begin earning fees for every 0x trade they facilitate.
Once someone finds and wishes to fill the 0x order authored by the maker, they are able to fill it by submitting the order, along with the amount they wish to fill it for, to the blockchain. The 0x protocols settlement logic will verify the makers digital signature and that all the conditions of the trade are satisfied. If so, the assets involved will be atomically swapped between the maker and taker. If any of the orders conditions are not met, the fill request is rejected.
<Component>Another component</Component>
```solidity
Source code
```

View File

@@ -1,8 +1,9 @@
import algoliasearch from 'algoliasearch/lite';
const algoliasearch = require('algoliasearch/lite');
import { configs } from 'ts/utils/configs';
const { configs } = require('ts/utils/configs');
export const searchClient = algoliasearch(configs.ALGOLIA_APP_ID, configs.ALGOLIA_API_KEY_CLIENT);
export const searchClient = algoliasearch(configs.ALGOLIA_APP_ID, configs.ALGOLIA_CLIENT_API_KEY);
// export const adminClient = algoliasearch(configs.ALGOLIA_APP_ID, configs.ALGOLIA_ADMIN_API_KEY);
export const searchIndex = {
guides: '0x_guides_test',

View File

@@ -5,7 +5,8 @@ const INFURA_API_KEY = 'T5WSC8cautR4KXyYgsRs';
export const configs = {
ALGOLIA_APP_ID: 'T7V7WKELRY',
ALGOLIA_API_KEY_CLIENT: '4c367b8cc6d6e175ae537cc61e4d8dfd',
ALGOLIA_ADMIN_API_KEY: 'ccc472dee2aa991ca4bc935975e76b5d',
ALGOLIA_CLIENT_API_KEY: '4c367b8cc6d6e175ae537cc61e4d8dfd',
AMOUNT_DISPLAY_PRECSION: 5,
BACKEND_BASE_PROD_URL: 'https://website-api.0x.org',
BACKEND_BASE_STAGING_URL: 'https://staging-website-api.0x.org',

466
yarn.lock
View File

@@ -851,6 +851,33 @@
dependencies:
"@babel/highlight" "^7.0.0"
"@babel/code-frame@^7.5.5":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==
dependencies:
"@babel/highlight" "^7.0.0"
"@babel/core@7.3.4":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b"
integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==
dependencies:
"@babel/code-frame" "^7.0.0"
"@babel/generator" "^7.3.4"
"@babel/helpers" "^7.2.0"
"@babel/parser" "^7.3.4"
"@babel/template" "^7.2.2"
"@babel/traverse" "^7.3.4"
"@babel/types" "^7.3.4"
convert-source-map "^1.1.0"
debug "^4.1.0"
json5 "^2.1.0"
lodash "^4.17.11"
resolve "^1.3.2"
semver "^5.4.1"
source-map "^0.5.0"
"@babel/core@^7.2.2":
version "7.4.5"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.5.tgz#081f97e8ffca65a9b4b0fdc7e274e703f000c06a"
@@ -870,6 +897,28 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/generator@7.3.4":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e"
integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==
dependencies:
"@babel/types" "^7.3.4"
jsesc "^2.5.1"
lodash "^4.17.11"
source-map "^0.5.0"
trim-right "^1.0.1"
"@babel/generator@^7.3.4", "@babel/generator@^7.5.5":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.5.tgz#873a7f936a3c89491b43536d12245b626664e3cf"
integrity sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==
dependencies:
"@babel/types" "^7.5.5"
jsesc "^2.5.1"
lodash "^4.17.13"
source-map "^0.5.0"
trim-right "^1.0.1"
"@babel/generator@^7.4.4":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.4.tgz#174a215eb843fc392c7edcaabeaa873de6e8f041"
@@ -1008,7 +1057,7 @@
"@babel/template" "^7.1.0"
"@babel/types" "^7.0.0"
"@babel/helper-split-export-declaration@^7.4.4":
"@babel/helper-split-export-declaration@^7.0.0", "@babel/helper-split-export-declaration@^7.4.4":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677"
dependencies:
@@ -1023,6 +1072,15 @@
"@babel/traverse" "^7.1.0"
"@babel/types" "^7.2.0"
"@babel/helpers@^7.2.0":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.5.5.tgz#63908d2a73942229d1e6685bc2a0e730dde3b75e"
integrity sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==
dependencies:
"@babel/template" "^7.4.4"
"@babel/traverse" "^7.5.5"
"@babel/types" "^7.5.5"
"@babel/helpers@^7.4.4":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.4.4.tgz#868b0ef59c1dd4e78744562d5ce1b59c89f2f2a5"
@@ -1039,6 +1097,16 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
"@babel/parser@7.3.4":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c"
integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==
"@babel/parser@^7.3.4", "@babel/parser@^7.5.5":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b"
integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==
"@babel/parser@^7.4.4", "@babel/parser@^7.4.5":
version "7.4.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872"
@@ -1438,13 +1506,20 @@
dependencies:
regenerator-runtime "^0.12.0"
"@babel/runtime@^7.3.1":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
dependencies:
regenerator-runtime "^0.13.2"
"@babel/runtime@^7.4.0":
version "7.4.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12"
dependencies:
regenerator-runtime "^0.13.2"
"@babel/template@^7.1.0", "@babel/template@^7.4.4":
"@babel/template@^7.1.0", "@babel/template@^7.2.2", "@babel/template@^7.4.4":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237"
dependencies:
@@ -1452,12 +1527,42 @@
"@babel/parser" "^7.4.4"
"@babel/types" "^7.4.4"
"@babel/traverse@7.3.4":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06"
integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==
dependencies:
"@babel/code-frame" "^7.0.0"
"@babel/generator" "^7.3.4"
"@babel/helper-function-name" "^7.1.0"
"@babel/helper-split-export-declaration" "^7.0.0"
"@babel/parser" "^7.3.4"
"@babel/types" "^7.3.4"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.11"
"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.4.5":
version "7.4.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.5.tgz#4e92d1728fd2f1897dafdd321efbff92156c3216"
dependencies:
regenerator-runtime "^0.13.2"
"@babel/traverse@^7.3.4", "@babel/traverse@^7.5.5":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb"
integrity sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==
dependencies:
"@babel/code-frame" "^7.5.5"
"@babel/generator" "^7.5.5"
"@babel/helper-function-name" "^7.1.0"
"@babel/helper-split-export-declaration" "^7.4.4"
"@babel/parser" "^7.5.5"
"@babel/types" "^7.5.5"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.13"
"@babel/types@^7.0.0":
version "7.1.3"
resolved "https://registry.npmjs.org/@babel/types/-/types-7.1.3.tgz#3a767004567060c2f40fca49a304712c525ee37d"
@@ -1474,6 +1579,15 @@
lodash "^4.17.11"
to-fast-properties "^2.0.0"
"@babel/types@^7.3.4", "@babel/types@^7.5.5":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a"
integrity sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==
dependencies:
esutils "^2.0.2"
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@emotion/is-prop-valid@^0.6.8":
version "0.6.8"
resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.6.8.tgz#68ad02831da41213a2089d2cab4e8ac8b30cbd85"
@@ -2142,9 +2256,41 @@
version "1.1.3"
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
"@octokit/endpoint@^5.1.0":
version "5.3.1"
resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-5.3.1.tgz#4a1714c7d35c1ed074e898c5f4a9897541581f79"
"@mdx-js/mdx@0.20.3":
version "0.20.3"
resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-0.20.3.tgz#1f32b4a4a0cc176a3192ef51a0a3502cdfdca3f0"
integrity sha512-IIlssEIPPAqo04krm270ifGjSVPqtTmjlryYGi8/4VXHCdi42l8v2piTJPo2NVc7J+HizY1uxxZb6AeoFsO/Iw==
dependencies:
"@babel/plugin-proposal-object-rest-spread" "^7.3.2"
"@babel/plugin-syntax-jsx" "^7.2.0"
change-case "^3.0.2"
detab "^2.0.0"
hast-util-raw "^5.0.0"
mdast-util-to-hast "^4.0.0"
remark-parse "^6.0.0"
remark-squeeze-paragraphs "^3.0.1"
to-style "^1.3.3"
unified "^7.0.0"
unist-builder "^1.0.1"
unist-util-visit "^1.3.0"
"@mdx-js/mdx@^0.15.5":
version "0.15.7"
resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-0.15.7.tgz#5fde5841d7b6f4c78f80c19fff559532af5ce5ad"
integrity sha512-bWUQidQhjTRFh5nK01kW3qQLCH/aCq6VTapOZ/+WI5hL4exoRw6TgnxxmgSf/p7mmrGxIpCHmnaWXdbHSObxlg==
dependencies:
change-case "^3.0.2"
detab "^2.0.0"
mdast-util-to-hast "^3.0.0"
remark-parse "^5.0.0"
remark-squeeze-paragraphs "^3.0.1"
to-style "^1.3.3"
unified "^6.1.6"
unist-util-visit "^1.3.0"
"@mdx-js/mdx@^1.0.0-rc.4":
version "1.0.21"
resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.0.21.tgz#028a7975fff026222f7ace19c8c130290c649025"
dependencies:
deepmerge "4.0.0"
is-plain-object "^3.0.0"
@@ -2743,7 +2889,7 @@
dependencies:
source-map "^0.6.1"
"@types/unist@*", "@types/unist@^2.0.0":
"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
@@ -5195,6 +5341,17 @@ caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
ccount@^1.0.0, ccount@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.4.tgz#9cf2de494ca84060a2a8d2854edd6dfb0445f386"
center-align@^0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
dependencies:
align-text "^0.1.3"
lazy-cache "^1.0.3"
chai-as-promised@^7.1.0:
version "7.1.1"
resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0"
@@ -5284,6 +5441,11 @@ change-emitter@^0.1.2:
version "0.1.6"
resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515"
character-entities-html4@^1.0.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.3.tgz#5ce6e01618e47048ac22f34f7f39db5c6fd679ef"
integrity sha512-SwnyZ7jQBCRHELk9zf2CN5AnGEc2nA+uKMZLHvcqhpPprjkYhiLn0DywMHgN5ttFZuITMATbh68M6VIVKwJbcg==
character-entities-legacy@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c"
@@ -6353,6 +6515,11 @@ css-select@^1.1.0, css-select@~1.2.0:
domutils "1.5.1"
nth-check "~1.0.1"
css-selector-parser@^1.1.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.3.0.tgz#5f1ad43e2d8eefbfdc304fcd39a521664943e3eb"
integrity sha1-XxrUPi2O77/cME/NOaUhZklD4+s=
css-selector-tokenizer@^0.5.1:
version "0.5.4"
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.5.4.tgz#139bafd34a35fd0c1428487049e0699e6f6a2c21"
@@ -7187,6 +7354,11 @@ elliptic@^3.1.0:
hash.js "^1.0.0"
inherits "^2.0.1"
"emoji-regex@>=6.0.0 <=6.1.1":
version "6.1.1"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e"
integrity sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=
emoji-regex@^7.0.1, emoji-regex@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
@@ -8322,6 +8494,18 @@ extract-comments@^1.1.0:
esprima-extract-comments "^1.1.0"
parse-code-context "^1.0.0"
extract-mdx-metadata@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/extract-mdx-metadata/-/extract-mdx-metadata-1.0.0.tgz#7a54c8a495da955ccef50b7fc41a823c64c6011a"
integrity sha512-rQ7ZDPFBjbM50XAqEnviPqaeYPl/GNmCi2DV9AZnOATPxqLMtuSzvm/y6eo7JR37PxwP+C0dBPRPXexWWuuIsg==
dependencies:
"@babel/core" "7.3.4"
"@babel/generator" "7.3.4"
"@babel/parser" "7.3.4"
"@babel/traverse" "7.3.4"
"@mdx-js/mdx" "0.20.3"
unist-util-visit "1.4.0"
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@@ -8688,6 +8872,11 @@ flatiron@~0.4.2:
optimist "0.6.0"
prompt "0.2.14"
flatmap@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/flatmap/-/flatmap-0.0.3.tgz#1f18a4d938152d495965f9c958d923ab2dd669b4"
integrity sha1-Hxik2TgVLUlZZfnJWNkjqy3WabQ=
flatten@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
@@ -9208,6 +9397,13 @@ github-from-package@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
github-slugger@^1.0.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.2.1.tgz#47e904e70bf2dccd0014748142d31126cfd49508"
integrity sha512-SsZUjg/P03KPzQBt7OxJPasGw6NRO5uOgiZ5RGXVud5iSIZ0eNZeNp5rTwCxtavrRUa/A77j8mePVc5lEvk0KQ==
dependencies:
emoji-regex ">=6.0.0 <=6.1.1"
github-url-to-object@^1.4.2:
version "1.6.0"
resolved "https://registry.yarnpkg.com/github-url-to-object/-/github-url-to-object-1.6.0.tgz#891ef7fbbfaba8fed71510acdb1b4e9346a970dc"
@@ -9527,21 +9723,10 @@ got@^6.7.1:
unzip-response "^2.0.1"
url-parse-lax "^1.0.0"
graceful-fs@^3.0.0:
version "3.0.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818"
integrity sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=
dependencies:
natives "^1.1.0"
graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
graceful-fs@4.1.15, graceful-fs@^3.0.0, graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@~1.2.0:
version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
graceful-fs@~1.2.0:
version "1.2.3"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364"
integrity sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
"graceful-readlink@>= 1.0.0":
version "1.0.1"
@@ -9901,11 +10086,11 @@ heap@0.2.6:
version "0.2.6"
resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac"
highlight.js@^9.0.0, highlight.js@^9.11.0, highlight.js@~9.12.0:
highlight.js@^9.0.0, highlight.js@^9.11.0:
version "9.12.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e"
highlight.js@^9.13.1:
highlight.js@^9.13.1, highlight.js@^9.6.0, highlight.js@~9.13.0:
version "9.13.1"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
@@ -10500,6 +10685,11 @@ is-alphabetical@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.3.tgz#eb04cc47219a8895d8450ace4715abff2258a1f8"
is-alphanumeric@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4"
integrity sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=
is-alphanumerical@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz#dfb4aa4d1085e33bdb61c2dee9c80e9c6c19f53b"
@@ -12357,6 +12547,11 @@ lodash@^4.0.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.10,
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
lodash@^4.17.13:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
lodash@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551"
@@ -12399,6 +12594,15 @@ lolex@^2.2.0, lolex@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.2.tgz#85f9450425103bf9e7a60668ea25dc43274ca807"
longest-streak@^2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.3.tgz#3de7a3f47ee18e9074ded8575b5c091f5d0a4105"
integrity sha512-9lz5IVdpwsKLMzQi0MQ+oD9EA0mIGcWYP7jXMTZVXP8D42PwuAk+M/HBFYQoxt1G5OR8m7aSIgb1UymfWGBWEw==
longest@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
looper@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec"
@@ -12444,12 +12648,13 @@ lowercase-keys@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
lowlight@~1.9.1:
version "1.9.2"
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.9.2.tgz#0b9127e3cec2c3021b7795dd81005c709a42fdd1"
lowlight@~1.11.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.11.0.tgz#1304d83005126d4e8b1dc0f07981e9b689ec2efc"
integrity sha512-xrGGN6XLL7MbTMdPD6NfWPwY43SNkjf/d0mecSx/CW36fUZTjRHEq0/Cdug3TWKtRXLWi7iMl1eP0olYxj/a4A==
dependencies:
fault "^1.0.2"
highlight.js "~9.12.0"
highlight.js "~9.13.0"
lru-cache@2:
version "2.7.3"
@@ -12610,6 +12815,11 @@ markdown-escapes@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122"
markdown-table@^1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60"
integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==
marked@0.3.18:
version "0.3.18"
resolved "https://registry.npmjs.org/marked/-/marked-0.3.18.tgz#3ef058cd926101849b92a7a7c15db18c7fc76b2f"
@@ -12682,12 +12892,36 @@ mdast-squeeze-paragraphs@^3.0.0:
dependencies:
unist-util-remove "^1.0.0"
mdast-util-compact@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.3.tgz#98a25cc8a7865761a41477b3a87d1dcef0b1e79d"
integrity sha512-nRiU5GpNy62rZppDKbLwhhtw5DXoFMqw9UNZFmlPsNaQCZ//WLjGKUwWMdJrUH+Se7UvtO2gXtAMe0g/N+eI5w==
dependencies:
unist-util-visit "^1.1.0"
mdast-util-definitions@^1.2.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-1.2.4.tgz#2b54ad4eecaff9d9fcb6bf6f9f6b68b232d77ca7"
dependencies:
unist-util-visit "^1.0.0"
mdast-util-to-hast@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-3.0.4.tgz#132001b266031192348d3366a6b011f28e54dc40"
integrity sha512-/eIbly2YmyVgpJNo+bFLLMCI1XgolO/Ffowhf+pHDq3X4/V6FntC9sGQCDLM147eTS+uSXv5dRzJyFn+o0tazA==
dependencies:
collapse-white-space "^1.0.0"
detab "^2.0.0"
mdast-util-definitions "^1.2.0"
mdurl "^1.0.1"
trim "0.0.1"
trim-lines "^1.0.0"
unist-builder "^1.0.1"
unist-util-generated "^1.1.0"
unist-util-position "^3.0.0"
unist-util-visit "^1.1.0"
xtend "^4.0.1"
mdast-util-to-hast@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-4.0.0.tgz#d8467ce28ea73b4648667bc389aa39dfa9f67f18"
@@ -12704,10 +12938,22 @@ mdast-util-to-hast@^4.0.0:
unist-util-visit "^1.1.0"
xtend "^4.0.1"
mdast-util-to-string@^1.0.0:
version "1.0.6"
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.0.6.tgz#7d85421021343b33de1552fc71cb8e5b4ae7536d"
integrity sha512-868pp48gUPmZIhfKrLbaDneuzGiw3OTDjHc5M1kAepR2CWBJ+HpEsm252K4aXdiP5coVZaJPOqGtVU6Po8xnXg==
mdurl@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
mdx-table-of-contents@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/mdx-table-of-contents/-/mdx-table-of-contents-0.1.0.tgz#a09dce9424ddff084ab07b7a6f3dcba5ed456fb3"
integrity sha512-aNhJvAkghJEKLat+THHJB9qi2bS4iBl1wNDLfwbByUZTvQ8DgLKUJ/TMEIrcWMuuks6BbsK7sp2IqLTUPnUfZQ==
dependencies:
"@mdx-js/mdx" "^0.15.5"
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@@ -13265,11 +13511,6 @@ nanomatch@^1.2.9:
snapdragon "^0.8.1"
to-regex "^3.0.1"
natives@^1.1.0:
version "1.1.6"
resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.6.tgz#a603b4a498ab77173612b9ea1acdec4d980f00bb"
integrity sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@@ -13663,9 +13904,10 @@ normalize-url@^1.4.0:
query-string "^4.1.0"
sort-keys "^1.0.0"
normalize-url@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
not@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/not/-/not-0.1.0.tgz#c9691c1746c55dcfbe54cbd8bd4ff041bc2b519d"
integrity sha1-yWkcF0bFXc++VMvYvU/wQbwrUZ0=
now-and-later@^2.0.0:
version "2.0.0"
@@ -13829,6 +14071,13 @@ nssocket@~0.5.1:
eventemitter2 "~0.4.14"
lazy "~1.0.11"
nth-check@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==
dependencies:
boolbase "~1.0.0"
nth-check@~1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4"
@@ -14408,6 +14657,18 @@ parse-code-context@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/parse-code-context/-/parse-code-context-1.0.0.tgz#718c295c593d0d19a37f898473268cc75e98de1e"
parse-entities@^1.0.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50"
integrity sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==
dependencies:
character-entities "^1.0.0"
character-entities-legacy "^1.0.0"
character-reference-invalid "^1.0.0"
is-alphanumerical "^1.0.0"
is-decimal "^1.0.0"
is-hexadecimal "^1.0.0"
parse-entities@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.1.tgz#8112d88471319f27abae4d64964b122fe4e1b890"
@@ -15654,7 +15915,7 @@ react-dom@^16.3.2:
object-assign "^4.1.1"
prop-types "^15.6.0"
react-dom@^16.8.0, react-dom@^16.8.4:
react-dom@^16.8.0, react-dom@^16.8.4, react-dom@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f"
dependencies:
@@ -15914,13 +16175,14 @@ react-svg-loader@^2.1.0:
loader-utils "^1.1.0"
react-svg-core "^2.1.0"
react-syntax-highlighter@^10.1.1:
version "10.1.2"
resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-10.1.2.tgz#645ad5e3d8667fd7a2b73fc1059f871055d23f82"
react-syntax-highlighter@^11.0.1:
version "11.0.2"
resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-11.0.2.tgz#4e3f376e752b20d2f54e4c55652fd663149e4029"
integrity sha512-kqmpM2OH5OodInbEADKARwccwSQWBfZi0970l5Jhp4h39q9Q65C4frNcnd6uHE5pR00W8pOWj9HDRntj2G4Rww==
dependencies:
"@babel/runtime" "^7.1.2"
highlight.js "~9.12.0"
lowlight "~1.9.1"
"@babel/runtime" "^7.3.1"
highlight.js "~9.13.0"
lowlight "~1.11.0"
prismjs "^1.8.4"
refractor "^2.4.1"
@@ -16001,7 +16263,7 @@ react@^16.3.2:
object-assign "^4.1.1"
prop-types "^15.6.0"
react@^16.8.0:
react@^16.8.0, react@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
dependencies:
@@ -16467,12 +16729,50 @@ remark-parse@^6.0.0:
vfile-location "^2.0.0"
xtend "^4.0.1"
remark-slug@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/remark-slug/-/remark-slug-5.1.2.tgz#715ecdef8df1226786204b1887d31ab16aa24609"
integrity sha512-DWX+Kd9iKycqyD+/B+gEFO3jjnt7Yg1O05lygYSNTe5i5PIxxxPjp5qPBDxPIzp5wreF7+1ROCwRgjEcqmzr3A==
dependencies:
github-slugger "^1.0.0"
mdast-util-to-string "^1.0.0"
unist-util-visit "^1.0.0"
remark-squeeze-paragraphs@^3.0.1:
version "3.0.4"
resolved "https://registry.yarnpkg.com/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-3.0.4.tgz#9fe50c3bf3b572dd88754cd426ada007c0b8dc5f"
dependencies:
mdast-squeeze-paragraphs "^3.0.0"
remark-stringify@^6.0.0:
version "6.0.4"
resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-6.0.4.tgz#16ac229d4d1593249018663c7bddf28aafc4e088"
integrity sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==
dependencies:
ccount "^1.0.0"
is-alphanumeric "^1.0.0"
is-decimal "^1.0.0"
is-whitespace-character "^1.0.0"
longest-streak "^2.0.1"
markdown-escapes "^1.0.0"
markdown-table "^1.1.0"
mdast-util-compact "^1.0.0"
parse-entities "^1.0.2"
repeat-string "^1.5.4"
state-toggle "^1.0.0"
stringify-entities "^1.0.1"
unherit "^1.0.4"
xtend "^4.0.1"
remark@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/remark/-/remark-10.0.1.tgz#3058076dc41781bf505d8978c291485fe47667df"
integrity sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==
dependencies:
remark-parse "^6.0.0"
remark-stringify "^6.0.0"
unified "^7.0.0"
remove-bom-buffer@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53"
@@ -17977,6 +18277,16 @@ string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
stringify-entities@^1.0.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.2.tgz#a98417e5471fd227b3e45d3db1861c11caf668f7"
integrity sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==
dependencies:
character-entities-html4 "^1.0.0"
character-entities-legacy "^1.0.0"
is-alphanumerical "^1.0.0"
is-hexadecimal "^1.0.0"
stringstream@~0.0.4, stringstream@~0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
@@ -18638,6 +18948,14 @@ to-through@^2.0.0:
dependencies:
through2 "^2.0.3"
to-vfile@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/to-vfile/-/to-vfile-6.0.0.tgz#96c4aa0ee09c51dd4e8fd0b9c11da040d7dba9ea"
integrity sha512-i9fwXXSsHLu7mzgixc1WjgnqSe6pGpjnzCYoFmrASvEueLfyKf09QAe+XQYu8OAJ62aFqHpe2EKXojeRVvEzqA==
dependencies:
is-buffer "^2.0.0"
vfile "^4.0.0"
toggle-selection@^1.0.3:
version "1.0.6"
resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
@@ -19147,6 +19465,18 @@ unified@^6.1.5:
x-is-function "^1.0.4"
x-is-string "^0.1.0"
unified@^6.1.6:
version "6.2.0"
resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba"
integrity sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==
dependencies:
bail "^1.0.0"
extend "^3.0.0"
is-plain-obj "^1.1.0"
trough "^1.0.0"
vfile "^2.0.0"
x-is-string "^0.1.0"
unified@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/unified/-/unified-7.1.0.tgz#5032f1c1ee3364bd09da12e27fdd4a7553c7be13"
@@ -19230,6 +19560,14 @@ unist-builder@^1.0.1:
dependencies:
object-assign "^4.1.0"
unist-util-filter@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/unist-util-filter/-/unist-util-filter-1.0.2.tgz#e6e4df8d3a54cc99482a8e882e9e37eb023251cc"
integrity sha512-AIJXJNzI8bLStKz3UDt4IX7/GSfO0NeV/plrd5td4VfB0SBlYil7pGzaeBHI8/KXzTWPaPtIbpGK53jYd1kG9A==
dependencies:
flatmap "0.0.3"
unist-util-is "^3.0.0"
unist-util-generated@^1.1.0:
version "1.1.4"
resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.4.tgz#2261c033d9fc23fae41872cdb7663746e972c1a7"
@@ -19258,10 +19596,28 @@ unist-util-remove@^1.0.0:
dependencies:
unist-util-is "^3.0.0"
unist-util-select@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/unist-util-select/-/unist-util-select-2.0.2.tgz#cb2774b599695172e7b60a8b5f50793e418f7ea6"
integrity sha512-Yv5Z5ShMxv7Z9Dw175tKvOiRVXV4FrMHG778DSD9Z0jALgb3wAx9DoeInr3200QlYp71rYUXzzJdCb76xKdrCw==
dependencies:
css-selector-parser "^1.1.0"
not "^0.1.0"
nth-check "^1.0.1"
unist-util-is "^3.0.0"
zwitch "^1.0.3"
unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c"
unist-util-stringify-position@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.1.tgz#de2a2bc8d3febfa606652673a91455b6a36fb9f3"
integrity sha512-Zqlf6+FRI39Bah8Q6ZnNGrEHUhwJOkHde2MHVk96lLyftfJJckaPslKgzhVcviXj8KcE9UJM9F+a4JEiBUTYgA==
dependencies:
"@types/unist" "^2.0.2"
unist-util-visit-parents@1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz#f6e3afee8bdbf961c0e6f028ea3c0480028c3d06"
@@ -19272,6 +19628,13 @@ unist-util-visit-parents@^2.0.0:
dependencies:
unist-util-is "^3.0.0"
unist-util-visit@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.0.tgz#1cb763647186dc26f5e1df5db6bd1e48b3cc2fb1"
integrity sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==
dependencies:
unist-util-visit-parents "^2.0.0"
unist-util-visit@^1.0.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3"
@@ -19572,6 +19935,14 @@ vfile-message@^1.0.0:
dependencies:
unist-util-stringify-position "^1.1.1"
vfile-message@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.1.tgz#951881861c22fc1eb39f873c0b93e336a64e8f6d"
integrity sha512-KtasSV+uVU7RWhUn4Lw+wW1Zl/nW8JWx7JCPps10Y9JRRIDeDXf8wfBLoOSsJLyo27DqMyAi54C6Jf/d6Kr2Bw==
dependencies:
"@types/unist" "^2.0.2"
unist-util-stringify-position "^2.0.0"
vfile@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a"
@@ -19590,6 +19961,17 @@ vfile@^3.0.0:
unist-util-stringify-position "^1.0.0"
vfile-message "^1.0.0"
vfile@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.0.1.tgz#fc3d43a1c71916034216bf65926d5ee3c64ed60c"
integrity sha512-lRHFCuC4SQBFr7Uq91oJDJxlnftoTLQ7eKIpMdubhYcVMho4781a8MWXLy3qZrZ0/STD1kRiKc0cQOHm4OkPeA==
dependencies:
"@types/unist" "^2.0.0"
is-buffer "^2.0.0"
replace-ext "1.0.0"
unist-util-stringify-position "^2.0.0"
vfile-message "^2.0.0"
vinyl-fs@^0.3.0:
version "0.3.14"
resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6"
@@ -20923,6 +21305,6 @@ zeppelin-solidity@1.8.0:
dotenv "^4.0.0"
ethjs-abi "^0.2.1"
zwitch@^1.0.0:
zwitch@^1.0.0, zwitch@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.4.tgz#93b1b993b13c8926753a41afaf8f27bbfac6be8b"