Skip to content

Commit 588b6be

Browse files
committed
Listen to lockers by mint, not dbc pool
1 parent 922d10a commit 588b6be

1 file changed

Lines changed: 51 additions & 64 deletions

File tree

‎solana/indexer/locker/indexer.go‎

Lines changed: 51 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99

1010
"api.audius.co/database"
1111
"api.audius.co/solana/indexer/common"
12-
"api.audius.co/solana/spl/programs/meteora_dbc"
1312
"api.audius.co/solana/spl/programs/meteora_locker"
1413
bin "github.com/gagliardetto/binary"
1514
"github.com/gagliardetto/solana-go"
@@ -22,8 +21,8 @@ import (
2221

2322
const (
2423
NAME = "LockerIndexer"
25-
MAX_POOLS_PER_SUBSCRIPTION = 10000 // Arbitrary
26-
NOTIFICATION_NAME = "dbc_pools_changed"
24+
MAX_MINTS_PER_SUBSCRIPTION = 10000 // Arbitrary
25+
NOTIFICATION_NAME = "artist_coins_changed"
2726
)
2827

2928
type Indexer struct {
@@ -145,32 +144,27 @@ func (d *Indexer) Start(ctx context.Context) {
145144
}
146145

147146
func (d *Indexer) subscribe(ctx context.Context) ([]common.GrpcClient, error) {
148-
// Fetch all DBC pools
149-
pools, err := getAllDbcPools(ctx, d.pool)
150-
if err != nil {
151-
return nil, fmt.Errorf("failed to fetch DBC pools: %w", err)
152-
}
153-
154-
d.logger.Info("subscribing to dbc pools", zap.Int("numPools", len(pools)))
155-
156-
// Create gRPC clients for each subscription batch
157-
var grpcClients []common.GrpcClient
158-
159-
// Subscribe in batches to avoid exceeding limits
160-
for i := 0; i < len(pools); i += MAX_POOLS_PER_SUBSCRIPTION {
161-
end := i + MAX_POOLS_PER_SUBSCRIPTION
162-
if end > len(pools) {
163-
end = len(pools)
147+
done := false
148+
page := 0
149+
pageSize := MAX_MINTS_PER_SUBSCRIPTION
150+
grpcClients := make([]common.GrpcClient, 0)
151+
total := 0
152+
for !done {
153+
mints, err := common.GetArtistCoinMints(ctx, d.pool, pageSize, page*pageSize)
154+
if err != nil {
155+
return nil, fmt.Errorf("failed to get artist coins: %w", err)
156+
}
157+
if len(mints) == 0 {
158+
d.logger.Info("no more artist coins to subscribe to, exiting")
159+
return grpcClients, nil
160+
}
161+
total += len(mints)
162+
d.logger.Debug("subscribing to artist coins...", zap.Int("count", len(mints)))
163+
subscription, err := d.makeSubscriptionRequest(ctx, mints)
164+
if err != nil {
165+
return nil, fmt.Errorf("failed to make mint subscription request: %w", err)
164166
}
165-
batch := pools[i:end]
166-
167-
d.logger.Info("creating locker subscription batch",
168-
zap.Int("startIndex", i),
169-
zap.Int("endIndex", end),
170-
zap.Int("batchSize", len(batch)),
171-
)
172167

173-
subscription := d.makeSubscriptionRequest(ctx, batch)
174168
handleMessage := func(ctx context.Context, update *pb.SubscribeUpdate) {
175169
err := d.HandleUpdate(ctx, update)
176170
if err != nil {
@@ -182,47 +176,56 @@ func (d *Indexer) subscribe(ctx context.Context) ([]common.GrpcClient, error) {
182176
}
183177
}
184178

185-
client := common.NewGrpcClient(d.grpcConfig)
186-
err := client.Subscribe(ctx, subscription, handleMessage, func(err error) {
187-
d.logger.Error("subscription error", zap.Error(err))
179+
grpcClient := common.NewGrpcClient(d.grpcConfig)
180+
err = grpcClient.Subscribe(ctx, subscription, handleMessage, func(err error) {
181+
d.logger.Error("error in token subscription", zap.Error(err))
188182
})
189183
if err != nil {
190-
return nil, fmt.Errorf("failed to start subscription: %w", err)
184+
return nil, fmt.Errorf("failed to subscribe to artist coins: %w", err)
191185
}
186+
grpcClients = append(grpcClients, grpcClient)
192187

193-
d.logger.Info("subscribed to locker programs",
194-
zap.Int("numPools", len(batch)),
195-
)
196-
197-
grpcClients = append(grpcClients, client)
188+
if len(mints) < pageSize {
189+
done = true
190+
}
191+
page++
198192
}
199-
193+
d.logger.Info("subscribed to artist coins", zap.Int("count", total))
200194
return grpcClients, nil
201195
}
202196

203197
// Makes a subscription to the relevant locker accounts and adds slot checkpointing
204-
func (d *Indexer) makeSubscriptionRequest(ctx context.Context, pools []string) *pb.SubscribeRequest {
198+
func (d *Indexer) makeSubscriptionRequest(ctx context.Context, mints []string) (*pb.SubscribeRequest, error) {
205199
commitment := pb.CommitmentLevel_CONFIRMED
206200
subscription := &pb.SubscribeRequest{
207201
Commitment: &commitment,
208202
}
209203

210204
// Listen to all lockers
211205
subscription.Accounts = make(map[string]*pb.SubscribeRequestFilterAccounts)
212-
subscription.Accounts["lockers"] = &pb.SubscribeRequestFilterAccounts{
213-
Owner: []string{meteora_locker.ProgramID.String()},
214-
Account: make([]string, len(pools)),
215-
}
216-
for i, pool := range pools {
217-
baseKey := meteora_dbc.DeriveBaseKeyForEscrow(solana.MustPublicKeyFromBase58(pool))
218-
escrowKey := meteora_dbc.DeriveEscrow(baseKey)
219-
subscription.Accounts["lockers"].Account[i] = escrowKey.String()
206+
for _, mint := range mints {
207+
accountFilter := pb.SubscribeRequestFilterAccounts{
208+
Owner: []string{meteora_locker.ProgramID.String()},
209+
Filters: []*pb.SubscribeRequestFilterAccountsFilter{
210+
{
211+
Filter: &pb.SubscribeRequestFilterAccountsFilter_Memcmp{
212+
Memcmp: &pb.SubscribeRequestFilterAccountsFilterMemcmp{
213+
Offset: 8 + 32, // Discriminator + recipient pubkey
214+
Data: &pb.SubscribeRequestFilterAccountsFilterMemcmp_Base58{
215+
Base58: mint,
216+
},
217+
},
218+
},
219+
},
220+
},
221+
}
222+
subscription.Accounts[mint] = &accountFilter
220223
}
221224

222225
// Ensure this subscription has a checkpoint
223226
checkpointId, fromSlot, err := common.EnsureCheckpoint(ctx, NAME, d.pool, d.rpcClient, subscription, d.logger)
224227
if err != nil {
225-
d.logger.Error("failed to ensure checkpoint", zap.Error(err))
228+
return nil, fmt.Errorf("failed to set from slot: %w", err)
226229
}
227230

228231
// Set the from slot for the subscription
@@ -232,7 +235,7 @@ func (d *Indexer) makeSubscriptionRequest(ctx context.Context, pools []string) *
232235
subscription.Slots = make(map[string]*pb.SubscribeRequestFilterSlots)
233236
subscription.Slots[checkpointId] = &pb.SubscribeRequestFilterSlots{}
234237

235-
return subscription
238+
return subscription, nil
236239
}
237240

238241
func (d *Indexer) HandleUpdate(ctx context.Context, update *pb.SubscribeUpdate) error {
@@ -287,19 +290,3 @@ func processLockerAccountUpdate(
287290

288291
return nil
289292
}
290-
291-
func getAllDbcPools(ctx context.Context, db database.DBTX) ([]string, error) {
292-
sql := `
293-
SELECT account
294-
FROM sol_meteora_dbc_pools
295-
`
296-
rows, err := db.Query(ctx, sql)
297-
if err != nil {
298-
return nil, fmt.Errorf("failed to query dbc pools: %w", err)
299-
}
300-
pools, err := pgx.CollectRows(rows, pgx.RowTo[string])
301-
if err != nil {
302-
return nil, fmt.Errorf("failed to collect dbc pools: %w", err)
303-
}
304-
return pools, nil
305-
}

0 commit comments

Comments
 (0)