JSON-RPC 2.0 over WebSocket

Realtime API

📘

この接続方法での通信内容は JSON-RPC 2.0 Specification に準拠しています。

エンドポイント

wss://ws.lightstream.bitflyer.com/json-rpc

🚧

  • JSON-RPC 2.0 にて定められた Batch リクエストをサポートしています。リクエストは配列の先頭から順番に処理されます。
  • 接続には TLS 1.2 に対応したクライアントや、場合によっては明示的な設定が必要となります。

サーバーメソッド

  • auth - 認証要求をします
    • params の内容は認証ページを参照してください
    • 認証に成功すると true が返ります (必ず確認してください)
  • subscribe - チャンネルの購読を開始します
    • params: { channel: "(Channel Name)" }
    • 購読が開始されると true が返ります
  • unsubscribe - チャンネルの購読を解除します
    • params: { channel: "(Channel Name)" }
    • 購読が解除されると true が返ります

クライアントメソッド

  • channelMessage - 購読している全チャンネルのメッセージが配信されます

利用例

// Node.js (JavaScript) const crypto = require("crypto"); const RPCClient = require("jsonrpc2-ws").Client; const key = "{{ YOUR API KEY }}"; const secret = "{{ YOUR API SECRET }}"; const publicChannels = ["lightning_executions_BTC_JPY"]; const privateChannels = ["child_order_events", "parent_order_events"]; const client = new RPCClient("wss://ws.lightstream.bitflyer.com/json-rpc", { protocols: undefined }); // connection handling client.on("connected", async () => {     // subscribe to the Public Channels     for (const channel of publicChannels) {         try {             await client.call("subscribe", { channel });         } catch (e) {             console.log(channel, "Subscribe Error:", e);             continue;         }         console.log(channel, "Subscribed.");     }     // authentication parameters     const now = Date.now();     const nonce = crypto.randomBytes(16).toString("hex");     const sign = crypto.createHmac("sha256", secret).update(`${now}${nonce}`).digest("hex");     // request auth     try {         await client.call("auth", {             api_key: key,             timestamp: now,             nonce: nonce,             signature: sign         });     } catch (e) {         console.error("auth", "Authentication Error:", e);         return;     }     console.log("auth", "Authenticated.");     // subscribe to the Private Channels     for (const channel of privateChannels) {         try {             await client.call("subscribe", { channel });         } catch (e) {             console.log(channel, "Subscribe Error:", e);             continue;         }         console.log(channel, "Subscribed.");     } }); // channel messages handling client.methods.set("channelMessage", (client, notify) => {     console.log("channelMessage", notify.channel, notify.message); });
// .NET Core / Framework (C# 7.1) // `dotnet add package StreamJsonRpc -v 1.4.46-beta` or // `Install-Package -Prerelease StreamJsonRpc` using Newtonsoft.Json.Linq; using StreamJsonRpc; using System; using System.Net.WebSockets; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; namespace LightStreamSampleNetCore { class Program { static async Task Main(string[] args) { const string key = "{{ YOUR API KEY }}"; const string secret = "{{ YOUR API SECRET }}"; var publicChannels = new[] { "lightning_executions_BTC_JPY" }; var privateChannels = new[] { "child_order_events", "parent_order_events" }; using (var ws = new ClientWebSocket()) { await ws.ConnectAsync(new Uri("wss://ws.lightstream.bitflyer.com/json-rpc"), CancellationToken.None); using (var rpc = new JsonRpc(new WebSocketMessageHandler(ws))) { // channel messages handling rpc.AddLocalRpcMethod("channelMessage", new Action<JToken, CancellationToken>((@params, cancellationToken) => { var p = @params as dynamic; Console.WriteLine($"{p.channel}: {p.message}"); })); rpc.StartListening(); // subscribe to the Public Channels foreach (var channel in publicChannels) { await rpc.InvokeWithParameterObjectAsync<object>("subscribe", new { channel }); Console.WriteLine($"{channel} Subscribed."); } // authentication parameters var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); var nonce = Guid.NewGuid().ToString(); var sign = SignWithHMACSHA256($"{now}{nonce}", secret); // request auth await rpc.InvokeWithParameterObjectAsync<object>("auth", new { api_key = key, timestamp = now, nonce = nonce, signature = sign, }); Console.WriteLine("Authenticated."); // subscribe to the Private Channels foreach (var channel in privateChannels) { await rpc.InvokeWithParameterObjectAsync<object>("subscribe", new { channel }); Console.WriteLine($"{channel} Subscribed."); } Console.ReadLine(); } } } static string SignWithHMACSHA256(string data, string secret) { using (var encoder = new HMACSHA256(Encoding.UTF8.GetBytes(secret))) { var hash = encoder.ComputeHash(Encoding.UTF8.GetBytes(data)); return ToHexString(hash); } } static string ToHexString(byte[] bytes) { var sb = new StringBuilder(bytes.Length * 2); foreach (var b in bytes) { sb.Append(b.ToString("x2")); } return sb.ToString(); } } }
require 'rubygems' require 'websocket-client-simple' require 'json' require 'securerandom' JSONRPC_ID_AUTH = 1 apiKey = "{{ YOUR API KEY }}" apiSecret = "{{ YOUR API SECRET }}" publicChannels = ["lightning_board_snapshot_BTC_JPY"] privateChannels = ["child_order_events"] # note: reconnection handling needed for production use. ws = WebSocket::Client::Simple.connect 'wss://ws.lightstream.bitflyer.com/json-rpc' ws.on :open do puts "open" publicChannels.each do |channel| json = JSON.generate({:method => :subscribe, :params => { :channel => channel }, :id => nil}) ws.send(json) end now = Time.now.strftime('%s%L') nonce = SecureRandom.hex(16) sign = OpenSSL::HMAC.hexdigest("sha256", apiSecret, now + nonce) ws.send(JSON.generate({ :method => :auth, :params => { :api_key => apiKey, :timestamp => now.to_i, :nonce => nonce, :signature => sign, }, :id => JSONRPC_ID_AUTH })) end ws.on :message do |msg| data = JSON.parse(msg.data) if data["id"] == JSONRPC_ID_AUTH then if data["error"] != nil then puts "auth error: " + data["error"]["message"] exit else puts "authed" privateChannels.each do |channel| json = JSON.generate({:method => :subscribe, :params => { :channel => channel }, :id => nil}) ws.send(json) end end end if data["method"] == "channelMessage" then p data["params"] end end ws.on :close do |e| p e exit 1 end ws.on :error do |e| p e end print "Please press key to exit." STDIN.getc

English
Powered by Localize
日本語