From edfe71a261ff5b3530d3806130f96df1a2fb62f5 Mon Sep 17 00:00:00 2001 From: Czino Date: Wed, 15 Nov 2023 11:20:21 +0100 Subject: [PATCH 1/3] Add address peek functionality --- .../main/java/io/ltbl/bdkrn/BdkRnModule.kt | 35 ++++++++++++++++--- android/src/main/java/io/ltbl/bdkrn/Utils.kt | 12 +++++-- ios/BdkRnModule.m | 4 +-- ios/BdkRnModule.swift | 27 +++++++++++--- ios/Utils.swift | 19 +++++++--- lib/classes/NativeLoader.d.ts | 2 +- lib/classes/NativeLoader.js.map | 2 +- lib/classes/Wallet.d.ts | 2 +- lib/classes/Wallet.js | 2 +- lib/classes/Wallet.js.map | 2 +- src/classes/NativeLoader.ts | 6 ++-- src/classes/Wallet.ts | 5 ++- 12 files changed, 88 insertions(+), 30 deletions(-) diff --git a/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt b/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt index 39a613d..fc735ee 100644 --- a/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt +++ b/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt @@ -1,6 +1,8 @@ package io.ltbl.bdkrn import com.facebook.react.bridge.* +import com.facebook.react.bridge.ReadableType +import com.facebook.react.bridge.Dynamic import com.facebook.react.bridge.UiThreadUtil.runOnUiThread import org.bitcoindevkit.* import org.bitcoindevkit.Descriptor.Companion.newBip44 @@ -380,11 +382,23 @@ class BdkRnModule(reactContext: ReactApplicationContext) : } @ReactMethod - fun getAddress(id: String, addressIndex: String, result: Promise) { + fun getAddress(id: String, addressIndex: Dynamic, result: Promise) { Thread { try { val randomId = randomId() - val addressInfo = getWalletById(id).getAddress(setAddressIndex(addressIndex)) + var resolvedIndex: Any = "new" + when (val type = addressIndex.getType()) { + ReadableType.String -> { + resolvedIndex = (addressIndex as Dynamic).asString() ?: "new" + } + ReadableType.Number -> { + resolvedIndex = (addressIndex as Dynamic).asDouble() ?: "new" + } + else -> { + result.reject("Invalid address index type", "Address index must be a String or an Int") + } + } + val addressInfo = getWalletById(id).getAddress(setAddressIndex(resolvedIndex)) _addresses[randomId] = addressInfo.address val responseObject = mutableMapOf() responseObject["index"] = addressInfo.index.toInt() @@ -398,12 +412,23 @@ class BdkRnModule(reactContext: ReactApplicationContext) : } @ReactMethod - fun getInternalAddress(id: String, addressIndex: String, result: Promise) { + fun getInternalAddress(id: String, addressIndex: Dynamic, result: Promise) { Thread { try { val randomId = randomId() - val addressInfo = - getWalletById(id).getInternalAddress(setAddressIndex(addressIndex)) + var resolvedIndex: Any = "new" + when (val type = addressIndex.getType()) { + ReadableType.String -> { + resolvedIndex = (addressIndex as Dynamic).asString() ?: "new" + } + ReadableType.Number -> { + resolvedIndex = (addressIndex as Dynamic).asDouble() ?: "new" + } + else -> { + result.reject("Invalid address index type", "Address index must be a String or an Int") + } + } + val addressInfo = getWalletById(id).getInternalAddress(setAddressIndex(resolvedIndex)) _addresses[randomId] = addressInfo.address val responseObject = mutableMapOf() responseObject["index"] = addressInfo.index.toInt() diff --git a/android/src/main/java/io/ltbl/bdkrn/Utils.kt b/android/src/main/java/io/ltbl/bdkrn/Utils.kt index f6d1bae..e8fadfb 100644 --- a/android/src/main/java/io/ltbl/bdkrn/Utils.kt +++ b/android/src/main/java/io/ltbl/bdkrn/Utils.kt @@ -53,10 +53,16 @@ fun getEntropy(entropy: ReadableArray): List { return entropyArray } -fun setAddressIndex(addressIndex: String?): AddressIndex { +fun setAddressIndex(addressIndex: Any?): AddressIndex { return when (addressIndex) { - "new" -> return AddressIndex.New - "lastUnused" -> return AddressIndex.LastUnused + is String -> when (addressIndex) { + "new" -> AddressIndex.New + "lastUnused" -> AddressIndex.LastUnused + else -> AddressIndex.New + } + is Double -> { + AddressIndex.Peek(addressIndex.toUInt()) + } else -> AddressIndex.New } } diff --git a/ios/BdkRnModule.m b/ios/BdkRnModule.m index 86f151e..3f95b77 100644 --- a/ios/BdkRnModule.m +++ b/ios/BdkRnModule.m @@ -186,14 +186,14 @@ @interface RCT_EXTERN_MODULE(BdkRnModule, NSObject) RCT_EXTERN_METHOD( getAddress:(nonnull NSString*)id - addressIndex: (nonnull NSString*)addressIndex + addressIndex: (nonnull id)addressIndex resolve: (RCTPromiseResolveBlock)resolve reject: (RCTPromiseRejectBlock)reject ) RCT_EXTERN_METHOD( getInternalAddress:(nonnull NSString*)id - addressIndex: (nonnull NSString*)addressIndex + addressIndex: (nonnull id)addressIndex resolve: (RCTPromiseResolveBlock)resolve reject: (RCTPromiseRejectBlock)reject ) diff --git a/ios/BdkRnModule.swift b/ios/BdkRnModule.swift index 9609f1e..c6d6edd 100644 --- a/ios/BdkRnModule.swift +++ b/ios/BdkRnModule.swift @@ -490,13 +490,23 @@ class BdkRnModule: NSObject { @objc func getAddress(_ id: String, - addressIndex: String, + addressIndex: Any, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock ) { do { + let resolvedIndex: AddressIndex + if let indexString = addressIndex as? String { + resolvedIndex = setAddressIndex(addressIndex: indexString) + } else if let indexInt = addressIndex as? Int { + resolvedIndex = setAddressIndex(addressIndex: indexInt) + } else { + reject("Invalid address index type", "Address index must be a String or an Int", nil) + return + } + let addressInfo = try getWalletById(id: id).getAddress( - addressIndex: setAddressIndex(addressIndex: addressIndex) + addressIndex: resolvedIndex ) let randomId = randomId() _addresses[randomId] = addressInfo.address @@ -509,13 +519,22 @@ class BdkRnModule: NSObject { @objc func getInternalAddress(_ id: String, - addressIndex: String, + addressIndex: Any, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock ) { do { + let resolvedIndex: AddressIndex + if let indexString = addressIndex as? String { + resolvedIndex = setAddressIndex(addressIndex: indexString) + } else if let indexInt = addressIndex as? Int { + resolvedIndex = setAddressIndex(addressIndex: indexInt) + } else { + reject("Invalid address index type", "Address index must be a String or an Int", nil) + return + } let addressInfo = try getWalletById(id: id).getInternalAddress( - addressIndex: setAddressIndex(addressIndex: addressIndex) + addressIndex: resolvedIndex ) let randomId = randomId() _addresses[randomId] = addressInfo.address diff --git a/ios/Utils.swift b/ios/Utils.swift index 0cfda22..0b228e9 100644 --- a/ios/Utils.swift +++ b/ios/Utils.swift @@ -50,11 +50,20 @@ func getEntropy(entropy: NSArray) -> Array { } -func setAddressIndex(addressIndex: String?) -> AddressIndex { - switch (addressIndex) { - case "new": return AddressIndex.new - case "lastUnused": return AddressIndex.lastUnused - default: return AddressIndex.new +func setAddressIndex(addressIndex: Any?) -> AddressIndex { + if let addressIndexString = addressIndex as? String { + switch addressIndexString { + case "new": + return AddressIndex.new + case "lastUnused": + return AddressIndex.lastUnused + default: + return AddressIndex.new + } + } else if let addressIndexNumber = addressIndex as? Int { + return AddressIndex.peek(index: UInt32(addressIndexNumber)) + } else { + return AddressIndex.new } } diff --git a/lib/classes/NativeLoader.d.ts b/lib/classes/NativeLoader.d.ts index 60c86e4..e5fda47 100644 --- a/lib/classes/NativeLoader.d.ts +++ b/lib/classes/NativeLoader.d.ts @@ -27,7 +27,7 @@ export interface NativeBdkRn { sqliteDBInit(path: string): string; walletInit(descriptor: string, changeDescriptor: string | null, network: Network, dbConfig: string): any; getAddress(id: string, addressIndex: AddressIndex): any; - getInternalAddress(id: string, addressIndex: AddressIndex): any; + getInternalAddress(id: string, addressIndex: AddressIndex | number): any; isMine(id: string, scriptId: string): boolean; getBalance(id: string): Balance; getNetwork(id: string): string; diff --git a/lib/classes/NativeLoader.js.map b/lib/classes/NativeLoader.js.map index 8cfe416..ac621cb 100644 --- a/lib/classes/NativeLoader.js.map +++ b/lib/classes/NativeLoader.js.map @@ -1 +1 @@ -{"version":3,"file":"NativeLoader.js","sourceRoot":"","sources":["../../src/classes/NativeLoader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAoI7C,MAAM,OAAO,YAAY;IAGvB;QACE,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC,WAAW,CAAC;IACxC,CAAC;CACF"} \ No newline at end of file +{"version":3,"file":"NativeLoader.js","sourceRoot":"","sources":["../../src/classes/NativeLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAuI7C,MAAM,OAAO,YAAY;IAGvB;QACE,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC,WAAW,CAAC;IACxC,CAAC;CACF"} \ No newline at end of file diff --git a/lib/classes/Wallet.d.ts b/lib/classes/Wallet.d.ts index 08a86af..5aa699b 100644 --- a/lib/classes/Wallet.d.ts +++ b/lib/classes/Wallet.d.ts @@ -30,7 +30,7 @@ export declare class Wallet extends NativeLoader { * @param addressIndex * @returns {Promise} */ - getInternalAddress(addressIndex: AddressIndex): Promise; + getInternalAddress(addressIndex: AddressIndex | number): Promise; /** * check if the wallet is yours or not * @param script diff --git a/lib/classes/Wallet.js b/lib/classes/Wallet.js index 85c89b3..92291e2 100644 --- a/lib/classes/Wallet.js +++ b/lib/classes/Wallet.js @@ -1,6 +1,6 @@ -import { AddressInfo, Balance, LocalUtxo } from './Bindings'; import { createOutpoint, createTxDetailsObject, createTxOut, getKeychainKind, getNetwork } from '../lib/utils'; import { Address } from './Address'; +import { AddressInfo, Balance, LocalUtxo } from './Bindings'; import { NativeLoader } from './NativeLoader'; import { PartiallySignedTransaction } from './PartiallySignedTransaction'; /** diff --git a/lib/classes/Wallet.js.map b/lib/classes/Wallet.js.map index 0186a41..7cacbbf 100644 --- a/lib/classes/Wallet.js.map +++ b/lib/classes/Wallet.js.map @@ -1 +1 @@ -{"version":3,"file":"Wallet.js","sourceRoot":"","sources":["../../src/classes/Wallet.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"Wallet.js","sourceRoot":"","sources":["../../src/classes/Wallet.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/classes/NativeLoader.ts b/src/classes/NativeLoader.ts index 7e0d1fb..baa9b2f 100644 --- a/src/classes/NativeLoader.ts +++ b/src/classes/NativeLoader.ts @@ -1,8 +1,8 @@ +import { NativeModules } from 'react-native'; + import { AddressIndex, BlockchainRpcConfig, KeychainKind, Network, Payload, WordCount } from '../lib/enums'; import { Balance, OutPoint, ScriptAmount, SignOptions, TransactionDetails } from './Bindings'; -import { NativeModules } from 'react-native'; - export interface NativeBdkRn { generateSeedFromWordCount(wordCount: WordCount): string; generateSeedFromString(mnemonic: string): string; @@ -51,7 +51,7 @@ export interface NativeBdkRn { walletInit(descriptor: string, changeDescriptor: string | null, network: Network, dbConfig: string): any; getAddress(id: string, addressIndex: AddressIndex): any; - getInternalAddress(id: string, addressIndex: AddressIndex): any; + getInternalAddress(id: string, addressIndex: AddressIndex | number): any; isMine(id: string, scriptId: string): boolean; getBalance(id: string): Balance; getNetwork(id: string): string; diff --git a/src/classes/Wallet.ts b/src/classes/Wallet.ts index 86c8dec..9bb9177 100644 --- a/src/classes/Wallet.ts +++ b/src/classes/Wallet.ts @@ -1,8 +1,7 @@ import { AddressIndex, Network } from '../lib/enums'; -import { AddressInfo, Balance, LocalUtxo, SignOptions, TransactionDetails } from './Bindings'; import { createOutpoint, createTxDetailsObject, createTxOut, getKeychainKind, getNetwork } from '../lib/utils'; - import { Address } from './Address'; +import { AddressInfo, Balance, LocalUtxo, SignOptions, TransactionDetails } from './Bindings'; import { Blockchain } from './Blockchain'; import { DatabaseConfig } from './DatabaseConfig'; import { Descriptor } from './Descriptor'; @@ -58,7 +57,7 @@ export class Wallet extends NativeLoader { * @param addressIndex * @returns {Promise} */ - async getInternalAddress(addressIndex: AddressIndex): Promise { + async getInternalAddress(addressIndex: AddressIndex | number): Promise { let addressInfo = await this._bdk.getInternalAddress(this.id, addressIndex); return new AddressInfo( addressInfo.index, From 4f47402e846e8cde34b14d3331cc90d27c79f24c Mon Sep 17 00:00:00 2001 From: Czino Date: Wed, 15 Nov 2023 11:22:54 +0100 Subject: [PATCH 2/3] Add unit tests and fix type error --- __tests__/classes/Wallet.spec.ts | 23 +++++++++++++++++++---- src/classes/NativeLoader.ts | 2 +- src/classes/Wallet.ts | 2 +- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/__tests__/classes/Wallet.spec.ts b/__tests__/classes/Wallet.spec.ts index 49ccb84..8237469 100644 --- a/__tests__/classes/Wallet.spec.ts +++ b/__tests__/classes/Wallet.spec.ts @@ -1,10 +1,9 @@ import { Address, Blockchain, DatabaseConfig, Descriptor, PartiallySignedTransaction, Wallet } from '../../src'; -import { AddressIndex, KeychainKind, Network } from '../../src/lib/enums'; import { AddressInfo, Balance, LocalUtxo, SignOptions } from '../../src/classes/Bindings'; -import { changeDescriptorString, descriptorString, mockTransactionDetails } from '../mockData'; -import { createOutpoint, createTxOut } from '../../src/lib/utils'; - import { Script } from '../../src/classes/Script'; +import { AddressIndex, KeychainKind, Network } from '../../src/lib/enums'; +import { createOutpoint, createTxOut } from '../../src/lib/utils'; +import { changeDescriptorString, descriptorString, mockTransactionDetails } from '../mockData'; import { mockBdkRnModule } from '../setup'; describe('Wallet', () => { @@ -67,6 +66,14 @@ describe('Wallet', () => { expect(mockBdkRnModule.getAddress).toHaveBeenCalledWith(wallet.id, AddressIndex.LastUnused); }); + it('Should return AddressInfo at index using the external descriptor', async () => { + const index = 21; + let res = await wallet.getAddress(index); + expect(res.index).toBe(addressIndex); + expect(res.address).toStrictEqual(new Address()._setAddress(address)); + expect(mockBdkRnModule.getAddress).toHaveBeenCalledWith(wallet.id, index); + }); + it('Should return a new AddressInfo using the internal descriptor', async () => { let res = await wallet.getInternalAddress(AddressIndex.New); expect(res).toBeInstanceOf(AddressInfo); @@ -82,6 +89,14 @@ describe('Wallet', () => { expect(mockBdkRnModule.getInternalAddress).toHaveBeenCalledWith(wallet.id, AddressIndex.LastUnused); }); + it('Should return AddressInfo at index using the internal descriptor', async () => { + const index = 21; + let res = await wallet.getInternalAddress(index); + expect(res.index).toBe(addressIndex); + expect(res.address).toStrictEqual(new Address()._setAddress(address)); + expect(mockBdkRnModule.getInternalAddress).toHaveBeenCalledWith(wallet.id, index); + }); + it('Should return valid Balance object', async () => { const mockedNumber = 150; const expectedBalance = new Balance(mockedNumber, mockedNumber, mockedNumber, mockedNumber, mockedNumber); diff --git a/src/classes/NativeLoader.ts b/src/classes/NativeLoader.ts index baa9b2f..9ee500e 100644 --- a/src/classes/NativeLoader.ts +++ b/src/classes/NativeLoader.ts @@ -50,7 +50,7 @@ export interface NativeBdkRn { sqliteDBInit(path: string): string; walletInit(descriptor: string, changeDescriptor: string | null, network: Network, dbConfig: string): any; - getAddress(id: string, addressIndex: AddressIndex): any; + getAddress(id: string, addressIndex: AddressIndex | number): any; getInternalAddress(id: string, addressIndex: AddressIndex | number): any; isMine(id: string, scriptId: string): boolean; getBalance(id: string): Balance; diff --git a/src/classes/Wallet.ts b/src/classes/Wallet.ts index 9bb9177..5a36653 100644 --- a/src/classes/Wallet.ts +++ b/src/classes/Wallet.ts @@ -43,7 +43,7 @@ export class Wallet extends NativeLoader { * @param addressIndex * @returns {Promise} */ - async getAddress(addressIndex: AddressIndex): Promise { + async getAddress(addressIndex: AddressIndex | number): Promise { let addressInfo = await this._bdk.getAddress(this.id, addressIndex); return new AddressInfo( addressInfo.index, From 84ae5a110eda2642b5de386ae8862df0deb796f7 Mon Sep 17 00:00:00 2001 From: Czino Date: Wed, 15 Nov 2023 11:29:59 +0100 Subject: [PATCH 3/3] Gracefully handle invalid addressIndex type by falling back to new --- android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt | 4 ++-- ios/BdkRnModule.swift | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt b/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt index fc735ee..ab8954e 100644 --- a/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt +++ b/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt @@ -395,7 +395,7 @@ class BdkRnModule(reactContext: ReactApplicationContext) : resolvedIndex = (addressIndex as Dynamic).asDouble() ?: "new" } else -> { - result.reject("Invalid address index type", "Address index must be a String or an Int") + resolvedIndex = setAddressIndex("new") } } val addressInfo = getWalletById(id).getAddress(setAddressIndex(resolvedIndex)) @@ -425,7 +425,7 @@ class BdkRnModule(reactContext: ReactApplicationContext) : resolvedIndex = (addressIndex as Dynamic).asDouble() ?: "new" } else -> { - result.reject("Invalid address index type", "Address index must be a String or an Int") + resolvedIndex = setAddressIndex("new") } } val addressInfo = getWalletById(id).getInternalAddress(setAddressIndex(resolvedIndex)) diff --git a/ios/BdkRnModule.swift b/ios/BdkRnModule.swift index c6d6edd..e9ddcd2 100644 --- a/ios/BdkRnModule.swift +++ b/ios/BdkRnModule.swift @@ -501,8 +501,7 @@ class BdkRnModule: NSObject { } else if let indexInt = addressIndex as? Int { resolvedIndex = setAddressIndex(addressIndex: indexInt) } else { - reject("Invalid address index type", "Address index must be a String or an Int", nil) - return + resolvedIndex = setAddressIndex(addressIndex: "new") } let addressInfo = try getWalletById(id: id).getAddress( @@ -530,8 +529,7 @@ class BdkRnModule: NSObject { } else if let indexInt = addressIndex as? Int { resolvedIndex = setAddressIndex(addressIndex: indexInt) } else { - reject("Invalid address index type", "Address index must be a String or an Int", nil) - return + resolvedIndex = setAddressIndex(addressIndex: "new") } let addressInfo = try getWalletById(id: id).getInternalAddress( addressIndex: resolvedIndex