Skip to content

Commit

Permalink
refactor: use IS_MAINNET/TESTNET_TYPE constants and related utils in …
Browse files Browse the repository at this point in the history
…code, and fix minor typos (#211)
  • Loading branch information
ShookLyngs authored Aug 26, 2024
1 parent 6ad5695 commit cb25b92
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 108 deletions.
28 changes: 9 additions & 19 deletions src/routes/rgbpp/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@ import { ZodTypeProvider } from 'fastify-type-provider-zod';
import { CKBTransaction, Cell, IsomorphicTransaction, Script, XUDTBalance } from './types';
import z from 'zod';
import { Env } from '../../env';
import {
isScriptEqual,
buildPreLockArgs,
getRgbppLockScript,
getXudtTypeScript,
isTypeAssetSupported,
} from '@rgbpp-sdk/ckb';
import { isScriptEqual, buildPreLockArgs, getXudtTypeScript, isTypeAssetSupported } from '@rgbpp-sdk/ckb';
import { groupBy, uniq } from 'lodash';
import { BI } from '@ckb-lumos/lumos';
import { UTXO } from '../../services/bitcoin/schema';
Expand All @@ -20,8 +14,9 @@ import { TransactionWithStatus } from '../../services/ckb';
import { computeScriptHash } from '@ckb-lumos/lumos/utils';
import { filterCellsByTypeScript, getTypeScript } from '../../utils/typescript';
import { unpackRgbppLockArgs } from '@rgbpp-sdk/btc/lib/ckb/molecule';
import { TestnetTypeMap } from '../../constants';
import { remove0x } from '@rgbpp-sdk/btc';
import { isRgbppLock } from '../../utils/lockscript';
import { IS_MAINNET } from '../../constants';

const addressRoutes: FastifyPluginCallback<Record<never, never>, Server, ZodTypeProvider> = (fastify, _, done) => {
const env: Env = fastify.container.resolve('env');
Expand All @@ -37,7 +32,7 @@ const addressRoutes: FastifyPluginCallback<Record<never, never>, Server, ZodType
/**
* Get UTXOs by btc address
*/
async function getUxtos(btc_address: string, no_cache?: string) {
async function getUtxos(btc_address: string, no_cache?: string) {
const utxos = await fastify.utxoSyncer.getUtxosByAddress(btc_address, no_cache === 'true');
if (env.UTXO_SYNC_DATA_CACHE_ENABLE) {
await fastify.utxoSyncer.enqueueSyncJob(btc_address);
Expand Down Expand Up @@ -65,12 +60,7 @@ const addressRoutes: FastifyPluginCallback<Record<never, never>, Server, ZodType
* Filter RgbppLock cells by cells
*/
function getRgbppLockCellsByCells(cells: Cell[]): Cell[] {
const rgbppLockScript = getRgbppLockScript(env.NETWORK === 'mainnet', TestnetTypeMap[env.NETWORK]);
return cells.filter(
(cell) =>
rgbppLockScript.codeHash === cell.cellOutput.lock.codeHash &&
rgbppLockScript.hashType === cell.cellOutput.lock.hashType,
);
return cells.filter((cell) => isRgbppLock(cell.cellOutput.lock));
}

fastify.get(
Expand Down Expand Up @@ -107,7 +97,7 @@ const addressRoutes: FastifyPluginCallback<Record<never, never>, Server, ZodType
async (request) => {
const { btc_address } = request.params;
const { no_cache } = request.query;
const utxos = await getUxtos(btc_address, no_cache);
const utxos = await getUtxos(btc_address, no_cache);
const cells = await getRgbppAssetsCells(btc_address, utxos, no_cache);
const typeScript = getTypeScript(request.query.type_script);
const assetCells = typeScript ? filterCellsByTypeScript(cells, typeScript) : cells;
Expand Down Expand Up @@ -146,7 +136,7 @@ const addressRoutes: FastifyPluginCallback<Record<never, never>, Server, ZodType
- as a hex string: '0x...' (You can pack by @ckb-lumos/codec blockchain.Script.pack({ "codeHash": "0x...", ... }))
`,
)
.default(getXudtTypeScript(env.NETWORK === 'mainnet')),
.default(getXudtTypeScript(IS_MAINNET)),
no_cache: z
.enum(['true', 'false'])
.default('false')
Expand All @@ -165,7 +155,7 @@ const addressRoutes: FastifyPluginCallback<Record<never, never>, Server, ZodType
const { no_cache } = request.query;

const typeScript = getTypeScript(request.query.type_script);
if (!typeScript || !isTypeAssetSupported(typeScript, env.NETWORK === 'mainnet')) {
if (!typeScript || !isTypeAssetSupported(typeScript, IS_MAINNET)) {
throw fastify.httpErrors.badRequest('Unsupported type asset');
}
const scripts = fastify.ckb.getScripts();
Expand All @@ -174,7 +164,7 @@ const addressRoutes: FastifyPluginCallback<Record<never, never>, Server, ZodType
}

const xudtBalances: Record<string, XUDTBalance> = {};
const utxos = await getUxtos(btc_address, no_cache);
const utxos = await getUtxos(btc_address, no_cache);

// Find confirmed RgbppLock XUDT assets
const confirmedUtxos = utxos.filter((utxo) => utxo.status.confirmed);
Expand Down
11 changes: 4 additions & 7 deletions src/routes/rgbpp/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ import z from 'zod';
import { Cell, Script, SporeTypeInfo, XUDTTypeInfo } from './types';
import { UTXO } from '../../services/bitcoin/schema';
import { getTypeScript } from '../../utils/typescript';
import { Env } from '../../env';
import { IndexerCell, isSporeTypeSupported, isUDTTypeSupported } from '@rgbpp-sdk/ckb';
import { computeScriptHash } from '@ckb-lumos/lumos/utils';
import { getSporeConfig, unpackToRawClusterData, unpackToRawSporeData } from '../../utils/spore';
import { SearchKey } from '../../services/rgbpp';
import { IS_MAINNET } from '../../constants';

const assetsRoute: FastifyPluginCallback<Record<never, never>, Server, ZodTypeProvider> = (fastify, _, done) => {
const env: Env = fastify.container.resolve('env');

fastify.get(
'/:btc_txid',
{
Expand Down Expand Up @@ -142,12 +140,11 @@ const assetsRoute: FastifyPluginCallback<Record<never, never>, Server, ZodTypePr
},
},
async (request) => {
const isMainnet = env.NETWORK === 'mainnet';
const typeScript = getTypeScript(request.query.type_script);
if (!typeScript) {
return null;
}
if (isUDTTypeSupported(typeScript, isMainnet)) {
if (isUDTTypeSupported(typeScript, IS_MAINNET)) {
const infoCell = await fastify.ckb.getInfoCellData(typeScript);
const typeHash = computeScriptHash(typeScript);
if (!infoCell) {
Expand All @@ -160,7 +157,7 @@ const assetsRoute: FastifyPluginCallback<Record<never, never>, Server, ZodTypePr
...infoCell,
};
}
if (isSporeTypeSupported(typeScript, isMainnet)) {
if (isSporeTypeSupported(typeScript, IS_MAINNET)) {
const searchKey: SearchKey = {
script: typeScript,
scriptType: 'type',
Expand All @@ -173,7 +170,7 @@ const assetsRoute: FastifyPluginCallback<Record<never, never>, Server, ZodTypePr
contentType: sporeData.contentType,
};
if (sporeData.clusterId) {
const sporeConfig = getSporeConfig(isMainnet);
const sporeConfig = getSporeConfig(IS_MAINNET);
const batchRequest = fastify.ckb.rpc.createBatchRequest(
sporeConfig.scripts.Cluster.versions.map((version) => {
const clusterScript = {
Expand Down
4 changes: 2 additions & 2 deletions src/services/bitcoin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Cradle } from '../../container';
import { IBitcoinBroadcastBackuper, IBitcoinDataProvider } from './interface';
import { MempoolClient } from './mempool';
import { ElectrsClient } from './electrs';
import { NetworkType } from '../../constants';
import { IS_MAINNET, NetworkType } from '../../constants';
import { ChainInfo } from './schema';

// https://github.com/mempool/electrs/blob/d4f788fc3d7a2b4eca4c5629270e46baba7d0f19/src/errors.rs#L6
Expand Down Expand Up @@ -169,7 +169,7 @@ export default class BitcoinClient implements IBitcoinClient {

const { difficulty, mediantime } = tip;
return {
chain: this.cradle.env.NETWORK === 'mainnet' ? 'main' : 'test',
chain: IS_MAINNET ? 'main' : 'test',
blocks: tip.height,
bestblockhash: hash,
difficulty,
Expand Down
15 changes: 7 additions & 8 deletions src/services/ckb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import DataCache from './base/data-cache';
import { scriptToHash } from '@nervosnetwork/ckb-sdk-utils';
import { Cell } from '../routes/rgbpp/types';
import { uniq } from 'lodash';
import { IS_MAINNET } from '../constants';

export type TransactionWithStatus = Awaited<ReturnType<CKBRPC['getTransaction']>>;

Expand Down Expand Up @@ -164,11 +165,10 @@ export default class CKBClient {
* Get the ckb script configs
*/
public getScripts() {
const isMainnet = this.cradle.env.NETWORK === 'mainnet';
const xudtTypeScript = getXudtTypeScript(isMainnet);
const sporeTypeScript = getSporeTypeScript(isMainnet);
const uniqueCellTypeScript = getUniqueTypeScript(isMainnet);
const inscriptionTypeScript = getInscriptionInfoTypeScript(isMainnet);
const xudtTypeScript = getXudtTypeScript(IS_MAINNET);
const sporeTypeScript = getSporeTypeScript(IS_MAINNET);
const uniqueCellTypeScript = getUniqueTypeScript(IS_MAINNET);
const inscriptionTypeScript = getInscriptionInfoTypeScript(IS_MAINNET);
return {
XUDT: xudtTypeScript,
SPORE: sporeTypeScript,
Expand Down Expand Up @@ -297,12 +297,11 @@ export default class CKBClient {
return cachedData as ReturnType<typeof decodeInfoCellData>;
}

const isMainnet = this.cradle.env.NETWORK === 'mainnet';
const txs = await this.getAllInfoCellTxs();
for (const tx of txs) {
// check if the unique cell is the info cell of the xudt type
const uniqueCellIndex = tx.transaction.outputs.findIndex((cell) => {
return cell.type && isUniqueCellTypeScript(cell.type, isMainnet);
return cell.type && isUniqueCellTypeScript(cell.type, IS_MAINNET);
});
if (uniqueCellIndex !== -1) {
const infoCellData = this.getUniqueCellData(tx, uniqueCellIndex, script);
Expand All @@ -313,7 +312,7 @@ export default class CKBClient {
}
// check if the inscription cell is the info cell of the xudt type
const inscriptionCellIndex = tx.transaction.outputs.findIndex((cell) => {
return cell.type && isInscriptionInfoTypeScript(cell.type, isMainnet);
return cell.type && isInscriptionInfoTypeScript(cell.type, IS_MAINNET);
});
if (inscriptionCellIndex !== -1) {
const infoCellData = this.getInscriptionInfoCellData(tx, inscriptionCellIndex, script);
Expand Down
9 changes: 4 additions & 5 deletions src/services/paymaster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AppendPaymasterCellAndSignTxParams, IndexerCell, appendPaymasterCellAnd
import { hd, config, BI } from '@ckb-lumos/lumos';
import * as Sentry from '@sentry/node';
import { Transaction } from '../routes/bitcoin/types';
import { IS_MAINNET } from '../constants';

interface IPaymaster {
getNextCell(token: string): Promise<IndexerCell | null>;
Expand Down Expand Up @@ -60,8 +61,7 @@ export default class Paymaster implements IPaymaster {

private get lockScript() {
const args = hd.key.privateKeyToBlake160(this.ckbPrivateKey);
const scripts =
this.cradle.env.NETWORK === 'mainnet' ? config.predefined.LINA.SCRIPTS : config.predefined.AGGRON4.SCRIPTS;
const scripts = IS_MAINNET ? config.MAINNET.SCRIPTS : config.TESTNET.SCRIPTS;
const template = scripts['SECP256K1_BLAKE160']!;
const lockScript = {
codeHash: template.CODE_HASH,
Expand Down Expand Up @@ -123,8 +123,7 @@ export default class Paymaster implements IPaymaster {
* The paymaster CKB address to pay the time cells spent tx fee
*/
public get ckbAddress() {
const isMainnet = this.cradle.env.NETWORK === 'mainnet';
const lumosConfig = isMainnet ? config.predefined.LINA : config.predefined.AGGRON4;
const lumosConfig = IS_MAINNET ? config.MAINNET : config.TESTNET;
const args = hd.key.privateKeyToBlake160(this.ckbPrivateKey);
const template = lumosConfig.SCRIPTS['SECP256K1_BLAKE160'];
const lockScript = {
Expand Down Expand Up @@ -296,7 +295,7 @@ export default class Paymaster implements IPaymaster {
sumInputsCapacity,
paymasterCell,
secp256k1PrivateKey: this.ckbPrivateKey,
isMainnet: this.cradle.env.NETWORK === 'mainnet',
isMainnet: IS_MAINNET,
});
this.cradle.logger.info(`[Paymaster] Signed transaction: ${JSON.stringify(signedTx)}`);
return signedTx;
Expand Down
2 changes: 1 addition & 1 deletion src/services/rgbpp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class RgbppCollectorError extends Error {
* will be recollected when the utxos are updated or new collect job is enqueued.
*/
export default class RgbppCollector extends BaseQueueWorker<IRgbppCollectRequest, IRgbppCollectJobReturn> {
private readonly limit: pLimit.Limit;
private limit: pLimit.Limit;
private dataCache: DataCache<IRgbppCollectJobReturn>;

constructor(private cradle: Cradle) {
Expand Down
61 changes: 14 additions & 47 deletions src/services/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import {
RGBPP_TX_ID_PLACEHOLDER,
appendCkbTxWitnesses,
generateSporeTransferCoBuild,
getBtcTimeLockScript,
getRgbppLockScript,
getSecp256k1CellDep,
getSporeTypeDep,
isClusterSporeTypeSupported,
Expand Down Expand Up @@ -37,8 +35,9 @@ import { BitcoinClientAPIError } from './bitcoin';
import { HttpStatusCode } from 'axios';
import BaseQueueWorker from './base/queue-worker';
import { Env } from '../env';
import { TestnetTypeMap } from '../constants';
import { getCommitmentFromBtcTx } from '../utils/commitment';
import { isBtcTimeLock, isRgbppLock } from '../utils/lockscript';
import { IS_MAINNET } from '../constants';

export interface ITransactionRequest {
txid: string;
Expand Down Expand Up @@ -123,30 +122,6 @@ export default class TransactionProcessor
};
}

private get isMainnet() {
return this.cradle.env.NETWORK === 'mainnet';
}

private get testnetType() {
return TestnetTypeMap[this.cradle.env.NETWORK];
}

private get rgbppLockScript() {
return getRgbppLockScript(this.isMainnet, this.testnetType);
}

private get btcTimeLockScript() {
return getBtcTimeLockScript(this.isMainnet, this.testnetType);
}

private isRgbppLock(lock: CKBComponents.Script) {
return lock.codeHash === this.rgbppLockScript.codeHash && lock.hashType === this.rgbppLockScript.hashType;
}

private isBtcTimeLock(lock: CKBComponents.Script) {
return lock.codeHash === this.btcTimeLockScript.codeHash && lock.hashType === this.btcTimeLockScript.hashType;
}

/**
* Clear the btcTxId in the RGBPP_LOCK/BTC_TIME_LOCK script to avoid the mismatch between the CKB and BTC transactions
* @param ckbRawTx - CKB Raw Transaction
Expand All @@ -155,7 +130,7 @@ export default class TransactionProcessor
private async resetOutputLockScript(ckbRawTx: CKBRawTransaction, txid: string) {
const outputs = ckbRawTx.outputs.map((output) => {
const { lock } = output;
if (this.isRgbppLock(lock)) {
if (isRgbppLock(lock)) {
const unpack = RGBPPLock.unpack(lock.args);
// https://github.com/ckb-cell/rgbpp-sdk/tree/main/examples/rgbpp#what-you-must-know-about-btc-transaction-id
const btcTxid = bytes.hexify(bytes.bytify(unpack.btcTxid).reverse());
Expand All @@ -164,18 +139,18 @@ export default class TransactionProcessor
}
return {
...output,
lock: genRgbppLockScript(buildPreLockArgs(unpack.outIndex), this.isMainnet),
lock: genRgbppLockScript(buildPreLockArgs(unpack.outIndex), IS_MAINNET),
};
}
if (this.isBtcTimeLock(lock)) {
if (isBtcTimeLock(lock)) {
const btcTxid = btcTxIdFromBtcTimeLockArgs(lock.args);
if (remove0x(btcTxid) !== txid) {
return output;
}
const toLock = lockScriptFromBtcTimeLockArgs(lock.args);
return {
...output,
lock: genBtcTimeLockScript(toLock, this.isMainnet),
lock: genBtcTimeLockScript(toLock, IS_MAINNET),
};
}
return output;
Expand Down Expand Up @@ -253,31 +228,23 @@ export default class TransactionProcessor
private getCkbRawTxWithRealBtcTxid(ckbVirtualResult: CKBVirtualResult, txid: string) {
let ckbRawTx = ckbVirtualResult.ckbRawTx;
const needUpdateCkbTx = ckbRawTx.outputs.some((output) => {
if (this.isRgbppLock(output.lock)) {
if (isRgbppLock(output.lock)) {
const { btcTxid } = RGBPPLock.unpack(output.lock.args);
const txid = remove0x(btcTxid);
this.cradle.logger.debug(`[TransactionProcessor] RGBPP_LOCK args txid: ${btcTxid}`);
return (
output.lock.codeHash === this.rgbppLockScript.codeHash &&
output.lock.hashType === this.rgbppLockScript.hashType &&
txid === RGBPP_TX_ID_PLACEHOLDER
);
return txid === RGBPP_TX_ID_PLACEHOLDER;
}
if (this.isBtcTimeLock(output.lock)) {
if (isBtcTimeLock(output.lock)) {
const btcTxid = btcTxIdFromBtcTimeLockArgs(output.lock.args);
const txid = remove0x(btcTxid);
this.cradle.logger.debug(`[TransactionProcessor] BTC_TIME_LOCK args txid: ${txid}`);
return (
output.lock.codeHash === this.btcTimeLockScript.codeHash &&
output.lock.hashType === this.btcTimeLockScript.hashType &&
txid === RGBPP_TX_ID_PLACEHOLDER
);
return txid === RGBPP_TX_ID_PLACEHOLDER;
}
return false;
});
if (needUpdateCkbTx) {
this.cradle.logger.info(`[TransactionProcessor] Update CKB Raw Transaction with real BTC txid: ${txid}`);
ckbRawTx = updateCkbTxWithRealBtcTxId({ ckbRawTx, btcTxId: txid, isMainnet: this.isMainnet });
ckbRawTx = updateCkbTxWithRealBtcTxId({ ckbRawTx, btcTxId: txid, isMainnet: IS_MAINNET });
}
return ckbRawTx;
}
Expand Down Expand Up @@ -331,7 +298,7 @@ export default class TransactionProcessor
* if the transaction has spore type dep, we need to append the spore cobuild witness to the transaction
*/
private hasSporeTypeDep(tx: CKBRawTransaction) {
const sporeTypeDep = getSporeTypeDep(this.isMainnet);
const sporeTypeDep = getSporeTypeDep(IS_MAINNET);
const hasSporeTypeDep = tx.cellDeps.some((cellDep) => {
return serializeCellDep(cellDep) === serializeCellDep(sporeTypeDep);
});
Expand All @@ -351,7 +318,7 @@ export default class TransactionProcessor
);
const sporeLiveCells = inputs
.filter(({ status, cell }) => {
return status === 'live' && cell?.output.type && isClusterSporeTypeSupported(cell?.output.type, this.isMainnet);
return status === 'live' && cell?.output.type && isClusterSporeTypeSupported(cell?.output.type, IS_MAINNET);
})
.map((liveCell) => liveCell.cell!);
if (sporeLiveCells.length > 0) {
Expand Down Expand Up @@ -413,7 +380,7 @@ export default class TransactionProcessor
const { txid, ckbVirtualResult } = job.data;
const { ckbRawTx } = ckbVirtualResult;
// append the secp256k1 cell dep to the transaction
ckbRawTx.cellDeps.push(getSecp256k1CellDep(this.isMainnet));
ckbRawTx.cellDeps.push(getSecp256k1CellDep(IS_MAINNET));
// update the job data to append the paymaster cell next time
job.updateData({
txid,
Expand Down
Loading

0 comments on commit cb25b92

Please sign in to comment.