Class: SessionContext

Inherits:
Object
  • Object
show all
Defined in:
app/models/session_context.rb

Overview

Canonical, single source of truth for the current viewer’s auth + wallet state.

‘mode` is the 3-way value the entire UI branches on:

:guest — not logged in
:web2  — logged in with a custodial/managed wallet this session (email or
         Google login, or a Phantom account that did NOT authenticate via a
         wallet signature this session)
:web3  — logged in AND authenticated via a live Phantom wallet signature
         this session (onchain_session?) — i.e. can sign on-chain txs now

Mode is decided by the SESSION, not by account identity: a Phantom owner who logs in by email is :web2 for that session. ‘phantom_linked?` exposes the account-level fact separately, so the UI can still offer “Connect Phantom”.

Built once per request by ApplicationController#wallet_context, serialised into the page, and mirrored client-side by Alpine.store(‘session’).

Lifted into studio-engine (was turf-monster app/models). Wallet predicates are called through ‘respond_to?` so an app with wallet sign-in disabled (no #phantom_wallet? / #solana_address on User) still gets correct :guest/:web2.

Constant Summary collapse

MODES =
%i[guest web2 web3].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user:, onchain_session:) ⇒ SessionContext

Returns a new instance of SessionContext.



26
27
28
29
# File 'app/models/session_context.rb', line 26

def initialize(user:, onchain_session:)
  @user = user
  @onchain_session = onchain_session
end

Instance Attribute Details

#userObject (readonly)

Returns the value of attribute user.



24
25
26
# File 'app/models/session_context.rb', line 24

def user
  @user
end

Instance Method Details

#addressObject

Primary wallet address (web3 preferred), or nil when logged out / wallet-less.



65
66
67
68
# File 'app/models/session_context.rb', line 65

def address
  return nil unless user.respond_to?(:solana_address)
  user.solana_address
end

#as_jsonObject



82
83
84
# File 'app/models/session_context.rb', line 82

def as_json(*)
  to_h
end

#guest?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'app/models/session_context.rb', line 37

def guest?
  mode == :guest
end

#logged_in?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'app/models/session_context.rb', line 49

def logged_in?
  !guest?
end

#modeObject

The canonical 3-way. Session-based — see class comment.



32
33
34
35
# File 'app/models/session_context.rb', line 32

def mode
  return :guest unless user
  @onchain_session ? :web3 : :web2
end

#phantom_linked?Boolean

Account-level fact, independent of ‘mode`: the account holds a self-custody (Phantom) wallet. A :web2-mode session can still be phantom_linked — that is exactly the “Phantom owner logged in by email” case.

Returns:

  • (Boolean)


56
57
58
# File 'app/models/session_context.rb', line 56

def phantom_linked?
  (user.respond_to?(:phantom_wallet?) && user.phantom_wallet?) || false
end

#to_hObject

Shape consumed by the client Alpine.store(‘session’). Kept deliberately cheap — DB/session columns only, never an on-chain RPC call.



72
73
74
75
76
77
78
79
80
# File 'app/models/session_context.rb', line 72

def to_h
  {
    loggedIn:      logged_in?,
    mode:          mode,
    phantomLinked: phantom_linked?,
    userId:        user_id,
    address:       address.to_s
  }
end

#user_idObject



60
61
62
# File 'app/models/session_context.rb', line 60

def user_id
  user&.id
end

#web2?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'app/models/session_context.rb', line 41

def web2?
  mode == :web2
end

#web3?Boolean

Returns:

  • (Boolean)


45
46
47
# File 'app/models/session_context.rb', line 45

def web3?
  mode == :web3
end