solrengine-sdp 0.1.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +197 -0
- data/app/jobs/solrengine/sdp/provision_wallet_job.rb +125 -0
- data/app/jobs/solrengine/sdp/track_transfer_job.rb +161 -0
- data/app/models/solrengine/sdp/transfer.rb +229 -0
- data/lib/generators/solrengine/sdp/install_generator.rb +225 -0
- data/lib/generators/solrengine/sdp/templates/add_solrengine_sdp_to_users.rb +13 -0
- data/lib/generators/solrengine/sdp/templates/cable.yml +23 -0
- data/lib/generators/solrengine/sdp/templates/create_solrengine_sdp_transfers.rb +27 -0
- data/lib/generators/solrengine/sdp/templates/initializer.rb +44 -0
- data/lib/generators/solrengine/sdp/templates/sdp_watcher +134 -0
- data/lib/solrengine/sdp/broadcaster.rb +163 -0
- data/lib/solrengine/sdp/configuration.rb +107 -0
- data/lib/solrengine/sdp/engine.rb +21 -0
- data/lib/solrengine/sdp/errors.rb +20 -0
- data/lib/solrengine/sdp/faucet.rb +115 -0
- data/lib/solrengine/sdp/version.rb +11 -0
- data/lib/solrengine/sdp/wallet_owner.rb +114 -0
- data/lib/solrengine/sdp.rb +128 -0
- data/lib/solrengine-sdp.rb +3 -0
- metadata +109 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bigdecimal"
|
|
4
|
+
require "solana-sdp"
|
|
5
|
+
require "solrengine/realtime"
|
|
6
|
+
|
|
7
|
+
require_relative "sdp/version"
|
|
8
|
+
require_relative "sdp/errors"
|
|
9
|
+
require_relative "sdp/configuration"
|
|
10
|
+
require_relative "sdp/wallet_owner"
|
|
11
|
+
require_relative "sdp/broadcaster"
|
|
12
|
+
require_relative "sdp/faucet"
|
|
13
|
+
require_relative "sdp/engine" if defined?(Rails::Engine)
|
|
14
|
+
|
|
15
|
+
module Solrengine
|
|
16
|
+
# Rails engine for custodial Solana wallets backed by the Solana Developer
|
|
17
|
+
# Platform (SDP). Composes the solana-sdp client with the solrengine family.
|
|
18
|
+
module Sdp
|
|
19
|
+
# Rake task prefixes for which the boot-time api_key check is skipped:
|
|
20
|
+
# CI and Docker image builds run these without production secrets.
|
|
21
|
+
EXEMPT_TASK_PREFIXES = %w[assets: db: app: tmp: log:].freeze
|
|
22
|
+
|
|
23
|
+
# Name this engine registers under on the solrengine-realtime subscriber
|
|
24
|
+
# registry (start_realtime!/stop_realtime!). Apps can register their own
|
|
25
|
+
# subscribers alongside it under their own names.
|
|
26
|
+
REALTIME_SUBSCRIBER_NAME = :solrengine_sdp
|
|
27
|
+
|
|
28
|
+
class << self
|
|
29
|
+
def configuration
|
|
30
|
+
@configuration ||= Configuration.new
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def configure
|
|
34
|
+
yield(configuration)
|
|
35
|
+
@client = nil
|
|
36
|
+
configuration
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Memoized SDP API client built from the configuration. Reset whenever
|
|
40
|
+
# `configure` runs, so reconfiguring always yields a fresh client.
|
|
41
|
+
def client
|
|
42
|
+
@client ||= ::Sdp::Client.new(
|
|
43
|
+
api_key: configuration.validate!.api_key,
|
|
44
|
+
base_url: configuration.base_url
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def reset_configuration!
|
|
49
|
+
@configuration = nil
|
|
50
|
+
@client = nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Pure function over rake task names so the exemption logic is
|
|
54
|
+
# unit-testable: exempt_context?(["assets:precompile"]) => true.
|
|
55
|
+
def exempt_context?(task_names)
|
|
56
|
+
Array(task_names).any? do |task|
|
|
57
|
+
EXEMPT_TASK_PREFIXES.any? { |prefix| task.to_s.start_with?(prefix) }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# True when the current process is an exempt rake task (boot check skip).
|
|
62
|
+
def exempt_rake_context?
|
|
63
|
+
return false unless defined?(Rake) && Rake.respond_to?(:application)
|
|
64
|
+
|
|
65
|
+
application = Rake.application
|
|
66
|
+
return false unless application.respond_to?(:top_level_tasks)
|
|
67
|
+
|
|
68
|
+
exempt_context?(application.top_level_tasks)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# solrengine-tokens is an optional price source — never a hard
|
|
72
|
+
# dependency. True when its JupiterClient is loadable.
|
|
73
|
+
def price_source_available?
|
|
74
|
+
return true if defined?(Solrengine::Tokens::JupiterClient)
|
|
75
|
+
|
|
76
|
+
begin
|
|
77
|
+
require "solrengine/tokens"
|
|
78
|
+
rescue LoadError
|
|
79
|
+
return false
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
defined?(Solrengine::Tokens::JupiterClient) ? true : false
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# USD price for a mint via the optional tokens gem. Returns nil when the
|
|
86
|
+
# gem is absent or the price lookup fails — price must never gate money
|
|
87
|
+
# flows (the U9 broadcaster builds on this).
|
|
88
|
+
def price_for(mint)
|
|
89
|
+
return nil unless price_source_available?
|
|
90
|
+
|
|
91
|
+
Solrengine::Tokens::JupiterClient.fetch_prices([ mint ])[mint]
|
|
92
|
+
rescue StandardError
|
|
93
|
+
nil
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# USD value for an Sdp::Balance (AE3): SDP's own usd_value when present
|
|
97
|
+
# (v0.29+ populates it), else derived from the optional tokens gem's
|
|
98
|
+
# Jupiter price, else nil. Price data is decorative — every failure
|
|
99
|
+
# path degrades to nil so a price hiccup can NEVER fail a broadcaster
|
|
100
|
+
# fetch or gate a money-movement broadcast.
|
|
101
|
+
def usd_value_for(balance)
|
|
102
|
+
usd = balance.usd_value
|
|
103
|
+
return usd unless usd.nil? || usd.to_s.empty?
|
|
104
|
+
|
|
105
|
+
price = price_for(balance.mint)
|
|
106
|
+
return nil unless price
|
|
107
|
+
|
|
108
|
+
BigDecimal(balance.ui_amount.to_s) * BigDecimal(price.to_s)
|
|
109
|
+
rescue StandardError
|
|
110
|
+
nil
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Registers the engine's Broadcaster on the solrengine-realtime
|
|
114
|
+
# subscriber registry: every account-change dispatch re-fetches and
|
|
115
|
+
# broadcasts for that wallet. Called by the watcher process
|
|
116
|
+
# (bin/sdp_watcher); idempotent — re-subscribing replaces the block.
|
|
117
|
+
def start_realtime!
|
|
118
|
+
Solrengine::Realtime.subscribe(REALTIME_SUBSCRIBER_NAME) do |wallet_address|
|
|
119
|
+
Broadcaster.call(wallet_address)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def stop_realtime!
|
|
124
|
+
Solrengine::Realtime.unsubscribe(REALTIME_SUBSCRIBER_NAME)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: solrengine-sdp
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jose Ferrer
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-06-13 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rails
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '7.1'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '7.1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: solana-sdp
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.1'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0.1'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: solrengine-realtime
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.2'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.2'
|
|
55
|
+
description: 'Rails engine for SDP-backed apps: Wallet-per-User provisioning, transfer
|
|
56
|
+
persistence and tracking, and real-time balance broadcasts built on the solrengine
|
|
57
|
+
family.'
|
|
58
|
+
email:
|
|
59
|
+
- estoy@moviendo.me
|
|
60
|
+
executables: []
|
|
61
|
+
extensions: []
|
|
62
|
+
extra_rdoc_files: []
|
|
63
|
+
files:
|
|
64
|
+
- LICENSE
|
|
65
|
+
- README.md
|
|
66
|
+
- app/jobs/solrengine/sdp/provision_wallet_job.rb
|
|
67
|
+
- app/jobs/solrengine/sdp/track_transfer_job.rb
|
|
68
|
+
- app/models/solrengine/sdp/transfer.rb
|
|
69
|
+
- lib/generators/solrengine/sdp/install_generator.rb
|
|
70
|
+
- lib/generators/solrengine/sdp/templates/add_solrengine_sdp_to_users.rb
|
|
71
|
+
- lib/generators/solrengine/sdp/templates/cable.yml
|
|
72
|
+
- lib/generators/solrengine/sdp/templates/create_solrengine_sdp_transfers.rb
|
|
73
|
+
- lib/generators/solrengine/sdp/templates/initializer.rb
|
|
74
|
+
- lib/generators/solrengine/sdp/templates/sdp_watcher
|
|
75
|
+
- lib/solrengine-sdp.rb
|
|
76
|
+
- lib/solrengine/sdp.rb
|
|
77
|
+
- lib/solrengine/sdp/broadcaster.rb
|
|
78
|
+
- lib/solrengine/sdp/configuration.rb
|
|
79
|
+
- lib/solrengine/sdp/engine.rb
|
|
80
|
+
- lib/solrengine/sdp/errors.rb
|
|
81
|
+
- lib/solrengine/sdp/faucet.rb
|
|
82
|
+
- lib/solrengine/sdp/version.rb
|
|
83
|
+
- lib/solrengine/sdp/wallet_owner.rb
|
|
84
|
+
homepage: https://github.com/solrengine/sdp
|
|
85
|
+
licenses:
|
|
86
|
+
- MIT
|
|
87
|
+
metadata:
|
|
88
|
+
homepage_uri: https://github.com/solrengine/sdp
|
|
89
|
+
source_code_uri: https://github.com/solrengine/sdp
|
|
90
|
+
post_install_message:
|
|
91
|
+
rdoc_options: []
|
|
92
|
+
require_paths:
|
|
93
|
+
- lib
|
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
|
+
requirements:
|
|
96
|
+
- - ">="
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: 3.2.0
|
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
requirements: []
|
|
105
|
+
rubygems_version: 3.5.22
|
|
106
|
+
signing_key:
|
|
107
|
+
specification_version: 4
|
|
108
|
+
summary: Custodial Solana wallets for Rails via the Solana Developer Platform
|
|
109
|
+
test_files: []
|