diff --git a/.changeset/tender-hornets-agree.md b/.changeset/tender-hornets-agree.md new file mode 100644 index 00000000..72361ace --- /dev/null +++ b/.changeset/tender-hornets-agree.md @@ -0,0 +1,11 @@ +--- +"@rgbpp-sdk/service": minor +"@rgbpp-sdk/btc": minor +--- + +Adapt btc-assets-api#154, adding new props and return values to the /balance and /unspent APIs + +- Add `available_satoshi` and `total_satoshi` to the BtcAssetsApi.getBtcBalance() API +- Add `only_non_rgbpp_utxos` to the props of the BtcAssetsApi.getBtcUtxos() API +- Remove `service.getRgbppAssetsByBtcUtxo()` lines from the DataCollector.collectSatoshi() +- Remove `hasRgbppAssets` related variables/function from the DataCache diff --git a/packages/btc/src/query/cache.ts b/packages/btc/src/query/cache.ts index 046b2c8e..3ac3e0e0 100644 --- a/packages/btc/src/query/cache.ts +++ b/packages/btc/src/query/cache.ts @@ -2,11 +2,9 @@ import { Utxo } from '../transaction/utxo'; export class DataCache { private utxos: Map; // Map - private hasRgbppAssets: Map; // Map<`{txid}:{vout}`, HasAssets> constructor() { this.utxos = new Map(); - this.hasRgbppAssets = new Map(); } setUtxos(key: string, utxos: Utxo[]) { @@ -32,31 +30,4 @@ export class DataCache { return utxos; } - - setHasRgbppAssets(key: string, hasAssets: boolean) { - this.hasRgbppAssets.set(key, hasAssets); - } - getHasRgbppAssets(key: string): boolean | undefined { - return this.hasRgbppAssets.get(key); - } - cleanHasRgbppAssets(key: string) { - if (this.hasRgbppAssets.has(key)) { - this.hasRgbppAssets.delete(key); - } - } - async optionalCacheHasRgbppAssets(props: { - key?: string; - getter: () => Promise | boolean; - }): Promise { - if (props.key && this.hasRgbppAssets.has(props.key)) { - return this.getHasRgbppAssets(props.key) as boolean; - } - - const hasRgbppAssets = await props.getter(); - if (props.key) { - this.setHasRgbppAssets(props.key, hasRgbppAssets); - } - - return hasRgbppAssets; - } } diff --git a/packages/btc/src/query/source.ts b/packages/btc/src/query/source.ts index d7dcff0a..e368b29b 100644 --- a/packages/btc/src/query/source.ts +++ b/packages/btc/src/query/source.ts @@ -116,32 +116,24 @@ export class DataSource { satoshi: number; exceedSatoshi: number; }> { - const { - address, - targetAmount, - minUtxoSatoshi, - onlyConfirmedUtxos, - onlyNonRgbppUtxos, - noAssetsApiCache, - internalCacheKey, - allowInsufficient = false, - excludeUtxos = [], - } = props; + const allowInsufficient = props.allowInsufficient ?? false; + const excludeUtxos = props.excludeUtxos ?? []; const utxos = await this.cache.optionalCacheUtxos({ - key: internalCacheKey, + key: props.internalCacheKey, getter: () => - this.getUtxos(address, { - only_confirmed: onlyConfirmedUtxos, - min_satoshi: minUtxoSatoshi, - no_cache: noAssetsApiCache, + this.getUtxos(props.address, { + only_non_rgbpp_utxos: props.onlyNonRgbppUtxos, + only_confirmed: props.onlyConfirmedUtxos, + min_satoshi: props.minUtxoSatoshi, + no_cache: props.noAssetsApiCache, }), }); const collected = []; let collectedAmount = 0; for (const utxo of utxos) { - if (collectedAmount >= targetAmount) { + if (collectedAmount >= props.targetAmount) { break; } if (excludeUtxos.length > 0) { @@ -152,33 +144,21 @@ export class DataSource { continue; } } - if (onlyNonRgbppUtxos) { - const hasRgbppAssets = await this.cache.optionalCacheHasRgbppAssets({ - key: `${utxo.txid}:${utxo.vout}`, - getter: async () => { - const ckbRgbppAssets = await this.service.getRgbppAssetsByBtcUtxo(utxo.txid, utxo.vout); - return Array.isArray(ckbRgbppAssets) && ckbRgbppAssets.length > 0; - }, - }); - if (hasRgbppAssets) { - continue; - } - } collected.push(utxo); collectedAmount += utxo.value; } - if (!allowInsufficient && collectedAmount < targetAmount) { + if (!allowInsufficient && collectedAmount < props.targetAmount) { throw TxBuildError.withComment( ErrorCodes.INSUFFICIENT_UTXO, - `expected: ${targetAmount}, actual: ${collectedAmount}`, + `expected: ${props.targetAmount}, actual: ${collectedAmount}`, ); } return { utxos: collected, satoshi: collectedAmount, - exceedSatoshi: collectedAmount - targetAmount, + exceedSatoshi: collectedAmount - props.targetAmount, }; } diff --git a/packages/btc/tests/DataSource.test.ts b/packages/btc/tests/DataSource.test.ts index fb001668..e2c9f90a 100644 --- a/packages/btc/tests/DataSource.test.ts +++ b/packages/btc/tests/DataSource.test.ts @@ -19,35 +19,39 @@ describe('DataSource', { retry: 3 }, () => { source.getUtxo('70b250e2a3cc7a33b47f7a4e94e41e1ee2501ce73b393d824db1dd4c872c5348', 0), ).rejects.toHaveProperty('code', ErrorCodes.UNSPENDABLE_OUTPUT); }); - it('Get UTXO[] via collectSatoshi()', async () => { - const address = 'tb1qnxdtut9vpycmpnjpp77rmx33mfxsr86dl3ce6a'; - const nonRgbppSatoshi = 2546; - const totalSatoshi = 3092; - const nonRgbppUtxo = 2; + describe('collectSatoshi()', () => { + const address = 'tb1qn5kgn70tpwsw4nuxrch8l7qa9nqn4fahxgzjg6'; + const totalSatoshi = 546 + 2000 + 1500; + const nonRgbppSatoshi = 1500; + const nonRgbppUtxo = 1; const totalUtxo = 3; - const c1 = await source.collectSatoshi({ - address, - targetAmount: totalSatoshi, - onlyNonRgbppUtxos: false, - }); - expect(c1.utxos).toHaveLength(totalUtxo); - expect(c1.satoshi).toEqual(totalSatoshi); - - const c2 = await source.collectSatoshi({ - address, - targetAmount: nonRgbppSatoshi, - onlyNonRgbppUtxos: true, - }); - expect(c2.utxos).toHaveLength(nonRgbppUtxo); - expect(c2.satoshi).toEqual(nonRgbppSatoshi); - - await expect(() => - source.collectSatoshi({ + it('onlyNonRgbppUtxos = false', async () => { + const c = await source.collectSatoshi({ address, targetAmount: totalSatoshi, + onlyNonRgbppUtxos: false, + }); + expect(c.utxos).toHaveLength(totalUtxo); + expect(c.satoshi).toEqual(totalSatoshi); + }); + it('onlyNonRgbppUtxos = true', async () => { + const c = await source.collectSatoshi({ + address, + targetAmount: nonRgbppSatoshi, onlyNonRgbppUtxos: true, - }), - ).rejects.toThrowError(); + }); + expect(c.utxos).toHaveLength(nonRgbppUtxo); + expect(c.satoshi).toEqual(nonRgbppSatoshi); + }); + it('Try onlyNonRgbppUtxos = true and targetAmount = totalSatoshi', async () => { + await expect(() => + source.collectSatoshi({ + address, + targetAmount: totalSatoshi, + onlyNonRgbppUtxos: true, + }), + ).rejects.toThrowError(); + }); }); }); diff --git a/packages/service/README.md b/packages/service/README.md index a6bb4898..8132bfe4 100644 --- a/packages/service/README.md +++ b/packages/service/README.md @@ -228,13 +228,18 @@ interface BtcApiBalanceParams { interface BtcApiBalance { address: string; + // @deprecated Use available_satoshi instead satoshi: number; + total_satoshi: number; + available_satoshi: number; pending_satoshi: number; + rgbpp_satoshi: number; dust_satoshi: number; utxo_count: number; } interface BtcApiUtxoParams { + only_non_rgbpp_utxos?: boolean; only_confirmed?: boolean; min_satoshi?: number; no_cache?: boolean; diff --git a/packages/service/src/types/btc.ts b/packages/service/src/types/btc.ts index d5bbd031..3bc9ee00 100644 --- a/packages/service/src/types/btc.ts +++ b/packages/service/src/types/btc.ts @@ -62,13 +62,18 @@ export interface BtcApiBalanceParams { } export interface BtcApiBalance { address: string; + // @deprecated Use available_satoshi instead satoshi: number; + total_satoshi: number; + available_satoshi: number; pending_satoshi: number; + rgbpp_satoshi: number; dust_satoshi: number; utxo_count: number; } export interface BtcApiUtxoParams { + only_non_rgbpp_utxos?: boolean; only_confirmed?: boolean; min_satoshi?: number; no_cache?: boolean; diff --git a/packages/service/tests/Service.test.ts b/packages/service/tests/Service.test.ts index f87fce67..a8fa09aa 100644 --- a/packages/service/tests/Service.test.ts +++ b/packages/service/tests/Service.test.ts @@ -79,6 +79,8 @@ describe( const res = await service.getBtcBalance(btcAddress); expect(res.address).toEqual(btcAddress); expect(res.satoshi).toBeTypeOf('number'); + expect(res.total_satoshi).toBeTypeOf('number'); + expect(res.available_satoshi).toBeTypeOf('number'); expect(res.pending_satoshi).toBeTypeOf('number'); expect(res.dust_satoshi).toBeTypeOf('number'); expect(res.utxo_count).toBeTypeOf('number'); @@ -89,8 +91,7 @@ describe( min_satoshi: originalBalance.satoshi + 1, }); - expect(filteredBalance.satoshi).toEqual(0); - // expect(filteredBalance.dust_satoshi).toEqual(originalBalance.satoshi + originalBalance.dust_satoshi); + expect(filteredBalance.available_satoshi).toEqual(0); }); it('getBtcBalance() with no_cache', async () => { const res = await service.getBtcBalance(btcAddress, {