dash-shielded-native 0.0.1

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +27 -0
  3. package/README.md +36 -0
  4. package/android/build.gradle +56 -0
  5. package/android/src/main/AndroidManifest.xml +1 -0
  6. package/android/src/main/java/app/edge/rndashshielded/RNDashShieldedModule.kt +215 -0
  7. package/android/src/main/java/app/edge/rndashshielded/RNDashShieldedPackage.kt +16 -0
  8. package/android/src/main/java/uniffi/dash/dash.kt +1665 -0
  9. package/android/src/main/jniLibs/arm64-v8a/libdashshielded.so +0 -0
  10. package/dash-shielded-native.podspec +32 -0
  11. package/ios/.uniffi-generated +1 -0
  12. package/ios/EdgeDashClient.swift +88 -0
  13. package/ios/RNDashShielded.m +83 -0
  14. package/ios/RNDashShielded.swift +214 -0
  15. package/ios/dash-shielded-native-Bridging-Header.h +2 -0
  16. package/ios/dash.swift +1124 -0
  17. package/ios/libdashshielded.xcframework/Info.plist +47 -0
  18. package/ios/libdashshielded.xcframework/ios-arm64/Headers/dashFFI.h +696 -0
  19. package/ios/libdashshielded.xcframework/ios-arm64/Headers/module.modulemap +7 -0
  20. package/ios/libdashshielded.xcframework/ios-arm64/libdashshielded.a +0 -0
  21. package/ios/libdashshielded.xcframework/ios-arm64-simulator/Headers/dashFFI.h +696 -0
  22. package/ios/libdashshielded.xcframework/ios-arm64-simulator/Headers/module.modulemap +7 -0
  23. package/ios/libdashshielded.xcframework/ios-arm64-simulator/libdashshielded.a +0 -0
  24. package/lib/load-addon.d.ts +34 -0
  25. package/lib/node.d.ts +50 -0
  26. package/lib/react-native.d.ts +31 -0
  27. package/lib/rndash.rn.js +267 -0
  28. package/lib/rndash.rn.js.map +1 -0
  29. package/lib/src/node.js +328 -0
  30. package/lib/src/node.js.map +1 -0
  31. package/lib/types.d.ts +73 -0
  32. package/node.d.ts +1 -0
  33. package/node.js +2 -0
  34. package/package.json +105 -0
  35. package/prebuilds/darwin-arm64/dashshielded.node +0 -0
  36. package/rust/Cargo.lock +6795 -0
  37. package/rust/Cargo.toml +63 -0
  38. package/rust/build.rs +7 -0
  39. package/rust/rust-toolchain.toml +3 -0
  40. package/rust/src/dash.udl +90 -0
  41. package/rust/src/lib.rs +16 -0
  42. package/rust/src/napi_api.rs +164 -0
  43. package/rust/src/uniffi_api.rs +116 -0
  44. package/rust/src/wallet.rs +888 -0
  45. package/rust/uniffi-bindgen.rs +3 -0
  46. package/src/load-addon.ts +99 -0
  47. package/src/node.ts +248 -0
  48. package/src/react-native.ts +212 -0
  49. package/src/types.ts +88 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # dash-shielded-native
