@vultisig/walletcore-native 0.1.2 → 0.2.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 +6 -0
- package/android/build.gradle +3 -2
- package/android/src/main/java/expo/modules/walletcore/ExpoWalletCoreModule.kt +1 -0
- package/ios/ExpoWalletCore.podspec +1 -1
- package/ios/ExpoWalletCoreModule.swift +8 -1
- package/package.json +3 -3
- package/src/ExpoWalletCoreModule.ts +1 -6
- package/src/index.test.ts +41 -0
- package/src/index.ts +28 -31
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @vultisig/walletcore-native
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1541](https://github.com/vultisig/vultisig-sdk/pull/1541) [`b9f81af`](https://github.com/vultisig/vultisig-sdk/commit/b9f81af9065a5c0bfc2f86f8fb20aa51e670ab77) Thanks [@realpaaao](https://github.com/realpaaao)! - Add Robinhood Chain (Arbitrum Orbit EVM L2, chain id 4663, ETH gas). Swaps enabled via LiFi and KyberSwap.
|
|
8
|
+
|
|
3
9
|
## 0.1.2
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/android/build.gradle
CHANGED
|
@@ -47,7 +47,8 @@ repositories {
|
|
|
47
47
|
username = System.getenv("GITHUB_USER")
|
|
48
48
|
?: System.getenv("GITHUB_ACTOR")
|
|
49
49
|
?: "token"
|
|
50
|
-
password = System.getenv("
|
|
50
|
+
password = System.getenv("TRUSTWALLET_PAT")
|
|
51
|
+
?: System.getenv("GITHUB_TOKEN")
|
|
51
52
|
?: System.getenv("GH_TOKEN")
|
|
52
53
|
?: ""
|
|
53
54
|
}
|
|
@@ -60,7 +61,7 @@ repositories {
|
|
|
60
61
|
dependencies {
|
|
61
62
|
implementation project(':expo-modules-core')
|
|
62
63
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${safeExtGet('kotlinVersion', '1.8.10')}"
|
|
63
|
-
implementation 'com.trustwallet:wallet-core:4.
|
|
64
|
+
implementation 'com.trustwallet:wallet-core:4.7.0'
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
def safeExtGet(prop, fallback) {
|
|
@@ -65,6 +65,7 @@ class ExpoWalletCoreModule : Module() {
|
|
|
65
65
|
"cronosChain" to CoinType.CRONOSCHAIN,
|
|
66
66
|
"blast" to CoinType.BLAST,
|
|
67
67
|
"zksync" to CoinType.ZKSYNC,
|
|
68
|
+
"robinhoodChain" to CoinType.ROBINHOODCHAIN,
|
|
68
69
|
"osmosis" to CoinType.OSMOSIS,
|
|
69
70
|
"terraV2" to CoinType.TERRAV2,
|
|
70
71
|
"noble" to CoinType.NOBLE,
|
|
@@ -92,6 +92,7 @@ public class ExpoWalletCoreModule: Module {
|
|
|
92
92
|
"polygon": .polygon, "optimism": .optimism,
|
|
93
93
|
"cronosChain": .cronosChain, "blast": .blast,
|
|
94
94
|
"zksync": .zksync, "osmosis": .osmosis,
|
|
95
|
+
"robinhoodChain": .robinhoodChain,
|
|
95
96
|
"terraV2": .terraV2, "terra": .terra,
|
|
96
97
|
"noble": .noble, "kujira": .kujira,
|
|
97
98
|
"dydx": .dydx, "akash": .akash, "mantle": .mantle, "sei": .sei,
|
|
@@ -342,7 +343,13 @@ public class ExpoWalletCoreModule: Module {
|
|
|
342
343
|
throw NSError(domain: "ExpoWalletCore", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid HDWallet handle"])
|
|
343
344
|
}
|
|
344
345
|
let ct = try coinTypeFromValue(coinType)
|
|
345
|
-
let key = wallet.getKey(coin: ct, derivationPath: derivationPath)
|
|
346
|
+
guard let key = wallet.getKey(coin: ct, derivationPath: derivationPath) else {
|
|
347
|
+
throw NSError(
|
|
348
|
+
domain: "ExpoWalletCore",
|
|
349
|
+
code: -1,
|
|
350
|
+
userInfo: [NSLocalizedDescriptionKey: "Failed to derive PrivateKey for CoinType raw value \(coinType)"]
|
|
351
|
+
)
|
|
352
|
+
}
|
|
346
353
|
return storePrivateKey(key)
|
|
347
354
|
}
|
|
348
355
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vultisig/walletcore-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.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",
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"@noble/hashes": "^1.8.0"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"expo": ">=
|
|
18
|
+
"expo": ">=56.0.8"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"expo": ">=
|
|
21
|
+
"expo": ">=56.0.12"
|
|
22
22
|
},
|
|
23
23
|
"publishConfig": {
|
|
24
24
|
"access": "public"
|
|
@@ -129,12 +129,7 @@ interface ExpoWalletCoreModuleType {
|
|
|
129
129
|
hdWalletGetAddressForCoin(handle: number, coinType: number): string
|
|
130
130
|
|
|
131
131
|
/** Get the extended private key. */
|
|
132
|
-
hdWalletGetExtendedPrivateKey(
|
|
133
|
-
handle: number,
|
|
134
|
-
purposeValue: number,
|
|
135
|
-
coinType: number,
|
|
136
|
-
versionValue: number
|
|
137
|
-
): string
|
|
132
|
+
hdWalletGetExtendedPrivateKey(handle: number, purposeValue: number, coinType: number, versionValue: number): string
|
|
138
133
|
|
|
139
134
|
/** Free an HDWallet handle. */
|
|
140
135
|
freeHDWallet(handle: number): void
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
const native = vi.hoisted(() => ({
|
|
4
|
+
derivationPath: vi.fn((_coinType: number) => "m/44'/60'/0'/0/0"),
|
|
5
|
+
deriveAddressFromPublicKey: vi.fn((_coinType: number, _handle: number) => '0x1234'),
|
|
6
|
+
}))
|
|
7
|
+
|
|
8
|
+
vi.mock('expo-modules-core', () => ({
|
|
9
|
+
requireNativeModule: () => native,
|
|
10
|
+
}))
|
|
11
|
+
|
|
12
|
+
import { type NativePublicKeyInstance, NativeWalletCore } from './index'
|
|
13
|
+
|
|
14
|
+
describe('NativeWalletCore Robinhood contract', () => {
|
|
15
|
+
beforeEach(() => vi.clearAllMocks())
|
|
16
|
+
|
|
17
|
+
it('passes the canonical finite coin type to the native derivation bridge', () => {
|
|
18
|
+
const walletCore = NativeWalletCore.getInstance()
|
|
19
|
+
const coinType = walletCore.CoinType.robinhoodChain
|
|
20
|
+
|
|
21
|
+
expect(coinType).toBe(10_004_663)
|
|
22
|
+
expect(Number.isInteger(coinType)).toBe(true)
|
|
23
|
+
expect(walletCore.CoinTypeExt.derivationPath(coinType)).toBe("m/44'/60'/0'/0/0")
|
|
24
|
+
expect(native.derivationPath).toHaveBeenCalledWith(10_004_663)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('uses the same EVM address derivation contract as Ethereum', () => {
|
|
28
|
+
const walletCore = NativeWalletCore.getInstance()
|
|
29
|
+
const publicKey = { _handle: 7 } as NativePublicKeyInstance
|
|
30
|
+
|
|
31
|
+
const ethereumAddress = walletCore.CoinTypeExt.deriveAddressFromPublicKey(walletCore.CoinType.ethereum, publicKey)
|
|
32
|
+
const robinhoodAddress = walletCore.CoinTypeExt.deriveAddressFromPublicKey(
|
|
33
|
+
walletCore.CoinType.robinhoodChain,
|
|
34
|
+
publicKey
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
expect(robinhoodAddress).toBe(ethereumAddress)
|
|
38
|
+
expect(native.deriveAddressFromPublicKey).toHaveBeenNthCalledWith(1, 60, 7)
|
|
39
|
+
expect(native.deriveAddressFromPublicKey).toHaveBeenNthCalledWith(2, 10_004_663, 7)
|
|
40
|
+
})
|
|
41
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Provides a JS object matching the WalletCore API shape expected by the SDK.
|
|
6
6
|
*/
|
|
7
7
|
import { keccak_256 } from '@noble/hashes/sha3'
|
|
8
|
+
|
|
8
9
|
import ExpoWalletCore from './ExpoWalletCoreModule'
|
|
9
10
|
|
|
10
11
|
// ---------------------------------------------------------------------------
|
|
@@ -95,13 +96,22 @@ export interface WalletCoreLike {
|
|
|
95
96
|
isValidBech32(address: string, coinType: number, hrp: string): boolean
|
|
96
97
|
isValidSS58(address: string, coinType: number, ss58Prefix: number): boolean
|
|
97
98
|
createWithString(address: string, coinType: number): NativeAnyAddressInstance
|
|
98
|
-
createBech32WithPublicKey(
|
|
99
|
+
createBech32WithPublicKey(
|
|
100
|
+
publicKey: NativePublicKeyInstance,
|
|
101
|
+
coinType: number,
|
|
102
|
+
hrp: string
|
|
103
|
+
): NativeAnyAddressInstance
|
|
99
104
|
createBech32(address: string, coinType: number, hrp: string): NativeAnyAddressInstance
|
|
100
105
|
}
|
|
101
106
|
|
|
102
107
|
TransactionCompiler: {
|
|
103
108
|
preImageHashes(coinType: number, txInputData: Uint8Array): Uint8Array
|
|
104
|
-
compileWithSignatures(
|
|
109
|
+
compileWithSignatures(
|
|
110
|
+
coinType: number,
|
|
111
|
+
txInputData: Uint8Array,
|
|
112
|
+
signatures: NativeDataVectorInstance,
|
|
113
|
+
publicKeys: NativeDataVectorInstance
|
|
114
|
+
): Uint8Array
|
|
105
115
|
}
|
|
106
116
|
|
|
107
117
|
DataVector: {
|
|
@@ -161,31 +171,27 @@ export interface WalletCoreLike {
|
|
|
161
171
|
// ---------------------------------------------------------------------------
|
|
162
172
|
// Helpers — base64 <-> Uint8Array
|
|
163
173
|
// ---------------------------------------------------------------------------
|
|
174
|
+
//
|
|
175
|
+
// Both helpers assume `Buffer` is globally available. On RN/Hermes that is
|
|
176
|
+
// guaranteed because `@vultisig/sdk`'s react-native entrypoint installs the
|
|
177
|
+
// buffer polyfill before any module graph import runs; on Node it is a
|
|
178
|
+
// builtin. Consumers importing `@vultisig/walletcore-native` directly
|
|
179
|
+
// (without going through @vultisig/sdk's RN entrypoint) must polyfill
|
|
180
|
+
// `globalThis.Buffer` themselves before invoking any WalletCore method.
|
|
164
181
|
|
|
165
182
|
function toBase64(bytes: Uint8Array | Buffer): string {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
let binary = ''
|
|
170
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
171
|
-
binary += String.fromCharCode(bytes[i]!)
|
|
172
|
-
}
|
|
173
|
-
return btoa(binary)
|
|
183
|
+
const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength)
|
|
184
|
+
return buf.toString('base64')
|
|
174
185
|
}
|
|
175
186
|
|
|
176
187
|
function fromBase64(b64: string): Uint8Array {
|
|
177
|
-
|
|
178
|
-
const bytes = new Uint8Array(binary.length)
|
|
179
|
-
for (let i = 0; i < binary.length; i++) {
|
|
180
|
-
bytes[i] = binary.charCodeAt(i)
|
|
181
|
-
}
|
|
182
|
-
return bytes
|
|
188
|
+
return new Uint8Array(Buffer.from(b64, 'base64'))
|
|
183
189
|
}
|
|
184
190
|
|
|
185
191
|
// ---------------------------------------------------------------------------
|
|
186
192
|
// CoinType enum — numeric values matching TrustWallet's CoinType
|
|
187
|
-
// Values sourced from TrustWallet wallet-core v4.
|
|
188
|
-
// https://github.com/trustwallet/wallet-core/blob/
|
|
193
|
+
// Values sourced from TrustWallet wallet-core v4.7.0:
|
|
194
|
+
// https://github.com/trustwallet/wallet-core/blob/4.7.0/include/TrustWalletCore/TWCoinType.h
|
|
189
195
|
// ---------------------------------------------------------------------------
|
|
190
196
|
|
|
191
197
|
const CoinTypeValues: Record<string, number> = {
|
|
@@ -216,6 +222,7 @@ const CoinTypeValues: Record<string, number> = {
|
|
|
216
222
|
cronosChain: 10000025,
|
|
217
223
|
blast: 81457,
|
|
218
224
|
zksync: 10000324,
|
|
225
|
+
robinhoodChain: 10004663,
|
|
219
226
|
osmosis: 10000118,
|
|
220
227
|
terraV2: 10000330,
|
|
221
228
|
noble: 18000118,
|
|
@@ -601,9 +608,7 @@ function abiEncode(name: string, params: AbiParam[]): Uint8Array {
|
|
|
601
608
|
|
|
602
609
|
// Concatenate: selector + heads + tails
|
|
603
610
|
const totalLen =
|
|
604
|
-
selector.length +
|
|
605
|
-
headParts.reduce((sum, p) => sum + p.length, 0) +
|
|
606
|
-
tailParts.reduce((sum, p) => sum + p.length, 0)
|
|
611
|
+
selector.length + headParts.reduce((sum, p) => sum + p.length, 0) + tailParts.reduce((sum, p) => sum + p.length, 0)
|
|
607
612
|
|
|
608
613
|
const result = new Uint8Array(totalLen)
|
|
609
614
|
let offset = 0
|
|
@@ -785,16 +790,8 @@ export class NativeWalletCore {
|
|
|
785
790
|
const dataB64 = ExpoWalletCore.anyAddressData(address, coinType)
|
|
786
791
|
return new NativeAnyAddress(desc, dataB64)
|
|
787
792
|
},
|
|
788
|
-
createBech32WithPublicKey(
|
|
789
|
-
publicKey
|
|
790
|
-
coinType: number,
|
|
791
|
-
hrp: string
|
|
792
|
-
): NativeAnyAddress {
|
|
793
|
-
const desc = ExpoWalletCore.anyAddressCreateBech32WithPublicKey(
|
|
794
|
-
publicKey._handle,
|
|
795
|
-
coinType,
|
|
796
|
-
hrp
|
|
797
|
-
)
|
|
793
|
+
createBech32WithPublicKey(publicKey: NativePublicKey, coinType: number, hrp: string): NativeAnyAddress {
|
|
794
|
+
const desc = ExpoWalletCore.anyAddressCreateBech32WithPublicKey(publicKey._handle, coinType, hrp)
|
|
798
795
|
return new NativeAnyAddress(desc)
|
|
799
796
|
},
|
|
800
797
|
createBech32(address: string, coinType: number, hrp: string): NativeAnyAddress {
|