mirror of
https://github.com/emo2007/block-accounting.git
synced 2025-01-18 15:36:27 +00:00
msigs fetch implemented
This commit is contained in:
parent
0558ddbd04
commit
55c6c14630
@ -406,16 +406,58 @@ curl --request GET \
|
||||
Response:
|
||||
``` json
|
||||
{
|
||||
// todo
|
||||
"_type": "multisigs",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/organizations/018fb61b-9f79-705a-bd92-59233ed15ac7/multisig"
|
||||
}
|
||||
},
|
||||
"multisigs": [
|
||||
{
|
||||
"id": "018fb61e-6c64-7a70-b677-992353389731",
|
||||
"title": "new sig",
|
||||
"owners": {
|
||||
"_type": "participants",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/organizations/018fb61b-9f79-705a-bd92-59233ed15ac7/participants"
|
||||
}
|
||||
},
|
||||
"participants": [
|
||||
{
|
||||
"_type": "participant",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/organizations/018fb61b-9f79-705a-bd92-59233ed15ac7/participants/018fb61b-76cb-71c1-8306-cea167411ac8"
|
||||
}
|
||||
},
|
||||
"id": "018fb61b-76cb-71c1-8306-cea167411ac8",
|
||||
"name": "Bladee The Grand Drainer",
|
||||
"credentials": {
|
||||
"email": "bladeee@gmail.com",
|
||||
"phone": "+79999999999",
|
||||
"telegram": "@thebladee"
|
||||
},
|
||||
"created_at": 1716758014713,
|
||||
"updated_at": 1716758014713,
|
||||
"is_user": true,
|
||||
"is_admin": true,
|
||||
"is_owner": true,
|
||||
"is_active": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## GET **/organizations/{organization_id}/payrolls**
|
||||
Fetch payrolls
|
||||
|
||||
## POST **/organizations/{organization_id}/payrolls**
|
||||
New payroll
|
||||
|
||||
## GET **/organizations/{organization_id}/payrolls**
|
||||
Fetch payrolls
|
||||
|
||||
## GET **/organizations/{organization_id}/license**
|
||||
Fetch licenses
|
||||
|
||||
|
@ -24,8 +24,8 @@ func provideOrganizationsRepository(
|
||||
return organizations.NewRepository(db, uRepo)
|
||||
}
|
||||
|
||||
func provideTxRepository(db *sql.DB) transactions.Repository {
|
||||
return transactions.NewRepository(db)
|
||||
func provideTxRepository(db *sql.DB, or organizations.Repository) transactions.Repository {
|
||||
return transactions.NewRepository(db, or)
|
||||
}
|
||||
|
||||
func provideAuthRepository(db *sql.DB) auth.Repository {
|
||||
|
@ -21,14 +21,14 @@ func ProvideService(c config.Config) (service.Service, func(), error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
usersRepository := provideUsersRepository(db)
|
||||
transactionsRepository := provideTxRepository(db)
|
||||
organizationsRepository := provideOrganizationsRepository(db, usersRepository)
|
||||
transactionsRepository := provideTxRepository(db, organizationsRepository)
|
||||
chainInteractor := provideChainInteractor(logger, c, transactionsRepository)
|
||||
usersInteractor := provideUsersInteractor(logger, usersRepository, chainInteractor)
|
||||
authRepository := provideAuthRepository(db)
|
||||
jwtInteractor := provideJWTInteractor(c, usersInteractor, authRepository)
|
||||
authPresenter := provideAuthPresenter(jwtInteractor)
|
||||
authController := provideAuthController(logger, usersInteractor, authPresenter, jwtInteractor, authRepository)
|
||||
organizationsRepository := provideOrganizationsRepository(db, usersRepository)
|
||||
client, cleanup2 := provideRedisConnection(c)
|
||||
cache := provideRedisCache(client, logger)
|
||||
organizationsInteractor := provideOrganizationsInteractor(logger, organizationsRepository, cache)
|
||||
|
@ -222,7 +222,7 @@ func (c *transactionsController) NewMultisig(w http.ResponseWriter, r *http.Requ
|
||||
slog.Any("req", req),
|
||||
)
|
||||
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
ownersPKs := make([][]byte, len(req.Owners))
|
||||
@ -246,6 +246,7 @@ func (c *transactionsController) NewMultisig(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
|
||||
if err := c.chainInteractor.NewMultisig(ctx, chain.NewMultisigParams{
|
||||
Title: req.Title,
|
||||
Owners: participants,
|
||||
Confirmations: req.Confirmations,
|
||||
}); err != nil {
|
||||
@ -256,7 +257,19 @@ func (c *transactionsController) NewMultisig(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
|
||||
func (s *transactionsController) ListMultisigs(w http.ResponseWriter, r *http.Request) ([]byte, error) {
|
||||
return nil, nil
|
||||
organizationID, err := ctxmeta.OrganizationId(r.Context())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetch organization ID from context. %w", err)
|
||||
}
|
||||
|
||||
msgs, err := s.chainInteractor.ListMultisigs(r.Context(), chain.ListMultisigsParams{
|
||||
OrganizationID: organizationID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.txPresenter.ResponseMultisigs(r.Context(), msgs)
|
||||
}
|
||||
|
||||
// todo creates a new payout
|
||||
|
@ -20,6 +20,14 @@ type ParticipantsPresenter interface {
|
||||
ctx context.Context,
|
||||
participant models.OrganizationParticipant,
|
||||
) ([]byte, error)
|
||||
ResponseParticipantsHal(
|
||||
ctx context.Context,
|
||||
participants []models.OrganizationParticipant,
|
||||
) (*hal.Resource, error)
|
||||
ResponseParticipantHal(
|
||||
ctx context.Context,
|
||||
participant models.OrganizationParticipant,
|
||||
) (*hal.Resource, error)
|
||||
}
|
||||
|
||||
type participantsPresenter struct{}
|
||||
@ -28,7 +36,7 @@ func NewParticipantsPresenter() ParticipantsPresenter {
|
||||
return new(participantsPresenter)
|
||||
}
|
||||
|
||||
func (p *participantsPresenter) responseParticipant(
|
||||
func (p *participantsPresenter) ResponseParticipantHal(
|
||||
ctx context.Context,
|
||||
participant models.OrganizationParticipant,
|
||||
) (*hal.Resource, error) {
|
||||
@ -78,14 +86,14 @@ func (p *participantsPresenter) responseParticipant(
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (p *participantsPresenter) responseParticipants(
|
||||
func (p *participantsPresenter) ResponseParticipantsHal(
|
||||
ctx context.Context,
|
||||
participants []models.OrganizationParticipant,
|
||||
) (*hal.Resource, error) {
|
||||
resources := make([]*hal.Resource, len(participants))
|
||||
|
||||
for i, pt := range participants {
|
||||
r, err := p.responseParticipant(ctx, pt)
|
||||
r, err := p.ResponseParticipantHal(ctx, pt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error map participant to hal resource. %w", err)
|
||||
}
|
||||
@ -113,7 +121,7 @@ func (p *participantsPresenter) ResponseListParticipants(
|
||||
ctx context.Context,
|
||||
participants []models.OrganizationParticipant,
|
||||
) ([]byte, error) {
|
||||
r, err := p.responseParticipants(ctx, participants)
|
||||
r, err := p.ResponseParticipantsHal(ctx, participants)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error map participants to hal. %w", err)
|
||||
}
|
||||
@ -130,7 +138,7 @@ func (p *participantsPresenter) ResponseParticipant(
|
||||
ctx context.Context,
|
||||
participant models.OrganizationParticipant,
|
||||
) ([]byte, error) {
|
||||
r, err := p.responseParticipant(ctx, participant)
|
||||
r, err := p.ResponseParticipantHal(ctx, participant)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error map participant to hal resource. %w", err)
|
||||
}
|
||||
|
@ -24,13 +24,18 @@ type TransactionsPresenter interface {
|
||||
ResponseNewTransaction(ctx context.Context, tx *models.Transaction) ([]byte, error)
|
||||
ResponseTransactionsArray(ctx context.Context, txs []*models.Transaction) ([]*hal.Resource, error)
|
||||
ResponseListTransactions(ctx context.Context, txs []*models.Transaction, cursor string) ([]byte, error)
|
||||
|
||||
ResponseMultisigs(ctx context.Context, msgs []models.Multisig) ([]byte, error)
|
||||
}
|
||||
|
||||
type transactionsPresenter struct {
|
||||
participantsPresenter ParticipantsPresenter
|
||||
}
|
||||
|
||||
func NewTransactionsPresenter() TransactionsPresenter {
|
||||
return &transactionsPresenter{}
|
||||
return &transactionsPresenter{
|
||||
participantsPresenter: NewParticipantsPresenter(),
|
||||
}
|
||||
}
|
||||
|
||||
// RequestTransaction returns a Transaction model WITHOUT CreatedBy user set. CreatedAt set as time.Now()
|
||||
@ -150,7 +155,7 @@ func (p *transactionsPresenter) ResponseListTransactions(
|
||||
r := hal.NewResource(
|
||||
txsResource,
|
||||
"/organizations/"+organizationID.String()+"/transactions",
|
||||
hal.WithType("organizations"),
|
||||
hal.WithType("transactions"),
|
||||
)
|
||||
|
||||
out, err := json.Marshal(r)
|
||||
@ -177,3 +182,49 @@ func (c *transactionsPresenter) ResponseNewTransaction(
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type Multisig struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Owners *hal.Resource `json:"owners"`
|
||||
}
|
||||
|
||||
func (c *transactionsPresenter) ResponseMultisigs(ctx context.Context, msgs []models.Multisig) ([]byte, error) {
|
||||
organizationID, err := ctxmeta.OrganizationId(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetch organization id from context. %w", err)
|
||||
}
|
||||
|
||||
outArray := make([]Multisig, len(msgs))
|
||||
|
||||
for i, m := range msgs {
|
||||
mout := Multisig{
|
||||
ID: m.ID.String(),
|
||||
Title: m.Title,
|
||||
}
|
||||
|
||||
partOut, err := c.participantsPresenter.ResponseParticipantsHal(ctx, m.Owners)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mout.Owners = partOut
|
||||
|
||||
outArray[i] = mout
|
||||
}
|
||||
|
||||
txsResource := map[string]any{"multisigs": outArray}
|
||||
|
||||
r := hal.NewResource(
|
||||
txsResource,
|
||||
"/organizations/"+organizationID.String()+"/multisig",
|
||||
hal.WithType("multisigs"),
|
||||
)
|
||||
|
||||
out, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshal tx to hal resource. %w", err)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
|
||||
type ChainInteractor interface {
|
||||
NewMultisig(ctx context.Context, params NewMultisigParams) error
|
||||
ListMultisigs(ctx context.Context, params ListMultisigsParams) ([]models.Multisig, error)
|
||||
PubKey(ctx context.Context, user *models.User) ([]byte, error)
|
||||
SalaryDeploy(ctx context.Context, firtsAdmin models.OrganizationParticipant) error
|
||||
}
|
||||
@ -223,4 +224,20 @@ func (i *chainInteractor) SalaryDeploy(ctx context.Context, firtsAdmin models.Or
|
||||
return nil
|
||||
}
|
||||
|
||||
// func (i *chainInteractor)
|
||||
type ListMultisigsParams struct {
|
||||
OrganizationID uuid.UUID
|
||||
}
|
||||
|
||||
func (i *chainInteractor) ListMultisigs(
|
||||
ctx context.Context,
|
||||
params ListMultisigsParams,
|
||||
) ([]models.Multisig, error) {
|
||||
multisigs, err := i.txRepository.ListMultisig(ctx, transactions.ListMultisigsParams{
|
||||
OrganizationID: params.OrganizationID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetch multisigs. %w", err)
|
||||
}
|
||||
|
||||
return multisigs, nil
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/emochka2007/block-accounting/internal/pkg/models"
|
||||
sqltools "github.com/emochka2007/block-accounting/internal/pkg/sqlutils"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/repository/organizations"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@ -52,15 +53,18 @@ type Repository interface {
|
||||
CancelTransaction(ctx context.Context, params CancelTransactionParams) error
|
||||
|
||||
AddMultisig(ctx context.Context, multisig models.Multisig) error
|
||||
ListMultisig(ctx context.Context, params ListMultisigsParams) ([]models.Multisig, error)
|
||||
}
|
||||
|
||||
type repositorySQL struct {
|
||||
db *sql.DB
|
||||
db *sql.DB
|
||||
orgRepo organizations.Repository
|
||||
}
|
||||
|
||||
func NewRepository(db *sql.DB) Repository {
|
||||
func NewRepository(db *sql.DB, orgRepo organizations.Repository) Repository {
|
||||
return &repositorySQL{
|
||||
db: db,
|
||||
db: db,
|
||||
orgRepo: orgRepo,
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,12 +414,16 @@ func (r *repositorySQL) AddMultisig(
|
||||
"id",
|
||||
"organization_id",
|
||||
"title",
|
||||
"address",
|
||||
"confirmations",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
).Values(
|
||||
multisig.ID,
|
||||
multisig.OrganizationID,
|
||||
multisig.Title,
|
||||
multisig.Address,
|
||||
multisig.ConfirmationsRequired,
|
||||
multisig.CreatedAt,
|
||||
multisig.UpdatedAt,
|
||||
).PlaceholderFormat(sq.Dollar)
|
||||
@ -445,3 +453,141 @@ func (r *repositorySQL) AddMultisig(
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
type ListMultisigsParams struct {
|
||||
IDs uuid.UUIDs
|
||||
OrganizationID uuid.UUID
|
||||
}
|
||||
|
||||
func (r *repositorySQL) ListMultisig(
|
||||
ctx context.Context,
|
||||
params ListMultisigsParams,
|
||||
) ([]models.Multisig, error) {
|
||||
msgs := make([]models.Multisig, 0)
|
||||
|
||||
if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
|
||||
query := sq.Select(
|
||||
"id",
|
||||
"organization_id",
|
||||
"title",
|
||||
"address",
|
||||
"confirmations",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
).From("multisigs").Where(sq.Eq{
|
||||
"organization_id": params.OrganizationID,
|
||||
}).PlaceholderFormat(sq.Dollar)
|
||||
|
||||
rows, err := query.RunWith(r.Conn(ctx)).QueryContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetch multisigs from database. %w", err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
msgsTmp := make([]*models.Multisig, 0)
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
id uuid.UUID
|
||||
organizationID uuid.UUID
|
||||
address []byte
|
||||
title string
|
||||
confirmations int
|
||||
createdAt time.Time
|
||||
updatedAt time.Time
|
||||
)
|
||||
|
||||
if err = rows.Scan(
|
||||
&id,
|
||||
&organizationID,
|
||||
&title,
|
||||
&address,
|
||||
&confirmations,
|
||||
&createdAt,
|
||||
&updatedAt,
|
||||
); err != nil {
|
||||
return fmt.Errorf("error scan row. %w", err)
|
||||
}
|
||||
|
||||
msgsTmp = append(msgsTmp, &models.Multisig{
|
||||
ID: id,
|
||||
Title: title,
|
||||
Address: address,
|
||||
OrganizationID: organizationID,
|
||||
ConfirmationsRequired: confirmations,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
for _, m := range msgsTmp {
|
||||
owners, err := r.fetchOwners(ctx, fetchOwnersParams{
|
||||
OrganizationID: params.OrganizationID,
|
||||
MultisigID: m.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Owners = owners
|
||||
|
||||
msgs = append(msgs, *m)
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return msgs, nil
|
||||
}
|
||||
|
||||
type fetchOwnersParams struct {
|
||||
MultisigID uuid.UUID
|
||||
OrganizationID uuid.UUID
|
||||
}
|
||||
|
||||
func (r *repositorySQL) fetchOwners(ctx context.Context, params fetchOwnersParams) ([]models.OrganizationParticipant, error) {
|
||||
owners := make([]models.OrganizationParticipant, 0)
|
||||
|
||||
if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
|
||||
query := sq.Select("owner_id").From("multisig_owners").Where(sq.Eq{
|
||||
"multisig_id": params.MultisigID,
|
||||
}).PlaceholderFormat(sq.Dollar)
|
||||
|
||||
rows, err := query.RunWith(r.Conn(ctx)).QueryContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetch multisigs owners from database. %w", err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
ids := make(uuid.UUIDs, 0)
|
||||
|
||||
for rows.Next() {
|
||||
var ownerId uuid.UUID
|
||||
|
||||
if err = rows.Scan(&ownerId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ids = append(ids, ownerId)
|
||||
}
|
||||
|
||||
owners, err = r.orgRepo.Participants(ctx, organizations.ParticipantsParams{
|
||||
OrganizationId: params.OrganizationID,
|
||||
Ids: ids,
|
||||
UsersOnly: true,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetch owners as participants. %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return owners, nil
|
||||
}
|
||||
|
@ -159,6 +159,8 @@ create index if not exists idx_contracts_organization_id_created_by
|
||||
create table multisigs (
|
||||
id uuid primary key,
|
||||
organization_id uuid not null references organizations(id),
|
||||
address bytea not null,
|
||||
confirmations smallint default 0,
|
||||
title varchar(350) default 'New Multi-Sig',
|
||||
created_at timestamp default current_timestamp,
|
||||
updated_at timestamp default current_timestamp
|
||||
|
Loading…
Reference in New Issue
Block a user