mixin_bot 1.0.0 → 1.1.0

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: 2ebb5e10a678c90007560b0f84676d0545ea510de1cefc5534091e0b1338c13b
4
- data.tar.gz: afe4ffc00de92429959bc310a6082112f3dc54d8c48e687165a08e0499a3b1a5
3
+ metadata.gz: 4257bfdffc20e27ffab5ce9da23080be113a552623f5022775f3cc8a6cc6db0c
4
+ data.tar.gz: 7f29a034845b45715e33b3b51e28be996408fcff145538025a243fb74d42b482
5
5
  SHA512:
6
- metadata.gz: 334913613e7a88d94e3783fbf028545ecfa0cecdb0a46c7189a63563be17830d33a1de098714e7c38da97094e041f16805cb5782b1101587629dde8d91d4abe6
7
- data.tar.gz: b2ae3479345b421c7e96983c32c0e85c42a028022f74428c90467407eeea93f323b52126d5ab305ee317ae44db69a8e284ec024fdd738fbe095c6a7cbe11e1f4
6
+ metadata.gz: 18e9d94005f235f827ce4e7598a2b2ddf13f48b296d9af46e4d6b2550e795c30f805c40b815352c159f7f2aa7b35c0a4e93ea0787889175c373e931720b5dc17
7
+ data.tar.gz: 56e0c4651199912fd4ed4bef7eb96cc22de1cd30842b7d8e767811ece926e880984a0f2734db19d4f1c48464c037e3b3d9c22b61be204c8a83ffd0f926203e37
@@ -52,8 +52,8 @@ module MixinBot
52
52
  @_scope = scope.join(' ')
53
53
  EM.run do
54
54
  start_blaze_connect do
