code.vegaprotocol.io/vega@v0.79.0/datanode/sqlsubscribers/asset.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package sqlsubscribers 17 18 import ( 19 "context" 20 "fmt" 21 "math" 22 "time" 23 24 "code.vegaprotocol.io/vega/core/events" 25 "code.vegaprotocol.io/vega/datanode/entities" 26 "code.vegaprotocol.io/vega/protos/vega" 27 28 "github.com/pkg/errors" 29 "github.com/shopspring/decimal" 30 ) 31 32 type AssetEvent interface { 33 events.Event 34 Asset() vega.Asset 35 } 36 37 type AssetStore interface { 38 Add(context.Context, entities.Asset) error 39 } 40 41 type Asset struct { 42 subscriber 43 store AssetStore 44 } 45 46 func NewAsset(store AssetStore) *Asset { 47 return &Asset{ 48 store: store, 49 } 50 } 51 52 func (a *Asset) Types() []events.Type { 53 return []events.Type{events.AssetEvent} 54 } 55 56 func (a *Asset) Push(ctx context.Context, evt events.Event) error { 57 return a.consume(ctx, evt.(AssetEvent)) 58 } 59 60 func (a *Asset) consume(ctx context.Context, ae AssetEvent) error { 61 err := a.addAsset(ctx, ae.Asset(), ae.TxHash(), a.vegaTime) 62 if err != nil { 63 return errors.WithStack(err) 64 } 65 66 return nil 67 } 68 69 func (a *Asset) addAsset(ctx context.Context, va vega.Asset, txHash string, vegaTime time.Time) error { 70 quantum, err := decimal.NewFromString(va.Details.Quantum) 71 if err != nil { 72 return errors.Errorf("bad quantum '%v'", va.Details.Quantum) 73 } 74 75 var source, erc20Contract, chainID string 76 lifetimeLimit := decimal.Zero 77 withdrawalThreshold := decimal.Zero 78 switch src := va.Details.Source.(type) { 79 case *vega.AssetDetails_BuiltinAsset: 80 source = src.BuiltinAsset.MaxFaucetAmountMint 81 case *vega.AssetDetails_Erc20: 82 erc20Contract = src.Erc20.ContractAddress 83 if src.Erc20.LifetimeLimit != "" { 84 res, err := decimal.NewFromString(src.Erc20.LifetimeLimit) 85 if err != nil { 86 return fmt.Errorf("couldn't parse lifetime_limit: %w", err) 87 } 88 lifetimeLimit = res 89 } 90 if src.Erc20.WithdrawThreshold != "" { 91 res, err := decimal.NewFromString(src.Erc20.WithdrawThreshold) 92 if err != nil { 93 return fmt.Errorf("couldn't parse withdraw_threshold: %w", err) 94 } 95 withdrawalThreshold = res 96 } 97 chainID = src.Erc20.ChainId 98 default: 99 return errors.Errorf("unknown asset source: %v", source) 100 } 101 102 if va.Details.Decimals > math.MaxInt { 103 return errors.Errorf("decimals value will cause integer overflow: %d", va.Details.Decimals) 104 } 105 106 decimals := int(va.Details.Decimals) 107 108 asset := entities.Asset{ 109 ID: entities.AssetID(va.Id), 110 ChainID: chainID, 111 Name: va.Details.Name, 112 Symbol: va.Details.Symbol, 113 Decimals: decimals, 114 Quantum: quantum, 115 Source: source, 116 ERC20Contract: erc20Contract, 117 TxHash: entities.TxHash(txHash), 118 VegaTime: vegaTime, 119 LifetimeLimit: lifetimeLimit, 120 WithdrawThreshold: withdrawalThreshold, 121 Status: entities.AssetStatus(va.Status), 122 } 123 124 return errors.WithStack(a.store.Add(ctx, asset)) 125 } 126 127 func (a *Asset) Name() string { 128 return "Asset" 129 }