@vultisig/walletcore-native 1.0.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 CHANGED
@@ -1,5 +1,15 @@
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
+
3
13
  ## 1.0.0
4
14
 
5
15
  ### Major Changes
@@ -1,6 +1,4 @@
1
- apply plugin: 'com.android.library'
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": "1.0.0",
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",
@@ -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
@@ -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)