Skip to content

Commit

Permalink
feat: update bitsacco shares
Browse files Browse the repository at this point in the history
  • Loading branch information
okjodom committed Jan 1, 2025
1 parent 2bfc04e commit 3e391c6
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 28 deletions.
22 changes: 12 additions & 10 deletions apps/api/src/shares/shares.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,10 @@ import {
OfferSharesDto,
SubscribeSharesDto,
TransferSharesDto,
UpdateSharesDto,
} from '@bitsacco/common';
import {
Body,
Controller,
Get,
Logger,
Param,
Post,
Query,
} from '@nestjs/common';
import { ApiOperation, ApiBody, ApiQuery, ApiParam } from '@nestjs/swagger';
import { Body, Controller, Get, Logger, Param, Post } from '@nestjs/common';
import { ApiOperation, ApiBody, ApiParam } from '@nestjs/swagger';
import { SharesService } from './shares.service';

@Controller('shares')
Expand Down Expand Up @@ -56,6 +49,15 @@ export class SharesController {
return this.sharesService.transferShares(req);
}

@Post('update')
@ApiOperation({ summary: 'Update Bitsacco shares' })
@ApiBody({
type: UpdateSharesDto,
})
updateShares(@Body() req: UpdateSharesDto) {
return this.sharesService.updateShares(req);
}

@Get('transactions')
@ApiOperation({ summary: 'List all Bitsacco share transactions' })
allSharesTransactions() {
Expand Down
5 changes: 5 additions & 0 deletions apps/api/src/shares/shares.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
SubscribeSharesDto,
TransferSharesDto,
UserSharesDto,
UpdateSharesDto,
} from '@bitsacco/common';
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { type ClientGrpc } from '@nestjs/microservices';
Expand Down Expand Up @@ -37,6 +38,10 @@ export class SharesService implements OnModuleInit {
return this.client.transferShares(req);
}

updateShares(req: UpdateSharesDto) {
return this.client.updateShares(req);
}

userSharesTransactions(req: UserSharesDto) {
return this.client.userSharesTransactions(req);
}
Expand Down
6 changes: 6 additions & 0 deletions apps/shares/src/shares.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
SharesServiceControllerMethods,
SubscribeSharesDto,
TransferSharesDto,
UpdateSharesDto,
UserTxsRequestDto,
} from '@bitsacco/common';
import { SharesService } from './shares.service';
Expand Down Expand Up @@ -35,6 +36,11 @@ export class SharesController {
return this.sharesService.transferShares(request);
}

@GrpcMethod()
updateShares(request: UpdateSharesDto) {
return this.sharesService.updateShares(request);
}

