mixin_bot 0.12.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mixin_bot/api/address.rb +21 -0
  3. data/lib/mixin_bot/api/app.rb +5 -11
  4. data/lib/mixin_bot/api/asset.rb +9 -16
  5. data/lib/mixin_bot/api/attachment.rb +27 -22
  6. data/lib/mixin_bot/api/auth.rb +31 -53
  7. data/lib/mixin_bot/api/blaze.rb +4 -3
  8. data/lib/mixin_bot/api/collectible.rb +60 -58
  9. data/lib/mixin_bot/api/conversation.rb +29 -49
  10. data/lib/mixin_bot/api/encrypted_message.rb +17 -17
  11. data/lib/mixin_bot/api/legacy_multisig.rb +87 -0
  12. data/lib/mixin_bot/api/legacy_output.rb +50 -0
  13. data/lib/mixin_bot/api/legacy_payment.rb +31 -0
  14. data/lib/mixin_bot/api/legacy_snapshot.rb +39 -0
  15. data/lib/mixin_bot/api/legacy_transaction.rb +173 -0
  16. data/lib/mixin_bot/api/legacy_transfer.rb +42 -0
  17. data/lib/mixin_bot/api/me.rb +13 -17
  18. data/lib/mixin_bot/api/message.rb +13 -10
  19. data/lib/mixin_bot/api/multisig.rb +16 -221
  20. data/lib/mixin_bot/api/output.rb +46 -0
  21. data/lib/mixin_bot/api/payment.rb +9 -20
  22. data/lib/mixin_bot/api/pin.rb +57 -65
  23. data/lib/mixin_bot/api/rpc.rb +9 -11
  24. data/lib/mixin_bot/api/snapshot.rb +15 -29
  25. data/lib/mixin_bot/api/tip.rb +43 -0
  26. data/lib/mixin_bot/api/transaction.rb +184 -60
  27. data/lib/mixin_bot/api/transfer.rb +64 -32
  28. data/lib/mixin_bot/api/user.rb +83 -53
  29. data/lib/mixin_bot/api/withdraw.rb +52 -53
  30. data/lib/mixin_bot/api.rb +78 -45
  31. data/lib/mixin_bot/cli/api.rb +151 -8
  32. data/lib/mixin_bot/cli/utils.rb +14 -4
  33. data/lib/mixin_bot/cli.rb +13 -10
  34. data/lib/mixin_bot/client.rb +76 -127
  35. data/lib/mixin_bot/configuration.rb +98 -0
  36. data/lib/mixin_bot/nfo.rb +174 -0
  37. data/lib/mixin_bot/transaction.rb +505 -0
  38. data/lib/mixin_bot/utils/address.rb +108 -0
  39. data/lib/mixin_bot/utils/crypto.rb +182 -0
  40. data/lib/mixin_bot/utils/decoder.rb +58 -0
  41. data/lib/mixin_bot/utils/encoder.rb +63 -0
  42. data/lib/mixin_bot/utils.rb +8 -109
  43. data/lib/mixin_bot/uuid.rb +41 -0
  44. data/lib/mixin_bot/version.rb +1 -1
  45. data/lib/mixin_bot.rb +39 -14
  46. data/lib/mvm/bridge.rb +2 -19
  47. data/lib/mvm/client.rb +11 -33
  48. data/lib/mvm/nft.rb +4 -4
  49. data/lib/mvm/registry.rb +9 -9
  50. data/lib/mvm/scan.rb +3 -5
  51. data/lib/mvm.rb +5 -6
  52. metadata +101 -44
  53. data/lib/mixin_bot/utils/nfo.rb +0 -176
  54. data/lib/mixin_bot/utils/transaction.rb +0 -478
  55. data/lib/mixin_bot/utils/uuid.rb +0 -43
@@ -3,75 +3,74 @@
3
3
  module MixinBot
4
4
  class API
5
5
  module Withdraw
6
- # https://developers.mixin.one/api/alpha-mixin-network/create-address/
7
- def create_withdraw_address(options, access_token: nil)
6
+ def create_withdraw_address(**kwargs)
8
7
  path = '/addresses'
