github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/types/types.go (about)

     1  package types
     2  
     3  import (
     4  	"context"
     5  	"crypto/hmac"
     6  	"crypto/sha256"
     7  	"encoding/base64"
     8  	"encoding/json"
     9  	"fmt"
    10  	"net/http"
    11  	"slices"
    12  	"strconv"
    13  	"strings"
    14  	"time"
    15  
    16  	"github.com/blocto/solana-go-sdk/client"
    17  	"github.com/ethereum/go-ethereum/ethclient"
    18  	"github.com/pkg/errors"
    19  	"github.com/tidwall/gjson"
    20  
    21  	"github.com/machinefi/w3bstream/pkg/depends/base/types"
    22  	"github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/datatypes"
    23  	"github.com/machinefi/w3bstream/pkg/depends/kit/validator/strfmt"
    24  	"github.com/machinefi/w3bstream/pkg/enums"
    25  )
    26  
    27  type UploadConfig struct {
    28  	FilesizeLimitBytes int64 `env:""`
    29  	DiskReserveBytes   int64 `env:""`
    30  }
    31  
    32  func (c *UploadConfig) SetDefault() {
    33  	if c.FilesizeLimitBytes == 0 {
    34  		c.FilesizeLimitBytes = 1024 * 1024
    35  	}
    36  	if c.DiskReserveBytes == 0 {
    37  		c.DiskReserveBytes = 20 * 1024 * 1024
    38  	}
    39  }
    40  
    41  type FileSystem struct {
    42  	Type enums.FileSystemMode `env:""`
    43  }
    44  
    45  func (f *FileSystem) SetDefault() {
    46  	if f.Type > enums.FILE_SYSTEM_MODE__S3 || f.Type <= 0 {
    47  		f.Type = enums.FILE_SYSTEM_MODE__LOCAL
    48  	}
    49  }
    50  
    51  type ETHClientConfig struct {
    52  	Endpoints string                       `env:""`
    53  	Clients   map[uint32]*ethclient.Client `env:"-"`
    54  }
    55  
    56  func (c *ETHClientConfig) Init() error {
    57  	c.Clients = make(map[uint32]*ethclient.Client)
    58  	if !gjson.Valid(c.Endpoints) {
    59  		fmt.Println(c.Endpoints)
    60  		return errors.Errorf("faild to parse endpoints from environment")
    61  	}
    62  	for k, v := range gjson.Parse(c.Endpoints).Map() {
    63  		chainID, err := strconv.Atoi(k)
    64  		if err != nil {
    65  			continue
    66  		}
    67  		url := v.String()
    68  		cli, err := ethclient.Dial(url)
    69  		if err != nil {
    70  			return err
    71  		}
    72  		c.Clients[uint32(chainID)] = cli
    73  	}
    74  	return nil
    75  }
    76  
    77  type Chain struct {
    78  	ChainID                         uint64          `json:"chainID,omitempty"`
    79  	Name                            enums.ChainName `json:"name"`
    80  	Endpoint                        string          `json:"endpoint"`
    81  	AABundlerEndpoint               string          `json:"aaBundlerEndpoint"`
    82  	AAPaymasterEndpoint             string          `json:"aaPaymasterEndpoint"`
    83  	AAEntryPointContractAddress     string          `json:"aaEntryPointContractAddress"`
    84  	AAAccountFactoryContractAddress string          `json:"aaAccountFactoryContractAddress"`
    85  }
    86  
    87  func (c *Chain) IsSolana() bool {
    88  	return c.Name == enums.SOLANA_DEVNET || c.Name == enums.SOLANA_TESTNET || c.Name == enums.SOLANA_MAINNET_BETA
    89  }
    90  
    91  func (c *Chain) IsZKSync() bool {
    92  	return c.Name == enums.ZKSYNC_ERA_MAINNET || c.Name == enums.ZKSYNC_ERA_TESTNET
    93  }
    94  
    95  func (c *Chain) IsEth() bool {
    96  	return c.ChainID != 0
    97  }
    98  
    99  func (c *Chain) IsAASupported() bool {
   100  	return c.AABundlerEndpoint != "" && c.AAPaymasterEndpoint != "" && c.AAEntryPointContractAddress != "" && c.AAAccountFactoryContractAddress != ""
   101  }
   102  
   103  type ChainConfig struct {
   104  	Configs          string                     `env:""     json:"-"`
   105  	Chains           map[enums.ChainName]*Chain `env:"-"    json:"-"`
   106  	ChainIDs         map[uint64]*Chain          `env:"-"    json:"-"`
   107  	AAUserOpEndpoint string                     `env:""     json:"-"`
   108  }
   109  
   110  func (cc *ChainConfig) LivenessCheck() map[string]string {
   111  	m := map[string]string{}
   112  
   113  	for _, c := range cc.Chains {
   114  		key := c.Endpoint
   115  		if err := cc.chainLivenessCheck(c); err != nil {
   116  			m[key] = err.Error()
   117  		} else {
   118  			m[key] = "ok"
   119  		}
   120  	}
   121  	return m
   122  }
   123  
   124  func (c *ChainConfig) Init() {
   125  	cs := []*Chain{}
   126  	if c.Configs != "" {
   127  		if err := json.Unmarshal([]byte(c.Configs), &cs); err != nil {
   128  			panic(err)
   129  		}
   130  	}
   131  
   132  	cm := make(map[enums.ChainName]*Chain)
   133  	cidm := make(map[uint64]*Chain)
   134  	for _, c := range cs {
   135  		cm[c.Name] = c
   136  		if c.ChainID != 0 {
   137  			cidm[c.ChainID] = c
   138  		}
   139  	}
   140  	c.Chains = cm
   141  	c.ChainIDs = cidm
   142  }
   143  
   144  func (c *ChainConfig) GetChain(chainID uint64, chainName enums.ChainName) (*Chain, bool) {
   145  	r, ok := c.ChainIDs[chainID]
   146  	if ok {
   147  		return r, ok
   148  	}
   149  	r, ok = c.Chains[chainName]
   150  	return r, ok
   151  }
   152  
   153  func (c *ChainConfig) chainLivenessCheck(chain *Chain) error {
   154  	if chain.IsSolana() {
   155  		cli := client.NewClient(chain.Endpoint)
   156  		_, err := cli.GetLatestBlockhash(context.Background())
   157  		return err
   158  	} else if chain.IsEth() {
   159  		cli, err := ethclient.Dial(chain.Endpoint)
   160  		if err != nil {
   161  			return err
   162  		}
   163  		defer cli.Close()
   164  
   165  		chainID, err := cli.ChainID(context.Background())
   166  		if err != nil {
   167  			return err
   168  		}
   169  		if chainID.Uint64() != chain.ChainID {
   170  			return errors.Errorf("chainID mismatch, want %d, got %d", chain.ChainID, chainID.Uint64())
   171  		}
   172  	}
   173  	return nil
   174  }
   175  
   176  // aliases from base/types
   177  type (
   178  	SFID                     = types.SFID
   179  	SFIDs                    = types.SFIDs
   180  	EthAddress               = types.EthAddress
   181  	Timestamp                = types.Timestamp
   182  	Initializer              = types.Initializer
   183  	ValidatedInitializer     = types.ValidatedInitializer
   184  	InitializerWith          = types.InitializerWith
   185  	ValidatedInitializerWith = types.ValidatedInitializerWith
   186  )
   187  
   188  type EthAddressWhiteList []string
   189  
   190  func (v *EthAddressWhiteList) Init() {
   191  	lst := EthAddressWhiteList{}
   192  	for _, addr := range *v {
   193  		if err := strfmt.EthAddressValidator.Validate(addr); err == nil {
   194  			lst = append(lst, strings.ToLower(addr))
   195  		}
   196  	}
   197  	*v = lst
   198  }
   199  
   200  func (v *EthAddressWhiteList) Validate(address string) bool {
   201  	if v == nil || len(*v) == 0 {
   202  		return true
   203  	}
   204  	for _, addr := range *v {
   205  		if addr == strings.ToLower(address) {
   206  			return true
   207  		}
   208  	}
   209  	return false
   210  }
   211  
   212  type StrategyResult struct {
   213  	ProjectName string         `json:"projectName" db:"f_prj_name"`
   214  	AppletID    types.SFID     `json:"appletID"    db:"f_app_id"`
   215  	AppletName  string         `json:"appletName"  db:"f_app_name"`
   216  	InstanceID  types.SFID     `json:"instanceID"  db:"f_ins_id"`
   217  	Handler     string         `json:"handler"     db:"f_hdl"`
   218  	EventType   string         `json:"eventType"   db:"f_evt"`
   219  	AutoCollect datatypes.Bool `json:"autoCollect" db:"f_auto_collect"`
   220  }
   221  
   222  type WasmDBConfig struct {
   223  	Endpoint        types.Endpoint
   224  	MaxConnection   int
   225  	PoolSize        int
   226  	ConnMaxLifetime types.Duration
   227  	LazyInit        bool
   228  }
   229  
   230  func (c *WasmDBConfig) SetDefault() {
   231  	if c.MaxConnection == 0 {
   232  		c.MaxConnection = 2
   233  	}
   234  	if c.PoolSize == 0 {
   235  		c.PoolSize = 2
   236  	}
   237  	if c.ConnMaxLifetime == 0 {
   238  		c.ConnMaxLifetime = *types.AsDuration(time.Second * 20)
   239  	}
   240  }
   241  
   242  type MetricsCenterConfig struct {
   243  	Endpoint      string `env:""`
   244  	ClickHouseDSN string `env:""`
   245  }
   246  
   247  type RobotNotifierConfig struct {
   248  	Vendor string   `env:""` // Vendor robot vendor eg: `Lark` `Wechat Work` `DingTalk`
   249  	Env    string   `env:""` // Env Service env, eg: dev-staging, prod
   250  	URL    string   `env:""` // URL webhook url
   251  	Secret string   `env:""` // Secret message secret
   252  	PINs   []string `env:""` // PINs pin someone
   253  
   254  	SignFn func(int64) (string, error) `env:"-"`
   255  }
   256  
   257  func (c *RobotNotifierConfig) IsZero() bool { return c == nil || c.URL == "" }
   258  
   259  func (c *RobotNotifierConfig) Init() {
   260  	if c.Secret != "" {
   261  		c.SignFn = func(ts int64) (string, error) {
   262  			payload := fmt.Sprintf("%v", ts) + "\n" + c.Secret
   263  
   264  			var data []byte
   265  			h := hmac.New(sha256.New, []byte(payload))
   266  			_, err := h.Write(data)
   267  			if err != nil {
   268  				return "", err
   269  			}
   270  
   271  			signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
   272  			return signature, nil
   273  		}
   274  	}
   275  }
   276  
   277  type Risc0Config struct {
   278  	Endpoint        string
   279  	Websocket       string
   280  	CreateProofPath string
   281  }
   282  
   283  func (r *Risc0Config) LivenessCheck() map[string]string {
   284  	m := map[string]string{}
   285  
   286  	_, err := http.NewRequest("GET", fmt.Sprintf("http://%s", r.Endpoint), nil)
   287  	if err != nil {
   288  		m[r.Endpoint] = err.Error()
   289  	} else {
   290  		m[r.Endpoint] = "ok"
   291  	}
   292  
   293  	return m
   294  }
   295  
   296  type ProjectFilter struct {
   297  	WhiteList []SFID
   298  	BlackList []SFID
   299  }
   300  
   301  func (f *ProjectFilter) Filter(id types.SFID) bool {
   302  	if len(f.WhiteList) > 0 {
   303  		return slices.Contains(f.WhiteList, id)
   304  	}
   305  	if len(f.BlackList) > 0 {
   306  		return !slices.Contains(f.BlackList, id)
   307  	}
   308  	return true
   309  }