55
- def on_open(ws, _event)
56
- ws.send write_ws_message(
55
+ def on_open(websocket, _event) # rubocop:disable Lint/NestedMethodDefinition
56
+ websocket.send write_ws_message(
57
57
  action: 'REFRESH_OAUTH_CODE',
58
58
  params: {
59
59
  client_id: @_app_id,
@@ -64,13 +64,13 @@ module MixinBot
64
64
  )
65
65
  end
66
66
 
67
- def on_message(ws, event)
67
+ def on_message(websocket, event) # rubocop:disable Lint/NestedMethodDefinition
68
68
  raw = JSON.parse ws_message(event.data)
69
69
  @_data = raw
70
- ws.close
70
+ websocket.close
71
71
  end
72
72
 
73
- def on_close(_ws, _event)
73
+ def on_close(_websocket, _event) # rubocop:disable Lint/NestedMethodDefinition
74
74
  EM.stop_event_loop
75
75
  end
76
76
  end
@@ -110,7 +110,7 @@ module MixinBot
110
110
  client.post path, *payload
111
111
  end
112
112
 
113
- def encrypt_message(data, sessions = [], sk: nil, pk: nil)
113
+ def encrypt_message(data, sessions = [], sk: nil, pk: nil) # rubocop:disable Naming/MethodParameterName
114
114
  raise ArgumentError, 'Wrong sessions format!' unless sessions.all?(&->(s) { s.key?('session_id') && s.key?('public_key') })
115
115
 
116
116
  sk ||= config.session_private_key[0...32]
@@ -153,7 +153,7 @@ module MixinBot
153
153
  Base64.urlsafe_encode64 bytes.pack('C*'), padding: false
154
154
  end
155
155
 
156
- def decrypt_message(data, sk: nil, si: nil)
156
+ def decrypt_message(data, sk: nil, si: nil) # rubocop:disable Naming/MethodParameterName
157
157
  bytes = Base64.urlsafe_decode64(data).bytes
158
158
 
159
159
  si ||= config.session_id
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MixinBot
4
+ class API
5
+ module Inscription
6
+ def collection(hash)
7
+ path = "/safe/inscriptions/collections/#{hash}"
8
+
9
+ client.get path
10
+ end
11
+
12
+ def collectible(hash)
13
+ path = "/safe/inscriptions/items/#{hash}"
14
+
15
+ client.get path
16
+ end
17
+
18
+ def collectibles(members: [], access_token: nil)
19
+ unspent_outputs = safe_outputs(state: :unspent, members:, access_token:)['data']
20
+ unspent_outputs.select { |output| output['inscription_hash'].present? }
21
+ end
22
+
23
+ def create_collectible_transfer(utxo, **kwargs)
24
+ # verify collectible
25
+ utxo = utxo.with_indifferent_access
26
+ raise MixinBot::ArgumentError, 'not a valid collectible' unless utxo['inscription_hash'].present?
27
+
28
+ # verify members
29
+ members = [kwargs[:members]].flatten.compact
30
+ raise ArgumentError, 'members required' if members.blank?
31
+
32
+ threshold = kwargs[:threshold] || members.length
33
+ request_id = kwargs[:request_id] || kwargs[:trace_id] || SecureRandom.uuid
34
+
35
+ memo = kwargs[:memo] || ''
36
+
37
+ # build transaction
38
+ tx = build_safe_transaction(
39
+ utxos: [utxo],
40
+ receivers: [{
41
+ members:,
42
+ threshold:,
43
+ amount: utxo['amount']
44
+ }],
45
+ extra: memo
46
+ )
47
+
48
+ # encode transaction
49
+ raw = MixinBot.utils.encode_raw_transaction tx
50
+
51
+ # verify transaction
52
+ request = create_safe_transaction_request(request_id, raw)['data']
53
+
54
+ # sign transaction
55
+ spend_key = MixinBot.utils.decode_key(kwargs[:spend_key]) || config.spend_key
56
+ signed_raw = MixinBot.api.sign_safe_transaction(
57
+ raw:,
58
+ utxos: [utxo],
59
+ request: request[0],
60
+ spend_key:
61
+ )
62
+
63
+ # submit transaction
64
+ send_safe_transaction(
65
+ request_id,
66
+ signed_raw
67
+ )
68
+ end
69
+ end
70
+ end
71
+ end
@@ -2,20 +2,20 @@
2
2
 
3
3
  module MixinBot
4
4
  class API
5
- module Collectible
5
+ module LegacyCollectible
6
6
  NFT_ASSET_MIXIN_ID = '1700941284a95f31b25ec8c546008f208f88eee4419ccdcdbe6e3195e60128ca'
7
7
 
8
- def collectible(id, access_token: nil)
8
+ def legacy_collectible(id, access_token: nil)
9
9
  path = "/collectibles/tokens/#{id}"
10
10
  client.get path, access_token:
11
11
  end
12
12
 
13
- def collection(id, access_token: nil)
13
+ def legacy_collection(id, access_token: nil)
14
14
  path = "/collectibles/collections/#{id}"
15
15
  client.get path, access_token:
16
16
  end
17
17
 
18
- def collectibles(**kwargs)
18
+ def legacy_collectibles(**kwargs)
19
19
  limit = kwargs[:limit] || 100
20
20
  offset = kwargs[:offset] || ''
21
21
  state = kwargs[:state] || ''
@@ -40,7 +40,7 @@ module MixinBot
40
40
  }
41
41
  end
42
42
 
43
- client.post path, **payload, access_token:
43
+ client.post path, **payload
44
44
  end
45
45
 
46
46
  def unlock_multisig_request(request_id, pin = nil)
@@ -3,7 +3,7 @@
3
3
  module MixinBot
4
4
  class API
5
5
  module LegacyOutput
6
- def outputs(**kwargs)
6
+ def legacy_outputs(**kwargs)
7
7
  limit = kwargs[:limit] || 100
8
8
  offset = kwargs[:offset] || ''
9
9
  state = kwargs[:state] || ''
@@ -23,8 +23,8 @@ module MixinBot
23
23
 
24
24
  client.get path, **params, access_token:
25
25
  end
26
- alias multisigs outputs
27
- alias multisig_outputs outputs
26
+ alias multisigs legacy_outputs
27
+ alias multisig_outputs legacy_outputs
28
28
 
29
29
  def create_output(receivers:, index:, hint: nil, access_token: nil)
30
30
  path = '/outputs'
@@ -6,11 +6,11 @@ module MixinBot
6
6
  def create_safe_multisig_request(request_id, raw, access_token: nil)
7
7
  path = '/safe/multisigs'
8
8
  payload = [{
9
- request_id: request_id,
10
- raw: raw
9
+ request_id:,
10
+ raw:
11
11
  }]
12
12
 
13
- client.post path, *payload
13
+ client.post path, *payload, access_token:
14
14
  end
15
15
 
16
16
  def sign_safe_multisig_request(request_id, raw, access_token: nil)
@@ -20,13 +20,13 @@ module MixinBot
20
20
  raw:
21
21
  }
22
22
 
23
- client.post path, **payload
23
+ client.post path, **payload, access_token:
24
24
  end
25
25
 
26
26
  def unlock_safe_multisig_request(request_id, access_token: nil)
27
27
  path = format('/safe/multisigs/%<request_id>s/unlock', request_id:)
28
28
 
29
- client.post path, access_token: access_token
29
+ client.post path, access_token:
30
30
  end
31
31
 
32
32
  def safe_multisig_request(request_id, access_token: nil)
@@ -18,7 +18,7 @@ module MixinBot
18
18
  state = kwargs[:state] || ''
19
19
  access_token = kwargs[:access_token]
20
20
  order = kwargs[:order] || 'ASC'
21
- members = kwargs[:members] || [config.app_id]
21
+ members = kwargs[:members].presence || [config.app_id]
22
22
  threshold = kwargs[:threshold] || members.length
23
23
 
24
24
  members_hash = SHA3::Digest::SHA256.hexdigest(members&.sort&.join)
@@ -36,11 +36,13 @@ module MixinBot
36
36
 
37
37
  client.get path, **params, access_token:
38
38
  end
39
+ alias outputs safe_outputs
39
40
 
40
41
  def safe_output(id, access_token: nil)
41
42
  path = format('/safe/outputs/%<id>s', id:)
42
43
  client.get path, access_token:
43
44
  end
45
+ alias output safe_output
44
46
  end
45
47
  end
46
48
  end
@@ -49,7 +49,7 @@ module MixinBot
49
49
  ed25519_key = JOSE::JWA::Ed25519.keypair
50
50
 
51
51
  private_key = ed25519_key[1].unpack1('H*')
52
- public_key = (ed25519_key[0].bytes + MixinBot::Utils.encode_uint_64(counter + 1)).pack('c*').unpack1('H*')
52
+ public_key = (ed25519_key[0].bytes + MixinBot::Utils.encode_uint64(counter + 1)).pack('c*').unpack1('H*')
53
53
 