9
- encrypted_pin = encrypt_pin(options[:pin])
8
+ pin = kwargs[:pin]
10
9
  payload =
11
- # for EOS withdraw, account_name & account_tag must be valid
12
- if options[:public_key].nil?
13
- {
14
- asset_id: options[:asset_id],
15
- account_name: options[:account_name],
16
- account_tag: options[:account_tag],
17
- label: options[:label],
18
- pin: encrypted_pin
19
- }
20
- # for other withdraw
21
- else
22
- {
23
- asset_id: options[:asset_id],
24
- public_key: options[:public_key],
25
- label: options[:label],
26
- pin: encrypted_pin
27
- }
28
- end
10
+ {
11
+ asset_id: kwargs[:asset_id],
12
+ destination: kwargs[:destination],
13
+ tag: kwargs[:tag],
14
+ label: kwargs[:label]
15
+ }
16
+
17
+ if pin.length > 6
18
+ payload[:pin_base64] = encrypt_tip_pin pin, 'TIP:ADDRESS:ADD:', payload[:asset_id], payload[:destination], payload[:tag], payload[:label]
19
+ else
20
+ payload[:pin] = encrypt_pin pin
21
+ end
29
22
 
30
- access_token ||= access_token('POST', path, payload.to_json)
31
- authorization = format('Bearer %<access_token>s', access_token: access_token)
32
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
23
+ client.post path, **payload
33
24
  end
34
25
 
35
- # https://developers.mixin.one/api/alpha-mixin-network/read-address/
36
26
  def get_withdraw_address(address, access_token: nil)
37
- path = format('/addresses/%<address>s', address: address)
38
- access_token ||= access_token('GET', path, '')
39
- authorization = format('Bearer %<access_token>s', access_token: access_token)
40
- client.get(path, headers: { 'Authorization': authorization })
27
+ path = format('/addresses/%<address>s', address:)
28
+
29
+ client.get path, access_token:
41
30
  end
42
31
 
43
- # https://developers.mixin.one/api/alpha-mixin-network/delete-address/
44
- def delete_withdraw_address(address, pin, access_token: nil)
45
- path = format('/addresses/%<address>s/delete', address: address)
46
- payload = {
47
- pin: encrypt_pin(pin)
48
- }
32
+ def delete_withdraw_address(address, **kwargs)
33
+ pin = kwargs[:pin]
49
34
 
50
- access_token ||= access_token('POST', path, payload.to_json)
51
- authorization = format('Bearer %<access_token>s', access_token: access_token)
52
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
35
+ path = format('/addresses/%<address>s/delete', address:)
36
+ payload =
37
+ if pin.length > 6
38
+ {
39
+ pin_base64: encrypt_tip_pin(pin, 'TIP:ADDRESS:REMOVE:', address)
40
+ }
41
+ else
42
+ {
43
+ pin: encrypt_pin(pin)
44
+ }
45
+ end
46
+
47
+ client.post path, **payload
53
48
  end
54
49
 
55
- # https://developers.mixin.one/api/alpha-mixin-network/withdrawal-addresses/
56
- def withdrawals(options, access_token: nil)
57
- address_id = options[:address_id]
58
- pin = options[:pin]
59
- amount = options[:amount]
60
- trace_id = options[:trace_id]
61
- memo = options[:memo]
50
+ def withdrawals(**kwargs)
51
+ address_id = kwargs[:address_id]
52
+ pin = kwargs[:pin]
53
+ amount = format('%.8f', kwargs[:amount].to_d.to_r)
54
+ trace_id = kwargs[:trace_id]
55
+ memo = kwargs[:memo]
56
+ kwargs[:access_token]
62
57
 
63
58
  path = '/withdrawals'
64
59
  payload = {
65
- address_id: address_id,
66
- amount: amount,
67
- trace_id: trace_id,
68
- memo: memo,
69
- pin: encrypt_pin(pin)
60
+ address_id:,
61
+ amount:,
62
+ trace_id:,
63
+ memo:
70
64
  }
