diff --git a/README.md b/README.md index 9419d0a9c..275e6ee00 100644 --- a/README.md +++ b/README.md @@ -393,6 +393,7 @@ Or install it yourself as: | Tidex | Y | | | | Y | | tidex | | | Tokenize | Y | | | | Y | Y | tokenize | | | Tokenjar | Y | | | | Y | | tokenjar | | +| Tokenmom | Y | Y | Y | | Y | Y | tokenmom | | | Tokenomy | Y | Y [x] | Y | | Y | Y | tokenomy | | | TokensNet | Y | Y | Y | | Y | N | tokens_net | | | Tokok | Y | Y [x] | Y | | Y | | tokok | | diff --git a/lib/cryptoexchange/exchanges/tokenmom/market.rb b/lib/cryptoexchange/exchanges/tokenmom/market.rb new file mode 100644 index 000000000..9ba82dc12 --- /dev/null +++ b/lib/cryptoexchange/exchanges/tokenmom/market.rb @@ -0,0 +1,12 @@ +module Cryptoexchange::Exchanges + module Tokenmom + class Market < Cryptoexchange::Models::Market + NAME = 'tokenmom' + API_URL = 'https://api.tokenmom.com' + + def self.trade_page_url(args={}) + "https://www.tokenmom.com/exchange/#{args[:base]}-#{args[:target]}" + end + end + end +end diff --git a/lib/cryptoexchange/exchanges/tokenmom/services/market.rb b/lib/cryptoexchange/exchanges/tokenmom/services/market.rb new file mode 100644 index 000000000..f52b67ecb --- /dev/null +++ b/lib/cryptoexchange/exchanges/tokenmom/services/market.rb @@ -0,0 +1,54 @@ +require 'bigdecimal' + +module Cryptoexchange::Exchanges + module Tokenmom + module Services + class Market < Cryptoexchange::Services::Market + class << self + def supports_individual_ticker_query? + false + end + end + + def fetch + output = super ticker_url + adapt_all(output) + end + + def ticker_url + "#{Cryptoexchange::Exchanges::Tokenmom::Market::API_URL}/market/get_tickers" + end + + def adapt_all(output) + output['tickers'].map do |pair| + base, target = pair['market_id'].split('-') + market_pair = Cryptoexchange::Models::MarketPair.new( + base: base, + target: target, + market: Tokenmom::Market::NAME + ) + adapt(pair, market_pair) + end + end + + def adapt(output, market_pair) + ticker = Cryptoexchange::Models::Ticker.new + ticker.base = market_pair.base + ticker.target = market_pair.target + ticker.market = Tokenmom::Market::NAME + + ticker.last = NumericHelper.to_d(output['price']) + ticker.volume = NumericHelper.to_d(output['volume']) + ticker.bid = NumericHelper.to_d(output['bid']) + ticker.ask = NumericHelper.to_d(output['ask']) + ticker.low = NumericHelper.to_d(output['low']) + ticker.high = NumericHelper.to_d(output['high']) + + ticker.timestamp = nil + ticker.payload = output + ticker + end + end + end + end +end diff --git a/lib/cryptoexchange/exchanges/tokenmom/services/order_book.rb b/lib/cryptoexchange/exchanges/tokenmom/services/order_book.rb new file mode 100644 index 000000000..f75cb4df4 --- /dev/null +++ b/lib/cryptoexchange/exchanges/tokenmom/services/order_book.rb @@ -0,0 +1,42 @@ +module Cryptoexchange::Exchanges + module Tokenmom + module Services + class OrderBook < Cryptoexchange::Services::Market + class << self + def supports_individual_ticker_query? + true + end + end + + def fetch(market_pair) + output = super(ticker_url(market_pair)) + adapt(output['orderbook'], market_pair) + end + + def ticker_url(market_pair) + "#{Cryptoexchange::Exchanges::Tokenmom::Market::API_URL}/order/get_orders?market_id=#{market_pair.base}-#{market_pair.target}" + end + + def adapt(output, market_pair) + order_book = Cryptoexchange::Models::OrderBook.new + order_book.base = market_pair.base + order_book.target = market_pair.target + order_book.market = Tokenmom::Market::NAME + order_book.asks = adapt_orders(output['asks']) + order_book.bids = adapt_orders(output['bids']) + order_book.timestamp = Time.now.to_i + order_book.payload = output + order_book + end + + def adapt_orders(orders) + orders.collect do |order_entry| + Cryptoexchange::Models::Order.new(price: order_entry['price'], + amount: order_entry['amount'], + timestamp: nil) + end + end + end + end + end +end diff --git a/lib/cryptoexchange/exchanges/tokenmom/services/pairs.rb b/lib/cryptoexchange/exchanges/tokenmom/services/pairs.rb new file mode 100644 index 000000000..5798af9f5 --- /dev/null +++ b/lib/cryptoexchange/exchanges/tokenmom/services/pairs.rb @@ -0,0 +1,25 @@ +module Cryptoexchange::Exchanges + module Tokenmom + module Services + class Pairs < Cryptoexchange::Services::Pairs + PAIRS_URL = "#{Cryptoexchange::Exchanges::Tokenmom::Market::API_URL}/market/get_markets" + + def fetch + output = super + adapt(output) + end + + def adapt(output) + output['markets'][0]['tokens'].map do |pair| + base, target = pair['market_id'].split('-') + Cryptoexchange::Models::MarketPair.new( + base: base, + target: target, + market: Tokenmom::Market::NAME + ) + end + end + end + end + end +end diff --git a/lib/cryptoexchange/exchanges/tokenmom/services/trades.rb b/lib/cryptoexchange/exchanges/tokenmom/services/trades.rb new file mode 100644 index 000000000..cc1a6a432 --- /dev/null +++ b/lib/cryptoexchange/exchanges/tokenmom/services/trades.rb @@ -0,0 +1,32 @@ +module Cryptoexchange::Exchanges + module Tokenmom + module Services + class Trades < Cryptoexchange::Services::Market + + def fetch(market_pair) + output = super(ticker_url(market_pair)) + adapt(output['trades'], market_pair) + end + + def ticker_url(market_pair) + "#{Cryptoexchange::Exchanges::Tokenmom::Market::API_URL}/market/get_trades?market_id=#{market_pair.base}-#{market_pair.target}" + end + + def adapt(output, market_pair) + output.collect do |trade| + tr = Cryptoexchange::Models::Trade.new + tr.trade_id = trade['id'] + tr.base = market_pair.base + tr.target = market_pair.target + tr.market = Tokenmom::Market::NAME + tr.price = trade['price'] + tr.amount = trade['amount'] + tr.timestamp = trade['updated_at'].to_i + tr.payload = trade + tr + end + end + end + end + end +end diff --git a/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_order_book.yml b/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_order_book.yml new file mode 100644 index 000000000..28a51a277 --- /dev/null +++ b/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_order_book.yml @@ -0,0 +1,34 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.tokenmom.com/order/get_orderbook?market_id=TM-WETH + body: + encoding: UTF-8 + string: '' + headers: + Connection: + - close + Host: + - api.tokenmom.com + User-Agent: + - http.rb/3.0.0 + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 11 Jan 2019 10:25:20 GMT + Content-Type: + - application/json; charset=utf-8 + X-Powered-By: + - Express + Access-Control-Allow-Origin: + - "*" + body: + encoding: UTF-8 + string: '{"status": "success","orderbook": {"market_id": "TM-WETH","bids": [{"id": 3385,"state": 0,"expire": 1552332042,"maker_address": "0xefd9928aa5a192c0267cdaed43235006b7a28628","amount": "3.0000000000","price": "0.0001700000","fee": "0.0025000000","order_hash": "0x8aa1413286695a0575e20402d39c8e873407482512f3462d3027ab713dcf4198","created_at": "2019-01-10T19:20:49.000Z","updated_at": "2019-01-10T19:20:51.000Z"}, ],"asks": [{"id": 3304,"state": 0,"expire": 1550395596,"maker_address": "0x71016bf0bc7a174c86b4e85983266b953d7d2f6f","amount": "75716.1444449800","price": "0.0001800000","fee": "0.0125000000","order_hash": "0x80f5c755df23262cb92294dfc68e50b4e4e4c65702b91e1ff837862fcc1685a7","created_at": "2018-12-19T09:26:40.000Z","updated_at": "2018-12-20T12:46:54.000Z"}]}}' + http_version: + recorded_at: Fri, 11 Jan 2019 10:25:20 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_pairs.yml b/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_pairs.yml new file mode 100644 index 000000000..c31b0f289 --- /dev/null +++ b/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_pairs.yml @@ -0,0 +1,37 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.tokenmom.com/market/get_markets + body: + encoding: UTF-8 + string: '' + headers: + Connection: + - close + Host: + - api.tokenmom.com + User-Agent: + - http.rb/3.0.0 + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 11 Jan 2019 10:03:28 GMT + Content-Type: + - application/json; charset=utf-8 + + Connection: + - close + X-Powered-By: + - Express + Access-Control-Allow-Origin: + - "*" + body: + encoding: UTF-8 + string: '{"status":"success","markets":[{"base_token":"WETH","base_token_decimals":18,"base_token_address":"0xc778417e063141139fce010982780140aa0cd5ab","tokens":[{"market_id":"TM-WETH","token_symbol":"TM","token_name":"Tokenmom","token_address":"0x91495d6969120fc016bb687ead5f5ce56f135504","token_decimals":18,"last_price":"0.0017000000","today_change":"21.43","today_volume":145.54681871624797}]},{"base_token":"TM","base_token_decimals":18,"base_token_address":"0x91495D6969120fc016BB687EaD5F5cE56F135504","markets":[{"market_id":"ZRX-TM","token_symbol":"ZRX","token_name":"ZRX","token_address":"0xE41d2489571d322189246DaFA5ebDe1F4699F498","token_decimals":18,"last_price":"--","today_change":"--","today_volume":0}]}]}' + http_version: + recorded_at: Fri, 11 Jan 2019 10:03:47 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_ticker.yml b/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_ticker.yml new file mode 100644 index 000000000..b2a8a8360 --- /dev/null +++ b/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_ticker.yml @@ -0,0 +1,36 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.tokenmom.com/market/get_tickers + body: + encoding: UTF-8 + string: '' + headers: + Connection: + - close + Host: + - api.tokenmom.com + User-Agent: + - http.rb/3.0.0 + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 11 Jan 2019 10:03:31 GMT + Content-Type: + - application/json; charset=utf-8 + Connection: + - close + X-Powered-By: + - Express + Access-Control-Allow-Origin: + - "*" + body: + encoding: UTF-8 + string: '{"status":"success","tickers":[{"market_id":"TM-WETH","price":"0.0038000000","volume":27125.8701987602,"bid":"0.0001800000","ask":"0.0038000000","low":"0.0001800000","high":"0.0043000000","updated_at":"2018-12-20T12:02:36.000Z"}]}' + http_version: + recorded_at: Wed, 02 Jan 2019 10:03:49 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_trade.yml b/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_trade.yml new file mode 100644 index 000000000..16069cc9b --- /dev/null +++ b/spec/cassettes/vcr_cassettes/Tokenmom/integration_specs_fetch_trade.yml @@ -0,0 +1,36 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.tokenmom.com/market/get_trades?market_id=TM-WETH + body: + encoding: UTF-8 + string: '' + headers: + Connection: + - close + Host: + - api.tokenmom.com + User-Agent: + - http.rb/3.0.0 + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 11 Jan 2019 10:35:35 GMT + Content-Type: + - application/json; charset=utf-8 + Connection: + - close + X-Powered-By: + - Express + Access-Control-Allow-Origin: + - "*" + body: + encoding: UTF-8 + string: '{"status":"success","trades":[{"id":1453,"type":0,"maker_address":"0x6cd11f533396f0bc72e6424355ebdbcdb5262ea5","taker_address":"0xdc8c0cf4beb2fa1f34aa395f331e323776a0c8a5","txHash":"0xb38b91b86e2498f23da2a5df22ab9afa11a5c66a1126b6ae435abc93b01897f7","amount":"243.9223530000","price":"0.0017000000","reward_status":null,"created_at":"2018-12-11T05:38:10.000Z","updated_at":"2018-12-11T05:38:10.000Z","market_id":"TM-WETH"}]}' + http_version: + recorded_at: Fri, 11 Jan 2019 10:35:36 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/exchanges/tokenmom/integration/market_spec.rb b/spec/exchanges/tokenmom/integration/market_spec.rb new file mode 100644 index 000000000..41e475aef --- /dev/null +++ b/spec/exchanges/tokenmom/integration/market_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +RSpec.describe 'Tokenmom integration specs' do + let(:client) { Cryptoexchange::Client.new } + let(:tm_weth_pair) { Cryptoexchange::Models::MarketPair.new(base: 'TM', target: 'WETH', market: 'tokenmom') } + + it 'fetch pairs' do + pairs = client.pairs('tokenmom') + expect(pairs).not_to be_empty + + pair = pairs.first + expect(pair.base).to_not be nil + expect(pair.target).to_not be nil + expect(pair.market).to eq 'tokenmom' + end + + it 'fetch ticker' do + ticker = client.ticker(tm_weth_pair) + + expect(ticker.base).to eq 'TM' + expect(ticker.target).to eq 'WETH' + expect(ticker.market).to eq 'tokenmom' + + expect(ticker.last).to be_a Numeric + expect(ticker.volume).to be_a Numeric + expect(ticker.bid).to be_a Numeric + expect(ticker.ask).to be_a Numeric + expect(ticker.low).to be_a Numeric + expect(ticker.high).to be_a Numeric + + expect(ticker.timestamp).to be_nil + expect(ticker.payload).to_not be nil + end +end diff --git a/spec/exchanges/tokenmom/market_spec.rb b/spec/exchanges/tokenmom/market_spec.rb new file mode 100644 index 000000000..8e1104ad5 --- /dev/null +++ b/spec/exchanges/tokenmom/market_spec.rb @@ -0,0 +1,6 @@ +require 'spec_helper' + +RSpec.describe Cryptoexchange::Exchanges::Tokenmom::Market do + it { expect(described_class::NAME).to eq 'tokenmom' } + it { expect(described_class::API_URL).to eq 'https://api.tokenmom.com' } +end