oracle.gno
5.46 Kb · 164 lines
1package pool
2
3import (
4 "gno.land/p/gnoswap/utils/v1"
5 "gno.land/p/nt/bptree/v0"
6)
7
8type Observation struct {
9 blockTimestamp int64 // timestamp of the observation
10 tickCumulative int64 // cumulative tick up to this timestamp
11 secondsPerLiquidityCumulativeX128 string // cumulative seconds per liquidity
12 initialized bool // whether this observation has been initialized
13}
14
15// Observation getter methods.
16// BlockTimestamp returns the observation's block timestamp.
17//
18// Returns:
19// - blockTimestamp: Timestamp at which this observation was recorded.
20func (o Observation) BlockTimestamp() int64 { return o.blockTimestamp }
21
22// TickCumulative returns the signed cumulative tick recorded by the observation.
23//
24// Returns:
25// - tickCumulative: Cumulative tick value through the observation timestamp.
26func (o Observation) TickCumulative() int64 { return o.tickCumulative }
27
28// SecondsPerLiquidityCumulativeX128 returns the Q128-encoded cumulative
29// seconds-per-liquidity value recorded by the observation.
30//
31// Returns:
32// - secondsPerLiquidityCumulativeX128: Decimal string containing the cumulative value scaled by 2^128.
33func (o Observation) SecondsPerLiquidityCumulativeX128() string {
34 return o.secondsPerLiquidityCumulativeX128
35}
36
37// Initialized reports whether the observation contains initialized oracle data.
38//
39// Returns:
40// - initialized: True when the observation slot has been initialized; false for an empty slot.
41func (o Observation) Initialized() bool { return o.initialized }
42
43// MakeObservation constructs an observation from its stored oracle accumulators.
44//
45// Parameters:
46// - blockTimestamp: Timestamp associated with the observation.
47// - tickCumulative: Signed cumulative tick at blockTimestamp.
48// - secondsPerLiquidityCumulativeX128: Decimal Q128-scaled cumulative seconds-per-liquidity value.
49// - initialized: Whether this observation slot is initialized and usable.
50//
51// Returns:
52// - observation: Observation containing the supplied timestamp, accumulators, and initialization flag.
53func MakeObservation(
54 blockTimestamp int64,
55 tickCumulative int64,
56 secondsPerLiquidityCumulativeX128 string,
57 initialized bool,
58) Observation {
59 return Observation{
60 blockTimestamp: blockTimestamp,
61 tickCumulative: tickCumulative,
62 secondsPerLiquidityCumulativeX128: secondsPerLiquidityCumulativeX128,
63 initialized: initialized,
64 }
65}
66
67// DefaultObservation returns the zero, uninitialized observation used for an empty slot.
68//
69// Returns:
70// - observation: Observation with zero timestamp and accumulators and Initialized false.
71func DefaultObservation() Observation {
72 return MakeObservation(
73 0,
74 0,
75 "0",
76 false,
77 )
78}
79
80// ObservationTree is a pool-local oracle ring buffer keyed by index.
81// It owns the B+tree key encoding so oracle code works with uint16 indices.
82type ObservationTree struct {
83 tree *bptree.BPTree
84}
85
86// NewObservationTree creates an empty pool-local observation tree keyed by uint16 index.
87//
88// Returns:
89// - tree: Initialized observation tree ready for Get, Set, and Has operations.
90func NewObservationTree() *ObservationTree {
91 return &ObservationTree{tree: bptree.NewBPTreeN(32)}
92}
93
94// Get looks up an observation by its circular-buffer index.
95//
96// Parameters:
97// - index: uint16 observation slot to read.
98//
99// Returns:
100// - observation: Stored observation when the tree contains a value of the expected type; otherwise the zero observation.
101// - ok: True when a stored value was found and decoded as an Observation; false for nil/uninitialized trees, missing slots, or a type mismatch.
102func (t *ObservationTree) Get(index uint16) (Observation, bool) {
103 if t == nil || t.tree == nil {
104 return Observation{}, false
105 }
106 value := t.tree.Get(utils.EncodeUint16(index))
107 if value == nil {
108 return Observation{}, false
109 }
110 observation, ok := value.(Observation)
111 return observation, ok
112}
113
114// Set stores an observation at a circular-buffer index.
115//
116// Parameters:
117// - index: uint16 observation slot to write.
118// - observation: Observation value to associate with index.
119func (t *ObservationTree) Set(index uint16, observation Observation) {
120 if t == nil || t.tree == nil {
121 panic("observation tree is not initialized")
122 }
123 t.tree.Set(utils.EncodeUint16(index), observation)
124}
125
126// Has reports whether an observation slot exists in the tree.
127//
128// Parameters:
129// - index: uint16 observation slot to test.
130//
131// Returns:
132// - exists: True when the initialized tree contains index; false for nil/uninitialized trees or an absent slot.
133func (t *ObservationTree) Has(index uint16) bool {
134 if t == nil || t.tree == nil {
135 return false
136 }
137 return t.tree.Has(utils.EncodeUint16(index))
138}
139
140// NewObservationsTree creates the top-level B+tree that indexes pool observation trees by pool path.
141//
142// Returns:
143// - tree: Empty B+tree suitable for storing pool-path observation trees.
144func NewObservationsTree() *bptree.BPTree {
145 return bptree.NewBPTreeN(32)
146}
147
148// NewPoolObservationsTree creates a circular observation buffer with slot zero initialized.
149//
150// Parameters:
151// - currentTime: Timestamp assigned to the initial observation at index zero.
152//
153// Returns:
154// - tree: Observation tree containing an initialized zero-index observation with zero cumulative values.
155func NewPoolObservationsTree(currentTime int64) *ObservationTree {
156 observations := NewObservationTree()
157 observations.Set(0, MakeObservation(
158 currentTime,
159 0,
160 "0",
161 true,
162 ))
163 return observations
164}