@vultisig/walletcore-native 0.2.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/android/build.gradle +2 -9
- package/android/src/main/java/expo/modules/walletcore/ExpoWalletCoreModule.kt +16 -0
- package/ios/ExpoWalletCoreModule.swift +24 -0
- package/package.json +3 -3
- package/src/ExpoWalletCoreModule.ts +10 -0
- package/src/index.test.ts +35 -0
- package/src/index.ts +19 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @vultisig/walletcore-native
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#2427](https://github.com/vultisig/vultisig-sdk/pull/2427) [`b38628f`](https://github.com/vultisig/vultisig-sdk/commit/b38628f1ad09fa9dac3e23b2056b24c0040500fe) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Use prefix-aware WalletCore SS58 constructors for Bittensor address derivation and transaction destinations, including native iOS and Android bridges. Reject destinations with a different network prefix or invalid account data.
|
|
8
|
+
|
|
9
|
+
Apply the Expo module Gradle plugin so Expo 56's required Kotlin compiler transformations run before Android module registration.
|
|
10
|
+
|
|
11
|
+
Direct callers of `buildBittensorSigningPayload` must pass their initialized WalletCore as the second argument. Direct callers of `refineBittensorChainSpecific` must provide `walletCore` in the input. High-level SDK signing and fee estimation pass the existing runtime automatically.
|
|
12
|
+
|
|
13
|
+
## 1.0.0
|
|
14
|
+
|
|
15
|
+
### Major Changes
|
|
16
|
+
|
|
17
|
+
- [#2218](https://github.com/vultisig/vultisig-sdk/pull/2218) [`d043dc4`](https://github.com/vultisig/vultisig-sdk/commit/d043dc43d9fe33a3160c2739150fd6294f0e7eff) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Unify the workspace on the coordinated Noble/Scure v2 stack and align related workspace peer dependency ranges.
|
|
18
|
+
|
|
3
19
|
## 0.2.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
package/android/build.gradle
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
apply plugin: '
|
|
2
|
-
apply plugin: 'kotlin-android'
|
|
3
|
-
apply plugin: 'maven-publish'
|
|
1
|
+
apply plugin: 'expo-module-gradle-plugin'
|
|
4
2
|
|
|
5
3
|
group = 'expo.modules.walletcore'
|
|
6
4
|
version = '0.1.0'
|
|
@@ -13,12 +11,7 @@ android {
|
|
|
13
11
|
defaultConfig {
|
|
14
12
|
minSdkVersion safeExtGet("minSdkVersion", 23)
|
|
15
13
|
targetSdkVersion safeExtGet("targetSdkVersion", 34)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
publishing {
|
|
19
|
-
singleVariant("release") {
|
|
20
|
-
withSourcesJar()
|
|
21
|
-
}
|
|
14
|
+
versionName project.version.toString()
|
|
22
15
|
}
|
|
23
16
|
|
|
24
17
|
lint {
|
|
@@ -149,6 +149,22 @@ class ExpoWalletCoreModule : Module() {
|
|
|
149
149
|
AnyAddress.isValidSS58(address, CoinType.createFromValue(coinType), ss58Prefix)
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
Function("anyAddressCreateSS58") { address: String, coinType: Int, ss58Prefix: Int ->
|
|
153
|
+
require(ss58Prefix >= 0) { "Invalid SS58 prefix" }
|
|
154
|
+
val coin = CoinType.createFromValue(coinType)
|
|
155
|
+
require(AnyAddress.isValidSS58(address, coin, ss58Prefix)) { "Invalid SS58 address" }
|
|
156
|
+
val addr = AnyAddress(address, coin, ss58Prefix)
|
|
157
|
+
mapOf("description" to addr.description(), "data" to android.util.Base64.encodeToString(addr.data(), android.util.Base64.NO_WRAP))
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
Function("anyAddressCreateSS58WithPublicKey") { publicKeyHandle: Int, coinType: Int, ss58Prefix: Int ->
|
|
161
|
+
val pk = publicKeys[publicKeyHandle] ?: throw Exception("Invalid PublicKey handle")
|
|
162
|
+
require(ss58Prefix >= 0) { "Invalid SS58 prefix" }
|
|
163
|
+
val addr = AnyAddress(pk, CoinType.createFromValue(coinType), ss58Prefix)
|
|
164
|
+
require(addr.description().isNotEmpty()) { "Failed to derive SS58 address" }
|
|
165
|
+
mapOf("description" to addr.description(), "data" to android.util.Base64.encodeToString(addr.data(), android.util.Base64.NO_WRAP))
|
|
166
|
+
}
|
|
167
|
+
|
|
152
168
|
Function("anyAddressCreateWithString") { address: String, coinType: Int ->
|
|
153
169
|
AnyAddress(address, CoinType.createFromValue(coinType)).description()
|
|
154
170
|
}
|
|
@@ -200,6 +200,30 @@ public class ExpoWalletCoreModule: Module {
|
|
|
200
200
|
return AnyAddress.isValidSS58(string: address, coin: ct, ss58Prefix: UInt32(ss58Prefix))
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
Function("anyAddressCreateSS58") { (address: String, coinType: Int, ss58Prefix: Int) -> [String: String] in
|
|
204
|
+
let ct = try coinTypeFromValue(coinType)
|
|
205
|
+
guard let prefix = UInt32(exactly: ss58Prefix),
|
|
206
|
+
let addr = AnyAddress(string: address, coin: ct, ss58Prefix: prefix) else {
|
|
207
|
+
throw NSError(domain: "ExpoWalletCore", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid SS58 address or prefix"])
|
|
208
|
+
}
|
|
209
|
+
return ["description": addr.description, "data": addr.data.base64EncodedString()]
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
Function("anyAddressCreateSS58WithPublicKey") { (publicKeyHandle: Int, coinType: Int, ss58Prefix: Int) -> [String: String] in
|
|
213
|
+
guard let pk = publicKeys[publicKeyHandle] else {
|
|
214
|
+
throw NSError(domain: "ExpoWalletCore", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid PublicKey handle"])
|
|
215
|
+
}
|
|
216
|
+
let ct = try coinTypeFromValue(coinType)
|
|
217
|
+
guard let prefix = UInt32(exactly: ss58Prefix) else {
|
|
218
|
+
throw NSError(domain: "ExpoWalletCore", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid SS58 prefix"])
|
|
219
|
+
}
|
|
220
|
+
let addr = AnyAddress(publicKey: pk, coin: ct, ss58Prefix: prefix)
|
|
221
|
+
guard !addr.description.isEmpty else {
|
|
222
|
+
throw NSError(domain: "ExpoWalletCore", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to derive SS58 address"])
|
|
223
|
+
}
|
|
224
|
+
return ["description": addr.description, "data": addr.data.base64EncodedString()]
|
|
225
|
+
}
|
|
226
|
+
|
|
203
227
|
Function("anyAddressCreateWithString") { (address: String, coinType: Int) -> String in
|
|
204
228
|
let ct = try coinTypeFromValue(coinType)
|
|
205
229
|
guard let addr = AnyAddress(string: address, coin: ct) else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vultisig/walletcore-native",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Native WalletCore bridge for Vultisig SDK (React Native / Expo)",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
"expo-module.config.json"
|
|
13
13
|
],
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@noble/hashes": "^
|
|
15
|
+
"@noble/hashes": "^2.2.0"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"expo": ">=56.0.
|
|
18
|
+
"expo": ">=56.0.12"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"expo": ">=56.0.12"
|
|
@@ -69,6 +69,16 @@ interface ExpoWalletCoreModuleType {
|
|
|
69
69
|
/** Check if an SS58 address is valid. */
|
|
70
70
|
anyAddressIsValidSS58(address: string, coinType: number, ss58Prefix: number): boolean
|
|
71
71
|
|
|
72
|
+
/** Create an SS58 address with an explicit prefix, returning its description and base64 data. */
|
|
73
|
+
anyAddressCreateSS58(address: string, coinType: number, ss58Prefix: number): { description: string; data: string }
|
|
74
|
+
|
|
75
|
+
/** Derive an SS58 address with an explicit prefix, returning its description and base64 data. */
|
|
76
|
+
anyAddressCreateSS58WithPublicKey(
|
|
77
|
+
publicKeyHandle: number,
|
|
78
|
+
coinType: number,
|
|
79
|
+
ss58Prefix: number
|
|
80
|
+
): { description: string; data: string }
|
|
81
|
+
|
|
72
82
|
/** Create an AnyAddress from a string. Returns the description (formatted address). */
|
|
73
83
|
anyAddressCreateWithString(address: string, coinType: number): string
|
|
74
84
|
|
package/src/index.test.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
2
|
|
|
3
3
|
const native = vi.hoisted(() => ({
|
|
4
|
+
anyAddressCreateSS58: vi.fn(() => ({ description: 'ss58-address', data: 'AQID' })),
|
|
5
|
+
anyAddressCreateSS58WithPublicKey: vi.fn(() => ({ description: 'ss58-address', data: 'AQID' })),
|
|
6
|
+
anyAddressData: vi.fn(),
|
|
4
7
|
derivationPath: vi.fn((_coinType: number) => "m/44'/60'/0'/0/0"),
|
|
5
8
|
deriveAddressFromPublicKey: vi.fn((_coinType: number, _handle: number) => '0x1234'),
|
|
6
9
|
}))
|
|
@@ -39,3 +42,35 @@ describe('NativeWalletCore Robinhood contract', () => {
|
|
|
39
42
|
expect(native.deriveAddressFromPublicKey).toHaveBeenNthCalledWith(2, 10_004_663, 7)
|
|
40
43
|
})
|
|
41
44
|
})
|
|
45
|
+
|
|
46
|
+
describe('NativeWalletCore SS58 constructors', () => {
|
|
47
|
+
beforeEach(() => vi.clearAllMocks())
|
|
48
|
+
|
|
49
|
+
it('forwards the explicit prefix and preserves description and bytes from one native result', () => {
|
|
50
|
+
const wc = NativeWalletCore.getInstance()
|
|
51
|
+
const address = wc.AnyAddress.createSS58('ss58-address', wc.CoinType.polkadot, 42)
|
|
52
|
+
expect(native.anyAddressCreateSS58).toHaveBeenCalledWith('ss58-address', 354, 42)
|
|
53
|
+
expect(address.description()).toBe('ss58-address')
|
|
54
|
+
expect(address.data()).toEqual(new Uint8Array([1, 2, 3]))
|
|
55
|
+
expect(native.anyAddressData).not.toHaveBeenCalled()
|
|
56
|
+
expect(() => address.delete()).not.toThrow()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('forwards the public-key handle and prefix without reparsing with a default prefix', () => {
|
|
60
|
+
const wc = NativeWalletCore.getInstance()
|
|
61
|
+
const publicKey = { _handle: 7 } as NativePublicKeyInstance
|
|
62
|
+
const address = wc.AnyAddress.createSS58WithPublicKey(publicKey, wc.CoinType.polkadot, 42)
|
|
63
|
+
expect(native.anyAddressCreateSS58WithPublicKey).toHaveBeenCalledWith(7, 354, 42)
|
|
64
|
+
expect(address.description()).toBe('ss58-address')
|
|
65
|
+
expect(address.data()).toEqual(new Uint8Array([1, 2, 3]))
|
|
66
|
+
expect(native.anyAddressData).not.toHaveBeenCalled()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('propagates invalid-address errors from the native constructor', () => {
|
|
70
|
+
const wc = NativeWalletCore.getInstance()
|
|
71
|
+
native.anyAddressCreateSS58.mockImplementationOnce(() => {
|
|
72
|
+
throw new Error('Invalid SS58 address')
|
|
73
|
+
})
|
|
74
|
+
expect(() => wc.AnyAddress.createSS58('invalid', wc.CoinType.polkadot, 42)).toThrow('Invalid SS58 address')
|
|
75
|
+
})
|
|
76
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Native WalletCore bridge for React Native / Expo.
|
|
5
5
|
* Provides a JS object matching the WalletCore API shape expected by the SDK.
|
|
6
6
|
*/
|
|
7
|
-
import { keccak_256 } from '@noble/hashes/sha3'
|
|
7
|
+
import { keccak_256 } from '@noble/hashes/sha3.js'
|
|
8
8
|
|
|
9
9
|
import ExpoWalletCore from './ExpoWalletCoreModule'
|
|
10
10
|
|
|
@@ -68,6 +68,7 @@ export interface NativeDataVectorInstance {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
export interface NativeAnyAddressInstance {
|
|
71
|
+
delete(): void
|
|
71
72
|
description(): string
|
|
72
73
|
data(): Uint8Array
|
|
73
74
|
}
|
|
@@ -95,6 +96,12 @@ export interface WalletCoreLike {
|
|
|
95
96
|
isValid(address: string, coinType: number): boolean
|
|
96
97
|
isValidBech32(address: string, coinType: number, hrp: string): boolean
|
|
97
98
|
isValidSS58(address: string, coinType: number, ss58Prefix: number): boolean
|
|
99
|
+
createSS58(address: string, coinType: number, ss58Prefix: number): NativeAnyAddressInstance
|
|
100
|
+
createSS58WithPublicKey(
|
|
101
|
+
publicKey: NativePublicKeyInstance,
|
|
102
|
+
coinType: number,
|
|
103
|
+
ss58Prefix: number
|
|
104
|
+
): NativeAnyAddressInstance
|
|
98
105
|
createWithString(address: string, coinType: number): NativeAnyAddressInstance
|
|
99
106
|
createBech32WithPublicKey(
|
|
100
107
|
publicKey: NativePublicKeyInstance,
|
|
@@ -434,6 +441,9 @@ class NativeDataVector implements NativeDataVectorInstance {
|
|
|
434
441
|
// ---------------------------------------------------------------------------
|
|
435
442
|
|
|
436
443
|
class NativeAnyAddress implements NativeAnyAddressInstance {
|
|
444
|
+
delete(): void {
|
|
445
|
+
// Results are copied from native objects; no native handle is retained.
|
|
446
|
+
}
|
|
437
447
|
private readonly _description: string
|
|
438
448
|
private readonly _data: string | null
|
|
439
449
|
|
|
@@ -785,6 +795,14 @@ export class NativeWalletCore {
|
|
|
785
795
|
isValidSS58(address: string, coinType: number, ss58Prefix: number): boolean {
|
|
786
796
|
return ExpoWalletCore.anyAddressIsValidSS58(address, coinType, ss58Prefix)
|
|
787
797
|
},
|
|
798
|
+
createSS58(address: string, coinType: number, ss58Prefix: number): NativeAnyAddress {
|
|
799
|
+
const result = ExpoWalletCore.anyAddressCreateSS58(address, coinType, ss58Prefix)
|
|
800
|
+
return new NativeAnyAddress(result.description, result.data)
|
|
801
|
+
},
|
|
802
|
+
createSS58WithPublicKey(publicKey: NativePublicKey, coinType: number, ss58Prefix: number): NativeAnyAddress {
|
|
803
|
+
const result = ExpoWalletCore.anyAddressCreateSS58WithPublicKey(publicKey._handle, coinType, ss58Prefix)
|
|
804
|
+
return new NativeAnyAddress(result.description, result.data)
|
|
805
|
+
},
|
|
788
806
|
createWithString(address: string, coinType: number): NativeAnyAddress {
|
|
789
807
|
const desc = ExpoWalletCore.anyAddressCreateWithString(address, coinType)
|
|
790
808
|
const dataB64 = ExpoWalletCore.anyAddressData(address, coinType)
|