From 223ad9c31e3df8189f6d5e48fa9fc7fb5f0a7ed5 Mon Sep 17 00:00:00 2001 From: optclblast Date: Sat, 25 May 2024 16:00:21 +0300 Subject: [PATCH] chain interactor updates --- backend/cmd/main.go | 7 + backend/internal/factory/interactors.go | 12 +- backend/internal/factory/wire.go | 1 + backend/internal/factory/wire_gen.go | 7 +- .../usecase/interactors/chain/chain.go | 176 ++++++++++-------- .../usecase/interactors/users/interactor.go | 20 +- 6 files changed, 137 insertions(+), 86 deletions(-) diff --git a/backend/cmd/main.go b/backend/cmd/main.go index 33078af..03bbff7 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -38,6 +38,10 @@ func main() { &cli.StringFlag{ Name: "jwt-secret", }, + &cli.StringFlag{ + Name: "chain-api-url", + Value: "http://localhost:3000", + }, // rest &cli.StringFlag{ @@ -108,6 +112,9 @@ func main() { CacheUser: c.String("cache-user"), CacheSecret: c.String("cache-secret"), }, + ChainAPI: config.ChainAPIConfig{ + Host: c.String("chain-api-url"), + }, } fmt.Println(config) diff --git a/backend/internal/factory/interactors.go b/backend/internal/factory/interactors.go index 531bb2b..16f70c1 100644 --- a/backend/internal/factory/interactors.go +++ b/backend/internal/factory/interactors.go @@ -4,6 +4,7 @@ import ( "log/slog" "github.com/emochka2007/block-accounting/internal/pkg/config" + "github.com/emochka2007/block-accounting/internal/usecase/interactors/chain" "github.com/emochka2007/block-accounting/internal/usecase/interactors/jwt" "github.com/emochka2007/block-accounting/internal/usecase/interactors/organizations" "github.com/emochka2007/block-accounting/internal/usecase/interactors/transactions" @@ -18,8 +19,9 @@ import ( func provideUsersInteractor( log *slog.Logger, usersRepo urepo.Repository, + chainInteractor chain.ChainInteractor, ) users.UsersInteractor { - return users.NewUsersInteractor(log.WithGroup("users-interactor"), usersRepo) + return users.NewUsersInteractor(log.WithGroup("users-interactor"), usersRepo, chainInteractor) } func provideJWTInteractor( @@ -49,3 +51,11 @@ func provideTxInteractor( orgInteractor, ) } + +func provideChainInteractor( + log *slog.Logger, + config config.Config, + txRepository txRepo.Repository, +) chain.ChainInteractor { + return chain.NewChainInteractor(log, config, txRepository) +} diff --git a/backend/internal/factory/wire.go b/backend/internal/factory/wire.go index ca44f89..d9bcf45 100644 --- a/backend/internal/factory/wire.go +++ b/backend/internal/factory/wire.go @@ -22,6 +22,7 @@ func ProvideService(c config.Config) (service.Service, func(), error) { provideOrganizationsRepository, provideOrganizationsInteractor, provideTxInteractor, + provideChainInteractor, provideAuthRepository, provideJWTInteractor, interfaceSet, diff --git a/backend/internal/factory/wire_gen.go b/backend/internal/factory/wire_gen.go index 289bd27..468846b 100644 --- a/backend/internal/factory/wire_gen.go +++ b/backend/internal/factory/wire_gen.go @@ -1,6 +1,6 @@ // Code generated by Wire. DO NOT EDIT. -//go:generate go run github.com/google/wire/cmd/wire +//go:generate go run -mod=mod github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject @@ -21,7 +21,9 @@ func ProvideService(c config.Config) (service.Service, func(), error) { return nil, nil, err } usersRepository := provideUsersRepository(db) - usersInteractor := provideUsersInteractor(logger, usersRepository) + transactionsRepository := provideTxRepository(db) + chainInteractor := provideChainInteractor(logger, c, transactionsRepository) + usersInteractor := provideUsersInteractor(logger, usersRepository, chainInteractor) authRepository := provideAuthRepository(db) jwtInteractor := provideJWTInteractor(c, usersInteractor, authRepository) authPresenter := provideAuthPresenter(jwtInteractor) @@ -32,7 +34,6 @@ func ProvideService(c config.Config) (service.Service, func(), error) { organizationsInteractor := provideOrganizationsInteractor(logger, organizationsRepository, cache) organizationsPresenter := provideOrganizationsPresenter() organizationsController := provideOrganizationsController(logger, organizationsInteractor, organizationsPresenter) - transactionsRepository := provideTxRepository(db) transactionsInteractor := provideTxInteractor(logger, transactionsRepository, organizationsInteractor) transactionsController := provideTxController(logger, transactionsInteractor) participantsController := provideParticipantsController(logger, organizationsInteractor, usersInteractor) diff --git a/backend/internal/usecase/interactors/chain/chain.go b/backend/internal/usecase/interactors/chain/chain.go index 551ec99..d3c5506 100644 --- a/backend/internal/usecase/interactors/chain/chain.go +++ b/backend/internal/usecase/interactors/chain/chain.go @@ -10,34 +10,33 @@ import ( "net/http" "github.com/emochka2007/block-accounting/internal/pkg/config" + "github.com/emochka2007/block-accounting/internal/pkg/ctxmeta" "github.com/emochka2007/block-accounting/internal/pkg/models" - "github.com/emochka2007/block-accounting/internal/usecase/interactors/users" "github.com/emochka2007/block-accounting/internal/usecase/repository/transactions" "github.com/ethereum/go-ethereum/common" ) type ChainInteractor interface { NewMultisig(ctx context.Context, params NewMultisigParams) error + PubKey(ctx context.Context, user *models.User) ([]byte, error) + SalaryDeploy(ctx context.Context, firtsAdmin models.OrganizationParticipant) error } type chainInteractor struct { - log *slog.Logger - config config.Config - txRepository transactions.Repository - usersInteractor users.UsersInteractor + log *slog.Logger + config config.Config + txRepository transactions.Repository } func NewChainInteractor( log *slog.Logger, config config.Config, txRepository transactions.Repository, - usersInteractor users.UsersInteractor, ) ChainInteractor { return &chainInteractor{ - log: log, - config: config, - txRepository: txRepository, - usersInteractor: usersInteractor, + log: log, + config: config, + txRepository: txRepository, } } @@ -47,11 +46,11 @@ type NewMultisigParams struct { } func (i *chainInteractor) NewMultisig(ctx context.Context, params NewMultisigParams) error { - deployAddr := i.config.ChainAPI.Host + "/multi-sig/deploy" + endpoint := i.config.ChainAPI.Host + "/multi-sig/deploy" i.log.Debug( "deploy multisig", - slog.String("endpoint", deployAddr), + slog.String("endpoint", endpoint), slog.Any("params", params), ) @@ -63,53 +62,45 @@ func (i *chainInteractor) NewMultisig(ctx context.Context, params NewMultisigPar return fmt.Errorf("error marshal request body. %w", err) } + user, err := ctxmeta.User(ctx) + if err != nil { + return fmt.Errorf("error fetch user from context. %w", err) + } + body := bytes.NewBuffer(requestBody) - doneCh := make(chan struct{}) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, body) + if err != nil { + return fmt.Errorf("error build request. %w", err) + } - errCh := make(chan error) + req.Header.Add("Content-Type", "application/json") + req.Header.Add("X-Seed", common.Bytes2Hex(user.Seed())) - go func() { - resp, err := http.Post(http.MethodPost, deployAddr, body) - if err != nil { - i.log.Error( - "error send deploy multisig request", - slog.String("endpoint", deployAddr), - slog.Any("params", params), - ) - - errCh <- fmt.Errorf("error build new multisig request. %w", err) - return - } - - defer resp.Body.Close() - - i.log.Debug( - "deploy multisig response", - slog.Int("code", resp.StatusCode), + resp, err := http.DefaultClient.Do(req) + if err != nil { + i.log.Error( + "error send deploy multisig request", + slog.String("endpoint", endpoint), + slog.Any("params", params), ) - if _, ok := <-doneCh; ok { - doneCh <- struct{}{} - } - }() - - select { - case err := <-errCh: - return err - case <-doneCh: - return nil - case <-ctx.Done(): - return ctx.Err() + return fmt.Errorf("error build new multisig request. %w", err) } + + defer resp.Body.Close() + + i.log.Debug( + "deploy multisig response", + slog.Int("code", resp.StatusCode), + ) + + return nil } func (i *chainInteractor) PubKey(ctx context.Context, user *models.User) ([]byte, error) { pubAddr := i.config.ChainAPI.Host + "/address-from-seed" - doneCh := make(chan struct{}) - errCh := make(chan error) - requestBody, err := json.Marshal(map[string]any{ "seedPhrase": user.Mnemonic, }) @@ -119,34 +110,67 @@ func (i *chainInteractor) PubKey(ctx context.Context, user *models.User) ([]byte body := bytes.NewBuffer(requestBody) - var pubKeyStr string - - go func() { - resp, err := http.Post(pubAddr, "application/json", body) - if err != nil { - errCh <- fmt.Errorf("error fetch pub address. %w", err) - return - } - - defer resp.Body.Close() - - respBody, err := io.ReadAll(resp.Body) - if err != nil { - errCh <- fmt.Errorf("error read resp body. %w", err) - return - } - - pubKeyStr = string(respBody) - - doneCh <- struct{}{} - }() - - select { - case err := <-errCh: - return nil, err - case <-doneCh: - return common.Hex2Bytes(pubKeyStr), nil - case <-ctx.Done(): - return nil, ctx.Err() + req, err := http.NewRequestWithContext(ctx, http.MethodPost, pubAddr, body) + if err != nil { + return nil, fmt.Errorf("error build request. %w", err) } + + req.Header.Add("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, fmt.Errorf("error fetch pub address. %w", err) + } + + defer resp.Body.Close() + + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("error read resp body. %w", err) + } + + pubKeyStr := string(respBody)[2:] + + return common.Hex2Bytes(pubKeyStr), nil } + +func (i *chainInteractor) SalaryDeploy(ctx context.Context, firtsAdmin models.OrganizationParticipant) error { + user, err := ctxmeta.User(ctx) + if err != nil { + return fmt.Errorf("error fetch user from context. %w", err) + } + + if user.Id() != firtsAdmin.Id() || firtsAdmin.GetUser() == nil { + return fmt.Errorf("error unauthorized access") + } + + requestBody, err := json.Marshal(map[string]any{ + "authorizedWallet": common.Bytes2Hex(user.Seed()), + }) + if err != nil { + return fmt.Errorf("error marshal request body. %w", err) + } + + body := bytes.NewBuffer(requestBody) + + endpoint := i.config.ChainAPI.Host + "/salaries/deploy" + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, body) + if err != nil { + return fmt.Errorf("error build request. %w", err) + } + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("X-Seed", common.Bytes2Hex(user.Seed())) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return fmt.Errorf("error fetch deploy salary contract. %w", err) + } + + defer resp.Body.Close() + + return nil +} + +// func (i *chainInteractor) diff --git a/backend/internal/usecase/interactors/users/interactor.go b/backend/internal/usecase/interactors/users/interactor.go index 1b3cf9e..6748089 100644 --- a/backend/internal/usecase/interactors/users/interactor.go +++ b/backend/internal/usecase/interactors/users/interactor.go @@ -9,6 +9,7 @@ import ( "github.com/emochka2007/block-accounting/internal/pkg/hdwallet" "github.com/emochka2007/block-accounting/internal/pkg/models" + "github.com/emochka2007/block-accounting/internal/usecase/interactors/chain" "github.com/emochka2007/block-accounting/internal/usecase/repository/users" "github.com/google/uuid" ) @@ -52,17 +53,20 @@ type UsersInteractor interface { } type usersInteractor struct { - log *slog.Logger - usersRepo users.Repository + log *slog.Logger + usersRepo users.Repository + chainInteractor chain.ChainInteractor } func NewUsersInteractor( log *slog.Logger, usersRepo users.Repository, + chainInteractor chain.ChainInteractor, ) UsersInteractor { return &usersInteractor{ - log: log, - usersRepo: usersRepo, + log: log, + usersRepo: usersRepo, + chainInteractor: chainInteractor, } } @@ -88,9 +92,13 @@ func (i *usersInteractor) Create(ctx context.Context, params CreateParams) (*mod Telegram: params.Tg, } - // TODO fetch user PK from chain-api + pk, err := i.chainInteractor.PubKey(ctx, user) + if err != nil { + // todo пока мокнуть + return nil, fmt.Errorf("error fetch user pub key. %w", err) + } - user.PK = []byte{0x01} // todo remove + user.PK = pk if err = i.usersRepo.Create(ctx, user); err != nil { return nil, fmt.Errorf("error create new user. %w", err)