Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: get balances from batch addresses #11

Merged
merged 9 commits into from
Feb 8, 2025
3 changes: 3 additions & 0 deletions config.mainnet/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ sync:
rgbppBtcCodeHash: "0xbc6c568a1a0d0a09f6844dc9d74ddb4343c32143ff25f727c59edf4fb72d6936"
rgbppBtcHashType: "type"

rgbppBtcTimelockCodeHash: "0x70d64497a075bd651e98ac030455ea200637ee325a12ad08aff03f1a117e5a62"
rgbppBtcTimelockHashType: "type"

udtTypes:
# sUDT
- codeHash: "0x5e7a36a77e68eecc013dfa2fe6a23f3b6c344b04005808694ae6dd45eea4cfd5"
Expand Down
3 changes: 3 additions & 0 deletions config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ sync:
rgbppBtcCodeHash: "0xd07598deec7ce7b5665310386b4abd06a6d48843e953c5cc2112ad0d5a220364"
rgbppBtcHashType: "type"

rgbppBtcTimelockCodeHash: "0x80a09eca26d77cea1f5a69471c59481be7404febf40ee90f886c36a948385b55"
rgbppBtcTimelockHashType: "type"

udtTypes:
# sUDT
- codeHash: "0x48dbf59b4c7ee1547238021b4869bceedf4eea6b43772e5d66ef8865b6ae7212"
Expand Down
42 changes: 38 additions & 4 deletions libs/asset/src/asset.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
EventType,
extractIsomorphicInfo,
IsomorphicBinding,
LeapType,
NormalizedReturn,
RpcError,
ScriptMode,
Expand All @@ -25,7 +26,7 @@ import { AssetService } from "./asset.service";
export class AssetController {
constructor(private readonly service: AssetService) {}

async cellDetialWithoutAssets(
async cellDetailWithoutAssets(
cell: ccc.Cell,
index: number,
eventType: EventType,
Expand All @@ -42,6 +43,7 @@ export class AssetController {
chain: Chain.Btc,
txHash: ccc.hexFrom(isomorphicInfo.txHash),
vout: Number(isomorphicInfo.index),
leapType: LeapType.None, // default is none
};
}
break;
Expand All @@ -50,6 +52,7 @@ export class AssetController {
chain: Chain.Doge,
txHash: ccc.hexFrom(isomorphicInfo.txHash),
vout: Number(isomorphicInfo.index),
leapType: LeapType.None, // default is none
};
}
}
Expand All @@ -70,17 +73,18 @@ export class AssetController {
index: number,
eventType: EventType,
): Promise<TxAssetCellDetail> {
const cellAsset = await this.cellDetialWithoutAssets(
const cellAsset = await this.cellDetailWithoutAssets(
cell,
index,
eventType,
);

const token = await this.service.getTokenFromCell(cell);
if (token) {
const { tokenInfo, balance } = token;
const { tokenInfo, balance, mintable } = token;
cellAsset.tokenData = {
tokenId: ccc.hexFrom(tokenInfo.hash),
mintable,
name: tokenInfo.name ?? undefined,
symbol: tokenInfo.symbol ?? undefined,
decimal: tokenInfo.decimals ?? undefined,
Expand Down Expand Up @@ -136,6 +140,7 @@ export class AssetController {
};
output: {
totalBalance: ccc.Num;
mintable: boolean;
indices: Array<number>;
};
}
Expand Down Expand Up @@ -168,6 +173,7 @@ export class AssetController {
},
output: {
totalBalance: ccc.numFrom(0),
mintable: cellAsset.tokenData.mintable,
indices: [],
},
};
Expand Down Expand Up @@ -215,6 +221,7 @@ export class AssetController {
},
output: {
totalBalance: cellAsset.tokenData.amount,
mintable: cellAsset.tokenData.mintable,
indices: [txAssetData.outputs.length],
},
};
Expand Down Expand Up @@ -275,6 +282,7 @@ export class AssetController {
const tokenId = ccc.hexFrom(firstTokenId);
txAssetData.outputs[index].tokenData = {
tokenId,
mintable: tokenGroups[tokenId].output.mintable,
name: tokenMetadata.name ?? undefined,
symbol: tokenMetadata.symbol ?? undefined,
decimal: tokenMetadata.decimals ?? undefined,
Expand All @@ -286,6 +294,32 @@ export class AssetController {
}
}

return this.filterAndChangeLeapTypes(txAssetData);
}

filterAndChangeLeapTypes(txAssetData: TxAssetCellData): TxAssetCellData {
for (const rgbppChain of [Chain.Btc, Chain.Doge]) {
const hasRgbppModeInInputs = txAssetData.inputs.some(
(input) => input.rgbppBinding?.chain === rgbppChain,
);
const hasRgbppModeInOutputs = txAssetData.outputs.some(
(output) => output.rgbppBinding?.chain === rgbppChain,
);
if (hasRgbppModeInInputs && !hasRgbppModeInOutputs) {
for (let i = 0; i < txAssetData.inputs.length; i++) {
if (txAssetData.inputs[i].rgbppBinding?.chain === rgbppChain) {
txAssetData.inputs[i].rgbppBinding!.leapType = LeapType.FromUtxo;
}
}
}
if (!hasRgbppModeInInputs && hasRgbppModeInOutputs) {
for (let i = 0; i < txAssetData.outputs.length; i++) {
if (txAssetData.outputs[i].rgbppBinding?.chain === rgbppChain) {
txAssetData.outputs[i].rgbppBinding!.leapType = LeapType.ToUtxo;
}
}
}
}
return txAssetData;
}

Expand Down Expand Up @@ -339,7 +373,7 @@ export class AssetController {
block.header.number,
);
if (
txAssetCellData.inputs.length > 0 &&
txAssetCellData.inputs.length > 0 ||
txAssetCellData.outputs.length > 0
) {
txAssetCellDataList.push(txAssetCellData);
Expand Down
19 changes: 18 additions & 1 deletion libs/asset/src/asset.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
assertConfig,
mintableScriptMode,
parseBtcAddress,
parseScriptMode,
ScriptMode,
Expand All @@ -9,14 +10,16 @@ import { ccc } from "@ckb-ccc/shell";
import { cccA } from "@ckb-ccc/shell/advanced";
import { Inject, Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import axios, { AxiosInstance } from "axios";
import { AxiosInstance } from "axios";
import { ClusterRepo, SporeRepo, UdtInfoRepo } from "./repos";

@Injectable()
export class AssetService {
private readonly client: ccc.Client;
private readonly rgbppBtcCodeHash: ccc.Hex;
private readonly rgbppBtcHashType: ccc.HashType;
private readonly rgbppBtcTimelockCodeHash: ccc.Hex;
private readonly rgbppBtcTimelockHashType: ccc.HashType;
private readonly udtTypes: {
codeHash: ccc.HexLike;
hashType: ccc.HashTypeLike;
Expand All @@ -41,6 +44,12 @@ export class AssetService {
this.rgbppBtcHashType = ccc.hashTypeFrom(
assertConfig(configService, "sync.rgbppBtcHashType"),
);
this.rgbppBtcTimelockCodeHash = ccc.hexFrom(
assertConfig(configService, "sync.rgbppBtcTimelockCodeHash"),
);
this.rgbppBtcTimelockHashType = ccc.hashTypeFrom(
assertConfig(configService, "sync.rgbppBtcTimelockHashType"),
);

const udtTypes =
configService.get<
Expand All @@ -60,6 +69,11 @@ export class AssetService {
hashType: this.rgbppBtcHashType,
mode: ScriptMode.RgbppBtc,
});
extension.push({
codeHash: this.rgbppBtcTimelockCodeHash,
hashType: this.rgbppBtcTimelockHashType,
mode: ScriptMode.RgbppBtcTimelock,
});
return await parseScriptMode(script, this.client, extension);
}

Expand Down Expand Up @@ -199,6 +213,7 @@ export class AssetService {
async getTokenFromCell(cell: ccc.Cell): Promise<
| {
tokenInfo: UdtInfo;
mintable: boolean;
balance: ccc.Num;
}
| undefined
Expand All @@ -220,8 +235,10 @@ export class AssetService {
typeArgs: cell.cellOutput.type.args,
});
const tokenAmount = ccc.udtBalanceFrom(cell.outputData);
const lockMode = await this.scriptMode(cell.cellOutput.lock);
return {
tokenInfo,
mintable: mintableScriptMode(lockMode),
balance: tokenAmount,
};
}
Expand Down
27 changes: 22 additions & 5 deletions libs/block/src/block.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import {
RpcError,
} from "@app/commons";
import { ccc } from "@ckb-ccc/shell";
import { Controller, Get, Param } from "@nestjs/common";
import { ApiOkResponse } from "@nestjs/swagger";
import { Controller, Get, Param, Query } from "@nestjs/common";
import { ApiOkResponse, ApiQuery } from "@nestjs/swagger";
import { BlockService } from "./block.service";

(BigInt.prototype as unknown as { toJSON: () => string }).toJSON = function () {
Expand All @@ -23,12 +23,21 @@ export class BlockController {
type: BlockHeader,
description: "Get tip block",
})
@ApiQuery({
name: "fromDb",
required: false,
default: true,
description:
"Determine whether to get the block from the database or from the CKB node",
})
@Get("/blocks/latest")
async getLatestBlock(): Promise<NormalizedReturn<BlockHeader>> {
async getLatestBlock(
@Query("fromDb") fromDb: boolean = true,
): Promise<NormalizedReturn<BlockHeader>> {
try {
const tipHeader = assert(
await this.service.getBlockHeader({
fromDb: false,
fromDb,
}),
RpcError.BlockNotFound,
);
Expand Down Expand Up @@ -57,15 +66,23 @@ export class BlockController {
type: BlockHeader,
description: "Get block by block number",
})
@ApiQuery({
name: "fromDb",
required: false,
default: true,
description:
"Determine whether to get the block from the database or from the CKB node",
})
@Get("/blocks/by-number/:blockNumber")
async getBlockHeaderByNumber(
@Param("blockNumber") blockNumber: number,
@Query("fromDb") fromDb: boolean = true,
): Promise<NormalizedReturn<BlockHeader>> {
try {
const blockHeader = assert(
await this.service.getBlockHeader({
blockNumber,
fromDb: false,
fromDb,
}),
RpcError.BlockNotFound,
);
Expand Down
Loading