mixin_bot 0.7.7 → 0.7.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a6b6a8ef2f385b184baa4c0228bfb9a97867cff65aa625618ce08a7ff0570237
4
- data.tar.gz: 4d4f11a16d0bf135c56768f5658ac20e80db652474a9a5b55cb3700f41092196
3
+ metadata.gz: 222522068617e93a42e0b59a81d8afc8908ed3569217c643d781ba4b721f639a
4
+ data.tar.gz: 8d15656e77f7176c91b3daf7d6fc4901c257db8005d1adf27d526913c1646286
5
5
  SHA512:
6
- metadata.gz: e1af0e4eb4050880c4ad2593045cc911a3cd078649f4a1cd90d7a820fec799cb9d758a70160af6b94b40ae9c04592c2a2ffa00159535d9b8954095a161ad1329
7
- data.tar.gz: 571922c76b219488eb406836cb2d293365d16abe71f4a2fb7039d69ee53b52b71578b2f604264dd0f604d13dcebb53a40db06addef52dfff34cd21941088ae94
6
+ metadata.gz: 5fb562d8867fb8b06723367e9d1a38d4d7bd6c9d6d7c1af7444283855b316d2f18b5aae365f27eb14be85a1630541c81e790cc7aae94bbf2ac21591e029e7f76
7
+ data.tar.gz: b722aa66007d94077ef6b963b260066cfd02074469f58f70f2959f4cf6e1c4c8aaae9c6d18e2bf45af2903a0443f76a3989b172250e4a8c958cea2fcffdc42b8
@@ -27,15 +27,16 @@ module MixinBot
27
27
  HTTP
28
28
  .timeout(connect: 5, write: 5, read: 5)
29
29
  .request(
30
- :put,
31
- attachment.delete('upload_url'),
30
+ :put,
31
+ attachment.delete('upload_url'),
32
32
  {
33
33
  body: file,
34
34
  headers: {
35
35
  'x-amz-acl': 'public-read',
36
- 'Content-Type': 'application/octet-stream',
36
+ 'Content-Type': 'application/octet-stream'
37
37
  }
38
- })
38
+ }
39
+ )
39
40
 
40
41
  attachment
41
42
  end
@@ -38,6 +38,7 @@ module MixinBot
38
38
  COLLECTABLE_REQUEST_ACTIONS = %i[sign unlock].freeze
39
39
  def create_collectible_request(action, raw, access_token: nil)
40
40
  raise ArgumentError, "request action is limited in #{COLLECTABLE_REQUEST_ACTIONS.join(', ')}" unless COLLECTABLE_REQUEST_ACTIONS.include? action.to_sym
41
+
41
42
  path = '/collectibles/requests'
