diff --git a/src/services/ckb.ts b/src/services/ckb.ts index 636978bd..20f7b5ab 100644 --- a/src/services/ckb.ts +++ b/src/services/ckb.ts @@ -9,6 +9,7 @@ import { import { Cradle } from '../container'; import { BI, Indexer, RPC, Script } from '@ckb-lumos/lumos'; import { CKBRPC } from '@ckb-lumos/rpc'; +import { UngroupedIndexerTransaction } from '@ckb-lumos/ckb-indexer/lib/type'; import { z } from 'zod'; import * as Sentry from '@sentry/node'; import { @@ -154,7 +155,7 @@ export default class CKBClient { this.indexer = new Indexer(cradle.env.CKB_RPC_URL); this.dataCache = new DataCache(cradle.redis, { prefix: 'ckb-info-cell-txs', - expire: 60 * 1000, + expire: 10 * 60 * 1000, }); } @@ -244,7 +245,9 @@ export default class CKBClient { script: searchScript, scriptType: 'type', }, + // XXX: The returned result is not asc-ordered, maybe it is a bug in ckb-indexer 'asc', + // TODO: There may be a maximum request limit. '0xffff', // 0xffff basically means no limit ); }); @@ -255,8 +258,23 @@ export default class CKBClient { batchRequest = this.rpc.createBatchRequest(); infoCellTxs.forEach((txs) => { txs.objects - .filter(({ ioType }) => ioType === 'output') - .forEach((tx) => { + .filter(({ ioType }: UngroupedIndexerTransaction) => ioType === 'output') + // make sure `infoCellTxs` are asc-ordered + .sort((txA: UngroupedIndexerTransaction, txB: UngroupedIndexerTransaction) => { + const aBlockNumber = BI.from(txA.blockNumber).toNumber(); + const bBlockNumber = BI.from(txB.blockNumber).toNumber(); + if (aBlockNumber < bBlockNumber) return -1; + else if (aBlockNumber > bBlockNumber) return 1; + else if (aBlockNumber === bBlockNumber) { + const aTxIndex = BI.from(txA.txIndex).toNumber(); + const bTxIndex = BI.from(txB.txIndex).toNumber(); + if (aTxIndex < bTxIndex) return -1; + else if (aTxIndex > bTxIndex) return 1; + } + // unreachable: aBlockNumber === bBlockNumber && aTxIndex === bTxIndex + return 0; + }) + .forEach((tx: UngroupedIndexerTransaction) => { batchRequest.add('getTransaction', tx.txHash); }); }); diff --git a/test/routes/rgbpp/__snapshots__/address.test.ts.snap b/test/routes/rgbpp/__snapshots__/address.test.ts.snap index 10666d99..ba933655 100644 --- a/test/routes/rgbpp/__snapshots__/address.test.ts.snap +++ b/test/routes/rgbpp/__snapshots__/address.test.ts.snap @@ -6888,7 +6888,7 @@ exports[`/:btc_address/balance - with pending_amount 1`] = ` "decimal": 8, "name": "Unique BBQ", "pending_amount": "0x5f5e100", - "symbol": "UBBQ", + "symbol": "", "total_amount": "0xbebc200", "type_hash": "0x78e21efcf107e7886eadeadecd1a01cfb88f1e5617f4438685db55b3a540d202", "type_script": { @@ -6952,7 +6952,7 @@ exports[`/:btc_address/balance - without pending_amount 1`] = ` "decimal": 8, "name": "Unique BBQ", "pending_amount": "0x0", - "symbol": "UBBQ", + "symbol": "", "total_amount": "0x5f5e100", "type_hash": "0x78e21efcf107e7886eadeadecd1a01cfb88f1e5617f4438685db55b3a540d202", "type_script": { diff --git a/test/services/__snapshots__/rgbpp.test.ts.snap b/test/services/__snapshots__/rgbpp.test.ts.snap index b8ab9f97..165efeb9 100644 --- a/test/services/__snapshots__/rgbpp.test.ts.snap +++ b/test/services/__snapshots__/rgbpp.test.ts.snap @@ -30,7 +30,7 @@ exports[`RgbppCollector > getRgbppBalanceByCells: should return the rgbpp balanc "amount": "0x5f5e100", "decimal": 8, "name": "Unique BBQ", - "symbol": "UBBQ", + "symbol": "", "type_hash": "0x78e21efcf107e7886eadeadecd1a01cfb88f1e5617f4438685db55b3a540d202", "type_script": { "args": "0x30d3fbec9ceba691770d57c6d06bdb98cf0f82bef0ca6e87687a118d6ce1e7b7", diff --git a/test/services/ckb.test.ts b/test/services/ckb.test.ts index b228aef0..44df7a81 100644 --- a/test/services/ckb.test.ts +++ b/test/services/ckb.test.ts @@ -23,6 +23,13 @@ describe('CKBClient', () => { hashType: 'type', }; + // {"name":"tUTXO","symbol":"tUTXO","decimal":8} + const tUtxoTypeScript: Script = { + codeHash: '0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb', + args: '0x92b419a8d8e03c683a47b960f707f2b866f6114b70327b6628762719b243c5ca', + hashType: 'type', + }; + // CKBI const inscriptionTypeScript: Script = { codeHash: '0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb', @@ -51,6 +58,17 @@ describe('CKBClient', () => { }); }); + test('getInfoCellData: should return the info cell data', async () => { + // related tx: + // https://pudge.explorer.nervos.org/transaction/0x38f88df8b0ce98ec0dee86249c8640b06439105a2500b4ca0638a1a229a52a48 + const infoCellData = await ckb.getInfoCellData(tUtxoTypeScript); + expect(infoCellData).toEqual({ + decimal: 8, + name: 'tUTXO', + symbol: 'tUTXO', + }); + }); + test('getInscriptionCellData: should return the inscription cell data (before rebase)', async () => { // CKBI (Inscription cell transaction) const tx = await ckb.rpc.getTransaction('0xd1195131f13eca1b4ec1c4b58f7a16f27a239b1064270d703d0c3eb5b6c1b332');