mirror of
https://github.com/emo2007/block-accounting.git
synced 2025-01-18 07:26:27 +00:00
deploy multisig implemented but tests needed
This commit is contained in:
parent
05d802630e
commit
b590daf305
@ -508,16 +508,28 @@ Response:
|
||||
### Request body:
|
||||
* title (string)
|
||||
* owners (array of object { "public_key":"string" })
|
||||
* confirmations (int)
|
||||
* confirmations (uint)
|
||||
|
||||
### Example
|
||||
Request:
|
||||
``` bash
|
||||
|
||||
curl --request POST \
|
||||
--url http://localhost:8081/organizations/018fb246-1616-7f1b-9fe2-1a3202224695/multisig \
|
||||
--header 'Authorization: Bearer token' \
|
||||
--header 'content-type: application/json' \
|
||||
--data '{
|
||||
"title":"new sig",
|
||||
"owners":[
|
||||
"0x5810f45ac87c0be03b4d8174132e2bc81ba1a928"
|
||||
],
|
||||
"confirmations":1
|
||||
}'
|
||||
```
|
||||
|
||||
Response:
|
||||
``` json
|
||||
|
||||
{
|
||||
"Ok": true
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -95,12 +95,14 @@ func provideTxController(
|
||||
log *slog.Logger,
|
||||
txInteractor transactions.TransactionsInteractor,
|
||||
chainInteractor chain.ChainInteractor,
|
||||
organizationsInteractor organizations.OrganizationsInteractor,
|
||||
) controllers.TransactionsController {
|
||||
return controllers.NewTransactionsController(
|
||||
log.WithGroup("transactions-controller"),
|
||||
txInteractor,
|
||||
presenters.NewTransactionsPresenter(),
|
||||
chainInteractor,
|
||||
organizationsInteractor,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ func ProvideService(c config.Config) (service.Service, func(), error) {
|
||||
organizationsPresenter := provideOrganizationsPresenter()
|
||||
organizationsController := provideOrganizationsController(logger, organizationsInteractor, organizationsPresenter)
|
||||
transactionsInteractor := provideTxInteractor(logger, transactionsRepository, organizationsInteractor)
|
||||
transactionsController := provideTxController(logger, transactionsInteractor, chainInteractor)
|
||||
transactionsController := provideTxController(logger, transactionsInteractor, chainInteractor, organizationsInteractor)
|
||||
participantsController := provideParticipantsController(logger, organizationsInteractor, usersInteractor)
|
||||
rootController := provideControllers(logger, authController, organizationsController, transactionsController, participantsController)
|
||||
server := provideRestServer(logger, rootController, c, jwtInteractor)
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"github.com/emochka2007/block-accounting/internal/pkg/ctxmeta"
|
||||
"github.com/emochka2007/block-accounting/internal/pkg/models"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/chain"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/organizations"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/transactions"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
@ -36,10 +37,11 @@ type TransactionsController interface {
|
||||
}
|
||||
|
||||
type transactionsController struct {
|
||||
log *slog.Logger
|
||||
txInteractor transactions.TransactionsInteractor
|
||||
txPresenter presenters.TransactionsPresenter
|
||||
chainInteractor chain.ChainInteractor
|
||||
log *slog.Logger
|
||||
txInteractor transactions.TransactionsInteractor
|
||||
txPresenter presenters.TransactionsPresenter
|
||||
chainInteractor chain.ChainInteractor
|
||||
organizationsInteractor organizations.OrganizationsInteractor
|
||||
}
|
||||
|
||||
func NewTransactionsController(
|
||||
@ -47,12 +49,14 @@ func NewTransactionsController(
|
||||
txInteractor transactions.TransactionsInteractor,
|
||||
txPresenter presenters.TransactionsPresenter,
|
||||
chainInteractor chain.ChainInteractor,
|
||||
organizationsInteractor organizations.OrganizationsInteractor,
|
||||
) TransactionsController {
|
||||
return &transactionsController{
|
||||
log: log,
|
||||
txInteractor: txInteractor,
|
||||
txPresenter: txPresenter,
|
||||
chainInteractor: chainInteractor,
|
||||
log: log,
|
||||
txInteractor: txInteractor,
|
||||
txPresenter: txPresenter,
|
||||
chainInteractor: chainInteractor,
|
||||
organizationsInteractor: organizationsInteractor,
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,18 +225,28 @@ func (c *transactionsController) NewMultisig(w http.ResponseWriter, r *http.Requ
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
ownersPKs := make([]string, len(req.Owners))
|
||||
ownersPKs := make([][]byte, len(req.Owners))
|
||||
|
||||
for i, pk := range req.Owners {
|
||||
ownersPKs[i] = pk.PublicKey
|
||||
ownersPKs[i] = common.Hex2Bytes(pk.PublicKey[2:])
|
||||
}
|
||||
|
||||
if req.Confirmations <= 0 {
|
||||
req.Confirmations = 1
|
||||
}
|
||||
|
||||
participants, err := c.organizationsInteractor.Participants(ctx, organizations.ParticipantsParams{
|
||||
PKs: ownersPKs,
|
||||
OrganizationID: organizationID,
|
||||
UsersOnly: true,
|
||||
ActiveOnly: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetch participants by pks. %w", err)
|
||||
}
|
||||
|
||||
if err := c.chainInteractor.NewMultisig(ctx, chain.NewMultisigParams{
|
||||
OwnersPKs: ownersPKs,
|
||||
Owners: participants,
|
||||
Confirmations: req.Confirmations,
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("error deploy multisig. %w", err)
|
||||
|
@ -144,7 +144,7 @@ func (s *Server) buildRouter() {
|
||||
r.Post("/invite", s.handle(s.controllers.Auth.Invite, "invite"))
|
||||
|
||||
r.Route("/{participant_id}", func(r chi.Router) {
|
||||
r.Get("/", nil)
|
||||
r.Get("/", nil) // todo если успею
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
type Multisig struct {
|
||||
ID uuid.UUID
|
||||
Title string
|
||||
Address []byte
|
||||
OrganizationID uuid.UUID
|
||||
Owners []OrganizationParticipant
|
||||
ConfirmationsRequired int
|
||||
|
@ -55,6 +55,10 @@ func (u *User) Seed() []byte {
|
||||
return u.Bip39Seed
|
||||
}
|
||||
|
||||
func (u *User) PublicKey() []byte {
|
||||
return u.PK
|
||||
}
|
||||
|
||||
type OrganizationParticipantType int
|
||||
|
||||
const (
|
||||
|
@ -8,12 +8,14 @@ import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"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/repository/transactions"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ChainInteractor interface {
|
||||
@ -41,10 +43,15 @@ func NewChainInteractor(
|
||||
}
|
||||
|
||||
type NewMultisigParams struct {
|
||||
OwnersPKs []string
|
||||
Title string
|
||||
Owners []models.OrganizationParticipant
|
||||
Confirmations int
|
||||
}
|
||||
|
||||
type newMultisigChainResponse struct {
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
func (i *chainInteractor) NewMultisig(ctx context.Context, params NewMultisigParams) error {
|
||||
endpoint := i.config.ChainAPI.Host + "/multi-sig/deploy"
|
||||
|
||||
@ -54,8 +61,18 @@ func (i *chainInteractor) NewMultisig(ctx context.Context, params NewMultisigPar
|
||||
slog.Any("params", params),
|
||||
)
|
||||
|
||||
pks := make([]string, len(params.Owners))
|
||||
|
||||
for i, owner := range params.Owners {
|
||||
if owner.GetUser() == nil {
|
||||
return fmt.Errorf("error invalis owners set")
|
||||
}
|
||||
|
||||
pks[i] = "0x" + common.Bytes2Hex(owner.GetUser().PublicKey())
|
||||
}
|
||||
|
||||
requestBody, err := json.Marshal(map[string]any{
|
||||
"owners": params.OwnersPKs,
|
||||
"owners": pks,
|
||||
"confirmations": params.Confirmations,
|
||||
})
|
||||
if err != nil {
|
||||
@ -67,6 +84,11 @@ func (i *chainInteractor) NewMultisig(ctx context.Context, params NewMultisigPar
|
||||
return fmt.Errorf("error fetch user from context. %w", err)
|
||||
}
|
||||
|
||||
organizationID, err := ctxmeta.OrganizationId(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetch organization id from context. %w", err)
|
||||
}
|
||||
|
||||
body := bytes.NewBuffer(requestBody)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, body)
|
||||
@ -90,6 +112,34 @@ func (i *chainInteractor) NewMultisig(ctx context.Context, params NewMultisigPar
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
raw, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error read body. %w", err)
|
||||
}
|
||||
|
||||
respObject := new(newMultisigChainResponse)
|
||||
|
||||
if err := json.Unmarshal(raw, &respObject); err != nil {
|
||||
return fmt.Errorf("error parse chain-api response body. %w", err)
|
||||
}
|
||||
|
||||
multisigAddress := common.Hex2Bytes(respObject.Address)
|
||||
|
||||
createdAt := time.Now()
|
||||
|
||||
if err := i.txRepository.AddMultisig(ctx, models.Multisig{
|
||||
ID: uuid.Must(uuid.NewV7()),
|
||||
Title: params.Title,
|
||||
Address: multisigAddress,
|
||||
OrganizationID: organizationID,
|
||||
Owners: params.Owners,
|
||||
ConfirmationsRequired: params.Confirmations,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("error add new multisig. %w", err)
|
||||
}
|
||||
|
||||
i.log.Debug(
|
||||
"deploy multisig response",
|
||||
slog.Int("code", resp.StatusCode),
|
||||
|
@ -49,6 +49,7 @@ type ParticipantParams struct {
|
||||
type ParticipantsParams struct {
|
||||
IDs uuid.UUIDs
|
||||
OrganizationID uuid.UUID
|
||||
PKs [][]byte
|
||||
|
||||
UsersOnly bool
|
||||
ActiveOnly bool
|
||||
@ -289,6 +290,7 @@ func (i *organizationsInteractor) Participants(
|
||||
participants, err := i.orgRepository.Participants(ctx, organizations.ParticipantsParams{
|
||||
Ids: params.IDs,
|
||||
OrganizationId: params.OrganizationID,
|
||||
PKs: params.PKs,
|
||||
UsersOnly: params.UsersOnly,
|
||||
EmployeesOnly: params.EmployeesOnly,
|
||||
ActiveOnly: params.ActiveOnly,
|
||||
|
@ -31,6 +31,7 @@ type GetParams struct {
|
||||
type ParticipantsParams struct {
|
||||
OrganizationId uuid.UUID
|
||||
Ids uuid.UUIDs
|
||||
PKs [][]byte
|
||||
|
||||
// Filters
|
||||
UsersOnly bool
|
||||
@ -388,6 +389,12 @@ func (r *repositorySQL) Participants(
|
||||
)
|
||||
}
|
||||
|
||||
if len(params.PKs) > 0 {
|
||||
ouQuery = ouQuery.InnerJoin("users as u on u.id = ou.user_id").Where(sq.Eq{
|
||||
"u.public_key": params.PKs,
|
||||
})
|
||||
}
|
||||
|
||||
rows, err := ouQuery.RunWith(r.Conn(ctx)).QueryContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetch organization participants. %w", err)
|
||||
@ -548,6 +555,7 @@ func (r *repositorySQL) Participants(
|
||||
|
||||
usrs, err = r.usersRepository.Get(usersCtx, users.GetParams{
|
||||
Ids: ids,
|
||||
PKs: params.PKs,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetch users by ids. %w", err)
|
||||
|
@ -435,7 +435,7 @@ func (r *repositorySQL) AddMultisig(
|
||||
owner.Id(),
|
||||
multisig.CreatedAt,
|
||||
multisig.UpdatedAt,
|
||||
)
|
||||
).PlaceholderFormat(sq.Dollar)
|
||||
|
||||
if _, err := addOwnerQuery.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil {
|
||||
return fmt.Errorf("error insert multisig owner data. %w", err)
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
|
||||
type GetParams struct {
|
||||
Ids uuid.UUIDs
|
||||
PKs [][]byte
|
||||
OrganizationId uuid.UUID
|
||||
Seed []byte
|
||||
}
|
||||
@ -60,6 +61,12 @@ func (r *repositorySQL) Get(ctx context.Context, params GetParams) ([]*models.Us
|
||||
})
|
||||
}
|
||||
|
||||
if len(params.PKs) > 0 {
|
||||
query = query.Where(sq.Eq{
|
||||
"u.public_key": params.PKs,
|
||||
})
|
||||
}
|
||||
|
||||
if params.OrganizationId != uuid.Nil {
|
||||
query = query.InnerJoin(
|
||||
"organizations_users as ou on ou.user_id = u.id",
|
||||
@ -72,6 +79,10 @@ func (r *repositorySQL) Get(ctx context.Context, params GetParams) ([]*models.Us
|
||||
query = query.Where("u.seed = ?", params.Seed)
|
||||
}
|
||||
|
||||
if params.PKs != nil {
|
||||
fmt.Println(query.ToSql())
|
||||
}
|
||||
|
||||
rows, err := query.RunWith(r.Conn(ctx)).QueryContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetch data from database. %w", err)
|
||||
|
Loading…
Reference in New Issue
Block a user