├── Gemfile ├── lib ├── zaif │ ├── version.rb │ └── exceptions.rb └── zaif.rb ├── spec ├── spec_helper.rb └── etwings_spec.rb ├── .gitignore ├── examples ├── config.default.rb ├── test_trade.rb └── test.rb ├── Rakefile ├── README.md ├── zaif.gemspec └── LICENSE.txt /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /lib/zaif/version.rb: -------------------------------------------------------------------------------- 1 | module Zaif 2 | VERSION = "0.0.2" 3 | end 4 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) 2 | require 'etwings' 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.sh 3 | pkg/* 4 | doc/* 5 | Gemfile.lock 6 | *.gem 7 | bin 8 | docs/_build 9 | config.rb 10 | -------------------------------------------------------------------------------- /examples/config.default.rb: -------------------------------------------------------------------------------- 1 | # You can obtain from https://exchange.etwings.com/api_keys 2 | ZAIF_KEY = "" 3 | ZAIF_SECRET = "" 4 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | #require "rspec/core/rake_task" 3 | 4 | #RSpec::Core::RakeTask.new(:spec) 5 | 6 | #task :default => :spec 7 | 8 | -------------------------------------------------------------------------------- /lib/zaif/exceptions.rb: -------------------------------------------------------------------------------- 1 | module Zaif 2 | class ConnectionFailedException < StandardError; end 3 | class APIErrorException < StandardError; end 4 | class JSONException < StandardError; end 5 | end 6 | -------------------------------------------------------------------------------- /examples/test_trade.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # coding: utf-8 3 | require "zaif" 4 | require "./config.rb" 5 | require "pp" 6 | api = Zaif::API.new(:api_key => ZAIF_KEY, :api_secret => ZAIF_SECRET) 7 | api.bid("mona", 23, 1) 8 | 9 | api.get_info 10 | -------------------------------------------------------------------------------- /spec/etwings_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Etwings do 4 | it 'has a version number' do 5 | expect(Etwings::VERSION).not_to be nil 6 | end 7 | 8 | # it 'does something useful' do 9 | # expect(false).to eq(true) 10 | # end 11 | end 12 | -------------------------------------------------------------------------------- /examples/test.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # coding: utf-8 3 | require "zaif" 4 | require "pp" 5 | api = Zaif::API.new 6 | 7 | puts "MONA/JPY: " + api.get_last_price("mona").to_s 8 | puts "BTC/JPY : " + api.get_last_price("btc").to_s 9 | p api.get_ticker("mona") 10 | p api.get_trades("mona") 11 | p api.get_depth("mona") 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zaif 2 | 3 | Zaif API wrapper for ruby. 4 | 5 | ## Installation 6 | 7 | Add this line to your application's Gemfile: 8 | 9 | gem 'zaif' 10 | 11 | And then execute: 12 | 13 | $ bundle 14 | 15 | Or install it yourself as: 16 | 17 | $ gem install zaif 18 | 19 | ## Usage 20 | 21 | ```ruby 22 | require 'zaif' 23 | 24 | api = Zaif::API.new(:api_key => ZAIF_KEY, :api_secret => ZAIF_SECRET) 25 | api.bid("btc", 30760, 0.0001) 26 | api.ask("btc", 30320, 0.0001) 27 | 28 | api.get_info 29 | ``` 30 | 31 | ## Contributing 32 | 33 | 1. Fork it ( https://github.com/palon7/zaif-ruby/fork ) 34 | 2. Create your feature branch (`git checkout -b my-new-feature`) 35 | 3. Commit your changes (`git commit -am 'Add some feature'`) 36 | 4. Push to the branch (`git push origin my-new-feature`) 37 | 5. Create a new Pull Request 38 | -------------------------------------------------------------------------------- /zaif.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'zaif/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "zaif" 8 | spec.version = Zaif::VERSION 9 | spec.authors = ["Palon"] 10 | spec.email = ["palon7@gmail.com"] 11 | spec.summary = %q{Zaif API wrapper.} 12 | spec.description = %q{Zaif API wrapper for monacoin/bitcoin trade.} 13 | spec.homepage = "https://github.com/palon7/zaif-ruby" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files -z`.split("\x0") 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ["lib"] 20 | 21 | spec.add_development_dependency "bundler", "~> 1.6" 22 | spec.add_development_dependency "rake", "~>0" 23 | spec.add_development_dependency "rspec", "~>0" 24 | end 25 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Palon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/zaif.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | require 'pp' 3 | require 'json' 4 | require 'openssl' 5 | require 'uri' 6 | require 'net/http' 7 | require 'time' 8 | 9 | require "zaif/version" 10 | require "zaif/exceptions" 11 | 12 | module Zaif 13 | class API 14 | def initialize(opt = {}) 15 | @cool_down = opt[:cool_down] || true 16 | @cool_down_time = opt[:cool_down_time] || 2 17 | @cert_path = opt[:cert_path] || nil 18 | @api_key = opt[:api_key] || nil 19 | @api_secret = opt[:api_secret] || nil 20 | @zaif_public_url = "https://api.zaif.jp/api/1/" 21 | @zaif_trade_url = "https://api.zaif.jp/tapi" 22 | end 23 | 24 | def set_api_key(api_key, api_secret) 25 | @api_key = api_key 26 | @api_secret = api_secret 27 | end 28 | 29 | # 30 | # Public API 31 | # 32 | 33 | # Get last price of *currency_code* / *counter_currency_code*. 34 | # @param [String] currency_code Base currency code 35 | # @param [String] counter_currency_code Counter currency code 36 | def get_last_price(currency_code, counter_currency_code = "jpy") 37 | json = get_ssl(@zaif_public_url + "last_price/" + currency_code + "_" + counter_currency_code) 38 | return json["last_price"] 39 | end 40 | 41 | # Get ticker of *currency_code* / *counter_currency_code*. 42 | # @param [String] currency_code Base currency code 43 | # @param [String] counter_currency_code Counter currency code 44 | def get_ticker(currency_code, counter_currency_code = "jpy") 45 | json = get_ssl(@zaif_public_url + "ticker/" + currency_code + "_" + counter_currency_code) 46 | return json 47 | end 48 | 49 | # Get trades of *currency_code* / *counter_currency_code*. 50 | # @param [String] currency_code Base currency code 51 | # @param [String] counter_currency_code Counter currency code 52 | def get_trades(currency_code, counter_currency_code = "jpy") 53 | json = get_ssl(@zaif_public_url + "trades/" + currency_code + "_" + counter_currency_code) 54 | return json 55 | end 56 | 57 | # Get depth of *currency_code* / *counter_currency_code*. 58 | # @param [String] currency_code Base currency code 59 | # @param [String] counter_currency_code Counter currency code 60 | def get_depth(currency_code, counter_currency_code = "jpy") 61 | json = get_ssl(@zaif_public_url + "depth/" + currency_code + "_" + counter_currency_code) 62 | return json 63 | end 64 | 65 | # 66 | # Trade API 67 | # 68 | 69 | # Get user infomation. 70 | # Need api key. 71 | # @return [Hash] Infomation of user. 72 | def get_info 73 | json = post_ssl(@zaif_trade_url, "get_info", {}) 74 | return json 75 | end 76 | 77 | # Get your trade history. 78 | # Avalible options: from. count, from_id, end_id, order, since, end, currency_pair 79 | # Need api key. 80 | # @param [Hash] 81 | def get_my_trades(option = {}) 82 | json = post_ssl(@zaif_trade_url, "trade_history", option) 83 | # Convert to datetime 84 | json.each do|k, v| 85 | v["datetime"] = Time.at(v["timestamp"].to_i) 86 | end 87 | 88 | return json 89 | end 90 | 91 | # Get your active orders. 92 | # Avalible options: currency_pair 93 | # Need api key. 94 | def get_active_orders(option = {}) 95 | json = post_ssl(@zaif_trade_url, "active_orders", option) 96 | # Convert to datetime 97 | json.each do|k, v| 98 | v["datetime"] = Time.at(v["timestamp"].to_i) 99 | end 100 | 101 | return json 102 | end 103 | # Issue trade. 104 | # Need api key. 105 | def trade(currency_code, price, amount, action, limit = nil, counter_currency_code = "jpy") 106 | currency_pair = currency_code + "_" + counter_currency_code 107 | params = {:currency_pair => currency_pair, :action => action, :price => price, :amount => amount} 108 | params.store(:limit, limit) if limit 109 | json = post_ssl(@zaif_trade_url, "trade", params) 110 | return json 111 | end 112 | 113 | # Issue bid order. 114 | # Need api key. 115 | def bid(currency_code, price, amount, limit = nil, counter_currency_code = "jpy") 116 | return trade(currency_code, price, amount, "bid", limit, counter_currency_code) 117 | end 118 | 119 | # Issue ask order. 120 | # Need api key. 121 | def ask(currency_code, price, amount, limit = nil, counter_currency_code = "jpy") 122 | return trade(currency_code, price, amount, "ask", limit, counter_currency_code) 123 | end 124 | 125 | # Cancel order. 126 | # Need api key. 127 | def cancel(order_id) 128 | json = post_ssl(@zaif_trade_url, "cancel_order", {:order_id => order_id}) 129 | return json 130 | end 131 | 132 | # Withdraw funds. 133 | # Need api key. 134 | def withdraw(currency_code, address, amount, option = {}) 135 | option["currency"] = currency_code 136 | option["address"] = address 137 | option["amount"] = amount 138 | json = post_ssl(@zaif_trade_url, "withdraw", option) 139 | return json 140 | end 141 | 142 | # 143 | # Class private method 144 | # 145 | 146 | private 147 | 148 | def check_key 149 | if @api_key.nil? or @api_secret.nil? 150 | raise "You need to set a API key and secret" 151 | end 152 | end 153 | 154 | # Connect to address via https, and return json reponse. 155 | def get_ssl(address) 156 | uri = URI.parse(address) 157 | begin 158 | https = Net::HTTP.new(uri.host, uri.port) 159 | https.use_ssl = true 160 | https.open_timeout = 5 161 | https.read_timeout = 15 162 | https.verify_mode = OpenSSL::SSL::VERIFY_PEER 163 | https.verify_depth = 5 164 | 165 | https.start {|w| 166 | response = w.get(uri.request_uri) 167 | case response 168 | when Net::HTTPSuccess 169 | json = JSON.parse(response.body) 170 | raise JSONException, response.body if json == nil 171 | raise APIErrorException, json["error"] if json.is_a?(Hash) && json.has_key?("error") 172 | get_cool_down 173 | return json 174 | else 175 | raise ConnectionFailedException, "Failed to connect to zaif." 176 | end 177 | } 178 | rescue 179 | raise 180 | end 181 | end 182 | 183 | # Connect to address via https, and return json reponse. 184 | def post_ssl(address, method, data) 185 | check_key 186 | uri = URI.parse(address) 187 | data["method"] = method 188 | data["nonce"] = get_nonce 189 | begin 190 | req = Net::HTTP::Post.new(uri) 191 | req.set_form_data(data) 192 | req["Key"] = @api_key 193 | req["Sign"] = OpenSSL::HMAC::hexdigest(OpenSSL::Digest.new('sha512'), @api_secret, req.body) 194 | 195 | 196 | https = Net::HTTP.new(uri.host, uri.port) 197 | https.use_ssl = true 198 | https.open_timeout = 5 199 | https.read_timeout = 15 200 | https.verify_mode = OpenSSL::SSL::VERIFY_PEER 201 | https.verify_depth = 5 202 | 203 | https.start {|w| 204 | response = w.request(req) 205 | case response 206 | when Net::HTTPSuccess 207 | json = JSON.parse(response.body) 208 | raise JSONException, response.body if json == nil 209 | raise APIErrorException, json["error"] if json.is_a?(Hash) && json["success"] == 0 210 | get_cool_down 211 | return json["return"] 212 | else 213 | raise ConnectionFailedException, "Failed to connect to zaif: " + response.value 214 | end 215 | } 216 | rescue 217 | raise 218 | end 219 | end 220 | 221 | def get_nonce 222 | time = Time.now.to_f 223 | return time.to_i 224 | end 225 | 226 | def get_cool_down 227 | if @cool_down 228 | sleep(@cool_down_time) 229 | end 230 | end 231 | 232 | end 233 | end 234 | --------------------------------------------------------------------------------