react-native-zcash 0.6.0 → 0.6.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # React Native Zcash
2
2
 
3
+ ## 0.6.1 (2023-10-11)
4
+
5
+ - added: Add `shieldFunds` support
6
+ - changed: Package now exports types
7
+ - deprecated: Balance event fields `availableZatoshi` and `totalZatoshi`
8
+
9
+ Android
10
+
11
+ - changed: Various syntax cleanups
12
+ - fixed: Transactions event now returns confirmed and pending (<10 confirmations) transactions
13
+
3
14
  ## 0.6.0 (2023-10-10)
4
15
 
5
16
  - added: Balances and transactions are no longer queryable and are now emitted as updates are found
package/README.md CHANGED
@@ -42,11 +42,12 @@ buildscript {
42
42
  - `rescan`
43
43
  - `getLatestNetworkHeight`
44
44
  - `sendToAddress`
45
+ - `shieldFunds`
45
46
  - `deriveUnifiedAddress`
46
47
 
47
48
  `Tools` contains methods that don't require a running synchronizer (with one exception, `isValidAddress` on Android which does requires any synchronizer connected to the requested network). In addition to the methods above, the following events can be subscribed to:
48
49
 
49
- - `BalanceEvent`- aggregate total and available balances
50
+ - `BalanceEvent`- available and total transparent and shielded balances
50
51
  - `StatusEvent` - current synchronizer activity (`STOPPED`, `DISCONNECTED`, `SYNCING`, and `SYNCED`)
51
52
  - `TransactionEvent`- confirmed transactions
52
53
  - `UpdateEvent` - syncing progress and network height
@@ -15,16 +15,14 @@ import co.electriccoin.lightwallet.client.model.Response
15
15
  import co.electriccoin.lightwallet.client.new
16
16
  import com.facebook.react.bridge.*
17
17
  import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter
18
- import kotlinx.coroutines.async
19
18
  import kotlinx.coroutines.CoroutineScope
20
19
  import kotlinx.coroutines.Dispatchers
21
- import kotlinx.coroutines.ExperimentalCoroutinesApi
20
+ import kotlinx.coroutines.async
22
21
  import kotlinx.coroutines.flow.*
23
22
  import kotlinx.coroutines.launch
24
23
 
25
24
  class RNZcashModule(private val reactContext: ReactApplicationContext) :
26
25
  ReactContextBaseJavaModule(reactContext) {
27
-
28
26
  /**
29
27
  * Scope for anything that out-lives the synchronizer, meaning anything that can be used before
30
28
  * the synchronizer starts or after it stops. Everything else falls within the scope of the
@@ -38,144 +36,176 @@ class RNZcashModule(private val reactContext: ReactApplicationContext) :
38
36
  override fun getName() = "RNZcash"
39
37
 
40
38
  @ReactMethod
41
- fun initialize(seed: String, birthdayHeight: Int, alias: String, networkName: String = "mainnet", defaultHost: String = "mainnet.lightwalletd.com", defaultPort: Int = 9067, newWallet: Boolean, promise: Promise) =
42
- moduleScope.launch {
43
- promise.wrap {
44
- val network = networks.getOrDefault(networkName, ZcashNetwork.Mainnet)
45
- val endpoint = LightWalletEndpoint(defaultHost, defaultPort, true)
46
- val seedPhrase = SeedPhrase.new(seed)
47
- val initMode = if (newWallet) WalletInitMode.NewWallet else WalletInitMode.ExistingWallet
48
- if (!synchronizerMap.containsKey(alias)) {
49
- synchronizerMap[alias] = Synchronizer.new(reactApplicationContext, network, alias, endpoint, seedPhrase.toByteArray(), BlockHeight.new(network, birthdayHeight.toLong()), initMode) as SdkSynchronizer
50
- }
51
- val wallet = getWallet(alias)
52
- val scope = wallet.coroutineScope
53
- combine(wallet.progress, wallet.networkHeight) { progress, networkHeight ->
54
- return@combine mapOf("progress" to progress, "networkHeight" to networkHeight)
55
- }.collectWith(scope) { map ->
56
- val progress = map["progress"] as PercentDecimal
57
- var networkBlockHeight = map["networkHeight"] as BlockHeight?
58
- if (networkBlockHeight == null) networkBlockHeight = BlockHeight.new(wallet.network, birthdayHeight.toLong())
39
+ fun initialize(
40
+ seed: String,
41
+ birthdayHeight: Int,
42
+ alias: String,
43
+ networkName: String = "mainnet",
44
+ defaultHost: String = "mainnet.lightwalletd.com",
45
+ defaultPort: Int = 9067,
46
+ newWallet: Boolean,
47
+ promise: Promise,
48
+ ) = moduleScope.launch {
49
+ promise.wrap {
50
+ val network = networks.getOrDefault(networkName, ZcashNetwork.Mainnet)
51
+ val endpoint = LightWalletEndpoint(defaultHost, defaultPort, true)
52
+ val seedPhrase = SeedPhrase.new(seed)
53
+ val initMode = if (newWallet) WalletInitMode.NewWallet else WalletInitMode.ExistingWallet
54
+ if (!synchronizerMap.containsKey(alias)) {
55
+ synchronizerMap[alias] =
56
+ Synchronizer.new(
57
+ reactApplicationContext, network, alias, endpoint, seedPhrase.toByteArray(),
58
+ BlockHeight.new(network, birthdayHeight.toLong()), initMode,
59
+ ) as SdkSynchronizer
60
+ }
61
+ val wallet = getWallet(alias)
62
+ val scope = wallet.coroutineScope
63
+ combine(wallet.progress, wallet.networkHeight) { progress, networkHeight ->
64
+ return@combine mapOf("progress" to progress, "networkHeight" to networkHeight)
65
+ }.collectWith(scope) { map ->
66
+ val progress = map["progress"] as PercentDecimal
67
+ var networkBlockHeight = map["networkHeight"] as BlockHeight?
68
+ if (networkBlockHeight == null) networkBlockHeight = BlockHeight.new(wallet.network, birthdayHeight.toLong())
59
69
 
60
- sendEvent("UpdateEvent") { args ->
61
- args.putString("alias", alias)
62
- args.putInt(
63
- "scanProgress",
64
- progress.toPercentage()
65
- )
66
- args.putInt("networkBlockHeight", networkBlockHeight.value.toInt())
67
- }
70
+ sendEvent("UpdateEvent") { args ->
71
+ args.putString("alias", alias)
72
+ args.putInt(
73
+ "scanProgress",
74
+ progress.toPercentage(),
75
+ )
76
+ args.putInt("networkBlockHeight", networkBlockHeight.value.toInt())
68
77
  }
69
- wallet.status.collectWith(scope) { status ->
70
- sendEvent("StatusEvent") { args ->
71
- args.putString("alias", alias)
72
- args.putString("name", status.toString())
73
- }
78
+ }
79
+ wallet.status.collectWith(scope) { status ->
80
+ sendEvent("StatusEvent") { args ->
81
+ args.putString("alias", alias)
82
+ args.putString("name", status.toString())
74
83
  }
75
- wallet.transactions.collectWith(scope) { txList ->
76
- scope.launch {
77
- val nativeArray = Arguments.createArray()
78
- txList.filter { tx -> tx.transactionState == TransactionState.Confirmed }.map { tx -> launch {
84
+ }
85
+ wallet.transactions.collectWith(scope) { txList ->
86
+ scope.launch {
87
+ val nativeArray = Arguments.createArray()
88
+ txList.filter { tx -> tx.transactionState != TransactionState.Expired }.map { tx ->
89
+ launch {
79
90
  val parsedTx = parseTx(wallet, tx)
80
91
  nativeArray.pushMap(parsedTx)
81
- } }.forEach { it.join() }
82
-
83
- sendEvent("TransactionEvent") { args ->
84
- args.putString("alias", alias)
85
- args.putArray(
86
- "transactions",
87
- nativeArray
88
- )
89
92
  }
93
+ }.forEach { it.join() }
94
+
95
+ sendEvent("TransactionEvent") { args ->
96
+ args.putString("alias", alias)
97
+ args.putArray(
98
+ "transactions",
99
+ nativeArray,
100
+ )
90
101
  }
91
102
  }
92
- combine(wallet.transparentBalances, wallet.saplingBalances, wallet.orchardBalances) { transparentBalances, saplingBalances, orchardBalances ->
93
- return@combine mapOf("transparentBalances" to transparentBalances, "saplingBalances" to saplingBalances, "orchardBalances" to orchardBalances)
94
- }.collectWith(scope) { map ->
95
- val transparentBalances = map["transparentBalances"]
96
- val saplingBalances = map["saplingBalances"]
97
- val orchardBalances = map["orchardBalances"]
98
-
99
- var availableZatoshi = Zatoshi(0L)
100
- var totalZatoshi = Zatoshi(0L)
101
-
102
- availableZatoshi = availableZatoshi.plus(transparentBalances?.available ?: Zatoshi(0L))
103
- totalZatoshi = totalZatoshi.plus(transparentBalances?.total ?: Zatoshi(0L))
103
+ }
104
+ combine(
105
+ wallet.transparentBalances,
106
+ wallet.saplingBalances,
107
+ ) { transparentBalances, saplingBalances ->
108
+ return@combine mapOf(
109
+ "transparentBalances" to transparentBalances,
110
+ "saplingBalances" to saplingBalances,
111
+ )
112
+ }.collectWith(scope) { map ->
113
+ val transparentBalances = map["transparentBalances"]
114
+ val saplingBalances = map["saplingBalances"]
104
115
 
105
- availableZatoshi = availableZatoshi.plus(saplingBalances?.available ?: Zatoshi(0L))
106
- totalZatoshi = totalZatoshi.plus(saplingBalances?.total ?: Zatoshi(0L))
116
+ val transparentAvailableZatoshi = transparentBalances?.available ?: Zatoshi(0L)
117
+ val transparentTotalZatoshi = transparentBalances?.total ?: Zatoshi(0L)
107
118
 
108
- availableZatoshi = availableZatoshi.plus(orchardBalances?.available ?: Zatoshi(0L))
109
- totalZatoshi = totalZatoshi.plus(orchardBalances?.total ?: Zatoshi(0L))
119
+ val saplingAvailableZatoshi = saplingBalances?.available ?: Zatoshi(0L)
120
+ val saplingTotalZatoshi = saplingBalances?.total ?: Zatoshi(0L)
110
121
 
111
- sendEvent("BalanceEvent") { args ->
112
- args.putString("alias", alias)
113
- args.putString(
114
- "totalZatoshi",
115
- totalZatoshi.value.toString()
116
- )
117
- args.putString(
118
- "availableZatoshi",
119
- availableZatoshi.value.toString()
120
- )
121
- }
122
+ sendEvent("BalanceEvent") { args ->
123
+ args.putString("alias", alias)
124
+ args.putString("transparentAvailableZatoshi", transparentAvailableZatoshi.value.toString())
125
+ args.putString("transparentTotalZatoshi", transparentTotalZatoshi.value.toString())
126
+ args.putString("saplingAvailableZatoshi", saplingAvailableZatoshi.value.toString())
127
+ args.putString("saplingTotalZatoshi", saplingTotalZatoshi.value.toString())
122
128
  }
123
- return@wrap null
124
129
  }
130
+ return@wrap null
125
131
  }
132
+ }
126
133
 
127
134
  @ReactMethod
128
- fun stop(alias: String, promise: Promise) {
135
+ fun stop(
136
+ alias: String,
137
+ promise: Promise,
138
+ ) {
129
139
  val wallet = getWallet(alias)
130
140
  wallet.close()
131
141
  synchronizerMap.remove(alias)
132
142
  promise.resolve(null)
133
143
  }
134
144
 
135
- private suspend fun parseTx(wallet: SdkSynchronizer, tx: TransactionOverview): WritableMap {
145
+ private suspend fun parseTx(
146
+ wallet: SdkSynchronizer,
147
+ tx: TransactionOverview,
148
+ ): WritableMap {
136
149
  val map = Arguments.createMap()
137
- val job = wallet.coroutineScope.launch {
138
- map.putString("value", tx.netValue.value.toString())
139
- if (tx.feePaid != null) {
140
- map.putString("fee", tx.feePaid!!.value.toString())
141
- }
142
- map.putInt("minedHeight", tx.minedHeight!!.value.toInt())
143
- map.putInt("blockTimeInSeconds", tx.blockTimeEpochSeconds!!.toInt())
144
- map.putString("rawTransactionId", tx.rawId.byteArray.toHexReversed())
145
- if (tx.raw != null) {
146
- map.putString("raw", tx.raw!!.byteArray.toHex())
147
- }
148
- if (tx.isSentTransaction) {
149
- val recipient = wallet.getRecipients(tx).first()
150
- if (recipient is TransactionRecipient.Address) {
151
- map.putString("toAddress", recipient.addressValue)
150
+ val job =
151
+ wallet.coroutineScope.launch {
152
+ map.putString("value", tx.netValue.value.toString())
153
+ if (tx.feePaid != null) {
154
+ map.putString("fee", tx.feePaid!!.value.toString())
155
+ }
156
+ map.putInt("minedHeight", tx.minedHeight?.value?.toInt() ?: 0)
157
+ map.putInt("blockTimeInSeconds", tx.blockTimeEpochSeconds?.toInt() ?: 0)
158
+ map.putString("rawTransactionId", tx.rawId.byteArray.toHexReversed())
159
+ if (tx.raw != null) {
160
+ map.putString("raw", tx.raw!!.byteArray.toHex())
161
+ }
162
+ if (tx.isSentTransaction) {
163
+ try {
164
+ val recipient = wallet.getRecipients(tx).first()
165
+ if (recipient is TransactionRecipient.Address) {
166
+ map.putString("toAddress", recipient.addressValue)
167
+ }
168
+ } catch (t: Throwable) {
169
+ // Error is OK. SDK limitation means we cannot find recipient for shielding transactions
170
+ }
171
+ }
172
+ if (tx.memoCount > 0) {
173
+ val memos = wallet.getMemos(tx).take(tx.memoCount).toList()
174
+ map.putArray("memos", Arguments.fromList(memos))
175
+ } else {
176
+ map.putArray("memos", Arguments.createArray())
152
177
  }
153
178
  }
154
- if (tx.memoCount > 0) {
155
- val memos = wallet.getMemos(tx).take(tx.memoCount).toList()
156
- map.putArray("memos", Arguments.fromList(memos))
157
- } else {
158
- map.putArray("memos", Arguments.createArray())
159
- }
160
- }
161
179
  job.join()
162
180
  return map
163
181
  }
164
182
 
165
183
  @ReactMethod
166
- fun rescan(alias: String, promise: Promise) {
184
+ fun rescan(
185
+ alias: String,
186
+ promise: Promise,
187
+ ) {
167
188
  val wallet = getWallet(alias)
168
189
  wallet.coroutineScope.launch {
169
- wallet.coroutineScope.async { wallet.rewindToNearestHeight(wallet.latestBirthdayHeight) }.await()
190
+ wallet.rewindToNearestHeight(wallet.latestBirthdayHeight)
170
191
  promise.resolve(null)
171
192
  }
172
193
  }
173
194
 
174
195
  @ReactMethod
175
- fun deriveViewingKey(seed: String, network: String = "mainnet", promise: Promise) {
196
+ fun deriveViewingKey(
197
+ seed: String,
198
+ network: String = "mainnet",
199
+ promise: Promise,
200
+ ) {
176
201
  val seedPhrase = SeedPhrase.new(seed)
177
202
  moduleScope.launch {
178
- val keys = moduleScope.async { DerivationTool.getInstance().deriveUnifiedFullViewingKeys(seedPhrase.toByteArray(), networks.getOrDefault(network, ZcashNetwork.Mainnet), DerivationTool.DEFAULT_NUMBER_OF_ACCOUNTS)[0] }.await()
203
+ val keys =
204
+ DerivationTool.getInstance().deriveUnifiedFullViewingKeys(
205
+ seedPhrase.toByteArray(),
206
+ networks.getOrDefault(network, ZcashNetwork.Mainnet),
207
+ DerivationTool.DEFAULT_NUMBER_OF_ACCOUNTS,
208
+ )[0]
179
209
  promise.resolve(keys.encoding)
180
210
  }
181
211
  }
@@ -185,13 +215,20 @@ class RNZcashModule(private val reactContext: ReactApplicationContext) :
185
215
  //
186
216
 
187
217
  @ReactMethod
188
- fun getLatestNetworkHeight(alias: String, promise: Promise) = promise.wrap {
218
+ fun getLatestNetworkHeight(
219
+ alias: String,
220
+ promise: Promise,
221
+ ) = promise.wrap {
189
222
  val wallet = getWallet(alias)
190
223
  return@wrap wallet.latestHeight
191
224
  }
192
225
 
193
226
  @ReactMethod
194
- fun getBirthdayHeight(host: String, port: Int, promise: Promise) {
227
+ fun getBirthdayHeight(
228
+ host: String,
229
+ port: Int,
230
+ promise: Promise,
231
+ ) {
195
232
  moduleScope.launch {
196
233
  promise.wrap {
197
234
  val endpoint = LightWalletEndpoint(host, port, true)
@@ -213,7 +250,6 @@ class RNZcashModule(private val reactContext: ReactApplicationContext) :
213
250
  }
214
251
  }
215
252
 
216
- @OptIn(ExperimentalCoroutinesApi::class)
217
253
  @ReactMethod
218
254
  fun sendToAddress(
219
255
  alias: String,
@@ -226,14 +262,15 @@ class RNZcashModule(private val reactContext: ReactApplicationContext) :
226
262
  val wallet = getWallet(alias)
227
263
  wallet.coroutineScope.launch {
228
264
  val seedPhrase = SeedPhrase.new(seed)
229
- val usk = wallet.coroutineScope.async { DerivationTool.getInstance().deriveUnifiedSpendingKey(seedPhrase.toByteArray(), wallet.network, Account.DEFAULT) }.await()
265
+ val usk = DerivationTool.getInstance().deriveUnifiedSpendingKey(seedPhrase.toByteArray(), wallet.network, Account.DEFAULT)
230
266
  try {
231
- val internalId = wallet.sendToAddress(
232
- usk,
233
- Zatoshi(zatoshi.toLong()),
234
- toAddress,
235
- memo,
236
- )
267
+ val internalId =
268
+ wallet.sendToAddress(
269
+ usk,
270
+ Zatoshi(zatoshi.toLong()),
271
+ toAddress,
272
+ memo,
273
+ )
237
274
  val tx = wallet.coroutineScope.async { wallet.transactions.first().first() }.await()
238
275
  val map = Arguments.createMap()
239
276
  map.putString("txId", tx.rawId.byteArray.toHexReversed())
@@ -245,28 +282,67 @@ class RNZcashModule(private val reactContext: ReactApplicationContext) :
245
282
  }
246
283
  }
247
284
 
285
+ @ReactMethod
286
+ fun shieldFunds(
287
+ alias: String,
288
+ seed: String,
289
+ memo: String,
290
+ threshold: String,
291
+ promise: Promise,
292
+ ) {
293
+ val wallet = getWallet(alias)
294
+ wallet.coroutineScope.launch {
295
+ val seedPhrase = SeedPhrase.new(seed)
296
+ val usk = DerivationTool.getInstance().deriveUnifiedSpendingKey(seedPhrase.toByteArray(), wallet.network, Account.DEFAULT)
297
+ try {
298
+ val internalId =
299
+ wallet.shieldFunds(
300
+ usk,
301
+ memo,
302
+ )
303
+ val tx = wallet.coroutineScope.async { wallet.transactions.first().first() }.await()
304
+ val parsedTx = parseTx(wallet, tx)
305
+
306
+ // Hack: Memos aren't ready to be queried right after broadcast
307
+ val memos = Arguments.createArray()
308
+ memos.pushString(memo)
309
+ parsedTx.putArray("memos", memos)
310
+ promise.resolve(parsedTx)
311
+ } catch (t: Throwable) {
312
+ promise.reject("Err", t)
313
+ }
314
+ }
315
+ }
316
+
248
317
  //
249
318
  // AddressTool
250
319
  //
251
320
 
252
321
  @ReactMethod
253
- fun deriveUnifiedAddress(alias: String, promise: Promise) {
322
+ fun deriveUnifiedAddress(
323
+ alias: String,
324
+ promise: Promise,
325
+ ) {
254
326
  val wallet = getWallet(alias)
255
327
  wallet.coroutineScope.launch {
256
- val unifiedAddress = wallet.coroutineScope.async { wallet.getUnifiedAddress(Account(0)) }.await()
257
- val saplingAddress = wallet.coroutineScope.async { wallet.getSaplingAddress(Account(0)) }.await()
258
- val transparentAddress = wallet.coroutineScope.async { wallet.getTransparentAddress(Account(0)) }.await()
328
+ val unifiedAddress = wallet.getUnifiedAddress(Account(0))
329
+ val saplingAddress = wallet.getSaplingAddress(Account(0))
330
+ val transparentAddress = wallet.getTransparentAddress(Account(0))
259
331
 
260
- val map = Arguments.createMap()
261
- map.putString("unifiedAddress", unifiedAddress)
262
- map.putString("saplingAddress", saplingAddress)
263
- map.putString("transparentAddress", transparentAddress)
264
- promise.resolve(map)
332
+ val map = Arguments.createMap()
333
+ map.putString("unifiedAddress", unifiedAddress)
334
+ map.putString("saplingAddress", saplingAddress)
335
+ map.putString("transparentAddress", transparentAddress)
336
+ promise.resolve(map)
265
337
  }
266
338
  }
267
339
 
268
340
  @ReactMethod
269
- fun isValidAddress(address: String, network: String, promise: Promise) {
341
+ fun isValidAddress(
342
+ address: String,
343
+ network: String,
344
+ promise: Promise,
345
+ ) {
270
346
  moduleScope.launch {
271
347
  promise.wrap {
272
348
  var isValid = false
@@ -304,7 +380,10 @@ class RNZcashModule(private val reactContext: ReactApplicationContext) :
304
380
  }
305
381
  }
306
382
 
307
- private fun sendEvent(eventName: String, putArgs: (WritableMap) -> Unit) {
383
+ private fun sendEvent(
384
+ eventName: String,
385
+ putArgs: (WritableMap) -> Unit,
386
+ ) {
308
387
  val args = Arguments.createMap()
309
388
  putArgs(args)
310
389
  reactApplicationContext
@@ -12,6 +12,5 @@ class RNZcashPackage : ReactPackage {
12
12
  RNZcashModule(reactContext),
13
13
  )
14
14
 
15
- override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> =
16
- emptyList()
15
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = emptyList()
17
16
  }
package/ios/RNZcash.m CHANGED
@@ -45,6 +45,14 @@ resolver:(RCTPromiseResolveBlock)resolve
45
45
  rejecter:(RCTPromiseRejectBlock)reject
46
46
  )
47
47
 
48
+ RCT_EXTERN_METHOD(shieldFunds:(NSString *)alias
49
+ :(NSString *)seed
50
+ :(NSString *)memo
51
+ :(NSString *)threshold
52
+ resolver:(RCTPromiseResolveBlock)resolve
53
+ rejecter:(RCTPromiseRejectBlock)reject
54
+ )
55
+
48
56
  RCT_EXTERN_METHOD(rescan:(NSString *)alias
49
57
  resolver:(RCTPromiseResolveBlock)resolve
50
58
  rejecter:(RCTPromiseRejectBlock)reject
package/ios/RNZcash.swift CHANGED
@@ -13,7 +13,7 @@ struct ConfirmedTx {
13
13
  var blockTimeInSeconds: Int
14
14
  var value: String
15
15
  var fee: String?
16
- var memos: Array<String>?
16
+ var memos: [String]?
17
17
  var dictionary: [String: Any?] {
18
18
  return [
19
19
  "minedHeight": minedHeight,
@@ -32,12 +32,16 @@ struct ConfirmedTx {
32
32
  }
33
33
 
34
34
  struct TotalBalances {
35
- var availableZatoshi: String
36
- var totalZatoshi: String
35
+ var transparentAvailableZatoshi: Zatoshi
36
+ var transparentTotalZatoshi: Zatoshi
37
+ var saplingAvailableZatoshi: Zatoshi
38
+ var saplingTotalZatoshi: Zatoshi
37
39
  var dictionary: [String: Any] {
38
40
  return [
39
- "availableZatoshi": availableZatoshi,
40
- "totalZatoshi": totalZatoshi,
41
+ "transparentAvailableZatoshi": String(transparentAvailableZatoshi.amount),
42
+ "transparentTotalZatoshi": String(transparentTotalZatoshi.amount),
43
+ "saplingAvailableZatoshi": String(saplingAvailableZatoshi.amount),
44
+ "saplingTotalZatoshi": String(saplingTotalZatoshi.amount),
41
45
  ]
42
46
  }
43
47
  var nsDictionary: NSDictionary {
@@ -81,7 +85,8 @@ class RNZcash: RCTEventEmitter {
81
85
  // Synchronizer
82
86
  @objc func initialize(
83
87
  _ seed: String, _ birthdayHeight: Int, _ alias: String, _ networkName: String,
84
- _ defaultHost: String, _ defaultPort: Int, _ newWallet: Bool, resolver resolve: @escaping RCTPromiseResolveBlock,
88
+ _ defaultHost: String, _ defaultPort: Int, _ newWallet: Bool,
89
+ resolver resolve: @escaping RCTPromiseResolveBlock,
85
90
  rejecter reject: @escaping RCTPromiseRejectBlock
86
91
  ) {
87
92
  Task {
@@ -234,6 +239,43 @@ class RNZcash: RCTEventEmitter {
234
239
  }
235
240
  }
236
241
 
242
+ @objc func shieldFunds(
243
+ _ alias: String, _ seed: String, _ memo: String, _ threshold: String,
244
+ resolver resolve: @escaping RCTPromiseResolveBlock,
245
+ rejecter reject: @escaping RCTPromiseRejectBlock
246
+ ) {
247
+ Task {
248
+ if let wallet = SynchronizerMap[alias] {
249
+ if !wallet.fullySynced {
250
+ reject("shieldFunds", "Wallet is not synced", genericError)
251
+ return
252
+ }
253
+
254
+ do {
255
+ let spendingKey = try deriveUnifiedSpendingKey(seed, wallet.synchronizer.network)
256
+ let sdkMemo = try Memo(string: memo)
257
+ let shieldingThreshold = Int64(threshold) ?? 10000
258
+
259
+ let tx = try await wallet.synchronizer.shieldFunds(
260
+ spendingKey: spendingKey,
261
+ memo: sdkMemo,
262
+ shieldingThreshold: Zatoshi(shieldingThreshold)
263
+ )
264
+
265
+ var confTx = await wallet.parseTx(tx: tx)
266
+
267
+ // Hack: Memos aren't ready to be queried right after broadcast
268
+ confTx.memos = [memo]
269
+ resolve(confTx.nsDictionary)
270
+ } catch {
271
+ reject("shieldFunds", "Failed to shield funds", genericError)
272
+ }
273
+ } else {
274
+ reject("shieldFunds", "Wallet does not exist", genericError)
275
+ }
276
+ }
277
+ }
278
+
237
279
  @objc func rescan(
238
280
  _ alias: String, resolver resolve: @escaping RCTPromiseResolveBlock,
239
281
  rejecter reject: @escaping RCTPromiseRejectBlock
@@ -315,11 +357,12 @@ class RNZcash: RCTEventEmitter {
315
357
  do {
316
358
  let unifiedAddress = try await wallet.synchronizer.getUnifiedAddress(accountIndex: 0)
317
359
  let saplingAddress = try await wallet.synchronizer.getSaplingAddress(accountIndex: 0)
318
- let transparentAddress = try await wallet.synchronizer.getTransparentAddress(accountIndex: 0)
360
+ let transparentAddress = try await wallet.synchronizer.getTransparentAddress(
361
+ accountIndex: 0)
319
362
  let addresses: NSDictionary = [
320
363
  "unifiedAddress": unifiedAddress.stringEncoded,
321
364
  "saplingAddress": saplingAddress.stringEncoded,
322
- "transparentAddress": transparentAddress.stringEncoded
365
+ "transparentAddress": transparentAddress.stringEncoded,
323
366
  ]
324
367
  resolve(addresses)
325
368
  return
@@ -379,7 +422,11 @@ class WalletSynchronizer: NSObject {
379
422
  scanProgress: 0,
380
423
  networkBlockHeight: 0
381
424
  )
382
- self.balances = TotalBalances(availableZatoshi: "0", totalZatoshi: "0")
425
+ self.balances = TotalBalances(
426
+ transparentAvailableZatoshi: Zatoshi(0),
427
+ transparentTotalZatoshi: Zatoshi(0),
428
+ saplingAvailableZatoshi: Zatoshi(0),
429
+ saplingTotalZatoshi: Zatoshi(0))
383
430
  }
384
431
 
385
432
  public func subscribe() {
@@ -393,19 +440,19 @@ class WalletSynchronizer: NSObject {
393
440
  self.synchronizer.eventStream
394
441
  .sink { SynchronizerEvent in
395
442
  switch SynchronizerEvent {
396
- case .minedTransaction(let transaction):
397
- self.emitTxs(transactions: [transaction])
398
- case .foundTransactions(let transactions, _):
399
- self.emitTxs(transactions: transactions)
400
- default:
401
- return
402
- }
443
+ case .minedTransaction(let transaction):
444
+ self.emitTxs(transactions: [transaction])
445
+ case .foundTransactions(let transactions, _):
446
+ self.emitTxs(transactions: transactions)
447
+ default:
448
+ return
449
+ }
403
450
  }
404
451
  .store(in: &cancellables)
405
452
  }
406
453
 
407
454
  func updateSyncStatus(event: SynchronizerState) {
408
-
455
+
409
456
  if !self.fullySynced {
410
457
  switch event.internalSyncStatus {
411
458
  case .syncing:
@@ -441,10 +488,18 @@ class WalletSynchronizer: NSObject {
441
488
  return
442
489
  }
443
490
 
444
- if (scanProgress == self.processorState.scanProgress && event.latestBlockHeight == self.processorState.networkBlockHeight) { return }
491
+ if scanProgress == self.processorState.scanProgress
492
+ && event.latestBlockHeight == self.processorState.networkBlockHeight
493
+ {
494
+ return
495
+ }
445
496
 
446
- self.processorState = ProcessorState(scanProgress: scanProgress, networkBlockHeight: event.latestBlockHeight)
447
- let data: NSDictionary = ["alias": self.alias, "scanProgress": self.processorState.scanProgress, "networkBlockHeight": self.processorState.networkBlockHeight]
497
+ self.processorState = ProcessorState(
498
+ scanProgress: scanProgress, networkBlockHeight: event.latestBlockHeight)
499
+ let data: NSDictionary = [
500
+ "alias": self.alias, "scanProgress": self.processorState.scanProgress,
501
+ "networkBlockHeight": self.processorState.networkBlockHeight,
502
+ ]
448
503
  emit("UpdateEvent", data)
449
504
  updateBalanceState(event: event)
450
505
  }
@@ -454,68 +509,86 @@ class WalletSynchronizer: NSObject {
454
509
  scanProgress: 0,
455
510
  networkBlockHeight: 0
456
511
  )
457
- self.balances = TotalBalances(availableZatoshi: "0", totalZatoshi: "0")
512
+ self.balances = TotalBalances(
513
+ transparentAvailableZatoshi: Zatoshi(0),
514
+ transparentTotalZatoshi: Zatoshi(0),
515
+ saplingAvailableZatoshi: Zatoshi(0),
516
+ saplingTotalZatoshi: Zatoshi(0))
458
517
  }
459
518
 
460
519
  func updateBalanceState(event: SynchronizerState) {
461
520
  let transparentBalance = event.transparentBalance
462
521
  let shieldedBalance = event.shieldedBalance
463
522
 
464
- let availableTransparentBalance = transparentBalance.verified
465
- let totalTransparentBalance = transparentBalance.total
466
-
467
- let availableShieldedBalance = shieldedBalance.verified
468
- let totalShieldedBalance = shieldedBalance.total
523
+ let transparentAvailableZatoshi = transparentBalance.verified
524
+ let transparentTotalZatoshi = transparentBalance.total
469
525
 
470
- let availableZatoshi = String((availableShieldedBalance + availableTransparentBalance).amount)
471
- let totalZatoshi = String((totalShieldedBalance + totalTransparentBalance).amount)
526
+ let saplingAvailableZatoshi = shieldedBalance.verified
527
+ let saplingTotalZatoshi = shieldedBalance.total
472
528
 
473
- if (availableZatoshi == self.balances.availableZatoshi && totalZatoshi == self.balances.totalZatoshi) { return }
529
+ if transparentAvailableZatoshi == self.balances.transparentAvailableZatoshi
530
+ && transparentTotalZatoshi == self.balances.transparentTotalZatoshi
531
+ && saplingAvailableZatoshi == self.balances.saplingAvailableZatoshi
532
+ && saplingTotalZatoshi == self.balances.saplingTotalZatoshi
533
+ {
534
+ return
535
+ }
474
536
 
475
- self.balances = TotalBalances(availableZatoshi: availableZatoshi, totalZatoshi: totalZatoshi)
476
- let data: NSDictionary = ["alias": self.alias, "availableZatoshi": self.balances.availableZatoshi, "totalZatoshi": self.balances.totalZatoshi]
537
+ self.balances = TotalBalances(
538
+ transparentAvailableZatoshi: transparentAvailableZatoshi,
539
+ transparentTotalZatoshi: transparentTotalZatoshi,
540
+ saplingAvailableZatoshi: saplingAvailableZatoshi,
541
+ saplingTotalZatoshi: saplingTotalZatoshi
542
+ )
543
+ let data = NSMutableDictionary(dictionary: self.balances.nsDictionary)
544
+ data["alias"] = self.alias
477
545
  emit("BalanceEvent", data)
478
546
  }
479
547
 
548
+ func parseTx(tx: ZcashTransaction.Overview) async -> ConfirmedTx {
549
+ var confTx = ConfirmedTx(
550
+ minedHeight: tx.minedHeight ?? 0,
551
+ rawTransactionId: (tx.rawID.toHexStringTxId()),
552
+ blockTimeInSeconds: Int(tx.blockTime ?? 0),
553
+ value: String(describing: abs(tx.value.amount))
554
+ )
555
+ if tx.raw != nil {
556
+ confTx.raw = tx.raw!.hexEncodedString()
557
+ }
558
+ if tx.fee != nil {
559
+ confTx.fee = String(describing: abs(tx.value.amount))
560
+ }
561
+ if tx.isSentTransaction {
562
+ let recipients = await self.synchronizer.getRecipients(for: tx)
563
+ if recipients.count > 0 {
564
+ let addresses = recipients.compactMap {
565
+ if case let .address(address) = $0 {
566
+ return address
567
+ } else {
568
+ return nil
569
+ }
570
+ }
571
+ if addresses.count > 0 {
572
+ confTx.toAddress = addresses.first!.stringEncoded
573
+ }
574
+ }
575
+ }
576
+ if tx.memoCount > 0 {
577
+ let memos = (try? await self.synchronizer.getMemos(for: tx)) ?? []
578
+ let textMemos = memos.compactMap {
579
+ return $0.toString()
580
+ }
581
+ confTx.memos = textMemos
582
+ }
583
+ return confTx
584
+ }
585
+
480
586
  func emitTxs(transactions: [ZcashTransaction.Overview]) {
481
587
  Task {
482
588
  var out: [NSDictionary] = []
483
589
  for tx in transactions {
484
- if (tx.isExpiredUmined ?? false) { continue }
485
- var confTx = ConfirmedTx(
486
- minedHeight: tx.minedHeight!,
487
- rawTransactionId: (tx.rawID.toHexStringTxId()),
488
- blockTimeInSeconds: Int(tx.blockTime!),
489
- value: String(describing: abs(tx.value.amount))
490
- )
491
- if tx.raw != nil {
492
- confTx.raw = tx.raw!.hexEncodedString()
493
- }
494
- if tx.fee != nil {
495
- confTx.fee = String(describing: abs(tx.value.amount))
496
- }
497
- if tx.isSentTransaction {
498
- let recipients = await self.synchronizer.getRecipients(for: tx)
499
- if recipients.count > 0 {
500
- let addresses = recipients.compactMap {
501
- if case let .address(address) = $0 {
502
- return address
503
- } else {
504
- return nil
505
- }
506
- }
507
- if addresses.count > 0 {
508
- confTx.toAddress = addresses.first!.stringEncoded
509
- }
510
- }
511
- }
512
- if tx.memoCount > 0 {
513
- let memos = (try? await self.synchronizer.getMemos(for: tx)) ?? []
514
- let textMemos = memos.compactMap {
515
- return $0.toString()
516
- }
517
- confTx.memos = textMemos
518
- }
590
+ if tx.isExpiredUmined ?? false { continue }
591
+ let confTx = await parseTx(tx: tx)
519
592
  out.append(confTx.nsDictionary)
520
593
  }
521
594
 
@@ -8,32 +8,32 @@
8
8
  <key>BinaryPath</key>
9
9
  <string>libzcashlc.a</string>
10
10
  <key>LibraryIdentifier</key>
11
- <string>ios-arm64</string>
11
+ <string>ios-arm64_x86_64-simulator</string>
12
12
  <key>LibraryPath</key>
13
13
  <string>libzcashlc.a</string>
14
14
  <key>SupportedArchitectures</key>
15
15
  <array>
16
16
  <string>arm64</string>
17
+ <string>x86_64</string>
17
18
  </array>
18
19
  <key>SupportedPlatform</key>
19
20
  <string>ios</string>
21
+ <key>SupportedPlatformVariant</key>
22
+ <string>simulator</string>
20
23
  </dict>
21
24
  <dict>
22
25
  <key>BinaryPath</key>
23
26
  <string>libzcashlc.a</string>
24
27
  <key>LibraryIdentifier</key>
25
- <string>ios-arm64_x86_64-simulator</string>
28
+ <string>ios-arm64</string>
26
29
  <key>LibraryPath</key>
27
30
  <string>libzcashlc.a</string>
28
31
  <key>SupportedArchitectures</key>
29
32
  <array>
30
33
  <string>arm64</string>
31
- <string>x86_64</string>
32
34
  </array>
33
35
  <key>SupportedPlatform</key>
34
36
  <string>ios</string>
35
- <key>SupportedPlatformVariant</key>
36
- <string>simulator</string>
37
37
  </dict>
38
38
  </array>
39
39
  <key>CFBundlePackageType</key>
package/lib/rnzcash.rn.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var biggystring = require('biggystring');
5
6
  var reactNative = require('react-native');
6
7
 
7
8
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
@@ -160,6 +161,19 @@ var Synchronizer = /*#__PURE__*/function () {
160
161
  }
161
162
 
162
163
  return sendToAddress;
164
+ }();
165
+
166
+ _proto.shieldFunds = /*#__PURE__*/function () {
167
+ var _shieldFunds = _asyncToGenerator(function* (shieldFundsInfo) {
168
+ var result = yield RNZcash.shieldFunds(this.alias, shieldFundsInfo.seed, shieldFundsInfo.memo, shieldFundsInfo.threshold);
169
+ return result;
170
+ });
171
+
172
+ function shieldFunds(_x10) {
173
+ return _shieldFunds.apply(this, arguments);
174
+ }
175
+
176
+ return shieldFunds;
163
177
  }() // Events
164
178
  ;
165
179
 
@@ -168,7 +182,15 @@ var Synchronizer = /*#__PURE__*/function () {
168
182
  onStatusChanged = _ref.onStatusChanged,
169
183
  onTransactionsChanged = _ref.onTransactionsChanged,
170
184
  onUpdate = _ref.onUpdate;
171
- this.setListener('BalanceEvent', onBalanceChanged);
185
+ this.setListener('BalanceEvent', function (event) {
186
+ var transparentAvailableZatoshi = event.transparentAvailableZatoshi,
187
+ transparentTotalZatoshi = event.transparentTotalZatoshi,
188
+ saplingAvailableZatoshi = event.saplingAvailableZatoshi,
189
+ saplingTotalZatoshi = event.saplingTotalZatoshi;
190
+ event.availableZatoshi = biggystring.add(transparentAvailableZatoshi, saplingAvailableZatoshi);
191
+ event.totalZatoshi = biggystring.add(transparentTotalZatoshi, saplingTotalZatoshi);
192
+ onBalanceChanged(event);
193
+ });
172
194
  this.setListener('StatusEvent', onStatusChanged);
173
195
  this.setListener('TransactionEvent', onTransactionsChanged);
174
196
  this.setListener('UpdateEvent', onUpdate);
@@ -203,7 +225,7 @@ var makeSynchronizer = /*#__PURE__*/function () {
203
225
  return synchronizer;
204
226
  });
205
227
 
206
- return function makeSynchronizer(_x10) {
228
+ return function makeSynchronizer(_x11) {
207
229
  return _ref2.apply(this, arguments);
208
230
  };
209
231
  }();
@@ -1 +1 @@
1
- {"version":3,"file":"rnzcash.rn.js","sources":["../src/react-native.ts"],"sourcesContent":["import {\n EventSubscription,\n NativeEventEmitter,\n NativeModules\n} from 'react-native'\n\nimport {\n Addresses,\n InitializerConfig,\n Network,\n SpendFailure,\n SpendInfo,\n SpendSuccess,\n SynchronizerCallbacks,\n UnifiedViewingKey\n} from './types'\n\nconst { RNZcash } = NativeModules\n\ntype Callback = (...args: any[]) => any\n\nexport const Tools = {\n deriveViewingKey: async (\n seedBytesHex: string,\n network: Network\n ): Promise<UnifiedViewingKey> => {\n const result = await RNZcash.deriveViewingKey(seedBytesHex, network)\n return result\n },\n getBirthdayHeight: async (host: string, port: number): Promise<number> => {\n const result = await RNZcash.getBirthdayHeight(host, port)\n return result\n },\n isValidAddress: async (\n address: string,\n network: Network = 'mainnet'\n ): Promise<boolean> => {\n const result = await RNZcash.isValidAddress(address, network)\n return result\n }\n}\n\nexport class Synchronizer {\n eventEmitter: NativeEventEmitter\n subscriptions: EventSubscription[]\n alias: string\n network: Network\n\n constructor(alias: string, network: Network) {\n this.eventEmitter = new NativeEventEmitter(RNZcash)\n this.subscriptions = []\n this.alias = alias\n this.network = network\n }\n\n async stop(): Promise<String> {\n this.unsubscribe()\n const result = await RNZcash.stop(this.alias)\n return result\n }\n\n async initialize(initializerConfig: InitializerConfig): Promise<void> {\n await RNZcash.initialize(\n initializerConfig.mnemonicSeed,\n initializerConfig.birthdayHeight,\n initializerConfig.alias,\n initializerConfig.networkName,\n initializerConfig.defaultHost,\n initializerConfig.defaultPort,\n initializerConfig.newWallet\n )\n }\n\n async deriveUnifiedAddress(): Promise<Addresses> {\n const result = await RNZcash.deriveUnifiedAddress(this.alias)\n return result\n }\n\n async getLatestNetworkHeight(alias: string): Promise<number> {\n const result = await RNZcash.getLatestNetworkHeight(alias)\n return result\n }\n\n rescan(): void {\n RNZcash.rescan(this.alias)\n }\n\n async sendToAddress(\n spendInfo: SpendInfo\n ): Promise<SpendSuccess | SpendFailure> {\n const result = await RNZcash.sendToAddress(\n this.alias,\n spendInfo.zatoshi,\n spendInfo.toAddress,\n spendInfo.memo,\n spendInfo.mnemonicSeed\n )\n return result\n }\n\n // Events\n\n subscribe({\n onBalanceChanged,\n onStatusChanged,\n onTransactionsChanged,\n onUpdate\n }: SynchronizerCallbacks): void {\n this.setListener('BalanceEvent', onBalanceChanged)\n this.setListener('StatusEvent', onStatusChanged)\n this.setListener('TransactionEvent', onTransactionsChanged)\n this.setListener('UpdateEvent', onUpdate)\n }\n\n private setListener<T>(\n eventName: string,\n callback: Callback = (t: any) => null\n ): void {\n this.subscriptions.push(\n this.eventEmitter.addListener(eventName, arg =>\n arg.alias === this.alias ? callback(arg) : null\n )\n )\n }\n\n unsubscribe(): void {\n this.subscriptions.forEach(subscription => {\n subscription.remove()\n })\n }\n}\n\nexport const makeSynchronizer = async (\n initializerConfig: InitializerConfig\n): Promise<Synchronizer> => {\n const synchronizer = new Synchronizer(\n initializerConfig.alias,\n initializerConfig.networkName\n )\n await synchronizer.initialize(initializerConfig)\n return synchronizer\n}\n"],"names":["RNZcash","NativeModules","Tools","deriveViewingKey","seedBytesHex","network","result","getBirthdayHeight","host","port","isValidAddress","address","Synchronizer","alias","eventEmitter","NativeEventEmitter","subscriptions","stop","unsubscribe","initialize","initializerConfig","mnemonicSeed","birthdayHeight","networkName","defaultHost","defaultPort","newWallet","deriveUnifiedAddress","getLatestNetworkHeight","rescan","sendToAddress","spendInfo","zatoshi","toAddress","memo","subscribe","onBalanceChanged","onStatusChanged","onTransactionsChanged","onUpdate","setListener","eventName","callback","t","push","addListener","arg","forEach","subscription","remove","makeSynchronizer","synchronizer"],"mappings":"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"}
1
+ {"version":3,"file":"rnzcash.rn.js","sources":["../src/react-native.ts"],"sourcesContent":["import { add } from 'biggystring'\nimport {\n EventSubscription,\n NativeEventEmitter,\n NativeModules\n} from 'react-native'\n\nimport {\n Addresses,\n InitializerConfig,\n Network,\n ShieldFundsInfo,\n SpendFailure,\n SpendInfo,\n SpendSuccess,\n SynchronizerCallbacks,\n Transaction,\n UnifiedViewingKey\n} from './types'\nexport * from './types'\n\nconst { RNZcash } = NativeModules\n\ntype Callback = (...args: any[]) => any\n\nexport const Tools = {\n deriveViewingKey: async (\n seedBytesHex: string,\n network: Network\n ): Promise<UnifiedViewingKey> => {\n const result = await RNZcash.deriveViewingKey(seedBytesHex, network)\n return result\n },\n getBirthdayHeight: async (host: string, port: number): Promise<number> => {\n const result = await RNZcash.getBirthdayHeight(host, port)\n return result\n },\n isValidAddress: async (\n address: string,\n network: Network = 'mainnet'\n ): Promise<boolean> => {\n const result = await RNZcash.isValidAddress(address, network)\n return result\n }\n}\n\nexport class Synchronizer {\n eventEmitter: NativeEventEmitter\n subscriptions: EventSubscription[]\n alias: string\n network: Network\n\n constructor(alias: string, network: Network) {\n this.eventEmitter = new NativeEventEmitter(RNZcash)\n this.subscriptions = []\n this.alias = alias\n this.network = network\n }\n\n async stop(): Promise<string> {\n this.unsubscribe()\n const result = await RNZcash.stop(this.alias)\n return result\n }\n\n async initialize(initializerConfig: InitializerConfig): Promise<void> {\n await RNZcash.initialize(\n initializerConfig.mnemonicSeed,\n initializerConfig.birthdayHeight,\n initializerConfig.alias,\n initializerConfig.networkName,\n initializerConfig.defaultHost,\n initializerConfig.defaultPort,\n initializerConfig.newWallet\n )\n }\n\n async deriveUnifiedAddress(): Promise<Addresses> {\n const result = await RNZcash.deriveUnifiedAddress(this.alias)\n return result\n }\n\n async getLatestNetworkHeight(alias: string): Promise<number> {\n const result = await RNZcash.getLatestNetworkHeight(alias)\n return result\n }\n\n rescan(): void {\n RNZcash.rescan(this.alias)\n }\n\n async sendToAddress(\n spendInfo: SpendInfo\n ): Promise<SpendSuccess | SpendFailure> {\n const result = await RNZcash.sendToAddress(\n this.alias,\n spendInfo.zatoshi,\n spendInfo.toAddress,\n spendInfo.memo,\n spendInfo.mnemonicSeed\n )\n return result\n }\n\n async shieldFunds(shieldFundsInfo: ShieldFundsInfo): Promise<Transaction> {\n const result = await RNZcash.shieldFunds(\n this.alias,\n shieldFundsInfo.seed,\n shieldFundsInfo.memo,\n shieldFundsInfo.threshold\n )\n return result\n }\n\n // Events\n\n subscribe({\n onBalanceChanged,\n onStatusChanged,\n onTransactionsChanged,\n onUpdate\n }: SynchronizerCallbacks): void {\n this.setListener('BalanceEvent', event => {\n const {\n transparentAvailableZatoshi,\n transparentTotalZatoshi,\n saplingAvailableZatoshi,\n saplingTotalZatoshi\n } = event\n\n event.availableZatoshi = add(\n transparentAvailableZatoshi,\n saplingAvailableZatoshi\n )\n event.totalZatoshi = add(transparentTotalZatoshi, saplingTotalZatoshi)\n onBalanceChanged(event)\n })\n this.setListener('StatusEvent', onStatusChanged)\n this.setListener('TransactionEvent', onTransactionsChanged)\n this.setListener('UpdateEvent', onUpdate)\n }\n\n private setListener<T>(\n eventName: string,\n callback: Callback = (t: any) => null\n ): void {\n this.subscriptions.push(\n this.eventEmitter.addListener(eventName, arg =>\n arg.alias === this.alias ? callback(arg) : null\n )\n )\n }\n\n unsubscribe(): void {\n this.subscriptions.forEach(subscription => {\n subscription.remove()\n })\n }\n}\n\nexport const makeSynchronizer = async (\n initializerConfig: InitializerConfig\n): Promise<Synchronizer> => {\n const synchronizer = new Synchronizer(\n initializerConfig.alias,\n initializerConfig.networkName\n )\n await synchronizer.initialize(initializerConfig)\n return synchronizer\n}\n"],"names":["RNZcash","NativeModules","Tools","deriveViewingKey","seedBytesHex","network","result","getBirthdayHeight","host","port","isValidAddress","address","Synchronizer","alias","eventEmitter","NativeEventEmitter","subscriptions","stop","unsubscribe","initialize","initializerConfig","mnemonicSeed","birthdayHeight","networkName","defaultHost","defaultPort","newWallet","deriveUnifiedAddress","getLatestNetworkHeight","rescan","sendToAddress","spendInfo","zatoshi","toAddress","memo","shieldFunds","shieldFundsInfo","seed","threshold","subscribe","onBalanceChanged","onStatusChanged","onTransactionsChanged","onUpdate","setListener","event","transparentAvailableZatoshi","transparentTotalZatoshi","saplingAvailableZatoshi","saplingTotalZatoshi","availableZatoshi","add","totalZatoshi","eventName","callback","t","push","addListener","arg","forEach","subscription","remove","makeSynchronizer","synchronizer"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { EventSubscription, NativeEventEmitter } from 'react-native';
2
- import { Addresses, InitializerConfig, Network, SpendFailure, SpendInfo, SpendSuccess, SynchronizerCallbacks, UnifiedViewingKey } from './types';
2
+ import { Addresses, InitializerConfig, Network, ShieldFundsInfo, SpendFailure, SpendInfo, SpendSuccess, SynchronizerCallbacks, Transaction, UnifiedViewingKey } from './types';
3
+ export * from './types';
3
4
  export declare const Tools: {
4
5
  deriveViewingKey: (seedBytesHex: string, network: Network) => Promise<UnifiedViewingKey>;
5
6
  getBirthdayHeight: (host: string, port: number) => Promise<number>;
@@ -11,12 +12,13 @@ export declare class Synchronizer {
11
12
  alias: string;
12
13
  network: Network;
13
14
  constructor(alias: string, network: Network);
14
- stop(): Promise<String>;
15
+ stop(): Promise<string>;
15
16
  initialize(initializerConfig: InitializerConfig): Promise<void>;
16
17
  deriveUnifiedAddress(): Promise<Addresses>;
17
18
  getLatestNetworkHeight(alias: string): Promise<number>;
18
19
  rescan(): void;
19
20
  sendToAddress(spendInfo: SpendInfo): Promise<SpendSuccess | SpendFailure>;
21
+ shieldFunds(shieldFundsInfo: ShieldFundsInfo): Promise<Transaction>;
20
22
  subscribe({ onBalanceChanged, onStatusChanged, onTransactionsChanged, onUpdate }: SynchronizerCallbacks): void;
21
23
  private setListener;
22
24
  unsubscribe(): void;
@@ -14,6 +14,11 @@ export interface SpendInfo {
14
14
  memo?: string;
15
15
  mnemonicSeed: string;
16
16
  }
17
+ export interface ShieldFundsInfo {
18
+ seed: string;
19
+ memo: string;
20
+ threshold: string;
21
+ }
17
22
  export interface SpendSuccess {
18
23
  txId: string;
19
24
  raw: string;
@@ -27,6 +32,11 @@ export interface UnifiedViewingKey {
27
32
  extpub: string;
28
33
  }
29
34
  export interface BalanceEvent {
35
+ transparentAvailableZatoshi: string;
36
+ transparentTotalZatoshi: string;
37
+ saplingAvailableZatoshi: string;
38
+ saplingTotalZatoshi: string;
39
+ /** @deprecated */
30
40
  availableZatoshi: string;
31
41
  totalZatoshi: string;
32
42
  }
@@ -35,7 +45,7 @@ export interface StatusEvent {
35
45
  name: 'STOPPED' /** Indicates that [stop] has been called on this Synchronizer and it will no longer be used. */ | 'DISCONNECTED' /** Indicates that this Synchronizer is disconnected from its lightwalletd server. When set, a UI element may want to turn red. */ | 'SYNCING' /** Indicates that this Synchronizer is actively downloading and scanning new blocks */ | 'SYNCED'; /** Indicates that this Synchronizer is fully up to date and ready for all wallet functions. When set, a UI element may want to turn green. In this state, the balance can be trusted. */
36
46
  }
37
47
  export interface TransactionEvent {
38
- transactions: ConfirmedTransaction[];
48
+ transactions: Transaction[];
39
49
  }
40
50
  export interface UpdateEvent {
41
51
  alias: string;
@@ -52,7 +62,7 @@ export interface BlockRange {
52
62
  first: number;
53
63
  last: number;
54
64
  }
55
- export interface ConfirmedTransaction {
65
+ export interface Transaction {
56
66
  rawTransactionId: string;
57
67
  raw?: string;
58
68
  blockTimeInSeconds: number;
@@ -62,6 +72,8 @@ export interface ConfirmedTransaction {
62
72
  toAddress?: string;
63
73
  memos: string[];
64
74
  }
75
+ /** @deprecated Renamed `Transaction` because the package can now return unconfirmed shielding transactions */
76
+ export declare type ConfirmedTransaction = Transaction;
65
77
  export interface Addresses {
66
78
  unifiedAddress: string;
67
79
  saplingAddress: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-zcash",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Zcash library for React Native",
5
5
  "homepage": "https://github.com/EdgeApp/react-native-zcash",
6
6
  "repository": {
@@ -45,6 +45,7 @@
45
45
  "*.{js,ts}": "eslint"
46
46
  },
47
47
  "dependencies": {
48
+ "biggystring": "^4.1.3",
48
49
  "rfc4648": "^1.3.0"
49
50
  },
50
51
  "devDependencies": {
@@ -1,3 +1,4 @@
1
+ import { add } from 'biggystring'
1
2
  import {
2
3
  EventSubscription,
3
4
  NativeEventEmitter,
@@ -8,12 +9,15 @@ import {
8
9
  Addresses,
9
10
  InitializerConfig,
10
11
  Network,
12
+ ShieldFundsInfo,
11
13
  SpendFailure,
12
14
  SpendInfo,
13
15
  SpendSuccess,
14
16
  SynchronizerCallbacks,
17
+ Transaction,
15
18
  UnifiedViewingKey
16
19
  } from './types'
20
+ export * from './types'
17
21
 
18
22
  const { RNZcash } = NativeModules
19
23
 
@@ -53,7 +57,7 @@ export class Synchronizer {
53
57
  this.network = network
54
58
  }
55
59
 
56
- async stop(): Promise<String> {
60
+ async stop(): Promise<string> {
57
61
  this.unsubscribe()
58
62
  const result = await RNZcash.stop(this.alias)
59
63
  return result
@@ -98,6 +102,16 @@ export class Synchronizer {
98
102
  return result
99
103
  }
100
104
 
105
+ async shieldFunds(shieldFundsInfo: ShieldFundsInfo): Promise<Transaction> {
106
+ const result = await RNZcash.shieldFunds(
107
+ this.alias,
108
+ shieldFundsInfo.seed,
109
+ shieldFundsInfo.memo,
110
+ shieldFundsInfo.threshold
111
+ )
112
+ return result
113
+ }
114
+
101
115
  // Events
102
116
 
103
117
  subscribe({
@@ -106,7 +120,21 @@ export class Synchronizer {
106
120
  onTransactionsChanged,
107
121
  onUpdate
108
122
  }: SynchronizerCallbacks): void {
109
- this.setListener('BalanceEvent', onBalanceChanged)
123
+ this.setListener('BalanceEvent', event => {
124
+ const {
125
+ transparentAvailableZatoshi,
126
+ transparentTotalZatoshi,
127
+ saplingAvailableZatoshi,
128
+ saplingTotalZatoshi
129
+ } = event
130
+
131
+ event.availableZatoshi = add(
132
+ transparentAvailableZatoshi,
133
+ saplingAvailableZatoshi
134
+ )
135
+ event.totalZatoshi = add(transparentTotalZatoshi, saplingTotalZatoshi)
136
+ onBalanceChanged(event)
137
+ })
110
138
  this.setListener('StatusEvent', onStatusChanged)
111
139
  this.setListener('TransactionEvent', onTransactionsChanged)
112
140
  this.setListener('UpdateEvent', onUpdate)
package/src/types.ts CHANGED
@@ -17,6 +17,12 @@ export interface SpendInfo {
17
17
  mnemonicSeed: string
18
18
  }
19
19
 
20
+ export interface ShieldFundsInfo {
21
+ seed: string
22
+ memo: string
23
+ threshold: string
24
+ }
25
+
20
26
  export interface SpendSuccess {
21
27
  txId: string
22
28
  raw: string
@@ -33,6 +39,12 @@ export interface UnifiedViewingKey {
33
39
  }
34
40
 
35
41
  export interface BalanceEvent {
42
+ transparentAvailableZatoshi: string
43
+ transparentTotalZatoshi: string
44
+ saplingAvailableZatoshi: string
45
+ saplingTotalZatoshi: string
46
+
47
+ /** @deprecated */
36
48
  availableZatoshi: string
37
49
  totalZatoshi: string
38
50
  }
@@ -47,7 +59,7 @@ export interface StatusEvent {
47
59
  }
48
60
 
49
61
  export interface TransactionEvent {
50
- transactions: ConfirmedTransaction[]
62
+ transactions: Transaction[]
51
63
  }
52
64
 
53
65
  export interface UpdateEvent {
@@ -68,7 +80,7 @@ export interface BlockRange {
68
80
  last: number
69
81
  }
70
82
 
71
- export interface ConfirmedTransaction {
83
+ export interface Transaction {
72
84
  rawTransactionId: string
73
85
  raw?: string
74
86
  blockTimeInSeconds: number
@@ -79,6 +91,9 @@ export interface ConfirmedTransaction {
79
91
  memos: string[]
80
92
  }
81
93
 
94
+ /** @deprecated Renamed `Transaction` because the package can now return unconfirmed shielding transactions */
95
+ export type ConfirmedTransaction = Transaction
96
+
82
97
  export interface Addresses {
83
98
  unifiedAddress: string
84
99
  saplingAddress: string