42
43
  payload = {
43
44
  action: action,
@@ -107,7 +108,7 @@ module MixinBot
107
108
 
108
109
  kwargs = kwargs.with_indifferent_access
109
110
  collectible = kwargs['collectible']
110
- raise "collectible is spent" if collectible['state'] == 'spent'
111
+ raise 'collectible is spent' if collectible['state'] == 'spent'
111
112
 
112
113
  build_raw_transaction(
113
114
  utxos: [collectible],
@@ -187,9 +187,9 @@ module MixinBot
187
187
  if outputs.empty?
188
188
  receivers_threshold = 1 if receivers.size == 1
189
189
  output0 = build_output(
190
- receivers: receivers,
191
- index: 0,
192
- amount: amount,
190
+ receivers: receivers,
191
+ index: 0,
192
+ amount: amount,
193
193
  threshold: receivers_threshold,
194
194
  hint: hint
195
195
  )
@@ -197,8 +197,8 @@ module MixinBot
197
197
 
198
198
  if input_amount > amount
199
199
  output1 = build_output(
200
- receivers: senders,
201
- index: 1,
200
+ receivers: senders,
201
+ index: 1,
202
202
  amount: input_amount - amount,
203
203
  threshold: senders_threshold,
204
204
  hint: hint
@@ -207,7 +207,7 @@ module MixinBot
207
207
  end
208
208
  end
209
209
 
210
- extra = extra || Digest.hexencode(memo.to_s.slice(0, 140))
210
+ extra ||= Digest.hexencode(memo.to_s.slice(0, 140))
211
211
  asset = asset_mixin_id || SHA3::Digest::SHA256.hexdigest(asset_id)
212
212
  tx = {
213
213
  version: 2,
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MixinBot
4
+ class CLI < Thor
5
+ desc 'api PATH', 'request PATH of Mixin API'
6
+ long_desc <<-LONGDESC
7
+ use `mixinbot api PATH` to request any Mixin API
8
+
9
+ Get user infomation:
10
+
11
+ $ mixinbot api /me -k ~/.mixinbot/keystore.json
12
+
13
+ Search user infomation:
14
+
15
+ $ mixinbot api /search/1051445 -k ~/.mixinbot/keystore.json
16
+
17
+ Generate a multisig payment:
18
+
19
+ $ mixinbot api /payments -k ~/.mixinbot/keystore.json -m POST -d '{"asset_id":"965e5c6e-434c-3fa9-b780-c50f43cd955c", "amount":"1", "trace_id": "37f16abb-0640-4d01-9423-a06121732d35", "memo":"test", "opponent_multisig":{"receivers":["0508a116-1239-4e28-b150-85a8e3e6b400", "7ed9292d-7c95-4333-aa48-a8c640064186", "a67c6e87-1c9e-4a1c-b81c-47a9f4f1bff1"], "threshold":2}}'
20
+ LONGDESC
21
+ option :keystore, type: :string, aliases: '-k', required: true, desc: 'keystore or keystore.json file path'
22
+ option :method, type: :string, aliases: '-m', default: 'GET', desc: 'HTTP method, GET or POST'
23
+ option :params, type: :hash, aliases: '-p', desc: 'HTTP GET params'
24
+ option :data, type: :string, aliases: '-d', default: '{}', desc: 'HTTP POST data'
25
+ option :accesstoken, type: :string, aliases: '-t', desc: 'Specify a accesstoken, or will generate by keystore'
26
+ def api(path)
27
+ path = "#{path}?#{URI.encode_www_form(options[:params])}" if options[:params].present?
28
+ payload =
29
+ begin
30
+ JSON.parse options[:data]
31
+ rescue JSON::ParserError => e
32
+ log UI.fmt("{{x}} #{e.inspect}")
33
+ {}
34
+ end
35
+
36
+ access_token = options[:accesstoken] || api_instance.access_token(options[:method].upcase, path, payload.blank? ? '' : payload.to_json)
37
+ authorization = format('Bearer %<access_token>s', access_token: access_token)
38
+ res = {}
39
+
40
+ CLI::UI::Spinner.spin("#{options[:method]} #{path}, payload: #{payload}") do |_spinner|
41
+ res =
42
+ case options[:method].downcase.to_sym
43
+ when :post
44
+ api_instance.client.post(path, headers: { 'Authorization': authorization }, json: payload)
45
+ when :get
46
+ api_instance.client.get(path, headers: { 'Authorization': authorization })
47
+ end
48
+ end
49
+
50
+ log res['data']
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MixinBot
4
+ class CLI < Thor
5
+ desc 'encrypt PIN', 'encrypt PIN using private key'
6
+ option :keystore, type: :string, aliases: '-k', required: true, desc: 'keystore or keystore.json file path'
7
+ option :iterator, type: :string, aliases: '-i', desc: 'Iterator'
8
+ def encrypt(pin)
9
+ log api_instance.encrypt_pin options[:pin].to_s, iterator: options[:iterator]
10
+ end
11
+
12
+ desc 'unique UUIDS', 'generate unique UUID for two or more UUIDs'
13
+ def unique(*uuids)
14
+ uuids.sort
15
+ r = uuids.first
16
+ uuids.each_with_index do |uuid, i|
17
+ r = MixinBot::Utils.unique_uuid(r, uuid) if i.positive?
18
+ end
19
+
20
+ log r
21
+ end
22
+
23
+ desc 'generatetrace HASH', 'generate trace ID from Tx hash'
24
+ def generatetrace(hash)
25
+ log MixinBot::Utils.generate_trace_from_hash(hash)
26
+ end
27
+
28
+ desc 'decodetx TRANSACTION', 'decode raw transaction'
29
+ def decodetx(transaction)
30
+ log MixinBot::Utils.decode_raw_transaction(transaction)
31
+ end
32
+
33
+ desc 'nftmemo', 'memo for mint NFT'
34
+ option :collection, type: :string, required: true, aliases: '-c', desc: 'Collection ID, UUID'
35
+ option :token, type: :numeric, required: true, aliases: '-t', desc: 'Token ID, Integer'
36
+ option :hash, type: :string, required: true, aliases: '-h', desc: 'Hash of NFT metadata, 256-bit string'
37
+ def nftmemo
38
+ log MixinBot::Utils.nft(options[:collection], options[:token], options[:hash])
39
+ end
40
+ end
41
+ end
data/lib/mixin_bot/cli.rb CHANGED
@@ -5,77 +5,61 @@ require 'cli/ui'
5
5
  require 'thor'
6
6
  require 'yaml'
7
7
  require 'json'
8
+ require_relative './cli/api'
8
9
  require_relative './cli/node'
9
- require_relative './cli/me'
10
- require_relative './cli/multisig'
10
+ require_relative './cli/utils'
11
11
 
12
12
  module MixinBot
13
13
  class CLI < Thor
14
14
  # https://github.com/Shopify/cli-ui
15
15
  UI = ::CLI::UI
16
16
 
17
- class_option :apihost, type: :string, aliases: '-a', desc: 'Specify mixin api host, default as api.mixin.one'
18
- class_option :pretty, type: :boolean, aliases: '-p', desc: 'Print output in pretty'
17
+ class_option :apihost, type: :string, aliases: '-a', default: 'api.mixin.one', desc: 'Specify mixin api host'
18
+ class_option :pretty, type: :boolean, aliases: '-r', default: true, desc: 'Print output in pretty'
19
19
 
20
- attr_reader :config, :api
20
+ attr_reader :keystore, :api_instance
21
21
 
22
22
  def initialize(*args)
23
23
  super
24
- if File.exist? options[:config].to_s
25
- @config =
26
- begin
27
- YAML.load_file options[:config]
28
- rescue StandardError => e
29
- log UI.fmt(
30
- format(
31
- '{{x}} %<file>s is not a valid .yml file',
32
- file: options[:config]
33
- )
34
- )
35
- UI::Frame.open('{{x}}', color: :red) do
36
- log e
37
- end
38
- end
39
- elsif options[:config]
40
- @confg =
41
- begin
42
- JSON.parse options[:config]
43
- rescue StandardError => e
44
- log UI.fmt(
45
- format(
46
- '{{x}} Failed to parse %<config>s',
47
- config: options[:config]
48
- )
24
+ return if options[:keystore].blank?
25
+
26
+ keystore =
27
+ if File.file? options[:keystore]
28
+ File.read options[:keystore]
29
+ else
30
+ options[:keystore]
31
+ end
32
+
33
+ @keystore =
34
+ begin
35
+ JSON.parse keystore
36
+ rescue JSON::ParserError => e
37
+ log UI.fmt(
38
+ format(
39
+ '{{x}} falied to parse keystore.json: %<keystore>s',
40
+ keystore: options[:keystore]
49
41
  )
50
- UI::Frame.open('{{x}}', color: :red) do
51
- log e
52
- end
53
- end
54
- end
42
+ )
43
+ end
55
44
 
56
- return unless @config
45
+ return unless @keystore
57
46
 
58
47
  MixinBot.api_host = options[:apihost]
59
- @api ||=
48
+ @api_instance ||=
60
49
  begin
61
50
  MixinBot::API.new(
62
- client_id: @config['client_id'],
63
- client_secret: @config['client_secret'],
64
- session_id: @config['session_id'],
65
- pin_token: @config['pin_token'],
66
- private_key: @config['private_key'],
67
- pin_code: @config['pin_code']
51
+ client_id: @keystore['client_id'],
52
+ session_id: @keystore['session_id'],
53
+ pin_token: @keystore['pin_token'],
54
+ private_key: @keystore['private_key']
68
55
  )
69
56
  rescue StandardError => e
70
- log UI.fmt '{{x}}: Failed to initialize api, maybe your config is incorrect.'
71
- UI.Frame.open('{{x}}', color: :red) do
72
- log e
73
- end
57
+ log UI.fmt '{{x}}: Failed to initialize api, maybe your keystore is incorrect.'
74
58
  end
75
59
  end
76
60
 
77
- desc 'node', 'mixin node commands helper'
78
- subcommand 'node', MixinBot::NodeCLI
61
+ # desc 'node', 'mixin node commands helper'
62
+ # subcommand 'node', MixinBot::NodeCLI
79
63
 
80
64
  desc 'version', 'Distay MixinBot version'
81
65
  def version
@@ -88,31 +72,6 @@ module MixinBot
88
72
 
89
73
  private
90
74
 
91
- def api_method(method, *args, **params)
92
- if api.nil?
93
- log UI.fmt '{{x}} MixinBot api not initialized!'
94
- return
95
- end
96
-
97
- res = if args.empty? && params.empty?
98
- api&.public_send method
99
- elsif args.empty? && !params.empty?
100
- api&.public_send method params
101
- elsif !args.empty? && params.empty?
102
- api&.public_send method, args
103
- else
104
- args.push params
105
- api&.public_send method, args
106
- end
107
- log res
108
-
109
- [res, res && res['error'].nil?]
110
- rescue MixinBot::Errors => e
111
- UI::Frame.open('{{x}}', color: :red) do
112
- log e
113
- end
114
- end
115
-
116
75
  def log(obj)
117
76
  if options[:pretty]
118
77
  if obj.is_a? String
@@ -57,7 +57,7 @@ module MixinBot
57
57
  if tx.is_a? String
58
58
  tx = JSON.parse tx
59
59
  end
60
- raise "#{tx} is not a valid json" unless tx.is_a? Hash
60
+ raise ArgumentError, "#{tx} is not a valid json" unless tx.is_a? Hash
61
61
 
62
62
  tx = tx.with_indifferent_access
63
63
  bytes = []
@@ -99,7 +99,7 @@ module MixinBot
99
99
  tx = {}
100
100
 
101
101
  magic = bytes.shift(2)
102
- raise 'Not valid raw' unless magic == MAGIC
102
+ raise ArgumentError, 'Not valid raw' unless magic == MAGIC
103
103
 
104
104
  version = bytes.shift(2)
105
105
  tx['version'] = bytes_to_int version
@@ -121,7 +121,7 @@ module MixinBot
121
121
  # aggregated
122
122
  aggregated = {}
123
123
 
124
- raise 'invalid aggregated' unless bytes.shift(2).reverse.pack('C*').unpack1('S*') == AGGREGATED_SIGNATURE_PREFIX
124
+ raise ArgumentError, 'invalid aggregated' unless bytes.shift(2).reverse.pack('C*').unpack1('S*') == AGGREGATED_SIGNATURE_PREFIX
125
125
 
126
126
  aggregated['signature'] = bytes.shift(64).pack('C*').unpack1('H*')
127
127
 
@@ -162,7 +162,7 @@ module MixinBot
162
162
 
163
163
  def nft_memo_hash(collection, token_id, hash)
164
164
  collection = NULL_UUID if collection.empty?
165
- raise 'hash must be 256-bit string' unless hash.is_a?(String) && hash.size == 64
165
+ raise ArgumentError, 'hash must be 256-bit string' unless hash.is_a?(String) && hash.size == 64
166
166
 
167
167
  memo = {
168
168
  prefix: NFT_MEMO_PREFIX,
@@ -171,14 +171,14 @@ module MixinBot
171
171
  chain: NFT_MEMO_DEFAULT_CHAIN,
172
172
  class: NFT_MEMO_DEFAULT_CLASS,
173
173
  collection: collection,
174
- token: token_id,
174
+ token: token_id.to_i,
175
175
  extra: hash
176
176
  }
177
177
 
178
178
  mark = [0]
179
179
  mark.map do |index|
180
180
  if index >= 64
181
- raise "invalid NFO memo index #{index}"
181
+ raise ArgumentError, "invalid NFO memo index #{index}"
182
182
  end
183
183
  memo[:mask] = memo[:mask] ^ (1 << index)
184
184
  end
@@ -252,8 +252,8 @@ module MixinBot
252
252
  private
253
253
 
254
254
  def encode_int(int)
255
- raise "only support int #{int}" unless int.is_a?(Integer)
256
- raise "int #{int} is larger than MAX_ENCODE_INT #{MAX_ENCODE_INT}" if int > MAX_ENCODE_INT
255
+ raise ArgumentError, "only support int #{int}" unless int.is_a?(Integer)
256
+ raise ArgumentError,"int #{int} is larger than MAX_ENCODE_INT #{MAX_ENCODE_INT}" if int > MAX_ENCODE_INT
257
257
 
258
258
  [int].pack('S*').bytes.reverse
259
259
  end
@@ -263,7 +263,7 @@ module MixinBot
263
263
  end
264
264
 
265
265
  def bytes_of(int)
266
- raise 'not integer' unless int.is_a?(Integer)
266
+ raise ArgumentError, 'not integer' unless int.is_a?(Integer)
267
267
 
268
268
  bytes = []
269
269
  loop do
@@ -427,8 +427,8 @@ module MixinBot
427
427
  bytes += NULL_BYTES
428
428
  else
429
429
  signers.each do |sig, i|
430
- raise 'signers not sorted' if i > 0 && sig <= signers[i - 1]
431
- raise 'signers not sorted' if sig > MAX_ENCODE_INT
430
+ raise ArgumentError, 'signers not sorted' if i > 0 && sig <= signers[i - 1]
431
+ raise ArgumentError, 'signers not sorted' if sig > MAX_ENCODE_INT
432
432
  end
433
433
 
434
434
  max = signers.last
@@ -458,7 +458,7 @@ module MixinBot
458
458
  0
459
459
  end
460
460
 
461
- raise 'signatures overflow' if sl == MAX_ENCODE_INT
461
+ raise ArgumentError, 'signatures overflow' if sl == MAX_ENCODE_INT
462
462
  bytes += encode_int sl
463
463
 
464
464
  if sl > 0
@@ -493,7 +493,7 @@ module MixinBot
493
493
 
494
494
  if bytes[...2] != NULL_BYTES
495
495
  magic = bytes.shift(2)
496
- raise 'Not valid input' unless magic == MAGIC
496
+ raise ArgumentError, 'Not valid input' unless magic == MAGIC
497
497
 
498
498
  deposit = {}
499
499
  deposit['chain'] = bytes.shift(32).pack('C*').unpack1('H*')
@@ -516,7 +516,7 @@ module MixinBot
516
516
 
517
517
  if bytes[...2] != NULL_BYTES
518
518
  magic = bytes.shift(2)
519
- raise 'Not valid input' unless magic == MAGIC
519
+ raise ArgumentError, 'Not valid input' unless magic == MAGIC
520
520
 
521
521
  mint = {}
522
522
  if bytes[...2] != NULL_BYTES
@@ -567,7 +567,7 @@ module MixinBot
567
567
 
568
568
  if bytes[...2] != NULL_BYTES
569
569
  magic = bytes.shift(2)
570
- raise 'Not valid output' unless magic == MAGIC
570
+ raise ArgumentError, 'Not valid output' unless magic == MAGIC
571
571
 
572
572
  withdraw = {}
573
573
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MixinBot
4
- VERSION = '0.7.7'
4
+ VERSION = '0.7.10'
5
5
  end
data/lib/mixin_bot.rb CHANGED
@@ -30,12 +30,14 @@ module MixinBot
30
30
  @api ||= MixinBot::API.new
31
31
  end
32
32
 
33
- class HttpError < StandardError; end
34
- class RequestError < StandardError; end
35
- class ResponseError < StandardError; end
36
- class UnauthorizedError < StandardError; end
37
- class ForbiddenError < StandardError; end
38
- class InsufficientBalanceError < StandardError; end
39
- class InsufficientPoolError < StandardError; end
40
- class PinError < StandardError; end
33
+ class Error < StandardError; end
34
+ class ArgumentError < StandardError; end
35
+ class HttpError < Error; end
36
+ class RequestError < Error; end
37
+ class ResponseError < Error; end
38
+ class UnauthorizedError < Error; end
39
+ class ForbiddenError < Error; end
40
+ class InsufficientBalanceError < Error; end
41
+ class InsufficientPoolError < Error; end
42
+ class PinError < Error; end
41
43
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixin_bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.7
4
+ version: 0.7.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - an-lee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-31 00:00:00.000000000 Z
11
+ date: 2022-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -293,9 +293,9 @@ files:
293
293
  - lib/mixin_bot/api/user.rb
294
294
  - lib/mixin_bot/api/withdraw.rb
295
295
  - lib/mixin_bot/cli.rb
296
- - lib/mixin_bot/cli/me.rb
297
- - lib/mixin_bot/cli/multisig.rb
296
+ - lib/mixin_bot/cli/api.rb
298
297
  - lib/mixin_bot/cli/node.rb
298
+ - lib/mixin_bot/cli/utils.rb
299
299
  - lib/mixin_bot/client.rb
300
300
  - lib/mixin_bot/utils.rb
301
301
  - lib/mixin_bot/version.rb
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module MixinBot
4
- class CLI < Thor
5
- desc 'read_me', 'fetch mixin bot profile'
6
- option :config, required: true, aliases: '-c'
7
- def read_me
8
- api_method(:read_me)
9
- end
10
-
11
- desc 'read_assets', 'fetch mixin bot assets'
12
- option :config, required: true, aliases: '-c'
13
- def read_assets
14
- api_method(:read_assets)
15
- end
16
-
17
- desc 'cal_assets_as_usd', 'fetch mixin bot assets'
18
- option :config, required: true, aliases: '-c'
19
- def cal_assets_as_usd
20
- assets, success = read_assets
21
- return unless success
22
-
23
- sum = assets['data'].map(
24
- &lambda { |asset|
25
- asset['balance'].to_f * asset['price_usd'].to_f
26
- }
27
- ).sum
28
- UI::Frame.open('USD') do
29
- log sum
30
- end
31
- end
32
-
33
- desc 'read_asset', 'fetch specific asset of mixin bot'
34
- option :config, required: true, aliases: '-c'
35
- option :assetid, required: true, aliases: '-s'
36
- def read_asset
37
- api_method(:read_asset, options[:assetid])
38
- end
39
- end
40
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module MixinBot
4
- class CLI < Thor
5
- desc 'get_all_multisigs', 'fetch all utxos'
6
- option :config, required: true, aliases: '-c'
7
- def all_multisigs
8
- api_method(:get_all_multisigs)
9
- end
10
- end
11
- end