71
65
 
72
- access_token ||= access_token('POST', path, payload.to_json)
73
- authorization = format('Bearer %<access_token>s', access_token: access_token)
74
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
66
+ if pin.length > 6
67
+ fee = '0'
68
+ payload[:pin_base64] = encrypt_tip_pin pin, 'TIP:WITHDRAW:', address_id, amount, fee, trace_id, memo
69
+ else
70
+ payload[:pin] = encrypt_pin pin
71
+ end
72
+
73
+ client.post path, **payload
75
74
  end
76
75
  end
77
76
  end
data/lib/mixin_bot/api.rb CHANGED
@@ -1,62 +1,86 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative './client'
4
- require_relative './api/app'
5
- require_relative './api/asset'
6
- require_relative './api/attachment'
7
- require_relative './api/auth'
8
- require_relative './api/blaze'
9
- require_relative './api/collectible'
10
- require_relative './api/conversation'
11
- require_relative './api/encrypted_message'
12
- require_relative './api/me'
13
- require_relative './api/message'
14
- require_relative './api/multisig'
15
- require_relative './api/payment'
16
- require_relative './api/pin'
17
- require_relative './api/rpc'
18
- require_relative './api/snapshot'
19
- require_relative './api/transaction'
20
- require_relative './api/transfer'
21
- require_relative './api/user'
22
- require_relative './api/withdraw'
3
+ require_relative 'client'
4
+ require_relative 'configuration'
5
+ require_relative 'api/address'
6
+ require_relative 'api/app'
7
+ require_relative 'api/asset'
8
+ require_relative 'api/attachment'
9
+ require_relative 'api/auth'
10
+ require_relative 'api/blaze'
11
+ require_relative 'api/collectible'
12
+ require_relative 'api/conversation'
13
+ require_relative 'api/encrypted_message'
14
+ require_relative 'api/legacy_multisig'
15
+ require_relative 'api/legacy_output'
16
+ require_relative 'api/legacy_payment'
17
+ require_relative 'api/legacy_snapshot'
18
+ require_relative 'api/legacy_transaction'
19
+ require_relative 'api/legacy_transfer'
20
+ require_relative 'api/me'
21
+ require_relative 'api/message'
22
+ require_relative 'api/multisig'
23
+ require_relative 'api/output'
24
+ require_relative 'api/payment'
25
+ require_relative 'api/pin'
26
+ require_relative 'api/rpc'
27
+ require_relative 'api/snapshot'
28
+ require_relative 'api/tip'
29
+ require_relative 'api/transaction'
30
+ require_relative 'api/transfer'
31
+ require_relative 'api/user'
32
+ require_relative 'api/withdraw'
23
33
 
24
34
  module MixinBot
25
35
  class API
26
- attr_reader :client_id, :client_secret, :session_id, :pin_token, :private_key, :client, :blaze_host, :key_type
27
-
28
- def initialize(options = {})
29
- @client_id = options[:client_id] || MixinBot.client_id
30
- @client_secret = options[:client_secret] || MixinBot.client_secret
31
- @session_id = options[:session_id] || MixinBot.session_id
32
- @client = Client.new(MixinBot.api_host || 'api.mixin.one')
33
- @blaze_host = MixinBot.blaze_host || 'blaze.mixin.one'
34
- @pin_token =
35
- begin
36
- Base64.urlsafe_decode64 options[:pin_token] || MixinBot.pin_token
37
- rescue StandardError
38
- ''
36
+ attr_reader :config, :client
37
+
38
+ def initialize(**kwargs)
39
+ @config =
40
+ if kwargs.present?
41
+ MixinBot::Configuration.new(**kwargs)
42
+ else
43
+ MixinBot.config
39
44
  end
