datastorestore

package
v1.49.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package datastorestore is the production treasury.IssuanceStore: it persists HUSD mint issuances to the per-org SQLite ledger via models/husdissuance.

It lives in a SUB-package (not package treasury) on purpose: package treasury stays free of the datastore/sqlite (cgo) dependency so its mint-logic unit tests and the live on-chain proof build CGO-free. Production wires datastorestore.New(db) as the treasury.IssuanceStore.

Idempotency follows the proven money-safe pattern (models/idempotencykey): the issuance storage id is deterministic in the idempotency key, so concurrent duplicate creates collapse onto ONE row via the backend ON CONFLICT(id, kind, namespace) upsert. CreateIfAbsent reads by the EXACT kind-qualified key (never GetById, whose hashid decode drops the kind and breaks the Postgres lookup).

LIMITATION (documented, same as models/idempotencykey): the read-then-create is not an atomic compare-and-swap (datastore.RunInTransaction is a no-op on this backend), so two callers racing a FIRST-EVER idempotency key can both see "absent" and both proceed to submit a chain tx. The deterministic id still guarantees ONE stored row, and the treasury account's sequential nonce rejects the second concurrent transfer, but the definitive backstop is the step-6 reconcile job (chain balance == Σ issuances per org). Callers derive the idempotency key from a stable logical event (welcome:<org>, topup:<paymentId>) so identical-key races are pathological, not routine.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store implements treasury.IssuanceStore against a datastore.

func New

func New(db *datastore.Datastore) *Store

New builds a datastore-backed issuance store. db must be namespaced to the org (or the system namespace for cross-org audit) by the caller.

func (*Store) ByTxHash

func (s *Store) ByTxHash(_ context.Context, txHash string) (*treasury.Issuance, error)

ByTxHash resolves the issuance behind a mint tx (indexed on TxHash) so the indexer can tag a projected on-chain transfer with its off-chain bucket/subject. Returns nil (not an error) when no issuance minted that tx — an external payin. It makes *Store also satisfy billing/husdindex.IssuanceLookup, so the SAME system-namespace store is both the mint's write target and the indexer's read source (one issuance ledger, queryable by tx globally).

func (*Store) CreateIfAbsent

func (s *Store) CreateIfAbsent(_ context.Context, iss *treasury.Issuance) (bool, *treasury.Issuance, error)

CreateIfAbsent records iss iff its Id is absent, else returns the existing row.

func (*Store) Get

func (s *Store) Get(_ context.Context, id string) (*treasury.Issuance, error)

Get loads an issuance by id (nil,nil if absent).

func (*Store) Update

func (s *Store) Update(_ context.Context, iss *treasury.Issuance) error

Update writes status/txHash/mintedAt in place on the deterministic row.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL