diff --git a/.changeset/odd-cheetahs-shake.md b/.changeset/odd-cheetahs-shake.md new file mode 100644 index 00000000..15834e16 --- /dev/null +++ b/.changeset/odd-cheetahs-shake.md @@ -0,0 +1,5 @@ +--- +"@rgbpp-sdk/service": minor +--- + +Add support of /rgbpp/v1/address/{btc_address}/activity API for querying RGBPP asset activities by an BTC address diff --git a/packages/service/README.md b/packages/service/README.md index d4e48475..19eba446 100644 --- a/packages/service/README.md +++ b/packages/service/README.md @@ -161,6 +161,7 @@ interface BaseApiRequestOptions extends RequestInit { params?: Record; method?: 'GET' | 'POST'; requireToken?: boolean; + allow404?: boolean; } interface BtcAssetsApiToken { @@ -188,7 +189,6 @@ interface BtcApis { interface BtcApiBlockchainInfo { chain: string; blocks: number; - headers: number; bestblockhash: number; difficulty: number; mediantime: number; @@ -222,11 +222,18 @@ interface BtcApiBlockTransactionIds { txids: string[]; } +interface BtcApiRecommendedFeeRates { + fastestFee: number; + halfHourFee: number; + hourFee: number; + economyFee: number; + minimumFee: number; +} + interface BtcApiBalanceParams { min_satoshi?: number; no_cache?: boolean; } - interface BtcApiBalance { address: string; // @deprecated Use available_satoshi instead @@ -245,7 +252,6 @@ interface BtcApiUtxoParams { min_satoshi?: number; no_cache?: boolean; } - interface BtcApiUtxo { txid: string; vout: number; @@ -262,7 +268,7 @@ interface BtcApiSentTransaction { txid: string; } -export interface BtcApiTransactionParams { +interface BtcApiTransactionParams { after_txid?: string; } @@ -312,9 +318,11 @@ interface RgbppApis { getRgbppPaymasterInfo(): Promise; getRgbppTransactionHash(btcTxId: string): Promise; getRgbppTransactionState(btcTxId: string): Promise; - getRgbppAssetsByBtcTxId(btcTxId: string): Promise; - getRgbppAssetsByBtcUtxo(btcTxId: string, vout: number): Promise; - getRgbppAssetsByBtcAddress(btcAddress: string, params?: RgbppApiAssetsByAddressParams): Promise; + getRgbppAssetsByBtcTxId(btcTxId: string): Promise; + getRgbppAssetsByBtcUtxo(btcTxId: string, vout: number): Promise; + getRgbppAssetsByBtcAddress(btcAddress: string, params?: RgbppApiAssetsByAddressParams): Promise; + getRgbppBalanceByBtcAddress(btcAddress: string, params?: RgbppApiBalanceByAddressParams): Promise; + getRgbppActivityByBtcAddress(btcAddress: string, params?: RgbppApiActivityByAddressParams): Promise; getRgbppSpvProof(btcTxId: string, confirmations: number): Promise; sendRgbppCkbTransaction(payload: RgbppApiSendCkbTransactionPayload): Promise; retryRgbppCkbTransaction(payload: RgbppApiRetryCkbTransactionPayload): Promise; @@ -331,8 +339,27 @@ interface RgbppApiCkbTransactionHash { txhash: string; } +interface RgbppApiTransactionStateParams { + with_data?: boolean; +} + interface RgbppApiTransactionState { state: RgbppTransactionState; + attempts: number; + failedReason?: string; + data?: { + txid: string; + ckbVirtualResult: { + ckbRawTx: CKBComponents.RawTransaction; + needPaymasterCell: boolean; + sumInputsCapacity: string; + commitment: string; + }; + }; +} + +interface RgbppCell extends Cell { + typeHash?: Hash; } interface RgbppApiAssetsByAddressParams { @@ -340,6 +367,48 @@ interface RgbppApiAssetsByAddressParams { no_cache?: boolean; } +interface RgbppApiBalanceByAddressParams { + type_script?: string; + no_cache?: boolean; +} +interface RgbppApiBalance { + address: string; + xudt: RgbppApiXudtBalance[]; +} +interface RgbppApiXudtBalance { + name: string; + decimal: number; + symbol: string; + total_amount: string; + available_amount: string; + pending_amount: string; + type_hash: string; + type_script: Script; +} + +interface RgbppApiActivityByAddressParams { + rgbpp_only?: boolean; + type_script?: string; + after_btc_txid?: string; +} +interface RgbppApiActivity { + address: string; + cursor: string; + txs: { + btcTx: BtcApiTransaction; + isRgbpp: boolean; + isomorphicTx?: { + ckbVirtualTx?: CKBComponents.RawTransaction; + ckbTx?: CKBComponents.Transaction; + inputs?: CKBComponents.CellOutput[]; + outputs?: CKBComponents.CellOutput[]; + status: { + confirmed: boolean; + }; + }; + }[]; +} + interface RgbppApiSpvProof { proof: string; spv_client: { @@ -350,12 +419,14 @@ interface RgbppApiSpvProof { interface RgbppApiSendCkbTransactionPayload { btc_txid: string; - ckb_virtual_result: { - ckbRawTx: CKBComponents.RawTransaction; - needPaymasterCell: boolean; - sumInputsCapacity: string; - commitment: string; - }; + // Support ckbVirtualTxResult and it's JSON string as request parameter + ckb_virtual_result: RgbppApiSendCkbVirtualResult | string; +} +interface RgbppApiSendCkbVirtualResult { + ckbRawTx: CKBComponents.RawTransaction; + needPaymasterCell: boolean; + sumInputsCapacity: string; + commitment: string; } interface RgbppApiRetryCkbTransactionPayload { @@ -366,4 +437,5 @@ interface RgbppApiTransactionRetry { success: boolean; state: RgbppTransactionState; } + ``` diff --git a/packages/service/src/service/service.ts b/packages/service/src/service/service.ts index e971e335..4f42485d 100644 --- a/packages/service/src/service/service.ts +++ b/packages/service/src/service/service.ts @@ -14,6 +14,8 @@ import { BtcApiUtxoParams, BtcApiTransactionParams, BtcApiRecommendedFeeRates, + RgbppApiActivityByAddressParams, + RgbppApiActivity, } from '../types'; import { RgbppApis, @@ -136,6 +138,12 @@ export class BtcAssetsApi extends BtcAssetsApiBase implements BtcApis, RgbppApis }); } + getRgbppActivityByBtcAddress(btcAddress: string, params?: RgbppApiActivityByAddressParams) { + return this.request(`/rgbpp/v1/address/${btcAddress}/activity`, { + params, + }); + } + getRgbppSpvProof(btcTxId: string, confirmations: number) { return this.request('/rgbpp/v1/btc-spv/proof', { params: { diff --git a/packages/service/src/types/btc.ts b/packages/service/src/types/btc.ts index 3bc9ee00..e188bf6d 100644 --- a/packages/service/src/types/btc.ts +++ b/packages/service/src/types/btc.ts @@ -15,7 +15,7 @@ export interface BtcApis { export interface BtcApiBlockchainInfo { chain: string; blocks: number; - bestblockhash: number; + bestblockhash: string; difficulty: number; mediantime: number; } diff --git a/packages/service/src/types/rgbpp.ts b/packages/service/src/types/rgbpp.ts index a5c8c7c4..07b678c9 100644 --- a/packages/service/src/types/rgbpp.ts +++ b/packages/service/src/types/rgbpp.ts @@ -1,4 +1,5 @@ import { Cell, Hash, Script } from '@ckb-lumos/base'; +import { BtcApiTransaction } from './btc'; export interface RgbppApis { getRgbppPaymasterInfo(): Promise; @@ -8,6 +9,7 @@ export interface RgbppApis { getRgbppAssetsByBtcUtxo(btcTxId: string, vout: number): Promise; getRgbppAssetsByBtcAddress(btcAddress: string, params?: RgbppApiAssetsByAddressParams): Promise; getRgbppBalanceByBtcAddress(btcAddress: string, params?: RgbppApiBalanceByAddressParams): Promise; + getRgbppActivityByBtcAddress(btcAddress: string, params?: RgbppApiActivityByAddressParams): Promise; getRgbppSpvProof(btcTxId: string, confirmations: number): Promise; sendRgbppCkbTransaction(payload: RgbppApiSendCkbTransactionPayload): Promise; retryRgbppCkbTransaction(payload: RgbppApiRetryCkbTransactionPayload): Promise; @@ -71,6 +73,29 @@ export interface RgbppApiXudtBalance { type_script: Script; } +export interface RgbppApiActivityByAddressParams { + rgbpp_only?: boolean; + type_script?: string; + after_btc_txid?: string; +} +export interface RgbppApiActivity { + address: string; + cursor: string; + txs: { + btcTx: BtcApiTransaction; + isRgbpp: boolean; + isomorphicTx?: { + ckbVirtualTx?: CKBComponents.RawTransaction; + ckbTx?: CKBComponents.Transaction; + inputs?: CKBComponents.CellOutput[]; + outputs?: CKBComponents.CellOutput[]; + status: { + confirmed: boolean; + }; + }; + }[]; +} + export interface RgbppApiSpvProof { proof: string; spv_client: { @@ -81,15 +106,14 @@ export interface RgbppApiSpvProof { export interface RgbppApiSendCkbTransactionPayload { btc_txid: string; - // Support ckbVirtaulTxResult and it's JSON string as request parameter - ckb_virtual_result: - | { - ckbRawTx: CKBComponents.RawTransaction; - needPaymasterCell: boolean; - sumInputsCapacity: string; - commitment: string; - } - | string; + // Support ckbVirtualTxResult and it's JSON string as request parameter + ckb_virtual_result: RgbppApiSendCkbVirtualResult | string; +} +export interface RgbppApiSendCkbVirtualResult { + ckbRawTx: CKBComponents.RawTransaction; + needPaymasterCell: boolean; + sumInputsCapacity: string; + commitment: string; } export interface RgbppApiRetryCkbTransactionPayload { diff --git a/packages/service/tests/Service.test.ts b/packages/service/tests/Service.test.ts index 33486b6e..672937ce 100644 --- a/packages/service/tests/Service.test.ts +++ b/packages/service/tests/Service.test.ts @@ -146,7 +146,6 @@ describe( }); it('getBtcTransactions()', async () => { const res = await service.getBtcTransactions(btcAddress); - console.log(res.map((tx) => tx.txid)); expect(Array.isArray(res)).toBe(true); expect(res.length).toBeGreaterThan(0); res.forEach((transaction) => { @@ -277,6 +276,30 @@ describe( expectScript(xudt.type_script); } }); + it('getRgbppActivityByBtcAddress()', async () => { + const res = await service.getRgbppActivityByBtcAddress(rgbppBtcAddress, { + type_script: rgbppCellType, + }); + expect(res).toBeDefined(); + expect(res.address).toBeTypeOf('string'); + expect(res.cursor).toBeTypeOf('string'); + expect(res.txs).toHaveProperty('length'); + if (res.txs.length > 0) { + for (const tx of res.txs) { + expect(tx.btcTx).toBeDefined(); + expect(tx.isRgbpp).toBeTypeOf('boolean'); + if (tx.isRgbpp) { + expect(tx.isomorphicTx).toBeDefined(); + expect(tx.isomorphicTx.status.confirmed).toBeTypeOf('boolean'); + const hasTxOrVirtualTx = tx.isomorphicTx.ckbVirtualTx ?? tx.isomorphicTx.ckbTx; + if (hasTxOrVirtualTx) { + expect(tx.isomorphicTx.inputs).toBeDefined(); + expect(tx.isomorphicTx.outputs).toBeDefined(); + } + } + } + } + }); it('getRgbppSpvProof()', async () => { const res = await service.getRgbppSpvProof(rgbppBtcTxId, 6); expect(res).toBeDefined();