Documentation
¶
Overview ¶
Package transaction is the business-logic layer for the platform's transaction ledger — the durable record of every money movement, whether it settled on the Stellar network, through an external provider, or internally. Service wraps the transaction repository and adds validation, uniqueness, and status-transition rules.
Build a Service with NewService. It records transactions (Create, BatchCreate), looks them up by ID, Stellar hash, external ID, loan, user, or status, and applies updates. List operations are paginated through services.Pagination, which the service clamps (default page size 10, capped at 100). Requests and responses are the DTOs in dto.go; failures are the sentinel errors in errors.go, which handlers map onto HTTP status codes.
What a record holds ¶
Each transaction carries a type and a category — on-chain, off-chain, or internal — an amount and asset, and optional links to a user, account, or loan. Settlement details hang off the same row: the Stellar hash, ledger, and status for on-chain work, or the external ID, provider, and status for an off-ramp provider. New transactions default to the on-chain category and open in the pending status.
Status lifecycle ¶
A transaction moves from pending to submitted, then to success or failed. A failed transaction may return to pending for a retry; pending may also be cancelled. success and cancelled are terminal — Update refuses to modify a transaction in either state, and every other status change is checked against the transition table, rejecting an illegal move with ErrInvalidStatusTransition.
Uniqueness ¶
A Stellar hash, when supplied, must be unique: Create rejects a duplicate with ErrStellarHashAlreadyExists, so one on-chain payment cannot be recorded twice. A genuine retry carries a different hash and is therefore still recordable.
External IDs are deliberately not unique. One anchor transaction settles as several legs — a MoneyGram cash pickup writes an anchor_transfer, an off_ramp and possibly a refund — and all of them carry the provider's request ID, which is what makes the reference reverse-lookupable when a provider quotes it. Uniqueness for the off-chain legs is enforced instead by a partial unique index on (loan_id, tx_type), stating the real invariant: one fiat payout per loan.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // Resource not found errors ErrTransactionNotFound = errors.New("transaction not found") // Conflict errors ErrStellarHashAlreadyExists = errors.New("stellar transaction hash already registered") // Business logic errors ErrInvalidStatusTransition = errors.New("invalid status transition") ErrCannotModifyTransaction = errors.New("cannot modify completed transaction") // Validation errors ErrInvalidInput = errors.New("invalid input") ErrInvalidTxType = errors.New("invalid transaction type") ErrInvalidAmount = errors.New("invalid amount") ErrInvalidStatus = errors.New("invalid transaction status") )
Transaction service specific errors
Functions ¶
This section is empty.
Types ¶
type CreateTransactionRequest ¶
type CreateTransactionRequest struct {
UserID *string `json:"user_id,omitempty"`
AccountID *string `json:"account_id,omitempty"`
LoanID *string `json:"loan_id,omitempty"`
TxType string `json:"tx_type" validate:"required"`
Amount int64 `json:"amount" validate:"required,gt=0"`
Asset string `json:"asset" validate:"required"`
StellarTxHash *string `json:"stellar_tx_hash,omitempty"`
StellarLedger *int64 `json:"stellar_ledger,omitempty"`
ContractID *string `json:"contract_id,omitempty"`
ContractFunction *string `json:"contract_function,omitempty"`
ExternalID *string `json:"external_id,omitempty"`
ExternalProvider *string `json:"external_provider,omitempty"`
Description *string `json:"description,omitempty"`
Metadata *string `json:"metadata,omitempty"`
}
CreateTransactionRequest represents the request to create a new transaction
type Service ¶
type Service interface {
// Transaction management
Create(ctx context.Context, req CreateTransactionRequest) (*TransactionResponse, error)
BatchCreate(ctx context.Context, reqs []CreateTransactionRequest) ([]*TransactionResponse, error)
GetByID(ctx context.Context, id string) (*TransactionResponse, error)
GetByStellarHash(ctx context.Context, txHash string) (*TransactionResponse, error)
ListByExternalID(ctx context.Context, externalID string) ([]*TransactionResponse, error)
GetByLoanIDAndType(ctx context.Context, loanID, txType string) (*TransactionResponse, error)
GetByLoanID(ctx context.Context, loanID string, pagination services.Pagination) (*services.PaginatedResponse[TransactionResponse], error)
GetByUserID(ctx context.Context, userID string, pagination services.Pagination) (*services.PaginatedResponse[TransactionResponse], error)
GetByStatus(ctx context.Context, status string, pagination services.Pagination) (*services.PaginatedResponse[TransactionResponse], error)
Update(ctx context.Context, id string, req UpdateTransactionRequest) (*TransactionResponse, error)
}
Service defines the interface for transaction business logic operations
func NewService ¶
func NewService(repo repository.TransactionRepository) Service
NewService creates a new transaction service instance
type TransactionFilters ¶
type TransactionFilters struct {
UserID string `json:"user_id,omitempty"`
LoanID string `json:"loan_id,omitempty"`
Status string `json:"status,omitempty"`
TxType string `json:"tx_type,omitempty"`
}
TransactionFilters represents filters for listing transactions
type TransactionResponse ¶
type TransactionResponse struct {
ID string `json:"id"`
UserID *string `json:"user_id,omitempty"`
AccountID *string `json:"account_id,omitempty"`
LoanID *string `json:"loan_id,omitempty"`
TxType string `json:"tx_type"`
// TxCategory is derived from TxType, not stored. See models.TxCategoryFor.
TxCategory string `json:"tx_category"`
Amount int64 `json:"amount"`
Asset string `json:"asset"`
StellarTxHash *string `json:"stellar_tx_hash,omitempty"`
StellarLedger *int64 `json:"stellar_ledger,omitempty"`
ContractID *string `json:"contract_id,omitempty"`
ContractFunction *string `json:"contract_function,omitempty"`
ExternalID *string `json:"external_id,omitempty"`
ExternalProvider *string `json:"external_provider,omitempty"`
ExternalStatus *string `json:"external_status,omitempty"`
Description *string `json:"description,omitempty"`
Metadata *string `json:"metadata,omitempty"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
TransactionResponse represents the response containing transaction information
type UpdateTransactionRequest ¶
type UpdateTransactionRequest struct {
StellarTxHash *string `json:"stellar_tx_hash,omitempty"`
StellarLedger *int64 `json:"stellar_ledger,omitempty"`
ExternalID *string `json:"external_id,omitempty"`
ExternalProvider *string `json:"external_provider,omitempty"`
ExternalStatus *string `json:"external_status,omitempty"`
Status *string `json:"status,omitempty"`
Description *string `json:"description,omitempty"`
Metadata *string `json:"metadata,omitempty"`
}
UpdateTransactionRequest represents the request to update a transaction