40
- _private_key = options[:private_key] || MixinBot.private_key
41
- if /^-----BEGIN RSA PRIVATE KEY-----/.match? _private_key
42
- @private_key = _private_key.gsub('\\r\\n', "\n").gsub("\r\n", "\n")
43
- @key_type = :rsa
44
- else
45
- @private_key = Base64.urlsafe_decode64 _private_key
46
- @key_type = :ed25519
47
- end
45
+
46
+ @client = Client.new(@config)
47
+ end
48
+
49
+ def utils
50
+ MixinBot::Utils
51
+ end
52
+
53
+ def client_id
54
+ config.app_id
48
55
  end
49
56
 
50
- def sign_raw_transaction(tx)
51
- MixinBot::Utils.sign_raw_transaction tx
57
+ def access_token(method, uri, body, **kwargs)
58
+ utils.access_token(
59
+ method,
60
+ uri,
61
+ body,
62
+ exp_in: kwargs.delete(:exp_in) || 600,
63
+ scp: kwargs.delete(:scp) || 'FULL',
64
+ app_id: config.app_id,
65
+ session_id: config.session_id,
66
+ private_key: config.session_private_key
67
+ )
68
+ end
69
+
70
+ def encode_raw_transaction(tx)
71
+ utils.encode_raw_transaction tx
52
72
  end
53
73
 
54
74
  def decode_raw_transaction(raw)
55
- MixinBot::Utils.decode_raw_transaction raw
75
+ utils.decode_raw_transaction raw
76
+ end
77
+
78
+ def generate_trace_from_hash(hash, output_index = 0)
79
+ utils.generate_trace_from_hash hash, output_index
56
80
  end
57
81
 
58
82
  # Use a mixin software to implement transaction build
59
- def sign_raw_transaction_native(json)
83
+ def encode_raw_transaction_native(json)
60
84
  ensure_mixin_command_exist
61
85
  command = format("mixin signrawtransaction --raw '%<arg>s'", arg: json)
62
86
 
@@ -77,6 +101,7 @@ module MixinBot
77
101
  JSON.parse output.chomp
78
102
  end
79
103
 
104
+ include MixinBot::API::Address
80
105
  include MixinBot::API::App
81
106
  include MixinBot::API::Asset
82
107
  include MixinBot::API::Attachment
@@ -85,13 +110,21 @@ module MixinBot
85
110
  include MixinBot::API::Collectible
86
111
  include MixinBot::API::Conversation
87
112
  include MixinBot::API::EncryptedMessage
113
+ include MixinBot::API::LegacyMultisig
114
+ include MixinBot::API::LegacyOutput
115
+ include MixinBot::API::LegacyPayment
116
+ include MixinBot::API::LegacySnapshot
117
+ include MixinBot::API::LegacyTransaction
118
+ include MixinBot::API::LegacyTransfer
88
119
  include MixinBot::API::Me
89
120
  include MixinBot::API::Message
90
121
  include MixinBot::API::Multisig
122
+ include MixinBot::API::Output
91
123
  include MixinBot::API::Payment
92
124
  include MixinBot::API::Pin
93
125
  include MixinBot::API::Rpc
94
126
  include MixinBot::API::Snapshot
127
+ include MixinBot::API::Tip
95
128
  include MixinBot::API::Transaction
96
129
  include MixinBot::API::Transfer
97
130
  include MixinBot::API::User
@@ -34,16 +34,16 @@ module MixinBot
34
34
  end
35
35
 
36
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)
37
+ authorization = format('Bearer %<access_token>s', access_token:)
38
38
  res = {}
39
39
 
40
40
  CLI::UI::Spinner.spin("#{options[:method]} #{path}, payload: #{payload}") do |_spinner|
41
41
  res =
42
42
  case options[:method].downcase.to_sym
43
43
  when :post
44
- api_instance.client.post(path, headers: { 'Authorization': authorization }, json: payload)
44
+ api_instance.client.post(path, headers: { Authorization: authorization }, json: payload)
45
45
  when :get
46
- api_instance.client.get(path, headers: { 'Authorization': authorization })
46
+ api_instance.client.get(path, headers: { Authorization: authorization })
47
47
  end
48
48
  end
49
49
 
@@ -52,20 +52,163 @@ module MixinBot
52
52
 
53
53
  desc 'authcode', 'code to authorize other mixin account'
54
54
  option :keystore, type: :string, aliases: '-k', required: true, desc: 'keystore or keystore.json file path'
55
- option :client_id, type: :string, required: true, aliases: '-c', desc: "client_id of bot to authorize"
55
+ option :app_id, type: :string, required: true, aliases: '-c', desc: 'app_id of bot to authorize'
56
56
  option :scope, type: :array, default: ['PROFILE:READ'], aliases: '-s', desc: 'scope to authorize'
57
- option :pin, type: :string, required: true, aliases: '-p', desc: 'pin'
58
57
  def authcode
59
58
  res = {}
60
- CLI::UI::Spinner.spin("POST /oauth/authorize") do |_spinner|
59
+ CLI::UI::Spinner.spin('POST /oauth/authorize') do |_spinner|
61
60
  res =
62
61
  api_instance.authorize_code(
63
- user_id: options[:client_id],
62
+ user_id: options[:app_id],
64
63
  scope: options[:scope],
65
- pin: options[:pin]
64
+ pin: keystore['pin']
66
65
  )
67
66
  end
68
67
  log res['data']
69
68
  end
69
+
70
+ desc 'updatetip PIN', 'update TIP pin'
71
+ option :keystore, type: :string, aliases: '-k', required: true, desc: 'keystore or keystore.json file path'
72
+ def updatetip(pin)
73
+ profile = api_instance.me
74
+ log UI.fmt "{{v}} #{profile['full_name']}, TIP counter: #{profile['tip_counter']}"
75
+
76
+ counter = profile['tip_counter']
77
+ key = api_instance.prepare_tip_key counter
78
+ log UI.fmt "{{v}} Generated key: #{key[:private_key]}"
79
+
80
+ res = api_instance.update_pin old_pin: pin.to_s, pin: key[:public_key]
81
+
82
+ log({
83
+ pin: key[:private_key],
84
+ tip_key_base64: res['tip_key_base64']
85
+ })
86
+ rescue StandardError => e
87
+ log UI.fmt "{{x}} #{e.inspect}"
88
+ end
89
+
90
+ desc 'verifypin PIN', 'verify pin'
91
+ option :keystore, type: :string, aliases: '-k', required: true, desc: 'keystore or keystore.json file path'
92
+ def verifypin(pin)
93
+ res = api_instance.verify_pin pin.to_s
94
+
95
+ log res
96
+ rescue StandardError => e
97
+ log UI.fmt "{{x}} #{e.inspect}"
98
+ end
99
+
100
+ desc 'transfer USER_ID', 'transfer asset to USER_ID'
101
+ option :asset, type: :string, required: true, desc: 'Asset ID'
102
+ option :amount, type: :numeric, required: true, desc: 'Amount'
103
+ option :memo, type: :string, required: false, desc: 'memo'
104
+ option :keystore, type: :string, aliases: '-k', required: true, desc: 'keystore or keystore.json file path'
105
+ def transfer(user_id)
106
+ res = {}
107
+
108
+ CLI::UI::Spinner.spin "Try to transfer #{options[:amount]} #{options[:asset]} to #{user_id}" do |_spinner|
109
+ res = api_instance.create_transfer(
110
+ keystore['pin'],
111
+ {
112
+ asset_id: options[:asset],
113
+ opponent_id: user_id,
114
+ amount: options[:amount],
115
+ memo: options[:memo]
116
+ }
117
+ )
118
+ end
119
+
120
+ return unless res['snapshot_id'].present?
121
+
122
+ log UI.fmt "{{v}} Finished: https://mixin.one/snapshots/#{res['snapshot_id']}"
123
+ end
124
+
125
+ desc 'saferegister', 'register SAFE network'
126
+ option :spend_key, type: :string, required: true, desc: 'spend_key'
127
+ option :keystore, type: :string, aliases: '-k', required: true, desc: 'keystore or keystore.json file path'
128
+ def saferegister
129
+ res = api_instance.safe_register options[:spend_key]
130
+ log res
131
+ end
132
+
133
+ desc 'pay', 'generate payment url'
134
+ option :members, type: :array, required: true, desc: 'Reveivers, maybe multisig'
135
+ option :threshold, type: :numeric, required: false, default: 1, desc: 'Threshold of multisig'
136
+ option :asset, type: :string, required: true, desc: 'Asset ID'
137
+ option :amount, type: :numeric, required: true, desc: 'Amount'
138
+ option :trace, type: :string, required: false, desc: 'Trace ID'
139
+ option :memo, type: :string, required: false, desc: 'memo'
140
+ def pay
141
+ url = api_instance.safe_pay_url(
142
+ members: options[:members],
143
+ threshold: options[:threshold],
144
+ asset_id: options[:asset],
145
+ amount: options[:amount],
146
+ trace_id: options[:trace],
147
+ memo: options[:memo]
148
+ )
149
+
150
+ log UI.fmt "{{v}} #{url}"
151
+ end
152
+
153
+ desc 'safetransfer USER_ID', 'transfer asset to USER_ID with SAFE network'
154
+ option :asset, type: :string, required: true, desc: 'Asset ID'
155
+ option :amount, type: :numeric, required: true, desc: 'Amount'
156
+ option :trace, type: :string, required: false, desc: 'Trace ID'
157
+ option :memo, type: :string, required: false, desc: 'memo'
158
+ option :keystore, type: :string, aliases: '-k', required: true, desc: 'keystore or keystore.json file path'
159
+ def safetransfer(user_id)
160
+ amount = options[:amount].to_d
161
+ asset = options[:asset]
162
+ memo = options[:memo] || ''
163
+
164
+ # step 1: select inputs
165
+ outputs = api_instance.safe_outputs(state: 'unspent', asset_id: asset, limit: 500)['data'].sort_by { |o| o['amount'].to_d }
166
+ balance = outputs.sum(&->(output) { output['amount'].to_d })
167
+
168
+ utxos = []
169
+ outputs.each do |output|
170
+ break if utxos.sum { |o| o['amount'].to_d } >= amount
171
+
172
+ utxos.shift if utxos.size >= 255
173
+ utxos << output
174
+ end
175
+
176
+ log UI.fmt "Step 1/7: {{v}} Found #{outputs.count} unspent outputs, balance: #{balance}, selected #{utxos.count} outputs"
177
+
178
+ # step 2: build transaction
179
+ tx = api_instance.build_safe_transaction(
180
+ utxos:,
181
+ receivers: [
182
+ members: [user_id],
183
+ threshold: 1,
184
+ amount:
185
+ ],
186
+ extra: memo
187
+ )
188
+ raw = MixinBot::Utils.encode_raw_transaction tx
189
+ log UI.fmt "Step 2/5: {{v}} Built raw: #{raw}"
190
+
191
+ # step 3: verify transaction
192
+ request_id = SecureRandom.uuid
193
+ request = api_instance.create_safe_transaction_request(request_id, raw)['data']
194
+ log UI.fmt "Step 3/5: {{v}} Verified transaction, request_id: #{request[0]['request_id']}"
195
+
196
+ # step 4: sign transaction
197
+ signed_raw = api_instance.sign_safe_transaction(
198
+ raw:,
199
+ utxos:,
200
+ request: request[0]
201
+ )
202
+ log UI.fmt "Step 4/5: {{v}} Signed transaction: #{signed_raw}"
203
+
204
+ # step 5: submit transaction
205
+ r = api_instance.send_safe_transaction(
206
+ request_id,
207
+ signed_raw
208
+ )
209
+ log UI.fmt "Step 5/5: {{v}} Submit transaction, hash: #{r['data'].first['transaction_hash']}"
210
+ rescue StandardError => e
211
+ log UI.fmt "{{x}} #{e.inspect}"
212
+ end
70
213
  end
