Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,34 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.7.1] - 2026-06-24

This version should add support to process new Gnoland testnet 13. Added support for Auth message
types, and the bank multi send should be supported.

### Added

- Feat(api): add new message types to the tx message route [e38c9f3](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/e38c9f38fe4b0a7285593196d89c140b29f71125)
- Feat(cli): add to setup db to init auth tables and multi send [1b56f5f](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/1b56f5f3832682d04457ca9b8300a6a0fdc06c5a)
- Feat(decoder): add convert to auth methods [72e2334](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/72e2334b44b2625e70ec3b863faf104c5f6ad3d2)
- Feat(sql_data_types): add schemas for the new auth msg types [0ecf0c7](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/0ecf0c7fed377b75f8532dbae7d39029a4521eb9)
- Feat(decoder): add auth msg types [32fb8df](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/32fb8df4c820a6d9a6c7782720194137aeb7bf87)
- Feat(timescaledb): add auth insert methods [33f4d34](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/33f4d340dc27fa31467625438fcdd266e07348b1)

### Changes

- Refac(timescaledb): move the GetAllBlockSigners to query_block.go [a4f9bf3](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/a4f9bf317c5da9bca5ff1abc4fb9bdebc144ed16)
- Refac(data_processor): add new auth types and partially move decoding [81ff897](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/81ff897728d48b4916c86aee79143ad2e15659b0)
- Refactor(decoder): refactor the decoder to use smaller fn per msg type [c71f39c](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/c71f39cbf4211f40e29193f39d2439506ba2628a)
- Deps: update gno to chain/test13 [f08460d](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/f08460d6a44dcf3cf437f8456f7c1ed6a85b0b65)

### Fixed

- Fix: add missing add address [f681153](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/f6811537e78ba1bcb9d46199a9938968b2cd7556)
- Fix(sql_data_types): fix chain_name to use enum type in database [ca36797](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/ca36797cfd6e92d3b9745ef0abe2f0ebd87551fc)
- Fix: add missing data to the create session [ac2130c](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/ac2130c71e40ad8bd435d49dc58624d06c27778e)
- Fix: dockerfile indexer.go path updated and force the toolcahin to auto [a04c48c](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/a04c48ca497a82565673900f90a6e0343232a1ba)
- Fix(ci): fix the release.yml to use correct path to indexer.go [61b96b3](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/61b96b3df53d342567fa8f46c69b63da31505312)

## [0.7.0] - 2026-06-14

