Search Apps Documentation Source Content File Folder Download Copy Actions Download

emission_state.gno

5.13 Kb ยท 167 lines
  1package gns
  2
  3import (
  4	"chain/runtime"
  5	"time"
  6
  7	"gno.land/p/nt/ufmt"
  8)
  9
 10var emissionState *EmissionState
 11
 12func init() {
 13	emissionState = NewEmissionState(0, 0)
 14}
 15
 16// EmissionState manages emission state and halving data.
 17// Tracks emission timing, status, and halving year information for 12-year schedule.
 18type EmissionState struct {
 19	createdHeight  int64
 20	startTimestamp int64
 21	endTimestamp   int64
 22	halvingData    *HalvingData
 23}
 24
 25// isInitialized returns true if emission state has been initialized with valid height and timestamp.
 26func (e *EmissionState) isInitialized() bool {
 27	return e.createdHeight != 0 && e.startTimestamp != 0
 28}
 29
 30// isActive returns true if emission is currently active at the given timestamp.
 31// Returns false if not initialized or timestamp is outside emission period.
 32func (e *EmissionState) isActive(timestamp int64) bool {
 33	if !e.isInitialized() {
 34		return false
 35	}
 36
 37	if e.startTimestamp > timestamp {
 38		return false
 39	}
 40
 41	if e.endTimestamp < timestamp {
 42		return false
 43	}
 44
 45	return true
 46}
 47
 48// isEnded returns true if emission has ended at the given timestamp.
 49func (e *EmissionState) isEnded(timestamp int64) bool {
 50	return e.endTimestamp < timestamp
 51}
 52
 53// getCurrentYear returns the halving year (1-12) for the given timestamp, or 0 if outside emission period.
 54func (e *EmissionState) getCurrentYear(timestamp int64) int64 {
 55	if timestamp < e.startTimestamp {
 56		return 0
 57	}
 58
 59	if timestamp > e.endTimestamp {
 60		return 0
 61	}
 62
 63	year := (timestamp - e.startTimestamp) / SECONDS_IN_YEAR
 64	return year + 1
 65}
 66
 67// getCreatedHeight returns the blockchain height when emission started.
 68func (e *EmissionState) getCreatedHeight() int64 {
 69	return e.createdHeight
 70}
 71
 72// getStartTimestamp returns the timestamp when emission started.
 73func (e *EmissionState) getStartTimestamp() int64 {
 74	return e.startTimestamp
 75}
 76
 77// getEndTimestamp returns the timestamp when emission ends.
 78func (e *EmissionState) getEndTimestamp() int64 {
 79	return e.endTimestamp
 80}
 81
 82// getHalvingData returns the halving data containing emission schedule details.
 83func (e *EmissionState) getHalvingData() *HalvingData {
 84	return e.halvingData
 85}
 86
 87// getHalvingYearStartTimestamp returns the start timestamp for the specified halving year.
 88func (e *EmissionState) getHalvingYearStartTimestamp(year int64) int64 {
 89	return e.halvingData.getStartTimestamp(year)
 90}
 91
 92// getHalvingYearEndTimestamp returns the end timestamp for the specified halving year.
 93func (e *EmissionState) getHalvingYearEndTimestamp(year int64) int64 {
 94	return e.halvingData.getEndTimestamp(year)
 95}
 96
 97// getHalvingYearAmountPerSecond returns the emission rate per second for the specified halving year.
 98func (e *EmissionState) getHalvingYearAmountPerSecond(year int64) int64 {
 99	return e.halvingData.getAmountPerSecond(year)
100}
101
102// getHalvingYearAccumulatedAmount returns the accumulated emission amount for the specified halving year.
103func (e *EmissionState) getHalvingYearAccumulatedAmount(year int64) int64 {
104	return e.halvingData.getAccumAmount(year)
105}
106
107// getHalvingYearLeftAmount returns the remaining emission amount for the specified halving year.
108func (e *EmissionState) getHalvingYearLeftAmount(year int64) int64 {
109	return e.halvingData.getLeftAmount(year)
110}
111
112// addHalvingYearAccumulatedAmount adds to the accumulated emission amount for the specified halving year.
113// Returns error if year is invalid (0 or outside 1-12 range).
114func (e *EmissionState) addHalvingYearAccumulatedAmount(year int64, amount int64) error {
115	if year == 0 {
116		return makeErrorWithDetails(errInvalidYear, ufmt.Sprintf("year: %d", year))
117	}
118
119	accumulatedAmount := e.halvingData.getAccumAmount(year)
120	accumulatedAmount = safeAddInt64(accumulatedAmount, amount)
121
122	return e.halvingData.setAccumAmount(year, accumulatedAmount)
123}
124
125// subHalvingYearLeftAmount subtracts from the remaining emission amount for the specified halving year.
126// Returns error if year is invalid (0 or outside 1-12 range).
127func (e *EmissionState) subHalvingYearLeftAmount(year int64, amount int64) error {
128	if year == 0 {
129		return makeErrorWithDetails(errInvalidYear, ufmt.Sprintf("year: %d", year))
130	}
131
132	leftAmount := e.halvingData.getLeftAmount(year)
133	leftAmount = safeSubInt64(leftAmount, amount)
134
135	return e.halvingData.setLeftAmount(year, leftAmount)
136}
137
138func (e *EmissionState) Clone() *EmissionState {
139	return &EmissionState{
140		createdHeight:  e.createdHeight,
141		startTimestamp: e.startTimestamp,
142		endTimestamp:   e.endTimestamp,
143		halvingData:    e.halvingData.Clone(),
144	}
145}
146
147// NewEmissionState creates a new EmissionState with specified start height and timestamp.
148// Calculates emission end time based on 12-year schedule and initializes halving data.
149func NewEmissionState(createdHeight int64, startTimestamp int64) *EmissionState {
150	emissionEndTime := safeAddInt64(startTimestamp, SECONDS_IN_YEAR*HALVING_END_YEAR-1)
151
152	return &EmissionState{
153		createdHeight:  createdHeight,
154		startTimestamp: startTimestamp,
155		endTimestamp:   emissionEndTime,
156		halvingData:    NewHalvingData(startTimestamp),
157	}
158}
159
160// getEmissionState returns the singleton emission state instance.
161func getEmissionState() *EmissionState {
162	if emissionState == nil {
163		emissionState = NewEmissionState(runtime.ChainHeight(), time.Now().Unix())
164	}
165
166	return emissionState
167}