71
214
  end
@@ -11,17 +11,17 @@ module MixinBot
11
11
 
12
12
  desc 'unique UUIDS', 'generate unique UUID for two or more UUIDs'
13
13
  def unique(*uuids)
14
- log MixinBot::Utils.unique_uuid(*uuids)
14
+ log MixinBot.utils.unique_uuid(*uuids)
15
15
  end
16
16
 
17
17
  desc 'generatetrace HASH', 'generate trace ID from Tx hash'
18
18
  def generatetrace(hash)
19
- log MixinBot::Utils.generate_trace_from_hash(hash)
19
+ log MixinBot.utils.generate_trace_from_hash(hash)
20
20
  end
21
21
 
22
22
  desc 'decodetx TRANSACTION', 'decode raw transaction'
23
23
  def decodetx(transaction)
24
- log MixinBot::Utils.decode_raw_transaction(transaction)
24
+ log MixinBot.utils.decode_raw_transaction(transaction)
25
25
  end
26
26
 
27
27
  desc 'nftmemo', 'memo for mint NFT'
@@ -29,7 +29,17 @@ module MixinBot
29
29
  option :token, type: :numeric, required: true, aliases: '-t', desc: 'Token ID, Integer'
30
30
  option :hash, type: :string, required: true, aliases: '-h', desc: 'Hash of NFT metadata, 256-bit string'
