bitget.rb 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -2
- data/bitget.rb.gemspec +1 -1
- data/lib/Bitget/V2/Client.rb +37 -27
- data/lib/Bitget/V2/Client2.rb +500 -0
- data/lib/Bitget/{VERSiON.rb → VERSION.rb} +1 -1
- data/lib/bitget.rb +0 -4
- data/test/V2/client_test.rb +59 -3
- data/test/client_test.rb +59 -3
- data/test/helper.rb +3 -24
- metadata +5 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: a9a76dd0384385ec874d2689053e2a9af7ed9cc4167e9980691bcca9b4855005
         | 
| 4 | 
            +
              data.tar.gz: 5d1f16940c82a9f072360fbecb5941be0df52d3161dab7db217814b5a5a2b00e
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 975b7a27c4ab2834dbcdd907b65d0fe66b17bb7d8a8c2fddee5d4cc6d3f4f2431afd670beee84312d5ff828e7d88a1dcdabb20fa1cb1a32a72a55f8da809c2b5
         | 
| 7 | 
            +
              data.tar.gz: 3f030a15eaf44fd3ccba97ea216a11da4f377135c9c49127b5dbe713d4227357512950ec6ffa4e521bd2d73fed4df903b9a574cf7ea92054110eb2a366f08857
         | 
    
        data/README.md
    CHANGED
    
    | @@ -23,7 +23,7 @@ Or install it yourself as: | |
| 23 23 |  | 
| 24 24 | 
             
            ### Setup
         | 
| 25 25 | 
             
            ```ruby
         | 
| 26 | 
            -
            bitget_client  | 
| 26 | 
            +
            bitget_client = Bitget::Client.new(
         | 
| 27 27 | 
             
              api_key: 'api_key0',
         | 
| 28 28 | 
             
              api_secret: 'api_secret0',
         | 
| 29 29 | 
             
              api_passphrase: 'api_passphrase0'
         | 
| @@ -97,9 +97,24 @@ bitget_client.spot_public_coins(coin: 'BTC') | |
| 97 97 | 
             
            #  }
         | 
| 98 98 | 
             
            ```
         | 
| 99 99 |  | 
| 100 | 
            +
            ### Get Account Information
         | 
| 101 | 
            +
            ```ruby
         | 
| 102 | 
            +
            bitget_client.spot_account_info
         | 
| 103 | 
            +
            ```
         | 
| 104 | 
            +
             | 
| 105 | 
            +
            ### Get Account Assets
         | 
| 106 | 
            +
            ```ruby
         | 
| 107 | 
            +
            bitget_client.spot_account_assets
         | 
| 108 | 
            +
            ```
         | 
| 109 | 
            +
            ```ruby
         | 
| 110 | 
            +
            bitget_client.spot_account_assets(coin: 'BTC')
         | 
| 111 | 
            +
            ```
         | 
| 112 | 
            +
             | 
| 113 | 
            +
            See https://www.bitget.com/api-doc/spot/intro for further information on endpoint arguments
         | 
| 114 | 
            +
             | 
| 100 115 | 
             
            ## Contributing
         | 
