From fc71ef429e3248d8122be9afa46e86c990f03bdd Mon Sep 17 00:00:00 2001 From: okjodom Date: Fri, 29 Nov 2024 08:16:29 +0300 Subject: [PATCH] feat: onramp to solo wallet (#37) * feat: solowallet api * chore: bump africastalking * fix: bootstrap solowallet * refactor: use shared transaction state definition * feat: solowallet depends on swap service * feat: onramp to solowallet --- apps/api/src/api.module.ts | 19 ++++ apps/api/src/shares/shares.service.ts | 4 +- .../solowallet/solowallet.controller.spec.ts | 31 ++++++ .../src/solowallet/solowallet.controller.ts | 22 ++++ .../src/solowallet/solowallet.service.spec.ts | 37 +++++++ apps/api/src/solowallet/solowallet.service.ts | 26 +++++ apps/solowallet/.env.manual | 3 +- apps/solowallet/src/db/solowallet.schema.ts | 17 ++- apps/solowallet/src/main.ts | 2 + apps/solowallet/src/solowallet.controller.ts | 12 ++- apps/solowallet/src/solowallet.module.ts | 23 +++- apps/solowallet/src/solowallet.service.ts | 98 ++++++++++++++++-- apps/swap/src/swap.service.spec.ts | 6 +- apps/swap/src/swap.service.ts | 32 +++--- bun.lockb | Bin 331630 -> 331630 bytes compose.yml | 23 ++++ libs/common/src/constants/events.ts | 1 + libs/common/src/dto/solowallet.dto.ts | 2 +- libs/common/src/types/proto/lib.ts | 9 ++ libs/common/src/types/proto/solowallet.ts | 20 +++- libs/common/src/types/proto/swap.ts | 12 +-- package.json | 1 + proto/lib.proto | 8 ++ proto/solowallet.proto | 23 +++- proto/swap.proto | 11 +- 25 files changed, 382 insertions(+), 60 deletions(-) create mode 100644 apps/api/src/solowallet/solowallet.controller.spec.ts create mode 100644 apps/api/src/solowallet/solowallet.controller.ts create mode 100644 apps/api/src/solowallet/solowallet.service.spec.ts create mode 100644 apps/api/src/solowallet/solowallet.service.ts diff --git a/apps/api/src/api.module.ts b/apps/api/src/api.module.ts index 5c9eac9..041fd3f 100644 --- a/apps/api/src/api.module.ts +++ b/apps/api/src/api.module.ts @@ -9,6 +9,7 @@ import { NOSTR_SERVICE_NAME, SHARES_SERVICE_NAME, SMS_SERVICE_NAME, + SOLOWALLET_SERVICE_NAME, SWAP_SERVICE_NAME, } from '@bitsacco/common'; import { SwapController, SwapService } from './swap'; @@ -19,6 +20,8 @@ import { SharesService } from './shares/shares.service'; import { SharesController } from './shares/shares.controller'; import { AdminController } from './admin/admin.controller'; import { AdminService } from './admin/admin.service'; +import { SolowalletService } from './solowallet/solowallet.service'; +import { SolowalletController } from './solowallet/solowallet.controller'; @Module({ imports: [ @@ -31,6 +34,8 @@ import { AdminService } from './admin/admin.service'; SWAP_GRPC_URL: Joi.string().required(), NOSTR_GRPC_URL: Joi.string().required(), SMS_GRPC_URL: Joi.string().required(), + SHARES_GRPC_URL: Joi.string().required(), + SOLOWALLET_GRPC_URL: Joi.string().required(), REDIS_HOST: Joi.string().required(), REDIS_PORT: Joi.number().required(), }), @@ -84,6 +89,18 @@ import { AdminService } from './admin/admin.service'; }), inject: [ConfigService], }, + { + name: SOLOWALLET_SERVICE_NAME, + useFactory: (configService: ConfigService) => ({ + transport: Transport.GRPC, + options: { + package: 'solowallet', + protoPath: join(__dirname, '../../../proto/solowallet.proto'), + url: configService.getOrThrow('SOLOWALLET_GRPC_URL'), + }, + }), + inject: [ConfigService], + }, { name: EVENTS_SERVICE_BUS, useFactory: (configService: ConfigService) => ({ @@ -103,6 +120,7 @@ import { AdminService } from './admin/admin.service'; NostrController, SmsController, SharesController, + SolowalletController, ], providers: [ SwapService, @@ -110,6 +128,7 @@ import { AdminService } from './admin/admin.service'; SmsService, SharesService, AdminService, + SolowalletService, ], }) export class ApiModule {} diff --git a/apps/api/src/shares/shares.service.ts b/apps/api/src/shares/shares.service.ts index 1f9c7d3..724b134 100644 --- a/apps/api/src/shares/shares.service.ts +++ b/apps/api/src/shares/shares.service.ts @@ -5,11 +5,11 @@ import { Empty, GetShareDetailDto, } from '@bitsacco/common'; -import { Inject, Injectable } from '@nestjs/common'; +import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; import { type ClientGrpc } from '@nestjs/microservices'; @Injectable() -export class SharesService { +export class SharesService implements OnModuleInit { private client: SharesServiceClient; constructor(@Inject(SHARES_SERVICE_NAME) private readonly grpc: ClientGrpc) {} diff --git a/apps/api/src/solowallet/solowallet.controller.spec.ts b/apps/api/src/solowallet/solowallet.controller.spec.ts new file mode 100644 index 0000000..ba56cf8 --- /dev/null +++ b/apps/api/src/solowallet/solowallet.controller.spec.ts @@ -0,0 +1,31 @@ +import { TestingModule } from '@nestjs/testing'; +import { createTestingModuleWithValidation } from '@bitsacco/testing'; +import { SolowalletController } from './solowallet.controller'; +import { SolowalletService } from './solowallet.service'; + +describe('SolowalletController', () => { + let controller: SolowalletController; + let walletService: SolowalletService; + + beforeEach(async () => { + const module: TestingModule = await createTestingModuleWithValidation({ + controllers: [SolowalletController], + providers: [ + { + provide: SolowalletService, + useValue: { + depositFunds: jest.fn(), + }, + }, + ], + }); + + controller = module.get(SolowalletController); + walletService = module.get(SolowalletService); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + expect(walletService).toBeDefined(); + }); +}); diff --git a/apps/api/src/solowallet/solowallet.controller.ts b/apps/api/src/solowallet/solowallet.controller.ts new file mode 100644 index 0000000..d206ec0 --- /dev/null +++ b/apps/api/src/solowallet/solowallet.controller.ts @@ -0,0 +1,22 @@ +import { DepositFundsRequestDto } from '@bitsacco/common'; +import { Body, Controller, Logger, Post } from '@nestjs/common'; +import { ApiOperation, ApiBody } from '@nestjs/swagger'; +import { SolowalletService } from './solowallet.service'; + +@Controller('solowallet') +export class SolowalletController { + private readonly logger = new Logger(SolowalletController.name); + + constructor(private readonly walletService: SolowalletService) { + this.logger.log('SolowalletController initialized'); + } + + @Post('deposit') + @ApiOperation({ summary: 'Deposit funds to Solowallet' }) + @ApiBody({ + type: DepositFundsRequestDto, + }) + depositFunds(@Body() req: DepositFundsRequestDto) { + return this.walletService.depositFunds(req); + } +} diff --git a/apps/api/src/solowallet/solowallet.service.spec.ts b/apps/api/src/solowallet/solowallet.service.spec.ts new file mode 100644 index 0000000..3027657 --- /dev/null +++ b/apps/api/src/solowallet/solowallet.service.spec.ts @@ -0,0 +1,37 @@ +import { TestingModule } from '@nestjs/testing'; +import { ClientGrpc } from '@nestjs/microservices'; +import { SolowalletServiceClient } from '@bitsacco/common'; +import { createTestingModuleWithValidation } from '@bitsacco/testing'; +import { SolowalletService } from './solowallet.service'; + +describe('SolowalletService', () => { + let service: SolowalletService; + let serviceGenerator: ClientGrpc; + let mockSolowalletServiceClient: Partial; + + beforeEach(async () => { + serviceGenerator = { + getService: jest.fn().mockReturnValue(mockSolowalletServiceClient), + getClientByServiceName: jest + .fn() + .mockReturnValue(mockSolowalletServiceClient), + }; + + const module: TestingModule = await createTestingModuleWithValidation({ + providers: [ + { + provide: SolowalletService, + useFactory: () => { + return new SolowalletService(serviceGenerator); + }, + }, + ], + }); + + service = module.get(SolowalletService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/apps/api/src/solowallet/solowallet.service.ts b/apps/api/src/solowallet/solowallet.service.ts new file mode 100644 index 0000000..6d93c7e --- /dev/null +++ b/apps/api/src/solowallet/solowallet.service.ts @@ -0,0 +1,26 @@ +import { + DepositFundsRequestDto, + SOLOWALLET_SERVICE_NAME, + SolowalletServiceClient, +} from '@bitsacco/common'; +import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; +import { type ClientGrpc } from '@nestjs/microservices'; + +@Injectable() +export class SolowalletService implements OnModuleInit { + private client: SolowalletServiceClient; + + constructor( + @Inject(SOLOWALLET_SERVICE_NAME) private readonly grpc: ClientGrpc, + ) {} + + onModuleInit() { + this.client = this.grpc.getService( + SOLOWALLET_SERVICE_NAME, + ); + } + + depositFunds(req: DepositFundsRequestDto) { + return this.client.depositFunds(req); + } +} diff --git a/apps/solowallet/.env.manual b/apps/solowallet/.env.manual index eb7d277..eee5e7a 100644 --- a/apps/solowallet/.env.manual +++ b/apps/solowallet/.env.manual @@ -1,3 +1,4 @@ NODE_ENV='development' SOLOWALLET_GRPC_URL='0.0.0.0:4080' -DATABASE_URL=mongodb://bs:password@mongodb:27017 +SWAP_GRPC_URL='0.0.0.0:4040' +DATABASE_URL=mongodb://bs:password@0.0.0.0:27017 diff --git a/apps/solowallet/src/db/solowallet.schema.ts b/apps/solowallet/src/db/solowallet.schema.ts index 32d71bd..72e661a 100644 --- a/apps/solowallet/src/db/solowallet.schema.ts +++ b/apps/solowallet/src/db/solowallet.schema.ts @@ -1,5 +1,5 @@ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; -import { AbstractDocument } from '@bitsacco/common'; +import { AbstractDocument, TransactionStatus } from '@bitsacco/common'; @Schema({ versionKey: false }) export class SolowalletDocument extends AbstractDocument { @@ -7,7 +7,20 @@ export class SolowalletDocument extends AbstractDocument { userId: string; @Prop({ type: Number, required: true }) - quantity: number; + amountMsats: number; + + @Prop({ type: Number, required: true }) + amountFiat: number; + + @Prop({ + type: String, + enum: Object.values(TransactionStatus), + required: true, + }) + status: TransactionStatus; + + @Prop({ type: String, required: true }) + reference: string; } export const SolowalletSchema = diff --git a/apps/solowallet/src/main.ts b/apps/solowallet/src/main.ts index 6abcec4..3c20771 100644 --- a/apps/solowallet/src/main.ts +++ b/apps/solowallet/src/main.ts @@ -31,3 +31,5 @@ async function bootstrap() { await app.startAllMicroservices(); } + +bootstrap(); diff --git a/apps/solowallet/src/solowallet.controller.ts b/apps/solowallet/src/solowallet.controller.ts index 96cbfbe..d8bfa0d 100644 --- a/apps/solowallet/src/solowallet.controller.ts +++ b/apps/solowallet/src/solowallet.controller.ts @@ -1,8 +1,10 @@ -import { Controller, Get } from '@nestjs/common'; -import { SolowalletService } from './solowallet.service'; +import { Controller } from '@nestjs/common'; import { GrpcMethod } from '@nestjs/microservices'; -import { SolowalletServiceControllerMethods } from '@bitsacco/common'; -import { DepositFundsRequestDto } from 'libs/common/src/dto/solowallet.dto'; +import { + SolowalletServiceControllerMethods, + DepositFundsRequestDto, +} from '@bitsacco/common'; +import { SolowalletService } from './solowallet.service'; @Controller() @SolowalletServiceControllerMethods() @@ -10,7 +12,7 @@ export class SolowalletController { constructor(private readonly solowalletService: SolowalletService) {} @GrpcMethod() - depositFunds(request: DepositFundsRequestDto): string { + depositFunds(request: DepositFundsRequestDto) { return this.solowalletService.depositFunds(request); } } diff --git a/apps/solowallet/src/solowallet.module.ts b/apps/solowallet/src/solowallet.module.ts index 55d6f78..e783a95 100644 --- a/apps/solowallet/src/solowallet.module.ts +++ b/apps/solowallet/src/solowallet.module.ts @@ -1,6 +1,12 @@ import * as Joi from 'joi'; +import { join } from 'path'; import { Module } from '@nestjs/common'; -import { DatabaseModule, LoggerModule } from '@bitsacco/common'; +import { ClientsModule, Transport } from '@nestjs/microservices'; +import { + DatabaseModule, + LoggerModule, + SWAP_SERVICE_NAME, +} from '@bitsacco/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { SolowalletController } from './solowallet.controller'; import { SolowalletService } from './solowallet.service'; @@ -17,6 +23,7 @@ import { validationSchema: Joi.object({ NODE_ENV: Joi.string().required(), SOLOWALLET_GRPC_URL: Joi.string().required(), + SWAP_GRPC_URL: Joi.string().required(), DATABASE_URL: Joi.string().required(), }), }), @@ -25,6 +32,20 @@ import { { name: SolowalletDocument.name, schema: SolowalletSchema }, ]), LoggerModule, + ClientsModule.registerAsync([ + { + name: SWAP_SERVICE_NAME, + useFactory: (configService: ConfigService) => ({ + transport: Transport.GRPC, + options: { + package: 'swap', + protoPath: join(__dirname, '../../../proto/swap.proto'), + url: configService.getOrThrow('SWAP_GRPC_URL'), + }, + }), + inject: [ConfigService], + }, + ]), ], controllers: [SolowalletController], providers: [SolowalletService, ConfigService, SolowalletRepository], diff --git a/apps/solowallet/src/solowallet.service.ts b/apps/solowallet/src/solowallet.service.ts index 4e9f047..b2a6aff 100644 --- a/apps/solowallet/src/solowallet.service.ts +++ b/apps/solowallet/src/solowallet.service.ts @@ -1,18 +1,104 @@ -import { ConfigService } from '@nestjs/config'; -import { Injectable, Logger } from '@nestjs/common'; -import { DepositFundsRequestDto } from '@bitsacco/common'; +import { Inject, Injectable, Logger } from '@nestjs/common'; +import { + CreateOnrampSwapDto, + DepositFundsRequestDto, + fiatToBtc, + SolowalletDepositTransaction, + SWAP_SERVICE_NAME, + SwapResponse, + SwapServiceClient, + TransactionStatus, +} from '@bitsacco/common'; import { SolowalletRepository } from './db'; +import { type ClientGrpc } from '@nestjs/microservices'; +import { catchError, firstValueFrom, map, of, tap } from 'rxjs'; @Injectable() export class SolowalletService { private readonly logger = new Logger(SolowalletService.name); + private readonly swapService: SwapServiceClient; constructor( private readonly wallet: SolowalletRepository, - private readonly configService: ConfigService, + @Inject(SWAP_SERVICE_NAME) private readonly swapGrpc: ClientGrpc, ) { - this.logger.log('SharesService created'); + this.logger.log('SolowalletService created'); + this.swapService = + this.swapGrpc.getService(SWAP_SERVICE_NAME); } - depositFunds({ userId, fiat_deposit }: DepositFundsRequestDto) {} + private async initiateSwap(fiatDeposit: CreateOnrampSwapDto): Promise<{ + status: TransactionStatus; + amountMsats: number; + amountFiat: number; + reference: string; + }> { + const reference = fiatDeposit.reference; + const amountFiat = Number(fiatDeposit.amountFiat); + + return firstValueFrom( + this.swapService + .createOnrampSwap(fiatDeposit) + .pipe( + tap((swap: SwapResponse) => { + this.logger.log(`Swap: ${swap}`); + }), + map((swap: SwapResponse) => { + const { amountMsats } = fiatToBtc({ + amountFiat, + btcToFiatRate: Number(swap.rate), + }); + + return { + status: swap.status, + amountMsats, + amountFiat, + reference, + }; + }), + ) + .pipe( + catchError((error) => { + this.logger.error('Error in swap:', error); + return of({ + status: TransactionStatus.FAILED, + amountMsats: 0, + amountFiat, + reference, + }); + }), + ), + ); + } + + async depositFunds({ + userId, + fiatDeposit, + }: DepositFundsRequestDto): Promise { + const { status, reference, amountMsats, amountFiat } = fiatDeposit + ? await this.initiateSwap(fiatDeposit) + : { + status: TransactionStatus.PENDING, + reference: '', + amountMsats: 0, + amountFiat: 0, + }; + + this.logger.log(status); + const deposit = await this.wallet.create({ + userId, + amountMsats, + amountFiat, + status, + reference, + }); + + return { + ...deposit, + status, + id: deposit._id, + createdAt: deposit.createdAt.toDateString(), + updatedAt: deposit.updatedAt.toDateString(), + }; + } } diff --git a/apps/swap/src/swap.service.spec.ts b/apps/swap/src/swap.service.spec.ts index 97e5e36..182d5f3 100644 --- a/apps/swap/src/swap.service.spec.ts +++ b/apps/swap/src/swap.service.spec.ts @@ -4,7 +4,7 @@ import { Currency, DatabaseModule, fiatToBtc, - SwapStatus, + TransactionStatus, } from '@bitsacco/common'; import { createTestingModuleWithValidation } from '@bitsacco/testing'; import { TestingModule } from '@nestjs/testing'; @@ -226,7 +226,7 @@ describe.skip('SwapService', () => { const swap = await swapService.createOnrampSwap(req); expect(swap).toBeDefined(); - expect(swap.status).toEqual(SwapStatus.PENDING); + expect(swap.status).toEqual(TransactionStatus.PENDING); }); }); @@ -394,7 +394,7 @@ describe.skip('SwapService', () => { expect(swap).toBeDefined(); expect(swap.rate).toEqual(mock_rate.toString()); - expect(swap.status).toEqual(SwapStatus.PENDING); + expect(swap.status).toEqual(TransactionStatus.PENDING); expect(mockCacheManager.set).toHaveBeenCalled(); }); }); diff --git a/apps/swap/src/swap.service.ts b/apps/swap/src/swap.service.ts index e7b8396..8c909bb 100644 --- a/apps/swap/src/swap.service.ts +++ b/apps/swap/src/swap.service.ts @@ -3,7 +3,7 @@ import { PaginatedRequest, QuoteRequest, QuoteResponse, - SwapStatus, + TransactionStatus, CreateOnrampSwapDto, FindSwapDto, CustomStore, @@ -178,7 +178,7 @@ export class SwapService { return { ...updatedSwap, id: updatedSwap._id.toString(), - status: mapSwapTxStateToSwapStatus(swap.state), + status: mapSwapTxStateToTransactionStatus(swap.state), createdAt: swap.createdAt.toDateString(), updatedAt: swap.updatedAt.toDateString(), }; @@ -191,7 +191,7 @@ export class SwapService { return { ...swap, id: swap._id.toString(), - status: mapSwapTxStateToSwapStatus(swap.state), + status: mapSwapTxStateToTransactionStatus(swap.state), retryCount: swap.retryCount, createdAt: swap.createdAt.toDateString(), updatedAt: swap.updatedAt.toDateString(), @@ -217,7 +217,7 @@ export class SwapService { .map((swap) => ({ ...swap, id: swap._id.toString(), - status: mapSwapTxStateToSwapStatus(swap.state), + status: mapSwapTxStateToTransactionStatus(swap.state), createdAt: swap.createdAt.toDateString(), updatedAt: swap.updatedAt.toDateString(), })); @@ -266,7 +266,9 @@ export class SwapService { ...swap, id: swap._id.toString(), lightning, - status: mapSwapTxStateToSwapStatus(swap.state as SwapTransactionState), + status: mapSwapTxStateToTransactionStatus( + swap.state as SwapTransactionState, + ), createdAt: swap.createdAt.toDateString(), updatedAt: swap.updatedAt.toDateString(), }; @@ -279,7 +281,9 @@ export class SwapService { return { ...swap, id: swap._id.toString(), - status: mapSwapTxStateToSwapStatus(swap.state as SwapTransactionState), + status: mapSwapTxStateToTransactionStatus( + swap.state as SwapTransactionState, + ), retryCount: swap.retryCount, createdAt: swap.createdAt.toDateString(), updatedAt: swap.updatedAt.toDateString(), @@ -305,7 +309,9 @@ export class SwapService { .map((swap) => ({ ...swap, id: swap._id.toString(), - status: mapSwapTxStateToSwapStatus(swap.state as SwapTransactionState), + status: mapSwapTxStateToTransactionStatus( + swap.state as SwapTransactionState, + ), createdAt: swap.createdAt.toDateString(), updatedAt: swap.updatedAt.toDateString(), })); @@ -483,16 +489,18 @@ function mapMpesaTxStateToSwapTxState( } } -function mapSwapTxStateToSwapStatus(state: SwapTransactionState): SwapStatus { +function mapSwapTxStateToTransactionStatus( + state: SwapTransactionState, +): TransactionStatus { switch (state) { case SwapTransactionState.PENDING: - return SwapStatus.PENDING; + return TransactionStatus.PENDING; case SwapTransactionState.FAILED: - return SwapStatus.FAILED; + return TransactionStatus.FAILED; case SwapTransactionState.COMPLETE: - return SwapStatus.COMPLETE; + return TransactionStatus.COMPLETE; case SwapTransactionState.RETRY: case SwapTransactionState.PROCESSING: - return SwapStatus.PROCESSING; + return TransactionStatus.PROCESSING; } } diff --git a/bun.lockb b/bun.lockb index f9294607ec99f8ba97194d93cf2d9839e0fcd7e1..45df185890139924b0be6a348347b439804fa63d 100755 GIT binary patch delta 33 pcmaDiPvqS^k%kt=7N#xC;aTjAaRz$kdIs%rS CreateOnrampSwapDto) @ApiProperty({ type: CreateOnrampSwapDto }) - fiat_deposit?: CreateOnrampSwapDto; + fiatDeposit?: CreateOnrampSwapDto; } diff --git a/libs/common/src/types/proto/lib.ts b/libs/common/src/types/proto/lib.ts index 9d46b62..cb2411d 100644 --- a/libs/common/src/types/proto/lib.ts +++ b/libs/common/src/types/proto/lib.ts @@ -6,4 +6,13 @@ /* eslint-disable */ +/** TransactionStatus: Enum representing the possible statuses of a transaction. */ +export enum TransactionStatus { + PENDING = 0, + PROCESSING = 1, + FAILED = 2, + COMPLETE = 3, + UNRECOGNIZED = -1, +} + export interface Empty {} diff --git a/libs/common/src/types/proto/solowallet.ts b/libs/common/src/types/proto/solowallet.ts index 150b62c..d079472 100644 --- a/libs/common/src/types/proto/solowallet.ts +++ b/libs/common/src/types/proto/solowallet.ts @@ -7,6 +7,7 @@ /* eslint-disable */ import { GrpcMethod, GrpcStreamMethod } from '@nestjs/microservices'; import { Observable } from 'rxjs'; +import { TransactionStatus } from './lib'; import { OnrampSwapRequest } from './swap'; export interface DepositFundsRequest { @@ -14,21 +15,30 @@ export interface DepositFundsRequest { fiatDeposit?: OnrampSwapRequest | undefined; } -export interface WalletDetailsResonse { +export interface SolowalletDepositTransaction { + id: string; userId: string; + status: TransactionStatus; + amountMsats: number; + amountFiat?: number | undefined; + reference: string; + createdAt: string; + updatedAt?: string | undefined; } export interface SolowalletServiceClient { - depositFunds(request: DepositFundsRequest): Observable; + depositFunds( + request: DepositFundsRequest, + ): Observable; } export interface SolowalletServiceController { depositFunds( request: DepositFundsRequest, ): - | Promise - | Observable - | WalletDetailsResonse; + | Promise + | Observable + | SolowalletDepositTransaction; } export function SolowalletServiceControllerMethods() { diff --git a/libs/common/src/types/proto/swap.ts b/libs/common/src/types/proto/swap.ts index 0bb029c..44631a4 100644 --- a/libs/common/src/types/proto/swap.ts +++ b/libs/common/src/types/proto/swap.ts @@ -7,6 +7,7 @@ /* eslint-disable */ import { GrpcMethod, GrpcStreamMethod } from '@nestjs/microservices'; import { Observable } from 'rxjs'; +import { TransactionStatus } from './lib'; import { Bolt11 } from './lightning'; /** Currency: Enum representing supported currencies. */ @@ -16,15 +17,6 @@ export enum Currency { UNRECOGNIZED = -1, } -/** SwapStatus: Enum representing the possible statuses of a swap. */ -export enum SwapStatus { - PENDING = 0, - PROCESSING = 1, - FAILED = 2, - COMPLETE = 3, - UNRECOGNIZED = -1, -} - /** QuoteRequest: Represents a request for a currency swap quote. */ export interface QuoteRequest { /** Currency to swap from */ @@ -172,7 +164,7 @@ export interface SwapResponse { /** lightning invoice to be paid for swap */ lightning: string; /** Current status of the swap */ - status: SwapStatus; + status: TransactionStatus; /** Optional reference to a user */ userId?: string | undefined; retryCount: number; diff --git a/package.json b/package.json index 94ac8de..e819928 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "build:nostr": "bun run build nostr", "build:sms": "bun run build sms", "build:shares": "bun run build shares", + "build:solowallet": "bun run build solowallet", "format": "prettier --write \"apps/**/*.ts\" \"libs/**/*.ts\"", "lint": "bun run eslint \"{apps,libs,test}/**/*.ts\" --fix", "test": "bun test", diff --git a/proto/lib.proto b/proto/lib.proto index 739ef3d..057a60d 100644 --- a/proto/lib.proto +++ b/proto/lib.proto @@ -3,3 +3,11 @@ syntax = "proto3"; package lib; message Empty {} + +// TransactionStatus: Enum representing the possible statuses of a transaction. +enum TransactionStatus { + PENDING = 0; + PROCESSING = 1; + FAILED = 2; + COMPLETE = 3; +} diff --git a/proto/solowallet.proto b/proto/solowallet.proto index 2b0fd3b..9600699 100644 --- a/proto/solowallet.proto +++ b/proto/solowallet.proto @@ -1,11 +1,12 @@ syntax = "proto3"; +import "lib.proto"; import "swap.proto"; package solowallet; service SolowalletService { - rpc DepositFunds(DepositFundsRequest) returns (WalletDetailsResonse){} + rpc DepositFunds(DepositFundsRequest) returns (SolowalletDepositTransaction){} } message DepositFundsRequest { @@ -16,6 +17,22 @@ message DepositFundsRequest { // Add more otional funding sources, like direct lightning deposit } -message WalletDetailsResonse { - string user_id = 1; +message SolowalletDepositTransaction { + string id = 1; + + string user_id = 2; + + lib.TransactionStatus status = 3; + + int32 amount_msats = 4; + + optional int32 amount_fiat = 5; + + reserved 6, 7, 8, 9; + + string reference = 10; + + string createdAt = 11; + + optional string updatedAt = 12; } diff --git a/proto/swap.proto b/proto/swap.proto index c6be19d..17fce42 100644 --- a/proto/swap.proto +++ b/proto/swap.proto @@ -1,5 +1,6 @@ syntax = "proto3"; +import "lib.proto"; import "lightning.proto"; package swap; @@ -152,14 +153,6 @@ enum Currency { KES = 1; } -// SwapStatus: Enum representing the possible statuses of a swap. -enum SwapStatus { - PENDING = 0; - PROCESSING = 1; - FAILED = 2; - COMPLETE = 3; -} - message PaginatedRequest { // Page offset to start from int32 page = 2; @@ -190,7 +183,7 @@ message SwapResponse { string lightning = 3; // Current status of the swap - SwapStatus status = 4; + lib.TransactionStatus status = 4; // Optional reference to a user optional string userId = 5;