diff --git a/cli/cli.go b/cli/cli.go index 596b0c68..b9b5d9e1 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -20,6 +20,7 @@ func init() { RootCmd.AddCommand(initiator.StartResigning) RootCmd.AddCommand(initiator.GenerateReshareMsg) RootCmd.AddCommand(initiator.StartReshare) + RootCmd.AddCommand(initiator.StartServer) } // RootCmd represents the root command of DKG-tool CLI @@ -40,6 +41,7 @@ func Execute(appName, version string) { initiator.StartResigning.Version = version initiator.GenerateReshareMsg.Version = version initiator.StartReshare.Version = version + initiator.StartServer.Version = version operator.StartDKGOperator.Version = version if err := RootCmd.Execute(); err != nil { log.Fatal("failed to execute root command", zap.Error(err)) diff --git a/cli/flags/init.go b/cli/flags/init.go index bb51bef5..4d01f600 100644 --- a/cli/flags/init.go +++ b/cli/flags/init.go @@ -61,6 +61,11 @@ func SetInitFlags(cmd *cobra.Command) { SetTLSInsecureFlag(cmd) } +func SetInitServerFlags(cmd *cobra.Command) { + SetBaseFlags(cmd) + SetPortFlag(cmd) +} + // BindInitiatorBaseFlags binds flags to yaml config parameters func BindInitiatorBaseFlags(cmd *cobra.Command) error { var err error @@ -174,6 +179,20 @@ func BindInitFlags(cmd *cobra.Command) error { return nil } +func BindInitServerFlags(cmd *cobra.Command) error { + if err := BindBaseFlags(cmd); err != nil { + return err + } + if err := viper.BindPFlag("port", cmd.PersistentFlags().Lookup("port")); err != nil { + return err + } + Port = viper.GetUint64("port") + if Port == 0 { + return fmt.Errorf("😥 Wrong port provided") + } + return nil +} + // SetViperConfig reads a yaml config file if provided func SetViperConfig(cmd *cobra.Command) error { if err := viper.BindPFlag("configPath", cmd.PersistentFlags().Lookup("configPath")); err != nil { diff --git a/cli/flags/operator.go b/cli/flags/operator.go index 00eaf17d..45d1eddd 100644 --- a/cli/flags/operator.go +++ b/cli/flags/operator.go @@ -37,7 +37,7 @@ func SetOperatorFlags(cmd *cobra.Command) { SetBaseFlags(cmd) PrivateKeyFlag(cmd) PrivateKeyPassFlag(cmd) - OperatorPortFlag(cmd) + SetPortFlag(cmd) OperatorIDFlag(cmd) SetServerTLSCertPath(cmd) SetServerTLSKeyPath(cmd) @@ -111,9 +111,9 @@ func PrivateKeyPassFlag(c *cobra.Command) { AddPersistentStringFlag(c, privKeyPassword, "", "Password to decrypt initiator`s Private Key file", false) } -// OperatorPortFlag adds operator listening port flag to the command -func OperatorPortFlag(c *cobra.Command) { - AddPersistentIntFlag(c, operatorPort, 3030, "Operator Private Key hex", false) +// SetPortFlag adds operator listening port flag to the command +func SetPortFlag(c *cobra.Command) { + AddPersistentIntFlag(c, operatorPort, 3030, "Port to listen", false) } // OperatorIDFlag add operator ID flag to the command diff --git a/cli/initiator/initiator.go b/cli/initiator/initiator.go index 9003f183..bc7c9c88 100644 --- a/cli/initiator/initiator.go +++ b/cli/initiator/initiator.go @@ -2,29 +2,22 @@ package initiator import ( "context" - "encoding/hex" "fmt" "log" e2m_core "github.com/bloxapp/eth2-key-manager/core" - "github.com/sourcegraph/conc/pool" "github.com/spf13/cobra" "go.uber.org/zap" - spec "github.com/ssvlabs/dkg-spec" "github.com/ssvlabs/ssv-dkg/cli/flags" cli_utils "github.com/ssvlabs/ssv-dkg/cli/utils" "github.com/ssvlabs/ssv-dkg/pkgs/initiator" - "github.com/ssvlabs/ssv-dkg/pkgs/wire" -) - -const ( - // maxConcurrency is the maximum number of DKG inits to run concurrently. - maxConcurrency = 20 + "github.com/ssvlabs/ssv-dkg/pkgs/initiator/server" ) func init() { flags.SetInitFlags(StartDKG) + flags.SetInitServerFlags(StartServer) } var StartDKG = &cobra.Command{ @@ -69,74 +62,60 @@ var StartDKG = &cobra.Command{ } // start the ceremony ctx := context.Background() - pool := pool.NewWithResults[*Result]().WithContext(ctx).WithFirstError().WithMaxGoroutines(maxConcurrency) - for i := 0; i < int(flags.Validators); i++ { - i := i - pool.Go(func(ctx context.Context) (*Result, error) { - // Create new DKG initiator - dkgInitiator, err := initiator.New(opMap.Clone(), logger, cmd.Version, flags.ClientCACertPath, flags.TLSInsecure) - if err != nil { - return nil, err - } - // Create a new ID. - id := spec.NewID() - nonce := flags.Nonce + uint64(i) - // Perform the ceremony. - depositData, keyShares, proofs, err := dkgInitiator.StartDKG(id, flags.WithdrawAddress.Bytes(), operatorIDs, ethNetwork, flags.OwnerAddress, nonce, flags.Amount) - if err != nil { - return nil, err - } - logger.Debug("DKG ceremony completed", - zap.String("id", hex.EncodeToString(id[:])), - zap.Uint64("nonce", nonce), - zap.String("pubkey", depositData.PubKey), - ) - return &Result{ - id: id, - depositData: depositData, - keyShares: keyShares, - nonce: nonce, - proof: proofs, - }, nil - }) - } - results, err := pool.Wait() - if err != nil { - logger.Fatal("😥 Failed to initiate DKG ceremony: ", zap.Error(err)) - } - var depositDataArr []*wire.DepositDataCLI - var keySharesArr []*wire.KeySharesCLI - var proofs [][]*wire.SignedProof - for _, res := range results { - depositDataArr = append(depositDataArr, res.depositData) - keySharesArr = append(keySharesArr, res.keyShares) - proofs = append(proofs, res.proof) - } - // Save results - logger.Info("🎯 All data is validated.") - if err := cli_utils.WriteResults( + initiator.StartInitCeremony( + ctx, logger, - depositDataArr, - keySharesArr, - proofs, - false, - int(flags.Validators), + opMap, + operatorIDs, flags.OwnerAddress, - flags.Nonce, flags.WithdrawAddress, + flags.Nonce, + flags.Amount, + uint64(flags.Validators), + ethNetwork, + flags.ClientCACertPath, + flags.TLSInsecure, flags.OutputPath, - ); err != nil { - logger.Fatal("Could not save results", zap.Error(err)) - } - logger.Info("🚀 DKG ceremony completed") + cmd.Version) return nil }, } -type Result struct { - id [24]byte - nonce uint64 - depositData *wire.DepositDataCLI - keyShares *wire.KeySharesCLI - proof []*wire.SignedProof +var StartServer = &cobra.Command{ + Use: "initiator_server", + Short: "Starts server to accept commands by http", + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Println(` + █████╗ ██╗ ██╗ ██████╗ ██╗███╗ ██╗██╗████████╗██╗ █████╗ ████████╗ ██████╗ ██████╗ + ██╔══██╗██║ ██╔╝██╔════╝ ██║████╗ ██║██║╚══██╔══╝██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ + ██║ ██║█████╔╝ ██║ ███╗ ██║██╔██╗ ██║██║ ██║ ██║███████║ ██║ ██║ ██║██████╔╝ + ██║ ██║██╔═██╗ ██║ ██║ ██║██║╚██╗██║██║ ██║ ██║██╔══██║ ██║ ██║ ██║██╔══██╗ + ██████╔╝██║ ██╗╚██████╔╝ ██║██║ ╚████║██║ ██║ ██║██║ ██║ ██║ ╚██████╔╝██║ ██║ + ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝`) + if err := flags.SetViperConfig(cmd); err != nil { + return err + } + if err := flags.BindInitServerFlags(cmd); err != nil { + return err + } + logger, err := cli_utils.SetGlobalLogger(cmd, "dkg-initiator-server", flags.LogFilePath, flags.LogLevel, flags.LogFormat, flags.LogLevelFormat) + if err != nil { + return err + } + defer func() { + if err := cli_utils.Sync(logger); err != nil { + log.Printf("Failed to sync logger: %v", err) + } + }() + logger.Info("🪛 Initiator`s", zap.String("Version", cmd.Version)) + srv, err := server.New(logger, cmd.Version, flags.OutputPath) + if err != nil { + logger.Fatal("😥 failed to create initiator server: ", zap.Error(err)) + } + logger.Info("🚀 Starting DKG initiator server", zap.Uint64("at port", flags.Port)) + if err := srv.Start(uint16(flags.Port)); err != nil { + logger.Fatal("error starting server", zap.Error(err)) + } + return nil + }, } diff --git a/cli/operator/operator.go b/cli/operator/operator.go index a7ebc548..6533d739 100644 --- a/cli/operator/operator.go +++ b/cli/operator/operator.go @@ -54,7 +54,7 @@ var StartDKGOperator = &cobra.Command{ } logger.Info("🚀 Starting DKG operator", zap.Uint64("at port", flags.Port)) if err := srv.Start(uint16(flags.Port), flags.ServerTLSCertPath, flags.ServerTLSKeyPath); err != nil { - log.Fatalf("Error in operator %v", err) + logger.Fatal("error starting server at operator", zap.Error(err)) } return nil }, diff --git a/cli/utils/utils.go b/cli/utils/utils.go index 871ede74..5749661b 100644 --- a/cli/utils/utils.go +++ b/cli/utils/utils.go @@ -23,7 +23,6 @@ import ( spec "github.com/ssvlabs/dkg-spec" "github.com/ssvlabs/ssv-dkg/pkgs/crypto" - "github.com/ssvlabs/ssv-dkg/pkgs/initiator" "github.com/ssvlabs/ssv-dkg/pkgs/utils" "github.com/ssvlabs/ssv-dkg/pkgs/validator" "github.com/ssvlabs/ssv-dkg/pkgs/wire" @@ -241,7 +240,7 @@ func WriteAggregatedInitResults(dir string, depositDataArr []*wire.DepositDataCL } keysharesFinalPath := fmt.Sprintf("%s/keyshares.json", dir) logger.Info("💾 Writing keyshares payload to file", zap.String("path", keysharesFinalPath)) - aggrKeySharesArr, err := initiator.GenerateAggregatesKeyshares(keySharesArr) + aggrKeySharesArr, err := GenerateAggregatesKeyshares(keySharesArr) if err != nil { return err } @@ -413,3 +412,15 @@ func SetGlobalLogger(cmd *cobra.Command, name, logFilePath, logLevel, logFormat, logger := zap.L().Named(name) return logger, nil } + +func GenerateAggregatesKeyshares(keySharesArr []*wire.KeySharesCLI) (*wire.KeySharesCLI, error) { + var data []*wire.Data + for _, keyShares := range keySharesArr { + data = append(data, keyShares.Shares...) + } + ks := &wire.KeySharesCLI{} + ks.Version = "v1.2.0" + ks.Shares = data + ks.CreatedAt = time.Now().UTC() + return ks, nil +} diff --git a/docker-compose.yml b/docker-compose.yml index e8d5e2c6..5c47b576 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -296,5 +296,18 @@ services: volumes: - ./examples:/data + initiator_server: + image: ssv-dkg:latest + networks: + - shared_network + command: + [ + "initiator_server", + "--configPath", + "/data/config/initiator_server.example.yaml", + ] + volumes: + - ./examples:/data + networks: shared_network: diff --git a/examples/config/initiator_server.example.yaml b/examples/config/initiator_server.example.yaml new file mode 100644 index 00000000..97353bee --- /dev/null +++ b/examples/config/initiator_server.example.yaml @@ -0,0 +1,6 @@ +port: 8080 +outputPath: /data/initiator/output +logLevel: info +logFormat: json +logLevelFormat: capitalColor +logFilePath: /data/initiator/output/initiator_debug.log diff --git a/pkgs/initiator/ceremony.go b/pkgs/initiator/ceremony.go new file mode 100644 index 00000000..9aeec9e8 --- /dev/null +++ b/pkgs/initiator/ceremony.go @@ -0,0 +1,90 @@ +package initiator + +import ( + "context" + "encoding/hex" + + e2m_core "github.com/bloxapp/eth2-key-manager/core" + "github.com/ethereum/go-ethereum/common" + "github.com/sourcegraph/conc/pool" + spec "github.com/ssvlabs/dkg-spec" + cli_utils "github.com/ssvlabs/ssv-dkg/cli/utils" + "github.com/ssvlabs/ssv-dkg/pkgs/wire" + "go.uber.org/zap" +) + +const ( + // maxConcurrency is the maximum number of DKG inits to run concurrently. + maxConcurrency = 20 +) + +type Result struct { + id [24]byte + nonce uint64 + depositData *wire.DepositDataCLI + keyShares *wire.KeySharesCLI + proof []*wire.SignedProof +} + +func StartInitCeremony(ctx context.Context, logger *zap.Logger, opMap wire.OperatorsCLI, operatorIDs []uint64, ownerAddress, withdrawAddress common.Address, nonce, amount, validators uint64, ethNetwork e2m_core.Network, clientCACertPath []string, tlsInsecure bool, outputPath, ver string) { + pool := pool.NewWithResults[*Result]().WithContext(ctx).WithFirstError().WithMaxGoroutines(maxConcurrency) + for i := 0; i < int(validators); i++ { + i := i + pool.Go(func(ctx context.Context) (*Result, error) { + // Create new DKG initiator + dkgInitiator, err := New(opMap.Clone(), logger, ver, clientCACertPath, tlsInsecure) + if err != nil { + return nil, err + } + // Create a new ID. + id := spec.NewID() + nonce := nonce + uint64(i) + // Perform the ceremony. + depositData, keyShares, proofs, err := dkgInitiator.StartDKG(id, withdrawAddress.Bytes(), operatorIDs, ethNetwork, ownerAddress, nonce, amount) + if err != nil { + return nil, err + } + logger.Debug("DKG ceremony completed", + zap.String("id", hex.EncodeToString(id[:])), + zap.Uint64("nonce", nonce), + zap.String("pubkey", depositData.PubKey), + ) + return &Result{ + id: id, + depositData: depositData, + keyShares: keyShares, + nonce: nonce, + proof: proofs, + }, nil + }) + } + results, err := pool.Wait() + if err != nil { + logger.Fatal("😥 Failed to initiate DKG ceremony: ", zap.Error(err)) + } + var depositDataArr []*wire.DepositDataCLI + var keySharesArr []*wire.KeySharesCLI + var proofs [][]*wire.SignedProof + for _, res := range results { + depositDataArr = append(depositDataArr, res.depositData) + keySharesArr = append(keySharesArr, res.keyShares) + proofs = append(proofs, res.proof) + } + // Save results + logger.Info("🎯 All data is validated.") + if err := cli_utils.WriteResults( + logger, + depositDataArr, + keySharesArr, + proofs, + false, + int(validators), + ownerAddress, + nonce, + withdrawAddress, + outputPath, + ); err != nil { + logger.Fatal("Could not save results", zap.Error(err)) + } + logger.Info("🚀 DKG ceremony completed") +} diff --git a/pkgs/initiator/initiator.go b/pkgs/initiator/initiator.go index 1f78cf4a..f96b47b8 100644 --- a/pkgs/initiator/initiator.go +++ b/pkgs/initiator/initiator.go @@ -86,18 +86,6 @@ func (c *Initiator) generateSSVKeysharesPayload(operators []*spec.Operator, dkgR return ks, nil } -func GenerateAggregatesKeyshares(keySharesArr []*wire.KeySharesCLI) (*wire.KeySharesCLI, error) { - var data []*wire.Data - for _, keyShares := range keySharesArr { - data = append(data, keyShares.Shares...) - } - ks := &wire.KeySharesCLI{} - ks.Version = "v1.2.0" - ks.Shares = data - ks.CreatedAt = time.Now().UTC() - return ks, nil -} - // New creates a main initiator structure func New(operators wire.OperatorsCLI, logger *zap.Logger, ver string, certs []string, tlsInsecure bool) (*Initiator, error) { client := req.C() @@ -374,6 +362,9 @@ func (c *Initiator) StartDKG(id [24]byte, withdraw []byte, ids []uint64, network Nonce: nonce, Amount: amount, } + if err := spec.ValidateInitMessage(init); err != nil { + return nil, nil, nil, err + } c.Logger.Info("Outgoing init request fields", zap.String("network", hex.EncodeToString(init.Fork[:])), zap.String("withdrawal", hex.EncodeToString(init.WithdrawalCredentials)), diff --git a/pkgs/initiator/server/handlers.go b/pkgs/initiator/server/handlers.go new file mode 100644 index 00000000..1bf0d631 --- /dev/null +++ b/pkgs/initiator/server/handlers.go @@ -0,0 +1,54 @@ +package server + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "go.uber.org/zap" + + e2m_core "github.com/bloxapp/eth2-key-manager/core" + "github.com/ethereum/go-ethereum/common" + "github.com/ssvlabs/ssv-dkg/pkgs/initiator" + "github.com/ssvlabs/ssv-dkg/pkgs/utils" + "github.com/ssvlabs/ssv-dkg/pkgs/wire" +) + +func (s *Server) initHandler(writer http.ResponseWriter, request *http.Request) { + ctx := context.Background() + s.Logger.Debug("incoming initial DKG msg") + rawdata, err := io.ReadAll(request.Body) + if err != nil { + s.Logger.Error("failed to read request body", zap.Error(err)) + utils.WriteErrorResponse(s.Logger, writer, fmt.Errorf("failed to read request body %w", err), http.StatusBadRequest) + return + } + var initCommandRequest wire.InitJSON + if err := json.Unmarshal(rawdata, &initCommandRequest); err != nil { + s.Logger.Error("failed to unmarshal body", zap.Error(err)) + utils.WriteErrorResponse(s.Logger, writer, fmt.Errorf("failed to unmarshal body %w", err), http.StatusBadRequest) + } + ethNetwork := e2m_core.NetworkFromString(initCommandRequest.Network) + if ethNetwork == "" { + s.Logger.Fatal("😥 Cant recognize eth network") + } + initiator.StartInitCeremony( + ctx, + s.Logger, + initCommandRequest.Operators, + initCommandRequest.OperatorIDs, + common.HexToAddress(initCommandRequest.Owner), + common.HexToAddress(initCommandRequest.WithdrawalCredentials), + initCommandRequest.Nonce, + initCommandRequest.Amount, + initCommandRequest.Validators, + ethNetwork, + nil, + true, + s.OutputPath, + s.Version, + ) + writer.WriteHeader(http.StatusOK) +} diff --git a/pkgs/initiator/server/router.go b/pkgs/initiator/server/router.go new file mode 100644 index 00000000..3c168365 --- /dev/null +++ b/pkgs/initiator/server/router.go @@ -0,0 +1,52 @@ +package server + +import ( + "net/http" + "time" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/httprate" + "go.uber.org/zap" +) + +// request limits +const ( + generalLimit = 5000 + timePeriod = time.Minute +) + +// RegisterRoutes creates routes at operator to process messages incoming from initiator +func RegisterRoutes(s *Server) { + s.Router.Use(rateLimit(s.Logger, generalLimit)) + addRoute(s.Router, "POST", "/init", s.initHandler, rateLimit(s.Logger, generalLimit)) + // addRoute(s.Router, "GET", "/health_check", s.healthHandler, rateLimit(s.Logger, generalLimit)) + // addRoute(s.Router, "POST", "/resign", s.signedResignHandler, rateLimit(s.Logger, generalLimit)) + // addRoute(s.Router, "POST", "/reshare", s.signedReshareHandler, rateLimit(s.Logger, generalLimit)) +} + +// Add route with optional middleware +func addRoute(router chi.Router, method, path string, handler http.HandlerFunc, middleware ...func(http.Handler) http.Handler) { + if len(middleware) > 0 { + router.With(middleware...).MethodFunc(method, path, handler) + } else { + router.MethodFunc(method, path, handler) + } +} + +func rateLimit(logger *zap.Logger, limit int) func(http.Handler) http.Handler { + return httprate.Limit( + limit, + timePeriod, + httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) { + logger.Debug("rate limit exceeded", + zap.String("ip", r.RemoteAddr), + zap.String("path", r.URL.Path)) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusTooManyRequests) + _, err := w.Write([]byte(ErrTooManyRouteRequests)) + if err != nil { + logger.Error("error writing rate limit response", zap.Error(err)) + } + }), + ) +} diff --git a/pkgs/initiator/server/server.go b/pkgs/initiator/server/server.go new file mode 100644 index 00000000..69d77089 --- /dev/null +++ b/pkgs/initiator/server/server.go @@ -0,0 +1,47 @@ +package server + +import ( + "fmt" + "net/http" + "time" + + "github.com/go-chi/chi/v5" + "go.uber.org/zap" +) + +// Server structure for operator to store http server and DKG ceremony instances +type Server struct { + Logger *zap.Logger // logger + HttpServer *http.Server // http server + Router chi.Router // http router + OutputPath string + Version string +} + +// TODO: either do all json or all SSZ +const ErrTooManyRouteRequests = `{"error": "too many requests to /route"}` + +// New creates Server structure using operator's RSA private key +func New(logger *zap.Logger, ver, outputPath string) (*Server, error) { + r := chi.NewRouter() + s := &Server{ + Logger: logger, + Router: r, + OutputPath: outputPath, + Version: ver, + } + RegisterRoutes(s) + return s, nil +} + +// Start runs a http server to listen for incoming messages at specified port +func (s *Server) Start(port uint16) error { + srv := &http.Server{Addr: fmt.Sprintf(":%v", port), Handler: s.Router, ReadHeaderTimeout: 10_000 * time.Millisecond} + s.HttpServer = srv + err := s.HttpServer.ListenAndServe() + if err != nil { + return err + } + s.Logger.Info("✅ Server is listening for incoming requests", zap.Uint16("port", port)) + return nil +} diff --git a/pkgs/wire/types_json.go b/pkgs/wire/types_json.go index 22506a51..8dea323d 100644 --- a/pkgs/wire/types_json.go +++ b/pkgs/wire/types_json.go @@ -703,6 +703,17 @@ func (r *ReshareMessage) UnmarshalJSON(data []byte) error { return nil } +type InitJSON struct { + Operators []OperatorCLI `json:"operatorsInfo"` + Validators uint64 `json:"validators"` + OperatorIDs []uint64 `json:"operatorIDs"` + WithdrawalCredentials string `json:"withdrawAddress"` + Network string `json:"network"` + Owner string `json:"owner"` + Nonce uint64 `json:"nonce"` + Amount uint64 `json:"amount"` +} + // TODO: duplicate from crypto. Resolve func ParseRSAPublicKey(pk []byte) (*rsa.PublicKey, error) { operatorKeyByte, err := base64.StdEncoding.DecodeString(string(pk)) diff --git a/utils/test-init-request/README.md b/utils/test-init-request/README.md new file mode 100644 index 00000000..449dcfbf --- /dev/null +++ b/utils/test-init-request/README.md @@ -0,0 +1,5 @@ +``` +$ npm install +$ npx tsc +$ node index.js +``` diff --git a/utils/test-init-request/index.ts b/utils/test-init-request/index.ts new file mode 100644 index 00000000..de377bc6 --- /dev/null +++ b/utils/test-init-request/index.ts @@ -0,0 +1,105 @@ +var operators = [ + { + id: 11, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdkFXRFppc1d4TUV5MGNwdjhoanAKQThDMWNYZ3VseHkyK0tDNldpWGo3NThuMjl4b1NsNHV1SjgwQ2NqQXJqbGQrWkNEWmxvSlhtMk51L0FFOFRaMgpQRW1UZFcxcGp5TmV1N2RDUWtGTHF3b3JGZ1AzVWdxczdQSEpqSE1mOUtTb1Y0eUxlbkxwYlR0L2tEczJ1Y1c3CnUrY3hvZFJ4d01RZHZiN29mT0FhbVhxR1haZ0NhNHNvdHZmSW9RS1dDaW9MczcvUkM3dHJrUGJONW4rbHQyZWEKd1J1SFRTTlNZcEdmbi9ud0FROHVDaW55SnNQV0Q0NUhldG9GekNKSlBnNjYzVzE1K1VsWU9tQVJCcWtaSVBISAp5V25ORjZTS2tRalI2MDJwQ3RXTkZRMi9wUVFqblJXbUkrU2FjMHhXRVQ3UUlsVmYxSGZ2NWRnWE9OT05hTTlFClN3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator1:3030", + }, + { + id: 22, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdnRVRWFlallqY3pBUWhnSTQ0S3cKcGZYZjhCNk1ZUjhOMzFmRVFLRGRDVmo5dUNPcHVybzYzSDdxWXNzMzVGaVdxNmRwMjR3M0dCRTAzR1llU1BSZgowTEVBVEJkYlhCVkY3WGR6ei9sV2UrblJNRG1Xdm1DTUZjRlRPRU5FYmhuTXVjOEQ1K3ZFTmo5cTQzbE4vejhqCmE2T2M4S2tEL2E4SW02Nm54ZkRhMjFyMzNaSW9GL1g5d0g2K25EN3Jockx5bzJub1lxaVJpT1NTTkp2R25UY08KazBmckk4b2xFNjR1clhxWXFLN2ZicXNaN082NnphN2ROTmc3MW1EWHlpdDlSTUlyR3lSME5xN0FUSkxwbytoTApEcldoY0h4M0NWb1dQZzNuR2phN0duVFhXU2FWb1JPSnBRVU9oYXgxNVJnZ2FBOHpodGgyOUorNnNNY2R6ZitQCkZ3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator2:3030", + }, + { + id: 33, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdlFhZlo0ODJQYXRsYnRrOVdIb2MKZDBWdWNWWDk4QUlzenAvazlFTlYyQU82SVhQUXVqU1BtdUZrQTlibThsSllnWTJPb0lQU0RmK1JHWGNMc2R0VApzdEJhQ2JPL0pMOFlSejk4NURKejhBRlhDU0J3bW5mbzROSFptUjJGMVdMTE5CS2wzdVQ5Q1VLbC9RUnpKRFF1CjNNYVJ6eE5FVmdONWtvU1Nid0NxVDNDSCtjam5QU0pIeGhiaTNTaldOSnJFb3ZRUmN3ZUlpYXRrZEdVNWJOUkoKUW1LVldhYzhzVklYN2NDNE54V2RDNG1VM1RPK2Vlei90N2xVcnhSNjdnb21TbGdwaU5weFJ1M2dFajRkSWpINwpsZDlTYW1ObEJPeHV5N0lFMEJpdm5nSUdIKzVwcXZVTXhoM0N5WkVtMjFHd3JTRFhqcVpwWG92OEUwQkQ5eGY4ClN3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator3:3030", + }, + { + id: 44, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBeFRWM2I5OHU4NmtzcEhQcWgrS2QKKzRHd0lSeEhwRHpEZjVlc3hjZytxaTlvbDRERmplUXMrbGloeUp5cGdOMXJwdTlQVnR5cXp2K3k5cEVNa0VXTgovYjBUQmdRMEp5TzdmNGliY1d5UUcrNGhVUS9XY3h1ZW5aUDA3S0VwTjh4Tk8xN3BzbmhRMXRqQVhybDNGN1lYCmlZdXl5Z0Rta2w0YjYrUDR6MjNhR01VSEtnTnJ5aFlZTFV4dWdycDVRTnJTV3lXNXFtb2EvYnJDenQ2RFJYb1UKU25JSkpSUVpPS2NnckdKMHVBYjJDRmtsL0xuaElxT2RZZ21aUG9oRmprVEorRnZNdkZsMjAwZ1BHbVpxUS9MMgpsM2ZBdmhZYlZRMlRVeUtmU2orYXZ1WUFZZnhKeG5OcWlmdkNkVGNmQzc3c0N0eFFERWVjY0pTVnVDbGZWeTFZCll3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator4:3030", + }, + { + id: 55, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBeXdVQzlqdTIrVHd3V29KeHh6SUMKR0V3RzZHUkQ4ekg4ZHVmMjNJVFJJdEtRZWlaUGpFdGQ1di9qTVRuYVdUK3NocEtaK3cvdEdkam8xc0xPeGk1ZQpDeVhPVllvSXE5UnVmcUxpSjNnQ0NmOGdaNnA1Tjl5b0I3bysySFVzbGpaYjN4QXlsbk03NU42LzJ2ZDZ2TTgvCnpFMWhBejVTMlhEQlB5UU5Bc2FhRkxzZjJEdDdmS1JWZWFWVWk0bGU1dzdVN3pnTmcvV1hNMlBVY1Z5YytZL1kKaS85dnlKN2hxMW1STXpITDVkUVE0YVU2NnI3LzNBVFlncWlKQjd2NzBOY0RNd2lMcnNKOEo3Tnh0aVpZdi9CbApXdHVqR3B3b3ltWUwzSGJLTXdJS1NMOEtweFpsNXZjL0ZZcjNSbmdDcXhJQjJ3ME1JNE51NkZqbTduZCtuYWxzCkl3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator5:3030", + }, + { + id: 66, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMFBQUXJSU2xmKzJhNHNIb1dFc28KUmFKTGhRWUo2NUdhN2gzeW5CbnB1bUxlck16NElUOVlGWUJxcHVzWXJ2dy9Ha2dpUWI3UXVHTGdWWUhwc01LcgpmOFFxM21odndkUU5Ya1duU1ZOb3p6SmlGZG13d1RXOHh1MElpQkEyWEpMa2Y5bFFNYUxlR2xnYythVThWUFg5CnFRQ2pVR1ZKY3k5eDRwUDNNNE8wRzBOckRPMzBTUHliU01JY2J6NHlESEo1ZDFDbkI5R1pUT0xjcEt5Y1BSZUUKWXIxR1ZYMlpxZjQwU2FYMjRLbXU0UGNUbmFERWh3cVBkaGQzLytQdHVmZGpLYVczdC9yeXVCcERuYlI2VXhLSwpzWEM5VTZNMExkSnVVaEJsQ3RhNnh5WlgvcWVLUDNTT0J6NEF1bGpnNnNNK2tsLzNoejFEVWllZUVpU1JFWGJUCnN3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator6:3030", + }, + { + id: 77, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBcjVLeDJqRXhNejcwR3lVVkM4VDAKdkd4UlBsMFU1eWFQVzZVTWZ4ekhUOXN0TE1ZbUhuSnMxTXdHQjIzcW4yc3NZeDJ2VGlWcUVXSDNDQnZjWjJoaQo5K29CYmRnRExtVDREU0dSbXlHbU1zWFgyTWlsaG9qU0hxNzIza1MxcEN0SnBGckpEU1RlQThPd1Q1VXMyc1FYCkM4Q0Z6c21tMG5OOWFkajg1SVJUbEJpRy9DMXErYXVtZmF4SGZEMCtLbjc0WXc0SnJqNDJIS21VaXdaUGRBbTgKRlM4YmUrZkdQdkdCNXJkYXNNdjV2eG56OUttN25Ld1UrTnJVcUZvVEgzUDcyOGpUQUpMbUZVUnhncTFGei9ITApVNkwwakI1RDdWanFmSUZ0ZThlbWp4VlByVEFOU0lLVUZBNEFKc2NVdHdmblJ4TW02SXJnaUJqK2tJQlpodDl0CjlRSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator7:3030", + }, + { + id: 88, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdTNablJKYUwvZ244ekJqQldqazIKSGIvT0RvSWhrR0xDVlVtNU9KZXB3ckZRTWxVeFI3S0lFMnZhUkkrM1BZb2VscmNwd3diWFFpUldhOCs3cHh2QwpQdGhRS2xob2NKUXVyR1hIMVlhYmNHV0RKdnRWWjJ3ZDY1cHNxYkNpOTE5Zmovdk1KVFEyNVE1c1M5SXU0UjF3ClVVcEt1TU4xUkg5RTE4cnpsSjdxQ3ZMZmVLRkZmd3llZ2NMN0tONUFBNjE5VUY3eFlrZU1VZmFNMDA3K2VzZFgKdG5icWNIWE5kVlRhT3FlZFcreXhHSU10QUFmN29EVnZvcVAydGJIckN3TFpXb0Y0NkFWRjVaaVdldzhKZnI5dgpMUDBiTnpIekNqQkRPS0dZeWEvQWc2TlpEdGxBdlREelVpMnU4YU9ycWs1aERscWk1VDMrZWhRdjFxQzRBZjZHCjV3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator8:3030", + }, + { + id: 99, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdmNPQ0VRbGl2RXVOWlpkaUZSMlUKQnRiVm5YZ0EyajdDcmp2MWJwdmcxNXVXL2h1eWQrU2l3T1BYdXZ2V3ZZNDNhTVR0WVA5QTNjRVlPZWEzRWJFVgpOdHZqTCt3QkRCbUUvNjYxemsrUzdyc3ZlY2pVUHB4KyswOUp2WGVOYlVWYllGR3h5eGlpVHpqU2hlZE5MOWFzCk1SbmpJTi9KcnFNS2I3akh5MVFway9rWUsrZ0Iwc0tVbHNFV0UveEJ5bmxWdXFRLzZkZWh3bjFqbnR6czJHOHgKQ3VINXBzcWxGbWd1a0kxSTg3eXBIZEhJK0ZZMVZpZzZna1hpZlFPd002QzFtbW5GamtHR21NY3pqREU4QmpENgo3UnBxSzd0RFg5WDJZVVJmTnRoYktuenR5UlIxZWhXa09OMXFEcllVbmQ0ZXZZME1YQjBYOWloUkpuY3pFVUtvCmZRSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator9:3030", + }, + { + id: 110, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBcjVCUHdPS3BLSkRmMjFyMHRENEgKZW9KMlFHVHVvdFJ5T2pxVkRXazNWVGxwTzJSbWNaQitnMXJEL3V5R25QMHFvRVhwMXFIbjMrdFlhR3h5ZkNNYQpMNTdLRFpDenk4ckg2dDhTd2l5ajhrOU1NaEhSSmEwMVhvVFVHOUF5cHdjTGt1WXlSYVd0dTFUdWY2NDY5QmZUCjcvWWhBQWJ3Wk83a1ZOM291V3NvUFpiZHUzY2o4TDhXV3I5RjYvMjl1ZjI2MjNvcVJsWWZwQlVYNis5WU0zM2sKcTRTeVRpZ0l2bng1cG8xUU85c2dvTllJeWU2cHJpOUpZcVI4QU02dDdIS2llcDNDai8vR1ovUUkvRlZVNVYxbQpKRno0ekg2LytCUFJDamNQQzk1OHA4WnpIS3F6K2ExM0dwbjQrZXVGZ3RnYnBlUkwrK2xybE1kcnNvRFpZQmlYClNRSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator10:3030", + }, + { + id: 111, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdmJHWnNXNzl1bmRrcDlZd1ZhMXUKTUhQN2JLZ2JHZFRwUTVWNjljT0FrclppT0tESTlpY0llenZQbEtmVWJQYUlJU3VXQ005dHoxSEJ3VzI2Y2RaeQpQUThMaDhjZnZtUkhOc1F0eUdlOVEyY1lIcURNeGxEYkRlaTVuZURMMzg2ZDd0MEZ0RmNoRzRUOWN6ZjE0WUFlCldsYUJvcmtEeTljeS9lMnN2WkFRaVI5WXo5N0lWclBxSUZOZUxVaUJDWmtjRnd0V3ZyTGp0dm5HK3pjQlduQUkKdTRmaVZvK0tiVXBZL2NMeW9oWEJUSng5TGtLNEkxUDYwNGllYlNSQTR6WU9OVzc2REhiQjFCN29iR0R0bndjdQo4UUttblc4bXVoY2h4TlJlUDY2Wk5BdDNUemdnTDVnOUs4dUUvYkhqdlhvaUkybGJvYkNEYytQV3M4ejlyU1A2CjdRSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator11:3030", + }, + { + id: 112, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMFR4Y1BVaVpFS1pYdCtuL0Yvc2YKRnVVVnE1OUM4KzZWWW9mU0k5UU9PV1JoTTV5RHo2SEZmZGlxMVF0R3Zld1hIK1NYRDIxUFkrVkJMem12REtnagpadS9uMER5UW5zcWMrOGhTN1NobzJUSVdIVXlPSWlEN0ZtUlZqenFYQ0J2ZnVSc3VpaVNHektvckFVOXNwTnhqClNPQ2pWeWYxcXUvM2hUKzlNQWtRSlZWNzF2VDg0NWRmaUFvNE9OenA0Q2lXL2ZkcFA2USttM3RBTWVJR21veDMKeC92TVNwRGhDdGlrM3Qzajl5WFZxbjBjd3V1VE1zWFU0RnNFK1lhbjRVVEZmYmFYOHZKK3hwb1NqOHZPblFDRQp2ZlNaU2JsSVJvYWVSdFJDd2tndUpjNy9pVVhSdlVqSExkUklMRFN6WStQNml1WlQ5eG1UTXEwa1Z5emNTSkVwCm13SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator12:3030", + }, + { + id: 113, + public_key: + "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBeVMrMHA5ZGJqU0hib25vbEU5a0sKMk9SYkpHb0crMWNDYnBPNGpDdkViYkI5T1ZCRFpjODNGU0w1OUg5VTFPMEVaRmlheHN3dE1YN1dLK1d4UFZPVwpOdnJHckFURHROc1l4dWNRV1dUQVUzRWJyNWtXWFd2eWl6KzFOVWszbWNFZktxaGVWdWY5VXZaaHdJNHRNMkVvCkdZWFpkck8wYVp3YXBPMmJuampKWExqZEZybkVTZ3dZUkhjdUxmWDZTQXlRanhSOWdBRzZkN2xrOVJVTDN0eXoKV0pRSXJHc0pvZlBJdkZRLzBPNXdwUTFKRm93SWRBc1RPZXA5MTdjYXRNLzhyR2pmTnNRQjlRREFSOWJMRUpXTQpMTFhzUGc4WU44Qnc4aWFRaW1ycUcrc1FHN3pZbWtvbVl3SmNVeXpEMWFEZk1IUzZMNnh0VjYrNnEwbUlHTFZ0CjJ3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K", + ip: "https://operator13:3030", + }, +]; + +async function main() { + (async () => { + const rawResponse = await fetch("http://172.19.0.2:8080/init", { + method: "POST", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + body: JSON.stringify({ + operatorsInfo: operators, + operatorIDs: [11, 22, 33, 44, 55, 66, 77, 88, 99, 110, 111, 112, 113], + withdrawAddress: "0x81592c3de184a3e2c0dcb5a261bc107bfa91f494", + owner: "0xDCc846fA10C7CfCE9e6Eb37e06eD93b666cFC5E9", + nonce: 1, + network: "holesky", + validators: 10, + amount: 32000000000 + }), + }); + const content = await rawResponse.json(); + console.log(content); + })(); +} +main(); diff --git a/utils/test-init-request/package-lock.json b/utils/test-init-request/package-lock.json new file mode 100644 index 00000000..d73a3fcb --- /dev/null +++ b/utils/test-init-request/package-lock.json @@ -0,0 +1,26 @@ +{ + "name": "test-init-request", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "typescript": "^5.6.2" + } + }, + "node_modules/typescript": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/utils/test-init-request/package.json b/utils/test-init-request/package.json new file mode 100644 index 00000000..282f115a --- /dev/null +++ b/utils/test-init-request/package.json @@ -0,0 +1,6 @@ +{ + "devDependencies": { + "typescript": "^5.6.2" + }, + "dependencies": {} +} diff --git a/utils/test-init-request/tsconfig.json b/utils/test-init-request/tsconfig.json new file mode 100644 index 00000000..a48fc9fa --- /dev/null +++ b/utils/test-init-request/tsconfig.json @@ -0,0 +1,110 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "ES2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +}