Merge branch 'feature/new-docs' of github.com:0xProject/0x-monorepo into feature/new-docs
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Introduction
|
||||
|
||||
0x is a protocol that facilitates the peer-to-peer exchange of [Ethereum](#ethereum-primer)-based assets. The protocol serves as an open standard and common building block for any developer needing exchange functionality. 0x provides secure [smart contracts](#ethereum-accounts-types) that are externally audited; [developer tools](/docs/tools) tailored to the 0x ecosystem; and open access to a [pool of shared liquidity](#networked-liquidity). Developers can integrate with 0x at the smart contract or application layer.
|
||||
0x is a protocol that facilitates the peer-to-peer exchange of [Ethereum](#ethereum-primer)-based assets. The protocol serves as an open standard and common building block for any developer needing exchange functionality. 0x provides secure [smart contracts](#ethereum-accounts-types) that are externally audited; [developer tools](/docs/tools) tailored to the 0x ecosystem; and open access to a [pool of shared liquidity](#networked-liquidity). Developers can integrate with 0x at the smart contract or application layer.
|
||||
|
||||
## What can I build on 0x?
|
||||
|
||||
@@ -31,25 +31,25 @@ A 0x order has the following fields:
|
||||
|
||||
| Field | Description |
|
||||
|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| makerAddress | The party that creates the order. The maker is also one of the two parties that will be involved in the trade if the order gets filled. |
|
||||
| takerAddress | The party that is allowed to fill the order. If set to a specific party, the order cannot be filled by anyone else. If left unspecified, anyone can fill the order. |
|
||||
| makerAssetData | Contains all the identifying information about the asset(s) the order maker is trying to sell. |
|
||||
| takerAssetData | Identifying information of the asset(s) the taker must trade in exchange for the maker's asset(s). |
|
||||
| makerAssetAmount | Amount of the maker's asset(s) being offered by the maker. |
|
||||
| takerAssetAmount | Amount of the taker's asset(s) the maker will accept in exchange for their maker asset(s). In order to calculate the price the maker is offering, one can divide the `makerAssetAmount` by the `takerAssetAmount` (the calculation is [a bit more complex](https://0x.org/docs/guides/v2-specification#assetproxy) if multiple assets are involved). |
|
||||
| expirationTimeSeconds | Timestamp in seconds of when the order expires. Expired orders cannot be filled. |
|
||||
| salt | A value that can be used to guarentee order uniqueness. Typically it is set to a random number. |
|
||||
| feeRecipientAddress | The entity that will receive any fees stipulated by the order. This is typically used to incentivize off-chain order relay. |
|
||||
| makerFee | The fee to be paid by the order maker to the `feeRecipientAddress` in the event of an order fill. Partial fills result in partial fees. |
|
||||
| takerFee | The fee to be paid by the taker to the `feeRecipientAddress` in the event of an order fill. |
|
||||
| senderAddress | An advanced field that doesn't need to be set. It allows the maker to enforce that the order flow through some additional logic before it can be filled (e.g., a KYC whitelist) -- more on the ability to extend 0x later. |
|
||||
| `makerAddress` | The party that creates the order. The maker is also one of the two parties that will be involved in the trade if the order gets filled. |
|
||||
| `takerAddress` | The party that is allowed to fill the order. If set to a specific party, the order cannot be filled by anyone else. If left unspecified, anyone can fill the order. |
|
||||
| `makerAssetData` | Contains all the identifying information about the asset(s) the order maker is trying to sell. |
|
||||
| `takerAssetData` | Identifying information of the asset(s) the taker must trade in exchange for the maker's asset(s). |
|
||||
| `makerAssetAmount` | Amount of the maker's asset(s) being offered by the maker. |
|
||||
| `takerAssetAmount` | Amount of the taker's asset(s) the maker will accept in exchange for their maker asset(s). In order to calculate the price the maker is offering, one can divide the `makerAssetAmount` by the `takerAssetAmount` (the calculation is [a bit more complex](https://0x.org/docs/guides/v2-specification#assetproxy) if multiple assets are involved). |
|
||||
| `expirationTimeSeconds` | Timestamp in seconds of when the order expires. Expired orders cannot be filled. |
|
||||
| `salt` | A value that can be used to guarentee order uniqueness. Typically it is set to a random number. |
|
||||
| `feeRecipientAddress` | The entity that will receive any fees stipulated by the order. This is typically used to incentivize off-chain order relay. |
|
||||
| `makerFee` | The fee to be paid by the order maker to the `feeRecipientAddress` in the event of an order fill. Partial fills result in partial fees. |
|
||||
| `takerFee` | The fee to be paid by the taker to the `feeRecipientAddress` in the event of an order fill. |
|
||||
| `senderAddress` | An advanced field that doesn't need to be set. It allows the maker to enforce that the order flow through some additional logic before it can be filled (e.g., a KYC whitelist) -- more on the ability to extend 0x later. |
|
||||
|
||||
The 0x order message format is rigid enough to enforce the conditions under which an order maker would feel comfortable entering into a trade and yet flexible enough to represent many different kinds of trades. Currently, 0x supports trading:
|
||||
|
||||
### 1. [Fungible](https://www.investopedia.com/terms/f/fungibility.asp) tokens (those conforming to the [ERC20 standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md))
|
||||
|
||||
**Examples:**
|
||||
|
||||
|
||||
| Utility Tokens | Stable coins | Fiat-backed tokens | Crypto-backed tokens | In-game currencies | Securities |
|
||||
|-----------------------------------------------------------------|------------------------------------|-------------------------------------------------------------------------------------|--------------------------------------------------------------------------------|---------------------------------------------------|------------|
|
||||
| [Ether](https://blog.0xproject.com/canonical-weth-a9aa7d0279dd) | [Dai](https://makerdao.com/en/dai) | [USDC](https://www.coinbase.com/usdc) | [WBTC](https://www.wbtc.network/) | [MANA in Decentraland](https://decentraland.org/) | TBA |
|
||||
@@ -57,7 +57,7 @@ The 0x order message format is rigid enough to enforce the conditions under whic
|
||||
| [Augur REP](https://www.augur.net/) | | [Tether EUR](https://etherscan.io/token/0xabdf147870235fcfc34153828c769a70b3fae01f) | [vEOS](https://etherscan.io/token/0x8055f300b7d209ace52dc16a49352d301b2fcce2) | | |
|
||||
| [Livepeer Token](https://livepeer.org/) | | [XCHF](https://etherscan.io/token/0xb4272071ecadd69d933adcd19ca99fe80664fc08) | [vAtom](https://etherscan.io/token/0xc5637328da2e0a3400274a4088cea2e25fb91446) | | |
|
||||
|
||||
|
||||
|
||||
### 2. [Non-fungible]() tokens (Those conforming to the [ERC721 standard](http://erc721.org/))
|
||||
|
||||
**Examples:**
|
||||
@@ -83,7 +83,7 @@ A [cryptographic hash function](https://en.wikipedia.org/wiki/Cryptographic_hash
|
||||
|
||||
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 a 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's fields.
|
||||
|
||||

|
||||
<Image src="/images/docs/hashing.svg" align="center" alt="Hashing" width="350px" padding="20px" marginBottom="3rem" />
|
||||
|
||||
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 succinct representation of their 0x order.
|
||||
|
||||
@@ -96,25 +96,25 @@ A [digital signature](https://en.wikipedia.org/wiki/Digital_signature) is a math
|
||||
|
||||
0x uses a digital signature to allow order makers to cryptographically commit to the 0x order they author. This allows the maker to rest assured that they cannot be tricked into filling any order except the ones they've authored. In turn, the potential counter-parties can verify that the maker did indeed author their 0x order(s).
|
||||
|
||||

|
||||
<Image src="/images/docs/signing.svg" align="center" alt="Signing" width="625px" padding="20px" marginBottom="3rem" />
|
||||
|
||||
For a 0x order to be considered valid and fillable, it must have all the stipulated fields mentioned above and include a digital signature from the maker attesting to all the chosen 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 has been created by the maker and has not yet left their computer. In order for a trade to occur, the maker must find someone willing to take the other side of the trade. 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.
|
||||
Up until this point, the 0x order has been created by the maker and has not yet left their computer. In order for a trade to occur, the maker must find someone willing to take the other side of the trade. 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, chat or an over-the-counter platform). If the maker doesn't know 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 0x orders. Existing relayers can be found by browsing the [Explore 0x](https://0x.org/explore) 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 protocol's 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 however, the fill request is rejected.
|
||||
|
||||
<Animation name="onOff" />
|
||||
<Animation name="onOff" marginBottom="3rem" />
|
||||
|
||||
## A non-custodial exchange protocol
|
||||
|
||||
Centralized exchanges require traders to deposit the assets they wish to trade with the exchange. From this point onwards, the exchange has full custody over the assets and the trader can only trade with other traders at that specific exchange. Centralized exchanges become large targets for hackers because they aggregate the assets of all their users into one place. There have been [over $1.5 billion stolen](https://discover.ledger.com/hackstimeline/) from centralized exchanges in the last 10 years. In response to this, the 0x protocol enables developers to build non-custodial exchanges; ones that never take custody over traders assets. Instead, the assets are settled directly between the two trader's wallets when an order is filled. This drastically reduces the counter-party risk involved with exchanging assets. Traders only need to trust a small amount of the 0x protocol source code running on the blockchain. All source code with the priviledge to move trader funds is open source, immutable and verifiable on-chain.
|
||||
|
||||
<Animation name="cexDex" />
|
||||
<Animation name="cexDex" padding="20px" marginBottom="3rem" />
|
||||
|
||||
## Networked liquidity
|
||||
|
||||
@@ -124,7 +124,7 @@ In order to help relayers share liquidity, the 0x core team has published [a sta
|
||||
|
||||
In addition to an API standard, the 0x core team is also building [0x Mesh](https://0x-org.gitbook.io/mesh/), a peer-to-peer network for sharing 0x orders. Anyone can [spin up a Mesh node](https://github.com/0xProject/0x-mesh/) and immediately start sharing 0x orders with others in the ecosystem. We hope to enable the creation of a globally accessible, physically distributed orderbook with more liquidity then any single centralized exchange.
|
||||
|
||||
<Animation name="mesh" />
|
||||
<Animation name="mesh" padding="30px" />
|
||||
|
||||
## Extending the 0x protocol
|
||||
|
||||
@@ -132,13 +132,13 @@ By design, the 0x protocol is built to be highly modular and extensible. Some ch
|
||||
|
||||
Another type of the 0x protocol extension that does not require any kind of approval to be used are aptly called [0x extensions](https://0x.org/extensions). 0x extensions add arbitrary logic that 0x orders must flow through before they can get filled or cancelled.
|
||||
|
||||

|
||||
<Image src="/images/docs/extension.png" align="center" alt="Extensions" width="700px" padding="20px" marginBottom="3rem" />
|
||||
|
||||
Examples of the types of features this enables are trading whitelists (KYC, invite-only, etc...), [Dutch auctions](https://0x.org/docs/guides/0x-extensions-explained#dutch-auction-contract) and [trade coordinators](https://0x.org/docs/guides/v2-coordinatior-specification) to name a few. We are just beginning to see the innovation this ability to permissionlessly extend the 0x protocol will unleash.
|
||||
|
||||
## Up next
|
||||
|
||||
We hope this conceptual overview of 0x was helpful in giving you a better understanding of what the 0x protocol is and the fundamental building blocks it provides developers (e.g., a standard order format, non-custodial trading/settlement, a shared liquidity pool and 0x extensions). In the next section we will dive deeper into the current technical implementation of the 0x protocol.
|
||||
We hope this conceptual overview of 0x was helpful in giving you a better understanding of what the 0x protocol is and the fundamental building blocks it provides developers (e.g., a standard order format, non-custodial trading/settlement, a shared liquidity pool and 0x extensions). In the next section we will dive deeper into the current technical implementation of the 0x protocol.
|
||||
|
||||
# 0x and Ethereum development
|
||||
|
||||
@@ -162,7 +162,7 @@ An EOA is an Ethereum account that is directly controlled by a human being. Both
|
||||
|
||||
A smart contract account is generated everytime a smart contract program is deployed to the blockchain. The contract code lives at this address. In order to invoke a function defined within a smart contract program, one must send a transaction to it's address. The transaction will also specify which function of this program the caller wishes to invoke, along with which parameters to supply. E.g., when filling an order using 0x, the taker will send an Etherem transaction to the 0x exchange contract address, specifying it should invoke the `fillOrder` function, and supply as parameters the order they want filled, and how much they want to fill it for.
|
||||
|
||||

|
||||
<Image src="/images/docs/eoa_smart_contract.svg" align="center" alt="EOA vs Smart Contract" width="650px" padding="20px" marginBottom="2.5rem" />
|
||||
|
||||
## Gas
|
||||
|
||||
@@ -251,22 +251,22 @@ Once all these fields are gathered, they are [hashed](https://en.wikipedia.org/w
|
||||
|
||||
## Subscribing to smart contract events
|
||||
|
||||
As a 0x developer, there might be times when you need to get notified when a state change occurs on-chain. For example, you might want to get an update as soon as orders from a specific maker get filled or cancelled. Ethereum let's smart contracts emit events during execution. These events can then be subscribed to and processed by your application.
|
||||
As a 0x developer, there might be times when you need to get notified when a state change occurs on-chain. For example, you might want to get an update as soon as orders from a specific maker get filled or cancelled. Ethereum let's smart contracts emit events during execution. These events can then be subscribed to and processed by your application.
|
||||
|
||||
Example 0x event:
|
||||
```solidity
|
||||
// Fill event is emitted whenever an order is filled.
|
||||
event Fill(
|
||||
address indexed makerAddress, // Address that created the order.
|
||||
address indexed makerAddress, // Address that created the order.
|
||||
address indexed feeRecipientAddress, // Address that received fees.
|
||||
address takerAddress, // Address that filled the order.
|
||||
address senderAddress, // Address that called the Exchange contract (msg.sender).
|
||||
uint256 makerAssetFilledAmount, // Amount of makerAsset sold by maker and bought by taker.
|
||||
uint256 makerAssetFilledAmount, // Amount of makerAsset sold by maker and bought by taker.
|
||||
uint256 takerAssetFilledAmount, // Amount of takerAsset sold by taker and bought by maker.
|
||||
uint256 makerFeePaid, // Amount of ZRX paid to feeRecipient by maker.
|
||||
uint256 takerFeePaid, // Amount of ZRX paid to feeRecipient by taker.
|
||||
bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash).
|
||||
bytes makerAssetData, // Encoded data specific to makerAsset.
|
||||
bytes makerAssetData, // Encoded data specific to makerAsset.
|
||||
bytes takerAssetData // Encoded data specific to takerAsset.
|
||||
);
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
0x Instant is a product from the 0x core team that offers a convenient way for people to get access to a wide variety of tokens and other crypto-assets in just a few clicks. Developers can integrate the free, open source library into their applications or websites in order to both offer seamless access to crypto-assets, as well as gain a new source of revenue, with just a few lines of code.
|
||||
|
||||

|
||||
<Image src="https://s3.eu-west-2.amazonaws.com/0x-wiki-images/instant_screenshot.png" align="center" alt="0x Instant" width="350px" padding="20px" marginBottom="40px"/>
|
||||
|
||||
Check out a live example on [mainnet](http://0x-instant-staging.s3-website-us-east-1.amazonaws.com/) and [kovan](http://0x-instant-staging.s3-website-us-east-1.amazonaws.com/?networkId=42&assetData=0xf47261b00000000000000000000000002002d3812f58e35f0ea1ffbf80a75a38c32175fa&liquiditySource=provided).
|
||||
|
||||
@@ -55,23 +55,23 @@ Codepen [example](https://codepen.io/bmillman19/pen/qQzQQK)
|
||||
|
||||
| Option | Description |
|
||||
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| orderSource | Accepts either a [Standard Relayer API HTTP endpoint](https://github.com/0xProject/standard-relayer-api/blob/master/http/v2.md) or an array of signed 0x [orders](https://0x.org/docs/tools/order-utils#types-SignedOrder) |
|
||||
| `orderSource` | Accepts either a [Standard Relayer API HTTP endpoint](https://github.com/0xProject/standard-relayer-api/blob/master/http/v2.md) or an array of signed 0x [orders](https://0x.org/docs/tools/order-utils#types-SignedOrder) |
|
||||
|
||||
## Optional
|
||||
|
||||
| Option | Description |
|
||||
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| provider | An instance of an Ethereum [provider](#faqs), but teams may optionally source liquidity themselves and pass in specific [SignedOrders](#faqs). If none is provided, 0x instant will try to grab the injected provider if one exists, otherwise it will suggest the user to install MetaMask |
|
||||
| walletDisplayName | A display string for the wallet you are connected to. Defaults to our best guess (i.e. MetaMask, Coinbase Wallet) but should be provided if a custom provider is supplied as an optional config. |
|
||||
| availableAssetDatas | An array of [assetDatas](#faqs), but teams may optionally source liquidity themselves and pass in specific [SignedOrders](#faqs) that can be purchased through Instant. Defaults to all token pairs from orderSource. Will throw an error if empty. |
|
||||
| defaultSelectedAssetData | The asset that should be opened by default. If this is not provided, Instant will show "Select Token" if there are multiple availableAssetDatas. |
|
||||
| defaultAssetBuyAmount | Pre-fill the amount of tokens to purchase. Defaults to 0. |
|
||||
| additionalAssetMetaDataMap | An object with keys that are assetData strings and values that are objects that adhere to the [AssetMetaData schema](#faqs), but teams may optionally source liquidity themselves and pass in specific [SignedOrders](#faqs). The values represent the meta data for that asset. There is an internal mapping for popular tokens that cannot be overriden and only appended to using this configuration option. |
|
||||
| networkId | Id of Ethereum network to connect to. Defaults to 1 (mainnet). |
|
||||
| affiliateInfo | An object specifying what % ETH fee should be added to orders and where the fee should be sent. Max feePercentage is .05 (See examples below) |
|
||||
| shouldDisableAnalyticsTracking | An option to turn on / off analytics used to make Instant a better experience. Defaults to false. |
|
||||
| onSuccess | a function handler that is called when the token purchase through 0x Instant is complete. The function handler requests one argument: the transaction hash. |
|
||||
| onClose | a function handler that is called when the Instant overlay is closed. The function handler does not request any argument |
|
||||
| `provider` | An instance of an Ethereum [provider](#faqs), but teams may optionally source liquidity themselves and pass in specific [SignedOrders](#faqs). If none is provided, 0x instant will try to grab the injected provider if one exists, otherwise it will suggest the user to install MetaMask |
|
||||
| `walletDisplayName` | A display string for the wallet you are connected to. Defaults to our best guess (i.e. MetaMask, Coinbase Wallet) but should be provided if a custom provider is supplied as an optional config. |
|
||||
| `availableAssetDatas` | An array of [assetDatas](#faqs), but teams may optionally source liquidity themselves and pass in specific [SignedOrders](#faqs) that can be purchased through Instant. Defaults to all token pairs from orderSource. Will throw an error if empty. |
|
||||
| `defaultSelectedAssetData` | The asset that should be opened by default. If this is not provided, Instant will show "Select Token" if there are multiple availableAssetDatas. |
|
||||
| `defaultAssetBuyAmount` | Pre-fill the amount of tokens to purchase. Defaults to 0. |
|
||||
| `additionalAssetMetaDataMap` | An object with keys that are assetData strings and values that are objects that adhere to the [AssetMetaData schema](#faqs), but teams may optionally source liquidity themselves and pass in specific [SignedOrders](#faqs). The values represent the meta data for that asset. There is an internal mapping for popular tokens that cannot be overriden and only appended to using this configuration option. |
|
||||
| `networkId` | Id of Ethereum network to connect to. Defaults to 1 (mainnet). |
|
||||
| `affiliateInfo` | An object specifying what % ETH fee should be added to orders and where the fee should be sent. Max feePercentage is .05 (See examples below) |
|
||||
| `shouldDisableAnalyticsTracking` | An option to turn on / off analytics used to make Instant a better experience. Defaults to false. |
|
||||
| `onSuccess` | a function handler that is called when the token purchase through 0x Instant is complete. The function handler requests one argument: the transaction hash. |
|
||||
| `onClose` | a function handler that is called when the Instant overlay is closed. The function handler does not request any argument |
|
||||
|
||||
# Examples
|
||||
|
||||
@@ -502,4 +502,3 @@ For apps using React Native or apps that have a web view, the asset buyer engine
|
||||
### Q: How do I make money as an affiliate?
|
||||
|
||||
If you host 0x Instant, you can designate an address that you own to receive a small % of ETH that users spend on assets. The fee percent maxes out at 5%. You can configure this in the AffiliateInfo setting.
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
"cache-loader": "^4.1.0",
|
||||
"compare-versions": "^3.5.1",
|
||||
"css-loader": "0.23.x",
|
||||
"extend": "^3.0.2",
|
||||
"glob": "^7.1.4",
|
||||
"json-stringify-pretty-compact": "^2.0.0",
|
||||
"less-loader": "^4.1.0",
|
||||
@@ -149,6 +150,7 @@
|
||||
"unist-util-find-after": "^2.0.4",
|
||||
"unist-util-modify-children": "^1.1.4",
|
||||
"unist-util-select": "^2.0.2",
|
||||
"unist-util-visit": "^2.0.0",
|
||||
"unist-util-visit-parents": "^3.0.0",
|
||||
"webpack": "^4.39.2",
|
||||
"webpack-cli": "3.3.7",
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 51 KiB |
66
packages/website/public/images/docs/hashing.svg
generated
66
packages/website/public/images/docs/hashing.svg
generated
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 27 KiB |
91
packages/website/public/images/docs/signing.svg
generated
91
packages/website/public/images/docs/signing.svg
generated
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 48 KiB |
@@ -1,7 +1,35 @@
|
||||
import styled from 'styled-components';
|
||||
import { Heading } from 'ts/components/text';
|
||||
|
||||
const H1 = styled(Heading).attrs({
|
||||
const MDXHeading = styled(Heading)`
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
.heading-link-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.heading-link-icon {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
position: absolute;
|
||||
transform: translateY(-50%);
|
||||
top: 50%;
|
||||
left: -26px;
|
||||
padding-right: 26px;
|
||||
|
||||
opacity: 0;
|
||||
transition: opacity 200ms ease-in-out;
|
||||
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' %3E%3Cpath d='M15 7h3a5 5 0 0 1 5 5 5 5 0 0 1-5 5h-3m-6 0H6a5 5 0 0 1-5-5 5 5 0 0 1 5-5h3M8 12h8'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
`;
|
||||
|
||||
const H1 = styled(MDXHeading).attrs({
|
||||
size: 34,
|
||||
asElement: 'h1',
|
||||
marginBottom: '1rem',
|
||||
@@ -12,32 +40,32 @@ const H1 = styled(Heading).attrs({
|
||||
}
|
||||
`;
|
||||
|
||||
const H2 = styled(Heading).attrs({
|
||||
const H2 = styled(MDXHeading).attrs({
|
||||
size: 'default',
|
||||
asElement: 'h2',
|
||||
marginBottom: '1rem',
|
||||
})``;
|
||||
|
||||
const H3 = styled(Heading).attrs({
|
||||
const H3 = styled(MDXHeading).attrs({
|
||||
size: 'small',
|
||||
asElement: 'h3',
|
||||
fontWeight: '300',
|
||||
marginBottom: '1rem',
|
||||
})``;
|
||||
|
||||
const H4 = styled(Heading).attrs({
|
||||
const H4 = styled(MDXHeading).attrs({
|
||||
asElement: 'h4',
|
||||
fontWeight: '300',
|
||||
marginBottom: '1rem',
|
||||
})``;
|
||||
|
||||
const H5 = styled(Heading).attrs({
|
||||
const H5 = styled(MDXHeading).attrs({
|
||||
asElement: 'h5',
|
||||
fontWeight: '300',
|
||||
marginBottom: '1rem',
|
||||
})``;
|
||||
|
||||
const H6 = styled(Heading).attrs({
|
||||
const H6 = styled(MDXHeading).attrs({
|
||||
asElement: 'h6',
|
||||
fontWeight: '300',
|
||||
marginBottom: '1rem',
|
||||
|
||||
@@ -38,7 +38,7 @@ export const TableOfContents: React.FC<ITableOfContentsProps> = ({ contents, ver
|
||||
|
||||
const Contents: React.FC<ITableOfContentsProps> = ({ contents }) => {
|
||||
return (
|
||||
<ContentsList>
|
||||
<ul>
|
||||
{contents.map(content => {
|
||||
const { children, id, level, title } = content;
|
||||
|
||||
@@ -58,16 +58,10 @@ const Contents: React.FC<ITableOfContentsProps> = ({ contents }) => {
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ContentsList>
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
const ContentsList = styled.ul`
|
||||
ul {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
`;
|
||||
|
||||
const ContentLink = styled(Link)<{ level: number }>`
|
||||
display: inline-block;
|
||||
|
||||
@@ -91,8 +85,7 @@ const ContentLink = styled(Link)<{ level: number }>`
|
||||
`
|
||||
font-size: 0.8333rem;
|
||||
line-height: 1.5;
|
||||
margin-bottom: .5rem;
|
||||
|
||||
margin: .4rem 0;
|
||||
`}
|
||||
|
||||
${({ level }) =>
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
},
|
||||
"tools": {
|
||||
"asset-swapper": {
|
||||
"title": "@0x/asset-swapper",
|
||||
"title": "0x Asset Swapper",
|
||||
"description": "Convenience package for discovering and performing swaps for any ERC20 Assets",
|
||||
"difficulty": "Intermediate",
|
||||
"isCommunity": false,
|
||||
@@ -175,7 +175,7 @@
|
||||
"externalUrl": "https://www.npmjs.com/package/0x.js"
|
||||
},
|
||||
"connect": {
|
||||
"title": "@0x/connect",
|
||||
"title": "0x Connect",
|
||||
"description": "An HTTP/WS client for interacting with the Standard Relayer API",
|
||||
"difficulty": "Beginner",
|
||||
"isCommunity": false,
|
||||
@@ -197,7 +197,7 @@
|
||||
"versions": ["v5.0.2"]
|
||||
},
|
||||
"asset-buyer": {
|
||||
"title": "@0x/asset-buyer",
|
||||
"title": "0x Asset Buyer (Deprecated)",
|
||||
"description": "Convenience package for discovering and buying assets with Ether",
|
||||
"difficulty": "Intermediate",
|
||||
"isCommunity": false,
|
||||
@@ -330,7 +330,7 @@
|
||||
"type": "Typescript Libraries"
|
||||
},
|
||||
"radar-relay-sdk": {
|
||||
"title": "RadarRelay SDK",
|
||||
"title": "Radar Relay SDK",
|
||||
"description": "The Radar Relay SDK is a software development kit that simplifies the interactions with Radar Relay’s APIs",
|
||||
"difficulty": "Beginner",
|
||||
"externalUrl": "https://developers.radarrelay.com/libraries/sdk",
|
||||
@@ -350,7 +350,7 @@
|
||||
"type": "Typescript Libraries"
|
||||
},
|
||||
"ganache-cli": {
|
||||
"title": "0xorg/ganache-cli",
|
||||
"title": "Ganache CLI",
|
||||
"description": "Spin up a Ganache test Ethereum node with the 0x smart contracts pre-deployed",
|
||||
"difficulty": "Beginner",
|
||||
"isCommunity": false,
|
||||
@@ -360,7 +360,7 @@
|
||||
"externalUrl": "https://hub.docker.com/r/0xorg/ganache-cli"
|
||||
},
|
||||
"launch-kit-backend-docker": {
|
||||
"title": "0xorg/launch-kit-backend",
|
||||
"title": "0x Launch Kit Backend",
|
||||
"description": "A pre-built Standard Relayer API backend server",
|
||||
"difficulty": "Beginner",
|
||||
"isCommunity": false,
|
||||
@@ -370,7 +370,7 @@
|
||||
"externalUrl": "https://hub.docker.com/r/0xorg/launch-kit-backend"
|
||||
},
|
||||
"launch-kit-frontend-docker": {
|
||||
"title": "0xorg/launch-kit-frontend",
|
||||
"title": "0x Launch Kit Front-end",
|
||||
"description": "An ERC20 exchange and ERC721 marketplace React front-end to use with any SRA API backend",
|
||||
"difficulty": "Beginner",
|
||||
"isCommunity": false,
|
||||
@@ -380,7 +380,7 @@
|
||||
"externalUrl": "https://hub.docker.com/r/0xorg/launch-kit-frontend"
|
||||
},
|
||||
"launch-kit-demo": {
|
||||
"title": "0xorg/launch-kit-demo",
|
||||
"title": "0x Launch Kit Demo",
|
||||
"description": "A demo of the front-end and backend Launch Kits running together",
|
||||
"difficulty": "Beginner",
|
||||
"isCommunity": false,
|
||||
@@ -390,7 +390,7 @@
|
||||
"externalUrl": "https://hub.docker.com/r/0xorg/launch-kit-demo"
|
||||
},
|
||||
"mesh": {
|
||||
"title": "0xorg/mesh",
|
||||
"title": "0x Mesh",
|
||||
"description": "A peer-to-peer network for sharing 0x orders",
|
||||
"difficulty": "Beginner",
|
||||
"isCommunity": false,
|
||||
@@ -410,7 +410,7 @@
|
||||
"externalUrl": "https://pypi.org/project/0x-contract-wrappers/"
|
||||
},
|
||||
"0x-order-utils": {
|
||||
"title": "0x-order-utils",
|
||||
"title": "0x Order Utilities",
|
||||
"description": "A set of utilities for generating, parsing, signing and validating 0x orders in Python",
|
||||
"difficulty": "Beginner",
|
||||
"isCommunity": false,
|
||||
@@ -420,7 +420,7 @@
|
||||
"externalUrl": "https://pypi.org/project/0x-order-utils/"
|
||||
},
|
||||
"0x-sra-client": {
|
||||
"title": "0x-sra-client",
|
||||
"title": "0x SRA Client",
|
||||
"description": "A Python client for interacting with servers conforming to the Standard Relayer API specification",
|
||||
"difficulty": "Beginner",
|
||||
"isCommunity": false,
|
||||
@@ -456,7 +456,7 @@
|
||||
"isCommunity": false,
|
||||
"isFeatured": false,
|
||||
"tags": ["Relayer"],
|
||||
"type": "Starter projects",
|
||||
"type": "Starter Projects",
|
||||
"externalUrl": "https://github.com/0xProject/0x-launch-kit-frontend/"
|
||||
},
|
||||
"launch-kit-backend": {
|
||||
@@ -466,7 +466,7 @@
|
||||
"isCommunity": false,
|
||||
"isFeatured": false,
|
||||
"tags": ["Relayer"],
|
||||
"type": "Starter projects",
|
||||
"type": "Starter Projects",
|
||||
"externalUrl": "https://github.com/0xProject/0x-launch-kit-backend/"
|
||||
},
|
||||
"starter-project": {
|
||||
@@ -476,7 +476,7 @@
|
||||
"isCommunity": false,
|
||||
"isFeatured": false,
|
||||
"tags": ["Relayer", "Trader", "Protocol Developer"],
|
||||
"type": "Starter projects",
|
||||
"type": "Starter Projects",
|
||||
"externalUrl": "https://github.com/0xProject/0x-starter-project"
|
||||
},
|
||||
"code-sandbox": {
|
||||
@@ -486,7 +486,7 @@
|
||||
"isCommunity": false,
|
||||
"isFeatured": true,
|
||||
"tags": ["Relayer", "Trader", "Protocol Developer"],
|
||||
"type": "Starter projects",
|
||||
"type": "Starter Projects",
|
||||
"externalUrl": "https://codesandbox.io/s/github/0xproject/0x-codesandbox"
|
||||
},
|
||||
"migrations": {
|
||||
@@ -501,7 +501,7 @@
|
||||
"versions": ["v4.3.0"]
|
||||
},
|
||||
"launch-kit-wizard": {
|
||||
"title": "@0x/launch-kit-wizard",
|
||||
"title": "Launch Kit Wizard",
|
||||
"description": "A “create-react-app”-style CLI for spinning up a 0x Relayer",
|
||||
"difficulty": "Beginner",
|
||||
"isCommunity": false,
|
||||
@@ -527,7 +527,7 @@
|
||||
"isCommunity": false,
|
||||
"isFeatured": false,
|
||||
"tags": ["Relayer"],
|
||||
"type": "Starter projects",
|
||||
"type": "Starter Projects",
|
||||
"externalUrl": "https://github.com/0xProject/0x-coordinator-server"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ const TerserPlugin = require('terser-webpack-plugin');
|
||||
const RollbarSourceMapPlugin = require('rollbar-sourcemap-webpack-plugin');
|
||||
const childProcess = require('child_process');
|
||||
const remarkSlug = require('remark-slug');
|
||||
const remarkAutolinkHeadings = require('./webpack/remark_autolink_headings');
|
||||
const remarkSectionizeHeadings = require('./webpack/remark_sectionize_headings');
|
||||
const mdxTableOfContents = require('./webpack/mdx_table_of_contents');
|
||||
|
||||
@@ -65,7 +66,7 @@ const config = {
|
||||
{
|
||||
loader: '@mdx-js/loader',
|
||||
options: {
|
||||
remarkPlugins: [remarkSlug, remarkSectionizeHeadings],
|
||||
remarkPlugins: [remarkSlug, remarkAutolinkHeadings, remarkSectionizeHeadings],
|
||||
compilers: [mdxTableOfContents],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -61,11 +61,14 @@ function isSlugifiedSection(node) {
|
||||
}
|
||||
|
||||
function toFragment(nodes) {
|
||||
if (nodes.length === 1 && nodes[0].type === 'text') {
|
||||
return JSON.stringify(nodes[0].value);
|
||||
} else {
|
||||
return '<React.Fragment>' + nodes.map(toJSX).join('') + '</React.Fragment>';
|
||||
// Because of autolinking headings earlier (at remark stage), the headings (nodes)
|
||||
// contain an anchor tag next to the title, we only want to render the text.
|
||||
// Unless there is no text, then we render whatever nodes we get in a Fragment
|
||||
const textNode = nodes.find(node => node.type === 'text');
|
||||
if (textNode) {
|
||||
return JSON.stringify(textNode.value);
|
||||
}
|
||||
return '<React.Fragment>' + nodes.map(toJSX).join('') + '</React.Fragment>';
|
||||
}
|
||||
|
||||
function tableOfContentsListSerializer(nodes, indent = 0) {
|
||||
|
||||
45
packages/website/webpack/remark_autolink_headings.js
Normal file
45
packages/website/webpack/remark_autolink_headings.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const visit = require('unist-util-visit');
|
||||
const extend = require('extend');
|
||||
|
||||
const content = {
|
||||
type: 'element',
|
||||
tagName: 'i',
|
||||
properties: { className: ['heading-link-icon'] },
|
||||
};
|
||||
|
||||
const linkProperties = { ariaHidden: 'true' };
|
||||
|
||||
const hChildren = Array.isArray(content) ? content : [content];
|
||||
|
||||
module.exports = plugin;
|
||||
|
||||
function plugin() {
|
||||
return transform;
|
||||
}
|
||||
|
||||
function transform(tree) {
|
||||
visit(tree, 'heading', visitor);
|
||||
}
|
||||
|
||||
function visitor(node) {
|
||||
const { data } = node;
|
||||
const id = data && data.hProperties && data.hProperties.id;
|
||||
const url = '#' + id;
|
||||
|
||||
if (id) {
|
||||
inject(node, url);
|
||||
}
|
||||
}
|
||||
|
||||
function inject(node, url) {
|
||||
node.children.unshift({
|
||||
type: 'link',
|
||||
url,
|
||||
title: null,
|
||||
children: [],
|
||||
data: {
|
||||
hProperties: extend(true, {}, linkProperties),
|
||||
hChildren: extend(true, [], hChildren),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
const findAfter = require('unist-util-find-after');
|
||||
const visit = require('unist-util-visit-parents');
|
||||
|
||||
const MAX_HEADING_DEPTH = 6;
|
||||
const MAX_HEADING_DEPTH = 2;
|
||||
|
||||
module.exports = plugin;
|
||||
|
||||
@@ -19,14 +19,18 @@ function sectionize(node, ancestors) {
|
||||
const start = node;
|
||||
const parent = ancestors[ancestors.length - 1];
|
||||
|
||||
const isEnd = node => node.type === 'heading' && node.depth <= start.depth;
|
||||
const isEnd = node => {
|
||||
if (start.depth < MAX_HEADING_DEPTH) {
|
||||
return node.type === 'section' || (node.type === 'heading' && node.depth <= start.depth);
|
||||
}
|
||||
return node.type === 'heading' && node.depth <= start.depth;
|
||||
};
|
||||
const end = findAfter(parent, start, isEnd);
|
||||
|
||||
const startIndex = parent.children.indexOf(start);
|
||||
const endIndex = parent.children.indexOf(end);
|
||||
|
||||
const between = parent.children.slice(startIndex, endIndex > 0 ? endIndex : undefined);
|
||||
|
||||
// We want to grab the ids created by remark-slug based on heading values
|
||||
// node (heading) data has this shape now:
|
||||
// { hProperties: { id: 'some-id' }, id: 'some-id' } }
|
||||
|
||||
@@ -8903,9 +8903,10 @@ extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
|
||||
|
||||
extend@~3.0.2:
|
||||
extend@^3.0.2, extend@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||
|
||||
external-editor@^2.0.4:
|
||||
version "2.2.0"
|
||||
@@ -20723,7 +20724,7 @@ unist-util-visit-parents@^3.0.0:
|
||||
"@types/unist" "^2.0.3"
|
||||
unist-util-is "^4.0.0"
|
||||
|
||||
unist-util-visit@2.0.0:
|
||||
unist-util-visit@2.0.0, unist-util-visit@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.0.tgz#1fdae5ea88251651bfe49b7e84390d664fc227c5"
|
||||
integrity sha512-kiTpWKsF54u/78L/UU/i7lxrnqGiEWBgqCpaIZBYP0gwUC+Akq0Ajm4U8JiNIoQNfAioBdsyarnOcTEAb9mLeQ==
|
||||
|
||||
Reference in New Issue
Block a user