I'm trying to do a GET request to an API with the specified headers and even though all the headers are right and exactly the same as the working python code but I get an error saying on of the header is not correct. This is the working python code:
api_passphrase = "passphrase"
api_secret = "secret"
api_key = "key"
url = 'https://api-futures.kucoin.com/api/v1/position?symbol=XBTUSDM'
now = int(time.time() * 1000)
str_to_sign = str(now) + 'GET' + '/api/v1/position?symbol=XBTUSDM'
signature = base64.b64encode(
hmac.new(api_secret.encode('utf-8'), str_to_sign.encode('utf-8'), hashlib.sha256).digest())
passphrase = base64.b64encode(hmac.new(api_secret.encode('utf-8'), api_passphrase.encode('utf-8'), hashlib.sha256).digest())
headers = {
"KC-API-SIGN": signature,
"KC-API-TIMESTAMP": str(now),
"KC-API-KEY": api_key,
"KC-API-PASSPHRASE": passphrase,
"KC-API-KEY-VERSION": "2"
}
response = requests.request('get', url, headers=headers)
# print(response.json())
# print(response)
# print(response.request.headers)
# print(response.request.body)
# #
print(passphrase)
and this is my Haskell code:
import qualified Config as C
import Control.Lens
import Control.Monad
import Control.Monad.Catch
import Control.Monad.IO.Class
import qualified Crypto.Hash.SHA256 as H
import qualified Data.Aeson as A
import Data.Aeson.Lens as AL
import qualified Data.ByteString as B
import qualified Data.ByteString.Base64 as U
import qualified Data.ByteString.Char8 as BC
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Lazy.UTF8 as BU
import Data.Monoid
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import qualified Data.Time.Clock.POSIX as TI
import GHC.Generics
import Network.Wreq
apiSign :: BC.ByteString -> BC.ByteString -> BC.ByteString -> TI.POSIXTime -> IO BC.ByteString
apiSign method endpoint body time = do
timeStamp <- apiTimeStamp' time
let message = mconcat [timeStamp,method,endpoint,body]
let hash = H.hmac (BC.pack C.apiSecret) message
return $ (encodeUtf8 . U.encodeBase64) hash
apiTimeStamp' :: TI.POSIXTime -> IO BC.ByteString
apiTimeStamp' = return . BC.take 13 . BC.pack . show . (* 1000)
apiPassphrase :: BC.ByteString
apiPassphrase = U.encodeBase64' $ H.hmac (BC.pack C.apiSecret) (BC.pack C.apiPassphrase)
apiKeyVersion :: BC.ByteString
apiKeyVersion = BC.pack C.apiVersion
main' :: IO ()
main' = do
time <- TI.getPOSIXTime
timeStamp <- apiTimeStamp' time
apiSignValue <- apiSign "GET" "/api/v1/position?symbol=XBTUSDM" "" time
let opt = defaults & header "Accept" .~ ["*/*"]
& header "KC-API-VERSION" .~ ["2"]
& header "KC-API-KEY" .~ [BC.pack C.apiKey]
& header "KC-API-TIMESTAMP" .~ [timeStamp]
& header "KC-API-PASSPHRASE" .~ [apiPassphrase]
& header "KC-API-SIGN" .~ [apiSignValue]
& param "symbol" .~ ["XBTUSDM"]
r <- getWith opt (kucoin ++ "position")
let response = r ^. responseBody
print response
The error says that the passphrase is not correct
this is the passphrase generated by python: b'e3GO2zT3kWv1oVrAhAF1TByq0u8ExNMw/76KrsFGnls='
and this is the passphrse genereted by Haskell:
e3GO2zT3kWv1oVrAhAF1TByq0u8ExNMw/76KrsFGnls=
and finally, this is the error I get while using the wreq library in Haskell
"{"code":"400004","msg":"Invalid KC-API-PASSPHRASE"}")
everything else beside passphrase is fine.
At some point I thought it's because of lazy evaluation and I tried BangPatterns but the issue didn't resolve.