54
54
  {
55
55
  private_key:,
@@ -19,7 +19,7 @@ module MixinBot
19
19
  end
20
20
 
21
21
  def get_transaction(hash, access_token: nil)
22
- rpc_proxy('gettransaction', [hash], access_token: nil)
22
+ rpc_proxy('gettransaction', [hash], access_token:)
23
23
  end
24
24
 
25
25
  def get_utxo(hash, index = 0, access_token: nil)
@@ -30,16 +30,16 @@ module MixinBot
30
30
  rpc_proxy 'getsnapshot', [hash], access_token:
31
31
  end
32
32
 
33
- def list_snapshots(offset = 0, count = 10, sig = false, tx = false, access_token: nil)
34
- rpc_proxy 'listsnapshots', [offset, count, sig, tx], access_token:
33
+ def list_snapshots(offset = 0, count = 10, sig: false, txn: false, access_token: nil)
34
+ rpc_proxy 'listsnapshots', [offset, count, sig, txn], access_token:
35
35
  end
36
36
 
37
37
  def list_mint_works(offset = 0, access_token: nil)
38
38
  rpc_proxy 'listmintworks', [offset], access_token:
39
39
  end
40
40
 
41
- def list_mint_distributions(offset = 0, count = 10, tx = false, access_token: nil)
42
- rpc_proxy 'listmintdistributions', [offset, count, tx], access_token:
41
+ def list_mint_distributions(offset = 0, count = 10, txn: false, access_token: nil)
42
+ rpc_proxy 'listmintdistributions', [offset, count, txn], access_token:
43
43
  end
44
44
  end
45
45
  end
@@ -6,8 +6,10 @@ module MixinBot
6
6
  SAFE_TX_VERSION = 0x05
7
7
  OUTPUT_TYPE_SCRIPT = 0x00
8
8
  OUTPUT_TYPE_WITHDRAW_SUBMIT = 0xa1
9
+ XIN_ASSET_ID = 'c94ac88f-4671-3976-b60a-09064f1811e8'
10
+ EXTRA_SIZE_STORAGE_CAPACITY = 1024 * 1024 * 4
11
+ EXTRA_STORAGE_PRICE_STEP = 0.0001
9
12
 
10
- # ghost keys
11
13
  def create_safe_keys(*payload, access_token: nil)
12
14
  raise ArgumentError, 'payload should be an array' unless payload.is_a? Array
13
15
  raise ArgumentError, 'payload should not be empty' unless payload.size.positive?
@@ -21,10 +23,58 @@ module MixinBot
21
23
 
22
24
  path = '/safe/keys'
23
25
 
24
- client.post path, *payload
26
+ client.post path, *payload, access_token:
25
27
  end
26
28
  alias create_ghost_keys create_safe_keys
27
29
 
30
+ def generate_safe_keys(recipients)
31
+ raise ArgumentError, 'recipients should be an array' unless recipients.is_a? Array
32
+
33
+ ghost_keys = []
34
+ uuid_recipients = []
35
+
36
+ recipients.each_with_index do |recipient, index|
37
+ next if recipient[:mix_address].blank?
38
+
39
+ if recipient[:members].all?(&->(m) { m.start_with? MixinBot::Utils::Address::MAIN_ADDRESS_PREFIX })
40
+ key = JOSE::JWA::Ed25519.keypair
41
+ gk = {
42
+ mask: key[0].unpack1('H*'),
43
+ keys: []
44
+ }
45
+ recipient[:members].each do |member|
46
+ payload = MixinBot.utils.parse_main_address member
47
+ spend_key = payload[0...32]
48
+ view_key = payload[-32..]
49
+
50
+ ghost_public_key = MixinBot.utils.derive_ghost_public_key(key[1], view_key, spend_key, index)
51
+
52
+ gk[:keys] << ghost_public_key.unpack1('H*')
53
+ end
54
+
55
+ ghost_keys[index] = gk.with_indifferent_access
56
+
57
+ elsif recipient[:members].none?(&->(m) { m.start_with? MixinBot::Utils::Address::MAIN_ADDRESS_PREFIX })
58
+ uuid_recipients.push(
59
+ {
60
+ receivers: recipient[:members],
61
+ index:,
62
+ hint: SecureRandom.uuid
63
+ }.with_indifferent_access
64
+ )
65
+ end
66
+ end
67
+
68
+ if uuid_recipients.present?
69
+ keys = create_safe_keys(*uuid_recipients)['data']
70
+ keys.each_with_index do |key, index|
71
+ ghost_keys[uuid_recipients[index][:index]] = key
72
+ end
73
+ end
74
+
75
+ ghost_keys
76
+ end
77
+
28
78
  # kwargs:
29
79
  # {
30
80
  # utxos: [ utxo ],
@@ -39,6 +89,8 @@ module MixinBot
39
89
  SAFE_RAW_TRANSACTION_ARGUMENTS = %i[utxos receivers].freeze
40
90
  def build_safe_transaction(**kwargs)
41
91
  raise ArgumentError, "#{SAFE_RAW_TRANSACTION_ARGUMENTS.join(', ')} are needed for build safe transaction" unless SAFE_RAW_TRANSACTION_ARGUMENTS.all? { |param| kwargs.keys.include? param }
92
+ raise ArgumentError, 'receivers should be an array' unless kwargs[:receivers].is_a? Array
93
+ raise ArgumentError, 'utxos should be an array' unless kwargs[:utxos].is_a? Array
42
94
 
43
95
  utxos = kwargs[:utxos].map(&:with_indifferent_access)
44
96
  receivers = kwargs[:receivers].map(&:with_indifferent_access)
@@ -63,12 +115,12 @@ module MixinBot
63
115
  inputs_sum = utxos.sum(&->(utxo) { utxo['amount'].to_d })
64
116
  outputs_sum = recipients.sum(&->(recipient) { recipient['amount'].to_d })
65
117
  change = inputs_sum - outputs_sum
66
- raise InsufficientBalanceError, "inputs sum: #{inputs_sum}" if change.negative?
118
+ raise InsufficientBalanceError, "inputs sum #{inputs_sum} < outputs sum #{outputs_sum}" if change.negative?
67
119
 
68
120
  if change.positive?
69
121
  recipients << MixinBot.utils.build_safe_recipient(
70
- members: utxos[0]['receivers'],
71
- threshold: utxos[0]['receivers_threshold'],
122
+ members: utxos.first['receivers'],
123
+ threshold: utxos.first['receivers_threshold'],
72
124
  amount: change
73
125
  ).with_indifferent_access
74
126
  end
@@ -85,14 +137,7 @@ module MixinBot
85
137
  }
