mixin_bot 3.0.0 → 3.0.2

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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +1 -1
  3. data/API_COVERAGE.md +1 -0
  4. data/CHANGELOG.md +11 -1
  5. data/README.md +75 -1
  6. data/docs/agent/cookbook.md +23 -0
  7. data/lib/generators/mixin_bot/authentication/USAGE +29 -0
  8. data/lib/generators/mixin_bot/authentication/authentication_generator.rb +82 -0
  9. data/lib/generators/mixin_bot/authentication/templates/app/controllers/concerns/authentication.rb.tt +52 -0
  10. data/lib/generators/mixin_bot/authentication/templates/app/controllers/sessions_controller.rb.tt +24 -0
  11. data/lib/generators/mixin_bot/authentication/templates/app/models/current.rb.tt +4 -0
  12. data/lib/generators/mixin_bot/authentication/templates/app/models/session.rb.tt +3 -0
  13. data/lib/generators/mixin_bot/authentication/templates/app/models/user.rb.tt +12 -0
  14. data/lib/generators/mixin_bot/authentication/templates/app/views/sessions/new.html.erb.tt +3 -0
  15. data/lib/generators/mixin_bot/authentication/templates/config/initializers/omniauth.rb.tt +21 -0
  16. data/lib/generators/mixin_bot/blaze/USAGE +19 -0
  17. data/lib/generators/mixin_bot/blaze/blaze_generator.rb +43 -0
  18. data/lib/generators/mixin_bot/blaze/templates/app/mixin/handlers/text_handler.rb +14 -0
  19. data/lib/generators/mixin_bot/blaze/templates/config/initializers/mixin_bot_blaze.rb +23 -0
  20. data/lib/generators/mixin_bot/install/USAGE +24 -0
  21. data/lib/generators/mixin_bot/install/install_generator.rb +50 -0
  22. data/lib/generators/mixin_bot/notifications/USAGE +13 -0
  23. data/lib/generators/mixin_bot/notifications/notifications_generator.rb +49 -0
  24. data/lib/generators/mixin_bot/notifications/templates/app/notifications/payment_received_notification.rb +24 -0
  25. data/lib/generators/mixin_bot/outputs/USAGE +29 -0
  26. data/lib/generators/mixin_bot/outputs/outputs_generator.rb +50 -0
  27. data/lib/generators/mixin_bot/outputs/templates/app/mixin/processors/deposit_processor.rb +21 -0
  28. data/lib/generators/mixin_bot/outputs/templates/app/models/mixin_output.rb +8 -0
  29. data/lib/generators/mixin_bot/outputs/templates/db/migrate/create_mixin_outputs.rb.tt +26 -0
  30. data/lib/generators/mixin_bot/transfers/USAGE +37 -0
  31. data/lib/generators/mixin_bot/transfers/templates/app/jobs/mixin_transfers/perform_job.rb +13 -0
  32. data/lib/generators/mixin_bot/transfers/templates/app/jobs/mixin_transfers/reconcile_job.rb +14 -0
  33. data/lib/generators/mixin_bot/transfers/templates/app/models/mixin_transfer.rb +11 -0
  34. data/lib/generators/mixin_bot/transfers/templates/db/migrate/create_mixin_transfers.rb.tt +23 -0
  35. data/lib/generators/mixin_bot/transfers/transfers_generator.rb +67 -0
  36. data/lib/generators/mixin_bot.rb +10 -0
  37. data/lib/mixin_bot/api/app.rb +20 -0
  38. data/lib/mixin_bot/api/snapshot.rb +5 -0
  39. data/lib/mixin_bot/blaze/reactor.rb +8 -3
  40. data/lib/mixin_bot/blaze/router.rb +333 -0
  41. data/lib/mixin_bot/cache_store_adapter.rb +3 -1
  42. data/lib/mixin_bot/client.rb +2 -1
  43. data/lib/mixin_bot/computer.rb +3 -1
  44. data/lib/mixin_bot/json_decoder.rb +14 -0
  45. data/lib/mixin_bot/notifications/mixin_channel.rb +80 -0
  46. data/lib/mixin_bot/outputs/cursor_model.rb +33 -0
  47. data/lib/mixin_bot/outputs/envelope.rb +160 -0
  48. data/lib/mixin_bot/outputs/memory_stores.rb +97 -0
  49. data/lib/mixin_bot/outputs/poller.rb +178 -0
  50. data/lib/mixin_bot/outputs/processing_job.rb +54 -0
  51. data/lib/mixin_bot/outputs/processors.rb +124 -0
  52. data/lib/mixin_bot/outputs/receipt_model.rb +86 -0
  53. data/lib/mixin_bot/outputs.rb +42 -0
  54. data/lib/mixin_bot/rails/railtie.rb +44 -0
  55. data/lib/mixin_bot/rails/tasks/poller.rake +33 -0
  56. data/lib/mixin_bot/rails.rb +34 -0
  57. data/lib/mixin_bot/registry.rb +79 -0
  58. data/lib/mixin_bot/transfers/model.rb +112 -0
  59. data/lib/mixin_bot/transfers/performer.rb +64 -0
  60. data/lib/mixin_bot/transfers/reconcile.rb +53 -0
  61. data/lib/mixin_bot/transfers.rb +23 -0
  62. data/lib/mixin_bot/version.rb +1 -1
  63. data/lib/mixin_bot.rb +3 -0
  64. data/llms.txt +1 -1
  65. metadata +51 -2
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Opt-in Rails integration layer: generators, railtie, and Rails glue.
4
+ #
5
+ # `require 'mixin_bot'` alone never loads any of this — the gem keeps no
6
+ # runtime dependency on Rails. Host applications opt in explicitly:
7
+ #
8
+ # # Gemfile
9
+ # gem 'mixin_bot'
10
+ # gem 'rails'
11
+ #
12
+ # # config/application.rb (after the bundler groups)
13
+ # require 'mixin_bot/rails'
14
+ #
15
+ # The railtie registers the mixin_bot rake tasks (e.g. `mixin_bot:poller`).
16
+ # Rails discovers the `lib/generators/mixin_bot/*` generators on its own.
17
+
18
+ require 'mixin_bot'
19
+
20
+ begin
21
+ require 'rails'
22
+ rescue LoadError => e
23
+ raise LoadError,
24
+ 'mixin_bot/rails requires the rails gem, which is not a runtime ' \
25
+ "dependency of mixin_bot. Add `gem 'rails'` to your Gemfile, or " \
26
+ "drop `require 'mixin_bot/rails'` if you only need the SDK. " \
27
+ "(#{e.message})"
28
+ end
29
+
30
+ require_relative 'blaze/router'
31
+ require_relative 'outputs'
32
+ require_relative 'transfers'
33
+ require_relative 'rails/railtie'
34
+ require_relative 'notifications/mixin_channel'
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MixinBot
4
+ ##
5
+ # Named registry for running several bots (keystores) inside one process.
6
+ #
7
+ # The default bot stays on the global configuration (+MixinBot.configure+ /
8
+ # +MixinBot.api+). Additional bots register under a name and return a
9
+ # dedicated +MixinBot::API+ whose configuration is frozen after registration:
10
+ #
11
+ # MixinBot.register_bot :shop,
12
+ # app_id: '...',
13
+ # session_id: '...',
14
+ # session_private_key: '...',
15
+ # server_public_key: '...'
16
+ #
17
+ # MixinBot.bot(:shop).me
18
+ #
19
+ # Integration components built on top of the SDK (router, poller, transfers,
20
+ # notifications) accept the bot name and default to the global API client.
21
+ module Registry
22
+ ##
23
+ # Registers a bot under +name+ with {MixinBot::API#initialize} kwargs and
24
+ # freezes the resulting client's configuration.
25
+ #
26
+ # @param name [Symbol, String] registry key
27
+ # @param kwargs [Hash] bot credentials (see {Configuration#initialize});
28
+ # empty kwargs would alias the global configuration and are rejected
29
+ # @return [MixinBot::API] the registered client
30
+ # @raise [MixinBot::ArgumentError] when the name is already registered or
31
+ # no credentials are given
32
+ #
33
+ def register_bot(name, **kwargs)
34
+ raise MixinBot::ArgumentError, 'register_bot requires bot credentials' if kwargs.empty?
35
+ raise MixinBot::ArgumentError, "bot #{name.inspect} is already registered" if bots.key?(name.to_sym)
36
+
37
+ api = MixinBot::API.new(**kwargs)
38
+ api.config.freeze
39
+ bots[name.to_sym] = api
40
+ end
41
+
42
+ ##
43
+ # Returns the API client registered under +name+.
44
+ #
45
+ # MixinBot.bot(:shop).assets
46
+ #
47
+ # @param name [Symbol, String] registry key
48
+ # @return [MixinBot::API]
49
+ # @raise [KeyError] when nothing is registered under that name
50
+ #
51
+ def bot(name)
52
+ bots.fetch(name.to_sym)
53
+ end
54
+
55
+ ##
56
+ # Finds a bot client by its app id: the default API when the app id is
57
+ # the global configuration's, else the registered bot carrying it.
58
+ #
59
+ # @param app_id [String, nil]
60
+ # @return [MixinBot::API, nil] nil when no bot carries that app id
61
+ #
62
+ def bot_by_app_id(app_id)
63
+ return nil if app_id.nil?
64
+ return api if config.app_id == app_id
65
+
66
+ bots.each_value.find { |client| client.config.app_id == app_id }
67
+ end
68
+
69
+ ##
70
+ # Returns the registry contents (bot name => API client). The hash is
71
+ # exposed for introspection; mutate it only between registrations.
72
+ #
73
+ # @return [Hash{Symbol => MixinBot::API}]
74
+ #
75
+ def bots
76
+ @bots ||= {}
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+
5
+ module MixinBot
6
+ module Transfers
7
+ ##
8
+ # ActiveRecord concern for the generated +MixinTransfer+ model
9
+ # (mixin_bot:transfers generator): the transfer ledger's state machine and
10
+ # its execution entry points.
11
+ #
12
+ # class MixinTransfer < ApplicationRecord
13
+ # include MixinBot::Transfers::Model
14
+ # end
15
+ #
16
+ # transfer = MixinTransfer.create!(
17
+ # recipient_id: user_id, asset_id: ASSET, amount: '1.5',
18
+ # memo: 'payout', trace_id: SecureRandom.uuid
19
+ # )
20
+ # transfer.perform! # executes the Safe pipeline
21
+ # transfer.reconcile! # resolves unknown outcomes
22
+ # MixinTransfer.reconcile_pending! # recurring-job entry point
23
+ #
24
+ # Required columns (see the generated migration): recipient_id, asset_id,
25
+ # amount, memo, trace_id (unique), state (default 'pending'),
26
+ # previous_state, transaction_hash, error, transitioned_at, bot_app_id
27
+ # (nil = the default bot), plus Rails timestamps.
28
+ #
29
+ module Model
30
+ extend ActiveSupport::Concern
31
+
32
+ STATES = %w[pending broadcast confirmed failed reconciling].freeze
33
+
34
+ # The allowed state graph: pending is pre-submission; broadcast means
35
+ # the transaction was submitted; confirmed and failed are terminal;
36
+ # reconciling means a submission outcome was indeterminate.
37
+ TRANSITIONS = {
38
+ 'pending' => %w[broadcast failed reconciling],
39
+ 'broadcast' => %w[confirmed reconciling],
40
+ 'reconciling' => %w[broadcast confirmed failed],
41
+ 'confirmed' => [].freeze,
42
+ 'failed' => [].freeze
43
+ }.freeze
44
+
45
+ included do
46
+ validates :trace_id, presence: true, uniqueness: true
47
+ validates :recipient_id, :asset_id, :amount, presence: true
48
+ validates :state, inclusion: { in: STATES }
49
+ end
50
+
51
+ class_methods do
52
+ # Recurring-job entry point: resolve every transfer whose send attempt
53
+ # ended indeterminately (timeout after submission).
54
+ def reconcile_pending!
55
+ reconciling.find_each(&:reconcile!)
56
+ end
57
+ end
58
+
59
+ ##
60
+ # Audited state transition through the allowed graph. Never mutate
61
+ # #state directly. Same-state transitions are no-ops (idempotent
62
+ # retries); terminal states (confirmed, failed) never change.
63
+ #
64
+ # @param state [String] target state
65
+ # @param transaction_hash [String, nil] set when the network revealed it
66
+ # @param error [String, nil] set when the transition records a failure
67
+ # @raise [MixinBot::ArgumentError] when the transition is not allowed
68
+ #
69
+ def transition_to!(state, transaction_hash: nil, error: nil)
70
+ state = state.to_s
71
+ return self if state == self.state
72
+
73
+ unless TRANSITIONS.fetch(self.state, []).include?(state)
74
+ raise MixinBot::ArgumentError, "illegal transfer transition: #{self.state.inspect} → #{state.inspect}"
75
+ end
76
+
77
+ update!(
78
+ previous_state: self.state,
79
+ state:,
80
+ transaction_hash: transaction_hash || self.transaction_hash,
81
+ error:,
82
+ transitioned_at: Time.now
83
+ )
84
+ end
85
+
86
+ ##
87
+ # Executes the Safe pipeline for this transfer (idempotent per trace
88
+ # id). Definitive rejections mark the transfer failed; indeterminate
89
+ # network outcomes mark it reconciling. {Reconcile} resolves those.
90
+ #
91
+ def perform!
92
+ return self if state == 'confirmed'
93
+ raise MixinBot::ArgumentError, "transfer #{trace_id} is failed and will not be retried" if state == 'failed'
94
+
95
+ Performer.new(self, api: bot_api).perform
96
+ end
97
+
98
+ ##
99
+ # Resolves an indeterminate outcome: confirm from the trace's snapshot,
100
+ # or re-send with the same trace id (safe — the network deduplicates).
101
+ #
102
+ def reconcile!
103
+ Reconcile.new(self, api: bot_api).call
104
+ end
105
+
106
+ # The API client bound to this transfer's bot (bot_app_id or default).
107
+ def bot_api
108
+ MixinBot.bot_by_app_id(bot_app_id) || MixinBot.api
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MixinBot
4
+ module Transfers
5
+ ##
6
+ # Executes the Safe pipeline for one transfer record:
7
+ # build_utxos → build_safe_transaction → verify → sign → send, with the
8
+ # transfer's trace id as the request id, so network-side deduplication
9
+ # makes every retry safe.
10
+ #
11
+ # Outcome mapping:
12
+ # - success → broadcast (transaction hash stored), then confirmed when the
13
+ # submission response carries the hash (it normally does);
14
+ # - definitive API rejection (insufficient funds, invalid request, ...) →
15
+ # failed — never retried;
16
+ # - indeterminate network outcome (timeout/connection loss around the
17
+ # submission) → reconciling — {Reconcile} resolves it.
18
+ #
19
+ class Performer
20
+ # Indeterminate-outcome network errors: the submission may or may not
21
+ # have landed, so the transfer goes to reconciling rather than failed.
22
+ NETWORK_ERRORS = [Faraday::Error, SocketError, Errno::ETIMEDOUT, Timeout::Error].freeze
23
+
24
+ attr_reader :transfer, :api
25
+
26
+ def initialize(transfer, api:)
27
+ @transfer = transfer
28
+ @api = api
29
+ end
30
+
31
+ ##
32
+ # Runs the pipeline and records the outcome. Re-raises unexpected
33
+ # (non-API, non-network) errors — those are bugs, left to the job
34
+ # backend's retry policy, with the transfer still in its prior state.
35
+ #
36
+ # @return [MixinBot::Transfers::Performer]
37
+ #
38
+ def perform
39
+ response = api.create_safe_transfer(
40
+ asset_id: transfer.asset_id,
41
+ amount: transfer.amount.to_d,
42
+ members: [transfer.recipient_id],
43
+ memo: transfer.memo.to_s,
44
+ trace_id: transfer.trace_id
45
+ )
46
+
47
+ data = response['data']
48
+ data = data.first if data.is_a?(Array)
49
+ data ||= {}
50
+
51
+ transfer.transition_to!('broadcast', transaction_hash: data['transaction_hash'])
52
+ transfer.transition_to!('confirmed', transaction_hash: data['transaction_hash']) if data['transaction_hash']
53
+ self
54
+ rescue MixinBot::APIError => e
55
+ transfer.transition_to!('failed', error: "#{e.class}: #{e.message}")
56
+ self
57
+ rescue Faraday::Error, SocketError, Errno::ETIMEDOUT, Timeout::Error => e
58
+ Transfers.logger.call(:indeterminate, "#{e.class}: #{e.message} (trace #{transfer.trace_id})")
59
+ transfer.transition_to!('reconciling', error: "#{e.class}: #{e.message}")
60
+ self
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MixinBot
4
+ module Transfers
5
+ ##
6
+ # Resolves a transfer whose send attempt ended indeterminately (timeout
7
+ # or connection loss around the submission):
8
+ #
9
+ # - a snapshot exists for the trace id → the transfer landed; confirm
10
+ # from the snapshot (no funds ever re-sent);
11
+ # - no snapshot exists → nothing landed; re-send with the same trace id —
12
+ # the network's trace deduplication makes that safe.
13
+ #
14
+ class Reconcile
15
+ attr_reader :transfer, :api
16
+
17
+ def initialize(transfer, api:)
18
+ @transfer = transfer
19
+ @api = api
20
+ end
21
+
22
+ ##
23
+ # @return [Symbol] :confirmed (found in the network), :resent (nothing
24
+ # existed; re-sent successfully) or :failed (the re-send was
25
+ # definitively rejected)
26
+ #
27
+ def call
28
+ snapshot = fetch_snapshot_by_trace
29
+
30
+ if snapshot
31
+ transfer.transition_to!('confirmed',
32
+ transaction_hash: snapshot['transaction_hash'] || transfer.transaction_hash)
33
+ :confirmed
34
+ else
35
+ Performer.new(transfer, api:).perform
36
+ transfer.state == 'failed' ? :failed : :resent
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ # Returns the snapshot hash for the trace id, or nil when the network
43
+ # has none (the only outcome that justifies a re-send).
44
+ def fetch_snapshot_by_trace
45
+ response = api.safe_snapshot_by_trace(transfer.trace_id)
46
+ data = response['data']
47
+ data.is_a?(Hash) && data['snapshot_id'] ? data : nil
48
+ rescue MixinBot::NotFoundError
49
+ nil
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MixinBot
4
+ ##
5
+ # Outbound transfer pipeline: a persisted transfer record enqueues a job
6
+ # that executes the Safe transaction pipeline exactly once per trace id,
7
+ # records the outcome on the record's state, and reconciles unknown
8
+ # outcomes (timeout after submission) against the snapshot API before any
9
+ # retry — the network's trace deduplication makes retries safe.
10
+ #
11
+ module Transfers
12
+ class << self
13
+ # Shared logger for the transfers integration; called with (level, detail).
14
+ attr_accessor :logger
15
+ end
16
+
17
+ self.logger = ->(level, detail) { warn "[mixin_transfers] #{level}: #{detail}" }
18
+ end
19
+ end
20
+
21
+ require_relative 'transfers/model'
22
+ require_relative 'transfers/performer'
23
+ require_relative 'transfers/reconcile'
@@ -11,5 +11,5 @@ module MixinBot
11
11
  #
