106 lines
3.2 KiB
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
|
|
}
|