Class: SolanaSessionsController

Inherits:
ApplicationController
  • Object
show all
Includes:
Solana::SessionAuth
Defined in:
app/controllers/solana_sessions_controller.rb

Overview

Solana / Phantom wallet sign-in (the web3 path).

GET  /auth/solana/nonce  — issue a one-time nonce for the SIWS message
POST /auth/solana/verify — verify the ed25519 signature, log in / sign up

The cryptography lives in the solana-studio gem (Solana::AuthVerifier); the Solana::SessionAuth concern adapts it to the Rails session (delete-before-verify nonce burn + host binding). On success the session is granted the :onchain flag so SessionContext reports :web3 (can sign on-chain txs this session).

Engine GENERIC base. Apps with a richer wallet identity (turf-monster: managed wallets, web2/web3 address split, account-linking, referral attribution) OVERRIDE this controller; it stays this simple for an app whose wallet is just an identity (one ‘solana_address` column).

Instance Method Summary collapse

Methods included from Solana::SessionAuth

#verify_solana_signature!

Instance Method Details

#nonceObject



19
20
21
22
23
# File 'app/controllers/solana_sessions_controller.rb', line 19

def nonce
  session[:solana_nonce]    = SecureRandom.hex(16)
  session[:solana_nonce_at] = Time.current.to_i
  render json: { nonce: session[:solana_nonce] }
end

#verifyObject



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'app/controllers/solana_sessions_controller.rb', line 25

def verify
  pubkey_b58 = verify_solana_signature!(
    message:       params[:message],
    signature_b58: params[:signature],
    pubkey_b58:    params[:pubkey],
    session:       session
  )

  user   = User.from_solana_wallet(pubkey_b58)
  is_new = user.nil?

  if is_new
    user = User.new(solana_address: pubkey_b58)
    Studio.configure_new_user.call(user)
  end

  rescue_and_log(target: user) do
    user.save! if user.new_record?
    set_app_session(user)
    session[:onchain] = true
    render json: { success: true, redirect: root_path, new_user: is_new }
  end
rescue ::Solana::AuthVerifier::VerificationError => e
  render json: { error: e.message }, status: :unauthorized
rescue StandardError => e
  render json: { error: e.message }, status: :unprocessable_entity
end