Documentation
¶
Overview ¶
Copyright 2024 Blnk Finance Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2026 LedgerForge Contributors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2024 Blnk Finance Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2024 Blnk Finance Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2024 Blnk Finance Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2024 Blnk Finance Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2024 Blnk Finance Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2024 Blnk Finance Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2024 Blnk Finance Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Index ¶
- Constants
- func ApplyPrecision(transaction *Transaction) *big.Int
- func ApplyPrecisionChecked(transaction *Transaction) (*big.Int, error)
- func ApplyPrecisionWithDBLookup(transaction *Transaction, db *sql.DB) *big.Int
- func ApplyPrecisionWithDBLookupChecked(transaction *Transaction, db *sql.DB) (*big.Int, error)
- func ApplyRate(preciseAmount *big.Int, rate float64) *big.Int
- func CalculateDistributionsPrecise(ctx context.Context, totalPreciseAmount *big.Int, distributions []Distribution, ...) (map[string]*big.Int, error)
- func CanonicalChainV2(prevHash string, r ChainRow) []byte
- func CanonicalChainV3(prevHash string, r ChainRow) []byte
- func ComputeChainHash(prevHash string, r ChainRow) string
- func ComputeChainHashVersion(version int, prevHash string, r ChainRow) (string, error)
- func DecodeTransactionMetadata(data []byte, t *Transaction) error
- func GenerateKey() (string, error)
- func GenerateUUIDWithSuffix(module string) string
- func Int64ToBigInt(value int64) *big.Int
- func ParseAmount(amount string, precision float64) (*big.Int, error)
- func PrecisionBankersRound(num float64, precision float64) float64
- func RefundReference(originalTransactionID string) string
- func UpdateBalances(transaction *Transaction, source, destination *Balance) error
- func ValidateCustomerTransactionMetadata(metadata map[string]interface{}) error
- func ValidatePrecision(precision float64) error
- type APIKey
- type Account
- type AlertCondition
- type Balance
- func (balance *Balance) Clone() *Balance
- func (balance *Balance) CommitInflightCredit(transaction *Transaction) error
- func (balance *Balance) CommitInflightDebit(transaction *Transaction) error
- func (balance *Balance) InitializeBalanceFields()
- func (balance *Balance) RollbackInflightCredit(amount *big.Int) error
- func (balance *Balance) RollbackInflightDebit(amount *big.Int) error
- type BalanceFilter
- type BalanceMonitor
- type BalanceProjection
- type BalanceTracker
- type BulkTransactionPreview
- type BulkTransactionRequest
- type BulkTransactionResult
- type ChainCheckpoint
- type ChainIssue
- type ChainRow
- type ChainState
- type ChainVerifyResult
- type ChainedTransaction
- type Distribution
- type ExecutionControls
- type ExternalTransaction
- type Identity
- type KeyPolicy
- type Ledger
- type LedgerFilter
- type LegProjection
- type LineageMapping
- type LineageOutbox
- type Match
- type MatchingCriteria
- type MatchingRule
- type PolicyAdmission
- type PolicyBudgetCapacity
- type PolicyCapacity
- type PolicyLeg
- type PreviewRejection
- type Reconciliation
- type ReconciliationProgress
- type ReconciliationResults
- type SpendingRule
- type Transaction
- func (transaction *Transaction) Clone() *Transaction
- func (t *Transaction) ExecutionControls() ExecutionControls
- func (t *Transaction) ExecutionMetadata() map[string]interface{}
- func (t *Transaction) GetEffectiveDate() time.Time
- func (transaction *Transaction) HashTxn() string
- func (transaction *Transaction) SplitTransactionPrecise(ctx context.Context) ([]*Transaction, error)
- func (transaction *Transaction) ToJSON() ([]byte, error)
- func (transaction *Transaction) ValidateAmount() error
- type TransactionPreview
Constants ¶
const ( OutboxStatusPending = "pending" OutboxStatusProcessing = "processing" OutboxStatusCompleted = "completed" OutboxStatusFailed = "failed" )
Outbox status constants
const ( LineageTypeCredit = "credit" LineageTypeDebit = "debit" LineageTypeBoth = "both" LineageTypeShadowCommit = "shadow_commit" LineageTypeShadowVoid = "shadow_void" )
Lineage type constants
const ( PreviewRoleSource = "source" PreviewRoleDestination = "destination" )
Balance roles reported by a projection.
const ChainGenesisHash = "0000000000000000000000000000000000000000000000000000000000000000"
ChainGenesisHash is the starting head of the transaction hash chain — 64 zeros. ledgerforge.chain_state.head_hash begins here.
const RefundReferenceSuffix = "_refund"
RefundReferenceSuffix is appended to the original transaction id to form the refund transaction's reference (see ledgerforge.io/docs/reference/refund-transaction).
Variables ¶
This section is empty.
Functions ¶
func ApplyPrecision ¶
func ApplyPrecision(transaction *Transaction) *big.Int
ApplyPrecision handles both operations involving precision: 1. If PreciseAmount exists: converts it to a decimal Amount 2. If Amount exists: converts it to a PreciseAmount This function is now a wrapper that sets default precision if needed and calls applyPrecisionLogic.
func ApplyPrecisionChecked ¶
func ApplyPrecisionChecked(transaction *Transaction) (*big.Int, error)
ApplyPrecisionChecked validates monetary inputs before changing them.
func ApplyPrecisionWithDBLookup ¶
func ApplyPrecisionWithDBLookup(transaction *Transaction, db *sql.DB) *big.Int
ApplyPrecisionWithDBLookup is retained for compatibility. Lookup failures return nil; callers needing the cause should use the checked variant.
func ApplyPrecisionWithDBLookupChecked ¶
ApplyPrecisionWithDBLookupChecked resolves precision authoritatively without process-global state. API callers use their injected datasource instead.
func ApplyRate ¶
ApplyRate applies the exchange rate to the precise amount and returns a *big.Int. The rate is applied after precision to maintain accuracy.
func CalculateDistributionsPrecise ¶
func CalculateDistributionsPrecise(ctx context.Context, totalPreciseAmount *big.Int, distributions []Distribution, precision int64) (map[string]*big.Int, error)
CalculateDistributionsPrecise parses components exactly, truncates fractional minor units, then assigns the remainder to the largest allocation. Equal allocations are ordered lexicographically by identifier. This preserves the existing allocation policy while making every split conserve its total.
func CanonicalChainV2 ¶
CanonicalChainV2 is a domain-separated, length-delimited encoding. Each length is an unsigned big-endian uint64 byte count. Numeric text retains its exact stored representation; timestamps denote UTC instants. Mutable metadata is intentionally excluded from the financial commitment.
func CanonicalChainV3 ¶
CanonicalChainV3 retains the exact v2 payload and adds immutable execution evidence under a new domain version. V1 and v2 remain byte-for-byte stable.
func ComputeChainHash ¶
ComputeChainHash is the v1 encoding, retained for older-format verification. New seals use ComputeChainHashVersion with canonical version 3.
func ComputeChainHashVersion ¶
ComputeChainHashVersion verifies explicitly supplied v1/v2 records and v3 seals.
func DecodeTransactionMetadata ¶
func DecodeTransactionMetadata(data []byte, t *Transaction) error
DecodeTransactionMetadata consumes the private SQL projection of immutable controls. The marker is removed before metadata leaves the database layer.
func GenerateUUIDWithSuffix ¶
GenerateUUIDWithSuffix generates a UUID with a given module name as a suffix. This is useful for creating unique identifiers with context-specific prefixes.
func Int64ToBigInt ¶
Int64ToBigInt converts an int64 value to a *big.Int. This is useful for handling large numbers in computations such as financial transactions.
func ParseAmount ¶
ParseAmount parses a major-unit decimal exactly and rounds to the nearest minor unit, with halves away from zero. Positive amounts rounding to zero are rejected. Use precise_amount for integer amounts beyond float64 accuracy.
func PrecisionBankersRound ¶
PrecisionBankersRound applies banker's rounding (round half to even) at the given precision scale factor.
func RefundReference ¶
RefundReference returns the canonical reference for a refund of originalTransactionID.
func UpdateBalances ¶
func UpdateBalances(transaction *Transaction, source, destination *Balance) error
UpdateBalances updates the balances for both the source and destination based on the transaction details. It ensures precision is applied and checks for overdraft before updating.
func ValidateCustomerTransactionMetadata ¶
ValidateCustomerTransactionMetadata protects execution, lineage and internal recovery/policy bookkeeping while leaving arbitrary customer keys mutable.
func ValidatePrecision ¶
ValidatePrecision accepts a finite positive integer scale. Zero means the existing default scale of one; stored precisions must be positive.
Types ¶
type APIKey ¶
type APIKey struct {
APIKeyID string `json:"api_key_id" db:"api_key_id"`
Key string `json:"key" db:"key"`
Name string `json:"name" db:"name"`
OwnerID string `json:"owner_id" db:"owner_id"`
Scopes []string `json:"scopes" db:"scopes"`
ExpiresAt time.Time `json:"expires_at" db:"expires_at"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
LastUsedAt time.Time `json:"last_used_at" db:"last_used_at"`
IsRevoked bool `json:"is_revoked" db:"is_revoked"`
RevokedAt *time.Time `json:"revoked_at,omitempty" db:"revoked_at"`
ParentAPIKeyID string `json:"parent_api_key_id,omitempty" db:"parent_api_key_id"`
}
type Account ¶
type Account struct {
AccountID string `json:"account_id"`
Name string `json:"name" form:"name"`
Number string `json:"number" form:"number"`
BankName string `json:"bank_name"`
Currency string `json:"currency"`
BalanceID string `json:"balance_id" `
IdentityID string `json:"identity_id" form:"identity_id"`
LedgerID string `json:"ledger_id"`
Ledger *Ledger `json:"ledger"`
Balance *Balance `json:"balance"`
Identity *Identity `json:"identity"`
CreatedAt time.Time `json:"created_at"`
MetaData map[string]interface{} `json:"meta_data"`
}
Account represents a financial account linked to a balance, identity, and ledger.
type AlertCondition ¶
type AlertCondition struct {
Value float64 `json:"value"`
Precision float64 `json:"precision"`
PreciseValue *big.Int `json:"precise_value"`
Field string `json:"field"`
Operator string `json:"operator"`
}
AlertCondition specifies the field, operator, value, and precision for a balance monitor alert threshold.
type Balance ¶
type Balance struct {
// CurrencyMultiplier is retained for client compatibility; ledger arithmetic does not use it.
CurrencyMultiplier float64 `json:"currency_multiplier"`
ID int64 `json:"-"`
Balance *big.Int `json:"balance"`
Version int64 `json:"version"`
InflightBalance *big.Int `json:"inflight_balance"`
CreditBalance *big.Int `json:"credit_balance"`
InflightCreditBalance *big.Int `json:"inflight_credit_balance"`
DebitBalance *big.Int `json:"debit_balance"`
InflightDebitBalance *big.Int `json:"inflight_debit_balance"`
QueuedDebitBalance *big.Int `json:"queued_debit_balance,omitempty"`
QueuedCreditBalance *big.Int `json:"queued_credit_balance,omitempty"`
LedgerID string `json:"ledger_id"`
IdentityID string `json:"identity_id"`
BalanceID string `json:"balance_id"`
Indicator string `json:"indicator,omitempty"`
Currency string `json:"currency"`
Identity *Identity `json:"identity,omitempty"`
Ledger *Ledger `json:"ledger,omitempty"`
CreatedAt time.Time `json:"created_at"`
InflightExpiresAt time.Time `json:"inflight_expires_at"`
MetaData map[string]interface{} `json:"meta_data"`
TrackFundLineage bool `json:"track_fund_lineage"`
AllocationStrategy string `json:"allocation_strategy,omitempty"`
}
Balance represents a financial balance with credit, debit, inflight, and queued sub-balances.
func (*Balance) Clone ¶
Clone returns a deep copy of the balance that a transaction can be applied to without affecting the original.
Every *big.Int field is copied by value. This is what makes the copy meaningful: big.Int's Add and Sub mutate their receiver, so a plain struct copy would share the underlying integers with the original, and applying a transaction to the copy would silently rewrite the original's balances too.
Used by the dry-run projection to hold a "before" snapshot alongside the balances the transaction is applied to.
func (*Balance) CommitInflightCredit ¶
func (balance *Balance) CommitInflightCredit(transaction *Transaction) error
CommitInflightCredit commits a credit from the inflight balance and adds it to the credit balance.
func (*Balance) CommitInflightDebit ¶
func (balance *Balance) CommitInflightDebit(transaction *Transaction) error
CommitInflightDebit commits a debit from the inflight balance and adds it to the debit balance, returning an error if the inflight hold cannot cover the amount.
func (*Balance) InitializeBalanceFields ¶
func (balance *Balance) InitializeBalanceFields()
InitializeBalanceFields initializes all the fields of the Balance struct that might be nil. This ensures that all balance-related fields have valid *big.Int values for further operations.
func (*Balance) RollbackInflightCredit ¶
RollbackInflightCredit rolls back (decreases) the inflight credit balance by the specified amount.
type BalanceFilter ¶
type BalanceFilter struct {
ID int64 `json:"id"`
BalanceRange string `json:"balance_range"`
CreditBalanceRange string `json:"credit_balance_range"`
DebitBalanceRange string `json:"debit_balance_range"`
Currency string `json:"currency"`
LedgerID string `json:"ledger_id"`
From time.Time `json:"from"`
To time.Time `json:"to"`
}
BalanceFilter defines filter criteria for querying balances by range, currency, ledger, and time period.
type BalanceMonitor ¶
type BalanceMonitor struct {
MonitorID string `json:"monitor_id"`
BalanceID string `json:"balance_id"`
Description string `json:"description,omitempty"`
CallBackURL string `json:"-"`
CreatedAt time.Time `json:"created_at"`
Condition AlertCondition `json:"condition"`
}
BalanceMonitor defines a condition-based alert that triggers a callback when a balance meets the specified criteria.
func (*BalanceMonitor) CheckCondition ¶
func (bm *BalanceMonitor) CheckCondition(b *Balance) bool
CheckCondition checks if a balance meets the condition specified by a BalanceMonitor. It compares various balance fields (e.g., debit balance, credit balance) against the precise value.
type BalanceProjection ¶
type BalanceProjection struct {
BalanceID string `json:"balance_id"`
Role string `json:"role"`
Currency string `json:"currency"`
// Virtual marks a balance that does not exist yet — an @indicator that a
// real post would create on demand. It is projected against zero and is
// not created by the preview.
Virtual bool `json:"virtual,omitempty"`
CurrentBalance string `json:"current_balance"`
CurrentAvailable string `json:"current_available"`
CurrentCreditBalance string `json:"current_credit_balance"`
CurrentDebitBalance string `json:"current_debit_balance"`
CurrentInflightDebitBalance string `json:"current_inflight_debit_balance"`
CurrentInflightCreditBalance string `json:"current_inflight_credit_balance"`
ResultingBalance string `json:"resulting_balance"`
ResultingAvailable string `json:"resulting_available"`
ResultingCreditBalance string `json:"resulting_credit_balance"`
ResultingDebitBalance string `json:"resulting_debit_balance"`
ResultingInflightDebitBalance string `json:"resulting_inflight_debit_balance"`
ResultingInflightCreditBalance string `json:"resulting_inflight_credit_balance"`
}
BalanceProjection is one balance's state before and after the projected transaction. Current* is the snapshot the projection started from; Resulting* is that snapshot with the transaction applied in memory.
type BalanceTracker ¶
type BalanceTracker struct {
Balances map[string]*Balance
Frequencies map[string]int
Mutex sync.Mutex
}
BalanceTracker tracks in-memory balance state and access frequency for hot-path optimization.
type BulkTransactionPreview ¶
type BulkTransactionPreview struct {
DryRun bool `json:"dry_run"`
// WouldApply is false when any item in the batch would be rejected.
WouldApply bool `json:"would_apply"`
// Cumulative reports whether items were projected against each other's
// effects. That mirrors how the batch would really run: items are applied
// one after another only when skip_queue is set, and are otherwise
// dispatched concurrently with no guaranteed order.
Cumulative bool `json:"cumulative"`
Atomic bool `json:"atomic"`
Results []TransactionPreview `json:"results"`
// Balances is the batch's combined effect per balance, and is reported only
// in cumulative mode — without a guaranteed order there is no single
// combined outcome to state.
Balances []BalanceProjection `json:"balances,omitempty"`
Notes []string `json:"notes,omitempty"`
}
BulkTransactionPreview is the projected effect of a batch that was evaluated but never applied.
func (*BulkTransactionPreview) AddNote ¶
func (preview *BulkTransactionPreview) AddNote(note string)
AddNote appends an advisory note to the batch projection.
func (*BulkTransactionPreview) Finalize ¶
func (preview *BulkTransactionPreview) Finalize()
Finalize applies the same reconciliation to a batch and to each of its items, so a rejected item does not report a status either.
type BulkTransactionRequest ¶
type BulkTransactionRequest struct {
Transactions []*Transaction `json:"transactions"`
Inflight bool `json:"inflight"`
Atomic bool `json:"atomic"`
RunAsync bool `json:"run_async"`
SkipQueue bool `json:"skip_queue"`
}
BulkTransactionRequest encapsulates the data needed for a bulk transaction request.
type BulkTransactionResult ¶
type BulkTransactionResult struct {
BatchID string `json:"batch_id"`
Status string `json:"status"` // e.g., "processing", "applied", "inflight", "failed"
TransactionCount int `json:"transaction_count,omitempty"`
Error string `json:"error,omitempty"`
}
BulkTransactionResult represents the outcome of a bulk transaction operation.
type ChainCheckpoint ¶
type ChainCheckpoint struct {
Sequence int64 `json:"sequence"`
Count int64 `json:"count"`
HeadHash string `json:"head_hash"`
CreatedAt time.Time `json:"created_at"`
}
ChainCheckpoint is an exportable root. External signatures or anchors can attest to it independently of the database that holds the chain.
type ChainIssue ¶
type ChainRow ¶
type ChainRow struct {
HistoricalRate string
OverdraftLimit string
QueueAction string
ExecutionControls string
ScheduledFor *time.Time
ID string
Precision string
Rate string
ParentTransaction string
EffectiveDate *time.Time
TransactionID string
Source string
Destination string
Amount string // NUMERIC rendered as text
PreciseAmount string // NUMERIC rendered as text (the authoritative ledger amount)
Currency string
Status string
Reference string
CreatedAt time.Time
}
ChainRow carries the canonical, immutable fields of a transaction that the hash chain seals. The chainer and the verifier both build it from the same DB columns so a recomputed hash is reproducible. Numeric values are read as exact PostgreSQL text, never converted through floating point.
type ChainState ¶
type ChainState struct {
ChainKey string
LastSeq int64
HeadHash string
GenesisHash string
GenesisAt time.Time
UpdatedAt time.Time
}
ChainState mirrors the ledgerforge.chain_state bookmark row.
type ChainVerifyResult ¶
type ChainVerifyResult struct {
Verified bool `json:"verified"`
LastSeq int64 `json:"last_sequence"`
HeadHash string `json:"head_hash"`
BrokenSeq int64 `json:"broken_sequence,omitempty"`
BrokenTxnID string `json:"broken_transaction_id,omitempty"`
Reason string `json:"reason,omitempty"`
Pending int64 `json:"pending"`
Tampering []ChainIssue `json:"tampering"`
}
ChainVerifyResult distinguishes broken commitments from asynchronous coverage.
type ChainedTransaction ¶
type ChainedTransaction struct {
CanonicalVersion int
Row ChainRow
ChainSeq int64
ChainPrevHash string
ChainHash string
}
ChainedTransaction is a transaction read back in chain order for verification: its canonical fields plus the stored chain linkage.
type Distribution ¶
type Distribution struct {
Identifier string `json:"identifier"`
Distribution string `json:"distribution"` // Can be a percentage (e.g., "10%"), a fixed amount (e.g., "100"), or "left"
PreciseDistribution string `json:"precise_distribution,omitempty"` // Fixed amount in minor units (e.g., "1006" for 1006 cents)
TransactionID string `json:"transaction_id"`
}
Distribution defines how a transaction amount is allocated to a specific source or destination.
type ExecutionControls ¶
type ExecutionControls struct {
ReservedMetadata map[string]interface{} `json:"reserved_metadata"`
EconomicVersion int `json:"economic_version"`
AllowOverdraft bool `json:"allow_overdraft"`
Inflight bool `json:"inflight"`
Atomic bool `json:"atomic"`
SkipQueue bool `json:"skip_queue"`
SkipBalanceUpdate bool `json:"skip_balance_update"`
ParentKind string `json:"parent_kind"`
QueuedParent string `json:"queued_parent"`
QueueLane string `json:"queue_lane"`
ShadowFor string `json:"shadow_for"`
GroupIDs []string `json:"group_ids"`
Sources []Distribution `json:"sources"`
Destinations []Distribution `json:"destinations"`
InflightExpiryDate time.Time `json:"inflight_expiry_date"`
InflightCommitDate time.Time `json:"inflight_commit_date"`
}
ExecutionControls is stored in an immutable JSONB column. It is independent of customer metadata, including for recovery and queued execution.
func DecodeExecutionControls ¶
func DecodeExecutionControls(data []byte) (ExecutionControls, error)
DecodeExecutionControls applies the historical type checks only to schema 0. It never normalizes the original evidence used by the hash chain.
func (ExecutionControls) Apply ¶
func (c ExecutionControls) Apply(t *Transaction)
type ExternalTransaction ¶
type ExternalTransaction struct {
ID string `json:"id"`
Amount float64 `json:"amount"`
Reference string `json:"reference"`
Currency string `json:"currency"`
Description string `json:"description"`
Date time.Time `json:"date"`
Source string `json:"source"`
}
func (*ExternalTransaction) ToInternalTransaction ¶
func (et *ExternalTransaction) ToInternalTransaction() *Transaction
ToInternalTransaction converts an ExternalTransaction to an InternalTransaction. This is useful when reconciling external transactions with internal records.
type Identity ¶
type Identity struct {
IdentityID string `json:"identity_id" form:"identity_id"`
IdentityType string `json:"identity_type" form:"identity_type"`
OrganizationName string `json:"organization_name" form:"organization_name"`
Category string `json:"category" form:"category"`
FirstName string `json:"first_name" form:"first_name"`
LastName string `json:"last_name" form:"last_name"`
OtherNames string `json:"other_names" form:"other_names"`
Gender string `json:"gender" form:"gender"`
EmailAddress string `json:"email_address" form:"email_address"`
PhoneNumber string `json:"phone_number" form:"phone_number"`
Nationality string `json:"nationality" form:"nationality"`
Street string `json:"street" form:"street"`
Country string `json:"country" form:"country"`
State string `json:"state" form:"state"`
PostCode string `json:"post_code" form:"postCode"`
City string `json:"city" form:"city"`
DOB time.Time `json:"dob" form:"dob"`
CreatedAt time.Time `json:"created_at" form:"createdAt"`
MetaData map[string]interface{} `json:"meta_data" form:"metaData"`
}
func (*Identity) IsFieldTokenized ¶
func (*Identity) MarkFieldAsTokenized ¶
type KeyPolicy ¶
type KeyPolicy struct {
DenyAll bool `json:"deny_all,omitempty"`
InheritedFrom []string `json:"inherited_from,omitempty"`
APIKeyID string `json:"api_key_id"`
Version int64 `json:"version"`
Rules []SpendingRule `json:"rules"`
LedgerIDs []string `json:"ledger_ids,omitempty"`
BalanceIDs []string `json:"balance_ids,omitempty"`
}
type LedgerFilter ¶
type LegProjection ¶
type LegProjection struct {
Identifier string `json:"identifier"`
Role string `json:"role"`
PreciseAmount string `json:"precise_amount"`
Amount float64 `json:"amount"`
}
LegProjection is one split of a multi-source/destination transaction.
type LineageMapping ¶
type LineageMapping struct {
ID int64 `json:"id"`
BalanceID string `json:"balance_id"`
Provider string `json:"provider"`
ShadowBalanceID string `json:"shadow_balance_id"`
AggregateBalanceID string `json:"aggregate_balance_id"`
IdentityID string `json:"identity_id"`
CreatedAt time.Time `json:"created_at"`
}
LineageMapping tracks the relationship between a balance, its fund provider, and associated shadow/aggregate balances.
type LineageOutbox ¶
type LineageOutbox struct {
ID int64 `json:"id"`
TransactionID string `json:"transaction_id"`
SourceBalanceID string `json:"source_balance_id,omitempty"`
DestinationBalanceID string `json:"destination_balance_id,omitempty"`
Provider string `json:"provider,omitempty"`
LineageType string `json:"lineage_type"` // "credit", "debit", "both"
Payload json.RawMessage `json:"payload"`
Status string `json:"status"`
Attempts int `json:"attempts"`
MaxAttempts int `json:"max_attempts"`
LastError string `json:"last_error,omitempty"`
CreatedAt time.Time `json:"created_at"`
ProcessedAt *time.Time `json:"processed_at,omitempty"`
LockedUntil *time.Time `json:"locked_until,omitempty"`
Inflight bool `json:"inflight"`
}
LineageOutbox represents a pending lineage processing task. It is inserted atomically with the main transaction to ensure no lineage work is lost.
type MatchingCriteria ¶
type MatchingRule ¶
type PolicyAdmission ¶
type PolicyAdmission struct {
ID string `json:"admission_id"`
APIKeyID string `json:"api_key_id"`
Identity string `json:"identity"`
Version int64 `json:"policy_version"`
Day time.Time `json:"day"`
Decision string `json:"decision"`
DecidedBy string `json:"decided_by,omitempty"`
Legs []PolicyLeg `json:"legs"`
}
type PolicyBudgetCapacity ¶
type PolicyCapacity ¶
type PolicyCapacity struct {
Budgets []PolicyBudgetCapacity `json:"budgets,omitempty"`
Currency string `json:"currency"`
Precision float64 `json:"precision"`
Day time.Time `json:"day"`
Used string `json:"used_minor"`
Remaining *string `json:"remaining_minor,omitempty"`
}
Used reports the narrowest declared daily budget. Remaining is the minimum available capacity across all charged budgets, whose usage is shown in Budgets.
type PolicyLeg ¶
type PolicyLeg struct {
TransactionID string `json:"transaction_id"`
Reference string `json:"reference"`
Source string `json:"source"`
Destination string `json:"destination"`
SourceLedger string `json:"source_ledger"`
DestinationLedger string `json:"destination_ledger"`
Currency string `json:"currency"`
Precision float64 `json:"precision"`
Amount string `json:"amount"`
}
type PreviewRejection ¶
type PreviewRejection struct {
Code string `json:"code"`
Reason string `json:"reason"`
Message string `json:"message"`
}
PreviewRejection describes why a projected transaction would not apply.
Code is the same error code a real post would return, so existing client-side handling for e.g. TXN_INSUFFICIENT_FUNDS works against a preview unchanged.
type Reconciliation ¶
type Reconciliation struct {
ID int64 `json:"-"`
ReconciliationID string `json:"reconciliation_id"`
UploadID string `json:"upload_id"`
Status string `json:"status"`
MatchedTransactions int `json:"matched_transactions"`
UnmatchedTransactions int `json:"unmatched_transactions"`
IsDryRun bool `json:"is_dry_run"`
StartedAt time.Time `json:"started_at"`
CompletedAt *time.Time `json:"completed_at"`
}
type ReconciliationProgress ¶
type ReconciliationResults ¶
type ReconciliationResults struct {
ReconciliationID string `json:"reconciliation_id"`
Status string `json:"status"`
StartedAt time.Time `json:"started_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
MatchedTransactions []Match `json:"matched_transactions"`
UnmatchedTransactions []string `json:"unmatched_transactions"`
}
type SpendingRule ¶
type SpendingRule struct {
Currency string `json:"currency"`
Precision float64 `json:"precision"`
MaxTransaction string `json:"max_transaction,omitempty"`
DailyLimit string `json:"daily_limit,omitempty"`
ApprovalAbove string `json:"approval_above,omitempty"`
}
Policy amounts are exact integer minor units encoded as decimal strings. A currency is authorised only at the specified minor-unit multiplier.
type Transaction ¶
type Transaction struct {
ParentKind string `json:"-"`
QueuedParent string `json:"queued_parent,omitempty"`
QueueLane string `json:"queue_lane,omitempty"`
ShadowFor string `json:"-"`
ReservedMetadata map[string]interface{} `json:"-"`
// Rate is retained for client compatibility; ledger arithmetic does not use it.
Rate float64 `json:"rate"`
ID int64 `json:"-"`
PreciseAmount *big.Int `json:"precise_amount,omitempty"`
Amount float64 `json:"amount"`
AmountString string `json:"amount_string,omitempty"`
Precision float64 `json:"precision"`
OverdraftLimit float64 `json:"overdraft_limit"`
TransactionID string `json:"transaction_id"`
ParentTransaction string `json:"parent_transaction"`
Source string `json:"source,omitempty"`
Destination string `json:"destination,omitempty"`
Reference string `json:"reference"`
Currency string `json:"currency"`
Description string `json:"description,omitempty"`
Status string `json:"status"`
QueueAction string `json:"queue_action,omitempty"`
Hash string `json:"hash"`
AllowOverdraft bool `json:"allow_overdraft"`
Inflight bool `json:"inflight"`
SkipBalanceUpdate bool `json:"-"`
SkipQueue bool `json:"skip_queue"`
Atomic bool `json:"atomic"`
GroupIds []string `json:"-"`
Sources []Distribution `json:"sources,omitempty"`
Destinations []Distribution `json:"destinations,omitempty"`
CreatedAt time.Time `json:"created_at"`
EffectiveDate *time.Time `json:"effective_date,omitempty"`
ScheduledFor time.Time `json:"scheduled_for,omitempty"`
InflightExpiryDate time.Time `json:"inflight_expiry_date,omitempty"`
InflightCommitDate time.Time `json:"inflight_commit_date,omitempty"`
MetaData map[string]interface{} `json:"meta_data,omitempty"`
}
Transaction represents a financial transaction between source and destination balances.
func (*Transaction) Clone ¶
func (transaction *Transaction) Clone() *Transaction
Clone returns a deep copy of the transaction, safe to mutate without affecting the original.
The balance-applying path mutates the transaction it is given — UpdateBalances sets PreciseAmount, and the inflight helpers rewrite Amount — so a caller that wants to keep its own transaction intact (notably the dry-run projection, which must not disturb a transaction it was only asked to evaluate) applies the arithmetic to a clone.
func (*Transaction) ExecutionControls ¶
func (t *Transaction) ExecutionControls() ExecutionControls
func (*Transaction) ExecutionMetadata ¶
func (t *Transaction) ExecutionMetadata() map[string]interface{}
ExecutionMetadata returns immutable internal lineage decisions after a DB read, and creation-time metadata for a transaction that has not been accepted.
func (*Transaction) GetEffectiveDate ¶
func (t *Transaction) GetEffectiveDate() time.Time
GetEffectiveDate returns the transaction's effective date, falling back to CreatedAt if not explicitly set.
func (*Transaction) HashTxn ¶
func (transaction *Transaction) HashTxn() string
HashTxn generates a SHA-256 hash of a transaction's relevant fields. This ensures the integrity of the transaction by creating a unique hash from its details.
func (*Transaction) SplitTransactionPrecise ¶
func (transaction *Transaction) SplitTransactionPrecise(ctx context.Context) ([]*Transaction, error)
Function to integrate the new CalculateDistributionsPrecise into SplitTransaction
func (*Transaction) ToJSON ¶
func (transaction *Transaction) ToJSON() ([]byte, error)
ToJSON serializes the transaction to JSON bytes.
func (*Transaction) ValidateAmount ¶
func (transaction *Transaction) ValidateAmount() error
ValidateAmount is the exported ingest check used by QueueTransaction so zero/empty amounts never land on the queue.
type TransactionPreview ¶
type TransactionPreview struct {
DryRun bool `json:"dry_run"`
// WouldApply reports whether a real post of this transaction would be
// accepted against the balances as they currently stand. When false,
// Rejection carries the reason.
WouldApply bool `json:"would_apply"`
Rejection *PreviewRejection `json:"rejection,omitempty"`
// Operation names the settlement being projected on the inflight endpoint:
// "commit" or "void". Empty for ordinary transaction projections.
Operation string `json:"operation,omitempty"`
// Status is the status the transaction would carry once applied. It is
// omitted when WouldApply is false: a rejected projection has no resulting
// status, because the real endpoint returns an error and writes no
// transaction at all. See Finalize.
Status string `json:"status,omitempty"`
Reference string `json:"reference,omitempty"`
Currency string `json:"currency"`
Amount float64 `json:"amount"`
PreciseAmount string `json:"precise_amount"`
Precision float64 `json:"precision"`
Balances []BalanceProjection `json:"balances"`
// Legs is populated for multi-source/destination transactions: one entry
// per split, using the same distribution math a real post would use.
Legs []LegProjection `json:"legs,omitempty"`
// Notes carry advisory information that is not a rejection — an ignored
// field, or a condition worth surfacing before the caller posts for real.
Notes []string `json:"notes,omitempty"`
}
TransactionPreview is the projected effect of a transaction that was evaluated but never applied.
Monetary values are strings in minor units, matching precise_amount, so no precision is lost in transit.
func (*TransactionPreview) AddNote ¶
func (preview *TransactionPreview) AddNote(note string)
AddNote appends an advisory note to the projection.
func (*TransactionPreview) Finalize ¶
func (preview *TransactionPreview) Finalize()
Finalize reconciles fields that only describe a transaction that would actually apply.
Status is set early, from the status the transaction would carry once applied, and the projection only later discovers it would be rejected -- an insufficient balance, a failing leg, a validation failure downstream. Left alone, the response then asserts two things that cannot both be true:
"would_apply": false,
"rejection": { "code": "TXN_INSUFFICIENT_FUNDS", ... },
"status": "APPLIED"
A rejected projection has no resulting status. The real endpoint returns an error and writes no transaction, so there is no status to report; clearing it lets the omitempty tag drop the field rather than name an outcome that cannot happen. Callers read would_apply and rejection for that answer.