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  }