12
12
  # @see https://semver.org/
13
13
  #
14
- VERSION = '3.0.0'
14
+ VERSION = '3.0.2'
15
15
  end
data/lib/mixin_bot.rb CHANGED
@@ -32,6 +32,7 @@ require_relative 'mixin_bot/cli'
32
32
  require_relative 'mixin_bot/computer'
33
33
  require_relative 'mixin_bot/invoice'
34
34
  require_relative 'mixin_bot/monitor'
35
+ require_relative 'mixin_bot/registry'
35
36
  require_relative 'mixin_bot/url_scheme'
36
37
  require_relative 'mixin_bot/utils'
37
38
  require_relative 'mixin_bot/nfo'
@@ -230,4 +231,6 @@ module MixinBot
230
231
  @deprecator ||= ActiveSupport::Deprecation.new('2.0', 'MixinBot')
231
232
  end
232
233
  end
234
+
235
+ extend Registry
233
236
  end
data/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # MixinBot
2
2
 
3
- > Ruby SDK and CLI for Mixin Network: Safe UTXO transfers, REST API, Blaze messaging, transaction crypto, optional MVM helpers. Ruby >= 4.0. Gem version 3.0.0.
3
+ > Ruby SDK and CLI for Mixin Network: Safe UTXO transfers, REST API, Blaze messaging, transaction crypto, optional MVM helpers. Ruby >= 4.0. Gem version 3.0.2.
4
4
 
5
5
  Important notes:
6
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixin_bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - an-lee
@@ -300,6 +300,36 @@ files:
300
300
  - examples/blaze.rb
301
301
  - examples/blaze_async.rb
302
302
  - examples/config.yml.example
303
+ - lib/generators/mixin_bot.rb
304
+ - lib/generators/mixin_bot/authentication/USAGE
305
+ - lib/generators/mixin_bot/authentication/authentication_generator.rb
306
+ - lib/generators/mixin_bot/authentication/templates/app/controllers/concerns/authentication.rb.tt
307
+ - lib/generators/mixin_bot/authentication/templates/app/controllers/sessions_controller.rb.tt
308
+ - lib/generators/mixin_bot/authentication/templates/app/models/current.rb.tt
309
+ - lib/generators/mixin_bot/authentication/templates/app/models/session.rb.tt
310
+ - lib/generators/mixin_bot/authentication/templates/app/models/user.rb.tt
311
+ - lib/generators/mixin_bot/authentication/templates/app/views/sessions/new.html.erb.tt
312
+ - lib/generators/mixin_bot/authentication/templates/config/initializers/omniauth.rb.tt
313
+ - lib/generators/mixin_bot/blaze/USAGE
314
+ - lib/generators/mixin_bot/blaze/blaze_generator.rb
315
+ - lib/generators/mixin_bot/blaze/templates/app/mixin/handlers/text_handler.rb
316
+ - lib/generators/mixin_bot/blaze/templates/config/initializers/mixin_bot_blaze.rb
317
+ - lib/generators/mixin_bot/install/USAGE
318
+ - lib/generators/mixin_bot/install/install_generator.rb
319
+ - lib/generators/mixin_bot/notifications/USAGE
320
+ - lib/generators/mixin_bot/notifications/notifications_generator.rb
321
+ - lib/generators/mixin_bot/notifications/templates/app/notifications/payment_received_notification.rb
322
+ - lib/generators/mixin_bot/outputs/USAGE
323
+ - lib/generators/mixin_bot/outputs/outputs_generator.rb
324
+ - lib/generators/mixin_bot/outputs/templates/app/mixin/processors/deposit_processor.rb
325
+ - lib/generators/mixin_bot/outputs/templates/app/models/mixin_output.rb
326
+ - lib/generators/mixin_bot/outputs/templates/db/migrate/create_mixin_outputs.rb.tt
327
+ - lib/generators/mixin_bot/transfers/USAGE
328
+ - lib/generators/mixin_bot/transfers/templates/app/jobs/mixin_transfers/perform_job.rb
329
+ - lib/generators/mixin_bot/transfers/templates/app/jobs/mixin_transfers/reconcile_job.rb
330
+ - lib/generators/mixin_bot/transfers/templates/app/models/mixin_transfer.rb
331
+ - lib/generators/mixin_bot/transfers/templates/db/migrate/create_mixin_transfers.rb.tt
332
+ - lib/generators/mixin_bot/transfers/transfers_generator.rb
303
333
  - lib/mixin_bot.rb
