react-native-zcash 0.6.0 → 0.6.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/CHANGELOG.md +17 -0
- package/README.md +2 -1
- package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/2260000.json +8 -0
- package/android/src/main/java/app/edge/rnzcash/RNZcashModule.kt +202 -123
- package/android/src/main/java/app/edge/rnzcash/RNZcashPackage.kt +1 -2
- package/ios/RNZcash.m +8 -0
- package/ios/RNZcash.swift +145 -70
- package/ios/ZCashLightClientKit/Block/CompactBlockProcessor.swift +8 -4
- package/ios/ZCashLightClientKit/Constants/ZcashSDK.swift +6 -1
- package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2260000.json +8 -0
- package/ios/libzcashlc.xcframework/Info.plist +5 -5
- package/lib/rnzcash.rn.js +35 -5
- package/lib/rnzcash.rn.js.map +1 -1
- package/lib/src/react-native.d.ts +5 -3
- package/lib/src/types.d.ts +14 -2
- package/package.json +2 -1
- package/src/react-native.ts +32 -4
- package/src/types.ts +17 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# React Native Zcash
|
|
2
2
|
|
|
3
|
+
## 0.6.2 (2023-10-16)
|
|
4
|
+
|
|
5
|
+
- changed: Upgrade ZcashLightClientKit to v2.0.2
|
|
6
|
+
- changed: Make `rescan` async
|
|
7
|
+
- changed: Throttle sync status to only report changes (iOS)
|
|
8
|
+
|
|
9
|
+
## 0.6.1 (2023-10-11)
|
|
10
|
+
|
|
11
|
+
- added: Add `shieldFunds` support
|
|
12
|
+
- changed: Package now exports types
|
|
13
|
+
- deprecated: Balance event fields `availableZatoshi` and `totalZatoshi`
|
|
14
|
+
|
|
15
|
+
Android
|
|
16
|
+
|
|
17
|
+
- changed: Various syntax cleanups
|
|
18
|
+
- fixed: Transactions event now returns confirmed and pending (<10 confirmations) transactions
|
|
19
|
+
|
|
3
20
|
## 0.6.0 (2023-10-10)
|
|
4
21
|
|
|
5
22
|
- 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`-
|
|
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
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"network": "main",
|
|
3
|
+
"height": "2260000",
|
|
4
|
+
"hash": "00000000014b3b907e559bd87daba56c85c16446aef59e9ce9dba37ad2691b86",
|
|
5
|
+
"time": 1697204301,
|
|
6
|
+
"saplingTree": "01ccd67f580cc75af1faf952deaa774c5008496e49f2b8c3f4de936ee0c268846b001a00000001db3f7578a2f0e1d7ce61030a4192f0500c655626c81edd69be7e2bb012cb5b3b0001299a4e80c4c7c13553248aae4f35f03318cc04713927b8aa9abf086df2d8375d0000015811cf08cc569867834281fd88ea6bc930529573fa2cbbff8fd0f64963cee702000169d3b6e6999f905b302b4f1d2f84acf1b84e04d1fe8a1d107efd1971faa0bd0e0001e192d9d422a7fdd876027946e61dc5034f54ae4df2834eda15800658196e731f000001ffdd1a0628296bf274daa5ea13fb57818d678957d49f91ccd69efae0bac249340182ac7ebe2f7e9d8084a38aa8be56b1bd86292babf05f98882a6959cf9d318c110001d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
|
|
7
|
+
"orchardTree": "01bf80f9a026cba7ffd8e4eb99895eefc6e7e7b1f3f451cd0272f8c8ee09b81e0601c94fc93463e006682dc287e10035a898a577becb7af338c7aad32b6aeeb592111f000151634a9677c3589d76542b11db3c79efccc8fbbe3cb521b9adf599ad3895dc020163ee08cae7b538138c74534a346d723e37beb3a886d9fc7e1b69e938a48c6d220188d5ac292703a08902cc79a54a801b13b41360e03cfb130e3b7ca9e76bd8961401b1021539f9d34c2df786324de29594dfd12f260ec6f893e37490a9c4cf7f7f380000014c3bc5b55f752c69ac57e14b8cb7c2bc00a1c7c21231dc4b1c9124fe434ea13900000000012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
|
|
8
|
+
}
|
|
@@ -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.
|
|
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(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
106
|
-
|
|
116
|
+
val transparentAvailableZatoshi = transparentBalances?.available ?: Zatoshi(0L)
|
|
117
|
+
val transparentTotalZatoshi = transparentBalances?.total ?: Zatoshi(0L)
|
|
107
118
|
|
|
108
|
-
|
|
109
|
-
|
|
119
|
+
val saplingAvailableZatoshi = saplingBalances?.available ?: Zatoshi(0L)
|
|
120
|
+
val saplingTotalZatoshi = saplingBalances?.total ?: Zatoshi(0L)
|
|
110
121
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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(
|
|
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(
|
|
145
|
+
private suspend fun parseTx(
|
|
146
|
+
wallet: SdkSynchronizer,
|
|
147
|
+
tx: TransactionOverview,
|
|
148
|
+
): WritableMap {
|
|
136
149
|
val map = Arguments.createMap()
|
|
137
|
-
val job =
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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(
|
|
184
|
+
fun rescan(
|
|
185
|
+
alias: String,
|
|
186
|
+
promise: Promise,
|
|
187
|
+
) {
|
|
167
188
|
val wallet = getWallet(alias)
|
|
168
189
|
wallet.coroutineScope.launch {
|
|
169
|
-
wallet.
|
|
190
|
+
wallet.rewindToNearestHeight(wallet.latestBirthdayHeight)
|
|
170
191
|
promise.resolve(null)
|
|
171
192
|
}
|
|
172
193
|
}
|
|
173
194
|
|
|
174
195
|
@ReactMethod
|
|
175
|
-
fun deriveViewingKey(
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
265
|
+
val usk = DerivationTool.getInstance().deriveUnifiedSpendingKey(seedPhrase.toByteArray(), wallet.network, Account.DEFAULT)
|
|
230
266
|
try {
|
|
231
|
-
val internalId =
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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(
|
|
322
|
+
fun deriveUnifiedAddress(
|
|
323
|
+
alias: String,
|
|
324
|
+
promise: Promise,
|
|
325
|
+
) {
|
|
254
326
|
val wallet = getWallet(alias)
|
|
255
327
|
wallet.coroutineScope.launch {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
328
|
+
val unifiedAddress = wallet.getUnifiedAddress(Account(0))
|
|
329
|
+
val saplingAddress = wallet.getSaplingAddress(Account(0))
|
|
330
|
+
val transparentAddress = wallet.getTransparentAddress(Account(0))
|
|
259
331
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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(
|
|
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(
|
|
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:
|
|
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
|
|
36
|
-
var
|
|
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
|
-
"
|
|
40
|
-
"
|
|
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,
|
|
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
|
|
@@ -250,8 +292,8 @@ class RNZcash: RCTEventEmitter {
|
|
|
250
292
|
wallet.restart = true
|
|
251
293
|
wallet.initializeProcessorState()
|
|
252
294
|
wallet.cancellables.forEach { $0.cancel() }
|
|
253
|
-
wallet.subscribe()
|
|
254
295
|
try await wallet.synchronizer.start()
|
|
296
|
+
wallet.subscribe()
|
|
255
297
|
resolve(nil)
|
|
256
298
|
case .failure:
|
|
257
299
|
reject("RescanError", "Failed to rescan wallet", genericError)
|
|
@@ -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(
|
|
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,12 +422,15 @@ class WalletSynchronizer: NSObject {
|
|
|
379
422
|
scanProgress: 0,
|
|
380
423
|
networkBlockHeight: 0
|
|
381
424
|
)
|
|
382
|
-
self.balances = TotalBalances(
|
|
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() {
|
|
386
433
|
self.synchronizer.stateStream
|
|
387
|
-
.throttle(for: .seconds(0.3), scheduler: DispatchQueue.main, latest: true)
|
|
388
434
|
.sink(receiveValue: { [weak self] state in self?.updateSyncStatus(event: state) })
|
|
389
435
|
.store(in: &cancellables)
|
|
390
436
|
self.synchronizer.stateStream
|
|
@@ -393,35 +439,38 @@ class WalletSynchronizer: NSObject {
|
|
|
393
439
|
self.synchronizer.eventStream
|
|
394
440
|
.sink { SynchronizerEvent in
|
|
395
441
|
switch SynchronizerEvent {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
442
|
+
case .minedTransaction(let transaction):
|
|
443
|
+
self.emitTxs(transactions: [transaction])
|
|
444
|
+
case .foundTransactions(let transactions, _):
|
|
445
|
+
self.emitTxs(transactions: transactions)
|
|
446
|
+
default:
|
|
447
|
+
return
|
|
448
|
+
}
|
|
403
449
|
}
|
|
404
450
|
.store(in: &cancellables)
|
|
405
451
|
}
|
|
406
452
|
|
|
407
453
|
func updateSyncStatus(event: SynchronizerState) {
|
|
408
|
-
|
|
454
|
+
var status = self.status
|
|
455
|
+
|
|
409
456
|
if !self.fullySynced {
|
|
410
457
|
switch event.internalSyncStatus {
|
|
411
458
|
case .syncing:
|
|
412
|
-
|
|
459
|
+
status = "SYNCING"
|
|
413
460
|
self.restart = false
|
|
414
461
|
case .synced:
|
|
415
462
|
if self.restart {
|
|
416
463
|
// The synchronizer emits "synced" status after starting a rescan. We need to ignore these.
|
|
417
464
|
return
|
|
418
465
|
}
|
|
419
|
-
|
|
466
|
+
status = "SYNCED"
|
|
420
467
|
self.fullySynced = true
|
|
421
468
|
default:
|
|
422
469
|
break
|
|
423
470
|
}
|
|
424
471
|
|
|
472
|
+
if status == self.status { return }
|
|
473
|
+
self.status = status
|
|
425
474
|
let data: NSDictionary = ["alias": self.alias, "name": self.status]
|
|
426
475
|
emit("StatusEvent", data)
|
|
427
476
|
}
|
|
@@ -441,10 +490,18 @@ class WalletSynchronizer: NSObject {
|
|
|
441
490
|
return
|
|
442
491
|
}
|
|
443
492
|
|
|
444
|
-
if
|
|
493
|
+
if scanProgress == self.processorState.scanProgress
|
|
494
|
+
&& event.latestBlockHeight == self.processorState.networkBlockHeight
|
|
495
|
+
{
|
|
496
|
+
return
|
|
497
|
+
}
|
|
445
498
|
|
|
446
|
-
self.processorState = ProcessorState(
|
|
447
|
-
|
|
499
|
+
self.processorState = ProcessorState(
|
|
500
|
+
scanProgress: scanProgress, networkBlockHeight: event.latestBlockHeight)
|
|
501
|
+
let data: NSDictionary = [
|
|
502
|
+
"alias": self.alias, "scanProgress": self.processorState.scanProgress,
|
|
503
|
+
"networkBlockHeight": self.processorState.networkBlockHeight,
|
|
504
|
+
]
|
|
448
505
|
emit("UpdateEvent", data)
|
|
449
506
|
updateBalanceState(event: event)
|
|
450
507
|
}
|
|
@@ -454,68 +511,86 @@ class WalletSynchronizer: NSObject {
|
|
|
454
511
|
scanProgress: 0,
|
|
455
512
|
networkBlockHeight: 0
|
|
456
513
|
)
|
|
457
|
-
self.balances = TotalBalances(
|
|
514
|
+
self.balances = TotalBalances(
|
|
515
|
+
transparentAvailableZatoshi: Zatoshi(0),
|
|
516
|
+
transparentTotalZatoshi: Zatoshi(0),
|
|
517
|
+
saplingAvailableZatoshi: Zatoshi(0),
|
|
518
|
+
saplingTotalZatoshi: Zatoshi(0))
|
|
458
519
|
}
|
|
459
520
|
|
|
460
521
|
func updateBalanceState(event: SynchronizerState) {
|
|
461
522
|
let transparentBalance = event.transparentBalance
|
|
462
523
|
let shieldedBalance = event.shieldedBalance
|
|
463
524
|
|
|
464
|
-
let
|
|
465
|
-
let
|
|
525
|
+
let transparentAvailableZatoshi = transparentBalance.verified
|
|
526
|
+
let transparentTotalZatoshi = transparentBalance.total
|
|
466
527
|
|
|
467
|
-
let
|
|
468
|
-
let
|
|
528
|
+
let saplingAvailableZatoshi = shieldedBalance.verified
|
|
529
|
+
let saplingTotalZatoshi = shieldedBalance.total
|
|
469
530
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
531
|
+
if transparentAvailableZatoshi == self.balances.transparentAvailableZatoshi
|
|
532
|
+
&& transparentTotalZatoshi == self.balances.transparentTotalZatoshi
|
|
533
|
+
&& saplingAvailableZatoshi == self.balances.saplingAvailableZatoshi
|
|
534
|
+
&& saplingTotalZatoshi == self.balances.saplingTotalZatoshi
|
|
535
|
+
{
|
|
536
|
+
return
|
|
537
|
+
}
|
|
474
538
|
|
|
475
|
-
self.balances = TotalBalances(
|
|
476
|
-
|
|
539
|
+
self.balances = TotalBalances(
|
|
540
|
+
transparentAvailableZatoshi: transparentAvailableZatoshi,
|
|
541
|
+
transparentTotalZatoshi: transparentTotalZatoshi,
|
|
542
|
+
saplingAvailableZatoshi: saplingAvailableZatoshi,
|
|
543
|
+
saplingTotalZatoshi: saplingTotalZatoshi
|
|
544
|
+
)
|
|
545
|
+
let data = NSMutableDictionary(dictionary: self.balances.nsDictionary)
|
|
546
|
+
data["alias"] = self.alias
|
|
477
547
|
emit("BalanceEvent", data)
|
|
478
548
|
}
|
|
479
549
|
|
|
550
|
+
func parseTx(tx: ZcashTransaction.Overview) async -> ConfirmedTx {
|
|
551
|
+
var confTx = ConfirmedTx(
|
|
552
|
+
minedHeight: tx.minedHeight ?? 0,
|
|
553
|
+
rawTransactionId: (tx.rawID.toHexStringTxId()),
|
|
554
|
+
blockTimeInSeconds: Int(tx.blockTime ?? 0),
|
|
555
|
+
value: String(describing: abs(tx.value.amount))
|
|
556
|
+
)
|
|
557
|
+
if tx.raw != nil {
|
|
558
|
+
confTx.raw = tx.raw!.hexEncodedString()
|
|
559
|
+
}
|
|
560
|
+
if tx.fee != nil {
|
|
561
|
+
confTx.fee = String(describing: abs(tx.value.amount))
|
|
562
|
+
}
|
|
563
|
+
if tx.isSentTransaction {
|
|
564
|
+
let recipients = await self.synchronizer.getRecipients(for: tx)
|
|
565
|
+
if recipients.count > 0 {
|
|
566
|
+
let addresses = recipients.compactMap {
|
|
567
|
+
if case let .address(address) = $0 {
|
|
568
|
+
return address
|
|
569
|
+
} else {
|
|
570
|
+
return nil
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
if addresses.count > 0 {
|
|
574
|
+
confTx.toAddress = addresses.first!.stringEncoded
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
if tx.memoCount > 0 {
|
|
579
|
+
let memos = (try? await self.synchronizer.getMemos(for: tx)) ?? []
|
|
580
|
+
let textMemos = memos.compactMap {
|
|
581
|
+
return $0.toString()
|
|
582
|
+
}
|
|
583
|
+
confTx.memos = textMemos
|
|
584
|
+
}
|
|
585
|
+
return confTx
|
|
586
|
+
}
|
|
587
|
+
|
|
480
588
|
func emitTxs(transactions: [ZcashTransaction.Overview]) {
|
|
481
589
|
Task {
|
|
482
590
|
var out: [NSDictionary] = []
|
|
483
591
|
for tx in transactions {
|
|
484
|
-
if
|
|
485
|
-
|
|
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
|
-
}
|
|
592
|
+
if tx.isExpiredUmined ?? false { continue }
|
|
593
|
+
let confTx = await parseTx(tx: tx)
|
|
519
594
|
out.append(confTx.nsDictionary)
|
|
520
595
|
}
|
|
521
596
|
|
|
@@ -22,7 +22,7 @@ actor CompactBlockProcessor {
|
|
|
22
22
|
private var syncTask: Task<Void, Error>?
|
|
23
23
|
|
|
24
24
|
private let actions: [CBPState: Action]
|
|
25
|
-
|
|
25
|
+
var context: ActionContext
|
|
26
26
|
|
|
27
27
|
private(set) var config: Configuration
|
|
28
28
|
private let configProvider: ConfigProvider
|
|
@@ -346,6 +346,8 @@ extension CompactBlockProcessor {
|
|
|
346
346
|
} catch {
|
|
347
347
|
return await context.completion(.failure(error))
|
|
348
348
|
}
|
|
349
|
+
|
|
350
|
+
await resetContext(restoreLastEnhancedHeight: false)
|
|
349
351
|
|
|
350
352
|
await context.completion(.success(rewindBlockHeight))
|
|
351
353
|
}
|
|
@@ -615,10 +617,12 @@ extension CompactBlockProcessor {
|
|
|
615
617
|
}
|
|
616
618
|
}
|
|
617
619
|
|
|
618
|
-
|
|
619
|
-
let
|
|
620
|
+
func resetContext(restoreLastEnhancedHeight: Bool = true) async {
|
|
621
|
+
let lastEnhancedHeight = await context.lastEnhancedHeight
|
|
620
622
|
context = ActionContextImpl(state: .idle)
|
|
621
|
-
|
|
623
|
+
if restoreLastEnhancedHeight {
|
|
624
|
+
await context.update(lastEnhancedHeight: lastEnhancedHeight)
|
|
625
|
+
}
|
|
622
626
|
}
|
|
623
627
|
|
|
624
628
|
private func syncStarted() async {
|
|
@@ -98,7 +98,12 @@ public enum ZcashSDK {
|
|
|
98
98
|
public static let defaultPollInterval: TimeInterval = 20
|
|
99
99
|
|
|
100
100
|
/// Default attempts at retrying.
|
|
101
|
-
|
|
101
|
+
// This has been tweaked in https://github.com/zcash/ZcashLightClientKit/issues/1303
|
|
102
|
+
// There are many places that rely on hasRetryAttempt() that reads and compares this value.
|
|
103
|
+
// Better solution is to think about retry logic and potentially either remove completely
|
|
104
|
+
// or implement more sophisticated solutuion. Until that time, Int.max solves our UX issues
|
|
105
|
+
// TODO: [#1304] smart retry logic, https://github.com/zcash/ZcashLightClientKit/issues/1304
|
|
106
|
+
public static let defaultRetries = Int.max
|
|
102
107
|
|
|
103
108
|
/// The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than
|
|
104
109
|
/// this before retrying.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"network": "main",
|
|
3
|
+
"height": "2260000",
|
|
4
|
+
"hash": "00000000014b3b907e559bd87daba56c85c16446aef59e9ce9dba37ad2691b86",
|
|
5
|
+
"time": 1697204301,
|
|
6
|
+
"saplingTree": "01ccd67f580cc75af1faf952deaa774c5008496e49f2b8c3f4de936ee0c268846b001a00000001db3f7578a2f0e1d7ce61030a4192f0500c655626c81edd69be7e2bb012cb5b3b0001299a4e80c4c7c13553248aae4f35f03318cc04713927b8aa9abf086df2d8375d0000015811cf08cc569867834281fd88ea6bc930529573fa2cbbff8fd0f64963cee702000169d3b6e6999f905b302b4f1d2f84acf1b84e04d1fe8a1d107efd1971faa0bd0e0001e192d9d422a7fdd876027946e61dc5034f54ae4df2834eda15800658196e731f000001ffdd1a0628296bf274daa5ea13fb57818d678957d49f91ccd69efae0bac249340182ac7ebe2f7e9d8084a38aa8be56b1bd86292babf05f98882a6959cf9d318c110001d8ccea507421a590ed38116b834189cdc22421b4764179fa4e364803dfa66d56018cf6f5034a55fed59d1d832620916a43c756d2379e50ef9440fc4c3e7a29aa2300011619f99023a69bb647eab2d2aa1a73c3673c74bb033c3c4930eacda19e6fd93b0000000160272b134ca494b602137d89e528c751c06d3ef4a87a45f33af343c15060cc1e",
|
|
7
|
+
"orchardTree": "01bf80f9a026cba7ffd8e4eb99895eefc6e7e7b1f3f451cd0272f8c8ee09b81e0601c94fc93463e006682dc287e10035a898a577becb7af338c7aad32b6aeeb592111f000151634a9677c3589d76542b11db3c79efccc8fbbe3cb521b9adf599ad3895dc020163ee08cae7b538138c74534a346d723e37beb3a886d9fc7e1b69e938a48c6d220188d5ac292703a08902cc79a54a801b13b41360e03cfb130e3b7ca9e76bd8961401b1021539f9d34c2df786324de29594dfd12f260ec6f893e37490a9c4cf7f7f380000014c3bc5b55f752c69ac57e14b8cb7c2bc00a1c7c21231dc4b1c9124fe434ea13900000000012ffae608e1b4d4de4f5ac38068b613d9761ba34d95430e5ec8d058848cc9c0250001dd3e61f3e1d497d923486bd000737ea0ffac885fa481316727d0d8f7fc2138100001cf3bf92f69798e68555548afcce1648add1fb2548d64fa9a1ec22a3e26e7890101e637281deb58dff0c44ba13149b784a95da1b493005efd057e6f4ac20ef5d81d000001cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d35470810012dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402c01daf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234150001e2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1b000000000000"
|
|
8
|
+
}
|
|
@@ -8,32 +8,32 @@
|
|
|
8
8
|
<key>BinaryPath</key>
|
|
9
9
|
<string>libzcashlc.a</string>
|
|
10
10
|
<key>LibraryIdentifier</key>
|
|
11
|
-
<string>ios-
|
|
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-
|
|
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) {
|
|
@@ -145,9 +146,17 @@ var Synchronizer = /*#__PURE__*/function () {
|
|
|
145
146
|
return getLatestNetworkHeight;
|
|
146
147
|
}();
|
|
147
148
|
|
|
148
|
-
_proto.rescan = function
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
_proto.rescan = /*#__PURE__*/function () {
|
|
150
|
+
var _rescan = _asyncToGenerator(function* () {
|
|
151
|
+
yield RNZcash.rescan(this.alias);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
function rescan() {
|
|
155
|
+
return _rescan.apply(this, arguments);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return rescan;
|
|
159
|
+
}();
|
|
151
160
|
|
|
152
161
|
_proto.sendToAddress = /*#__PURE__*/function () {
|
|
153
162
|
var _sendToAddress = _asyncToGenerator(function* (spendInfo) {
|
|
@@ -160,6 +169,19 @@ var Synchronizer = /*#__PURE__*/function () {
|
|
|
160
169
|
}
|
|
161
170
|
|
|
162
171
|
return sendToAddress;
|
|
172
|
+
}();
|
|
173
|
+
|
|
174
|
+
_proto.shieldFunds = /*#__PURE__*/function () {
|
|
175
|
+
var _shieldFunds = _asyncToGenerator(function* (shieldFundsInfo) {
|
|
176
|
+
var result = yield RNZcash.shieldFunds(this.alias, shieldFundsInfo.seed, shieldFundsInfo.memo, shieldFundsInfo.threshold);
|
|
177
|
+
return result;
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
function shieldFunds(_x10) {
|
|
181
|
+
return _shieldFunds.apply(this, arguments);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return shieldFunds;
|
|
163
185
|
}() // Events
|
|
164
186
|
;
|
|
165
187
|
|
|
@@ -168,7 +190,15 @@ var Synchronizer = /*#__PURE__*/function () {
|
|
|
168
190
|
onStatusChanged = _ref.onStatusChanged,
|
|
169
191
|
onTransactionsChanged = _ref.onTransactionsChanged,
|
|
170
192
|
onUpdate = _ref.onUpdate;
|
|
171
|
-
this.setListener('BalanceEvent',
|
|
193
|
+
this.setListener('BalanceEvent', function (event) {
|
|
194
|
+
var transparentAvailableZatoshi = event.transparentAvailableZatoshi,
|
|
195
|
+
transparentTotalZatoshi = event.transparentTotalZatoshi,
|
|
196
|
+
saplingAvailableZatoshi = event.saplingAvailableZatoshi,
|
|
197
|
+
saplingTotalZatoshi = event.saplingTotalZatoshi;
|
|
198
|
+
event.availableZatoshi = biggystring.add(transparentAvailableZatoshi, saplingAvailableZatoshi);
|
|
199
|
+
event.totalZatoshi = biggystring.add(transparentTotalZatoshi, saplingTotalZatoshi);
|
|
200
|
+
onBalanceChanged(event);
|
|
201
|
+
});
|
|
172
202
|
this.setListener('StatusEvent', onStatusChanged);
|
|
173
203
|
this.setListener('TransactionEvent', onTransactionsChanged);
|
|
174
204
|
this.setListener('UpdateEvent', onUpdate);
|
|
@@ -203,7 +233,7 @@ var makeSynchronizer = /*#__PURE__*/function () {
|
|
|
203
233
|
return synchronizer;
|
|
204
234
|
});
|
|
205
235
|
|
|
206
|
-
return function makeSynchronizer(
|
|
236
|
+
return function makeSynchronizer(_x11) {
|
|
207
237
|
return _ref2.apply(this, arguments);
|
|
208
238
|
};
|
|
209
239
|
}();
|
package/lib/rnzcash.rn.js.map
CHANGED
|
@@ -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<
|
|
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 async rescan(): Promise<void> {\n await 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<
|
|
15
|
+
stop(): Promise<string>;
|
|
15
16
|
initialize(initializerConfig: InitializerConfig): Promise<void>;
|
|
16
17
|
deriveUnifiedAddress(): Promise<Addresses>;
|
|
17
18
|
getLatestNetworkHeight(alias: string): Promise<number>;
|
|
18
|
-
rescan(): void
|
|
19
|
+
rescan(): Promise<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;
|
package/lib/src/types.d.ts
CHANGED
|
@@ -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:
|
|
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
|
|
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.
|
|
3
|
+
"version": "0.6.2",
|
|
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": {
|
package/src/react-native.ts
CHANGED
|
@@ -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<
|
|
60
|
+
async stop(): Promise<string> {
|
|
57
61
|
this.unsubscribe()
|
|
58
62
|
const result = await RNZcash.stop(this.alias)
|
|
59
63
|
return result
|
|
@@ -81,8 +85,8 @@ export class Synchronizer {
|
|
|
81
85
|
return result
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
rescan(): void {
|
|
85
|
-
RNZcash.rescan(this.alias)
|
|
88
|
+
async rescan(): Promise<void> {
|
|
89
|
+
await RNZcash.rescan(this.alias)
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
async sendToAddress(
|
|
@@ -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',
|
|
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:
|
|
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
|
|
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
|