Expand Down
58 changes: 53 additions & 5 deletions api/handlers/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ type MockDatabase struct {
blockSigners map[uint64]*database.BlockSigners
latestBlock *database.BlockData

bankSend map[string]*database.BankSend
msgCall map[string]*database.MsgCall
msgAddPackage map[string]*database.MsgAddPackage
msgRun map[string]*database.MsgRun
msgTypes map[string][]string
bankSend map[string]*database.BankSend
bankMultiSend map[string][]*database.BankMultiSendRow
msgCall map[string]*database.MsgCall
msgAddPackage map[string]*database.MsgAddPackage
msgRun map[string]*database.MsgRun
msgAuthCrSession map[string]*database.MsgAuthCrSession
msgAuthRvSession map[string]*database.MsgAuthRvSession
msgAuthRvAll map[string]*database.MsgAuthRvAllSessions
msgTypes map[string][]string

shouldError bool
errorMsg string
Expand Down Expand Up @@ -205,6 +209,50 @@ func (m *MockDatabase) GetMsgRun(ctx context.Context, txHash string, chainName s
return []*database.MsgRun{msgRun}, nil
}

func (m *MockDatabase) GetBankMultiSend(ctx context.Context, txHash string, chainName string) ([]*database.BankMultiSendRow, error) {
if m.shouldError {
return nil, m.simulatedError()
}
rows, ok := m.bankMultiSend[txHash]
if !ok {
return nil, notFoundErr("bank multi send not found")
}
return rows, nil
}

func (m *MockDatabase) GetMsgAuthCrSession(ctx context.Context, txHash string, chainName string) ([]*database.MsgAuthCrSession, error) {
if m.shouldError {
return nil, m.simulatedError()
}
msg, ok := m.msgAuthCrSession[txHash]
if !ok {
return nil, notFoundErr("auth create session not found")
}
return []*database.MsgAuthCrSession{msg}, nil
}

func (m *MockDatabase) GetMsgAuthRvSession(ctx context.Context, txHash string, chainName string) ([]*database.MsgAuthRvSession, error) {
if m.shouldError {
return nil, m.simulatedError()
}
msg, ok := m.msgAuthRvSession[txHash]
if !ok {
return nil, notFoundErr("auth revoke session not found")
}
return []*database.MsgAuthRvSession{msg}, nil
}

func (m *MockDatabase) GetMsgAuthRvAllSessions(ctx context.Context, txHash string, chainName string) ([]*database.MsgAuthRvAllSessions, error) {
if m.shouldError {
return nil, m.simulatedError()
}
msg, ok := m.msgAuthRvAll[txHash]
if !ok {
return nil, notFoundErr("auth revoke all sessions not found")
}
return []*database.MsgAuthRvAllSessions{msg}, nil
}

func (m *MockDatabase) GetTransactionsByRange(
ctx context.Context, chainName string, cursor string, limit uint64, direction database.Direction,
) ([]*database.Transaction, bool, error) {
Expand Down
4 changes: 4 additions & 0 deletions api/handlers/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,13 @@ type TransactionDbHandler interface {
) ([]*database.Transaction, error)
GetMsgTypes(ctx context.Context, txHash string, chainName string) ([]string, error)
GetBankSend(ctx context.Context, txHash string, chainName string) ([]*database.BankSend, error)
GetBankMultiSend(ctx context.Context, txHash string, chainName string) ([]*database.BankMultiSendRow, error)
GetMsgCall(ctx context.Context, txHash string, chainName string) ([]*database.MsgCall, error)
GetMsgAddPackage(ctx context.Context, txHash string, chainName string) ([]*database.MsgAddPackage, error)
GetMsgRun(ctx context.Context, txHash string, chainName string) ([]*database.MsgRun, error)
GetMsgAuthCrSession(ctx context.Context, txHash string, chainName string) ([]*database.MsgAuthCrSession, error)
GetMsgAuthRvSession(ctx context.Context, txHash string, chainName string) ([]*database.MsgAuthRvSession, error)
GetMsgAuthRvAllSessions(ctx context.Context, txHash string, chainName string) ([]*database.MsgAuthRvAllSessions, error)
GetTransactionsByRange(
ctx context.Context, chainName string, cursor string, limit uint64, direction database.Direction,
) ([]*database.Transaction, bool, error)
Expand Down
169 changes: 157 additions & 12 deletions api/handlers/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,35 @@ func (h *TransactionsHandler) GetTransactionMessage(
for _, msgType := range msgTypes {
switch msgType {
case "bank_msg_send":
if err := h.getBankSendResponse(ctx, msgType, txHashBase64, h.chainName, &response); err != nil {
if err := h.getBankSendResponse(ctx, msgType, txHashBase64, h.chainName, response); err != nil {
return nil, err
}
case "bank_msg_multi_send":
if err := h.getBankMultiSendResponse(ctx, msgType, txHashBase64, h.chainName, response); err != nil {
return nil, err
}
case "vm_msg_call":
if err := h.getMsgCallResponse(ctx, msgType, txHashBase64, h.chainName, &response); err != nil {
if err := h.getMsgCallResponse(ctx, msgType, txHashBase64, h.chainName, response); err != nil {
return nil, err
}
case "vm_msg_add_package":
if err := h.getMsgAddPackageResponse(ctx, msgType, txHashBase64, h.chainName, &response); err != nil {
if err := h.getMsgAddPackageResponse(ctx, msgType, txHashBase64, h.chainName, response); err != nil {
return nil, err
}
case "vm_msg_run":
if err := h.getMsgRunResponse(ctx, msgType, txHashBase64, h.chainName, &response); err != nil {
if err := h.getMsgRunResponse(ctx, msgType, txHashBase64, h.chainName, response); err != nil {
return nil, err
}
case "auth_msg_create_session":
if err := h.getMsgAuthCrSessionResponse(ctx, msgType, txHashBase64, h.chainName, response); err != nil {
return nil, err
}
case "auth_msg_revoke_session":
if err := h.getMsgAuthRvSessionResponse(ctx, msgType, txHashBase64, h.chainName, response); err != nil {
return nil, err
}
case "auth_msg_revoke_all_sessions":
if err := h.getMsgAuthRvAllSessionsResponse(ctx, msgType, txHashBase64, h.chainName, response); err != nil {
return nil, err
}
default:
Expand Down Expand Up @@ -331,15 +347,15 @@ func (h *TransactionsHandler) getMsgCallResponse(
msgType string,
txHash string,
chainName string,
response *map[int16]humatypes.TransactionMessage,
response map[int16]humatypes.TransactionMessage,
) error {
data, err := h.db.GetMsgCall(ctx, txHash, chainName)
if err != nil {
return internalError("GetMsgCall", err)
}
for _, d := range data {
index := d.MessageCounter
(*response)[index] = humatypes.TransactionMessage{
response[index] = humatypes.TransactionMessage{
MessageType: msgType,
TxHash: d.TxHash,
Timestamp: d.Timestamp,
Expand All @@ -361,15 +377,15 @@ func (h *TransactionsHandler) getMsgAddPackageResponse(
msgType string,
txHash string,
chainName string,
response *map[int16]humatypes.TransactionMessage,
response map[int16]humatypes.TransactionMessage,
) error {
data, err := h.db.GetMsgAddPackage(ctx, txHash, chainName)
if err != nil {
return internalError("GetMsgAddPackage", err)
}
for _, d := range data {
index := d.MessageCounter
(*response)[index] = humatypes.TransactionMessage{
response[index] = humatypes.TransactionMessage{
MessageType: msgType,
TxHash: d.TxHash,
Timestamp: d.Timestamp,
Expand All @@ -391,15 +407,15 @@ func (h *TransactionsHandler) getMsgRunResponse(
msgType string,
txHash string,
chainName string,
response *map[int16]humatypes.TransactionMessage,
response map[int16]humatypes.TransactionMessage,
) error {
data, err := h.db.GetMsgRun(ctx, txHash, chainName)
if err != nil {
return internalError("GetMsgRun", err)
}
for _, d := range data {
index := d.MessageCounter
(*response)[index] = humatypes.TransactionMessage{
response[index] = humatypes.TransactionMessage{
MessageType: msgType,
TxHash: d.TxHash,
Timestamp: d.Timestamp,
Expand All @@ -415,21 +431,150 @@ func (h *TransactionsHandler) getMsgRunResponse(
return nil
}

// Helper method that collects bank multi-send data from the database and adds it to the response.
// Rows are aggregated by message_counter: direction=true rows become Outputs, direction=false become Inputs.
func (h *TransactionsHandler) getBankMultiSendResponse(
ctx context.Context,
msgType string,
txHash string,
chainName string,
response map[int16]humatypes.TransactionMessage,
) error {
data, err := h.db.GetBankMultiSend(ctx, txHash, chainName)
if err != nil {
return internalError("GetBankMultiSend", err)
}
type agg struct {
base humatypes.TransactionMessage
inputs []humatypes.MultiSendEntry
outputs []humatypes.MultiSendEntry
}
byCounter := make(map[int16]*agg)
for _, d := range data {
idx := d.MessageCounter
if _, ok := byCounter[idx]; !ok {
byCounter[idx] = &agg{
base: humatypes.TransactionMessage{
MessageType: msgType,
TxHash: d.TxHash,
Timestamp: d.Timestamp,
Signers: d.Signers,
},
}
}
entry := humatypes.MultiSendEntry{Address: d.Address, Coins: d.Coins}
if d.Direction {
byCounter[idx].outputs = append(byCounter[idx].outputs, entry)
} else {
byCounter[idx].inputs = append(byCounter[idx].inputs, entry)
}
}
for idx, a := range byCounter {
msg := a.base
msg.Inputs = a.inputs
msg.Outputs = a.outputs
response[idx] = msg
}
return nil
}

// Helper method that collects auth create-session data from the database and adds it to the response
func (h *TransactionsHandler) getMsgAuthCrSessionResponse(
ctx context.Context,
msgType string,
txHash string,
chainName string,
response map[int16]humatypes.TransactionMessage,
) error {
data, err := h.db.GetMsgAuthCrSession(ctx, txHash, chainName)
if err != nil {
return internalError("GetMsgAuthCrSession", err)
}
for _, d := range data {
index := d.MessageCounter
expiresAt := d.ExpiresAt
spendPeriod := d.SpendPeriod
response[index] = humatypes.TransactionMessage{
MessageType: msgType,
TxHash: d.TxHash,
Timestamp: d.Timestamp,
Signers: d.Signers,
Creator: d.Creator,
SessionKey: d.SessionKey,
ExpiresAt: &expiresAt,
SpendLimit: d.SpendLimit,
SpendPeriod: &spendPeriod,
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
return nil
}

// Helper method that collects auth revoke-session data from the database and adds it to the response
func (h *TransactionsHandler) getMsgAuthRvSessionResponse(
ctx context.Context,
msgType string,
txHash string,
chainName string,
response map[int16]humatypes.TransactionMessage,
) error {
data, err := h.db.GetMsgAuthRvSession(ctx, txHash, chainName)
if err != nil {
return internalError("GetMsgAuthRvSession", err)
}
for _, d := range data {
index := d.MessageCounter
response[index] = humatypes.TransactionMessage{
MessageType: msgType,
TxHash: d.TxHash,
Timestamp: d.Timestamp,
Signers: d.Signers,
Creator: d.Creator,
SessionKey: d.SessionKey,
}
}
return nil
}

// Helper method that collects auth revoke-all-sessions data from the database and adds it to the response
func (h *TransactionsHandler) getMsgAuthRvAllSessionsResponse(
ctx context.Context,
msgType string,
txHash string,
chainName string,
response map[int16]humatypes.TransactionMessage,
) error {
data, err := h.db.GetMsgAuthRvAllSessions(ctx, txHash, chainName)
if err != nil {
return internalError("GetMsgAuthRvAllSessions", err)
}
for _, d := range data {
index := d.MessageCounter
response[index] = humatypes.TransactionMessage{
MessageType: msgType,
TxHash: d.TxHash,
Timestamp: d.Timestamp,
Signers: d.Signers,
Creator: d.Creator,
}
}
return nil
}

// Helper method that collects bank send data from the database and adds it to the response
func (h *TransactionsHandler) getBankSendResponse(
ctx context.Context,
msgType string,
txHash string,
chainName string,
response *map[int16]humatypes.TransactionMessage,
response map[int16]humatypes.TransactionMessage,
) error {
data, err := h.db.GetBankSend(ctx, txHash, chainName)
if err != nil {
return internalError("GetBankSend", err)
}
for _, d := range data {
index := d.MessageCounter
(*response)[index] = humatypes.TransactionMessage{
response[index] = humatypes.TransactionMessage{
MessageType: msgType,
TxHash: d.TxHash,
Timestamp: d.Timestamp,
Expand Down
Loading
Loading