| 101 116 |  | 
| 102 | 
            -
            1. Fork it ( | 
| 117 | 
            +
            1. Fork it (https://github.com/thoran/bitget.rb/fork)
         | 
| 103 118 | 
             
            2. Create your feature branch (`git checkout -b my-new-feature`)
         | 
| 104 119 | 
             
            3. Commit your changes (`git commit -am 'Add some feature'`)
         | 
| 105 120 | 
             
            4. Push to the branch (`git push origin my-new-feature`)
         | 
    
        data/bitget.rb.gemspec
    CHANGED
    
    
    
        data/lib/Bitget/V2/Client.rb
    CHANGED
    
    | @@ -42,22 +42,33 @@ module Bitget | |
| 42 42 | 
             
                    end
         | 
| 43 43 | 
             
                  end # class << self
         | 
| 44 44 |  | 
| 45 | 
            +
                  # Get Coin Info
         | 
| 46 | 
            +
                  # GET /api/v2/spot
         | 
| 45 47 | 
             
                  def spot_public_coins(coin: nil)
         | 
| 46 | 
            -
                    response = get(
         | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 48 | 
            +
                    response = get(path: '/spot/public/coins', args: {coin: coin})
         | 
| 49 | 
            +
                    handle_response(response)
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  # Get Account Information
         | 
| 53 | 
            +
                  # GET /api/v2/spot/account/info
         | 
| 54 | 
            +
                  def spot_account_info
         | 
| 55 | 
            +
                    response = get(path: '/spot/account/info')
         | 
| 56 | 
            +
                    handle_response(response)
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  # Get Account Assets
         | 
| 60 | 
            +
                  # GET /api/v2/spot/account/assets
         | 
| 61 | 
            +
                  def spot_account_assets(**args)
         | 
| 62 | 
            +
                    response = get(path: '/spot/account/assets', args: args)
         | 
| 52 63 | 
             
                    handle_response(response)
         | 
| 53 64 | 
             
                  end
         | 
| 54 65 |  | 
| 55 66 | 
             
                  private
         | 
| 56 67 |  | 
| 57 68 | 
             
                  def initialize(api_key:, api_secret:, api_passphrase:)
         | 
| 58 | 
            -
                    @api_key = api_key | 
| 59 | 
            -
                    @api_secret = api_secret | 
| 60 | 
            -
                    @api_passphrase = api_passphrase | 
| 69 | 
            +
                    @api_key = api_key
         | 
| 70 | 
            +
                    @api_secret = api_secret
         | 
| 71 | 
            +
                    @api_passphrase = api_passphrase
         | 
| 61 72 | 
             
                  end
         | 
| 62 73 |  | 
| 63 74 | 
             
                  def full_path(path)
         | 
| @@ -70,30 +81,28 @@ module Bitget | |
| 70 81 | 
             
                  end
         | 
| 71 82 |  | 
| 72 83 | 
             
                  def timestamp
         | 
| 73 | 
            -
                    @timestamp ||= Time.now.to_i.to_s
         | 
| 84 | 
            +
                    @timestamp ||= (Time.now.to_f * 1000).to_i.to_s
         | 
| 74 85 | 
             
                  end
         | 
| 75 86 |  | 
| 76 87 | 
             
                  def message(verb:, path:, args:)
         | 
| 77 | 
            -
                     | 
| 78 | 
            -
             | 
| 79 | 
            -
                       | 
| 80 | 
            -
                         | 
| 81 | 
            -
                      when 'POST'
         | 
| 82 | 
            -
                        nil
         | 
| 88 | 
            +
                    case verb
         | 
| 89 | 
            +
                    when 'GET'
         | 
| 90 | 
            +
                      if args.empty?
         | 
| 91 | 
            +
                        [timestamp, verb, full_path(path)].join
         | 
| 83 92 | 
             
                      else
         | 
| 84 | 
            -
                         | 
| 93 | 
            +
                        query_string = args.to_parameter_string
         | 
| 94 | 
            +
                        [timestamp, verb, full_path(path), '?', query_string].join
         | 
| 85 95 | 
             
                      end
         | 
| 86 | 
            -
                     | 
| 87 | 
            -
             | 
| 88 | 
            -
                    if query_string.nil?
         | 
| 96 | 
            +
                    when 'POST'
         | 
| 97 | 
            +
                      body = args.to_json
         | 
| 89 98 | 
             
                      [timestamp, verb, full_path(path), body].join
         | 
| 90 | 
            -
                    else
         | 
| 91 | 
            -
                      [timestamp, verb, full_path(path), '?', query_string, body].join
         | 
| 92 99 | 
             
                    end
         | 
| 93 100 | 
             
                  end
         | 
| 94 101 |  | 
| 95 102 | 
             
                  def signature(message)
         | 
| 96 | 
            -
                    OpenSSL:: | 
| 103 | 
            +
                    digest = OpenSSL::Digest.new('SHA256')
         | 
| 104 | 
            +
                    hmac = OpenSSL::HMAC.digest(digest, @api_secret, message)
         | 
| 105 | 
            +
                    Base64.strict_encode64(hmac)
         | 
| 97 106 | 
             
                  end
         | 
| 98 107 |  | 
| 99 108 | 
             
                  def request_string(path)
         | 
| @@ -106,9 +115,8 @@ module Bitget | |
| 106 115 | 
             
                      'ACCESS-SIGN' => signature,
         | 
| 107 116 | 
             
                      'ACCESS-TIMESTAMP' => timestamp,
         | 
| 108 117 | 
             
                      'ACCESS-PASSPHRASE' => @api_passphrase,
         | 
| 109 | 
            -
                      'Content- | 
| 110 | 
            -
                      ' | 
| 111 | 
            -
                      'Accept' => 'application/json',
         | 
| 118 | 
            +
                      'Content-Type' => 'application/json',
         | 
| 119 | 
            +
                      'X-CHANNEL-API-CODE' => 'spot',
         | 
| 112 120 | 
             
                    }
         | 
| 113 121 | 
             
                  end
         | 
| 114 122 |  | 
| @@ -133,7 +141,9 @@ module Bitget | |
| 133 141 | 
             
                    log_request(verb: verb, request_string: request_string(path), args: args)
         | 
| 134 142 | 
             
                    message = message(verb: verb, path: path, args: args)
         | 
| 135 143 | 
             
                    signature = signature(message)
         | 
| 136 | 
            -
                     | 
| 144 | 
            +
                    headers = headers(signature)
         | 
| 145 | 
            +
                    @timestamp = nil
         | 
| 146 | 
            +
                    HTTP.send(verb.to_s.downcase, request_string(path), args, headers)
         | 
| 137 147 | 
             
                  end
         | 
| 138 148 |  | 
| 139 149 | 
             
                  def get(path:, args: {})
         | 
| @@ -0,0 +1,500 @@ | |
| 1 | 
            +
            # Bitget/V2/Client.rb
         | 
| 2 | 
            +
            # Bitget::V2::Client
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'fileutils'
         | 
| 5 | 
            +
            gem 'http.rb'; require 'http.rb'
         | 
| 6 | 
            +
            require 'json'
         | 
| 7 | 
            +
            require 'logger'
         | 
| 8 | 
            +
            require 'openssl'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            require_relative '../Error'
         | 
| 11 | 
            +
            require_relative '../../Hash/to_parameter_string'
         | 
| 12 | 
            +
            require_relative '../../Hash/x_www_form_urlencode'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            module Bitget
         | 
| 15 | 
            +
              module V2
         | 
| 16 | 
            +
                class Client
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  API_HOST = 'api.bitget.com'
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  class << self
         | 
| 21 | 
            +
                    attr_writer :log_file_path
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    def path_prefix
         | 
| 24 | 
            +
                      '/api/v2'
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    def default_log_file_path
         | 
| 28 | 
            +
                      File.join(%w{~ log bitget log.txt})
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    def log_file_path
         | 
| 32 | 
            +
                      File.expand_path(@log_file_path || default_log_file_path)
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    def log_file
         | 
| 36 | 
            +
                      FileUtils.mkdir_p(File.dirname(log_file_path))
         | 
| 37 | 
            +
                      File.open(log_file_path, File::WRONLY | File::APPEND | File::CREAT)
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    def logger
         | 
| 41 | 
            +
                      @logger ||= Logger.new(log_file, 'daily')
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                  end # class << self
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  # Market
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def spot_public_coins(coin: nil)
         | 
| 48 | 
            +
                    response = get(path: '/spot/public/coins', args: {coin: coin})
         | 
| 49 | 
            +
                    handle_response(response)
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  def spot_public_symbols(symbol: nil)
         | 
| 53 | 
            +
                    response = get(path: '/spot/public/symbols', args: {symbol: symbol})
         | 
| 54 | 
            +
                    handle_response(response)
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  def spot_market_vip_free_rate
         | 
| 58 | 
            +
                    response = get(path: '/spot/market/vip-fee-rate')
         | 
| 59 | 
            +
                    handle_response(response)
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def spot_market_tickers(symbol: nil)
         | 
| 63 | 
            +
                    response = get(path: '/spot/market/tickers', args: {symbol: symbol})
         | 
| 64 | 
            +
                    handle_response(response)
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  def spot_market_merge_depth(symbol:, precision: nil, limit: nil)
         | 
| 68 | 
            +
                    response = get(path: '/spot/market/merge-depth', args: {symbol: symbol, precision: precision, limit: limit})
         | 
| 69 | 
            +
                    handle_response(response)
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  def spot_market_orderbook(symbol:, type: nil, limit: nil)
         | 
| 73 | 
            +
                    response = get(path: '/spot/market/orderbook', args: {symbol: symbol, type: type, limit: limit})
         | 
| 74 | 
            +
                    handle_response(response)
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  def spot_market_candles(symbol:, granularity:, start_time: nil, end_time: nil, limit: nil)
         | 
| 78 | 
            +
                    response = get(
         | 
| 79 | 
            +
                      path: '/spot/market/candles',
         | 
| 80 | 
            +
                      args: {symbol: symbol, granularity: granularity, startTime: start_time, endTime: end_time, limit: limit}
         | 
| 81 | 
            +
                    )
         | 
| 82 | 
            +
                    handle_response(response)
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  def spot_market_history_candles(symbol:, granularity:, end_time: nil, limit: nil)
         | 
| 86 | 
            +
                    response = get(
         | 
| 87 | 
            +
                      path: '/spot/market/history-candles',
         | 
| 88 | 
            +
                      args: {symbol: symbol, granularity: granularity, endTime: end_time, limit: limit}
         | 
| 89 | 
            +
                    )
         | 
| 90 | 
            +
                    handle_response(response)
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  def spot_market_fills(symbol:, limit: nil)
         | 
| 94 | 
            +
                    response = get(path: '/spot/market/fills', args: {symbol: symbol, limit: limit})
         | 
| 95 | 
            +
                    handle_response(response)
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  def spot_market_fills_history(symbol:, limit: nil, id_less_than: nil, start_time: nil, end_time: nil)
         | 
| 99 | 
            +
                    response = get(
         | 
| 100 | 
            +
                      path: '/spot/market/fills-history',
         | 
| 101 | 
            +
                      args: {symbol: symbol, limit: limit, idLessThan: id_less_than, startTime: start_time, endTime: end_time}
         | 
| 102 | 
            +
                    )
         | 
| 103 | 
            +
                    handle_response(response)
         | 
| 104 | 
            +
                  end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  # Trade
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                  def trade_place_order(
         | 
| 109 | 
            +
                    symbol:,
         | 
| 110 | 
            +
                    side:,
         | 
| 111 | 
            +
                    order_type:,
         | 
| 112 | 
            +
                    force:,
         | 
| 113 | 
            +
                    price: nil,
         | 
| 114 | 
            +
                    size:,
         | 
| 115 | 
            +
                    client_order_id: nil,
         | 
| 116 | 
            +
                    trigger_price: nil,
         | 
| 117 | 
            +
                    tpsl_type: nil,
         | 
| 118 | 
            +
                    request_time: nil,
         | 
| 119 | 
            +
                    receive_window: nil,
         | 
| 120 | 
            +
                    stp_mode: nil,
         | 
| 121 | 
            +
                    preset_take_profit_price: nil,
         | 
| 122 | 
            +
                    execute_take_profit_price: nil,
         | 
| 123 | 
            +
                    preset_stop_loss_price: nil,
         | 
| 124 | 
            +
                    execute_stop_loss_price: nil
         | 
| 125 | 
            +
                  )
         | 
| 126 | 
            +
                    response = post(
         | 
| 127 | 
            +
                      path: '/trade/place-order',
         | 
| 128 | 
            +
                      args: {
         | 
| 129 | 
            +
                        symbol: symbol,
         | 
| 130 | 
            +
                        side: side,
         | 
| 131 | 
            +
                        orderType: order_type,
         | 
| 132 | 
            +
                        force: force,
         | 
| 133 | 
            +
                        price: price,
         | 
| 134 | 
            +
                        size: size,
         | 
| 135 | 
            +
                        client_order_id: clientOid,
         | 
| 136 | 
            +
                        trigger_price: triggerPrice,
         | 
| 137 | 
            +
                        tpsl_type: tpslType,
         | 
| 138 | 
            +
                        request_time: requestTime,
         | 
| 139 | 
            +
                        receive_window: receiveWindow,
         | 
| 140 | 
            +
                        stp_mode: stpMode,
         | 
| 141 | 
            +
                        preset_take_profit_price: presetTakeProfitPrice,
         | 
| 142 | 
            +
                        execute_take_profit_price: executeTakeProfitPrice,
         | 
| 143 | 
            +
                        preset_stop_loss_price: presetStopLossPrice,
         | 
| 144 | 
            +
                        execute_stop_loss_price: executeStopLossPrice,
         | 
| 145 | 
            +
                      }
         | 
| 146 | 
            +
                    )
         | 
| 147 | 
            +
                    handle_response(response)
         | 
| 148 | 
            +
                  end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                  def trade_cancel_replace_order(
         | 
| 151 | 
            +
                    symbol:,
         | 
| 152 | 
            +
                    price:,
         | 
| 153 | 
            +
                    size:,
         | 
| 154 | 
            +
                    client_order_id: nil,
         | 
| 155 | 
            +
                    order_id: nil,
         | 
| 156 | 
            +
                    new_client_order_id: nil,
         | 
| 157 | 
            +
                    preset_take_profit_price: nil,
         | 
| 158 | 
            +
                    execute_take_profit_price: nil,
         | 
| 159 | 
            +
                    preset_stop_loss_price: nil,
         | 
| 160 | 
            +
                    execute_stop_loss_price: nil
         | 
| 161 | 
            +
                  )
         | 
| 162 | 
            +
                    response = post(
         | 
| 163 | 
            +
                      path: '/trade/cancel-replace-order',
         | 
| 164 | 
            +
                      args: {
         | 
| 165 | 
            +
                        symbol: symbol,
         | 
| 166 | 
            +
                        price: price,
         | 
| 167 | 
            +
                        size: size,
         | 
| 168 | 
            +
                        client_order_id: clientOid,
         | 
| 169 | 
            +
                        order_id: orderId,
         | 
| 170 | 
            +
                        newClientOid: new_client_order_id,
         | 
| 171 | 
            +
                        preset_take_profit_price: presetTakeProfitPrice,
         | 
| 172 | 
            +
                        execute_take_profit_price: executeTakeProfitPrice,
         | 
| 173 | 
            +
                        preset_stop_loss_price: presetStopLossPrice,
         | 
| 174 | 
            +
                        execute_stop_loss_price: executeStopLossPrice,
         | 
| 175 | 
            +
                      }
         | 
| 176 | 
            +
                    )
         | 
| 177 | 
            +
                    handle_response(response)
         | 
| 178 | 
            +
                  end
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                  # I got lazy... (with specifying the args)
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                  def trade_batch_cancel_replace_order(**args)
         | 
| 183 | 
            +
                    response = post(path: '/trade/batch-cancel-replace-order', args: args)
         | 
| 184 | 
            +
                    handle_response(response)
         | 
| 185 | 
            +
                  end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                  def trade_cancel_order(**args)
         | 
| 188 | 
            +
                    response = post(path: '/trade/cancel-order', args: args)
         | 
| 189 | 
            +
                    handle_response(response)
         | 
| 190 | 
            +
                  end
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                  def trade_batch_orders(**args)
         | 
| 193 | 
            +
                    response = post(path: '/trade/batch-orders', args: args)
         | 
| 194 | 
            +
                    handle_response(response)
         | 
| 195 | 
            +
                  end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                  def trade_batch_cancel_order
         | 
| 198 | 
            +
                    response = post(path: '/trade/batch-cancel-order', args: args)
         | 
| 199 | 
            +
                    handle_response(response)
         | 
| 200 | 
            +
                  end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                  def trade_cancel_symbol_order(symbol:)
         | 
| 203 | 
            +
                    response = post(path: '/trade/cancel-symbol-order', args: {symbol: symbol})
         | 
| 204 | 
            +
                    handle_response(response)
         | 
| 205 | 
            +
                  end
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                  def trade_order_info(**args)
         | 
| 208 | 
            +
                    response = get(path: '/trade/orderInfo', args: args)
         | 
| 209 | 
            +
                    handle_response(response)
         | 
| 210 | 
            +
                  end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                  def trade_unfilled_orders(**args)
         | 
| 213 | 
            +
                    response = get(path: '/trade/unfilled-orders', args: args)
         | 
| 214 | 
            +
                    handle_response(response)
         | 
| 215 | 
            +
                  end
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                  def trade_history_orders(**args)
         | 
| 218 | 
            +
                    response = get(path: '/trade/history-orders', args: args)
         | 
| 219 | 
            +
                    handle_response(response)
         | 
| 220 | 
            +
                  end
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                  def trade_fills(**args)
         | 
| 223 | 
            +
                    response = get(path: '/trade/fills', args: args)
         | 
| 224 | 
            +
                    handle_response(response)
         | 
| 225 | 
            +
                  end
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                  # Trigger
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                  # Place Plan Order
         | 
| 230 | 
            +
                  # POST /api/v2/spot/trade/place-plan-order
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                  # Modify Plan Order
         | 
| 233 | 
            +
                  # POST /api/v2/spot/trade/modify-plan-order
         | 
| 234 | 
            +
             | 
| 235 | 
            +
                  # Cancel Plan Order
         | 
| 236 | 
            +
                  # POST /api/v2/spot/trade/cancel-plan-order
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                  # Get Current Plan Orders
         | 
| 239 | 
            +
                  # GET /api/v2/spot/trade/current-plan-order
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                  # Get Plan Sub Order
         | 
| 242 | 
            +
                  # GET /api/v2/spot/trade/plan-sub-order
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                  # Get History Plan Orders
         | 
| 245 | 
            +
                  # GET /api/v2/spot/trade/history-plan-order
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                  # Cancel Plan Orders in Batch
         | 
| 248 | 
            +
                  # POST /api/v2/spot/trade/batch-cancel-plan-order
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                  # Account
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                  # Get Account Information
         | 
| 253 | 
            +
                  # GET /api/v2/spot/account/info
         | 
| 254 | 
            +
                  def spot_account_info
         | 
| 255 | 
            +
                    response = get(path: '/spot/account/info')
         | 
| 256 | 
            +
                    handle_response(response)
         | 
| 257 | 
            +
                  end
         | 
| 258 | 
            +
             | 
| 259 | 
            +
                  # Get Account Assets
         | 
| 260 | 
            +
                  # GET /api/v2/spot/account/assets
         | 
| 261 | 
            +
                  def spot_account_assets(**args)
         | 
| 262 | 
            +
                    response = get(path: '/spot/account/assets', args: args)
         | 
| 263 | 
            +
                    handle_response(response)
         | 
| 264 | 
            +
                  end
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                  # Get Sub-accounts Assets
         | 
| 267 | 
            +
                  # GET /api/v2/spot/account/subaccount-assets
         | 
| 268 | 
            +
                  def spot_account_subaccount_assets(**args)
         | 
| 269 | 
            +
                    response = get(path: '/spot/account/subaccount-assets', args: args)
         | 
| 270 | 
            +
                    handle_response(response)
         | 
| 271 | 
            +
                  end
         | 
| 272 | 
            +
             | 
| 273 | 
            +
                  # Modify Deposit Account
         | 
| 274 | 
            +
                  # POST /api/v2/spot/wallet/modify-deposit-account
         | 
| 275 | 
            +
                  def spot_wallet_modify_deposit_account(**args)
         | 
| 276 | 
            +
                    response = post(path: '/spot/wallet/modify-deposit-account', args: args)
         | 
| 277 | 
            +
                    handle_response(response)
         | 
| 278 | 
            +
                  end
         | 
| 279 | 
            +
             | 
| 280 | 
            +
                  # Get Account Bills
         | 
| 281 | 
            +
                  # GET /api/v2/spot/account/bills
         | 
| 282 | 
            +
                  def spot_account_bills(**args)
         | 
| 283 | 
            +
                    response = get(path: '/spot/account/bills', args: args)
         | 
| 284 | 
            +
                    handle_response(response)
         | 
| 285 | 
            +
                  end
         | 
| 286 | 
            +
             | 
| 287 | 
            +
                  # Transfer
         | 
| 288 | 
            +
                  # POST /api/v2/spot/wallet/transfer
         | 
| 289 | 
            +
                  def spot_wallet_transfer(**args)
         | 
| 290 | 
            +
                    response = post(path: '/spot/wallet/transfer', args: args)
         | 
| 291 | 
            +
                    handle_response(response)
         | 
| 292 | 
            +
                  end
         | 
| 293 | 
            +
             | 
| 294 | 
            +
                  # GET Transferable Coin List
         | 
| 295 | 
            +
                  # GET /api/v2/spot/wallet/transfer-coin-info
         | 
| 296 | 
            +
                  def spot_wallet_transfer_coin_info(**args)
         | 
| 297 | 
            +
                    response = get(path: '/spot/wallet/transfer-coin-info', args: args)
         | 
| 298 | 
            +
                    handle_response(response)
         | 
| 299 | 
            +
                  end
         | 
| 300 | 
            +
             | 
| 301 | 
            +
                  # Sub Transfer
         | 
| 302 | 
            +
                  # POST /api/v2/spot/wallet/subaccount-transfer
         | 
| 303 | 
            +
                  def spot_wallet_subaccount_transer(**args)
         | 
| 304 | 
            +
                    response = post(path: '/spot/wallet/subaccount-transfer', args: args)
         | 
| 305 | 
            +
                    handle_response(response)
         | 
| 306 | 
            +
                  end
         | 
| 307 | 
            +
             | 
| 308 | 
            +
                  # Withdraw
         | 
| 309 | 
            +
                  # POST /api/v2/spot/wallet/withdrawal
         | 
| 310 | 
            +
                  def spot_wallet_withdrawal(**args)
         | 
| 311 | 
            +
                    response = post(path: '/spot/wallet/withdrawal', args: args)
         | 
| 312 | 
            +
                    handle_response(response)
         | 
| 313 | 
            +
                  end
         | 
| 314 | 
            +
             | 
| 315 | 
            +
                  # Get MainSub Transfer Record
         | 
| 316 | 
            +
                  # GET /api/v2/spot/account/sub-main-trans-record
         | 
| 317 | 
            +
                  def spot_account_sub_main_trans_record(**args)
         | 
| 318 | 
            +
                    response = get(path: '/spot/account/sub-main-trans-record', args: args)
         | 
| 319 | 
            +
                    handle_response(response)
         | 
| 320 | 
            +
                  end
         | 
| 321 | 
            +
             | 
| 322 | 
            +
                  # Get Transfer Record
         | 
| 323 | 
            +
                  # GET /api/v2/spot/account/transferRecords
         | 
| 324 | 
            +
                  def spot_account_transfer_records(**args)
         | 
| 325 | 
            +
                    response = get(path: '/spot/account/transferRecords', args: args)
         | 
| 326 | 
            +
                    handle_response(response)
         | 
| 327 | 
            +
                  end
         | 
| 328 | 
            +
             | 
| 329 | 
            +
                  # Switch BGB Deduct
         | 
| 330 | 
            +
                  # POST /api/v2/spot/account/switch-deduct
         | 
| 331 | 
            +
                  def spot_account_switch_deduct(deduct:)
         | 
| 332 | 
            +
                    response = post(path: '/spot/account/switch-deduct', args: {deduct: deduct})
         | 
| 333 | 
            +
                    handle_response(response)
         | 
| 334 | 
            +
                  end
         | 
| 335 | 
            +
             | 
| 336 | 
            +
                  # Get Deposit Address
         | 
| 337 | 
            +
                  # GET /api/v2/spot/wallet/deposit-address
         | 
| 338 | 
            +
                  def spot_wallet_deposit_address(**args)
         | 
| 339 | 
            +
                    response = get(path: '/spot/wallet/deposit-address', args: args)
         | 
| 340 | 
            +
                    handle_response(response)
         | 
| 341 | 
            +
                  end
         | 
| 342 | 
            +
             | 
| 343 | 
            +
                  # Get SubAccount Deposit Address
         | 
| 344 | 
            +
                  # GET /api/v2/spot/wallet/subaccount-deposit-address
         | 
| 345 | 
            +
                  def spot_wallet_subaccount_deposit_address(**args)
         | 
| 346 | 
            +
                    response = get(path: '/spot/wallet/subaccount-deposit-address', args: args)
         | 
| 347 | 
            +
                    handle_response(response)
         | 
| 348 | 
            +
                  end
         | 
| 349 | 
            +
             | 
| 350 | 
            +
                  # Get BGB Deduct Info
         | 
| 351 | 
            +
                  # GET /api/v2/spot/account/deduct-info
         | 
| 352 | 
            +
                  def spot_account_deduct_info
         | 
| 353 | 
            +
                    response = get(path: '/spot/account/deduct-info')
         | 
| 354 | 
            +
                    handle_response(response)
         | 
| 355 | 
            +
                  end
         | 
| 356 | 
            +
             | 
| 357 | 
            +
                  # Cancel Withdrawal
         | 
| 358 | 
            +
                  # POST /api/v2/spot/wallet/cancel-withdrawal
         | 
| 359 | 
            +
                  def spot_wallet_cancel_withdrawal(order_id:)
         | 
| 360 | 
            +
                    response = post(path: '/spot/wallet/cancel-withdrawal', args: {order_id: order_id})
         | 
| 361 | 
            +
                    handle_response(response)
         | 
| 362 | 
            +
                  end
         | 
| 363 | 
            +
             | 
| 364 | 
            +
                  # Get SubAccount Deposit Records
         | 
| 365 | 
            +
                  # GET /api/v2/spot/wallet/subaccount-deposit-records
         | 
| 366 | 
            +
                  def spot_wallet_subaccount_deposit_records(**args)
         | 
| 367 | 
            +
                    response = get(path: '/spot/wallet/subaccount-deposit-records', args: args)
         | 
| 368 | 
            +
                    handle_response(response)
         | 
| 369 | 
            +
                  end
         | 
| 370 | 
            +
             | 
| 371 | 
            +
                  # Get Withdrawal Records
         | 
| 372 | 
            +
                  # GET /api/v2/spot/wallet/withdrawal-records
         | 
| 373 | 
            +
                  def spot_wallet_withdrawal_records(**args)
         | 
| 374 | 
            +
                    response = get(path: '/spot/wallet/withdrawal-records', args: args)
         | 
| 375 | 
            +
                    handle_response(response)
         | 
| 376 | 
            +
                  end
         | 
| 377 | 
            +
             | 
| 378 | 
            +
                  # Get Deposit Records
         | 
| 379 | 
            +
                  # GET /api/v2/spot/wallet/deposit-records
         | 
| 380 | 
            +
                  def spot_wallet_deposit_records(**args)
         | 
| 381 | 
            +
                    response = get(path: '/spot/wallet/deposit-records', args: args)
         | 
| 382 | 
            +
                    handle_response(response)
         | 
| 383 | 
            +
                  end
         | 
| 384 | 
            +
             | 
| 385 | 
            +
                  private
         | 
| 386 | 
            +
             | 
| 387 | 
            +
                  def initialize(api_key:, api_secret:, api_passphrase:)
         | 
| 388 | 
            +
                    @api_key = api_key
         | 
| 389 | 
            +
                    @api_secret = api_secret
         | 
| 390 | 
            +
                    @api_passphrase = api_passphrase
         | 
| 391 | 
            +
                  end
         | 
| 392 | 
            +
             | 
| 393 | 
            +
                  def initialize(api_key:, api_secret:, api_passphrase:)
         | 
| 394 | 
            +
                    @api_key = api_key.encode('UTF-8')
         | 
| 395 | 
            +
                    @api_secret = api_secret.encode('UTF-8')
         | 
| 396 | 
            +
                    @api_passphrase = api_passphrase.encode('UTF-8')
         | 
| 397 | 
            +
                  end
         | 
| 398 | 
            +
             | 
| 399 | 
            +
                  def full_path(path)
         | 
| 400 | 
            +
                    self.class.path_prefix + path
         | 
| 401 | 
            +
                  end
         | 
| 402 | 
            +
             | 
| 403 | 
            +
                  def encoded_payload(args)
         | 
| 404 | 
            +
                    args.reject!{|k,v| v.nil?}
         | 
| 405 | 
            +
                    OpenSSL::Digest::SHA512.hexdigest(JSON.dump(args))
         | 
| 406 | 
            +
                  end
         | 
| 407 | 
            +
             | 
| 408 | 
            +
                  def timestamp
         | 
| 409 | 
            +
                    @timestamp ||= (Time.now.to_f * 1000).to_i.to_s
         | 
| 410 | 
            +
                  end
         | 
| 411 | 
            +
             | 
| 412 | 
            +
                  def message(verb:, path:, args:)
         | 
| 413 | 
            +
                    case verb
         | 
| 414 | 
            +
                    when 'GET'
         | 
| 415 | 
            +
                      if args.empty?
         | 
| 416 | 
            +
                        [timestamp, verb, full_path(path)].join
         | 
| 417 | 
            +
                      else
         | 
| 418 | 
            +
                        query_string = args.to_parameter_string
         | 
| 419 | 
            +
                        [timestamp, verb, full_path(path), '?', query_string].join
         | 
| 420 | 
            +
                      end
         | 
| 421 | 
            +
                    when 'POST'
         | 
| 422 | 
            +
                      body = args.to_json
         | 
| 423 | 
            +
                      [timestamp, verb, full_path(path), body].join
         | 
| 424 | 
            +
                    end
         | 
| 425 | 
            +
                  end
         | 
| 426 | 
            +
             | 
| 427 | 
            +
                  def signature(message)
         | 
| 428 | 
            +
                    digest = OpenSSL::Digest.new('SHA256')
         | 
| 429 | 
            +
                    hmac = OpenSSL::HMAC.digest(digest, @api_secret, message)
         | 
| 430 | 
            +
                    Base64.strict_encode64(hmac)
         | 
| 431 | 
            +
                  end
         | 
| 432 | 
            +
             | 
| 433 | 
            +
                  def request_string(path)
         | 
| 434 | 
            +
                    "https://#{API_HOST}#{self.class.path_prefix}#{path}"
         | 
| 435 | 
            +
                  end
         | 
| 436 | 
            +
             | 
| 437 | 
            +
                  def headers(signature)
         | 
| 438 | 
            +
                    {
         | 
| 439 | 
            +
                      'ACCESS-KEY' => @api_key,
         | 
| 440 | 
            +
                      'ACCESS-SIGN' => signature,
         | 
| 441 | 
            +
                      'ACCESS-TIMESTAMP' => timestamp,
         | 
| 442 | 
            +
                      'ACCESS-PASSPHRASE' => @api_passphrase,
         | 
| 443 | 
            +
                      'Content-Type' => 'application/json',
         | 
| 444 | 
            +
                      'X-CHANNEL-API-CODE' => 'spot',
         | 
| 445 | 
            +
                    }
         | 
| 446 | 
            +
                  end
         | 
| 447 | 
            +
             | 
| 448 | 
            +
                  def log_args?(args)
         | 
| 449 | 
            +
                    !args.values.all?(&:nil?)
         | 
| 450 | 
            +
                  end
         | 
| 451 | 
            +
             | 
| 452 | 
            +
                  def log_request(verb:, request_string:, args:)
         | 
| 453 | 
            +
                    log_string = "#{verb} #{request_string}"
         | 
| 454 | 
            +
                    if log_args?(args)
         | 
| 455 | 
            +
                      log_string << "?#{args.x_www_form_urlencode}"
         | 
| 456 | 
            +
                    end
         | 
| 457 | 
            +
                    self.class.logger.info(log_string)
         | 
| 458 | 
            +
                  end
         | 
| 459 | 
            +
             | 
| 460 | 
            +
                  def log_error(code:, message:, body:)
         | 
| 461 | 
            +
                    log_string = "#{code}\n#{message}\n#{body}"
         | 
| 462 | 
            +
                    self.class.logger.error(log_string)
         | 
| 463 | 
            +
                  end
         | 
| 464 | 
            +
             | 
| 465 | 
            +
                  def do_request(verb:, path:, args: {})
         | 
| 466 | 
            +
                    log_request(verb: verb, request_string: request_string(path), args: args)
         | 
| 467 | 
            +
                    message = message(verb: verb, path: path, args: args)
         | 
| 468 | 
            +
                    signature = signature(message)
         | 
| 469 | 
            +
                    headers = headers(signature)
         | 
| 470 | 
            +
                    @timestamp = nil
         | 
| 471 | 
            +
                    HTTP.send(verb.to_s.downcase, request_string(path), args, headers)
         | 
| 472 | 
            +
                  end
         | 
| 473 | 
            +
             | 
| 474 | 
            +
                  def get(path:, args: {})
         | 
| 475 | 
            +
                    do_request(verb: 'GET', path: path, args: args)
         | 
| 476 | 
            +
                  end
         | 
| 477 | 
            +
             | 
| 478 | 
            +
                  def post(path:, args: {})
         | 
| 479 | 
            +
                    do_request(verb: 'POST', path: path, args: args)
         | 
| 480 | 
            +
                  end
         | 
| 481 | 
            +
             | 
| 482 | 
            +
                  def handle_response(response)
         | 
| 483 | 
            +
                    if response.success?
         | 
| 484 | 
            +
                      JSON.parse(response.body)
         | 
| 485 | 
            +
                    else
         | 
| 486 | 
            +
                      log_error(
         | 
| 487 | 
            +
                        code: response.code,
         | 
| 488 | 
            +
                        message: response.message,
         | 
| 489 | 
            +
                        body: response.body
         | 
| 490 | 
            +
                      )
         | 
| 491 | 
            +
                      raise Bitget::Error.new(
         | 
| 492 | 
            +
                        code: response.code,
         | 
| 493 | 
            +
                        message: response.message,
         | 
| 494 | 
            +
                        body: response.body
         | 
| 495 | 
            +
                      )
         | 
| 496 | 
            +
                    end
         | 
| 497 | 
            +
                  end
         | 
| 498 | 
            +
                end
         | 
| 499 | 
            +
              end
         | 
| 500 | 
            +
            end
         | 
    
        data/lib/bitget.rb
    CHANGED
    
    
    
        data/test/V2/client_test.rb
    CHANGED
    
    | @@ -4,9 +4,9 @@ require_relative '../../lib/Bitget/V2/Client' | |
| 4 4 | 
             
            describe Bitget::V2::Client do
         | 
| 5 5 | 
             
              let(:client) do
         | 
| 6 6 | 
             
                Bitget::V2::Client.new(
         | 
| 7 | 
            -
                  api_key:  | 
| 8 | 
            -
                  api_secret:  | 
| 9 | 
            -
                  api_passphrase:  | 
| 7 | 
            +
                  api_key: ENV.fetch('BITGET_API_KEY', '<API_KEY>'),
         | 
| 8 | 
            +
                  api_secret: ENV.fetch('BITGET_API_SECRET', '<API_SECRET>'),
         | 
| 9 | 
            +
                  api_passphrase: ENV.fetch('BITGET_API_PASSPHRASE', '<API_PASSPHRASE>')
         | 
| 10 10 | 
             
                )
         | 
| 11 11 | 
             
              end
         | 
| 12 12 |  | 
| @@ -50,4 +50,60 @@ describe Bitget::V2::Client do | |
| 50 50 | 
             
                  end
         | 
| 51 51 | 
             
                end
         | 
| 52 52 | 
             
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              describe "#spot_account_info" do
         | 
| 55 | 
            +
                it "retrieves account information" do
         | 
| 56 | 
            +
                  VCR.use_cassette('v2/spot/account/info') do
         | 
| 57 | 
            +
                    response = client.spot_account_info
         | 
| 58 | 
            +
                    _(response).must_include('data')
         | 
| 59 | 
            +
                    _(response['data']).must_include('userId')
         | 
| 60 | 
            +
                    _(response['data']).must_include('channelCode')
         | 
| 61 | 
            +
                    _(response['data']).must_include('authorities')
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                context "when an error occurs" do
         | 
| 66 | 
            +
                  it "logs then raises an error" do
         | 
| 67 | 
            +
                    VCR.use_cassette('v2/spot/account/info-when_an_error_occurs') do
         | 
| 68 | 
            +
                      assert_raises(Bitget::Error) do
         | 
| 69 | 
            +
                        mocked_method = Minitest::Mock.new
         | 
| 70 | 
            +
                        mocked_method.expect(:call, nil, [], code: '418', message: "I'm a teapot", body: '')
         | 
| 71 | 
            +
                        client.stub(:log_error, mocked_method) do
         | 
| 72 | 
            +
                          client.spot_account_info
         | 
| 73 | 
            +
                        end
         | 
| 74 | 
            +
                        mocked_method.verify
         | 
| 75 | 
            +
                      end
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              describe "#spot_account_assets" do
         | 
| 82 | 
            +
                it "retrieves account assets" do
         | 
| 83 | 
            +
                  VCR.use_cassette('v2/spot/account/assets') do
         | 
| 84 | 
            +
                    response = client.spot_account_assets
         | 
| 85 | 
            +
                    _(response).must_include('data')
         | 
| 86 | 
            +
                    _(response['data'].first).must_include('coin')
         | 
| 87 | 
            +
                    _(response['data'].first).must_include('available')
         | 
| 88 | 
            +
                    _(response['data'].first).must_include('frozen')
         | 
| 89 | 
            +
                    _(response['data'].first).must_include('locked')
         | 
| 90 | 
            +
                    _(response['data'].first).must_include('uTime')
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                context "when an error occurs" do
         | 
| 95 | 
            +
                  it "logs then raises an error" do
         | 
| 96 | 
            +
                    VCR.use_cassette('v2/spot/account/assets-when_an_error_occurs') do
         | 
| 97 | 
            +
                      assert_raises(Bitget::Error) do
         | 
| 98 | 
            +
                        mocked_method = Minitest::Mock.new
         | 
| 99 | 
            +
                        mocked_method.expect(:call, nil, [], code: '418', message: "I'm a teapot", body: '')
         | 
| 100 | 
            +
                        client.stub(:log_error, mocked_method) do
         | 
| 101 | 
            +
                          client.spot_account_assets
         | 
| 102 | 
            +
                        end
         | 
| 103 | 
            +
                        mocked_method.verify
         | 
| 104 | 
            +
                      end
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
              end
         | 
| 53 109 | 
             
            end
         | 
    
        data/test/client_test.rb
    CHANGED
    
    | @@ -4,9 +4,9 @@ require_relative '../lib/Bitget/Client' | |
| 4 4 | 
             
            describe Bitget::Client do
         | 
| 5 5 | 
             
              let(:client) do
         | 
| 6 6 | 
             
                Bitget::Client.new(
         | 
| 7 | 
            -
                  api_key:  | 
| 8 | 
            -
                  api_secret:  | 
| 9 | 
            -
                  api_passphrase:  | 
| 7 | 
            +
                  api_key: ENV.fetch('BITGET_API_KEY', '<API_KEY>'),
         | 
| 8 | 
            +
                  api_secret: ENV.fetch('BITGET_API_SECRET', '<API_SECRET>'),
         | 
| 9 | 
            +
                  api_passphrase: ENV.fetch('BITGET_API_PASSPHRASE', '<API_PASSPHRASE>')
         | 
| 10 10 | 
             
                )
         | 
| 11 11 | 
             
              end
         | 
| 12 12 |  | 
| @@ -50,4 +50,60 @@ describe Bitget::Client do | |
| 50 50 | 
             
                  end
         | 
| 51 51 | 
             
                end
         | 
| 52 52 | 
             
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              describe "#spot_account_info" do
         | 
| 55 | 
            +
                it "retrieves account information" do
         | 
| 56 | 
            +
                  VCR.use_cassette('v2/spot/account/info') do
         | 
| 57 | 
            +
                    response = client.spot_account_info
         | 
| 58 | 
            +
                    _(response).must_include('data')
         | 
| 59 | 
            +
                    _(response['data']).must_include('userId')
         | 
| 60 | 
            +
                    _(response['data']).must_include('channelCode')
         | 
| 61 | 
            +
                    _(response['data']).must_include('authorities')
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                context "when an error occurs" do
         | 
| 66 | 
            +
                  it "logs then raises an error" do
         | 
| 67 | 
            +
                    VCR.use_cassette('v2/spot/account/info-when_an_error_occurs') do
         | 
| 68 | 
            +
                      assert_raises(Bitget::Error) do
         | 
| 69 | 
            +
                        mocked_method = Minitest::Mock.new
         | 
| 70 | 
            +
                        mocked_method.expect(:call, nil, [], code: '418', message: "I'm a teapot", body: '')
         | 
| 71 | 
            +
                        client.stub(:log_error, mocked_method) do
         | 
| 72 | 
            +
                          client.spot_account_info
         | 
| 73 | 
            +
                        end
         | 
| 74 | 
            +
                        mocked_method.verify
         | 
| 75 | 
            +
                      end
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              describe "#spot_account_assets" do
         | 
| 82 | 
            +
                it "retrieves account assets" do
         | 
| 83 | 
            +
                  VCR.use_cassette('v2/spot/account/assets') do
         | 
| 84 | 
            +
                    response = client.spot_account_assets
         | 
| 85 | 
            +
                    _(response).must_include('data')
         | 
| 86 | 
            +
                    _(response['data'].first).must_include('coin')
         | 
| 87 | 
            +
                    _(response['data'].first).must_include('available')
         | 
| 88 | 
            +
                    _(response['data'].first).must_include('frozen')
         | 
| 89 | 
            +
                    _(response['data'].first).must_include('locked')
         | 
| 90 | 
            +
                    _(response['data'].first).must_include('uTime')
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                context "when an error occurs" do
         | 
| 95 | 
            +
                  it "logs then raises an error" do
         | 
| 96 | 
            +
                    VCR.use_cassette('v2/spot/account/assets-when_an_error_occurs') do
         | 
| 97 | 
            +
                      assert_raises(Bitget::Error) do
         | 
| 98 | 
            +
                        mocked_method = Minitest::Mock.new
         | 
| 99 | 
            +
                        mocked_method.expect(:call, nil, [], code: '418', message: "I'm a teapot", body: '')
         | 
| 100 | 
            +
                        client.stub(:log_error, mocked_method) do
         | 
| 101 | 
            +
                          client.spot_account_assets
         | 
| 102 | 
            +
                        end
         | 
| 103 | 
            +
                        mocked_method.verify
         | 
| 104 | 
            +
                      end
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
              end
         | 
| 53 109 | 
             
            end
         | 
    
        data/test/helper.rb
    CHANGED
    
    | @@ -1,34 +1,13 @@ | |
| 1 1 | 
             
            require 'minitest/autorun'
         | 
| 2 2 | 
             
            require 'minitest-spec-context'
         | 
| 3 3 | 
             
            require 'minitest/spec'
         | 
| 4 | 
            -
            require 'ostruct'
         | 
| 5 4 | 
             
            require 'vcr'
         | 
| 6 5 |  | 
| 7 6 | 
             
            VCR.configure do |config|
         | 
| 8 7 | 
             
              config.cassette_library_dir = File.expand_path('../fixtures/vcr_cassettes', __FILE__)
         | 
| 9 8 | 
             
              config.hook_into :webmock
         | 
| 10 | 
            -
            end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            def api_key
         | 
| 13 | 
            -
              if ENV['BITGET_API_KEY']
         | 
| 14 | 
            -
                ENV['BITGET_API_KEY']
         | 
| 15 | 
            -
              else
         | 
| 16 | 
            -
                'api_key0'
         | 
| 17 | 
            -
              end
         | 
| 18 | 
            -
            end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
            def api_secret
         | 
| 21 | 
            -
              if ENV['BITGET_API_SECRET']
         | 
| 22 | 
            -
                ENV['BITGET_API_SECRET']
         | 
| 23 | 
            -
              else
         | 
| 24 | 
            -
                'api_secret0'
         | 
| 25 | 
            -
              end
         | 
| 26 | 
            -
            end
         | 
| 27 9 |  | 
| 28 | 
            -
             | 
| 29 | 
            -
               | 
| 30 | 
            -
             | 
| 31 | 
            -
              else
         | 
| 32 | 
            -
                'api_passphrase0'
         | 
| 33 | 
            -
              end
         | 
| 10 | 
            +
              config.filter_sensitive_data('<API_KEY>'){ENV['BITGET_API_KEY']}
         | 
| 11 | 
            +
              config.filter_sensitive_data('<API_SECRET>'){ENV['BITGET_API_SECRET'] }
         | 
| 12 | 
            +
              config.filter_sensitive_data('<API_PASSPHRASE>'){ENV['BITGET_API_PASSPHRASE']}
         | 
| 34 13 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: bitget.rb
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.4.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - thoran
         | 
| 8 8 | 
             
            bindir: bin
         | 
| 9 9 | 
             
            cert_chain: []
         | 
| 10 | 
            -
            date: 2025- | 
| 10 | 
            +
            date: 2025-05-16 00:00:00.000000000 Z
         | 
| 11 11 | 
             
            dependencies:
         | 
| 12 12 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 13 13 | 
             
              name: http.rb
         | 
| @@ -35,7 +35,8 @@ files: | |
| 35 35 | 
             
            - lib/Bitget/Client.rb
         | 
| 36 36 | 
             
            - lib/Bitget/Error.rb
         | 
| 37 37 | 
             
            - lib/Bitget/V2/Client.rb
         | 
| 38 | 
            -
            - lib/Bitget/ | 
| 38 | 
            +
            - lib/Bitget/V2/Client2.rb
         | 
| 39 | 
            +
            - lib/Bitget/VERSION.rb
         | 
| 39 40 | 
             
            - lib/Hash/to_parameter_string.rb
         | 
| 40 41 | 
             
            - lib/Hash/x_www_form_urlencode.rb
         | 
| 41 42 | 
             
            - lib/String/url_encode.rb
         | 
| @@ -64,7 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 64 65 | 
             
                - !ruby/object:Gem::Version
         | 
| 65 66 | 
             
                  version: '0'
         | 
| 66 67 | 
             
            requirements: []
         | 
| 67 | 
            -
            rubygems_version: 3.6. | 
| 68 | 
            +
            rubygems_version: 3.6.8
         | 
| 68 69 | 
             
            specification_version: 4
         | 
| 69 70 | 
             
            summary: Access the Bitget API with Ruby.
         | 
| 70 71 | 
             
            test_files: []
         |