HLab

Julien Hautefeuille

Golang API pour le site cex.io

Cex.io est un site d’achat et de vente de possibilités de générer des Bitcoins. Il permet d’acheter ou de vendre des GH/s. Le GH/s correspond à la capacité de calcul nécessaire à générer des Bitcoins.

Le site Cex.io propose les API pour les langages suivants : Php, Node.js et Python. Malheureusement, certaines de ces API ne me conviennent pas ou sont incomplètes.

Le projet qui nécessite d’utiliser une telle API est un projet réalisé en langage Go. J’ai donc essayé de développer une API dans ce langage pour le site Cex.io et pour les besoins du projet.

La partie du code source la plus intéressante est celle qui concerne l’authentification. La description des contraintes d’authentification est détaillée sur la page dédiée à l’API du site Cex.io.

“Nonce” est un nombre entier arbitraire. Il doit être incrémenté à chaque requête. J’utilise ici le temps Unix retourné en nanoseconde.

“Signature” est un message chiffré avec l’algorithme HMAC-SHA256. Ce message contient : le nombre entier (Nonce), le nom de l’utilisateur (client id) et la clé de l’API. Le code HMAC-SHA256 doit être généré en utilisant une clé secrète qui est générée avec la clé de l’API. Le code doit être converti dans sa représentation hexadécimale en majuscule.

Le code de l’authentification qui résout ces contraintes :

// Key structure
type CexKey struct {
    Username string
    Api_key string
    Api_secret string
}

// Return Unix time in nano
func (cexapi *CexKey) Nonce() string {
    return strconv.FormatInt(time.Now().UnixNano(), 10)
}

// Return sha256 hashing
func (cexapi *CexKey) ToHmac256(message string, secret string) string {
    key := []byte(secret)
    h := hmac.New(sha256.New, key)
    h.Write([]byte(message))
    return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
}

// Return formatted signature
func (cexapi *CexKey) Signature() (string, string) {
    nonce := cexapi.Nonce()
    message := nonce + cexapi.Username + cexapi.Api_key
    signature := cexapi.ToHmac256(message, cexapi.Api_secret)
    return signature, nonce
}

L’API est disponible à cette adresse : https://github.com/jhautefeuille/go-cexio-api.

L’API s’utilise de la façon suivante :

package main

import (
    "github.com/jhautefeuille/go-cexio-api"
    "fmt"
)

func main() {
    cexapi := cexio.CexKey{
        Username:"your_username", 
        Api_key:"your_api_key", 
        Api_secret:"your_api_secret"}

    // Public
    fmt.Printf("Ticker => %s\n", cexapi.Ticker("GHS/BTC"))
    //fmt.Printf("Order Book => %s\n", cexapi.OrderBook("GHS/BTC"))
    //fmt.Printf("Trade History => %s\n", cexapi.TradeHistory("GHS/BTC"))

    // Private
    fmt.Printf("Balance => %s\n", cexapi.Balance())
    fmt.Printf("Open Orders => %s\n", cexapi.OpenOrders("GHS/BTC"))

    // Trading orders
    //fmt.Printf("Place Order => %s\n", cexapi.PlaceOrder("buy", "0.001", "0.017", "GHS/BTC"))
    //fmt.Printf("Cancel Order => %s\n", cexapi.CancelOrder("477571539"))

    // Workers 
    fmt.Printf("Hashrate => %s\n", cexapi.Hashrate())
    fmt.Printf("Workers => %s\n", cexapi.Workers())
}

Dans une application, on peut également profiter du package “encoding/json” :

package main

import (
    "go-cexio-api"
    "fmt"
    "encoding/json"
)

type Ticker_ struct {
    Timestamp string
    Bid float64
    Ask float64
    Low string
    High string
    Last string
    Volume string
}

func main() {
    cexapi := cexio.CexKey{
        Username:"your_username", 
        Api_key:"your_api_key", 
        Api_secret:"your_api_secret"}

    my_json := cexapi.Ticker("GHS/BTC")
    var myticker Ticker_
    json.Unmarshal([]byte(my_json), &myticker)

    fmt.Println("ticker", myticker.Bid)
}

La conversion du JSON vers la structure est une fonction très puissante dans le langage Go :

json.Unmarshal([]byte(my_json), &myticker)

Un utilisateur m’a contacté au sujet de cette API. D’autres versions améliorées sont à prévoir. Le développement de cette application m’a permis d’appréhender le langage Go que je n’avais pas encore utilisé.