Skip to content

Commit

Permalink
feat: impl bitcoin transactionsCountIn24Hours
Browse files Browse the repository at this point in the history
  • Loading branch information
ahonn committed Jul 30, 2024
1 parent b9c1247 commit 39cd2b3
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 24 deletions.
7 changes: 6 additions & 1 deletion backend/src/modules/api.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Env } from 'src/env';
import { CkbModule } from './ckb/ckb.module';
import { RgbppModule } from './rgbpp/rgbpp.module';
import { BitcoinModule } from './bitcoin/bitcoin.module';
import { FastifyReply, FastifyRequest } from 'fastify';

@Module({
imports: [
Expand All @@ -25,7 +26,11 @@ import { BitcoinModule } from './bitcoin/bitcoin.module';
buildSchemaOptions: {
dateScalarMode: 'timestamp',
},
context: () => {
context: (req: FastifyRequest, res: FastifyReply) => {
if (req.method === 'GET') {
res.redirect(302, '/graphiql');
return;
}
return {
span: sentryService.instance().startInactiveSpan({
op: 'gql',
Expand Down
30 changes: 25 additions & 5 deletions backend/src/modules/bitcoin/bitcoin.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { Float, Query, ResolveField, Resolver } from '@nestjs/graphql';
import { Float, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql';
import { BitcoinApiService } from 'src/core/bitcoin-api/bitcoin-api.service';
import { BitcoinBaseChainInfo, BitcoinChainInfo, BitcoinFees } from './bitcoin.model';
import { Loader } from '@applifting-io/nestjs-dataloader';
import {
BitcoinBlockTransactionsLoader,
BitcoinBlockTransactionsLoaderType,
} from './block/block.dataloader';

// 60 * 24 = 1440 minutes
const BLOCK_NUMBER_OF_24_HOURS = 144;

@Resolver(() => BitcoinChainInfo)
export class BitcoinResolver {
constructor(private bitcoinApiService: BitcoinApiService) {}
constructor(private bitcoinApiService: BitcoinApiService) { }

@Query(() => BitcoinChainInfo, { name: 'btcChainInfo' })
public async chainInfo(): Promise<BitcoinBaseChainInfo> {
Expand All @@ -13,9 +21,21 @@ export class BitcoinResolver {
}

@ResolveField(() => Float)
public async transactionsCountIn24Hours(): Promise<number> {
// TODO: implement this resolver
return 0;
public async transactionsCountIn24Hours(
@Parent() chainInfo: BitcoinBaseChainInfo,
@Loader(BitcoinBlockTransactionsLoader) blockTxsLoader: BitcoinBlockTransactionsLoaderType,
): Promise<number> {
const blockNumbers = Array.from(
{ length: BLOCK_NUMBER_OF_24_HOURS },
(_, i) => chainInfo.tipBlockHeight - i,
);
const transactions = await blockTxsLoader.loadMany(
blockNumbers.map((blockNumber) => ({ height: blockNumber })),
);
const count = transactions
.map((txs) => (txs instanceof Array ? txs : []))
.reduce((acc, txs) => acc + txs?.length ?? 0, 0);
return count;
}

@ResolveField(() => BitcoinFees)
Expand Down
25 changes: 15 additions & 10 deletions backend/src/modules/bitcoin/block/block.dataloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as BitcoinApi from 'src/core/bitcoin-api/bitcoin-api.schema';
export class BitcoinBlockLoader implements NestDataLoader<string, BitcoinApi.Block | null> {
private logger = new Logger(BitcoinBlockLoader.name);

constructor(private bitcoinApiService: BitcoinApiService) {}
constructor(private bitcoinApiService: BitcoinApiService) { }

public getBatchFunction() {
return async (keys: string[]) => {
Expand All @@ -32,28 +32,33 @@ export type BitcoinBlockLoaderType = DataLoader<string, BitcoinApi.Block | null>
export type BitcoinBlockLoaderResponse = DataLoaderResponse<BitcoinBlockLoader>;

export interface BitcoinBlockTransactionsLoaderParams {
hash: string;
hash?: string;
height?: number;
startIndex?: number;
}

@Injectable()
export class BitcoinBlockTransactionsLoader
implements NestDataLoader<BitcoinBlockTransactionsLoaderParams, BitcoinApi.Transaction[] | null>
{
implements NestDataLoader<BitcoinBlockTransactionsLoaderParams, BitcoinApi.Transaction[] | null> {
private logger = new Logger(BitcoinBlockLoader.name);

constructor(private bitcoinApiService: BitcoinApiService) {}
constructor(private bitcoinApiService: BitcoinApiService) { }

public getBatchFunction() {
return async (batchProps: BitcoinBlockTransactionsLoaderParams[]) => {
this.logger.debug(`Loading bitcoin block transactions: ${batchProps}`);
const results = await Promise.allSettled(
batchProps.map((props) =>
this.bitcoinApiService.getBlockTxs({
hash: props.hash,
batchProps.map(async (props) => {
let hash = props.hash;
if (props.height && !hash) {
hash = await this.bitcoinApiService.getBlockHeight({ height: props.height });
}
const txs = await this.bitcoinApiService.getBlockTxs({
hash,
startIndex: props.startIndex,
}),
),
});
return txs;
}),
);
return results.map((result) => (result.status === 'fulfilled' ? result.value : null));
};
Expand Down
16 changes: 8 additions & 8 deletions backend/src/modules/ckb/ckb.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export class CkbResolver {
constructor(
private ckbRpcService: CkbRpcWebsocketService,
private ckbExplorerService: CkbExplorerService,
) {}
) { }

@Query(() => CkbChainInfo, { name: 'ckbChainInfo' })
public async chainInfo(): Promise<CkbBaseChainInfo> {
Expand All @@ -31,15 +31,15 @@ export class CkbResolver {
// https://github.com/nervosnetwork/ckb-explorer-frontend/blob/develop/src/utils/chart.ts#L109-L157
// https://github.com/nervosnetwork/ckb-explorer-frontend/blob/develop/src/pages/FeeRateTracker/FeeRateTrackerComp.tsx#L39-L67

const ckbStatsRes = await this.ckbExplorerService.getStatistics();
const ckbStats = ckbStatsRes.data.attributes;
// const ckbStatsRes = await this.ckbExplorerService.getStatistics();
// const ckbStats = ckbStatsRes.data.attributes;

const feesStatsRes = await this.ckbExplorerService.getTransactionFeesStatistic();
const feesStats = feesStatsRes.data.attributes;
// const feesStatsRes = await this.ckbExplorerService.getTransactionFeesStatistic();
// const feesStats = feesStatsRes.data.attributes;

const txFees = feesStats.transaction_fee_rates;
const txsPerMinute = ckbStats.transactions_count_per_minute;
const averageBlockTime = ckbStats.average_block_time;
// const txFees = feesStats.transaction_fee_rates;
// const txsPerMinute = ckbStats.transactions_count_per_minute;
// const averageBlockTime = ckbStats.average_block_time;
return {
fast: 0,
slow: 0,
Expand Down

0 comments on commit 39cd2b3

Please sign in to comment.