2
+
3
+ ## 0.1.0 (2026-08-31)
4
+
5
+ - Initial Node N-API + React Native UniFFI package for Dash Platform shielded addresses and transfers.
package/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Airbitz, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ This package wraps the Dash Platform wallet crates, which are MIT, and ships
26
+ binaries compiled from them. The Rust dependencies they pull in remain under
27
+ their own licenses.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # dash-shielded-native
2
+
3
+ Native Dash Platform shielded-pool wallet library for React Native and Node.js.
4
+
5
+ One package serves both hosts, matching `monero-native` / `zcash-native` / `zano-native`:
6
+
7
+ | Export | Backend |
8
+ |--------|---------|
9
+ | `dash-shielded-native` / `./rn` | UniFFI iOS + Android |
10
+ | `dash-shielded-native/node` | N-API (`makeNodeDashShieldedModule`) |
11
+
12
+ v1 covers keys, `dash1z` / `tdash1z` addresses, sync stubs, and `ShieldedTransfer` proposal/create. Create currently requires `rs-platform-wallet` DAPI bindings before a live testnet send.
13
+
14
+ ```ts
15
+ import { makeNodeDashShieldedModule } from 'dash-shielded-native/node'
16
+
17
+ const io = makeNodeDashShieldedModule({ documentDirectory })
18
+ const keys = await io.Tools.deriveViewingKey(mnemonic, 'testnet')
19
+ const synchronizer = await io.makeSynchronizer({
20
+ mnemonicSeed: mnemonic,
21
+ account: 0,
22
+ alias: 'wallet',
23
+ network: 'testnet',
24
+ dataDir: documentDirectory,
25
+ defaultHost: 'seed-1.testnet.networks.dash.org',
26
+ defaultPort: 1443
27
+ })
28
+ ```
29
+
30
+ Host build:
31
+
32
+ ```bash
33
+ socket npm install
34
+ socket npm run build-native-host
35
+ socket npm run smoke-node
36
+ ```
@@ -0,0 +1,56 @@
1
+ buildscript {
2
+ def kotlinVersion = rootProject.ext.has('kotlinVersion')
3
+ ? rootProject.ext.get('kotlinVersion')
4
+ : '2.1.10'
5
+
6
+ repositories {
7
+ mavenCentral()
8
+ google()
9
+ }
10
+ dependencies {
11
+ classpath 'com.android.tools.build:gradle:8.5.0'
12
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
13
+ }
14
+ }
15
+
16
+ apply plugin: 'com.android.library'
17
+ apply plugin: 'kotlin-android'
18
+
19
+ def safeExtGet(prop, fallback) {
20
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
21
+ }
22
+
23
+ android {
24
+ compileSdkVersion safeExtGet('compileSdkVersion', 35)
25
+ defaultConfig {
26
+ minSdkVersion safeExtGet('minSdkVersion', 27)
27
+ targetSdkVersion safeExtGet('targetSdkVersion', 35)
28
+ ndk {
29
+ abiFilters 'arm64-v8a'
30
+ }
31
+ }
32
+ sourceSets {
33
+ main {
34
+ jniLibs.srcDirs = ['src/main/jniLibs']
35
+ }
36
+ }
37
+ lintOptions {
38
+ abortOnError false
39
+ }
40
+ namespace 'app.edge.rndashshielded'
41
+ }
42
+
43
+ repositories {
44
+ maven {
45
+ url('../node_modules/react-native/android')
46
+ }
47
+ google()
48
+ mavenCentral()
49
+ }
50
+
51
+ dependencies {
52
+ implementation 'com.facebook.react:react-native:+'
53
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
54
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"
55
+ implementation 'net.java.dev.jna:jna:5.17.0@aar'
56
+ }
@@ -0,0 +1 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android" />
@@ -0,0 +1,215 @@
1
+ package app.edge.rndashshielded
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.WritableMap
9
+ import kotlinx.coroutines.CoroutineScope
10
+ import kotlinx.coroutines.Dispatchers
11
+ import kotlinx.coroutines.launch
12
+ import uniffi.dash.Poll
13
+ import java.io.File
14
+
15
+ class RNDashShieldedModule(
16
+ private val reactContext: ReactApplicationContext,
17
+ ) : ReactContextBaseJavaModule(reactContext) {
18
+ private val moduleScope: CoroutineScope = CoroutineScope(Dispatchers.IO)
19
+
20
+ override fun getName() = "RNDashShielded"
21
+
22
+ @Volatile private var documentDirReady = false
23
+
24
+ init {
25
+ System.setProperty("uniffi.component.dash.libraryOverride", "dashshielded")
26
+ }
27
+
28
+ private fun ensureDocumentDirectory() {
29
+ if (documentDirReady) return
30
+ synchronized(this) {
31
+ if (documentDirReady) return
32
+ val dir = File(reactContext.filesDir, "native/dashshielded")
33
+ dir.mkdirs()
34
+ uniffi.dash.setDocumentDirectory(dir.absolutePath)
35
+ documentDirReady = true
36
+ }
37
+ }
38
+
39
+ private inline fun Promise.wrap(block: () -> Any?) {
40
+ try {
41
+ ensureDocumentDirectory()
42
+ resolve(block())
43
+ } catch (t: Throwable) {
44
+ reject("Err", t)
45
+ }
46
+ }
47
+
48
+ private fun pollMap(snap: Poll): WritableMap {
49
+ val transactions = Arguments.createArray()
50
+ snap.transactions.forEach { tx ->
51
+ val map = Arguments.createMap()
52
+ map.putString("txid", tx.txid)
53
+ map.putInt("blockTimeInSeconds", tx.blockTimeInSeconds.toInt())
54
+ map.putInt("minedHeight", tx.minedHeight.toInt())
55
+ map.putString("value", tx.value)
56
+ tx.fee?.let { map.putString("fee", it) }
57
+ tx.toAddress?.let { map.putString("toAddress", it) }
58
+ map.putArray("memos", Arguments.fromList(tx.memos))
59
+ transactions.pushMap(map)
60
+ }
61
+
62
+ val out = Arguments.createMap()
63
+ out.putString("alias", snap.alias)
64
+ out.putString("status", snap.status)
65
+ out.putDouble("scanProgress", snap.scanProgress)
66
+ out.putInt("networkBlockHeight", snap.networkBlockHeight.toInt())
67
+ out.putString("availableCredits", snap.availableCredits)
68
+ out.putString("totalCredits", snap.totalCredits)
69
+ out.putArray("transactions", transactions)
70
+ return out
71
+ }
72
+
73
+ @ReactMethod
74
+ fun initialize(
75
+ seed: String,
76
+ account: Int,
77
+ alias: String,
78
+ networkName: String,
79
+ defaultHost: String,
80
+ defaultPort: Int,
81
+ promise: Promise,
82
+ ) {
83
+ moduleScope.launch {
84
+ promise.wrap {
85
+ uniffi.dash.initialize(
86
+ seed,
87
+ account.toUInt(),
88
+ alias,
89
+ networkName,
90
+ defaultHost,
91
+ defaultPort.toUInt(),
92
+ )
93
+ null
94
+ }
95
+ }
96
+ }
97
+
98
+ @ReactMethod
99
+ fun stop(alias: String, promise: Promise) {
100
+ moduleScope.launch {
101
+ promise.wrap { uniffi.dash.stop(alias) }
102
+ }
103
+ }
104
+
105
+ @ReactMethod
106
+ fun startSync(alias: String, promise: Promise) {
107
+ moduleScope.launch {
108
+ promise.wrap {
109
+ uniffi.dash.startSync(alias)
110
+ null
111
+ }
112
+ }
113
+ }
114
+
115
+ @ReactMethod
116
+ fun stopSync(alias: String, promise: Promise) {
117
+ moduleScope.launch {
118
+ promise.wrap {
119
+ uniffi.dash.stopSync(alias)
120
+ null
121
+ }
122
+ }
123
+ }
124
+
125
+ @ReactMethod
126
+ fun deriveShieldedAddress(alias: String, promise: Promise) {
127
+ moduleScope.launch {
128
+ promise.wrap {
129
+ val addresses = uniffi.dash.deriveShieldedAddress(alias)
130
+ val map = Arguments.createMap()
131
+ map.putString("shieldedAddress", addresses.shieldedAddress)
132
+ map
133
+ }
134
+ }
135
+ }
136
+
137
+ @ReactMethod
138
+ fun deriveShieldedAddressFromSeed(
139
+ seed: String,
140
+ network: String,
141
+ account: Int,
142
+ promise: Promise,
143
+ ) {
144
+ moduleScope.launch {
145
+ promise.wrap {
146
+ uniffi.dash.deriveShieldedAddressFromSeed(seed, network, account.toUInt())
147
+ }
148
+ }
149
+ }
150
+
151
+ @ReactMethod
152
+ fun isValidAddress(address: String, network: String, promise: Promise) {
153
+ moduleScope.launch {
154
+ promise.wrap { uniffi.dash.isValidAddress(address, network) }
155
+ }
156
+ }
157
+
158
+ @ReactMethod
159
+ fun deriveViewingKey(seed: String, network: String, promise: Promise) {
160
+ moduleScope.launch {
161
+ promise.wrap { uniffi.dash.deriveViewingKey(seed, network) }
162
+ }
163
+ }
164
+
165
+ @ReactMethod
166
+ fun warmUpProver(promise: Promise) {
167
+ moduleScope.launch {
168
+ promise.wrap {
169
+ uniffi.dash.warmUpProver()
170
+ null
171
+ }
172
+ }
173
+ }
174
+
175
+ @ReactMethod
176
+ fun isProverReady(promise: Promise) {
177
+ moduleScope.launch {
178
+ promise.wrap { uniffi.dash.isProverReady() }
179
+ }
180
+ }
181
+
182
+ @ReactMethod
183
+ fun poll(alias: String, promise: Promise) {
184
+ moduleScope.launch {
185
+ promise.wrap { pollMap(uniffi.dash.poll(alias)) }
186
+ }
187
+ }
188
+
189
+ @ReactMethod
190
+ fun proposeTransfer(
191
+ alias: String,
192
+ amountCredits: String,
193
+ toAddress: String,
194
+ memo: String?,
195
+ promise: Promise,
196
+ ) {
197
+ moduleScope.launch {
198
+ promise.wrap {
199
+ uniffi.dash.proposeTransfer(alias, amountCredits, toAddress, memo)
200
+ }
201
+ }
202
+ }
203
+
204
+ @ReactMethod
205
+ fun createTransfer(
206
+ alias: String,
207
+ proposalId: String,
208
+ seed: String,
209
+ promise: Promise,
210
+ ) {
211
+ moduleScope.launch {
212
+ promise.wrap { uniffi.dash.createTransfer(alias, proposalId, seed) }
213
+ }
214
+ }
215
+ }
@@ -0,0 +1,16 @@
1
+ package app.edge.rndashshielded
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
+ import java.util.Collections.emptyList
8
+
9
+ class RNDashShieldedPackage : ReactPackage {
10
+ override fun createNativeModules(reactContext: ReactApplicationContext) =
11
+ listOf<NativeModule>(
12
+ RNDashShieldedModule(reactContext),
13
+ )
14
+
15
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = emptyList()
16
+ }