Skip to content

Commit fe05114

Browse files
Pass solana wallet via user context for all track endpoints (#741)
## Summary - Moves solana wallet from `TracksParams.SolanaWallet` to the Go context, so every endpoint that fetches tracks gets wallet-based token gate checks automatically - Middleware now calls `c.SetUserContext(context.WithValue(...))` alongside `c.Locals()` - `TracksKeyed` reads the wallet from `ctx.Value("solanaWallet")` instead of `arg.SolanaWallet` - Removes per-endpoint wiring (previously only `v1_track_stream` passed it through) ## Test plan - [ ] Wallet-only auth: connect Solana wallet, track listing shows "Access granted" for coin-gated tracks - [ ] OAuth auth: sign in with Audius, access checks still work via `sol_user_balances` - [ ] Stream endpoint still works with wallet auth - [ ] No regression on unauthenticated track listing 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 33c4e54 commit fe05114

5 files changed

Lines changed: 17 additions & 25 deletions

File tree

api/dbv1/parallel.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ func (q *Queries) Parallel(ctx context.Context, arg ParallelParams) (*ParallelRe
4343
var err error
4444
trackMap, err = q.TracksKeyed(ctx, TracksParams{
4545
GetTracksParams: GetTracksParams{
46-
Ids: arg.TrackIds,
47-
MyID: arg.MyID,
48-
AuthedWallet: arg.AuthedWallet,
46+
Ids: arg.TrackIds,
47+
MyID: arg.MyID,
48+
AuthedWallet: arg.AuthedWallet,
4949
},
5050
})
5151
return err

api/dbv1/tracks.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010

1111
type TracksParams struct {
1212
GetTracksParams
13-
SolanaWallet string
1413
}
1514

1615
// Track is the standard track type containing all track data
@@ -35,7 +34,7 @@ type Track struct {
3534
}
3635

3736
func (q *Queries) TracksKeyed(ctx context.Context, arg TracksParams) (map[int32]Track, error) {
38-
rawTracks, err := q.GetTracks(ctx, GetTracksParams(arg.GetTracksParams))
37+
rawTracks, err := q.GetTracks(ctx, arg.GetTracksParams)
3938
if err != nil {
4039
return nil, err
4140
}
@@ -84,8 +83,9 @@ func (q *Queries) TracksKeyed(ctx context.Context, arg TracksParams) (map[int32]
8483
userPtrMap[id] = &userCopy
8584
}
8685

87-
// Get bulk access for all tracks
88-
accessMap, err := q.GetBulkTrackAccess(ctx, arg.MyID.(int32), trackPtrs, userPtrMap, arg.SolanaWallet)
86+
// Read solana wallet from context (set by middleware) for token gate checks
87+
solanaWallet, _ := ctx.Value("solanaWallet").(string)
88+
accessMap, err := q.GetBulkTrackAccess(ctx, arg.MyID.(int32), trackPtrs, userPtrMap, solanaWallet)
8989
if err != nil {
9090
return nil, err
9191
}

api/solana_wallet_middleware.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
package api
22

33
import (
4+
"context"
45
"crypto/ed25519"
56

67
"github.com/gofiber/fiber/v2"
78
"github.com/mr-tron/base58"
89
"go.uber.org/zap"
910
)
1011

12+
// SolanaWalletCtxKey is the context key used to pass a verified Solana wallet
13+
// from the HTTP middleware to the database layer.
14+
const SolanaWalletCtxKey = "solanaWallet"
15+
1116
// solanaWalletMiddleware verifies Solana wallet signatures from request headers.
12-
// If the X-Solana-Wallet, X-Solana-Message, and X-Solana-Signature headers are
13-
// present and valid, the verified wallet public key is stored in c.Locals("solanaWallet").
17+
// If valid, the verified wallet public key is set on the Go context via SolanaWalletCtxKey.
1418
// If headers are absent, the middleware is a no-op. If present but invalid, returns 401.
1519
func (app *ApiServer) solanaWalletMiddleware(c *fiber.Ctx) error {
1620
wallet := c.Get("X-Solana-Wallet")
@@ -48,14 +52,6 @@ func (app *ApiServer) solanaWalletMiddleware(c *fiber.Ctx) error {
4852
}
4953

5054
app.logger.Debug("solanaWalletMiddleware: verified", zap.String("wallet", wallet))
51-
c.Locals("solanaWallet", wallet)
55+
c.SetUserContext(context.WithValue(c.UserContext(), SolanaWalletCtxKey, wallet))
5256
return c.Next()
5357
}
54-
55-
// tryGetSolanaWallet returns the verified Solana wallet from context, or "" if not set.
56-
func (app *ApiServer) tryGetSolanaWallet(c *fiber.Ctx) string {
57-
if w, ok := c.Locals("solanaWallet").(string); ok {
58-
return w
59-
}
60-
return ""
61-
}

api/solana_wallet_middleware_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ func TestSolanaWalletMiddleware(t *testing.T) {
1818
var capturedWallet string
1919
testApp := fiber.New()
2020
testApp.Get("/", app.solanaWalletMiddleware, func(c *fiber.Ctx) error {
21-
capturedWallet = app.tryGetSolanaWallet(c)
21+
if w, ok := c.UserContext().Value(SolanaWalletCtxKey).(string); ok {
22+
capturedWallet = w
23+
}
2224
return c.SendStatus(fiber.StatusOK)
2325
})
2426

api/v1_track_stream.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@ func (app *ApiServer) v1TrackStream(c *fiber.Ctx) error {
1818
},
1919
}
2020

21-
// If a verified Solana wallet is present, pass it through so
22-
// GetBulkTrackAccess can check token gate balances for it.
23-
if solWallet := app.tryGetSolanaWallet(c); solWallet != "" {
24-
params.SolanaWallet = solWallet
25-
}
26-
2721
tracks, err := app.queries.Tracks(c.Context(), params)
2822
if err != nil {
2923
return err

0 commit comments

Comments
 (0)