GolangでQuoineのAPIを使ってみた

#はじめに
最近UdemyでGolangを勉強しているのですが、応用編のビットコイン自動売買の講義でbitflyerのアカウントがなく実際に売買できないってなったので代わりにみつけたQuoine APIを使って講義を受けています。

実際に動くものを書きながら講義を受けたほうが理解が深まりやすいと思ったので、初めてですが記事を書いてみることにしました。
こちらのかたの講座です。
https://www.udemy.com/share/100BhMBEsZeF9QQn4=/

#Liquid by Quoineについて
bitflyerの持っていない方はアカウントを作れない現状（2019年3月）これ以外特に選択肢がないように思えます。
現物取引が手数料無料なので、bitflyerをお持ちの方にもliquidがおすすめです。

#アカウントの準備
https://www.liquid.com/

こちらでアカウントを作成してAPIのIDとキーを取得してください。
こちらはググれば出てくるので割愛します。

#APIをGoで書いてみる
APIのリファレンスです。
https://developers.quoine.com/

##LiquidAPIの認証
```quoine.go
type APIClient struct {
	key        string
	secret     string
	httpClient *http.Client
}

// header リクエストに追加するヘッダー情報
func (api APIClient) header(method, endpoint string, body []byte) map[string]string {
	token := jwt.New(jwt.GetSigningMethod("HS256"))
	token.Claims = jwt.MapClaims{
		"path":     endpoint,
		"nonce":    strconv.FormatInt(time.Now().Unix(), 10),
		"token_id": "APIキーをここに",
	}
	signature, _ := token.SignedString([]byte("APIシークレットをここに"))
	return map[string]string{
		"X-Quoine-Auth":        signature,
		"X-Quoine-API-Version": "2",
		"Content-Type":         "application/json",
	}
}

```

すみません。JWTについてはよく分からなかったのでgithub.com/dgrijalva/jwt-goを使いました。

##残高の取得

```quoine.go
type Balance struct {
	Currency string `json:"currency"`
	Balance  string `json:"balance"`
}

// GetBalances 現在の総合資産を取得する
func (api *APIClient) GetBalances() []Balance {
	url := "/accounts/balance"
	var balances []Balance
	resp, err := api.doRequest("GET", url, nil, nil)
	if err != nil {
		log.Printf("action=GETBalances err=%s", err.Error())
		return balances
	}
	err = json.Unmarshal(resp, &balances)
	if err != nil {
		log.Printf("action=GETBalances(unmarshal) err=%s", err.Error())
		return balances
	}
	return balances
}

```

#注文

```quoine.go
// Order 注文
type Order struct {
	OrderType string `json:"order_type"`
	ProductID int    `json:"product_id"`
	Side      string `json:"side"`
	Quantity  string `json:"quantity"`
	Price     string `json:"price"`
}

// ResponseSendChildOrder 注文のレスポンス情報
type ResponseSendChildOrder struct {
	ID                   int         `json:"id"`
	OrderType            string      `json:"order_type"`
	Quantity             string      `json:"quantity"`
	DiscQuantity         string      `json:"disc_quantity"`
	IcebergTotalQuantity string      `json:"iceberg_total_quantity"`
	Side                 string      `json:"side"`
	FilledQuantity       string      `json:"filled_quantity"`
	Price                float64     `json:"price"`
	CreatedAt            int         `json:"created_at"`
	UpdatedAt            int         `json:"updated_at"`
	Status               string      `json:"status"`
	LeverageLevel        int         `json:"leverage_level"`
	SourceExchange       string      `json:"source_exchange"`
	ProductID            int         `json:"product_id"`
	ProductCode          string      `json:"product_code"`
	FundingCurrency      string      `json:"funding_currency"`
	CryptoAccountID      interface{} `json:"crypto_account_id"`
	CurrencyPairCode     string      `json:"currency_pair_code"`
	AveragePrice         float64     `json:"average_price"`
	Target               string      `json:"target"`
	OrderFee             float64     `json:"order_fee"`
	SourceAction         string      `json:"source_action"`
	UnwoundTradeID       interface{} `json:"unwound_trade_id"`
	TradeID              interface{} `json:"trade_id"`
}

// SendOrder 注文を送る
func (api *APIClient) SendOrder(order *SendOrder) (*ResponseSendChildOrder, error) {
	data, _ := json.Marshal(order)
	url := "/orders/"
	resp, err := api.doRequest("POST", url, map[string]string{}, data)
	if err != nil {
		log.Printf("Order Request fail, err=%s", err.Error())
		return nil, err
	}
	var response ResponseSendChildOrder
	err = json.Unmarshal(resp, &response)
	if err != nil {
		log.Printf("Order Request Unmarshal fail, err=%s", err.Error())
		return nil, err
	}
	return &response, nil
}

// GetOrder 注文IDの情報を取得する
func (api *APIClient) GetOrder(orderID int) (*GetOrder, error) {
	var getOrder *GetOrder
	spath := fmt.Sprintf("/orders/%d", orderID)
	resp, err := api.doRequest("GET", spath, nil, nil)
	if err != nil {
		log.Printf("Get Order Request Error, err = %s", err.Error())
		return nil, err
	}

	err = json.Unmarshal(resp, &getOrder)
	if err != nil {
		log.Printf("Get Order Request Unmarshal Error, err = %s", err.Error())
		return nil, err
	}
	return getOrder, nil
}


```

#さいごに
まだ勉強中なのでこれを機にたくさんアウトプットをしてみようと思います。

ありがとうございました。