304
334
  - lib/mixin_bot/address.rb
305
335
  - lib/mixin_bot/api.rb
@@ -347,6 +377,7 @@ files:
347
377
  - lib/mixin_bot/api/user.rb
348
378
  - lib/mixin_bot/api/withdraw.rb
349
379
  - lib/mixin_bot/blaze/reactor.rb
380
+ - lib/mixin_bot/blaze/router.rb
350
381
  - lib/mixin_bot/bot_auth.rb
351
382
  - lib/mixin_bot/cache_store_adapter.rb
352
383
  - lib/mixin_bot/cli.rb
@@ -365,6 +396,7 @@ files:
365
396
  - lib/mixin_bot/configuration.rb
366
397
  - lib/mixin_bot/errors.rb
367
398
  - lib/mixin_bot/invoice.rb
399
+ - lib/mixin_bot/json_decoder.rb
368
400
  - lib/mixin_bot/models.rb
369
401
  - lib/mixin_bot/models/address.rb
370
402
  - lib/mixin_bot/models/api_envelope.rb
@@ -376,11 +408,28 @@ files:
376
408
  - lib/mixin_bot/models/user.rb
377
409
  - lib/mixin_bot/monitor.rb
378
410
  - lib/mixin_bot/nfo.rb
411
+ - lib/mixin_bot/notifications/mixin_channel.rb
412
+ - lib/mixin_bot/outputs.rb
413
+ - lib/mixin_bot/outputs/cursor_model.rb
414
+ - lib/mixin_bot/outputs/envelope.rb
415
+ - lib/mixin_bot/outputs/memory_stores.rb
416
+ - lib/mixin_bot/outputs/poller.rb
417
+ - lib/mixin_bot/outputs/processing_job.rb
418
+ - lib/mixin_bot/outputs/processors.rb
419
+ - lib/mixin_bot/outputs/receipt_model.rb
420
+ - lib/mixin_bot/rails.rb
421
+ - lib/mixin_bot/rails/railtie.rb
422
+ - lib/mixin_bot/rails/tasks/poller.rake
423
+ - lib/mixin_bot/registry.rb
379
424
  - lib/mixin_bot/session_store.rb
380
425
  - lib/mixin_bot/transaction.rb
381
426
  - lib/mixin_bot/transaction/buffer.rb
382
427
  - lib/mixin_bot/transaction/decoder.rb
383
428
  - lib/mixin_bot/transaction/encoder.rb
429
+ - lib/mixin_bot/transfers.rb
430
+ - lib/mixin_bot/transfers/model.rb
431
+ - lib/mixin_bot/transfers/performer.rb
432
+ - lib/mixin_bot/transfers/reconcile.rb
384
433
  - lib/mixin_bot/url_scheme.rb
385
434
  - lib/mixin_bot/utils.rb
386
435
  - lib/mixin_bot/utils/address.rb
@@ -423,7 +472,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
423
472
  - !ruby/object:Gem::Version
424
473
  version: '0'
425
474
  requirements: []
426
- rubygems_version: 4.0.16
475
+ rubygems_version: 4.0.20
427
476
  specification_version: 4
428
477
  summary: A Ruby SDK for Mixin Network
429
478
  test_files: []