solrengine 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/README.md +159 -0
- data/lib/generators/solrengine/install_generator.rb +146 -0
- data/lib/generators/solrengine/templates/cable.yml +18 -0
- data/lib/generators/solrengine/templates/database.yml +55 -0
- data/lib/generators/solrengine/templates/env +11 -0
- data/lib/generators/solrengine/templates/solana_monitor +35 -0
- data/lib/generators/solrengine/templates/solrengine_realtime.rb +25 -0
- data/lib/generators/solrengine/templates/solrengine_rpc.rb +3 -0
- data/lib/solrengine/version.rb +5 -0
- data/lib/solrengine.rb +12 -0
- metadata +141 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 30115b7e2f062eb4560210d27fdd25e547e593e98b86abad78c84b87cf2161ed
|
|
4
|
+
data.tar.gz: 7c64d97f057b5b25cbe9a1df2f126d181e9740d2a11c048cd57465ea1178d44c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a8f44d0ca1cfdbdbff72481513c239862e2c4b0c78a7e8e53bf4a7a92679d0709bd0ca91d8eb280b988922a5e5561fb3b4536fa5892d25ae1de40ea0a1c6eb5d
|
|
7
|
+
data.tar.gz: a0869720bb4296812e9113d5d01ea97160f64b1d96b96e7bb747a4e2b2f22ec951d4205e41290a3fa483ec1579ab0e470a27e9c5d0f452221eb474ed5f36769f
|
data/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# SolRengine
|
|
2
|
+
|
|
3
|
+
The Rails framework for building Solana dapps.
|
|
4
|
+
|
|
5
|
+
Wallet authentication, token portfolio, SOL transfers, real-time WebSocket updates, and custom program interaction — using the Rails 8 default stack.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### 1. Create a Rails app
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
rails new my_solana_app --css=tailwind --javascript=esbuild
|
|
13
|
+
cd my_solana_app
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### 2. Add SolRengine to your Gemfile
|
|
17
|
+
|
|
18
|
+
Once published to RubyGems, this will be just `gem "solrengine"`. During pre-release:
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
gem "solrengine", github: "solrengine/solrengine", branch: "main"
|
|
22
|
+
gem "solrengine-auth", github: "solrengine/auth", branch: "main"
|
|
23
|
+
gem "solrengine-rpc", github: "solrengine/rpc", branch: "main"
|
|
24
|
+
gem "solrengine-tokens", github: "solrengine/tokens", branch: "main"
|
|
25
|
+
gem "solrengine-transactions", github: "solrengine/transactions", branch: "main"
|
|
26
|
+
gem "solrengine-realtime", github: "solrengine/realtime", branch: "main"
|
|
27
|
+
gem "solrengine-programs", github: "solrengine/programs", branch: "master"
|
|
28
|
+
gem "dotenv-rails", group: [:development, :test]
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 3. Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
bundle install
|
|
35
|
+
rails generate solrengine:install
|
|
36
|
+
rails db:prepare
|
|
37
|
+
yarn add @solana/kit @wallet-standard/app @solana/wallet-standard-features @rails/actioncable
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 4. Start
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
bin/dev
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Visit `localhost:3000/auth/login` — connect your wallet and sign in.
|
|
47
|
+
|
|
48
|
+
## What the Generator Does
|
|
49
|
+
|
|
50
|
+
- Creates `User` model with wallet auth (SIWS)
|
|
51
|
+
- Creates `Token` model with Jupiter metadata
|
|
52
|
+
- Creates `Transfer` model with confirmation tracking
|
|
53
|
+
- Sets up multi-database SQLite (primary, cache, queue, cable)
|
|
54
|
+
- Configures Solid Queue, Solid Cache, and Solid Cable for development
|
|
55
|
+
- Installs Stimulus wallet controller (Wallet Standard discovery)
|
|
56
|
+
- Adds Tailwind sources for gem views
|
|
57
|
+
- Creates `.env` template, `bin/solana_monitor`, and Procfile entries
|
|
58
|
+
- Mounts auth engine at `/auth` (login, nonce, verify, logout)
|
|
59
|
+
|
|
60
|
+
## What You Get
|
|
61
|
+
|
|
62
|
+
| Gem | What |
|
|
63
|
+
|-----|------|
|
|
64
|
+
| [**solrengine-auth**](https://github.com/solrengine/auth) | SIWS wallet authentication (any Wallet Standard wallet) |
|
|
65
|
+
| [**solrengine-rpc**](https://github.com/solrengine/rpc) | Solana JSON-RPC client with SSL fix and multi-network config |
|
|
66
|
+
| [**solrengine-tokens**](https://github.com/solrengine/tokens) | Token metadata from Jupiter, USD prices, wallet portfolio |
|
|
67
|
+
| [**solrengine-transactions**](https://github.com/solrengine/transactions) | SOL transfers with @solana/kit, confirmation tracking |
|
|
68
|
+
| [**solrengine-realtime**](https://github.com/solrengine/realtime) | WebSocket account monitoring, Turbo Streams push updates |
|
|
69
|
+
| [**solrengine-programs**](https://github.com/solrengine/programs) | Anchor IDL parsing, Borsh serialization, program account models, instruction builders |
|
|
70
|
+
|
|
71
|
+
Each gem can be used independently or together via the `solrengine` meta-gem.
|
|
72
|
+
|
|
73
|
+
## Custom Program Interaction
|
|
74
|
+
|
|
75
|
+
Interact with any Anchor program by generating from its IDL:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
rails generate solrengine:program PiggyBank path/to/piggy_bank.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
This scaffolds account models, instruction builders, and a Stimulus controller. See [solrengine-programs](https://github.com/solrengine/programs) for details.
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
The generator creates initializers automatically. Customize as needed:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
# config/initializers/solrengine_auth.rb
|
|
89
|
+
Solrengine::Auth.configure do |config|
|
|
90
|
+
config.domain = ENV.fetch("APP_DOMAIN", "localhost")
|
|
91
|
+
config.nonce_ttl = 5.minutes
|
|
92
|
+
config.after_sign_in_path = "/dashboard"
|
|
93
|
+
config.after_sign_out_path = "/"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# config/initializers/solrengine_rpc.rb
|
|
97
|
+
Solrengine::Rpc.configure do |config|
|
|
98
|
+
config.network = ENV.fetch("SOLANA_NETWORK", "mainnet")
|
|
99
|
+
end
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Environment Variables
|
|
103
|
+
|
|
104
|
+
The generator creates a `.env` file. Configure with your RPC URLs:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
SOLANA_NETWORK=devnet
|
|
108
|
+
SOLANA_RPC_URL=https://mainnet.helius-rpc.com/?api-key=xxx
|
|
109
|
+
SOLANA_WS_URL=wss://mainnet.helius-rpc.com/?api-key=xxx
|
|
110
|
+
SOLANA_RPC_DEVNET_URL=https://devnet.helius-rpc.com/?api-key=xxx
|
|
111
|
+
SOLANA_WS_DEVNET_URL=wss://devnet.helius-rpc.com/?api-key=xxx
|
|
112
|
+
APP_DOMAIN=myapp.com
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Free RPC keys available at [helius.dev](https://helius.dev).
|
|
116
|
+
|
|
117
|
+
## Building After Auth
|
|
118
|
+
|
|
119
|
+
After sign-in, the app redirects to `/dashboard` (configurable). Create your own:
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
# config/routes.rb
|
|
123
|
+
root "dashboard#show"
|
|
124
|
+
|
|
125
|
+
# app/controllers/dashboard_controller.rb
|
|
126
|
+
class DashboardController < ApplicationController
|
|
127
|
+
before_action :authenticate!
|
|
128
|
+
|
|
129
|
+
def show
|
|
130
|
+
@wallet = current_user.wallet_address
|
|
131
|
+
@portfolio = Solrengine::Tokens::Portfolio.new(@wallet)
|
|
132
|
+
@tokens = @portfolio.tokens
|
|
133
|
+
@transactions = @portfolio.recent_transactions
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`current_user`, `logged_in?`, and `authenticate!` are added to your ApplicationController by the generator.
|
|
139
|
+
|
|
140
|
+
## Processes
|
|
141
|
+
|
|
142
|
+
`bin/dev` starts 5 processes via Procfile.dev:
|
|
143
|
+
|
|
144
|
+
| Process | What |
|
|
145
|
+
|---------|------|
|
|
146
|
+
| web | Rails server (Puma) |
|
|
147
|
+
| js | esbuild watch |
|
|
148
|
+
| css | Tailwind watch |
|
|
149
|
+
| jobs | Solid Queue worker |
|
|
150
|
+
| ws | Solana WebSocket monitor |
|
|
151
|
+
|
|
152
|
+
## Showcase
|
|
153
|
+
|
|
154
|
+
- [**WalletTrain**](https://github.com/solrengine/wallet-train) — Solana wallet with token portfolio, SOL transfers, and real-time updates.
|
|
155
|
+
- [**PiggyBank**](https://github.com/solrengine/piggybank) — Time-locked SOL savings using a custom Anchor program via `solrengine-programs`.
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
MIT. A [Moviendome](https://moviendo.me) project.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
class Solrengine::InstallGenerator < Rails::Generators::Base
|
|
2
|
+
source_root File.expand_path("templates", __dir__)
|
|
3
|
+
|
|
4
|
+
def run_sub_generators
|
|
5
|
+
generate "solrengine:auth:install"
|
|
6
|
+
generate "solrengine:tokens:install"
|
|
7
|
+
generate "solrengine:transactions:install"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def create_rpc_initializer
|
|
11
|
+
template "solrengine_rpc.rb", "config/initializers/solrengine_rpc.rb"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create_realtime_initializer
|
|
15
|
+
template "solrengine_realtime.rb", "config/initializers/solrengine_realtime.rb"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_solana_monitor
|
|
19
|
+
template "solana_monitor", "bin/solana_monitor"
|
|
20
|
+
chmod "bin/solana_monitor", 0o755
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def create_env_file
|
|
24
|
+
template "env", ".env" unless File.exist?(".env")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def setup_multi_database
|
|
28
|
+
template "database.yml", "config/database.yml", force: true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def setup_solid_queue_in_development
|
|
32
|
+
dev_rb = "config/environments/development.rb"
|
|
33
|
+
content = File.read(dev_rb)
|
|
34
|
+
|
|
35
|
+
unless content.include?("solid_queue")
|
|
36
|
+
inject_into_file dev_rb, after: "config.active_job.verbose_enqueue_logs = true\n" do
|
|
37
|
+
<<~RUBY
|
|
38
|
+
|
|
39
|
+
# SolRengine: Use Solid Queue for background jobs
|
|
40
|
+
config.active_job.queue_adapter = :solid_queue
|
|
41
|
+
config.solid_queue.connects_to = { database: { writing: :queue } }
|
|
42
|
+
RUBY
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
unless content.include?("solid_cache_store")
|
|
47
|
+
gsub_file dev_rb,
|
|
48
|
+
"config.cache_store = :memory_store",
|
|
49
|
+
"config.cache_store = :solid_cache_store"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def setup_solid_cable
|
|
54
|
+
template "cable.yml", "config/cable.yml", force: true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def setup_cache_yml
|
|
58
|
+
cache_yml = "config/cache.yml"
|
|
59
|
+
if File.exist?(cache_yml)
|
|
60
|
+
content = File.read(cache_yml)
|
|
61
|
+
unless content.include?("database: cache")
|
|
62
|
+
gsub_file cache_yml, "development:\n <<: *default", "development:\n database: cache\n <<: *default"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def add_tailwind_gem_sources
|
|
68
|
+
css_file = "app/assets/stylesheets/application.tailwind.css"
|
|
69
|
+
return unless File.exist?(css_file)
|
|
70
|
+
|
|
71
|
+
content = File.read(css_file)
|
|
72
|
+
return if content.include?("solrengine")
|
|
73
|
+
|
|
74
|
+
# Find gem paths for Tailwind to scan
|
|
75
|
+
gem_paths = %w[solrengine-auth].filter_map do |gem_name|
|
|
76
|
+
spec = Gem.loaded_specs[gem_name] || Bundler.load.specs.find { |s| s.name == gem_name }
|
|
77
|
+
spec&.full_gem_path
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
return if gem_paths.empty?
|
|
81
|
+
|
|
82
|
+
source_lines = gem_paths.map { |p| "@source \"#{p}/app\";" }.join("\n")
|
|
83
|
+
|
|
84
|
+
append_to_file css_file, "\n/* SolRengine gem views */\n#{source_lines}\n"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def install_stimulus_controllers
|
|
88
|
+
# Copy wallet controller from gem into the app
|
|
89
|
+
auth_gem_path = %w[solrengine-auth].filter_map { |n|
|
|
90
|
+
spec = Gem.loaded_specs[n] || Bundler.load.specs.find { |s| s.name == n }
|
|
91
|
+
spec&.full_gem_path
|
|
92
|
+
}.first
|
|
93
|
+
|
|
94
|
+
if auth_gem_path
|
|
95
|
+
wallet_src = File.join(auth_gem_path, "app/assets/javascripts/solrengine/auth/wallet_controller.js")
|
|
96
|
+
if File.exist?(wallet_src)
|
|
97
|
+
copy_file wallet_src, "app/javascript/controllers/wallet_controller.js"
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Register in index.js
|
|
102
|
+
index_js = "app/javascript/controllers/index.js"
|
|
103
|
+
if File.exist?(index_js)
|
|
104
|
+
content = File.read(index_js)
|
|
105
|
+
unless content.include?("WalletController")
|
|
106
|
+
append_to_file index_js, <<~JS
|
|
107
|
+
|
|
108
|
+
import WalletController from "./wallet_controller"
|
|
109
|
+
application.register("wallet", WalletController)
|
|
110
|
+
JS
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def fix_stylesheet_link
|
|
116
|
+
layout = "app/views/layouts/application.html.erb"
|
|
117
|
+
if File.exist?(layout)
|
|
118
|
+
content = File.read(layout)
|
|
119
|
+
if content.include?("stylesheet_link_tag :app")
|
|
120
|
+
gsub_file layout,
|
|
121
|
+
"stylesheet_link_tag :app",
|
|
122
|
+
'stylesheet_link_tag "application"'
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def update_procfile
|
|
128
|
+
procfile = "Procfile.dev"
|
|
129
|
+
if File.exist?(procfile)
|
|
130
|
+
append_to_file procfile, "jobs: bin/jobs\n" unless File.read(procfile).include?("jobs:")
|
|
131
|
+
append_to_file procfile, "ws: bin/solana_monitor\n" unless File.read(procfile).include?("ws:")
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def show_post_install
|
|
136
|
+
say "\n SolRengine installed!", :green
|
|
137
|
+
say ""
|
|
138
|
+
say " Next steps:"
|
|
139
|
+
say " 1. rails db:prepare"
|
|
140
|
+
say " 2. yarn add @solana/kit @wallet-standard/app @solana/wallet-standard-features @rails/actioncable"
|
|
141
|
+
say " 3. Configure .env with your RPC URLs"
|
|
142
|
+
say " 4. bin/dev"
|
|
143
|
+
say " 5. Visit /auth/login"
|
|
144
|
+
say ""
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
development:
|
|
2
|
+
adapter: solid_cable
|
|
3
|
+
connects_to:
|
|
4
|
+
database:
|
|
5
|
+
writing: cable
|
|
6
|
+
polling_interval: 0.1.seconds
|
|
7
|
+
message_retention: 1.hour
|
|
8
|
+
|
|
9
|
+
test:
|
|
10
|
+
adapter: test
|
|
11
|
+
|
|
12
|
+
production:
|
|
13
|
+
adapter: solid_cable
|
|
14
|
+
connects_to:
|
|
15
|
+
database:
|
|
16
|
+
writing: cable
|
|
17
|
+
polling_interval: 0.1.seconds
|
|
18
|
+
message_retention: 1.day
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
default: &default
|
|
2
|
+
adapter: sqlite3
|
|
3
|
+
pool: <%%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
|
|
4
|
+
timeout: 5000
|
|
5
|
+
|
|
6
|
+
development:
|
|
7
|
+
primary:
|
|
8
|
+
<<: *default
|
|
9
|
+
database: storage/development.sqlite3
|
|
10
|
+
cache:
|
|
11
|
+
<<: *default
|
|
12
|
+
database: storage/development_cache.sqlite3
|
|
13
|
+
migrations_paths: db/cache_migrate
|
|
14
|
+
queue:
|
|
15
|
+
<<: *default
|
|
16
|
+
database: storage/development_queue.sqlite3
|
|
17
|
+
migrations_paths: db/queue_migrate
|
|
18
|
+
cable:
|
|
19
|
+
<<: *default
|
|
20
|
+
database: storage/development_cable.sqlite3
|
|
21
|
+
migrations_paths: db/cable_migrate
|
|
22
|
+
|
|
23
|
+
test:
|
|
24
|
+
primary:
|
|
25
|
+
<<: *default
|
|
26
|
+
database: storage/test.sqlite3
|
|
27
|
+
cache:
|
|
28
|
+
<<: *default
|
|
29
|
+
database: storage/test_cache.sqlite3
|
|
30
|
+
migrations_paths: db/cache_migrate
|
|
31
|
+
queue:
|
|
32
|
+
<<: *default
|
|
33
|
+
database: storage/test_queue.sqlite3
|
|
34
|
+
migrations_paths: db/queue_migrate
|
|
35
|
+
cable:
|
|
36
|
+
<<: *default
|
|
37
|
+
database: storage/test_cable.sqlite3
|
|
38
|
+
migrations_paths: db/cable_migrate
|
|
39
|
+
|
|
40
|
+
production:
|
|
41
|
+
primary:
|
|
42
|
+
<<: *default
|
|
43
|
+
database: storage/production.sqlite3
|
|
44
|
+
cache:
|
|
45
|
+
<<: *default
|
|
46
|
+
database: storage/production_cache.sqlite3
|
|
47
|
+
migrations_paths: db/cache_migrate
|
|
48
|
+
queue:
|
|
49
|
+
<<: *default
|
|
50
|
+
database: storage/production_queue.sqlite3
|
|
51
|
+
migrations_paths: db/queue_migrate
|
|
52
|
+
cable:
|
|
53
|
+
<<: *default
|
|
54
|
+
database: storage/production_cable.sqlite3
|
|
55
|
+
migrations_paths: db/cable_migrate
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Solana Network (mainnet, devnet, testnet)
|
|
2
|
+
SOLANA_NETWORK=devnet
|
|
3
|
+
|
|
4
|
+
# RPC URLs (get free keys at helius.dev)
|
|
5
|
+
# SOLANA_RPC_URL=https://mainnet.helius-rpc.com/?api-key=YOUR_KEY
|
|
6
|
+
# SOLANA_WS_URL=wss://mainnet.helius-rpc.com/?api-key=YOUR_KEY
|
|
7
|
+
# SOLANA_RPC_DEVNET_URL=https://devnet.helius-rpc.com/?api-key=YOUR_KEY
|
|
8
|
+
# SOLANA_WS_DEVNET_URL=wss://devnet.helius-rpc.com/?api-key=YOUR_KEY
|
|
9
|
+
|
|
10
|
+
# SIWS domain (your production domain)
|
|
11
|
+
# APP_DOMAIN=myapp.com
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require_relative "../config/environment"
|
|
4
|
+
|
|
5
|
+
config = Solrengine::Rpc.configuration
|
|
6
|
+
puts "[SolanaMonitor] Starting on #{config.network}"
|
|
7
|
+
puts "[SolanaMonitor] WS: #{config.ws_url.sub(/api-key=.*/, 'api-key=***')}"
|
|
8
|
+
|
|
9
|
+
monitors = {}
|
|
10
|
+
|
|
11
|
+
loop do
|
|
12
|
+
active_wallets = User.where("updated_at > ?", 1.hour.ago).pluck(:wallet_address)
|
|
13
|
+
|
|
14
|
+
active_wallets.each do |wallet|
|
|
15
|
+
next if monitors[wallet]
|
|
16
|
+
|
|
17
|
+
puts "[SolanaMonitor] Subscribing to #{wallet}"
|
|
18
|
+
monitor = Solrengine::Realtime::AccountMonitor.new(wallet)
|
|
19
|
+
Thread.new { monitor.start }
|
|
20
|
+
monitors[wallet] = monitor
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
monitors.each do |wallet, monitor|
|
|
24
|
+
unless active_wallets.include?(wallet)
|
|
25
|
+
puts "[SolanaMonitor] Unsubscribing from #{wallet}"
|
|
26
|
+
monitor.stop
|
|
27
|
+
monitors.delete(wallet)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
sleep 30
|
|
32
|
+
rescue => e
|
|
33
|
+
puts "[SolanaMonitor] Error: #{e.message}"
|
|
34
|
+
sleep 5
|
|
35
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Solrengine::Realtime.on_account_change = ->(wallet_address) {
|
|
2
|
+
Rails.cache.delete("wallet/#{wallet_address}/tokens")
|
|
3
|
+
Rails.cache.delete("wallet/#{wallet_address}/recent_txs")
|
|
4
|
+
|
|
5
|
+
portfolio = Solrengine::Tokens::Portfolio.new(wallet_address)
|
|
6
|
+
stream = "wallet_#{wallet_address}"
|
|
7
|
+
|
|
8
|
+
Turbo::StreamsChannel.broadcast_replace_to(
|
|
9
|
+
stream, target: "portfolio_value",
|
|
10
|
+
partial: "dashboard/portfolio_value",
|
|
11
|
+
locals: { total_usd: portfolio.total_usd_value }
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
Turbo::StreamsChannel.broadcast_replace_to(
|
|
15
|
+
stream, target: "token_list",
|
|
16
|
+
partial: "dashboard/token_list",
|
|
17
|
+
locals: { tokens: portfolio.tokens }
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
Turbo::StreamsChannel.broadcast_replace_to(
|
|
21
|
+
stream, target: "recent_activity",
|
|
22
|
+
partial: "dashboard/recent_activity",
|
|
23
|
+
locals: { transactions: portfolio.recent_transactions, wallet_address: wallet_address }
|
|
24
|
+
)
|
|
25
|
+
}
|
data/lib/solrengine.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require_relative "solrengine/version"
|
|
2
|
+
|
|
3
|
+
require "solrengine/rpc"
|
|
4
|
+
require "solrengine/auth"
|
|
5
|
+
require "solrengine/tokens"
|
|
6
|
+
require "solrengine/transactions"
|
|
7
|
+
require "solrengine/realtime"
|
|
8
|
+
require "solrengine/programs"
|
|
9
|
+
|
|
10
|
+
module Solrengine
|
|
11
|
+
class Error < StandardError; end
|
|
12
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: solrengine
|
|
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-03-21 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: solrengine-auth
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0.1'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0.1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: solrengine-rpc
|
|
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-tokens
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.1'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.1'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: solrengine-transactions
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0.1'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0.1'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: solrengine-realtime
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0.1'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0.1'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: solrengine-programs
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0.1'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0.1'
|
|
97
|
+
description: 'SolRengine gives Rails developers everything they need to build Solana
|
|
98
|
+
dapps: wallet authentication (SIWS), RPC client, token portfolio, SOL transfers,
|
|
99
|
+
and real-time WebSocket updates. One gem, full stack.'
|
|
100
|
+
email:
|
|
101
|
+
- estoy@moviendo.me
|
|
102
|
+
executables: []
|
|
103
|
+
extensions: []
|
|
104
|
+
extra_rdoc_files: []
|
|
105
|
+
files:
|
|
106
|
+
- README.md
|
|
107
|
+
- lib/generators/solrengine/install_generator.rb
|
|
108
|
+
- lib/generators/solrengine/templates/cable.yml
|
|
109
|
+
- lib/generators/solrengine/templates/database.yml
|
|
110
|
+
- lib/generators/solrengine/templates/env
|
|
111
|
+
- lib/generators/solrengine/templates/solana_monitor
|
|
112
|
+
- lib/generators/solrengine/templates/solrengine_realtime.rb
|
|
113
|
+
- lib/generators/solrengine/templates/solrengine_rpc.rb
|
|
114
|
+
- lib/solrengine.rb
|
|
115
|
+
- lib/solrengine/version.rb
|
|
116
|
+
homepage: https://github.com/solrengine/solrengine
|
|
117
|
+
licenses:
|
|
118
|
+
- MIT
|
|
119
|
+
metadata:
|
|
120
|
+
homepage_uri: https://github.com/solrengine/solrengine
|
|
121
|
+
source_code_uri: https://github.com/solrengine/solrengine
|
|
122
|
+
post_install_message:
|
|
123
|
+
rdoc_options: []
|
|
124
|
+
require_paths:
|
|
125
|
+
- lib
|
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - ">="
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: 3.2.0
|
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
|
+
requirements:
|
|
133
|
+
- - ">="
|
|
134
|
+
- !ruby/object:Gem::Version
|
|
135
|
+
version: '0'
|
|
136
|
+
requirements: []
|
|
137
|
+
rubygems_version: 3.5.22
|
|
138
|
+
signing_key:
|
|
139
|
+
specification_version: 4
|
|
140
|
+
summary: The Rails framework for building Solana dapps
|
|
141
|
+
test_files: []
|