31
31
  def nftmemo
32
- log MixinBot::Utils.nft(options[:collection], options[:token], options[:hash])
32
+ log MixinBot.utils.nft(options[:collection], options[:token], options[:hash])
33
+ end
34
+
35
+ desc 'rsa', 'generate RSA key'
36
+ def rsa
37
+ log MixinBot.utils.generate_rsa_key
38
+ end
39
+
40
+ desc 'ed25519', 'generate Ed25519 key'
41
+ def ed25519
42
+ log MixinBot.utils.generate_ed25519_key
33
43
  end
34
44
  end
35
45
  end
data/lib/mixin_bot/cli.rb CHANGED
@@ -5,9 +5,9 @@ require 'cli/ui'
5
5
  require 'thor'
6
6
  require 'yaml'
7
7
  require 'json'
8
- require_relative './cli/api'
9
- require_relative './cli/node'
10
- require_relative './cli/utils'
8
+ require_relative 'cli/api'
9
+ require_relative 'cli/node'
10
+ require_relative 'cli/utils'
11
11
 
12
12
  module MixinBot
13
13
  class CLI < Thor
@@ -21,7 +21,10 @@ module MixinBot
21
21
 
22
22
  def initialize(*args)
23
23
  super
24
- return if options[:keystore].blank?
24
+ if options[:keystore].blank?
25
+ @api_instance = MixinBot::API.new
26
+ return
27
+ end
25
28
 
26
29
  keystore =
27
30
  if File.file? options[:keystore]
@@ -33,7 +36,7 @@ module MixinBot
33
36
  @keystore =
34
37
  begin
35
38
  JSON.parse keystore
36
- rescue JSON::ParserError => e
39
+ rescue JSON::ParserError
37
40
  log UI.fmt(
38
41
  format(
39
42
  '{{x}} falied to parse keystore.json: %<keystore>s',
@@ -44,17 +47,17 @@ module MixinBot
44
47
 
45
48
  return unless @keystore
46
49
 
47
- MixinBot.api_host = options[:apihost]
50
+ MixinBot.config.api_host = options[:apihost]
48
51
  @api_instance ||=
49
52
  begin
50
53
  MixinBot::API.new(
51
- client_id: @keystore['client_id'],
54
+ app_id: @keystore['app_id'] || @keystore['client_id'],
52
55
  session_id: @keystore['session_id'],
53
- pin_token: @keystore['pin_token'],
54
- private_key: @keystore['private_key']
56
+ server_public_key: @keystore['server_public_key'] || @keystore['pin_token'],
57
+ session_private_key: @keystore['session_private_key'] || @keystore['private_key']
55
58
  )
56
59
  rescue StandardError => e
57
- log UI.fmt '{{x}}: Failed to initialize api, maybe your keystore is incorrect.'
60
+ log UI.fmt '{{x}}: Failed to initialize api, maybe your keystore is incorrect: %<error>s', error: e.message
58
61
  end
59
62
  end
60
63