Package: bittrade-kraken-rest
ELM Bittrade's Kraken REST package & optional CLIInstallpip install bittrade-kraken-restorpoetry add bittrade-kraken-restNot all Kraken endpoints are implemented yet.Public endpointsfrombittrade_kraken_restimportget_server_timeserver_time=get_server_time().run()print(server_time)# GetServerTimeResult(unixtime=1673053481, rfc1123='Sat, 07 Jan 23 01:04:41 +0000')The above example is complete, it should run as isBring Your OwnCredentialsSignature (Private endpoints)TLDR; Don't agree to pass your API secret to third-party code; instead sign the requests yourself, with your own code. It's safer.This library doesn't want to ever access your Kraken secret keys.Most libraries expect you to provide your api key and secret. I'm not comfortable doing that with third-party code, even open sourced.Here instead, the library prepares the request, which you then sign using your own code and the library finishes the job. It has NO access to your secret.Thankfully this is quite straightforward: you need to implement asign(x: tuple[PreparedRequest, str, dict[str, Any]]) -> PreparedRequestmethod which sets the correct headers. Below is an example of such a signature function:fromosimportgetenvimporturllib,hmac,base64,hashlibfrompathlibimportPath# Taken from https://docs.kraken.com/rest/#section/Authentication/Headers-and-Signaturedefgenerate_kraken_signature(urlpath,data,secret):post_data=urllib.parse.urlencode(data)encoded=(str(data["nonce"])+post_data).encode()message=urlpath.encode()+hashlib.sha256(encoded).digest()mac=hmac.new(base64.b64decode(secret),message,hashlib.sha512)signature_digest=base64.b64encode(mac.digest())returnsignature_digest.decode()# Here the key/secret are loaded from a .gitignored folder, but you can use environment variables or other method of configurationdefsign(x:tuple[PreparedRequest,str,dict[str,Any]]):request,url,data=xrequest.headers["API-Key"]=Path("./config_local/key").read_text()request.headers["API-Sign"]=generate_kraken_signature(url,data,Path("./config_local/secret").read_text())returnrequestWith that in place, a observable pipe will get you the result you need:frombittrade_kraken_restimportget_websockets_token_request,get_websockets_token_resultfromreactiveximportoperatorsresult=get_websockets_token_request().pipe(operators.map(sign),get_websockets_token_result()).run()Full example with signature functionfromosimportgetenvimporturllib,hmac,base64,hashlibfrompathlibimportPathfrombittrade_kraken_restimportget_websockets_token_request,get_websockets_token_resultfromreactiveximportoperators# Taken from https://docs.kraken.com/rest/#section/Authentication/Headers-and-Signaturedefgenerate_kraken_signature(urlpath,data,secret):post_data=urllib.parse.urlencode(data)encoded=(str(data["nonce"])+post_data).encode()message=urlpath.encode()+hashlib.sha256(encoded).digest()mac=hmac.new(base64.b64decode(secret),message,hashlib.sha512)signature_digest=base64.b64encode(mac.digest())returnsignature_digest.decode()# Here the key/secret are loaded from a .gitignored folder, but you can use environment variables or other method of configurationdefsign(x:tuple[PreparedRequest,str,dict[str,Any]]):request,url,data=xrequest.headers["API-Key"]=Path("./config_local/key").read_text()request.headers["API-Sign"]=generate_kraken_signature(url,data,Path("./config_local/secret").read_text())returnrequestresult=get_websockets_token_request().pipe(operators.map(sign),get_websockets_token_result()).run()The above example is complete, it should run as isObservablesThe above examples use.run()to trigger the observable subscription but Observables make it very easy to create pipes, retries and more. All operators can be found on theRxPy read the docs.TestspytestNote that integration tests require a valid key/secret pair saved askeyandsecretfiles in a.config_localfolder placed at the root of the repo.CLIThe CLI has been moved toits own repo