Skip to content

Commit

Permalink
feat: resume solowallet transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
okjodom committed Jan 9, 2025
1 parent 9a995bc commit dd054fb
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 4 deletions.
10 changes: 10 additions & 0 deletions apps/api/src/solowallet/solowallet.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
ContinueTxRequestDto,
DepositFundsRequestDto,
UpdateTxDto,
UserTxsRequestDto,
Expand Down Expand Up @@ -51,4 +52,13 @@ export class SolowalletController {
updateShares(@Body() req: UpdateTxDto) {
return this.walletService.updateTransaction(req);
}

@Post('continue')
@ApiOperation({ summary: 'Continue Solowallet transaction' })
@ApiBody({
type: ContinueTxRequestDto,
})
continueTransaction(@Body() req: ContinueTxRequestDto) {
return this.walletService.continueTransaction(req);
}
}
5 changes: 5 additions & 0 deletions apps/api/src/solowallet/solowallet.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
SolowalletServiceClient,
WithdrawFundsRequestDto,
UpdateTxDto,
ContinueTxRequestDto,
} from '@bitsacco/common';
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { type ClientGrpc } from '@nestjs/microservices';
Expand Down Expand Up @@ -38,4 +39,8 @@ export class SolowalletService implements OnModuleInit {
updateTransaction(req: UpdateTxDto) {
return this.client.updateTransaction(req);
}

continueTransaction(req: ContinueTxRequestDto) {
return this.client.continueTransaction(req);
}
}
6 changes: 6 additions & 0 deletions apps/solowallet/src/solowallet.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
UserTxsRequestDto,
WithdrawFundsRequestDto,
UpdateTxDto,
ContinueTxRequestDto,
} from '@bitsacco/common';
import { SolowalletService } from './solowallet.service';

Expand Down Expand Up @@ -33,4 +34,9 @@ export class SolowalletController {
updateTransaction(request: UpdateTxDto) {
return this.solowalletService.updateTransaction(request);
}

@GrpcMethod()
continueTransaction(request: ContinueTxRequestDto) {
return this.solowalletService.continueTransaction(request);
}
}
80 changes: 77 additions & 3 deletions apps/solowallet/src/solowallet.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
WithdrawFundsRequestDto,
CreateOfframpSwapDto,
UpdateTxDto,
ContinueTxRequestDto,
} from '@bitsacco/common';
import { type ClientGrpc } from '@nestjs/microservices';
import { catchError, firstValueFrom, map, of, tap } from 'rxjs';
Expand Down Expand Up @@ -71,7 +72,7 @@ export class SolowalletService {
})
.pipe(
tap((quote: QuoteResponse) => {
this.logger.log(`Quote: ${quote}`);
this.logger.log(`Quote: ${JSON.stringify(quote)}`);
}),
map((quote: QuoteResponse) => {
const { amountMsats } = fiatToBtc({
Expand Down Expand Up @@ -114,7 +115,7 @@ export class SolowalletService {
.createOnrampSwap(fiatDeposit)
.pipe(
tap((swap: SwapResponse) => {
this.logger.log(`Swap: ${swap}`);
this.logger.log(`Swap: ${JSON.stringify(swap)}`);
}),
map((swap: SwapResponse) => {
const { amountMsats } = fiatToBtc({
Expand Down Expand Up @@ -330,7 +331,7 @@ export class SolowalletService {
status: TransactionStatus.PENDING,
};

this.logger.log(status);
this.logger.log(`Status: ${status}`);
const deposit = await this.wallet.create({
userId,
amountMsats,
Expand Down Expand Up @@ -490,6 +491,79 @@ export class SolowalletService {
};
}

async continueTransaction({
userId,
txId,
amountFiat,
onramp,
}: ContinueTxRequestDto): Promise<UserTxsResponse> {
const tx = await this.wallet.findOne({ _id: txId });

if (tx.userId !== userId) {
throw 'Invalid request to continue transaction';
}

const { quote, amountMsats } = await this.getQuote({
from: onramp?.currency || Currency.KES,
to: Currency.BTC,
amount: amountFiat.toString(),
});

const lightning = await this.fedimintService.invoice(
amountMsats,
tx.reference,
);

const { status } = onramp
? await this.initiateOnrampSwap({
quote,
amountFiat: amountFiat.toString(),
reference: tx.reference,
source: onramp,
target: {
payout: lightning,
},
})
: {
status: TransactionStatus.PENDING,
};

this.logger.log(`Status: ${status}`);
const deposit = await this.wallet.findOneAndUpdate(
{
_id: txId,
userId,
},
{
amountMsats,
amountFiat,
lightning: JSON.stringify(lightning),
paymentTracker: lightning.operationId,
status,
},
);

// listen for payment
this.fedimintService.receive(
ReceiveContext.SOLOWALLET,
lightning.operationId,
);

const ledger = await this.getPaginatedUserTxLedger({
userId,
pagination: { page: 0, size: 10 },
});

const meta = await this.getWalletMeta(userId);

return {
txId: deposit._id,
ledger,
meta,
userId,
};
}

@OnEvent(fedimint_receive_success)
private async handleSuccessfulReceive({
context,
Expand Down
1 change: 0 additions & 1 deletion libs/common/src/database/abstract.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
Model,
PipelineStage,
SortOrder,
Types,
UpdateQuery,
} from 'mongoose';
import { Logger, NotFoundException } from '@nestjs/common';
Expand Down
26 changes: 26 additions & 0 deletions libs/common/src/dto/solowallet.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
UpdateTxRequest,
SolowalletTxUpdates,
TransactionStatus,
ContinueTxRequest,
} from '../types';
import { PaginatedRequestDto } from './lib.dto';

Expand Down Expand Up @@ -125,3 +126,28 @@ export class UpdateTxDto implements UpdateTxRequest {
@ApiProperty({ type: SolowalletTxUpdatesDto })
updates: SolowalletTxUpdatesDto;
}

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

@IsNotEmpty()
@IsString()
@Type(() => String)
@ApiProperty({ example: '35f47ebd-599e-4334-a741-67f3495995e3' })
txId: string;

@ApiProperty()
@IsNumber()
@Min(1)
@ApiProperty({ example: 2 })
amountFiat: number;

@ValidateNested()
@Type(() => OnrampSwapSourceDto)
@ApiProperty({ type: OnrampSwapSourceDto })
onramp?: OnrampSwapSourceDto;
}
14 changes: 14 additions & 0 deletions libs/common/src/types/proto/solowallet.ts

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

12 changes: 12 additions & 0 deletions proto/solowallet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ service SolowalletService {
rpc UserTransactions(UserTxsRequest) returns (UserTxsResponse){}

rpc UpdateTransaction(UpdateTxRequest) returns (UserTxsResponse) {}

rpc ContinueTransaction(ContinueTxRequest) returns (UserTxsResponse) {}
}

message DepositFundsRequest {
Expand Down Expand Up @@ -110,3 +112,13 @@ message SolowalletTxUpdates {
optional lightning.Bolt11 lightning = 2;
optional string reference = 3;
}

message ContinueTxRequest {
string user_id = 1;

string tx_id = 2;

int32 amount_fiat = 3;

optional swap.OnrampSwapSource onramp = 5;
}

0 comments on commit dd054fb

Please sign in to comment.