This commit is contained in:
r8zavetr8v 2024-05-29 01:46:30 +03:00
parent cd99143ed7
commit 05802514f5
11 changed files with 207 additions and 274 deletions

View File

@ -454,9 +454,59 @@ Response:
## POST **/organizations/{organization_id}/payrolls**
New payroll
### Request body:
* title (string)
* multisig_id (string)
### Example
Request:
``` bash
curl --request POST \
--url http://localhost:8081/organizations/018fb666-d7b7-740a-92e5-c2e04c7abafc/payrolls \
--header 'Authorization: Bearer TOKEN' \
--header 'content-type: application/json' \
--data '{
"title":"sdjkhfjsdk",
"multisig_id":"018fbb03-d4c5-73be-ab07-6c5f8d3afebc"
}'
```
Response:
``` json
{
"ok": true
}
```
## GET **/organizations/{organization_id}/payrolls**
Fetch payrolls
### Request body:
* ids ([]string)
* limit (uint32)
### Example
Request:
``` bash
curl --request POST \
--url http://localhost:8081/organizations/018fb666-d7b7-740a-92e5-c2e04c7abafc/payrolls \
--header 'Authorization: Bearer TOKEN' \
--header 'content-type: application/json' \
--data '{
"title":"sdjkhfjsdk",
"multisig_id":"018fbb03-d4c5-73be-ab07-6c5f8d3afebc"
}'
```
Response:
``` json
{
"ok": true
}
```
## PUT **/organizations/{organization_id}/payrolls**
Confirm payroll
// todo
## GET **/organizations/{organization_id}/license**
Fetch licenses
@ -506,9 +556,9 @@ curl --request POST \
Response:
```json
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTY5MTgzMzk5OTEsInVpZCI6IjAxOGZiYjI4LTZkODgtNzg2NC04OWMxLTYzODYxNzU3NmFhNiJ9.zobQ9AAEUEHPz2BoetdtZDm5AfgUPCyCVS0JYNEYj5c",
"token": "TOKEN",
"token_expired_at": 1716918339991,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTczNTAzMzk5OTEsInJ0X2hhc2giOiJzQStTZW42WDFUOVNVOGl1eVFhTy9sejJLSHNBMkpHcnlURDRHR3JQcTg1QUtLTE9XSWc0VTVEcFpXcjkvR1pqaDBGWGkvdWJYdHpIRzRCcUswV09jZz09IiwidWlkIjoiMDE4ZmJiMjgtNmQ4OC03ODY0LTg5YzEtNjM4NjE3NTc2YWE2In0.D0ZAHcJGH0Ga_nXLZojLBW8cMgTf8kNhcQbFVfKrGWs",
"refresh_token": "TOKEN",
"refresh_token_expired_at": 1717350339991
}
```
@ -535,9 +585,10 @@ Response:
```
## GET **/{organization_id}/transactions**
Feth txs
Fetch txs
### Request body:
ready_to_confirm (optional)
pending (optional)
### Example
Request:
@ -546,61 +597,6 @@ curl --location --request GET 'http://localhost:8081/organizations/018f9078-af60
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer TOKEN' \
--data '{
"description":"New test tx!",
"amount": 100,
"to":"0x323b5d4c32345ced77393b3530b1eed0f346429d",
"limit":1
}'
```
Response:
``` json
{
"_type": "transaction",
"_links": {
"self": {
"href": "/organizations/{organization_id}/transactions"
}
},
"id": "018f8ce2-dada-75fb-9745-8560e5736bec",
"description": "New test tx!",
"organization_id": "018f8ccd-2431-7d21-a0c2-a2735c852764",
"created_by": "018f8ccc-e4fc-7a46-9628-15f9c3301f5b",
"amount": 100,
"to": "MjtdTDI0XO13OTs1MLHu0PNGQp0=",
"max_fee_allowed": 5,
"deadline": 123456767,
"created_at": 1716055628507,
"updated_at": 1716055628507
}
```
## POST **/{organization_id}/transactions**
Add new tx
### Request body:
* ids ([]uuid)
* created_by (uuid)
* to (string)
* cancelled (bool)
* confirmed (bool)
* commited (bool)
* expired (bool)
* pending (bool)
* cursor (string)
* limit (int)
* offset_date (unix milli time)
### Example
Request:
``` bash
curl --location --request GET 'http://localhost:8081/organizations/018f9112-1805-7b5e-ae30-7fc2151810f3/transactions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer TOKEN' \
--data '{
"to": "0xD53990543641Ee27E2FC670ad2cf3cA65ccDc8BD",
"pending":true,
"limit":1,
"created_by":"018f9111-f0fb-708a-aec1-55295f5496d6"
}'
```
@ -635,3 +631,38 @@ Response:
]
}
```
## POST **/{organization_id}/transactions**
Add new tx
### Request body:
* description (string, optional)
* amount (float, required)
* to (string, required)
### Example
Request:
``` bash
// todo
```
Response:
``` json
{
"_type": "transaction",
"_links": {
"self": {
"href": "/organizations/{organization_id}/transactions"
}
},
"id": "018f8ce2-dada-75fb-9745-8560e5736bec",
"description": "New test tx!",
"organization_id": "018f8ccd-2431-7d21-a0c2-a2735c852764",
"created_by": "018f8ccc-e4fc-7a46-9628-15f9c3301f5b",
"amount": 100,
"to": "MjtdTDI0XO13OTs1MLHu0PNGQp0=",
"max_fee_allowed": 5,
"deadline": 123456767,
"created_at": 1716055628507,
"updated_at": 1716055628507
}
```

View File

@ -107,49 +107,15 @@ func (c *transactionsController) List(w http.ResponseWriter, r *http.Request) ([
return nil, fmt.Errorf("error fetch organization ID from context. %w", err)
}
ids := make(uuid.UUIDs, len(req.IDs))
for i, id := range req.IDs {
txUUID, err := uuid.Parse(id)
if err != nil {
return nil, fmt.Errorf("error parse tx id. %w", err)
}
ids[i] = txUUID
}
var toAddr []byte
if req.To != "" {
toAddr = common.HexToAddress(req.To).Bytes()
}
var createdBy uuid.UUID
if req.CreatedBy != "" {
createdBy, err = uuid.Parse(req.CreatedBy)
if err != nil {
return nil, fmt.Errorf("error parse created by id. %w", err)
}
}
ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
defer cancel()
txs, err := c.txInteractor.List(ctx, transactions.ListParams{
IDs: ids,
OrganizationID: organizationID,
To: toAddr,
CreatedBy: createdBy,
Limit: int64(req.Limit),
Cursor: req.Cursor,
WithCancelled: req.Cancelled,
WithConfirmed: req.Confirmed,
WithCommited: req.Commited,
WithExpired: req.Expired,
WithPending: req.Pending,
Limit: int64(req.Limit),
Cursor: req.Cursor,
Pending: req.Pending,
ReadyToConfirm: req.ReadyToConfirm,
})
if err != nil {
return nil, fmt.Errorf("error fetch organizations list. %w", err)
@ -376,6 +342,12 @@ func (c *transactionsController) ListPayrolls(w http.ResponseWriter, r *http.Req
return c.txPresenter.ResponsePayrolls(ctx, payrolls)
}
func (c *transactionsController) SetSalary(w http.ResponseWriter, r *http.Request) ([]byte, error) {
// req, err := presenters.CreateRequest[domain.]()
return presenters.ResponseOK()
}
func (c *transactionsController) ConfirmPayroll(w http.ResponseWriter, r *http.Request) ([]byte, error) {
return nil, nil

View File

@ -65,23 +65,17 @@ type ListOrganizationsRequest struct {
// Transactions
type NewTransactionRequest struct {
Description string `json:"description,omitempty"`
Amount float64 `json:"amount,omitempty"`
ToAddr string `json:"to,omitempty"`
MaxFeeAllowed float64 `json:"max_fee_allowed,omitempty"`
Deadline int64 `json:"deadline,omitempty"`
Description string `json:"description,omitempty"`
Amount float64 `json:"amount,omitempty"`
ToAddr string `json:"to,omitempty"`
MultisigID string `json:"multisig_id"`
ConfirmationsRequired int `json:"confirmations_required"`
}
type ListTransactionsRequest struct {
IDs []string `json:"ids,omitempty"`
CreatedBy string `json:"created_by,omitempty"`
To string `json:"to,omitempty"`
Cancelled bool `json:"cancelled,omitempty"`
Confirmed bool `json:"confirmed,omitempty"`
Commited bool `json:"commited,omitempty"`
Expired bool `json:"expired,omitempty"`
Pending bool `json:"pending,omitempty"`
ReadyToConfirm bool `json:"ready_to_confirm"`
Pending bool `json:"pending"`
Cursor string `json:"cursor,omitempty"`
Limit uint8 `json:"limit,omitempty"` // Default: 50, Max: 50
@ -116,6 +110,15 @@ type NewMultisigRequest struct {
Confirmations int `json:"confirmations"`
}
type ListMultisigsRequest struct{}
type NewMultisigDepositRequest struct {
MultisigID string `json:"multisig_id"`
Amount float64 `json:"amount"`
}
// Payrolls and salaries
type NewPayrollRequest struct {
MultisigID string `json:"multisig_id"`
Title string `json:"title"`
@ -125,3 +128,23 @@ type ListPayrollsRequest struct {
IDs []string `json:"ids"`
Limit uint8 `json:"limit"`
}
type SetSalaryRequest struct {
EmployeeID string `json:"employee_id"`
Salary float64 `json:"salary"`
PayrollID string `json:"payroll_id"`
}
type NewPayoutRequest struct {
EmployeeID string `json:"employee_id"`
SalaryID string `json:"salary_id"`
}
type NewDepositRequest struct {
PayrollID string `json:"payroll_id"`
Amount float64 `json:"amount"`
}
type ConfirmSalaryRequest struct {
SalaryID string `json:"salary_id"`
}

View File

@ -12,6 +12,8 @@ type Participant struct {
UpdatedAt int64 `json:"updated_at"`
DeletedAt int64 `json:"deleted_at,omitempty"`
PublicKey string `json:"public_key"`
IsUser bool `json:"is_user"`
IsAdmin bool `json:"is_admin"`
IsOwner bool `json:"is_owner"`

View File

@ -36,7 +36,7 @@ func NewAuthPresenter(
}
func (p *authPresenter) ResponseJoin(user *models.User) ([]byte, error) {
tokens, err := p.jwtInteractor.NewToken(user, 24*time.Hour, "")
tokens, err := p.jwtInteractor.NewToken(user, 24*time.Hour*30, "")
if err != nil {
return nil, fmt.Errorf("error create access token. %w", err)
}
@ -55,7 +55,7 @@ func (p *authPresenter) ResponseJoin(user *models.User) ([]byte, error) {
}
func (p *authPresenter) ResponseLogin(user *models.User) ([]byte, error) {
tokens, err := p.jwtInteractor.NewToken(user, 24*time.Hour, "")
tokens, err := p.jwtInteractor.NewToken(user, 24*time.Hour*30, "")
if err != nil {
return nil, fmt.Errorf("error create access token. %w", err)
}

View File

@ -9,6 +9,7 @@ import (
"github.com/emochka2007/block-accounting/internal/interface/rest/domain/hal"
"github.com/emochka2007/block-accounting/internal/pkg/ctxmeta"
"github.com/emochka2007/block-accounting/internal/pkg/models"
"github.com/ethereum/go-ethereum/common"
)
type ParticipantsPresenter interface {
@ -62,6 +63,7 @@ func (p *participantsPresenter) ResponseParticipantHal(
}
domainParticipant.Position = user.Position()
domainParticipant.PublicKey = common.Bytes2Hex(user.PublicKey())
domainParticipant.IsUser = true
domainParticipant.IsAdmin = user.IsAdmin()
domainParticipant.IsOwner = user.IsOwner()

View File

@ -61,14 +61,9 @@ func (p *transactionsPresenter) RequestTransaction(
Description: r.Description,
Amount: r.Amount,
ToAddr: toAddress.Bytes(),
MaxFeeAllowed: r.MaxFeeAllowed,
CreatedAt: time.Now(),
}
if r.Deadline > 0 {
tx.Deadline = time.UnixMilli(r.Deadline)
}
return tx, nil
}

View File

@ -33,3 +33,9 @@ type Payroll struct {
CreatedAt time.Time
UpdatedAt time.Time
}
type Salary struct {
ID uuid.UUID
EmployeeID uuid.UUID
Amount float64
}

View File

@ -19,21 +19,10 @@ import (
type ListParams struct {
IDs uuid.UUIDs
OrganizationID uuid.UUID
CreatedBy uuid.UUID
To []byte
Limit int64
Cursor string
WithPending bool
WithCancelled bool
WithConfirmed bool
WithCommited bool
WithExpired bool
WithConfirmations bool
Pending bool
ReadyToConfirm bool
Limit int64
Cursor string
}
type CreateParams struct {
@ -133,17 +122,11 @@ func (i *transactionsInteractor) List(ctx context.Context, params ListParams) (*
}
txs, err := i.txRepo.GetTransactions(ctx, transactions.GetTransactionsParams{
Ids: params.IDs,
OrganizationId: params.OrganizationID,
CreatedById: params.CreatedBy,
To: params.To,
Limit: params.Limit,
CursorId: cursor.Id,
WithCancelled: params.WithCancelled,
WithConfirmed: params.WithConfirmed,
WithCommited: params.WithCommited,
WithExpired: params.WithExpired,
WithPending: params.WithPending,
Pending: params.Pending,
ReadyToConfirm: params.ReadyToConfirm,
})
if err != nil {
return nil, fmt.Errorf("error fetch transaction from repository. %w", err)

View File

@ -17,18 +17,11 @@ import (
type GetTransactionsParams struct {
Ids uuid.UUIDs
OrganizationId uuid.UUID
CreatedById uuid.UUID
To []byte
Limit int64
CursorId uuid.UUID
WithCancelled bool
WithConfirmed bool
WithCommited bool
WithExpired bool
WithPending bool
WithConfirmations bool
Pending bool
ReadyToConfirm bool
}
type ConfirmTransactionParams struct {
@ -309,8 +302,10 @@ func buildGetTransactionsQuery(params GetTransactionsParams) sq.SelectBuilder {
t.to_addr,
t.max_fee_allowed,
t.deadline,
t.confirmations_required,
t.created_at,
t.updated_at,
t.confirmed_at,
t.cancelled_at,
t.commited_at,
@ -335,73 +330,16 @@ func buildGetTransactionsQuery(params GetTransactionsParams) sq.SelectBuilder {
})
}
if params.CreatedById != uuid.Nil {
query = query.Where(sq.Eq{
"t.created_by": params.CreatedById,
})
}
if params.OrganizationId != uuid.Nil {
query = query.Where(sq.Eq{
"t.organization_id": params.OrganizationId,
})
}
if params.To != nil {
query = query.Where(sq.Eq{
"t.to_addr": params.To,
})
}
if params.WithExpired {
query = query.Where(sq.LtOrEq{
"t.deadline": time.Now(),
})
} else {
query = query.Where(sq.Or{
sq.GtOrEq{
"t.deadline": time.Now(),
},
sq.Eq{
"t.deadline": nil,
},
})
}
if params.WithCancelled {
query = query.Where(sq.NotEq{
"t.cancelled_at": nil,
})
}
if params.WithConfirmed {
query = query.Where(sq.NotEq{
"t.confirmed_at": nil,
})
}
if params.WithCommited {
query = query.Where(sq.NotEq{
"t.commited_at": nil,
})
}
if params.Limit <= 0 || params.Limit > 50 {
params.Limit = 50
}
if params.WithPending {
query = query.Where(sq.Eq{
"t.cancelled_at": nil,
"t.commited_at": nil,
"t.confirmed_at": nil,
})
}
if params.CursorId != uuid.Nil {
query = query.Where(sq.Gt{
"t.id": params.CursorId,
})
if params.Pending {
query = query.InnerJoin("multisig_confirmations as mc on mc.multisig_id = t.multisig_id").Where(
sq.Lt{},
)
}
query = query.Limit(uint64(params.Limit))

View File

@ -90,72 +90,9 @@ create index if not exists index_organizations_users_organization_id_user_id
create index if not exists index_organizations_users_organization_id_employee_id
on organizations_users (organization_id, employee_id);
create table if not exists transactions (
id uuid primary key,
description text default 'New Transaction',
organization_id uuid not null,
created_by uuid not null,
amount decimal default 0,
to_addr bytea not null,
tx_index bigint default 0,
max_fee_allowed decimal default 0,
deadline timestamp default null,
status int default 0,
created_at timestamp default current_timestamp,
updated_at timestamp default current_timestamp,
confirmed_at timestamp default null,
cancelled_at timestamp default null,
commited_at timestamp default null
);
create index if not exists index_transactions_id_organization_id
on transactions (organization_id);
create index if not exists index_transactions_id_organization_id_created_by
on transactions (organization_id, created_by);
create index if not exists index_transactions_organization_id_deadline
on transactions (organization_id, deadline);
create table transactions_confirmations (
tx_id uuid not null,
user_id uuid not null,
organization_id uuid not null,
created_at timestamp default current_timestamp,
updated_at timestamp default current_timestamp,
confirmed bool
);
create index if not exists index_transactions_confirmations_tx_id_user_id_organization_id
on transactions_confirmations (tx_id, user_id, organization_id);
create table contracts (
id uuid primary key,
title varchar(250) default 'New Contract',
description text not null,
address bytea not null,
payload bytea not null,
created_by uuid not null references users(id),
organization_id uuid not null references organizations(id),
status smallint default 0,
tx_index bytea default null,
multisig bytea default null,
created_at timestamp default current_timestamp,
updated_at timestamp default current_timestamp
);
create index if not exists idx_contracts_organization_id_multisig
on contracts (organization_id, multisig);
create index if not exists idx_contracts_organization_id_created_by
on contracts (organization_id, created_by);
create table multisigs (
id uuid primary key,
organization_id uuid not null references organizations(id),
@ -217,3 +154,47 @@ create table payrolls (
created_at timestamp default current_timestamp,
updated_at timestamp default current_timestamp
);
create table if not exists transactions (
id uuid primary key,
description text default 'New Transaction',
organization_id uuid not null,
created_by uuid not null,
amount decimal default 0,
to_addr bytea not null,
tx_index bigint default 0,
max_fee_allowed decimal default 0,
deadline timestamp default null,
confirmations_required bigint default 1,
multisig_id uuid default null,
status int default 0,
created_at timestamp default current_timestamp,
updated_at timestamp default current_timestamp,
confirmed_at timestamp default null,
cancelled_at timestamp default null,
commited_at timestamp default null
);
create index if not exists index_transactions_id_organization_id
on transactions (organization_id);
create index if not exists index_transactions_id_organization_id_created_by
on transactions (organization_id, created_by);
create index if not exists index_transactions_organization_id_deadline
on transactions (organization_id, deadline);
create table transactions_confirmations (
tx_id uuid not null,
user_id uuid not null,
organization_id uuid not null,
created_at timestamp default current_timestamp,
updated_at timestamp default current_timestamp,
confirmed bool
);