gcx/backend/services/chain-indexer/internal/infrastructure/postgres/transaction_repository.go

106 lines
3.2 KiB
Go

package postgres
import (
"context"
"fmt"
"time"
"github.com/genex/chain-indexer/internal/domain/entity"
"github.com/genex/chain-indexer/internal/domain/repository"
"gorm.io/gorm"
)
// Compile-time check: PostgresTransactionRepository implements repository.TransactionRepository.
var _ repository.TransactionRepository = (*PostgresTransactionRepository)(nil)
// chainTxModel is the GORM persistence model for the chain_transactions table.
type chainTxModel struct {
Hash string `gorm:"column:hash;primaryKey"`
BlockHeight int64 `gorm:"column:block_height;not null"`
FromAddr string `gorm:"column:from_addr;not null"`
ToAddr string `gorm:"column:to_addr;not null"`
Amount string `gorm:"column:amount;not null;default:0"`
Status string `gorm:"column:status;not null;default:confirmed"`
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime"`
}
func (chainTxModel) TableName() string { return "chain_transactions" }
func (m *chainTxModel) toEntity() *entity.ChainTransaction {
return &entity.ChainTransaction{
Hash: m.Hash,
BlockHeight: m.BlockHeight,
From: m.FromAddr,
To: m.ToAddr,
Amount: m.Amount,
Status: m.Status,
Timestamp: m.CreatedAt,
}
}
func chainTxFromEntity(e *entity.ChainTransaction) *chainTxModel {
return &chainTxModel{
Hash: e.Hash,
BlockHeight: e.BlockHeight,
FromAddr: e.From,
ToAddr: e.To,
Amount: e.Amount,
Status: e.Status,
}
}
// PostgresTransactionRepository is the GORM-backed implementation of
// repository.TransactionRepository.
type PostgresTransactionRepository struct {
db *gorm.DB
}
// NewPostgresTransactionRepository creates a new repository backed by PostgreSQL via GORM.
func NewPostgresTransactionRepository(db *gorm.DB) *PostgresTransactionRepository {
return &PostgresTransactionRepository{db: db}
}
func (r *PostgresTransactionRepository) Save(ctx context.Context, tx *entity.ChainTransaction) error {
if tx == nil {
return fmt.Errorf("transaction must not be nil")
}
model := chainTxFromEntity(tx)
return r.db.WithContext(ctx).Save(model).Error
}
func (r *PostgresTransactionRepository) SaveBatch(ctx context.Context, txs []*entity.ChainTransaction) error {
if len(txs) == 0 {
return nil
}
models := make([]chainTxModel, len(txs))
for i, tx := range txs {
models[i] = *chainTxFromEntity(tx)
}
return r.db.WithContext(ctx).Save(&models).Error
}
func (r *PostgresTransactionRepository) FindByHash(ctx context.Context, hash string) (*entity.ChainTransaction, error) {
var model chainTxModel
err := r.db.WithContext(ctx).Where("hash = ?", hash).First(&model).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, err
}
return model.toEntity(), nil
}
func (r *PostgresTransactionRepository) FindByBlock(ctx context.Context, blockHeight int64) ([]*entity.ChainTransaction, error) {
var models []chainTxModel
err := r.db.WithContext(ctx).Where("block_height = ?", blockHeight).Find(&models).Error
if err != nil {
return nil, err
}
result := make([]*entity.ChainTransaction, len(models))
for i := range models {
result[i] = models[i].toEntity()
}
return result, nil
}