bitget.rb 0.5.0 → 0.6.1
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 +59 -0
- data/lib/Bitget/Configuration.rb +32 -0
- data/lib/Bitget/Error.rb +33 -1
- data/lib/Bitget/V2/Client.rb +27 -44
- data/lib/Bitget/{VERSiON.rb → VERSION.rb} +1 -1
- data/lib/{bitget.rb → Bitget.rb} +2 -0
- data/test/Configuration_test.rb +87 -0
- data/test/V2/{client_test.rb → Client_test.rb} +34 -52
- data/test/helper.rb +16 -2
- data/test/test_all.rb +2 -2
- metadata +7 -9
- data/lib/Hash/x_www_form_urlencode.rb +0 -7
- data/lib/Thoran/Hash/XWwwFormUrlencode/x_www_form_urlencode.rb +0 -26
- data/test/V2/client_logging_test.rb +0 -92
- data/test/client_test.rb +0 -198
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 68ebcc266ecbdcc502c80abf56f670fd7b0d274e1cee117dafdff7fed81f02de
|
|
4
|
+
data.tar.gz: 9e59c895f487eef1ffa14f3d88266fcd6ae87a79864dc8ed9f0ff28b63afadf3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1dda1a6e29afc914c90cfeb318b0250d10fbe9a04e12502a842e7a1b908baf0f45ed27e51e4be89c5035988553ee6dfc6bf0ff4197cb993f03b3a8aa50560f26
|
|
7
|
+
data.tar.gz: 7d5f81ce7c5b2b3c943015724b81b0ab7e7d4868f2935b00fb570f66dd5e7d03c6e6b83fad8ef3cf9c08a9fa347394ff9b5186420978c2849f546bd4814bb19a
|
data/README.md
CHANGED
|
@@ -30,6 +30,65 @@ bitget_client = Bitget::Client.new(
|
|
|
30
30
|
)
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
### Configuration
|
|
34
|
+
|
|
35
|
+
Settings may be declared once, and every client built afterwards reads them as its defaults.
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
Bitget.configure do |config|
|
|
39
|
+
config.api_key = 'api_key0'
|
|
40
|
+
config.api_secret = 'api_secret0'
|
|
41
|
+
config.api_passphrase = 'api_passphrase0'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
bitget_client = Bitget::Client.new
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The settings are `api_key`, `api_secret`, `api_passphrase`, `debug` and `logger`.
|
|
48
|
+
|
|
49
|
+
Any of them may still be given per client, which wins over the configured value. The
|
|
50
|
+
credentials are named arguments; the rest go under `options`.
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
bitget_client = Bitget::Client.new(
|
|
54
|
+
api_key: 'api_key1',
|
|
55
|
+
options: {logger: Logger.new('bitget.log', 'daily')}
|
|
56
|
+
)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Logging
|
|
60
|
+
|
|
61
|
+
A client logs when it has somewhere to log to, and not at all when it does not. Hand it any
|
|
62
|
+
object answering to `#info` and `#error`; the standard library's `Logger` will do.
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
require 'logger'
|
|
66
|
+
|
|
67
|
+
Bitget.configure do |config|
|
|
68
|
+
config.logger = Logger.new($stdout)
|
|
69
|
+
end
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`Logger` rotates by itself, so a daily log file wants no more than its second argument. It
|
|
73
|
+
will not create the directory, so make that first.
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
require 'fileutils'
|
|
77
|
+
require 'logger'
|
|
78
|
+
|
|
79
|
+
log_file_path = File.expand_path(File.join(%w{~ log bitget log.txt}))
|
|
80
|
+
FileUtils.mkdir_p(File.dirname(log_file_path))
|
|
81
|
+
|
|
82
|
+
Bitget.configure do |config|
|
|
83
|
+
config.logger = Logger.new(log_file_path, 'daily')
|
|
84
|
+
end
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Before 0.6.0 the client chose the path, created the directory and rotated the file itself. It
|
|
88
|
+
no longer does any of that: what is logged is the client's business and where it goes is
|
|
89
|
+
yours, which is what lets a StringIO logger in a test, or a levelled one, or something which
|
|
90
|
+
is not a Logger at all, work as well as the above.
|
|
91
|
+
|
|
33
92
|
### Retrieve Info on All the Coins Traded
|
|
34
93
|
```ruby
|
|
35
94
|
bitget_client.spot_public_coins
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Bitget/Configuration.rb
|
|
2
|
+
# Bitget::Configuration
|
|
3
|
+
|
|
4
|
+
module Bitget
|
|
5
|
+
class Configuration
|
|
6
|
+
attr_accessor :api_key, :api_secret, :api_passphrase, :debug, :logger
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@api_key = nil
|
|
10
|
+
@api_secret = nil
|
|
11
|
+
@api_passphrase = nil
|
|
12
|
+
@debug = false
|
|
13
|
+
@logger = nil
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
attr_writer :configuration
|
|
19
|
+
|
|
20
|
+
def configuration
|
|
21
|
+
@configuration ||= Configuration.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def configure
|
|
25
|
+
yield(configuration)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def reset_configuration!
|
|
29
|
+
@configuration = Configuration.new
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/Bitget/Error.rb
CHANGED
|
@@ -1,9 +1,31 @@
|
|
|
1
1
|
# Bitget/Error.rb
|
|
2
2
|
# Bitget::Error
|
|
3
3
|
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
4
6
|
module Bitget
|
|
5
7
|
class Error < RuntimeError
|
|
6
|
-
attr_reader
|
|
8
|
+
attr_reader\
|
|
9
|
+
:code,
|
|
10
|
+
:message,
|
|
11
|
+
:body
|
|
12
|
+
|
|
13
|
+
# Bitget answers most errors with a JSON body carrying its own code and
|
|
14
|
+
# message, which are more use than the HTTP ones. Not all of them: a 418
|
|
15
|
+
# arrives with an empty body and there is nothing to parse. Where the body
|
|
16
|
+
# says nothing the HTTP code and message answer instead, so that an error
|
|
17
|
+
# renders as something rather than as a pair of blanks.
|
|
18
|
+
def error_code
|
|
19
|
+
@parsed_body['code'] || @code
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def error_message
|
|
23
|
+
@parsed_body['msg'] || @parsed_body['message'] || @message
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_s
|
|
27
|
+
"Bitget::Error: #{error_code} - #{error_message}"
|
|
28
|
+
end
|
|
7
29
|
|
|
8
30
|
private
|
|
9
31
|
|
|
@@ -11,6 +33,16 @@ module Bitget
|
|
|
11
33
|
@code = code
|
|
12
34
|
@message = message
|
|
13
35
|
@body = body
|
|
36
|
+
@parsed_body = parsed(body)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# An error is raised in answer to something already having gone wrong, so it
|
|
40
|
+
# must construct from whatever arrived. Raising a JSON::ParserError from
|
|
41
|
+
# here loses the error being reported and replaces it with one about parsing.
|
|
42
|
+
def parsed(body)
|
|
43
|
+
JSON.parse(body)
|
|
44
|
+
rescue JSON::ParserError
|
|
45
|
+
{}
|
|
14
46
|
end
|
|
15
47
|
end
|
|
16
48
|
end
|
data/lib/Bitget/V2/Client.rb
CHANGED
|
@@ -8,8 +8,8 @@ require 'json'
|
|
|
8
8
|
require 'logger'
|
|
9
9
|
require 'openssl'
|
|
10
10
|
|
|
11
|
+
require_relative '../Configuration'
|
|
11
12
|
require_relative '../Error'
|
|
12
|
-
require_relative '../../Hash/x_www_form_urlencode'
|
|
13
13
|
|
|
14
14
|
module Bitget
|
|
15
15
|
module V2
|
|
@@ -18,28 +18,11 @@ module Bitget
|
|
|
18
18
|
API_HOST = 'api.bitget.com'
|
|
19
19
|
|
|
20
20
|
class << self
|
|
21
|
-
attr_writer :log_file_path
|
|
22
21
|
|
|
23
22
|
def path_prefix
|
|
24
23
|
'/api/v2'
|
|
25
24
|
end
|
|
26
25
|
|
|
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
26
|
end # class << self
|
|
44
27
|
|
|
45
28
|
# Market
|
|
@@ -1824,15 +1807,22 @@ module Bitget
|
|
|
1824
1807
|
:api_key,
|
|
1825
1808
|
:api_secret,
|
|
1826
1809
|
:api_passphrase,
|
|
1827
|
-
:
|
|
1810
|
+
:debug,
|
|
1811
|
+
:logger
|
|
1828
1812
|
|
|
1829
1813
|
private
|
|
1830
1814
|
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1815
|
+
# Anything not given here is taken from Bitget.configuration, so that a
|
|
1816
|
+
# setting declared once need not be repeated at every call site. The
|
|
1817
|
+
# credentials fall back upon nil, having no meaningful nil value of their
|
|
1818
|
+
# own; the options ask whether the key was given, nil being a value a
|
|
1819
|
+
# caller may mean for a logger.
|
|
1820
|
+
def initialize(api_key: nil, api_secret: nil, api_passphrase: nil, options: {})
|
|
1821
|
+
@api_key = api_key || Bitget.configuration.api_key
|
|
1822
|
+
@api_secret = api_secret || Bitget.configuration.api_secret
|
|
1823
|
+
@api_passphrase = api_passphrase || Bitget.configuration.api_passphrase
|
|
1824
|
+
@debug = options.key?(:debug) ? options[:debug] : Bitget.configuration.debug
|
|
1825
|
+
@logger = options.key?(:logger) ? options[:logger] : Bitget.configuration.logger
|
|
1836
1826
|
end
|
|
1837
1827
|
|
|
1838
1828
|
def full_path(path)
|
|
@@ -1845,7 +1835,8 @@ module Bitget
|
|
|
1845
1835
|
end
|
|
1846
1836
|
|
|
1847
1837
|
def timestamp
|
|
1848
|
-
@timestamp ||= (Time.now.to_f * 1000).to_i.to_s
|
|
1838
|
+
# @timestamp ||= (Time.now.to_f * 1000).to_i.to_s
|
|
1839
|
+
@timestamp ||= (Time.now.to_i * 1000).to_s
|
|
1849
1840
|
end
|
|
1850
1841
|
|
|
1851
1842
|
def message(verb:, path:, args:)
|
|
@@ -1884,6 +1875,10 @@ module Bitget
|
|
|
1884
1875
|
}
|
|
1885
1876
|
end
|
|
1886
1877
|
|
|
1878
|
+
def use_logging?
|
|
1879
|
+
!@logger.nil?
|
|
1880
|
+
end
|
|
1881
|
+
|
|
1887
1882
|
def log_args?(args)
|
|
1888
1883
|
!args.values.all?(&:nil?)
|
|
1889
1884
|
end
|
|
@@ -1894,21 +1889,21 @@ module Bitget
|
|
|
1894
1889
|
log_string << " Args: #{args}\n"
|
|
1895
1890
|
end
|
|
1896
1891
|
log_string << " Headers: #{headers}\n"
|
|
1897
|
-
|
|
1892
|
+
logger.info(log_string)
|
|
1898
1893
|
end
|
|
1899
1894
|
|
|
1900
1895
|
def log_response(code:, message:, body:)
|
|
1901
1896
|
log_string = "Code: #{code}\n"
|
|
1902
1897
|
log_string << "Message: #{message}\n"
|
|
1903
1898
|
log_string << "Body: #{body}\n"
|
|
1904
|
-
|
|
1899
|
+
logger.info(log_string)
|
|
1905
1900
|
end
|
|
1906
1901
|
|
|
1907
1902
|
def log_error(code:, message:, body:)
|
|
1908
1903
|
log_string = "Code: #{code}\n"
|
|
1909
1904
|
log_string << "Message: #{message}\n"
|
|
1910
1905
|
log_string << "Body: #{body}\n"
|
|
1911
|
-
|
|
1906
|
+
logger.error(log_string)
|
|
1912
1907
|
end
|
|
1913
1908
|
|
|
1914
1909
|
def do_request(verb:, path:, args: {})
|
|
@@ -1916,7 +1911,7 @@ module Bitget
|
|
|
1916
1911
|
message = message(verb: verb, path: path, args: sorted_args)
|
|
1917
1912
|
signature = signature(message)
|
|
1918
1913
|
headers = headers(signature)
|
|
1919
|
-
log_request(verb: verb, request_string: request_string(path), args: sorted_args, headers: headers) if
|
|
1914
|
+
log_request(verb: verb, request_string: request_string(path), args: sorted_args, headers: headers) if use_logging?
|
|
1920
1915
|
@timestamp = nil
|
|
1921
1916
|
HTTP.send(verb.to_s.downcase, request_string(path), sorted_args, headers)
|
|
1922
1917
|
end
|
|
@@ -1932,23 +1927,11 @@ module Bitget
|
|
|
1932
1927
|
def handle_response(response)
|
|
1933
1928
|
if response.success?
|
|
1934
1929
|
parsed_body = JSON.parse(response.body)
|
|
1935
|
-
log_response(
|
|
1936
|
-
code: response.code,
|
|
1937
|
-
message: response.message,
|
|
1938
|
-
body: response.body
|
|
1939
|
-
) if @use_logging
|
|
1930
|
+
log_response(code: response.code, message: response.message, body: response.body) if use_logging?
|
|
1940
1931
|
parsed_body
|
|
1941
1932
|
else
|
|
1942
|
-
log_error(
|
|
1943
|
-
|
|
1944
|
-
message: response.message,
|
|
1945
|
-
body: response.body
|
|
1946
|
-
) if @use_logging
|
|
1947
|
-
raise Bitget::Error.new(
|
|
1948
|
-
code: response.code,
|
|
1949
|
-
message: response.message,
|
|
1950
|
-
body: response.body
|
|
1951
|
-
)
|
|
1933
|
+
log_error(code: response.code, message: response.message, body: response.body) if use_logging?
|
|
1934
|
+
raise Bitget::Error.new(code: response.code, message: response.message, body: response.body)
|
|
1952
1935
|
end
|
|
1953
1936
|
end
|
|
1954
1937
|
end
|
data/lib/{bitget.rb → Bitget.rb}
RENAMED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require_relative './helper'
|
|
2
|
+
|
|
3
|
+
describe Bitget::Configuration do
|
|
4
|
+
describe "#initialize" do
|
|
5
|
+
it "sets default values" do
|
|
6
|
+
config = Bitget::Configuration.new
|
|
7
|
+
_(config.debug).must_equal(false)
|
|
8
|
+
_(config.api_key).must_be_nil
|
|
9
|
+
_(config.api_secret).must_be_nil
|
|
10
|
+
_(config.api_passphrase).must_be_nil
|
|
11
|
+
_(config.logger).must_be_nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "declares a setting for everything a client reads" do
|
|
15
|
+
_(Bitget::Configuration.new.public_methods(false).grep(/[^=]\z/).sort) \
|
|
16
|
+
.must_equal(%i{api_key api_passphrase api_secret debug logger})
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# The credentials are named arguments and fall back upon nil, having no
|
|
21
|
+
# meaningful nil of their own. The options are given under options: and fall
|
|
22
|
+
# back upon the key being absent, nil being a value a caller may mean.
|
|
23
|
+
describe "the credentials, which are named arguments" do
|
|
24
|
+
before do
|
|
25
|
+
Bitget.configure do |config|
|
|
26
|
+
config.api_key = 'configured_key'
|
|
27
|
+
config.api_secret = 'configured_secret'
|
|
28
|
+
config.api_passphrase = 'configured_passphrase'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "supplies every one, so that a client needs no arguments at all" do
|
|
33
|
+
client = Bitget::Client.new
|
|
34
|
+
_(client.api_key).must_equal('configured_key')
|
|
35
|
+
_(client.api_secret).must_equal('configured_secret')
|
|
36
|
+
_(client.api_passphrase).must_equal('configured_passphrase')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "yields to each one given, and only to that one" do
|
|
40
|
+
_(Bitget::Client.new(api_key: 'given').api_key).must_equal('given')
|
|
41
|
+
_(Bitget::Client.new(api_key: 'given').api_secret).must_equal('configured_secret')
|
|
42
|
+
_(Bitget::Client.new(api_secret: 'given').api_secret).must_equal('given')
|
|
43
|
+
_(Bitget::Client.new(api_secret: 'given').api_key).must_equal('configured_key')
|
|
44
|
+
_(Bitget::Client.new(api_passphrase: 'given').api_passphrase).must_equal('given')
|
|
45
|
+
_(Bitget::Client.new(api_passphrase: 'given').api_key).must_equal('configured_key')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "is unreachable where nothing is configured and nothing is given" do
|
|
49
|
+
Bitget.reset_configuration!
|
|
50
|
+
client = Bitget::Client.new
|
|
51
|
+
_(client.api_key).must_be_nil
|
|
52
|
+
_(client.api_secret).must_be_nil
|
|
53
|
+
_(client.api_passphrase).must_be_nil
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "the options, which are given under options:" do
|
|
58
|
+
let(:logger){Logger.new(StringIO.new)}
|
|
59
|
+
|
|
60
|
+
before do
|
|
61
|
+
Bitget.configure do |config|
|
|
62
|
+
config.debug = true
|
|
63
|
+
config.logger = logger
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "supplies every one" do
|
|
68
|
+
client = Bitget::Client.new
|
|
69
|
+
_(client.debug).must_equal(true)
|
|
70
|
+
_(client.logger).must_equal(logger)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "yields to each one given, and only to that one" do
|
|
74
|
+
other = Logger.new(StringIO.new)
|
|
75
|
+
_(Bitget::Client.new(options: {debug: false}).debug).must_equal(false)
|
|
76
|
+
_(Bitget::Client.new(options: {debug: false}).logger).must_equal(logger)
|
|
77
|
+
_(Bitget::Client.new(options: {logger: other}).logger).must_equal(other)
|
|
78
|
+
_(Bitget::Client.new(options: {logger: other}).debug).must_equal(true)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "takes nil as a value rather than as an absence" do
|
|
82
|
+
client = Bitget::Client.new(options: {logger: nil})
|
|
83
|
+
_(client.logger).must_be_nil
|
|
84
|
+
_(client.send(:use_logging?)).must_equal(false)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require_relative '../helper'
|
|
2
|
-
require_relative '../../lib/Bitget/V2/Client'
|
|
3
2
|
|
|
4
3
|
describe Bitget::V2::Client do
|
|
5
4
|
let(:api_key){ENV.fetch('BITGET_API_KEY', '<API_KEY>')}
|
|
@@ -14,6 +13,19 @@ describe Bitget::V2::Client do
|
|
|
14
13
|
)
|
|
15
14
|
end
|
|
16
15
|
|
|
16
|
+
describe "where a request is addressed" do
|
|
17
|
+
# Written out rather than built from API_HOST and .path_prefix, which would
|
|
18
|
+
# pass however wrong either of them was.
|
|
19
|
+
it "is the scheme, the host, the version prefix, and the path" do
|
|
20
|
+
_(client.send(:request_string, '/spot/public/coins')) \
|
|
21
|
+
.must_equal('https://api.bitget.com/api/v2/spot/public/coins')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "takes its version prefix from the client, which is what makes V2 a class of its own" do
|
|
25
|
+
_(Bitget::V2::Client.path_prefix).must_equal('/api/v2')
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
17
29
|
# Market
|
|
18
30
|
|
|
19
31
|
describe "#spot_public_coins" do
|
|
@@ -998,12 +1010,12 @@ describe Bitget::V2::Client do
|
|
|
998
1010
|
let(:mock_error){Minitest::Mock.new}
|
|
999
1011
|
|
|
1000
1012
|
before do
|
|
1001
|
-
client.
|
|
1013
|
+
client.logger = Logger.new(StringIO.new)
|
|
1002
1014
|
mock_error.expect(:call, nil, [], code: '418', message: "I'm a teapot", body: '')
|
|
1003
1015
|
end
|
|
1004
1016
|
|
|
1005
1017
|
after do
|
|
1006
|
-
client.
|
|
1018
|
+
client.logger = nil
|
|
1007
1019
|
mock_error.verify
|
|
1008
1020
|
end
|
|
1009
1021
|
|
|
@@ -1070,79 +1082,49 @@ describe Bitget::V2::Client do
|
|
|
1070
1082
|
end
|
|
1071
1083
|
|
|
1072
1084
|
describe "logging" do
|
|
1085
|
+
let(:log){StringIO.new}
|
|
1086
|
+
|
|
1073
1087
|
before do
|
|
1074
|
-
client.
|
|
1075
|
-
FileUtils.rm_f(client.class.log_file_path)
|
|
1076
|
-
client.class.instance_variable_set(:@log_file_path, nil)
|
|
1077
|
-
client.class.instance_variable_set(:@logger, nil)
|
|
1088
|
+
client.logger = Logger.new(log)
|
|
1078
1089
|
end
|
|
1079
1090
|
|
|
1080
1091
|
after do
|
|
1081
|
-
client.
|
|
1082
|
-
FileUtils.rm_f(client.class.log_file_path)
|
|
1083
|
-
end
|
|
1084
|
-
|
|
1085
|
-
describe "logging configuration" do
|
|
1086
|
-
it "uses the configured log file path" do
|
|
1087
|
-
client.class.log_file_path = '/tmp/path'
|
|
1088
|
-
_(client.class.log_file_path).must_equal(File.expand_path('/tmp/path'))
|
|
1089
|
-
end
|
|
1090
|
-
|
|
1091
|
-
it "creates log directory if it doesn't exist" do
|
|
1092
|
-
nested_path = File.join(Dir.tmpdir, 'bitget_test', 'nested', 'test.log')
|
|
1093
|
-
client.class.log_file_path = nested_path
|
|
1094
|
-
client.class.logger
|
|
1095
|
-
_(File.directory?(File.dirname(nested_path))).must_equal(true)
|
|
1096
|
-
end
|
|
1097
|
-
|
|
1098
|
-
it "creates a daily rotating logger" do
|
|
1099
|
-
_(client.class.logger).must_be_kind_of(Logger)
|
|
1100
|
-
_(File.exist?(client.class.log_file_path)).must_equal(true)
|
|
1101
|
-
end
|
|
1092
|
+
client.logger = nil
|
|
1102
1093
|
end
|
|
1103
1094
|
|
|
1104
1095
|
describe "request logging" do
|
|
1105
1096
|
it "logs requests" do
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
client.spot_public_coins(coin: 'BTC')
|
|
1097
|
+
VCR.use_cassette("v2/spot/public/coins-when_coin_is_supplied") do
|
|
1098
|
+
client.spot_public_coins(coin: "BTC")
|
|
1109
1099
|
end
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
_(
|
|
1113
|
-
_(log_content).must_match(/Args: \{coin: \"BTC\"}/)
|
|
1114
|
-
_(log_content).must_match(/Headers: .+\"Content-Type\" => \"application\/json\"/)
|
|
1100
|
+
_(log.string).must_match(/GET https:\/\/api.bitget.com\/api\/v2\/spot\/public\/coins/)
|
|
1101
|
+
_(log.string).must_match(/Args: \{coin: "BTC"}/)
|
|
1102
|
+
_(log.string).must_match(/Headers: .+"Content-Type" => "application\/json"/)
|
|
1115
1103
|
end
|
|
1116
1104
|
end
|
|
1117
1105
|
|
|
1118
1106
|
describe "response logging" do
|
|
1119
1107
|
it "logs responses" do
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
client.spot_public_coins(coin: 'BTC')
|
|
1108
|
+
VCR.use_cassette("v2/spot/public/coins-when_coin_is_supplied") do
|
|
1109
|
+
client.spot_public_coins(coin: "BTC")
|
|
1123
1110
|
end
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
_(
|
|
1127
|
-
_(log_content).must_match(/Message:/)
|
|
1128
|
-
_(log_content).must_match(/Body:/)
|
|
1111
|
+
_(log.string).must_match(/Code:/)
|
|
1112
|
+
_(log.string).must_match(/Message:/)
|
|
1113
|
+
_(log.string).must_match(/Body:/)
|
|
1129
1114
|
end
|
|
1130
1115
|
end
|
|
1131
1116
|
|
|
1132
1117
|
describe "error logging" do
|
|
1133
1118
|
it "logs error responses" do
|
|
1134
|
-
|
|
1135
|
-
VCR.use_cassette('v2/spot/public/coins-when_error_occurs') do
|
|
1119
|
+
VCR.use_cassette("v2/spot/public/coins-when_error_occurs") do
|
|
1136
1120
|
begin
|
|
1137
|
-
client.spot_public_coins(coin:
|
|
1121
|
+
client.spot_public_coins(coin: "INVALID")
|
|
1138
1122
|
rescue Bitget::Error
|
|
1139
1123
|
end
|
|
1140
1124
|
end
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
_(
|
|
1144
|
-
_(log_content).must_match(/Message:/)
|
|
1145
|
-
_(log_content).must_match(/Body:/)
|
|
1125
|
+
_(log.string).must_match(/Code:/)
|
|
1126
|
+
_(log.string).must_match(/Message:/)
|
|
1127
|
+
_(log.string).must_match(/Body:/)
|
|
1146
1128
|
end
|
|
1147
1129
|
end
|
|
1148
1130
|
end
|
data/test/helper.rb
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
require 'minitest/autorun'
|
|
2
|
-
require 'minitest
|
|
2
|
+
require 'minitest/mock'
|
|
3
3
|
require 'minitest/spec'
|
|
4
|
+
require 'minitest-spec-context'
|
|
4
5
|
require 'vcr'
|
|
6
|
+
require 'webmock' # Necessary? Was working without.
|
|
7
|
+
|
|
8
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
|
|
9
|
+
require 'bitget'
|
|
5
10
|
|
|
6
11
|
VCR.configure do |config|
|
|
7
|
-
config.cassette_library_dir = File.expand_path('../fixtures/vcr_cassettes', __FILE__)
|
|
12
|
+
# config.cassette_library_dir = File.expand_path('../fixtures/vcr_cassettes', __FILE__)
|
|
13
|
+
config.cassette_library_dir = 'test/fixtures/vcr_cassettes'
|
|
14
|
+
|
|
8
15
|
config.hook_into :webmock
|
|
9
16
|
|
|
10
17
|
config.filter_sensitive_data('<API_KEY>'){ENV['BITGET_API_KEY']}
|
|
11
18
|
config.filter_sensitive_data('<API_SECRET>'){ENV['BITGET_API_SECRET'] }
|
|
12
19
|
config.filter_sensitive_data('<API_PASSPHRASE>'){ENV['BITGET_API_PASSPHRASE']}
|
|
13
20
|
end
|
|
21
|
+
|
|
22
|
+
class Minitest::Test
|
|
23
|
+
def before_setup
|
|
24
|
+
super
|
|
25
|
+
Bitget.reset_configuration!
|
|
26
|
+
end
|
|
27
|
+
end
|
data/test/test_all.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bitget.rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- thoran
|
|
@@ -32,18 +32,16 @@ files:
|
|
|
32
32
|
- Gemfile
|
|
33
33
|
- README.md
|
|
34
34
|
- bitget.rb.gemspec
|
|
35
|
+
- lib/Bitget.rb
|
|
35
36
|
- lib/Bitget/Client.rb
|
|
37
|
+
- lib/Bitget/Configuration.rb
|
|
36
38
|
- lib/Bitget/Error.rb
|
|
37
39
|
- lib/Bitget/V2/Client.rb
|
|
38
|
-
- lib/Bitget/
|
|
39
|
-
- lib/Hash/x_www_form_urlencode.rb
|
|
40
|
+
- lib/Bitget/VERSION.rb
|
|
40
41
|
- lib/String/url_encode.rb
|
|
41
|
-
- lib/Thoran/Hash/XWwwFormUrlencode/x_www_form_urlencode.rb
|
|
42
42
|
- lib/Thoran/String/UrlEncode/url_encode.rb
|
|
43
|
-
-
|
|
44
|
-
- test/V2/
|
|
45
|
-
- test/V2/client_test.rb
|
|
46
|
-
- test/client_test.rb
|
|
43
|
+
- test/Configuration_test.rb
|
|
44
|
+
- test/V2/Client_test.rb
|
|
47
45
|
- test/helper.rb
|
|
48
46
|
- test/test_all.rb
|
|
49
47
|
homepage: http://github.com/thoran/bitget.rb
|
|
@@ -64,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
64
62
|
- !ruby/object:Gem::Version
|
|
65
63
|
version: '0'
|
|
66
64
|
requirements: []
|
|
67
|
-
rubygems_version:
|
|
65
|
+
rubygems_version: 4.0.18
|
|
68
66
|
specification_version: 4
|
|
69
67
|
summary: Access the Bitget API with Ruby.
|
|
70
68
|
test_files: []
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Thoran/Hash/XWwwFormUrlEncode/x_www_form_urlencode.rb
|
|
2
|
-
# Thoran::Hash::XWwwFormUrlEncode#x_www_form_urlencode
|
|
3
|
-
|
|
4
|
-
# 20241009
|
|
5
|
-
# 0.2.0
|
|
6
|
-
|
|
7
|
-
# Changes since 0.1:
|
|
8
|
-
# -/0: (The class name and the snake case name are consistent now.)
|
|
9
|
-
# 1. /XWWWFormUrlEncode/XWwwFormUrlEncode/
|
|
10
|
-
|
|
11
|
-
require 'Thoran/String/UrlEncode/url_encode'
|
|
12
|
-
|
|
13
|
-
module Thoran
|
|
14
|
-
module Hash
|
|
15
|
-
module XWwwFormUrlEncode
|
|
16
|
-
|
|
17
|
-
def x_www_form_url_encode(joiner = '&')
|
|
18
|
-
inject([]){|a,e| a << "#{e.first.to_s.url_encode}=#{e.last.to_s.url_encode}" unless e.last.nil?; a}.join(joiner)
|
|
19
|
-
end
|
|
20
|
-
alias_method :x_www_form_urlencode, :x_www_form_url_encode
|
|
21
|
-
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
Hash.send(:include, Thoran::Hash::XWwwFormUrlEncode)
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
require_relative '../helper'
|
|
2
|
-
require_relative '../../lib/Bitget/V2/Client'
|
|
3
|
-
|
|
4
|
-
describe Bitget::V2::Client do
|
|
5
|
-
let(:api_key){ENV.fetch('BITGET_API_KEY', '<API_KEY>')}
|
|
6
|
-
let(:api_secret){ENV.fetch('BITGET_API_SECRET', '<API_SECRET>')}
|
|
7
|
-
let(:api_passphrase){ENV.fetch('BITGET_API_PASSPHRASE', '<API_PASSPHRASE>')}
|
|
8
|
-
|
|
9
|
-
let(:client) do
|
|
10
|
-
Bitget::V2::Client.new(
|
|
11
|
-
api_key: api_key,
|
|
12
|
-
api_secret: api_secret,
|
|
13
|
-
api_passphrase: api_passphrase
|
|
14
|
-
)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe "logging" do
|
|
18
|
-
before do
|
|
19
|
-
FileUtils.rm_f(client.class.log_file_path)
|
|
20
|
-
client.class.instance_variable_set(:@log_file_path, nil)
|
|
21
|
-
client.class.instance_variable_set(:@logger, nil)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
after do
|
|
25
|
-
FileUtils.rm_f(client.class.log_file_path)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
describe "logging configuration" do
|
|
29
|
-
it "uses the configured log file path" do
|
|
30
|
-
client.class.log_file_path = '/some/path'
|
|
31
|
-
_(client.class.log_file_path).must_equal(File.expand_path('/some/path'))
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
it "creates log directory if it doesn't exist" do
|
|
35
|
-
nested_path = File.join(Dir.tmpdir, 'bitget_test', 'nested', 'test.log')
|
|
36
|
-
client.class.log_file_path = nested_path
|
|
37
|
-
client.class.logger
|
|
38
|
-
_(File.directory?(File.dirname(nested_path))).must_equal(true)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
it "creates a daily rotating logger" do
|
|
42
|
-
_(client.class.logger).must_be_kind_of(Logger)
|
|
43
|
-
_(File.exist?(client.class.log_file_path)).must_equal(true)
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
describe "request logging" do
|
|
48
|
-
it "logs requests" do
|
|
49
|
-
client.class.logger
|
|
50
|
-
VCR.use_cassette('v2/spot/public/coins-when_coin_is_supplied') do
|
|
51
|
-
client.spot_public_coins(coin: 'BTC')
|
|
52
|
-
end
|
|
53
|
-
client.class.logger.close
|
|
54
|
-
log_content = File.read(client.class.log_file_path)
|
|
55
|
-
_(log_content).must_match(/GET https:\/\/api.bitget.com\/api\/v2\/spot\/public\/coins/)
|
|
56
|
-
_(log_content).must_match(/Args: \{coin: \"BTC\"}/)
|
|
57
|
-
_(log_content).must_match(/Headers: .+\"Content-Type\" => \"application\/json\"/)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
describe "response logging" do
|
|
62
|
-
it "logs responses" do
|
|
63
|
-
client.class.logger
|
|
64
|
-
VCR.use_cassette('v2/spot/public/coins-when_coin_is_supplied') do
|
|
65
|
-
client.spot_public_coins(coin: 'BTC')
|
|
66
|
-
end
|
|
67
|
-
client.class.logger.close
|
|
68
|
-
log_content = File.read(client.class.log_file_path)
|
|
69
|
-
_(log_content).must_match(/Code:/)
|
|
70
|
-
_(log_content).must_match(/Message:/)
|
|
71
|
-
_(log_content).must_match(/Body:/)
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
describe "error logging" do
|
|
76
|
-
it "logs error responses" do
|
|
77
|
-
client.class.logger
|
|
78
|
-
VCR.use_cassette('v2/spot/public/coins-when_error_occurs') do
|
|
79
|
-
begin
|
|
80
|
-
client.spot_public_coins(coin: 'INVALID')
|
|
81
|
-
rescue Bitget::Error
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
client.class.logger.close
|
|
85
|
-
log_content = File.read(client.class.log_file_path)
|
|
86
|
-
_(log_content).must_match(/Code:/)
|
|
87
|
-
_(log_content).must_match(/Message:/)
|
|
88
|
-
_(log_content).must_match(/Body:/)
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
data/test/client_test.rb
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
require_relative './helper'
|
|
2
|
-
require_relative '../lib/Bitget/Client'
|
|
3
|
-
|
|
4
|
-
describe Bitget::Client do
|
|
5
|
-
let(:client) do
|
|
6
|
-
Bitget::Client.new(
|
|
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
|
-
)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# Market
|
|
14
|
-
|
|
15
|
-
%w[
|
|
16
|
-
spot_public_coins
|
|
17
|
-
spot_public_symbols
|
|
18
|
-
spot_market_vip_free_rate
|
|
19
|
-
spot_market_tickers
|
|
20
|
-
spot_market_merge_depth
|
|
21
|
-
spot_market_orderbook
|
|
22
|
-
spot_market_candles
|
|
23
|
-
spot_market_history_candles
|
|
24
|
-
spot_market_fills
|
|
25
|
-
spot_market_fills_history
|
|
26
|
-
].each do |method|
|
|
27
|
-
describe "##{method}" do
|
|
28
|
-
it "delegates to V2::Client" do
|
|
29
|
-
mock_v2_client = Minitest::Mock.new
|
|
30
|
-
client.instance_variable_set(:@v2_client, mock_v2_client)
|
|
31
|
-
|
|
32
|
-
args = case method
|
|
33
|
-
when 'spot_market_merge_depth', 'spot_market_orderbook'
|
|
34
|
-
{symbol: 'BTCUSDT'}
|
|
35
|
-
when 'spot_market_candles', 'spot_market_history_candles'
|
|
36
|
-
{symbol: 'BTCUSDT', granularity: '1min'}
|
|
37
|
-
when 'spot_market_fills', 'spot_market_fills_history'
|
|
38
|
-
{symbol: 'BTCUSDT'}
|
|
39
|
-
else
|
|
40
|
-
{}
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
mock_v2_client.expect(method.to_sym, nil, [args])
|
|
44
|
-
client.send(method, **args)
|
|
45
|
-
mock_v2_client.verify
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Trade
|
|
51
|
-
|
|
52
|
-
%w[
|
|
53
|
-
spot_trade_place_order
|
|
54
|
-
spot_trade_cancel_replace_order
|
|
55
|
-
spot_trade_batch_cancel_replace_order
|
|
56
|
-
spot_trade_cancel_order
|
|
57
|
-
spot_trade_batch_orders
|
|
58
|
-
spot_trade_batch_cancel_order
|
|
59
|
-
spot_trade_cancel_symbol_order
|
|
60
|
-
spot_trade_order_info
|
|
61
|
-
spot_trade_unfilled_orders
|
|
62
|
-
spot_trade_history_orders
|
|
63
|
-
spot_trade_fills
|
|
64
|
-
].each do |method|
|
|
65
|
-
describe "##{method}" do
|
|
66
|
-
it "delegates to V2::Client" do
|
|
67
|
-
mock_v2_client = Minitest::Mock.new
|
|
68
|
-
client.instance_variable_set(:@v2_client, mock_v2_client)
|
|
69
|
-
|
|
70
|
-
args = case method
|
|
71
|
-
when 'spot_trade_place_order'
|
|
72
|
-
{
|
|
73
|
-
symbol: 'BTCUSDT',
|
|
74
|
-
side: 'buy',
|
|
75
|
-
order_type: 'limit',
|
|
76
|
-
force: 'normal',
|
|
77
|
-
size: '0.001',
|
|
78
|
-
price: '30000'
|
|
79
|
-
}
|
|
80
|
-
when /cancel|modify|info/
|
|
81
|
-
{symbol: 'BTCUSDT', order_id: '123456'}
|
|
82
|
-
when /batch/
|
|
83
|
-
{symbol: 'BTCUSDT', order_ids: ['123', '456']}
|
|
84
|
-
else
|
|
85
|
-
{symbol: 'BTCUSDT'}
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
mock_v2_client.expect(method.to_sym, nil, [args])
|
|
89
|
-
client.send(method, **args)
|
|
90
|
-
mock_v2_client.verify
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
# Trigger
|
|
96
|
-
|
|
97
|
-
%w[
|
|
98
|
-
spot_trade_place_plan_order
|
|
99
|
-
spot_trade_modify_plan_order
|
|
100
|
-
spot_trade_cancel_plan_order
|
|
101
|
-
spot_trade_current_plan_order
|
|
102
|
-
spot_trade_plan_sub_order
|
|
103
|
-
spot_trade_history_plan_order
|
|
104
|
-
spot_trade_batch_cancel_plan_order
|
|
105
|
-
].each do |method|
|
|
106
|
-
describe "##{method}" do
|
|
107
|
-
it "delegates to V2::Client" do
|
|
108
|
-
mock_v2_client = Minitest::Mock.new
|
|
109
|
-
client.instance_variable_set(:@v2_client, mock_v2_client)
|
|
110
|
-
|
|
111
|
-
args = case method
|
|
112
|
-
when 'spot_trade_place_plan_order'
|
|
113
|
-
{
|
|
114
|
-
symbol: 'BTCUSDT',
|
|
115
|
-
side: 'buy',
|
|
116
|
-
order_type: 'limit',
|
|
117
|
-
size: '0.001',
|
|
118
|
-
trigger_price: '31000',
|
|
119
|
-
execute_price: '30000'
|
|
120
|
-
}
|
|
121
|
-
when 'spot_trade_modify_plan_order'
|
|
122
|
-
{
|
|
123
|
-
order_id: '123456',
|
|
124
|
-
trigger_price: '31000',
|
|
125
|
-
execute_price: '30000',
|
|
126
|
-
size: '0.001'
|
|
127
|
-
}
|
|
128
|
-
when 'spot_trade_cancel_plan_order'
|
|
129
|
-
{order_id: '123456'}
|
|
130
|
-
when 'spot_trade_plan_sub_order'
|
|
131
|
-
{order_id: '123456'}
|
|
132
|
-
when 'spot_trade_batch_cancel_plan_order'
|
|
133
|
-
{symbol: 'BTCUSDT', order_ids: ['123', '456']}
|
|
134
|
-
else
|
|
135
|
-
{symbol: 'BTCUSDT'}
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
mock_v2_client.expect(method.to_sym, nil, [args])
|
|
139
|
-
client.send(method, **args)
|
|
140
|
-
mock_v2_client.verify
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
# Account
|
|
146
|
-
|
|
147
|
-
%w[
|
|
148
|
-
spot_account_info
|
|
149
|
-
spot_account_assets
|
|
150
|
-
spot_account_subaccount_assets
|
|
151
|
-
spot_account_bills
|
|
152
|
-
spot_account_sub_main_trans_record
|
|
153
|
-
spot_account_transfer_records
|
|
154
|
-
spot_account_switch_deduct
|
|
155
|
-
spot_account_deduct_info
|
|
156
|
-
spot_wallet_modify_deposit_account
|
|
157
|
-
spot_wallet_transfer
|
|
158
|
-
spot_wallet_transfer_coin_info
|
|
159
|
-
spot_wallet_subaccount_transfer
|
|
160
|
-
spot_wallet_withdrawal
|
|
161
|
-
spot_wallet_cancel_withdrawal
|
|
162
|
-
spot_wallet_deposit_address
|
|
163
|
-
spot_wallet_subaccount_deposit_address
|
|
164
|
-
spot_wallet_subaccount_deposit_records
|
|
165
|
-
spot_wallet_withdrawal_records
|
|
166
|
-
spot_wallet_deposit_records
|
|
167
|
-
].each do |method|
|
|
168
|
-
describe "##{method}" do
|
|
169
|
-
it "delegates to V2::Client" do
|
|
170
|
-
mock_v2_client = Minitest::Mock.new
|
|
171
|
-
client.instance_variable_set(:@v2_client, mock_v2_client)
|
|
172
|
-
|
|
173
|
-
args = case method
|
|
174
|
-
when 'spot_wallet_withdrawal'
|
|
175
|
-
{
|
|
176
|
-
coin: 'USDT',
|
|
177
|
-
chain: 'TRC20',
|
|
178
|
-
address: '0x1234567890abcdef',
|
|
179
|
-
amount: '100'
|
|
180
|
-
}
|
|
181
|
-
when /transfer/
|
|
182
|
-
{
|
|
183
|
-
coin: 'USDT',
|
|
184
|
-
amount: '100'
|
|
185
|
-
}
|
|
186
|
-
when /subaccount/
|
|
187
|
-
{subaccount_id: '123456'}
|
|
188
|
-
else
|
|
189
|
-
{}
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
mock_v2_client.expect(method.to_sym, nil, [args])
|
|
193
|
-
client.send(method, **args)
|
|
194
|
-
mock_v2_client.verify
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
end
|