GelöstHi
Ich möchte eine API Anbindung an Yacuna.com in Python3.
Hier deren API Seite mit Beschreibung was wie gefordert wird:
http://docs.yacuna.com/api/Ich habe mich schon selbst so gut es geht daran versucht und auch ein wenig Hilfe vom Support bekommen. Leider kann dieser aber kein Python, weshalb sie wohl auch mit ihrer Weisheit am Ende sind.. Zusätzlich gibt es das Problem, dass man bei einem Fehler von Yacuna nur sinngemäß "fehler" zurückbekommt, ohne irgendeinen Hinweis darauf, was denn nun nicht stimmt.
So sieht mein Skript bisher aus (key, secret und wallet Ids im init müssen natürlich durch korrekte werte ersetzt werden):
import json
import requests
import sys
import hmac
import hashlib
import time
from requests import Request, Session
class YacunaAPI:
def load_key(self, path): # falls key nicht in skript speichern, hiermit laden
f = open(path, "r")
self.key = f.readline().strip()
self.secret = f.readline().strip()
def __init__(self, key = '', secret = ''):
self.key = "abc"
self.secret = "123"
self.uri = 'https://yacuna.com'
self.apiversion = '1'
self.walletId = "AAA" # die ganzen Walletdaten bekommt man über die GetWallet Funktion und können dann hardgecodet werden (glaub ich)
self.walletAccountIdEUR = "BBB"
self.walletAccountIdXBT = "CCC"
def CalculateURLPath(self, method, params):
urlpath = '/api/' + self.apiversion + '/' + method + '/'
s = Session()
req = Request('POST', self.uri + urlpath, data=params) # für den body ists egal ob post oder get
prepped = s.prepare_request(req)
aufgeteilt = prepped.body.split("&") # bei & getrennt
aufgeteilt2 = sorted(aufgeteilt) # und alpabetisch sortiert
neu = "?" # startet mit einem ?
for element in aufgeteilt2:
neu = neu + element + "&" # elemente werden mit einem & dazwischen wieder zusammengesetzt
neu = neu[0:len(neu)-1] # das letzte & Zeichen abschneiden
return(urlpath + neu)
def query_call(self, method, public=0, get=0, params={}):
print("")
DetailedUrlPath = self.CalculateURLPath(method, params)
print(DetailedUrlPath) # zur überprüfung mal printen..
print("")
if get:
if public:
urlpath = '/api/' + self.apiversion + '/' + method + '/'
return (requests.get(self.uri + urlpath, params=params,timeout=30).json() )
else:
urlpath = '/api/' + self.apiversion + '/' + method + '/'
nonce = str(int(1000*time.time()))
string = nonce + "@" + self.secret + "@GET@" + DetailedUrlPath
encoded = string.encode()
signature = hashlib.sha512(encoded).hexdigest()
signature = nonce + "T" + signature
print(signature)
print("")
headers = {
"Api-Token-Id": self.key,
"Api-Token": signature,
"Api-Token-OTP": ""
}
return (requests.get(self.uri + urlpath, params=params,headers=headers,timeout=30).json() )
else:
if public:
urlpath = '/api/' + self.apiversion + '/' + method + '/'
return (requests.post(self.uri + urlpath, params=params,timeout=30).json() )
else:
urlpath = '/api/' + self.apiversion + '/' + method + '/'
nonce = str(int(1000*time.time()))
string = nonce + "@" + self.secret + "@GET@" + DetailedUrlPath
encoded = string.encode()
signature = hashlib.sha512(encoded).hexdigest()
signature = nonce + "T" + signature
print(signature)
print("")
headers = {
"Api-Token-Id": self.key,
"Api-Token": signature,
"Api-Token-OTP": ""
}
return (requests.post(self.uri + urlpath, params=params,headers=headers,timeout=30).json() )
def GetWallet(self,currency=0): # gibt alle möglichen Wallet infos, inklusive aller Balances aus
method = 'wallet/get'
if currency:
Wallet = self.query_call(method,0,1,{"currency":currency})
else:
Wallet = self.query_call(method,0,1)
return(Wallet)
def OrderBook(self, currency1, currency2):# getting the full orderbook
method = "orderbook/get" # zb https://yacuna.com/api/1/orderbook/get/EUR/XBT
Orders = self.query_call(method,0,1,{"currency1":currency1,"currency2":currency2})
return Orders # Fehlerprüfung in eigenen Funktionen
def CancelOrder(self, ID):
method = "order/cancel"
Cancel = self.query_call(method,0,0,{"orderId":ID})
return Cancel # Fehlerprüfung in eigenen Funktionen
def CreateOrder(self, currency1, currency2, type, amount, price):
method = "order/create"
# es werden immer btc gekauft/verkauft, also walletid XBT
if type=="buy":
tradeOrderType="BuyLimit"
buyAmount = amount
buyCurrency = "XBT"
priceLimitCurrency = "EUR"
priceLimitAmount = price
Create = self.query_call(method,0,0,{"currency1":currency1,"currency2":currency2,"walletAccountId":self.walletAccountIdXBT,"tradeOrderType":tradeOrderType,"buyAmount":amount,"buyCurrency":buyCurrency,"priceLimitCurrency":priceLimitCurrency,"priceLimitAmount":priceLimitAmount})
elif type=="sell":
tradeOrderType="SellLimit"
sellAmount = amount
sellCurrency = "XBT"
priceLimitCurrency = "EUR"
priceLimitAmount = price
Create = self.query_call(method,0,0,{"currency1":currency1,"currency2":currency2,"walletAccountId":self.walletAccountIdXBT,"tradeOrderType":tradeOrderType,"sellAmount":amount,"sellCurrency":sellCurrency,"priceLimitCurrency":priceLimitCurrency,"priceLimitAmount":priceLimitAmount})
else:
raise AssertionError("Ungültiger kauf/verkauftype in YacunaAPI createorder.")
return Create # Fehlerprüfung in eigenen Funktionen
def OrderList(self, tradeOrderStatus, count=30): # tradeOrderStatus == "Confirmed" .. gibt noch mehr sortierungsmöglichkeiten, siehe api doku
method = "order/list"
List = self.query_call(method,0,1,{"walletAccountId":self.walletAccountIdEUR,"tradeOrderStatus":tradeOrderStatus,"count":count,"startWith":0})
return List # Fehlerprüfung in eigenen Funktionen
Ich glaube jeder Pythonprogrammierer würde mir nun erstmal einen Vortrag halten, wie unschön dieses Skript ist und so weiter. Das ist der Grund weshalb ich die Frage nicht im Pythonforum stelle.. habe da keine guten erfahrungen gemacht.
Es ist mir egal wie es aussieht, hauptsache es tut was es soll
Jedenfalls möchte ich, wie man sieht, das Modul "requests" verwenden, welches hier beschrieben wird:
http://docs.python-requests.org/en/latest/Ich glaube der GetWallet Aufruf funktioniert sogar schon. Probleme gibt es mit anderen Aufrufen, wie CreateOrder bzw CancelOrder (also den Post-Anfragen).
Zum austesten ob eure Korrektur funktioniert würde ich empfehlen einfach schnell einen Yacuna Account aufzumachen und dort API Key + Secret zu generieren. Ich glaube dazu muss man sich nicht verifizieren, sollte also kein Problem sein.