0xプロトコルのOrder Watcherを解説する（基礎編）

# モチベーション
日本語文献の無い（現時点で）0xのOrderWatcherをコードベースで解説すること。間違い、ご意見あれば[Twitter経由](https://twitter.com/WatanabeSota?lang=en)でご連絡ください。

# OrderWatcherとはなにか？
* オーダーが「valid」なのか「Invalid」なのかを追跡、管理、確認するツール。

* 特定のオーダーを追跡し、オーダーのステータスが変更されるとEventを出力され、OrderWatcherで管理できる。
* OrderaWatcherは[daemon](https://wa3.i-3-i.info/word11000.html)的な役割を果たすのでユーザーのインターフェースからは意識されることはない。
* リレイヤーがオーダーを取り除いたりトレーダーが特定のオーダーを取りに行ったりする時に使われる。例えば、 OrderWatcherが起動し、オーダーが追加されると`orderStateChange`が毎回出力される。

# 使い方
インストール
`yarn add @0x/order-watcher`

インストール後、所定のファイル内で
`import { OrderWatcher } from '@0x/order-watcher';`
をすることでorder-watcherをインポートすることができる。

# @0x/order-watcherのメソッド
### 新しいインスタンスを生成する
```Json:constructor
new OrderWatcher(
  provider: Provider, 
  networkId: number, 
  contractAddresses?: ContractAddresses, 
  partialConfig: Partial<OrderWatcherConfig> = DEFAULT_ORDER_WATCHER_CONFIG, 
): OrderWatcher
```
**Provider: JSON RPCを使用するためのWeb3プロバイダー**
**Network: オーダーが流れるネットワークID**
**contractAddress：networkIDに従ったコントラクトアドレス（任意で設定）**
**partialConfig: configuration（任意）**

### 基本的なメソッド
```json:addOrderAsync
orderWatcher.addOrderAsync(signedOrder: SignedOrder): Promise<void>
```
OrderWatcherにオーダーを追加する。オーダーを追加する前に署名が検証される。
**signedOrder: watchingしたいオーダー**


```json:getStats
orderWatcher.getStats(): Stats
```
Orderwatcherのインスタンスを確認する。

```json:removeOrder
orderWatcher.removeOrder(orderHash: string): void
```
orderWatcherからオーダーを取り除く。
**orderHash: watchingをやめたいオーダーのオーダーハッシュ**

```json:subscribe
expirationWatcher.subscribe(callback: (orderHash: string) => void): void
```

```json:unsubscribe
expirationWatcher.unsubscribe(): void
```
これ以外のメソッドは[こちら](https://0x.org/docs/order-watcher#introduction)から確認。0xプロトコルのOrder Watcherを解説する（応用編）でも書く。

### オーダーの検証
オーダーの検証は「valid」「Invalid」の2択ではなく、部分的に正しいということもありうる。つまり、部分的にfillされ、cancelされ、fillableになっているステータスなどもありうる。

例：`filled | cancelled | unfunded | fillable`

オーダーは、1つでもfillできる0でない値がある場合に、OrderWatcherによって「valid」と評価される。

上記の要項を満たすには以下の条件が必要である。

1. 正当なデータ構造であること
2. 正当な署名がある
3. 有効期限内のものである
4. 完全にfillもしくはcancelされているわけではない
5. Makerがトレードを行うのに十分な資金とAllowanceがある

validと評価されたオーダーの内、リレイヤーの採択によってどのオーダーを取り、どのオーダーを捨てるなどのロジックを作ることができる。その中でも、リレイヤーは以下の3つのロジックは確実に決めておかないといけないルールになっている。

1. 指定した値以下の部分的にfillすることのできるオーダーを受け付けるかどうか
2. 部分的にfillすることのできる値の最低値
3. griefingなどの問題を起こしたユーザーに罰則を与えるかどうか

### OrderWatcherがデフォルトでもっているコントラクトのイベント

| 0x Exchange Event | Token Type | 
|:-----------:|:------------:|
| Fill      |        | 
| Cancel     |       |   
| CancelUpTo       |         | 
| Transfer         |    ERC20 |    
| Approval       |  ERC20 |    
| Transfer    |   ERC721 | 
| Approval    |   ERC721 |  
| ApprovalForAll    |   ERC721 |  
| Deposit    |   WETH |  
| Withdraw    |   WETH |   

上記のイベントがオーダーの状態を変更すると変更記録が通知される。

### 検証記録の確認
```javascript:OrderState
type OrderState = OrderStateValid|OrderStateInvalid`
```
でオーダーが「Valid」か「Invalid」かを判断できる。

ちなみに、「Valid」の場合

```Json:OrderStateValid
{
    isValid: true,
    orderHash: string,
    orderRelevantState: OrderRelevantState,
    transactionHash: undefined|string,
}
```


「Invalid」の場合

```JSON:OrderStateInvalid
{
    error: ExchangeContractErrs,
    isValid: false,
    orderHash: string,
    transactionHash: undefined|string,
}
```

が返ってくる。

Invalidが返ってきた場合、よくある原因は

1. 有効期限切れ
2. fillされていた
3. Makerがオーダーをcancelした
4. Makerのトークン残高が0を下回った

などがある。

その他のエラーは[こちら](https://0x.org/docs/order-watcher#types-ExchangeContractErrs)から確認できる。

エラーが出たコントラクトオーダーはすぐにOrderBookより取り除いたほうが良い。

# 参考
1. [0x doc](https://0x.org/wiki#List-of-Projects-Using-0x-Protocol)
2. [daemon](https://wa3.i-3-i.info/word11000.html)
3. [OrderWatcher](https://0x.org/docs/order-watcher#introduction)