mixin_bot 0.12.0 → 1.0.0
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/lib/mixin_bot/api/address.rb +21 -0
- data/lib/mixin_bot/api/app.rb +5 -11
- data/lib/mixin_bot/api/asset.rb +9 -16
- data/lib/mixin_bot/api/attachment.rb +27 -22
- data/lib/mixin_bot/api/auth.rb +31 -53
- data/lib/mixin_bot/api/blaze.rb +4 -3
- data/lib/mixin_bot/api/collectible.rb +60 -58
- data/lib/mixin_bot/api/conversation.rb +29 -49
- data/lib/mixin_bot/api/encrypted_message.rb +17 -17
- data/lib/mixin_bot/api/legacy_multisig.rb +87 -0
- data/lib/mixin_bot/api/legacy_output.rb +50 -0
- data/lib/mixin_bot/api/legacy_payment.rb +31 -0
- data/lib/mixin_bot/api/legacy_snapshot.rb +39 -0
- data/lib/mixin_bot/api/legacy_transaction.rb +173 -0
- data/lib/mixin_bot/api/legacy_transfer.rb +42 -0
- data/lib/mixin_bot/api/me.rb +13 -17
- data/lib/mixin_bot/api/message.rb +13 -10
- data/lib/mixin_bot/api/multisig.rb +16 -221
- data/lib/mixin_bot/api/output.rb +46 -0
- data/lib/mixin_bot/api/payment.rb +9 -20
- data/lib/mixin_bot/api/pin.rb +57 -65
- data/lib/mixin_bot/api/rpc.rb +9 -11
- data/lib/mixin_bot/api/snapshot.rb +15 -29
- data/lib/mixin_bot/api/tip.rb +43 -0
- data/lib/mixin_bot/api/transaction.rb +184 -60
- data/lib/mixin_bot/api/transfer.rb +64 -32
- data/lib/mixin_bot/api/user.rb +83 -53
- data/lib/mixin_bot/api/withdraw.rb +52 -53
- data/lib/mixin_bot/api.rb +78 -45
- data/lib/mixin_bot/cli/api.rb +151 -8
- data/lib/mixin_bot/cli/utils.rb +14 -4
- data/lib/mixin_bot/cli.rb +13 -10
- data/lib/mixin_bot/client.rb +76 -127
- data/lib/mixin_bot/configuration.rb +98 -0
- data/lib/mixin_bot/nfo.rb +174 -0
- data/lib/mixin_bot/transaction.rb +505 -0
- data/lib/mixin_bot/utils/address.rb +108 -0
- data/lib/mixin_bot/utils/crypto.rb +182 -0
- data/lib/mixin_bot/utils/decoder.rb +58 -0
- data/lib/mixin_bot/utils/encoder.rb +63 -0
- data/lib/mixin_bot/utils.rb +8 -109
- data/lib/mixin_bot/uuid.rb +41 -0
- data/lib/mixin_bot/version.rb +1 -1
- data/lib/mixin_bot.rb +39 -14
- data/lib/mvm/bridge.rb +2 -19
- data/lib/mvm/client.rb +11 -33
- data/lib/mvm/nft.rb +4 -4
- data/lib/mvm/registry.rb +9 -9
- data/lib/mvm/scan.rb +3 -5
- data/lib/mvm.rb +5 -6
- metadata +101 -44
- data/lib/mixin_bot/utils/nfo.rb +0 -176
- data/lib/mixin_bot/utils/transaction.rb +0 -478
- 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
|
-
|
7
|
-
def create_withdraw_address(options, access_token: nil)
|
6
|
+
def create_withdraw_address(**kwargs)
|
8
7
|
path = '/addresses'
|
9
|
-
|
8
|
+
pin = kwargs[:pin]
|
10
9
|
payload =
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
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:
|
38
|
-
|
39
|
-
|
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
|
-
|
44
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
66
|
-
amount
|
67
|
-
trace_id
|
68
|
-
memo:
|
69
|
-
pin: encrypt_pin(pin)
|
60
|
+
address_id:,
|
61
|
+
amount:,
|
62
|
+
trace_id:,
|
63
|
+
memo:
|
70
64
|
}
|
71
65
|
|
72
|
-
|
73
|
-
|
74
|
-
|
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 '
|
4
|
-
require_relative '
|
5
|
-
require_relative '
|
6
|
-
require_relative '
|
7
|
-
require_relative '
|
8
|
-
require_relative '
|
9
|
-
require_relative '
|
10
|
-
require_relative '
|
11
|
-
require_relative '
|
12
|
-
require_relative '
|
13
|
-
require_relative '
|
14
|
-
require_relative '
|
15
|
-
require_relative '
|
16
|
-
require_relative '
|
17
|
-
require_relative '
|
18
|
-
require_relative '
|
19
|
-
require_relative '
|
20
|
-
require_relative '
|
21
|
-
require_relative '
|
22
|
-
require_relative '
|
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 :
|
27
|
-
|
28
|
-
def initialize(
|
29
|
-
@
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
51
|
-
|
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
|
-
|
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
|
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
|
data/lib/mixin_bot/cli/api.rb
CHANGED
@@ -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:
|
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: {
|
44
|
+
api_instance.client.post(path, headers: { Authorization: authorization }, json: payload)
|
45
45
|
when :get
|
46
|
-
api_instance.client.get(path, headers: {
|
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 :
|
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(
|
59
|
+
CLI::UI::Spinner.spin('POST /oauth/authorize') do |_spinner|
|
61
60
|
res =
|
62
61
|
api_instance.authorize_code(
|
63
|
-
user_id: options[:
|
62
|
+
user_id: options[:app_id],
|
64
63
|
scope: options[:scope],
|
65
|
-
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
|
data/lib/mixin_bot/cli/utils.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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 '
|
9
|
-
require_relative '
|
10
|
-
require_relative '
|
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
|
-
|
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
|
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
|
-
|
54
|
+
app_id: @keystore['app_id'] || @keystore['client_id'],
|
52
55
|
session_id: @keystore['session_id'],
|
53
|
-
|
54
|
-
|
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
|
|