Skip to content

Commit 8f22e6a

Browse files
author
Jeff Yanta
committed
Add a store for launchpad currency metadata
1 parent 85ebe50 commit 8f22e6a

File tree

10 files changed

+725
-87
lines changed

10 files changed

+725
-87
lines changed

pkg/code/async/currency/reserve.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func (p *reserveService) UpdateAllCurrencyReserves(ctx context.Context) error {
9191
tokenAccount.Unmarshal(ai.Data)
9292
coreMintVaultBalance := tokenAccount.Amount
9393

94-
return p.data.PutCurrencyReserveRecord(ctx, &currency.ReserveRecord{
94+
return p.data.PutCurrencyReserve(ctx, &currency.ReserveRecord{
9595
Mint: jeffyMintAccount.PublicKey().ToBase58(),
9696
SupplyFromBonding: currencycreator.DefaultMintMaxQuarkSupply - jeffyVaultBalance,
9797
CoreMintLocked: coreMintVaultBalance,

pkg/code/data/currency/memory/store.go

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ type store struct {
1818
mu sync.Mutex
1919
exchangeRateRecords []*currency.ExchangeRateRecord
2020
lastExchangeRateIndex uint64
21+
metadataRecords []*currency.MetadataRecord
22+
lastMetadataIndex uint64
2123
reserveRecords []*currency.ReserveRecord
2224
lastReserveIndex uint64
2325
}
@@ -51,6 +53,8 @@ func (s *store) reset() {
5153
s.mu.Lock()
5254
s.exchangeRateRecords = make([]*currency.ExchangeRateRecord, 0)
5355
s.lastExchangeRateIndex = 1
56+
s.metadataRecords = make([]*currency.MetadataRecord, 0)
57+
s.lastMetadataIndex = 1
5458
s.reserveRecords = make([]*currency.ReserveRecord, 0)
5559
s.lastReserveIndex = 1
5660
s.mu.Unlock()
@@ -154,7 +158,46 @@ func (s *store) GetExchangeRatesInRange(ctx context.Context, symbol string, inte
154158
return all, nil
155159
}
156160

161+
func (s *store) PutMetadata(ctx context.Context, data *currency.MetadataRecord) error {
162+
if err := data.Validate(); err != nil {
163+
return err
164+
}
165+
166+
s.mu.Lock()
167+
defer s.mu.Unlock()
168+
169+
// Not ideal but fine for testing the currency store
170+
for _, item := range s.metadataRecords {
171+
if item.Mint == data.Mint {
172+
return currency.ErrExists
173+
}
174+
}
175+
176+
data.Id = s.lastMetadataIndex
177+
s.metadataRecords = append(s.metadataRecords, data.Clone())
178+
s.lastMetadataIndex = s.lastMetadataIndex + 1
179+
180+
return nil
181+
}
182+
183+
func (s *store) GetMetadata(ctx context.Context, mint string) (*currency.MetadataRecord, error) {
184+
s.mu.Lock()
185+
defer s.mu.Unlock()
186+
187+
for _, item := range s.metadataRecords {
188+
if item.Mint == mint {
189+
return item.Clone(), nil
190+
}
191+
}
192+
193+
return nil, currency.ErrNotFound
194+
}
195+
157196
func (s *store) PutReserveRecord(ctx context.Context, data *currency.ReserveRecord) error {
197+
if err := data.Validate(); err != nil {
198+
return err
199+
}
200+
158201
s.mu.Lock()
159202
defer s.mu.Unlock()
160203

@@ -165,13 +208,8 @@ func (s *store) PutReserveRecord(ctx context.Context, data *currency.ReserveReco
165208
}
166209
}
167210

168-
s.reserveRecords = append(s.reserveRecords, &currency.ReserveRecord{
169-
Id: s.lastReserveIndex,
170-
Mint: data.Mint,
171-
SupplyFromBonding: data.SupplyFromBonding,
172-
CoreMintLocked: data.CoreMintLocked,
173-
Time: data.Time,
174-
})
211+
data.Id = s.lastReserveIndex
212+
s.reserveRecords = append(s.reserveRecords, data.Clone())
175213
s.lastReserveIndex = s.lastReserveIndex + 1
176214

177215
return nil
@@ -195,5 +233,5 @@ func (s *store) GetReserveAtTime(ctx context.Context, mint string, t time.Time)
195233

196234
sort.Sort(ReserveByTime(results))
197235

198-
return results[0], nil
236+
return results[0].Clone(), nil
199237
}

pkg/code/data/currency/model.go

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
package currency
2+
3+
import (
4+
"errors"
5+
"time"
6+
7+
"github.com/code-payments/code-server/pkg/solana/currencycreator"
8+
)
9+
10+
type ExchangeRateRecord struct {
11+
Id uint64
12+
Time time.Time
13+
Rate float64
14+
Symbol string
15+
}
16+
17+
type MultiRateRecord struct {
18+
Time time.Time
19+
Rates map[string]float64
20+
}
21+
22+
type MetadataRecord struct {
23+
Id uint64
24+
25+
Name string
26+
Symbol string
27+
28+
Seed string
29+
30+
Authority string
31+
32+
Mint string
33+
MintBump uint8
34+
Decimals uint8
35+
36+
CurrencyConfig string
37+
CurrencyConfigBump uint8
38+
39+
LiquidityPool string
40+
LiquidityPoolBump uint8
41+
42+
VaultMint string
43+
VaultMintBump uint8
44+
45+
VaultCore string
46+
VaultCoreBump uint8
47+
48+
FeesMint string
49+
BuyFeeBps uint16
50+
51+
FeesCore string
52+
SellFeeBps uint16
53+
54+
CreatedBy string
55+
CreatedAt time.Time
56+
}
57+
58+
func (m *MetadataRecord) Validate() error {
59+
if len(m.Name) == 0 {
60+
return errors.New("name is required")
61+
}
62+
63+
if len(m.Symbol) == 0 {
64+
return errors.New("symbol is required")
65+
}
66+
67+
if len(m.Seed) == 0 {
68+
return errors.New("seed is required")
69+
}
70+
71+
if len(m.Authority) == 0 {
72+
return errors.New("authority is required")
73+
}
74+
75+
if len(m.Mint) == 0 {
76+
return errors.New("mint is required")
77+
}
78+
79+
if m.MintBump == 0 {
80+
return errors.New("mint bump is required")
81+
}
82+
83+
if m.Decimals != currencycreator.DefaultMintDecimals {
84+
return errors.New("invalid mint decimals")
85+
}
86+
87+
if len(m.CurrencyConfig) == 0 {
88+
return errors.New("currency config is required")
89+
}
90+
91+
if m.CurrencyConfigBump == 0 {
92+
return errors.New("currency config bump is required")
93+
}
94+
95+
if len(m.LiquidityPool) == 0 {
96+
return errors.New("liquidity pool is required")
97+
}
98+
99+
if m.LiquidityPoolBump == 0 {
100+
return errors.New("liquidity pool bump is required")
101+
}
102+
103+
if len(m.VaultMint) == 0 {
104+
return errors.New("vault mint is required")
105+
}
106+
107+
if m.VaultMintBump == 0 {
108+
return errors.New("vault mint bump is required")
109+
}
110+
111+
if len(m.VaultCore) == 0 {
112+
return errors.New("vault core is required")
113+
}
114+
115+
if m.VaultCoreBump == 0 {
116+
return errors.New("vault core bump is required")
117+
}
118+
119+
if len(m.FeesMint) == 0 {
120+
return errors.New("fees mint is required")
121+
}
122+
123+
if m.BuyFeeBps != currencycreator.DefaultBuyFeeBps {
124+
return errors.New("invalid buy fee bps")
125+
}
126+
127+
if len(m.Name) == 0 {
128+
return errors.New("fees core is required")
129+
}
130+
131+
if m.SellFeeBps != currencycreator.DefaultSellFeeBps {
132+
return errors.New("invalid buy sell bps")
133+
}
134+
135+
if len(m.CreatedBy) == 0 {
136+
return errors.New("created by is required")
137+
}
138+
139+
if m.CreatedAt.IsZero() {
140+
return errors.New("creation timestamp is required")
141+
}
142+
143+
return nil
144+
}
145+
146+
func (m *MetadataRecord) Clone() *MetadataRecord {
147+
return &MetadataRecord{
148+
Id: m.Id,
149+
150+
Name: m.Name,
151+
Symbol: m.Symbol,
152+
153+
Seed: m.Seed,
154+
155+
Authority: m.Authority,
156+
157+
Mint: m.Mint,
158+
MintBump: m.MintBump,
159+
Decimals: m.Decimals,
160+
161+
CurrencyConfig: m.CurrencyConfig,
162+
CurrencyConfigBump: m.CurrencyConfigBump,
163+
164+
LiquidityPool: m.LiquidityPool,
165+
LiquidityPoolBump: m.LiquidityPoolBump,
166+
167+
VaultMint: m.VaultMint,
168+
VaultMintBump: m.VaultMintBump,
169+
170+
VaultCore: m.VaultCore,
171+
VaultCoreBump: m.VaultCoreBump,
172+
173+
FeesMint: m.FeesMint,
174+
BuyFeeBps: m.BuyFeeBps,
175+
176+
FeesCore: m.FeesCore,
177+
SellFeeBps: m.SellFeeBps,
178+
179+
CreatedBy: m.CreatedBy,
180+
CreatedAt: m.CreatedAt,
181+
}
182+
}
183+
184+
func (m *MetadataRecord) CopyTo(dst *MetadataRecord) {
185+
dst.Id = m.Id
186+
187+
dst.Name = m.Name
188+
dst.Symbol = m.Symbol
189+
190+
dst.Seed = m.Seed
191+
192+
dst.Authority = m.Authority
193+
194+
dst.Mint = m.Mint
195+
dst.MintBump = m.MintBump
196+
dst.Decimals = m.Decimals
197+
198+
dst.CurrencyConfig = m.CurrencyConfig
199+
dst.CurrencyConfigBump = m.CurrencyConfigBump
200+
201+
dst.LiquidityPool = m.LiquidityPool
202+
dst.LiquidityPoolBump = m.LiquidityPoolBump
203+
204+
dst.VaultMint = m.VaultMint
205+
dst.VaultMintBump = m.VaultMintBump
206+
207+
dst.VaultCore = m.VaultCore
208+
dst.VaultCoreBump = m.VaultCoreBump
209+
210+
dst.FeesMint = m.FeesMint
211+
dst.BuyFeeBps = m.BuyFeeBps
212+
213+
dst.FeesCore = m.FeesCore
214+
dst.SellFeeBps = m.SellFeeBps
215+
216+
dst.CreatedBy = m.CreatedBy
217+
dst.CreatedAt = m.CreatedAt
218+
}
219+
220+
type ReserveRecord struct {
221+
Id uint64
222+
Mint string
223+
SupplyFromBonding uint64
224+
CoreMintLocked uint64
225+
Time time.Time
226+
}
227+
228+
func (m *ReserveRecord) Validate() error {
229+
if len(m.Mint) == 0 {
230+
return errors.New("mint is required")
231+
}
232+
233+
if m.Time.IsZero() {
234+
return errors.New("timestamp is required")
235+
}
236+
237+
return nil
238+
}
239+
240+
func (m *ReserveRecord) Clone() *ReserveRecord {
241+
return &ReserveRecord{
242+
Id: m.Id,
243+
Mint: m.Mint,
244+
SupplyFromBonding: m.SupplyFromBonding,
245+
CoreMintLocked: m.CoreMintLocked,
246+
Time: m.Time,
247+
}
248+
}
249+
250+
func (m *ReserveRecord) CopyTo(dst *ReserveRecord) {
251+
dst.Id = m.Id
252+
dst.Mint = m.Mint
253+
dst.SupplyFromBonding = m.SupplyFromBonding
254+
dst.CoreMintLocked = m.CoreMintLocked
255+
dst.Time = m.Time
256+
}

0 commit comments

Comments
 (0)