ship(P04): merge Bloom Engine into milestone v0.1
---ci--- project: oy phase: 4 milestone: v0.1 status: complete ship: v0.0.4 ---/ci---
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package types
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
const (
|
||||
ModuleName = "bloom"
|
||||
StoreKey = ModuleName
|
||||
RouterKey = ModuleName
|
||||
QuerierRoute = ModuleName
|
||||
|
||||
// Target Bloom rate: ~4-5% per year (§6)
|
||||
// Honest expectation, not a promise
|
||||
TargetBloomRateBasisPoints = 450 // 4.5%
|
||||
MinBloomRateBasisPoints = 400 // 4.0%
|
||||
MaxBloomRateBasisPoints = 500 // 5.0%
|
||||
|
||||
// Bloom accrues automatically to every Grain in every Stash (§6)
|
||||
// Accrual period: daily (in blocks, assuming ~10min blocks)
|
||||
AccrualPeriodBlocks = 144
|
||||
)
|
||||
|
||||
// BloomRecord tracks Bloom accrued to a Stash
|
||||
type BloomRecord struct {
|
||||
StashID string `json:"stash_id" yaml:"stash_id"`
|
||||
AccruedGrain int64 `json:"accrued_grain" yaml:"accrued_grain"`
|
||||
LastAccrualBlock int64 `json:"last_accrual_block" yaml:"last_accrual_block"`
|
||||
RateBasisPoints uint32 `json:"rate_basis_points" yaml:"rate_basis_points"`
|
||||
}
|
||||
|
||||
// BloomBoosterBucket represents a higher-strategy bucket (§3 lexicon)
|
||||
type BloomBoosterBucket struct {
|
||||
BucketID string `json:"bucket_id" yaml:"bucket_id"`
|
||||
StashID string `json:"stash_id" yaml:"stash_id"`
|
||||
PledgeAmount int64 `json:"pledge_amount" yaml:"pledge_amount"`
|
||||
BoostRateBps uint32 `json:"boost_rate_bps" yaml:"boost_rate_bps"`
|
||||
UnlockHeight int64 `json:"unlock_height" yaml:"unlock_height"`
|
||||
}
|
||||
|
||||
// BloomSource defines where Bloom originates (§6: only from real yield)
|
||||
type BloomSource string
|
||||
|
||||
const (
|
||||
BloomFromTreasury BloomSource = "TreasuryCoupons"
|
||||
BloomFromCorporate BloomSource = "CorporateCoupons"
|
||||
BloomFromGoldCarry BloomSource = "GoldCarry"
|
||||
BloomFromRwaCashflow BloomSource = "RwaCashflow"
|
||||
)
|
||||
|
||||
// MissionLockBloom: Bloom originates ONLY from real yield (§6)
|
||||
// No synthetic Bloom. No protocol-printed Bloom.
|
||||
// This is a Mission Lock — no Council vote can change it.
|
||||
const MissionLockBloom = "Bloom originates only from real yield. No synthetic Bloom. No protocol-printed Bloom."
|
||||
|
||||
type Params struct {
|
||||
TargetRateBps uint32 `json:"target_rate_bps" yaml:"target_rate_bps"`
|
||||
AccrualBlocks uint32 `json:"accrual_blocks" yaml:"accrual_blocks"`
|
||||
}
|
||||
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
TargetRateBps: TargetBloomRateBasisPoints,
|
||||
AccrualBlocks: AccrualPeriodBlocks,
|
||||
}
|
||||
}
|
||||
|
||||
type GenesisState struct {
|
||||
Params Params `json:"params" yaml:"params"`
|
||||
}
|
||||
|
||||
func DefaultGenesisState() *GenesisState {
|
||||
return &GenesisState{Params: DefaultParams()}
|
||||
}
|
||||
|
||||
func ValidateGenesis(bz json.RawMessage) error { return nil }
|
||||
@@ -0,0 +1,41 @@
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/oy/openyield/x/bloom/types"
|
||||
)
|
||||
|
||||
func TestTargetBloomRate(t *testing.T) {
|
||||
if types.TargetBloomRateBasisPoints != 450 {
|
||||
t.Errorf("TargetBloomRate = %d, expected 450 (§6: 4.5 pct)", types.TargetBloomRateBasisPoints)
|
||||
}
|
||||
if types.MinBloomRateBasisPoints != 400 {
|
||||
t.Errorf("MinBloomRate = %d, expected 400 (§6: 4-5 pct)", types.MinBloomRateBasisPoints)
|
||||
}
|
||||
if types.MaxBloomRateBasisPoints != 500 {
|
||||
t.Errorf("MaxBloomRate = %d, expected 500 (§6: 4-5 pct)", types.MaxBloomRateBasisPoints)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBloomSources(t *testing.T) {
|
||||
sources := []types.BloomSource{
|
||||
types.BloomFromTreasury, types.BloomFromCorporate,
|
||||
types.BloomFromGoldCarry, types.BloomFromRwaCashflow,
|
||||
}
|
||||
if len(sources) != 4 {
|
||||
t.Errorf("Expected 4 Bloom sources, got %d", len(sources))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissionLockBloom(t *testing.T) {
|
||||
if types.MissionLockBloom == "" {
|
||||
t.Error("MissionLockBloom should not be empty (§6: mission-locked)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccrualPeriod(t *testing.T) {
|
||||
if types.AccrualPeriodBlocks != 144 {
|
||||
t.Errorf("AccrualPeriodBlocks = %d, expected 144 (~daily)", types.AccrualPeriodBlocks)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user