Skip to content

Commit 2a2bddc

Browse files
authored
feat: [Indexer] implemented pg store for indexer (#164)
* feat: indexer fetcher * feat: indexer refactored * improved impl * store modified * removed doc * feat: indexer http service * feat: only applied private http * lint fixed * removed unused middleware * feat: pg implementation for indexer store * ordering fix * lint fix and improvements * added negetive balance check
1 parent 1de0d8a commit 2a2bddc

8 files changed

Lines changed: 1340 additions & 0 deletions

File tree

pkg/indexer/store/model.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package store
2+
3+
import (
4+
"time"
5+
6+
"github.com/uptrace/bun"
7+
8+
"github.com/chainsafe/canton-middleware/pkg/indexer"
9+
)
10+
11+
// EventDao maps to the 'indexer_events' table.
12+
// ContractID is the idempotency key — one row per TokenTransferEvent contract.
13+
type EventDao struct {
14+
bun.BaseModel `bun:"table:indexer_events"`
15+
ContractID string `bun:",pk,type:varchar(255)"`
16+
InstrumentID string `bun:",notnull,type:varchar(255)"`
17+
InstrumentAdmin string `bun:",notnull,type:varchar(255)"`
18+
Issuer string `bun:",notnull,type:varchar(255)"`
19+
EventType string `bun:",notnull,type:varchar(20)"`
20+
Amount string `bun:",notnull,type:text"`
21+
FromPartyID *string `bun:",type:varchar(255)"`
22+
ToPartyID *string `bun:",type:varchar(255)"`
23+
ExternalTxID *string `bun:",type:varchar(255)"`
24+
ExternalAddress *string `bun:",type:varchar(255)"`
25+
Fingerprint *string `bun:",type:varchar(255)"`
26+
TxID string `bun:",notnull,type:varchar(255)"`
27+
LedgerOffset int64 `bun:",notnull"`
28+
Timestamp time.Time `bun:",notnull"`
29+
EffectiveTime time.Time `bun:",notnull"`
30+
}
31+
32+
// TokenDao maps to the 'indexer_tokens' table.
33+
// The composite key (InstrumentAdmin, InstrumentID) uniquely identifies a token.
34+
type TokenDao struct {
35+
bun.BaseModel `bun:"table:indexer_tokens"`
36+
InstrumentAdmin string `bun:",pk,type:varchar(255)"`
37+
InstrumentID string `bun:",pk,type:varchar(255)"`
38+
Issuer string `bun:",notnull,type:varchar(255)"`
39+
TotalSupply string `bun:",notnull,type:text,default:'0'"`
40+
HolderCount int64 `bun:",notnull,default:0"`
41+
FirstSeenOffset int64 `bun:",notnull"`
42+
FirstSeenAt time.Time `bun:",notnull"`
43+
}
44+
45+
// BalanceDao maps to the 'indexer_balances' table.
46+
// The composite key (PartyID, InstrumentAdmin, InstrumentID) is unique per holding.
47+
type BalanceDao struct {
48+
bun.BaseModel `bun:"table:indexer_balances"`
49+
PartyID string `bun:",pk,type:varchar(255)"`
50+
InstrumentAdmin string `bun:",pk,type:varchar(255)"`
51+
InstrumentID string `bun:",pk,type:varchar(255)"`
52+
Amount string `bun:",notnull,type:text"`
53+
}
54+
55+
// OffsetDao maps to the 'indexer_offsets' table.
56+
// A single row (ID=1) holds the latest persisted ledger offset.
57+
type OffsetDao struct {
58+
bun.BaseModel `bun:"table:indexer_offsets"`
59+
ID int `bun:",pk,default:1"`
60+
LedgerOffset int64 `bun:",notnull,default:0"`
61+
}
62+
63+
func toEventDao(e *indexer.ParsedEvent) *EventDao {
64+
return &EventDao{
65+
ContractID: e.ContractID,
66+
InstrumentID: e.InstrumentID,
67+
InstrumentAdmin: e.InstrumentAdmin,
68+
Issuer: e.Issuer,
69+
EventType: string(e.EventType),
70+
Amount: e.Amount,
71+
FromPartyID: e.FromPartyID,
72+
ToPartyID: e.ToPartyID,
73+
ExternalTxID: e.ExternalTxID,
74+
ExternalAddress: e.ExternalAddress,
75+
Fingerprint: e.Fingerprint,
76+
TxID: e.TxID,
77+
LedgerOffset: e.LedgerOffset,
78+
Timestamp: e.Timestamp,
79+
EffectiveTime: e.EffectiveTime,
80+
}
81+
}
82+
83+
func fromEventDao(d *EventDao) *indexer.ParsedEvent {
84+
return &indexer.ParsedEvent{
85+
ContractID: d.ContractID,
86+
InstrumentID: d.InstrumentID,
87+
InstrumentAdmin: d.InstrumentAdmin,
88+
Issuer: d.Issuer,
89+
EventType: indexer.EventType(d.EventType),
90+
Amount: d.Amount,
91+
FromPartyID: d.FromPartyID,
92+
ToPartyID: d.ToPartyID,
93+
ExternalTxID: d.ExternalTxID,
94+
ExternalAddress: d.ExternalAddress,
95+
Fingerprint: d.Fingerprint,
96+
TxID: d.TxID,
97+
LedgerOffset: d.LedgerOffset,
98+
Timestamp: d.Timestamp,
99+
EffectiveTime: d.EffectiveTime,
100+
}
101+
}
102+
103+
func fromTokenDao(d *TokenDao) *indexer.Token {
104+
return &indexer.Token{
105+
InstrumentAdmin: d.InstrumentAdmin,
106+
InstrumentID: d.InstrumentID,
107+
Issuer: d.Issuer,
108+
TotalSupply: d.TotalSupply,
109+
HolderCount: d.HolderCount,
110+
FirstSeenOffset: d.FirstSeenOffset,
111+
FirstSeenAt: d.FirstSeenAt,
112+
}
113+
}
114+
115+
func fromBalanceDao(d *BalanceDao) *indexer.Balance {
116+
return &indexer.Balance{
117+
PartyID: d.PartyID,
118+
InstrumentAdmin: d.InstrumentAdmin,
119+
InstrumentID: d.InstrumentID,
120+
Amount: d.Amount,
121+
}
122+
}

0 commit comments

Comments
 (0)