@GrpcMethod()
userSharesTransactions(request: UserTxsRequestDto) {
return this.sharesService.userSharesTransactions(request);
Expand Down
44 changes: 30 additions & 14 deletions apps/shares/src/shares.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
SharesTxStatus,
SubscribeSharesDto,
TransferSharesDto,
UpdateSharesDto,
UserSharesDto,
UserShareTxsResponse,
} from '@bitsacco/common';
Expand Down Expand Up @@ -90,10 +91,6 @@ export class SharesService {
sharesId,
...transfer
}: TransferSharesDto): Promise<UserShareTxsResponse> {
// const originShares = await this.userShareTransactions({
// userId: fromUserId,
// });

const originShares = await this.shares.findOne({ _id: sharesId });

if (originShares.status !== SharesTxStatus.COMPLETE) {
Expand All @@ -104,29 +101,48 @@ export class SharesService {
throw new Error('Not enough shares to transfer');
}

await this.shares.findOneAndUpdate(
{ _id: sharesId },
{
$set: {
quantity: originShares.quantity - transfer.quantity,
updatedAt: Date.now(),
transfer,
},
// Update origin shares quantity, and record transfer metadata
await this.updateShares({
sharesId,
updates: {
quantity: originShares.quantity - transfer.quantity,
transfer,
},
);
});

// Assign shares to the recipient
await this.shares.create({
userId: transfer.toUserId,
offerId: originShares.offerId,
quantity: transfer.quantity,
transfer,
status: SharesTxStatus.COMPLETE,
transfer,
});

return this.userSharesTransactions({ userId: transfer.fromUserId });
}

async updateShares({
sharesId,
updates,
}: UpdateSharesDto): Promise<UserShareTxsResponse> {
const originShares = await this.shares.findOne({ _id: sharesId });
const { quantity, status, transfer, offerId } = updates;

let { userId } = await this.shares.findOneAndUpdate(
{ _id: sharesId },
{
quantity: quantity ?? originShares.quantity,
status: status ?? originShares.status,
transfer: transfer ?? originShares.transfer,
offerId: offerId ?? originShares.offerId,
updatedAt: Date.now(),
},
);

return this.userSharesTransactions({ userId });
}

async userSharesTransactions({
userId,
}: UserSharesDto): Promise<UserShareTxsResponse> {
Expand Down
82 changes: 78 additions & 4 deletions libs/common/src/dto/shares.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@ import {
IsPositive,
IsNumber,
IsDateString,
IsEnum,
IsOptional,
ValidateNested,
IsNotEmptyObject,
} from 'class-validator';
import {
OfferSharesRequest,
SharesTxStatus,
type SharesTxTransferMeta,
SharesTxUpdates,
SubscribeSharesRequest,
TransferSharesRequest,
UpdateSharesRequest,
UserSharesTxsRequest,
} from '@bitsacco/common';
import { ApiProperty } from '@nestjs/swagger';
Expand All @@ -24,13 +32,19 @@ export class OfferSharesDto implements OfferSharesRequest {
@IsNotEmpty()
@IsDateString()
@Type(() => String)
@ApiProperty({ description: 'Start date of availability (ISO 8601 format)', example: '2024-12-30T12:19:04.077Z' })
@ApiProperty({
description: 'Start date of availability (ISO 8601 format)',
example: '2024-12-30T12:19:04.077Z',
})
availableFrom: string;

@IsNotEmpty()
@IsDateString()
@Type(() => String)
@ApiProperty({ description: 'End date of availability (ISO 8601 format)', example: '2025-12-30T12:19:04.077Z' })
@ApiProperty({
description: 'End date of availability (ISO 8601 format)',
example: '2025-12-30T12:19:04.077Z',
})
availableTo?: string;
}

Expand All @@ -50,7 +64,7 @@ export class SubscribeSharesDto implements SubscribeSharesRequest {
@IsPositive()
@IsNumber()
@Type(() => Number)
@ApiProperty()
@ApiProperty({ description: 'Amount of shares to subscribe', example: 21 })
quantity: number;
}

Expand All @@ -76,10 +90,70 @@ export class TransferSharesDto implements TransferSharesRequest {
@IsPositive()
@IsNumber()
@Type(() => Number)
@ApiProperty()
@ApiProperty({ description: 'Amount of shares to transfer', example: 10 })
quantity: number;
}

class SharesTxTransferMetaDto implements SharesTxTransferMeta {
@IsNotEmpty()
@IsString()
@Type(() => String)
@ApiProperty({ example: '7b158dfd-cb98-40b1-9ed2-a13006a9f670' })
fromUserId: string;

@IsNotEmpty()
@IsString()
@Type(() => String)
@ApiProperty({ example: '8b158dfd-cb98-40b1-9ed2-a13006a9f671' })
toUserId: string;

@IsPositive()
@IsNumber()
@Type(() => Number)
@ApiProperty({ description: 'Amount of shares transferred', example: 10 })
quantity: number;
}

class SharesTxUpdatesDto implements SharesTxUpdates {
@IsOptional()
@IsPositive()
@IsNumber()
@Type(() => Number)
@ApiProperty()
quantity?: number;

@IsOptional()
@IsEnum(SharesTxStatus)
@ApiProperty({ enum: SharesTxStatus })
status?: SharesTxStatus;

@IsOptional()
@ValidateNested()
@Type(() => SharesTxTransferMetaDto)
@ApiProperty({ type: SharesTxTransferMetaDto })
transfer?: SharesTxTransferMeta;

@IsOptional()
@IsString()
@Type(() => String)
@ApiProperty({ example: '3e158dfd-cb98-40b1-9ed2-a13006a9f430' })
offerId?: string;
}

export class UpdateSharesDto implements UpdateSharesRequest {
@IsNotEmpty()
@IsString()
@Type(() => String)
@ApiProperty({ example: '3e158dfd-cb98-40b1-9ed2-a13006a9f430' })
sharesId: string;

@IsNotEmptyObject()
@ValidateNested()
@Type(() => SharesTxUpdatesDto)
@ApiProperty({ type: SharesTxUpdatesDto })
updates: SharesTxUpdatesDto;
}

export class UserSharesDto implements UserSharesTxsRequest {
@IsNotEmpty()
@IsString()
Expand Down
22 changes: 22 additions & 0 deletions libs/common/src/types/proto/shares.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions proto/shares.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ service SharesService {
rpc GetSharesOffers(lib.Empty) returns (AllSharesOffers);
rpc SubscribeShares(SubscribeSharesRequest) returns (UserShareTxsResponse);
rpc TransferShares(TransferSharesRequest) returns (UserShareTxsResponse);
rpc UpdateShares(UpdateSharesRequest) returns (UserShareTxsResponse);
rpc UserSharesTransactions(UserSharesTxsRequest) returns (UserShareTxsResponse);
rpc AllSharesTransactions(lib.Empty) returns (AllSharesTxsResponse);
}
Expand Down Expand Up @@ -101,6 +102,21 @@ message TransferSharesRequest {
int32 quantity = 4;
}

message UpdateSharesRequest {
string shares_id = 1;
SharesTxUpdates updates = 2;
}

message SharesTxUpdates {
optional int32 quantity = 1;

optional SharesTxStatus status = 2;

optional SharesTxTransferMeta transfer = 3;

optional string offer_id = 4;
}

message UserSharesTxsRequest {
string user_id = 1;
}
Expand Down

0 comments on commit 3e391c6

Please sign in to comment.