質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

Swaggerを用いたAPI構築時のファイル構成とそれぞれの役割について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 95

masayoshi555

score 5

背景

BitMEXというサービスのAPI(https://github.com/BitMEX/api-connectors)を使ってiPhoneアプリを作ろうと考えております。

構築環境

macbbookpro(mid17) OS10.15.1(Catalina)

現状

こちらのサイトを参考にswaggerを用いたRESTfulAPI環境構築を実施し、githubのswagger-apiサンプルコードの実行まで出来ました。
(URLの末尾を変更することで、"hello, {name}!"の{name}が変わることをターミナル上で確認)

出来ないこと

BitMEXでの応用にいたりません。
その原因としてサンプルファイル群のそれぞれの機能を理解していないことにあると考えています。

現時点で理解していること

先ほどのサイトを参考に以下の部分までは理解出来ました。
現状これ以上の理解がありません。
イメージ説明
イメージ説明
イメージ説明
 

知りたいこと(質問のピントがずれているかも)

  • それぞれのファイルの役割
  • BitMEXでやる場合、どのファイルがどう置き換わるのか
    イメージ説明
  • API keyやAPI secret kyeはどこに入力するのか
    ・・・などなど恐らく知らなければいけないことに対して、全て質問が出来ていないと思われます。
    「まずはここを見なさい」でも構いませんので、情報頂けると大変助かります。

やったこと

  • 本屋さんで参考になりそうな本を探した → ない。orもしくわわからない
  • ネットで参考になりそうなファイル構成を説明してそうなサイトを探した → 断片的
    参考サイト:https://qiita.com/ta1nakamura/items/9ce151835d5b131fddf4
    API関連、特にswaggerは情報が少なく苦労しています。(そもそもAPI関連も少ない)

追記

その後、BitMEX側にある程度の文書があることがわかりました。(一般的だと後ほどわかりました)
https://www.bitmex.com/app/apiKeysUsage
その中にAPI keyとAPI secret(secret keyとは言わないんですね)の入力場所があるのですが、それがどのファイルかはわかりませんでした。
イメージ説明

追記2

正しいかどうかはわかっていないのですが、その後のアクションを追記します。
swaggerのsampleコードとbitmexのサンプルコードで対応するものを探しました。
これに対して不足や指摘があればお願いしたいです。

  1. app.jsに該当するものを見つけ、ルート直下へ
    イメージ説明
  2. apiファイルを作成し、定義ファイルを移動&node_modulesフォルダのコピー
    イメージ説明
  3. swaggerClient.jsの「接続できません:TypeError:未定義のプロパティ ‘add’を読み取れません」
    web上に解決策あったので、これに基づき解決(https://codeday.me/jp/qa/20190426/709259.html
'use strict';
var SwaggerClient = require("swagger-client");
var _ = require('lodash');
var BitMEXAPIKeyAuthorization = require('./lib/BitMEXAPIKeyAuthorization');

require('dotenv').config();

new SwaggerClient({
  // Switch this to `www.bitmex.com` when you're ready to try it out for real.
  // Don't forget the `www`!
  url: 'https://testnet.bitmex.com/api/explorer/swagger.json',
  usePromise: true
})
.then(function(client) {
  //console.log(client);
  // Comment out if you're not requesting any user data.
  client.clientAuthorizations.add("apiKey", new BitMEXAPIKeyAuthorization(process.env.BITMEX_API_KEY, process.env.BITMEX_API_SECRET));

  // Print client capabilities
  //

})
.catch(function(e) {
  console.error("Unable to connect:", e);
})
new SwaggerClient({
    // Switch this to `www.bitmex.com` when you're ready to try it out for real.
    // Don't forget the `www`!
    url: 'https://testnet.bitmex.com/api/explorer/swagger.json',
    usePromise: true,
    authorizations: {
        apiKey: new BitMEXAPIKeyAuthorization(process.env.BITMEX_API_KEY, process.env.BITMEX_API_SECRET)
    }
})
.then(client => {
    // Do whatever with client
})
.catch(function(e) {
console.error("Unable to connect:", e);
})

結果(現在)

フォルダ構成は以下の通り、
イメージ説明
この状態でのターミナルからの実行結果

**:bitmex admin$ swagger project start
Starting: /Users/admin/swagger/bitmex/swaggerClient.js...
  project started here: http://undefined/api/v1
  project will restart on changes.
  to restart at any time, enter `rs`
/Users/admin/swagger/bitmex/swaggerClient.js:11
  authorizations: {
  ^^^^^^^^^^^^^^

SyntaxError: Unexpected identifier
    at wrapSafe (internal/modules/cjs/loader.js:891:16)
    at Module._compile (internal/modules/cjs/loader.js:941:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1011:10)
    at Module.load (internal/modules/cjs/loader.js:822:32)
    at Function.Module._load (internal/modules/cjs/loader.js:730:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1051:12)
    at internal/main/run_main_module.js:16:11
'use strict';
var SwaggerClient = require("swagger-client");
var _ = require('lodash');
var BitMEXAPIKeyAuthorization = require('./lib/BitMEXAPIKeyAuthorization');

new SwaggerClient({
  // Switch this to `www.bitmex.com` when you're ready to try it out for real.
  // Don't forget the `www`!
  url: 'https://testnet.bitmex.com/api/explorer/swagger.json',
  usePromise: true,
  authorizations: {
    apiKey: new BitMEXAPIKeyAuthorization(process.env.BITMEX_API_KEY, process.env.BITMEX_API_SECRET)
  }
})
.then(client => {
  // Comment out if you're not requesting any user data.
  // client.clientAuthorizations.add("apiKey", new BitMEXAPIKeyAuthorization('api-key', 'api-secret'));

  // Print client capabilities
  inspect(client.apis);

  // Get a trade
  client.Trade.Trade_get({symbol: 'XBTUSD', count: 40})
  .then(function(response) {
    var trades = JSON.parse(response.data.toString());
    // Print the max price traded in the last `count` trades.
    console.log('\nMax Trade:\n----\n', JSON.stringify(_.max(trades, 'price'), undefined, 2));
  })
  .catch(function(e) {
    // Error handling...
    console.log('Error:', e.statusText);
  })

  client.User.User_getMargin()
  .then(function(response) {
    var margin = JSON.parse(response.data.toString());
    var marginBalance = (margin.marginBalance / 1e8).toFixed(4);
    console.log('\nMargin Balance:', marginBalance, 'XBT');
  })
  .catch(function(e) {
    // Error handling...
    console.log('Error:', e.statusText);
  })

  // Example: Placing an order - commented for your safety
  // .then(function() {
  //   return client.Order.Order_new({symbol: 'XBTUSD', price: 1000, orderQty: 1})
  // })
  // .then(function (response) {
  //   console.log(response.data.toString());
  // });

  // Example: sending a bulk order
  // Note: due to a bug in the Swagger client, you must stringify the Array, otherwise
  // we will be sent `["[object Object]","[object Object]"]`
  // client.Order.Order_newBulk({
  //   "orders": JSON.stringify([
  //     {"symbol":"XBTUSD","price":2433.5,"orderQty":147,"side":"Sell"},
  //     {"symbol":"XBTUSD","price":2431.1,"orderQty":190,"side":"Sell"}
  //   ])
  // })
  // .then(function (response) {
  //   console.log(response.data.toString());
  // });
})
.catch(function(e) {
  console.error("Unable to connect:", e);
})

function inspect(client) {
  console.log("Inspecting BitMEX API...");
  Object.keys(client).forEach(function(model) {
    if (!client[model].operations) return;
    console.log("Available methods for %s: %s", model, Object.keys(client[model].operations).join(', '));
  });
  console.log("------------------------\n");
}

追記3

"authorizations:{エラー"は以下の変更でなくなりましたが、次のエラーが出ました。引き続き検証します。
(参考URL:https://github.com/swagger-api/swagger-js/blob/903569948d5a5c718d7b87d6832a672de4e76afc/docs/MIGRATION_2_X.md#authorizations

'use strict';
var SwaggerClient = require("swagger-client");
var _ = require('lodash');
var BitMEXAPIKeyAuthorization = require('./lib/BitMEXAPIKeyAuthorization');

new SwaggerClient({
  // Switch this to `www.bitmex.com` when you're ready to try it out for real.
  // Don't forget the `www`!
  url: 'https://testnet.bitmex.com/api/explorer/swagger.json',
  usePromise: true,
  authorizations: {
    apiKey: new BitMEXAPIKeyAuthorization(process.env.BITMEX_API_KEY, process.env.BITMEX_API_SECRET)
  }
})
.then(client => {
(以下変更なし)
'use strict';
var SwaggerClient = require("swagger-client");
var _ = require('lodash');
var BitMEXAPIKeyAuthorization = require('./lib/BitMEXAPIKeyAuthorization');

var client = new SwaggerClient('http://petstore.swagger.io/v2/swagger.json',{
  // Switch this to `www.bitmex.com` when you're ready to try it out for real.
  // Don't forget the `www`!
  url: 'https://testnet.bitmex.com/api/explorer/swagger.json',
  usePromise: true,
  authorizations: {
    apiKey: new BitMEXAPIKeyAuthorization(process.env.BITMEX_API_KEY, process.env.BITMEX_API_SECRET)
  }
})
.then(client => {
(以下省略)
:bitmex admin$ swagger project start
Starting: /Users/admin/swagger/bitmex/swaggerClient.js...
  project started here: http://undefined/api/v1
  project will restart on changes.
  to restart at any time, enter `rs`
Inspecting BitMEX API...
------------------------

Unable to connect: TypeError: Cannot read property 'Trade_get' of undefined
    at /Users/admin/swagger/bitmex/swaggerClient.js:23:16
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

js:23:16は "client.Trade.Trade_get({symbol: 'XBTUSD', count: 40})"です。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

最終的にauthorizationエラーが治らず解決しませんでした。

色々調べているうちにこちらのサイトに辿り着き、
あっという間にAPIテストが完了しました。

BitMEXのサンプルコードよりもシンプルで、ファイルも一つなので、一見してわかりやすい内容です。
https://note.mu/take_bits/n/n36db57e2f70f

var request = require('request');
var crypto = require('crypto');

var key = '自分のAPIキー';
var secret = 'シークレットキー';

//かこの時間だとエラーになるので余裕に足すと良い
var timestamp = parseInt(Date.now() / 1000 + 60);

//5555ドルで100枚買う
order_simple('Buy', 100, 5555);
//order_simple('Sell', 100, 9999);

function order_simple (_side, _size, _price) {
  var path = '/api/v1/order';
  var body = JSON.stringify({
                            symbol: 'XBTUSD',
                            side: _side,
                            orderQty: _size,
                            price: _price,
                            ordType: "Limit",
                            //clOrdID: "clOrdID"
                            });
  var url = "https://www.bitmex.com" + path;
  var mathod = "POST";
  var text = mathod + path + timestamp + body;
  var sign = crypto.createHmac('sha256', secret).update(text).digest('hex');
  var options = {
  url: url,
  method: mathod,
  body: body,
  headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'X-Requested-With': 'XMLHttpRequest',
      'api-expires': timestamp,
      'api-key': key,
      'api-signature': sign,
  }
  };



   //リクエスト開始
  request(options, function (err, response, payload) {
          if (!payload) {return;}
          var getData = JSON.parse(payload);

          if (getData.error) {
          console.log("message:", getData.error.message);
          console.log("name:", getData.error.name);
          return
          }
          
          console.log("orderID:", getData.orderID);
          console.log("clOrdID:", getData.clOrdID);
          console.log("clOrdLinkID:", getData.clOrdLinkID);
          console.log("account:", getData.account);
          console.log("symbol:", getData.symbol);
          console.log("side:", getData.side);
          console.log("simpleOrderQty:", getData.simpleOrderQty);
          console.log("orderQty:", getData.orderQty);
          console.log("price:", getData.price);
          console.log("displayQty:", getData.displayQty);
          console.log("stopPx:", getData.stopPx);
          console.log("pegOffsetValue:", getData.pegOffsetValue);
          console.log("pegPriceType:", getData.pegPriceType);
          console.log("currency:", getData.currency);
          console.log("settlCurrency:", getData.osettlCurrency);
          console.log("ordType:", getData.ordType);
          console.log("timeInForce:", getData.timeInForce);
          console.log("execInst:", getData.execInst);
          console.log("contingencyType:", getData.contingencyType);
          console.log("exDestination:", getData.exDestination);
          console.log("ordStatus:", getData.ordStatus);
          console.log("triggered:", getData.triggered);
          console.log("workingIndicator:", getData.workingIndicator);
          console.log("ordRejReason:", getData.ordRejReason);
          console.log("simpleLeavesQty:", getData.simpleLeavesQty);
          console.log("leavesQty:", getData.leavesQty);
          console.log("simpleCumQty:", getData.simpleCumQty);
          console.log("cumQty:", getData.cumQty);
          console.log("avgPx:", getData.avgPx);
          console.log("multiLegReportingType:", getData.multiLegReportingType);
          console.log("text:", getData.text);
          console.log("transactTime:", getData.transactTime);
          console.log("timestamp:", getData.timestamp);
          });

}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる