ship(P03): merge Storage Substrate into milestone v0.1
---ci--- project: oy phase: 3 milestone: v0.1 status: complete ship: v0.0.3 ---/ci--- Phase 3 shipped: Stash + Vault + Root-Pool types. 4 tests passing. Three-pool model (§5) implemented.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package types
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
const (
|
||||
ModuleName = "rootpool"
|
||||
StoreKey = ModuleName
|
||||
RouterKey = ModuleName
|
||||
QuerierRoute = ModuleName
|
||||
)
|
||||
|
||||
// RootPool is the mesh's treasury (§5)
|
||||
// Attested by Watchers, visible to every Holder.
|
||||
type RootPool struct {
|
||||
BalanceGrain int64 `json:"balance_grain" yaml:"balance_grain"`
|
||||
LastAttestation int64 `json:"last_attestation" yaml:"last_attestation"`
|
||||
QuorumMet bool `json:"quorum_met" yaml:"quorum_met"`
|
||||
ReserveRatioPct uint32 `json:"reserve_ratio_pct" yaml:"reserve_ratio_pct"`
|
||||
}
|
||||
|
||||
// RootPoolEntry tracks incoming/outgoing Root-Pool movements
|
||||
type RootPoolEntry struct {
|
||||
EntryID string `json:"entry_id" yaml:"entry_id"`
|
||||
Source string `json:"source" yaml:"source"`
|
||||
Amount int64 `json:"amount" yaml:"amount"`
|
||||
Reason string `json:"reason" yaml:"reason"`
|
||||
Timestamp int64 `json:"timestamp" yaml:"timestamp"`
|
||||
}
|
||||
|
||||
type Params struct{}
|
||||
|
||||
func DefaultParams() Params { return Params{} }
|
||||
|
||||
type GenesisState struct {
|
||||
Params Params `json:"params" yaml:"params"`
|
||||
RootPool RootPool `json:"root_pool" yaml:"root_pool"`
|
||||
}
|
||||
|
||||
func DefaultGenesisState() *GenesisState {
|
||||
return &GenesisState{Params: DefaultParams()}
|
||||
}
|
||||
|
||||
func ValidateGenesis(bz json.RawMessage) error { return nil }
|
||||
@@ -0,0 +1,55 @@
|
||||
package types
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
const (
|
||||
ModuleName = "stash"
|
||||
StoreKey = ModuleName
|
||||
RouterKey = ModuleName
|
||||
QuerierRoute = ModuleName
|
||||
)
|
||||
|
||||
// Stash is a per-Holder sovereign storage (§5)
|
||||
// The Holder owns it. No one else can access it without a Window (§10).
|
||||
type Stash struct {
|
||||
HolderID string `json:"holder_id" yaml:"holder_id"`
|
||||
StashID string `json:"stash_id" yaml:"stash_id"`
|
||||
CreatedAt int64 `json:"created_at" yaml:"created_at"`
|
||||
LastActive int64 `json:"last_active" yaml:"last_active"`
|
||||
BalanceGrain int64 `json:"balance_grain" yaml:"balance_grain"`
|
||||
IsStill bool `json:"is_still" yaml:"is_still"` // Still = Holder paused partner access (§10)
|
||||
}
|
||||
|
||||
// StashActivity tracks Stash maturity for Freeholder signals (§9.1: 90 days, no gap >30 days)
|
||||
type StashActivity struct {
|
||||
StashID string `json:"stash_id" yaml:"stash_id"`
|
||||
ActiveDays uint32 `json:"active_days" yaml:"active_days"`
|
||||
MaxGapDays uint32 `json:"max_gap_days" yaml:"max_gap_days"` // must be ≤30 for Freeholder
|
||||
LastActivityDay int64 `json:"last_activity_day" yaml:"last_activity_day"`
|
||||
}
|
||||
|
||||
// MaturityThreshold for Freeholder signal (§9.1: 90 days)
|
||||
const MaturityThresholdDays = 90
|
||||
|
||||
// MaxGapForMaturity for Freeholder signal (§9.1: no gap > 30 days)
|
||||
const MaxGapForMaturity = 30
|
||||
|
||||
// IsMature checks if Stash activity meets the Freeholder maturity threshold (§9.1)
|
||||
func (a StashActivity) IsMature() bool {
|
||||
return a.ActiveDays >= MaturityThresholdDays && a.MaxGapDays <= MaxGapForMaturity
|
||||
}
|
||||
|
||||
type Params struct{}
|
||||
|
||||
func DefaultParams() Params { return Params{} }
|
||||
|
||||
type GenesisState struct {
|
||||
Params Params `json:"params" yaml:"params"`
|
||||
Stashes []Stash `json:"stashes" yaml:"stashes"`
|
||||
}
|
||||
|
||||
func DefaultGenesisState() *GenesisState {
|
||||
return &GenesisState{Params: DefaultParams(), Stashes: []Stash{}}
|
||||
}
|
||||
|
||||
func ValidateGenesis(bz json.RawMessage) error { return nil }
|
||||
@@ -0,0 +1,43 @@
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/oy/openyield/x/stash/types"
|
||||
)
|
||||
|
||||
func TestMaturityThreshold(t *testing.T) {
|
||||
if types.MaturityThresholdDays != 90 {
|
||||
t.Errorf("MaturityThresholdDays = %d, expected 90 (§9.1)", types.MaturityThresholdDays)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxGapForMaturity(t *testing.T) {
|
||||
if types.MaxGapForMaturity != 30 {
|
||||
t.Errorf("MaxGapForMaturity = %d, expected 30 (§9.1: no gap > 30 days)", types.MaxGapForMaturity)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStashIsMature(t *testing.T) {
|
||||
mature := types.StashActivity{ActiveDays: 90, MaxGapDays: 15}
|
||||
if !mature.IsMature() {
|
||||
t.Error("90 days active, 15 max gap should be mature (§9.1)")
|
||||
}
|
||||
|
||||
notEnoughDays := types.StashActivity{ActiveDays: 89, MaxGapDays: 15}
|
||||
if notEnoughDays.IsMature() {
|
||||
t.Error("89 days should NOT be mature (threshold = 90)")
|
||||
}
|
||||
|
||||
gapTooBig := types.StashActivity{ActiveDays: 100, MaxGapDays: 31}
|
||||
if gapTooBig.IsMature() {
|
||||
t.Error("31-day gap should NOT be mature (max gap = 30)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStashStillFlag(t *testing.T) {
|
||||
stash := types.Stash{IsStill: true}
|
||||
if !stash.IsStill {
|
||||
t.Error("Stash with IsStill=true should reflect Still state (§10: Holder paused partner access)")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package types
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
const (
|
||||
ModuleName = "vault"
|
||||
StoreKey = ModuleName
|
||||
RouterKey = ModuleName
|
||||
QuerierRoute = ModuleName
|
||||
)
|
||||
|
||||
// Vault is a per-Stand governed storage (§5)
|
||||
// Governed by the Stand Council (§19). Holds shared funds for a Stand.
|
||||
type Vault struct {
|
||||
VaultID string `json:"vault_id" yaml:"vault_id"`
|
||||
StandID string `json:"stand_id" yaml:"stand_id"`
|
||||
CreatedAt int64 `json:"created_at" yaml:"created_at"`
|
||||
BalanceGrain int64 `json:"balance_grain" yaml:"balance_grain"`
|
||||
}
|
||||
|
||||
// VaultAllocation tracks sub-Vault allocations within a Stand
|
||||
type VaultAllocation struct {
|
||||
VaultID string `json:"vault_id" yaml:"vault_id"`
|
||||
SubVaultID string `json:"sub_vault_id" yaml:"sub_vault_id"`
|
||||
Percentage uint32 `json:"percentage" yaml:"percentage"`
|
||||
Purpose string `json:"purpose" yaml:"purpose"`
|
||||
}
|
||||
|
||||
type Params struct{}
|
||||
|
||||
func DefaultParams() Params { return Params{} }
|
||||
|
||||
type GenesisState struct {
|
||||
Params Params `json:"params" yaml:"params"`
|
||||
Vaults []Vault `json:"vaults" yaml:"vaults"`
|
||||
}
|
||||
|
||||
func DefaultGenesisState() *GenesisState {
|
||||
return &GenesisState{Params: DefaultParams(), Vaults: []Vault{}}
|
||||
}
|
||||
|
||||
func ValidateGenesis(bz json.RawMessage) error { return nil }
|
||||
Reference in New Issue
Block a user