C-Sharp

Gemini API 讀取響應/內容?

  • January 3, 2017

所以我正在嘗試測試來自 Gemini 的經過驗證的響應。我得到了一個“響應”,但不是我所期望的……它以 html 字元串的形式返回,而不是API 建議我應該得到的“餘額數組” 。我以前沒有使用過 HttpClient,所以這裡的學習曲線是雙重的。不確定我是否有錯誤的資訊,或者我是否正在查看錯誤的方法/屬性?

對於如何從 Gemini 返回這個數組,我有點困惑。

我在那裡有 API 密鑰和秘密,因為這只是在沙盒上。帳戶有大約 1,000,000 個假資產。

JSON字元串

{"request":"/v1/balances","nonce":1477275934999}

JSON / Payload 的 Base64 編碼

eyJyZXF1ZXN0IjoiL3YxL2JhbGFuY2VzIiwibm9uY2UiOjE0NzcyNzU5MzQ5OTl9

留言

Method: POST, RequestUri: 'https://api.sandbox.gemini.com/', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
 X-GEMINI-APIKEY: L6qDKmQZcmLVDTd5zK9S
 X-GEMINI-PAYLOAD: eyJyZXF1ZXN0IjoiL3YxL2JhbGFuY2VzIiwibm9uY2UiOjE0NzcyNzU5MzQ5OTl9
 X-GEMINI-SIGNATURE: DBA15C6B2FFA602F9323E0180A14BABEA018640324E313D6C8BBAE9F8872B06325B75F6C507C55435982D600EE5DDF57
 Content-Type: text/plain; charset=utf-8
}

響應字元串:(似乎總是“工作”,即使我有格式錯誤的請求,我也沒有註意到)

StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
 Connection: keep-alive
 Age: 6605
 X-Cache: Hit from cloudfront
 X-Amz-Cf-Id: Ae3ps4mhbjIzGCrgFr43dq0ICZvnUmPKpeo1miv4ufDFJkJtNZy8GA==
 Date: Sat, 22 Oct 2016 22:55:51 GMT
 ETag: "5dc6bbdccdd2100c4ca4b0155402db35"
 Server: AmazonS3
 Via: 1.1 cae81d5ff1d682b28f2deabdd94777d4.cloudfront.net (CloudFront)
 Content-Length: 172
 Content-Type: text/html
 Last-Modified: Fri, 29 Jul 2016 18:31:06 GMT
}

Response.Content - 不是我所期望的……

<html>
   <head>
       <script>
           window.location.replace("/rest-api/" + window.location.search + window.location.hash);
       </script>
   </head>
</html>

程式碼(C# .NET 4.5)

using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Gemini.API;
using Newtonsoft.Json;

namespace HodlBot
{
   class Program
   {
       public const int TIME_INTERVAL_IN_MILLISECONDS = 3000;
       private static Timer m_timer = null;

       private static void Main(string[] args)
       {
           var source = new CancellationTokenSource();
           Console.CancelKeyPress += (s, e) =>
           {
               e.Cancel = true;
               source.Cancel();
           };

           m_timer = new System.Threading.Timer(Tick, source, TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite);

           source.Token.WaitHandle.WaitOne();
       }

       private async static void Tick(object p_state)
       {
           Console.Clear();
           var c = (CancellationTokenSource)p_state;

           /* All requests must contain a nonce, a number that will never be repeated and must increase between requests. This is to prevent an attacker who has
            * captured a previous request from simply replaying that request. We recommend using a millisecond-level timestamp. The nonce need only be
            * increasing with respect to the session that the message is on.*/

           long nonce = DateTimeOffset.Now.ToUnixTimeMilliseconds();
           string jObject = JsonConvert.SerializeObject(new Balance(nonce));

           await POST(jObject);

           // Re-Prime Event
           if(!c.Token.IsCancellationRequested)
               m_timer.Change(TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite);
       }

       private static async Task POST(string jsonText)
       {
           // Sign Payload
           Console.WriteLine(jsonText);
           string payload = System.Convert.ToBase64String((Encoding.UTF8.GetBytes(jsonText)));

           Console.WriteLine(payload);

           HMACSHA384 hmac = new HMACSHA384(Encoding.UTF8.GetBytes("LixWGpx3h89D8B4uQvfxd8hy5N1"));           //My API SECRET
           byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
           string hexHash = BitConverter.ToString(hash).Replace("-", "");

           using(var httpClient = new HttpClient())
           using(var stringContent = new StringContent("", Encoding.UTF8, "text/plain"))
           using(var r = new HttpRequestMessage(HttpMethod.Post, "https://api.sandbox.gemini.com"))
           {
               r.Headers.Add("X-GEMINI-APIKEY", "L6qDKmQZcmLVDTd5zK9S");
               r.Headers.Add("X-GEMINI-PAYLOAD", payload);
               r.Headers.Add("X-GEMINI-SIGNATURE", hexHash);
               r.Content = stringContent;

               Console.WriteLine(r.ToString());

               var response = await httpClient.SendAsync(r);
               if(response.IsSuccessStatusCode)
               {
                   Console.WriteLine(response.ToString());
                   var content = await response.Content.ReadAsStringAsync();
                   Console.WriteLine(content);
               }
           }
       }
   }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Gemini.API
{
   public class BasicRequest
   {
       [JsonProperty("request", Order = 1)]
       public string Request { get; internal set; }

       [JsonProperty("nonce", Order = 2)]
       public long Nonce { get; internal set; }

       public BasicRequest(string request, long nonce)
       {
           Request = request;
           Nonce = nonce;
       }
   }

   public class HeartBeat : BasicRequest
   {
       public HeartBeat(long nonce) : base("/v1/heartbeat", nonce) { }
   }


   public class Balance : BasicRequest
   {
       public Balance(long nonce) : base("/v1/balances", nonce) { }
   }
}

除了request在有效負載中設置參數之外,您還需要向正確的 URI 發出 POST 請求。

所以你寫的地方:

using(var r = new HttpRequestMessage(HttpMethod.Post, "https://api.sandbox.gemini.com"))
{
   ...
}

你需要類似的東西:

var request = "/v1/balances"; // or whatever endpoint you're trying to use
var url = "https://api.sandbox.gemini.com" + request;
using(var r = new HttpRequestMessage(HttpMethod.Post, url))
{
   ...
}

引用自:https://ethereum.stackexchange.com/questions/9549