86
138
  end
87
139
 
88
- ghost_payload = recipients.map.with_index do |r, index|
89
- {
90
- receivers: r[:members],
91
- index:,
92
- hint: SecureRandom.uuid
93
- }
94
- end
95
- ghosts = create_safe_keys(*ghost_payload)['data']
140
+ ghosts = generate_safe_keys(recipients)
96
141
 
97
142
  outputs = []
98
143
  recipients.each_with_index do |recipient, index|
@@ -121,7 +166,8 @@ module MixinBot
121
166
  asset:,
122
167
  inputs:,
123
168
  outputs:,
124
- extra: kwargs[:extra] || ''
169
+ extra: kwargs[:extra] || '',
170
+ references: kwargs[:references] || []
125
171
  }
126
172
  end
127
173
 
@@ -164,7 +210,7 @@ module MixinBot
164
210
 
165
211
  msg = [raw].pack('H*')
166
212
 
167
- y_point = JOSE::JWA::FieldElement.new(
213
+ y_scalar = JOSE::JWA::FieldElement.new(
168
214
  JOSE::JWA::X25519.clamp_scalar(spend_key[...32]).x,
169
215
  JOSE::JWA::Edwards25519Point::L
170
216
  )
@@ -175,16 +221,12 @@ module MixinBot
175
221
  raise ArgumentError, 'utxo not match' unless input['hash'] == utxo['transaction_hash'] && input['index'] == utxo['output_index']
176
222
 
177
223
  view = [request['views'][index]].pack('H*')
178
- x_point = JOSE::JWA::FieldElement.new(
179
- # https://github.com/potatosalad/ruby-jose/blob/e1be589b889f1e59ac233a5d19a3fa13f1e4b8a0/lib/jose/jwa/x25519.rb#L122C14-L122C48
180
- OpenSSL::BN.new(view.reverse, 2),
181
- JOSE::JWA::Edwards25519Point::L
182
- )
224
+ x_scalar = MixinBot.utils.scalar_from_bytes(view)
183
225
 
184
- t_point = x_point + y_point
185
- key = t_point.to_bytes(JOSE::JWA::Edwards25519Point::B)
226
+ t_scalar = x_scalar + y_scalar
227
+ key = t_scalar.to_bytes(JOSE::JWA::Edwards25519Point::B)
186
228
 
187
- pub = MixinBot.utils.generate_public_key key
229
+ pub = MixinBot.utils.shared_public_key key
188
230
  key_index = utxo['keys'].index pub.unpack1('H*')
189
231
  raise ArgumentError, 'cannot find valid key' unless key_index.is_a? Integer
190
232
 
@@ -197,6 +239,75 @@ module MixinBot
197
239
 
198
240
  MixinBot.utils.encode_raw_transaction tx
199
241
  end
242
+
243
+ def build_object_transaction(extra, **)
244
+ extra = extra.to_s
245
+ raise ArgumentError, 'Extra too large' if extra.bytesize > EXTRA_SIZE_STORAGE_CAPACITY
246
+
247
+ # calculate fee base on extra length
248
+ amount = EXTRA_STORAGE_PRICE_STEP * ((extra.bytesize / 1024) + 1)
249
+
250
+ # burning address
251
+ receivers = [
252
+ {
253
+ members: [MixinBot.utils.burning_address],
254
+ threshold: 64,
255
+ amount:
256
+ }
257
+ ]
258
+
259
+ # find XIN utxos
260
+ utxos = build_utxos(asset_id: XIN_ASSET_ID, amount:)
261
+
262
+ # build transaction
263
+ build_safe_transaction utxos:, receivers:, extra:, **
264
+ end
265
+
266
+ INSCRIBE_TRANSACTION_ARGUMENTS = %i[content collection_hash].freeze
267
+ def build_inscribe_transaction(**kwargs)
268
+ raise ArgumentError, "#{INSCRIBE_TRANSACTION_ARGUMENTS.join(', ')} are needed for inscribe transaction" unless INSCRIBE_TRANSACTION_ARGUMENTS.all? { |param| kwargs.keys.include? param }
269
+
270
+ receivers = kwargs[:receivers].presence || [config.app_id]
271
+ receivers_threshold = kwargs[:receivers_threshold] || receivers.length
272
+ recipient = MixinBot.utils.build_mix_address(receivers, receivers_threshold)
273
+
274
+ content = kwargs[:content]
275
+ collection_hash = kwargs[:collection_hash]
276
+
277
+ data = {
278
+ operation: 'inscribe',
279
+ recipient:,
280
+ content:
281
+ }
282
+
283
+ MixinBot.api.build_object_transaction data.to_json, references: [collection_hash]
284
+ end
285
+
286
+ OCCUPY_INSCRIPTION_TRANSACTION_ARGUMENTS = %i[amount inscription_hash utxos].freeze
287
+ def build_occupy_transaction(**kwargs)
288
+ raise ArgumentError, "#{OCCUPY_INSCRIPTION_TRANSACTION_ARGUMENTS.join(', ')} are needed for occupy NFT transaction" unless OCCUPY_INSCRIPTION_TRANSACTION_ARGUMENTS.all? { |param| kwargs.keys.include? param }
289
+
290
+ members = kwargs[:members].presence || [config.app_id]
291
+ threshold = kwargs[:threshold] || members.length
292
+ amount = kwargs[:amount]
293
+ inscription_hash = kwargs[:inscription_hash]
294
+
295
+ receivers = [
296
+ {
297
+ members:,
298
+ threshold:,
299
+ amount:
300
+ }
301
+ ]
302
+
303
+ extra = {
304
+ operation: 'occupy',
305
+ recipient:,
306
+ content:
307
+ }.to_json
308
+
309
+ MixinBot.api.build_safe_transaction(utxos:, receivers:, extra:, references: [inscription_hash])
310
+ end
200
311
  end
201
312
  end
202
313
  end
@@ -29,15 +29,7 @@ module MixinBot
29
29
  memo = kwargs[:memo] || ''
30
30
 
31
31
  # step 1: select inputs
32
- outputs = safe_outputs(state: 'unspent', asset: asset_id, limit: 500)['data'].sort_by { |o| o['amount'].to_d }
33
-
34
- utxos = []
35
- outputs.each do |output|
36
- break if utxos.sum { |o| o['amount'].to_d } >= amount
37
-
38
- utxos.shift if utxos.size >= 256
39
- utxos << output
40
- end
32
+ utxos = build_utxos(asset_id:, amount:)
41
33
 
42
34
  # step 2: build transaction
43
35
  tx = build_safe_transaction(
@@ -56,7 +48,7 @@ module MixinBot
56
48
 
57
49
  # step 4: sign transaction
58
50
  spend_key = MixinBot.utils.decode_key(kwargs[:spend_key]) || config.spend_key
59
- signed_raw = sign_safe_transaction(
51
+ signed_raw = MixinBot.api.sign_safe_transaction(
60
52
  raw:,
61
53
  utxos:,
62
54
  request: request[0],
@@ -69,6 +61,20 @@ module MixinBot
69
61
  signed_raw
70
62
  )
71
63
  end
64
+
65
+ def build_utxos(asset_id:, amount:)
66
+ outputs = safe_outputs(state: 'unspent', asset: asset_id, limit: 500)['data'].sort_by { |o| o['amount'].to_d }
67
+
68
+ utxos = []
69
+ outputs.each do |output|
70
+ break if utxos.sum { |o| o['amount'].to_d } >= amount
71
+
72
+ utxos.shift if utxos.size >= 256
73
+ utxos << output
74
+ end
75
+
76
+ utxos
77
+ end
72
78
  end
73
79
  end
74
80
  end
@@ -86,19 +86,24 @@ module MixinBot
86
86
  client.post path, **payload
87
87
  end
88
88
 
89
- def migrate_to_safe(spend_key:, old_pin: nil)
89
+ def migrate_to_safe(spend_key:, pin: nil)
90
90
  profile = me['data']
91
91
  return true if profile['has_safe']
92
92
 
93
93
  spend_keypair = JOSE::JWA::Ed25519.keypair spend_key
94
94
  spend_key = spend_keypair[1].unpack1('H*')
95
95
 
96
- update_pin pin: MixinBot.utils.tip_public_key(spend_keypair[0], counter: profile['tip_counter']) if profile['tip_key_base64'].blank?
96
+ if profile['tip_key_base64'].blank?
97
+ new_pin = MixinBot.utils.tip_public_key(spend_keypair[0], counter: profile['tip_counter'])
98
+ update_pin(pin: new_pin, old_pin: pin)
99
+
100
+ pin = new_pin
101
+ end
97
102
 
98
103
  # wait for tip pin update in server
99
104
  sleep 1
100
105
 
101
- safe_register spend_key
106
+ safe_register pin, spend_key
102
107
 
103
108
  {
104
109
  spend_key:
data/lib/mixin_bot/api.rb CHANGED
@@ -8,9 +8,10 @@ require_relative 'api/asset'
8
8
  require_relative 'api/attachment'
9
9
  require_relative 'api/auth'
10
10
  require_relative 'api/blaze'
11
- require_relative 'api/collectible'
12
11
  require_relative 'api/conversation'
13
12
  require_relative 'api/encrypted_message'
13
+ require_relative 'api/inscription'
14
+ require_relative 'api/legacy_collectible'
14
15
  require_relative 'api/legacy_multisig'
15
16
  require_relative 'api/legacy_output'
16
17
  require_relative 'api/legacy_payment'
@@ -67,8 +68,8 @@ module MixinBot
67
68
  )
68
69
  end
69
70
 
70
- def encode_raw_transaction(tx)
71
- utils.encode_raw_transaction tx
71
+ def encode_raw_transaction(txn)
72
+ utils.encode_raw_transaction txn
72
73
  end
73
74
 
74
75
  def decode_raw_transaction(raw)
@@ -107,9 +108,10 @@ module MixinBot
107
108
  include MixinBot::API::Attachment
108
109
  include MixinBot::API::Auth
109
110
  include MixinBot::API::Blaze
110
- include MixinBot::API::Collectible
111
111
  include MixinBot::API::Conversation
112
112
  include MixinBot::API::EncryptedMessage
113
+ include MixinBot::API::Inscription
114
+ include MixinBot::API::LegacyCollectible
113
115
  include MixinBot::API::LegacyMultisig
114
116
  include MixinBot::API::LegacyOutput
115
117
  include MixinBot::API::LegacyPayment
@@ -78,7 +78,7 @@ module MixinBot
78
78
  return result
79
79
  end
80
80
 
81
- errmsg = "#{verb.upcase}|#{path}|#{body}, errcode: #{result['error']['code']}, errmsg: #{result['error']['description']}, request_id: #{response&.[]('X-Request-Id')}, server_time: #{response&.[]('X-Server-Time')}'"
81
+ errmsg = "#{verb.upcase} | #{path} | #{body}, errcode: #{result['error']['code']}, errmsg: #{result['error']['description']}, request_id: #{response&.[]('X-Request-Id')}, server_time: #{response&.[]('X-Server-Time')}'"
82
82
 
83
83
  case result['error']['code']
84
84
  when 401, 20121
@@ -87,8 +87,6 @@ module MixinBot
87
87
  raise ForbiddenError, errmsg
88
88
  when 404
89
89
  raise NotFoundError, errmsg
90
- when 400, 10006, 20133, 500, 7000, 7001
91
- raise ResponseError, errmsg
92
90
  when 20117
93
91
  raise InsufficientBalanceError, errmsg
94
92
  when 20118, 20119
data/lib/mixin_bot/nfo.rb CHANGED
@@ -74,7 +74,7 @@ module MixinBot
74
74
  bytes += [0]
75
75
  else
76
76
  bytes += [1]
77
- bytes += MixinBot.utils.encode_uint_64 mask
77
+ bytes += MixinBot.utils.encode_uint64 mask
78
78
  bytes += MixinBot::UUID.new(hex: chain).packed.bytes
79
79
 
80
80
  class_bytes = [nm_class].pack('H*').bytes