@bubolabs/wallet-rn-sdk 0.1.2
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/BuboWalletRnSdk.podspec +29 -0
- package/README.md +71 -0
- package/android/build.gradle +46 -0
- package/android/consumer-rules.pro +1 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/com/bubo/wallet/BuboWalletSmokeModule.kt +65 -0
- package/android/src/main/java/com/bubo/wallet/BuboWalletSmokePackage.kt +18 -0
- package/android/src/main/java/uniffi/bubo_wallet_ffi/WalletLibSmoke.kt +92 -0
- package/android/src/main/java/uniffi/bubo_wallet_ffi/bubo_wallet_ffi.kt +1664 -0
- package/android/src/main/jniLibs/arm64-v8a/libbubo_wallet_ffi.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/libuniffi_bubo_wallet_ffi.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libbubo_wallet_ffi.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libuniffi_bubo_wallet_ffi.so +0 -0
- package/android/src/main/jniLibs/x86/libbubo_wallet_ffi.so +0 -0
- package/android/src/main/jniLibs/x86/libuniffi_bubo_wallet_ffi.so +0 -0
- package/android/src/main/jniLibs/x86_64/libbubo_wallet_ffi.so +0 -0
- package/android/src/main/jniLibs/x86_64/libuniffi_bubo_wallet_ffi.so +0 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/native.d.ts +18 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +37 -0
- package/dist/smoke.d.ts +4 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +82 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/ios/BuboWalletSmoke.swift +110 -0
- package/ios/BuboWalletSmokeModule.m +11 -0
- package/ios/BuboWalletSmokeModule.swift +51 -0
- package/ios/bubo_wallet_ffi.swift +905 -0
- package/ios/bubo_wallet_ffiFFI.h +606 -0
- package/ios/bubo_wallet_ffiFFI.modulemap +7 -0
- package/ios/lib/BuboWalletFFI.xcframework/Info.plist +48 -0
- package/ios/lib/BuboWalletFFI.xcframework/ios-arm64/Headers/bubo_wallet_ffiFFI.h +606 -0
- package/ios/lib/BuboWalletFFI.xcframework/ios-arm64/Headers/module.modulemap +7 -0
- package/ios/lib/BuboWalletFFI.xcframework/ios-arm64/libbubo_wallet_ffi.a +0 -0
- package/ios/lib/BuboWalletFFI.xcframework/ios-arm64_x86_64-simulator/Headers/bubo_wallet_ffiFFI.h +606 -0
- package/ios/lib/BuboWalletFFI.xcframework/ios-arm64_x86_64-simulator/Headers/module.modulemap +7 -0
- package/ios/lib/BuboWalletFFI.xcframework/ios-arm64_x86_64-simulator/libbubo_wallet_ffi.a +0 -0
- package/package.json +47 -0
- package/react-native.config.js +12 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "BuboWalletRnSdk"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = "https://github.com/bubo/wallet-rn-sdk"
|
|
10
|
+
s.license = "MIT"
|
|
11
|
+
s.author = { "Bubo" => "dev@bubo.example" }
|
|
12
|
+
s.source = { :path => "." }
|
|
13
|
+
s.platforms = { :ios => "13.4" }
|
|
14
|
+
s.static_framework = true
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/**/*.{swift,m,h}"
|
|
17
|
+
s.public_header_files = "ios/bubo_wallet_ffiFFI.h"
|
|
18
|
+
s.preserve_paths = "ios/bubo_wallet_ffiFFI.modulemap", "ios/lib/BuboWalletFFI.xcframework/**/*"
|
|
19
|
+
s.vendored_frameworks = "ios/lib/BuboWalletFFI.xcframework"
|
|
20
|
+
|
|
21
|
+
s.dependency "React-Core"
|
|
22
|
+
|
|
23
|
+
s.pod_target_xcconfig = {
|
|
24
|
+
"DEFINES_MODULE" => "YES",
|
|
25
|
+
"SWIFT_VERSION" => "5.0",
|
|
26
|
+
"HEADER_SEARCH_PATHS" => "$(inherited) \"${PODS_TARGET_SRCROOT}/ios\"",
|
|
27
|
+
"OTHER_SWIFT_FLAGS" => "$(inherited) -Xcc -fmodule-map-file=${PODS_TARGET_SRCROOT}/ios/bubo_wallet_ffiFFI.modulemap"
|
|
28
|
+
}
|
|
29
|
+
end
|
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# @bubolabs/wallet-rn-sdk
|
|
2
|
+
|
|
3
|
+
Minimal React Native smoke SDK for the UniFFI wallet library.
|
|
4
|
+
|
|
5
|
+
This package is a standard React Native native module layout:
|
|
6
|
+
|
|
7
|
+
- `android/` React Native Android library module (autolinked)
|
|
8
|
+
- `ios/` Pod sources + vendored `BuboWalletFFI.xcframework` (autolinked)
|
|
9
|
+
- `react-native.config.js` for Android package registration
|
|
10
|
+
|
|
11
|
+
## API
|
|
12
|
+
|
|
13
|
+
- `runSmoke()`
|
|
14
|
+
- `runBtcSmoke()`
|
|
15
|
+
|
|
16
|
+
Both methods call native module `BuboWalletSmoke` and return:
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
type WalletSmokeResult = {
|
|
20
|
+
supportedChains: Array<{ chainId: string; capabilities: string[] }>;
|
|
21
|
+
deriveChainId: string;
|
|
22
|
+
derivedAddress: string;
|
|
23
|
+
signChainId: string | null;
|
|
24
|
+
signedTxHex: string | null;
|
|
25
|
+
};
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Example
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { runSmoke } from "@bubolabs/wallet-rn-sdk";
|
|
32
|
+
|
|
33
|
+
const result = await runSmoke();
|
|
34
|
+
console.log(result.deriveChainId, result.derivedAddress);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install @bubolabs/wallet-rn-sdk
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
iOS:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cd ios && pod install
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Distribution Scripts
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
cd ../..
|
|
53
|
+
./scripts/package-rn-sdk.sh
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Builds a publishable tarball and verifies runtime assets are present/synced.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
./scripts/verify-rn-sdk-distribution.sh
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Installs the tarball into `example/` and verifies iOS/Android native builds.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
./scripts/publish-rn-sdk.sh --dry-run
|
|
66
|
+
./scripts/publish-rn-sdk.sh --publish --tag latest
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Publish wrapper:
|
|
70
|
+
- default is dry-run
|
|
71
|
+
- real publish requires `--publish`
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
ext.safeExtGet = { prop, fallback ->
|
|
3
|
+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
apply plugin: "com.android.library"
|
|
8
|
+
apply plugin: "org.jetbrains.kotlin.android"
|
|
9
|
+
|
|
10
|
+
android {
|
|
11
|
+
namespace "com.bubo.wallet"
|
|
12
|
+
compileSdkVersion safeExtGet("compileSdkVersion", 35)
|
|
13
|
+
|
|
14
|
+
defaultConfig {
|
|
15
|
+
minSdkVersion safeExtGet("minSdkVersion", 24)
|
|
16
|
+
targetSdkVersion safeExtGet("targetSdkVersion", 34)
|
|
17
|
+
consumerProguardFiles "consumer-rules.pro"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
compileOptions {
|
|
21
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
22
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
kotlinOptions {
|
|
26
|
+
jvmTarget = "17"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
sourceSets {
|
|
30
|
+
main {
|
|
31
|
+
java.srcDirs = ["src/main/java"]
|
|
32
|
+
jniLibs.srcDirs = ["src/main/jniLibs"]
|
|
33
|
+
manifest.srcFile "src/main/AndroidManifest.xml"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
repositories {
|
|
39
|
+
google()
|
|
40
|
+
mavenCentral()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
dependencies {
|
|
44
|
+
implementation "com.facebook.react:react-android"
|
|
45
|
+
implementation "net.java.dev.jna:jna:5.14.0@aar"
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Consumer ProGuard rules can be added here when needed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
package com.bubo.wallet
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.Promise
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
7
|
+
import com.facebook.react.bridge.ReactMethod
|
|
8
|
+
import com.facebook.react.bridge.WritableArray
|
|
9
|
+
import com.facebook.react.bridge.WritableMap
|
|
10
|
+
import uniffi.bubo_wallet_ffi.SupportedChainInfo
|
|
11
|
+
import uniffi.bubo_wallet_ffi.WalletLibSmoke
|
|
12
|
+
import uniffi.bubo_wallet_ffi.WalletSmokeResult
|
|
13
|
+
|
|
14
|
+
class BuboWalletSmokeModule(
|
|
15
|
+
reactContext: ReactApplicationContext
|
|
16
|
+
) : ReactContextBaseJavaModule(reactContext) {
|
|
17
|
+
|
|
18
|
+
override fun getName(): String = "BuboWalletSmoke"
|
|
19
|
+
|
|
20
|
+
@ReactMethod
|
|
21
|
+
fun runSmoke(promise: Promise) {
|
|
22
|
+
try {
|
|
23
|
+
val result = WalletLibSmoke.runSmoke()
|
|
24
|
+
promise.resolve(toWritableMap(result))
|
|
25
|
+
} catch (t: Throwable) {
|
|
26
|
+
promise.reject("BUBO_WALLET_SMOKE", t.message, t)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@ReactMethod
|
|
31
|
+
fun runBtcSmoke(promise: Promise) {
|
|
32
|
+
try {
|
|
33
|
+
val result = WalletLibSmoke.runBtcSmoke()
|
|
34
|
+
promise.resolve(toWritableMap(result))
|
|
35
|
+
} catch (t: Throwable) {
|
|
36
|
+
promise.reject("BUBO_WALLET_SMOKE", t.message, t)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private fun toWritableMap(result: WalletSmokeResult): WritableMap {
|
|
41
|
+
val map = Arguments.createMap()
|
|
42
|
+
map.putArray("supportedChains", toWritableChains(result.supportedChains))
|
|
43
|
+
map.putString("deriveChainId", result.deriveChainId)
|
|
44
|
+
map.putString("derivedAddress", result.derivedAddress)
|
|
45
|
+
map.putString("signChainId", result.signChainId)
|
|
46
|
+
map.putString("signedTxHex", result.signedTxHex)
|
|
47
|
+
return map
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private fun toWritableChains(chains: List<SupportedChainInfo>): WritableArray {
|
|
51
|
+
val out = Arguments.createArray()
|
|
52
|
+
for (chain in chains) {
|
|
53
|
+
val item = Arguments.createMap()
|
|
54
|
+
item.putString("chainId", chain.chainId)
|
|
55
|
+
|
|
56
|
+
val caps = Arguments.createArray()
|
|
57
|
+
for (cap in chain.capabilities) {
|
|
58
|
+
caps.pushString(cap)
|
|
59
|
+
}
|
|
60
|
+
item.putArray("capabilities", caps)
|
|
61
|
+
out.pushMap(item)
|
|
62
|
+
}
|
|
63
|
+
return out
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
package com.bubo.wallet
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
class BuboWalletSmokePackage : ReactPackage {
|
|
9
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
10
|
+
return listOf(BuboWalletSmokeModule(reactContext))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override fun createViewManagers(
|
|
14
|
+
reactContext: ReactApplicationContext
|
|
15
|
+
): List<ViewManager<*, *>> {
|
|
16
|
+
return emptyList()
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
package uniffi.bubo_wallet_ffi
|
|
2
|
+
|
|
3
|
+
data class WalletSmokeResult(
|
|
4
|
+
val supportedChains: List<SupportedChainInfo>,
|
|
5
|
+
val deriveChainId: String,
|
|
6
|
+
val derivedAddress: String,
|
|
7
|
+
val signChainId: String?,
|
|
8
|
+
val signedTxHex: String?,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
object WalletLibSmoke {
|
|
12
|
+
private const val SAMPLE_MNEMONIC =
|
|
13
|
+
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
|
|
14
|
+
|
|
15
|
+
private val BTC_SMOKE_PAYLOAD = """
|
|
16
|
+
{
|
|
17
|
+
"account": 0,
|
|
18
|
+
"address_index": 0,
|
|
19
|
+
"change_index": 0,
|
|
20
|
+
"network": "mainnet",
|
|
21
|
+
"prev_txid": "0000000000000000000000000000000000000000000000000000000000000001",
|
|
22
|
+
"prev_vout": 0,
|
|
23
|
+
"prev_script_pubkey_hex": "76a914d986ed01b7a22225a70edbf2ba7cfb63a15cb3aa88ac",
|
|
24
|
+
"prev_value_sat": 100000,
|
|
25
|
+
"to_address": "1BoatSLRHtKNngkdXEeobR76b53LETtpyT",
|
|
26
|
+
"amount_sat": 10000,
|
|
27
|
+
"fee_sat": 1000,
|
|
28
|
+
"lock_time": 0,
|
|
29
|
+
"sequence": 4294967295
|
|
30
|
+
}
|
|
31
|
+
""".trimIndent().toByteArray(Charsets.UTF_8)
|
|
32
|
+
|
|
33
|
+
fun runSmoke(): WalletSmokeResult {
|
|
34
|
+
val wallet = WalletLib()
|
|
35
|
+
try {
|
|
36
|
+
wallet.init()
|
|
37
|
+
val chains = wallet.listSupportedChains()
|
|
38
|
+
require(chains.isNotEmpty()) { "no supported chains after init()" }
|
|
39
|
+
|
|
40
|
+
val deriveChain = chains.firstOrNull { it.capabilities.contains("deriveAddress") }
|
|
41
|
+
?: error("no chain exposes deriveAddress capability")
|
|
42
|
+
val address = wallet.deriveAddress(
|
|
43
|
+
deriveChain.chainId,
|
|
44
|
+
SAMPLE_MNEMONIC,
|
|
45
|
+
0u,
|
|
46
|
+
0u,
|
|
47
|
+
null,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
val btcSignCap = chains.firstOrNull { chain ->
|
|
51
|
+
chain.chainId == "btc" && chain.capabilities.contains("buildAndSign")
|
|
52
|
+
}
|
|
53
|
+
if (btcSignCap == null) {
|
|
54
|
+
return WalletSmokeResult(
|
|
55
|
+
supportedChains = chains,
|
|
56
|
+
deriveChainId = deriveChain.chainId,
|
|
57
|
+
derivedAddress = address,
|
|
58
|
+
signChainId = null,
|
|
59
|
+
signedTxHex = null,
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
val signed = wallet.buildAndSign("btc", SAMPLE_MNEMONIC, BTC_SMOKE_PAYLOAD)
|
|
64
|
+
return WalletSmokeResult(
|
|
65
|
+
supportedChains = chains,
|
|
66
|
+
deriveChainId = deriveChain.chainId,
|
|
67
|
+
derivedAddress = address,
|
|
68
|
+
signChainId = "btc",
|
|
69
|
+
signedTxHex = signed.toHex(),
|
|
70
|
+
)
|
|
71
|
+
} finally {
|
|
72
|
+
wallet.close()
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fun runBtcSmoke(): WalletSmokeResult {
|
|
77
|
+
val result = runSmoke()
|
|
78
|
+
require(result.signChainId == "btc" && result.signedTxHex != null) {
|
|
79
|
+
"btc buildAndSign not available in current feature set"
|
|
80
|
+
}
|
|
81
|
+
return result
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private fun ByteArray.toHex(): String {
|
|
86
|
+
val out = StringBuilder(size * 2)
|
|
87
|
+
for (byte in this) {
|
|
88
|
+
out.append(((byte.toInt() ushr 4) and 0xF).toString(16))
|
|
89
|
+
out.append((byte.toInt() and 0xF).toString(16))
|
|
90
|
+
}
|
|
91
|
+
return out.toString()
|
|
92
|
+
}
|