react-native-zcash 0.1.0 â 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/Scripts/build_librustzcash.sh +23 -0
- package/Scripts/build_librustzcash_xcode.sh +64 -0
- package/Scripts/generate_test_constants.sh +16 -0
- package/Scripts/prepare_zcash_sdk.sh +31 -0
- package/Scripts/script_commons.sh +23 -0
- package/Scripts/travis/ZcashLightClientSample_setup.sh +8 -0
- package/Scripts/travis/rust_setup.sh +13 -0
- package/android/src/main/java/app/edge/rnzcash/RNZcashModule.kt +21 -91
- package/ios/RNZcash-Bridging-Header.h +6 -0
- package/ios/RNZcash.m +89 -43
- package/ios/RNZcash.swift +528 -0
- package/ios/RNZcash.xcodeproj/xcuserdata/Matthew.xcuserdatad/xcschemes/xcschememanagement.plist +22 -0
- package/ios/RNZcash.xcworkspace/xcuserdata/Matthew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/lib/rnzcash.rn.js +16 -26
- package/lib/rnzcash.rn.js.map +1 -1
- package/lib/src/react-native.d.ts +3 -4
- package/lib/src/types.d.ts +0 -2
- package/package.json +4 -2
- package/react-native-zcash.podspec +13 -3
- package/src/react-native.ts +11 -21
- package/src/types.ts +0 -2
- package/ios/RNZcash.h +0 -5
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import ZcashLightClientKit
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
var SynchronizerMap = [String: WalletSynchronizer]()
|
|
6
|
+
var loggerProxy = RNZcashLogger(logLevel: .debug)
|
|
7
|
+
|
|
8
|
+
struct ViewingKey: UnifiedViewingKey {
|
|
9
|
+
var extfvk: ExtendedFullViewingKey
|
|
10
|
+
var extpub: ExtendedPublicKey
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
struct ConfirmedTx {
|
|
14
|
+
var minedHeight: Int
|
|
15
|
+
var toAddress: String?
|
|
16
|
+
var rawTransactionId: String
|
|
17
|
+
var blockTimeInSeconds: Int
|
|
18
|
+
var value: String
|
|
19
|
+
var memo: String?
|
|
20
|
+
var dictionary: [String: Any] {
|
|
21
|
+
return [
|
|
22
|
+
"minedHeight": minedHeight,
|
|
23
|
+
"toAddress": toAddress,
|
|
24
|
+
"rawTransactionId": rawTransactionId,
|
|
25
|
+
"blockTimeInSeconds": blockTimeInSeconds,
|
|
26
|
+
"value": value,
|
|
27
|
+
"memo": memo
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
var nsDictionary: NSDictionary {
|
|
31
|
+
return dictionary as NSDictionary
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
struct ShieldedBalance {
|
|
36
|
+
var availableZatoshi: String
|
|
37
|
+
var totalZatoshi: String
|
|
38
|
+
var dictionary: [String: Any] {
|
|
39
|
+
return [
|
|
40
|
+
"availableZatoshi": availableZatoshi,
|
|
41
|
+
"totalZatoshi": totalZatoshi
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
var nsDictionary: NSDictionary {
|
|
45
|
+
return dictionary as NSDictionary
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
struct ProcessorState {
|
|
50
|
+
var alias: String
|
|
51
|
+
var lastDownloadedHeight: Int
|
|
52
|
+
var lastScannedHeight: Int
|
|
53
|
+
var scanProgress: Int
|
|
54
|
+
var networkBlockHeight: Int
|
|
55
|
+
var dictionary: [String: Any] {
|
|
56
|
+
return [
|
|
57
|
+
"alias": alias,
|
|
58
|
+
"lastDownloadedHeight": lastDownloadedHeight,
|
|
59
|
+
"lastScannedHeight": lastScannedHeight,
|
|
60
|
+
"scanProgress": scanProgress,
|
|
61
|
+
"networkBlockHeight": networkBlockHeight
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
var nsDictionary: NSDictionary {
|
|
65
|
+
return dictionary as NSDictionary
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Used when calling reject where there isn't an error object
|
|
70
|
+
let genericError = NSError(domain: "", code: 0)
|
|
71
|
+
|
|
72
|
+
@objc(RNZcash)
|
|
73
|
+
class RNZcash : RCTEventEmitter {
|
|
74
|
+
|
|
75
|
+
override static func requiresMainQueueSetup() -> Bool {
|
|
76
|
+
return true
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private func getNetworkParams(_ network: String) -> ZcashNetwork {
|
|
80
|
+
switch network {
|
|
81
|
+
case "testnet":
|
|
82
|
+
return ZcashNetworkBuilder.network(for: .testnet)
|
|
83
|
+
default:
|
|
84
|
+
return ZcashNetworkBuilder.network(for: .mainnet)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Synchronizer
|
|
89
|
+
@objc func initialize(_ extfvk: String, _ extpub: String, _ birthdayHeight: Int, _ alias: String, _ networkName: String, _ defaultHost: String, _ defaultPort: Int, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
90
|
+
let network = getNetworkParams(networkName)
|
|
91
|
+
let endpoint = LightWalletEndpoint(address: defaultHost, port: defaultPort, secure: true)
|
|
92
|
+
let viewingKey = ViewingKey(extfvk: extfvk, extpub:extpub)
|
|
93
|
+
let initializer = Initializer(
|
|
94
|
+
cacheDbURL: try! cacheDbURLHelper(alias, network),
|
|
95
|
+
dataDbURL: try! dataDbURLHelper(alias, network),
|
|
96
|
+
pendingDbURL: try! pendingDbURLHelper(alias, network),
|
|
97
|
+
endpoint: endpoint,
|
|
98
|
+
network: network,
|
|
99
|
+
spendParamsURL: try! spendParamsURLHelper(alias),
|
|
100
|
+
outputParamsURL: try! outputParamsURLHelper(alias),
|
|
101
|
+
viewingKeys: [viewingKey],
|
|
102
|
+
walletBirthday: birthdayHeight,
|
|
103
|
+
loggerProxy: loggerProxy
|
|
104
|
+
)
|
|
105
|
+
if (SynchronizerMap[alias] == nil) {
|
|
106
|
+
do {
|
|
107
|
+
let wallet = try WalletSynchronizer(alias:alias, initializer:initializer, emitter:sendToJs)
|
|
108
|
+
try wallet.synchronizer.initialize()
|
|
109
|
+
try wallet.synchronizer.prepare()
|
|
110
|
+
SynchronizerMap[alias] = wallet
|
|
111
|
+
resolve(nil)
|
|
112
|
+
} catch {
|
|
113
|
+
reject("InitializeError", "Synchronizer failed to initialize", error)
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
// Wallet already initialized
|
|
117
|
+
resolve(nil)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@objc func start(_ alias: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
122
|
+
if let wallet = SynchronizerMap[alias] {
|
|
123
|
+
do {
|
|
124
|
+
try wallet.synchronizer.start()
|
|
125
|
+
wallet.subscribe()
|
|
126
|
+
} catch {
|
|
127
|
+
reject("StartError", "Synchronizer failed to start", error)
|
|
128
|
+
}
|
|
129
|
+
resolve(nil)
|
|
130
|
+
} else {
|
|
131
|
+
reject("StartError", "Wallet does not exist", genericError)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@objc func stop(_ alias: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
136
|
+
if let wallet = SynchronizerMap[alias] {
|
|
137
|
+
wallet.synchronizer.stop()
|
|
138
|
+
resolve(nil)
|
|
139
|
+
} else {
|
|
140
|
+
reject("StopError", "Wallet does not exist", genericError)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@objc func spendToAddress(_ alias: String, _ zatoshi: String, _ toAddress: String, _ memo: String, _ fromAccountIndex: Int, _ spendingKey: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
145
|
+
if let wallet = SynchronizerMap[alias] {
|
|
146
|
+
let amount = Int64(zatoshi)
|
|
147
|
+
if amount == nil {
|
|
148
|
+
reject("SpendToAddressError", "Amount is invalid", genericError)
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
wallet.synchronizer.sendToAddress(
|
|
152
|
+
spendingKey:spendingKey,
|
|
153
|
+
zatoshi:amount!,
|
|
154
|
+
toAddress:toAddress,
|
|
155
|
+
memo: memo,
|
|
156
|
+
from:fromAccountIndex
|
|
157
|
+
) { result in
|
|
158
|
+
switch result {
|
|
159
|
+
case .success(let pendingTransaction):
|
|
160
|
+
if (pendingTransaction.rawTransactionId != nil && pendingTransaction.raw != nil) {
|
|
161
|
+
let tx: NSDictionary = ["txId": pendingTransaction.rawTransactionId!.toHexStringTxId(), "raw":z_hexEncodedString(data:pendingTransaction.raw!)]
|
|
162
|
+
resolve(tx)
|
|
163
|
+
} else {
|
|
164
|
+
reject("SpendToAddressError", "Missing txid or rawtx in success object", genericError)
|
|
165
|
+
}
|
|
166
|
+
case .failure(let error):
|
|
167
|
+
reject("SpendToAddressError", "Failed to spend", error)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
reject("SpendToAddressError", "Wallet does not exist", genericError)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@objc func getTransactions(_ alias: String, _ first: Int, _ last: Int, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
176
|
+
if let wallet = SynchronizerMap[alias] {
|
|
177
|
+
if !wallet.fullySynced {
|
|
178
|
+
reject("GetTransactionsError", "Wallet is not synced", genericError)
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
var out: [NSDictionary] = []
|
|
182
|
+
if let txs = try? wallet.synchronizer.allConfirmedTransactions(from:nil, limit:Int.max) {
|
|
183
|
+
// Get all txs, all the time, because the iOS SDK doesn't support querying by block height
|
|
184
|
+
for tx in txs {
|
|
185
|
+
if (tx.rawTransactionId != nil) {
|
|
186
|
+
var confTx = ConfirmedTx(
|
|
187
|
+
minedHeight: tx.minedHeight,
|
|
188
|
+
rawTransactionId: (tx.rawTransactionId?.toHexStringTxId())!,
|
|
189
|
+
blockTimeInSeconds: Int(tx.blockTimeInSeconds),
|
|
190
|
+
value: String(describing: tx.value)
|
|
191
|
+
)
|
|
192
|
+
if (tx.toAddress != nil) {
|
|
193
|
+
confTx.toAddress = tx.toAddress
|
|
194
|
+
}
|
|
195
|
+
if (tx.memo != nil) {
|
|
196
|
+
confTx.memo = String(bytes: tx.memo!, encoding: .utf8)
|
|
197
|
+
}
|
|
198
|
+
out.append(confTx.nsDictionary)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
resolve(out)
|
|
202
|
+
} else {
|
|
203
|
+
reject("GetTransactionsError", "Failed to query transactions", genericError)
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
reject("GetTransactionsError", "Wallet does not exist", genericError)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@objc func getShieldedBalance(_ alias: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
211
|
+
if let wallet = SynchronizerMap[alias] {
|
|
212
|
+
let total = String(describing: wallet.synchronizer.getShieldedBalance())
|
|
213
|
+
let available = String(describing: wallet.synchronizer.getShieldedVerifiedBalance())
|
|
214
|
+
let balance = ShieldedBalance(availableZatoshi:available, totalZatoshi:total)
|
|
215
|
+
resolve(balance.nsDictionary)
|
|
216
|
+
} else {
|
|
217
|
+
reject("GetShieldedBalanceError", "Wallet does not exist", genericError)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@objc func rescan(_ alias: String, _ height: Int, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
222
|
+
if let wallet = SynchronizerMap[alias] {
|
|
223
|
+
do {
|
|
224
|
+
try wallet.synchronizer.rewind(.height(blockheight: height))
|
|
225
|
+
wallet.restart = true
|
|
226
|
+
wallet.fullySynced = false
|
|
227
|
+
} catch {
|
|
228
|
+
reject("RescanError", "Failed to rescan wallet", error)
|
|
229
|
+
}
|
|
230
|
+
resolve(nil)
|
|
231
|
+
} else {
|
|
232
|
+
reject("RescanError", "Wallet does not exist", genericError)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Derivation Tool
|
|
237
|
+
private func getDerivationToolForNetwork(_ network: String) -> DerivationTool {
|
|
238
|
+
switch network {
|
|
239
|
+
case "testnet":
|
|
240
|
+
return DerivationTool(networkType:ZcashNetworkBuilder.network(for: .testnet).networkType)
|
|
241
|
+
default:
|
|
242
|
+
return DerivationTool(networkType:ZcashNetworkBuilder.network(for: .mainnet).networkType)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
@objc func deriveViewingKey(_ seed: String, _ network: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
247
|
+
let derivationTool = getDerivationToolForNetwork(network)
|
|
248
|
+
if let viewingKeys: [UnifiedViewingKey] = try? derivationTool.deriveUnifiedViewingKeysFromSeed(seed.hexaBytes, numberOfAccounts:1) {
|
|
249
|
+
let out = ["extfvk": viewingKeys[0].extfvk, "extpub": viewingKeys[0].extpub]
|
|
250
|
+
resolve(out);
|
|
251
|
+
} else {
|
|
252
|
+
reject("DeriveViewingKeyError", "Failed to derive viewing key", genericError)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
@objc func deriveSpendingKey(_ seed: String, _ network: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
257
|
+
let derivationTool = getDerivationToolForNetwork(network)
|
|
258
|
+
if let spendingKeys: [String] = try? derivationTool.deriveSpendingKeys(seed:seed.hexaBytes, numberOfAccounts:1) {
|
|
259
|
+
resolve(spendingKeys[0]);
|
|
260
|
+
} else {
|
|
261
|
+
reject("DeriveSpendingKeyError", "Failed to derive spending key", genericError)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
@objc func deriveShieldedAddress(_ viewingKey: String, _ network: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
266
|
+
let derivationTool = getDerivationToolForNetwork(network)
|
|
267
|
+
if let address: String = try? derivationTool.deriveShieldedAddress(viewingKey:viewingKey) {
|
|
268
|
+
resolve(address);
|
|
269
|
+
} else {
|
|
270
|
+
reject("DeriveShieldedAddressError", "Failed to derive shielded address", genericError)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
@objc func isValidShieldedAddress(_ address: String, _ network: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
275
|
+
let derivationTool = getDerivationToolForNetwork(network)
|
|
276
|
+
if let bool = try? derivationTool.isValidShieldedAddress(address) {
|
|
277
|
+
resolve(bool);
|
|
278
|
+
} else {
|
|
279
|
+
resolve(false)
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
@objc func isValidTransparentAddress(_ address: String, _ network: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
|
|
284
|
+
let derivationTool = getDerivationToolForNetwork(network)
|
|
285
|
+
if let bool = try? derivationTool.isValidTransparentAddress(address) {
|
|
286
|
+
resolve(bool);
|
|
287
|
+
} else {
|
|
288
|
+
resolve(false)
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Events
|
|
293
|
+
public func sendToJs(name: String, data: Any) {
|
|
294
|
+
self.sendEvent(withName:name, body:data)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
override func supportedEvents() -> [String] {
|
|
298
|
+
return ["StatusEvent", "UpdateEvent"]
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
class WalletSynchronizer : NSObject {
|
|
304
|
+
public var alias: String
|
|
305
|
+
public var synchronizer: SDKSynchronizer
|
|
306
|
+
var status: String
|
|
307
|
+
var emit: (String, Any) -> Void
|
|
308
|
+
var fullySynced: Bool
|
|
309
|
+
var restart: Bool
|
|
310
|
+
var processorState: ProcessorState
|
|
311
|
+
|
|
312
|
+
init(alias: String, initializer: Initializer, emitter:@escaping (String, Any) -> Void) throws {
|
|
313
|
+
self.alias = alias
|
|
314
|
+
self.synchronizer = try SDKSynchronizer(initializer:initializer)
|
|
315
|
+
self.status = "DISCONNECTED"
|
|
316
|
+
self.emit = emitter
|
|
317
|
+
self.fullySynced = false
|
|
318
|
+
self.restart = false
|
|
319
|
+
self.processorState = ProcessorState(
|
|
320
|
+
alias:self.alias,
|
|
321
|
+
lastDownloadedHeight:0,
|
|
322
|
+
lastScannedHeight:0,
|
|
323
|
+
scanProgress:0,
|
|
324
|
+
networkBlockHeight:0
|
|
325
|
+
)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
public func subscribe() {
|
|
329
|
+
// Processor status
|
|
330
|
+
NotificationCenter.default.addObserver(self, selector: #selector(updateProcessorState(notification:)), name: .blockProcessorUpdated, object: self.synchronizer.blockProcessor)
|
|
331
|
+
// Synchronizer Status
|
|
332
|
+
NotificationCenter.default.addObserver(self, selector: #selector(updateSyncStatus(notification:)), name: .synchronizerDisconnected, object: self.synchronizer)
|
|
333
|
+
NotificationCenter.default.addObserver(self, selector: #selector(updateSyncStatus(notification:)), name: .synchronizerStopped, object: self.synchronizer)
|
|
334
|
+
NotificationCenter.default.addObserver(self, selector: #selector(updateSyncStatus(notification:)), name: .synchronizerSynced, object: self.synchronizer)
|
|
335
|
+
NotificationCenter.default.addObserver(self, selector: #selector(updateSyncStatus(notification:)), name: .synchronizerDownloading, object: self.synchronizer)
|
|
336
|
+
NotificationCenter.default.addObserver(self, selector: #selector(updateSyncStatus(notification:)), name: .synchronizerValidating, object: self.synchronizer)
|
|
337
|
+
NotificationCenter.default.addObserver(self, selector: #selector(updateSyncStatus(notification:)), name: .synchronizerScanning, object: self.synchronizer)
|
|
338
|
+
NotificationCenter.default.addObserver(self, selector: #selector(updateSyncStatus(notification:)), name: .synchronizerEnhancing, object: self.synchronizer)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
@objc public func updateSyncStatus(notification: NSNotification) {
|
|
342
|
+
if !self.fullySynced {
|
|
343
|
+
switch notification.name.rawValue {
|
|
344
|
+
case "SDKSyncronizerStopped":
|
|
345
|
+
self.status = "STOPPED"
|
|
346
|
+
if (self.restart == true) {
|
|
347
|
+
try! self.synchronizer.start()
|
|
348
|
+
initializeProcessorState()
|
|
349
|
+
self.restart = false
|
|
350
|
+
}
|
|
351
|
+
case "SDKSyncronizerDisconnected":
|
|
352
|
+
self.status = "DISCONNECTED"
|
|
353
|
+
case "SDKSyncronizerDownloading":
|
|
354
|
+
self.status = "DOWNLOADING"
|
|
355
|
+
case "SDKSyncronizerScanning":
|
|
356
|
+
if (self.processorState.scanProgress < 100) {
|
|
357
|
+
self.status = "SCANNING"
|
|
358
|
+
} else {
|
|
359
|
+
self.status = "SYNCED"
|
|
360
|
+
}
|
|
361
|
+
case "SDKSyncronizerSynced":
|
|
362
|
+
self.status = "SYNCED"
|
|
363
|
+
self.fullySynced = true
|
|
364
|
+
default:
|
|
365
|
+
break
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
let data: NSDictionary = ["alias": self.alias, "name":self.status]
|
|
369
|
+
emit("StatusEvent", data)
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
@objc public func updateProcessorState(notification: NSNotification) {
|
|
374
|
+
let status: CompactBlockProgress = notification.userInfo![CompactBlockProcessorNotificationKey.progress] as! CompactBlockProgress
|
|
375
|
+
if case .download = status {
|
|
376
|
+
self.processorState.lastDownloadedHeight = status.progressHeight!
|
|
377
|
+
} else if case .scan = status {
|
|
378
|
+
self.processorState.lastScannedHeight = status.progressHeight!
|
|
379
|
+
self.processorState.scanProgress = Int(status.progress * 100)
|
|
380
|
+
} else {
|
|
381
|
+
return
|
|
382
|
+
}
|
|
383
|
+
self.processorState.networkBlockHeight = status.targetHeight!
|
|
384
|
+
emit("UpdateEvent", self.processorState.nsDictionary)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
func initializeProcessorState() {
|
|
388
|
+
self.processorState = ProcessorState(
|
|
389
|
+
alias:self.alias,
|
|
390
|
+
lastDownloadedHeight:0,
|
|
391
|
+
lastScannedHeight:0,
|
|
392
|
+
scanProgress:0,
|
|
393
|
+
networkBlockHeight:0
|
|
394
|
+
)
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Convert hex strings to [UInt8]
|
|
399
|
+
extension StringProtocol {
|
|
400
|
+
var hexaData: Data { .init(hexa) }
|
|
401
|
+
var hexaBytes: [UInt8] { .init(hexa) }
|
|
402
|
+
private var hexa: UnfoldSequence<UInt8, Index> {
|
|
403
|
+
sequence(state: startIndex) { startIndex in
|
|
404
|
+
guard startIndex < self.endIndex else { return nil }
|
|
405
|
+
let endIndex = self.index(startIndex, offsetBy: 2, limitedBy: self.endIndex) ?? self.endIndex
|
|
406
|
+
defer { startIndex = endIndex }
|
|
407
|
+
return UInt8(self[startIndex..<endIndex], radix: 16)
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
func z_hexEncodedString(data: Data) -> String {
|
|
413
|
+
let hexDigits = Array("0123456789abcdef".utf16)
|
|
414
|
+
var chars: [unichar] = []
|
|
415
|
+
|
|
416
|
+
chars.reserveCapacity(2 * data.count)
|
|
417
|
+
for byte in data {
|
|
418
|
+
chars.append(hexDigits[Int(byte / 16)])
|
|
419
|
+
chars.append(hexDigits[Int(byte % 16)])
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return String(utf16CodeUnits: chars, count: chars.count)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Local file helper funcs
|
|
426
|
+
func documentsDirectoryHelper() throws -> URL {
|
|
427
|
+
try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
func cacheDbURLHelper(_ alias: String, _ network: ZcashNetwork) throws -> URL {
|
|
431
|
+
try documentsDirectoryHelper()
|
|
432
|
+
.appendingPathComponent(
|
|
433
|
+
network.constants.DEFAULT_DB_NAME_PREFIX + alias + ZcashSDK.DEFAULT_CACHES_DB_NAME,
|
|
434
|
+
isDirectory: false
|
|
435
|
+
)
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
func dataDbURLHelper(_ alias: String, _ network: ZcashNetwork) throws -> URL {
|
|
439
|
+
try documentsDirectoryHelper()
|
|
440
|
+
.appendingPathComponent(
|
|
441
|
+
network.constants.DEFAULT_DB_NAME_PREFIX + alias + ZcashSDK.DEFAULT_DATA_DB_NAME,
|
|
442
|
+
isDirectory: false
|
|
443
|
+
)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
func pendingDbURLHelper(_ alias: String, _ network: ZcashNetwork) throws -> URL {
|
|
447
|
+
try documentsDirectoryHelper()
|
|
448
|
+
.appendingPathComponent(network.constants.DEFAULT_DB_NAME_PREFIX + alias + ZcashSDK.DEFAULT_PENDING_DB_NAME)
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
func spendParamsURLHelper(_ alias: String) throws -> URL {
|
|
452
|
+
try documentsDirectoryHelper().appendingPathComponent(alias + "sapling-spend.params")
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
func outputParamsURLHelper(_ alias: String) throws -> URL {
|
|
456
|
+
try documentsDirectoryHelper().appendingPathComponent(alias + "sapling-output.params")
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
// Logger
|
|
461
|
+
class RNZcashLogger: ZcashLightClientKit.Logger {
|
|
462
|
+
enum LogLevel: Int {
|
|
463
|
+
case debug
|
|
464
|
+
case error
|
|
465
|
+
case warning
|
|
466
|
+
case event
|
|
467
|
+
case info
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
enum LoggerType {
|
|
471
|
+
case osLog
|
|
472
|
+
case printerLog
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
var level: LogLevel
|
|
476
|
+
var loggerType: LoggerType
|
|
477
|
+
|
|
478
|
+
init(logLevel: LogLevel, type: LoggerType = .osLog) {
|
|
479
|
+
self.level = logLevel
|
|
480
|
+
self.loggerType = type
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
private static let subsystem = Bundle.main.bundleIdentifier!
|
|
484
|
+
static let oslog = OSLog(subsystem: subsystem, category: "logs")
|
|
485
|
+
|
|
486
|
+
func debug(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
|
487
|
+
guard level.rawValue == LogLevel.debug.rawValue else { return }
|
|
488
|
+
log(level: "DEBUG đ", message: message, file: file, function: function, line: line)
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
func error(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
|
492
|
+
guard level.rawValue <= LogLevel.error.rawValue else { return }
|
|
493
|
+
log(level: "ERROR đĨ", message: message, file: file, function: function, line: line)
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
func warn(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
|
497
|
+
guard level.rawValue <= LogLevel.warning.rawValue else { return }
|
|
498
|
+
log(level: "WARNING â ī¸", message: message, file: file, function: function, line: line)
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
func event(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
|
502
|
+
guard level.rawValue <= LogLevel.event.rawValue else { return }
|
|
503
|
+
log(level: "EVENT âą", message: message, file: file, function: function, line: line)
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
func info(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
|
507
|
+
guard level.rawValue <= LogLevel.info.rawValue else { return }
|
|
508
|
+
log(level: "INFO âšī¸", message: message, file: file, function: function, line: line)
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
private func log(level: String, message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
|
|
512
|
+
let fileName = (String(describing: file) as NSString).lastPathComponent
|
|
513
|
+
switch loggerType {
|
|
514
|
+
case .printerLog:
|
|
515
|
+
print("[\(level)] \(fileName) - \(function) - line: \(line) -> \(message)")
|
|
516
|
+
default:
|
|
517
|
+
os_log(
|
|
518
|
+
"[%{public}@] %{public}@ - %{public}@ - Line: %{public}d -> %{public}@",
|
|
519
|
+
level,
|
|
520
|
+
fileName,
|
|
521
|
+
String(describing: function),
|
|
522
|
+
line,
|
|
523
|
+
message
|
|
524
|
+
)
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
package/ios/RNZcash.xcodeproj/xcuserdata/Matthew.xcuserdatad/xcschemes/xcschememanagement.plist
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>SchemeUserState</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>RNZcash.xcscheme_^#shared#^_</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>orderHint</key>
|
|
10
|
+
<integer>28</integer>
|
|
11
|
+
</dict>
|
|
12
|
+
</dict>
|
|
13
|
+
<key>SuppressBuildableAutocreation</key>
|
|
14
|
+
<dict>
|
|
15
|
+
<key>58B511DA1A9E6C8500147676</key>
|
|
16
|
+
<dict>
|
|
17
|
+
<key>primary</key>
|
|
18
|
+
<true/>
|
|
19
|
+
</dict>
|
|
20
|
+
</dict>
|
|
21
|
+
</dict>
|
|
22
|
+
</plist>
|
|
Binary file
|
package/lib/rnzcash.rn.js
CHANGED
|
@@ -99,37 +99,33 @@ var AddressTool = {
|
|
|
99
99
|
|
|
100
100
|
return deriveShieldedAddress;
|
|
101
101
|
}(),
|
|
102
|
-
deriveTransparentAddress: function () {
|
|
103
|
-
var _deriveTransparentAddress = _asyncToGenerator(function* (seedHex, network) {
|
|
104
|
-
var result = yield RNZcash.deriveTransparentAddress(seedHex, network);
|
|
105
|
-
return result;
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
function deriveTransparentAddress(_x7, _x8) {
|
|
109
|
-
return _deriveTransparentAddress.apply(this, arguments);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return deriveTransparentAddress;
|
|
113
|
-
}(),
|
|
114
102
|
isValidShieldedAddress: function () {
|
|
115
|
-
var _isValidShieldedAddress = _asyncToGenerator(function* (address) {
|
|
116
|
-
|
|
103
|
+
var _isValidShieldedAddress = _asyncToGenerator(function* (address, network) {
|
|
104
|
+
if (network === void 0) {
|
|
105
|
+
network = 'mainnet';
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
var result = yield RNZcash.isValidShieldedAddress(address, network);
|
|
117
109
|
return result;
|
|
118
110
|
});
|
|
119
111
|
|
|
120
|
-
function isValidShieldedAddress(
|
|
112
|
+
function isValidShieldedAddress(_x7, _x8) {
|
|
121
113
|
return _isValidShieldedAddress.apply(this, arguments);
|
|
122
114
|
}
|
|
123
115
|
|
|
124
116
|
return isValidShieldedAddress;
|
|
125
117
|
}(),
|
|
126
118
|
isValidTransparentAddress: function () {
|
|
127
|
-
var _isValidTransparentAddress = _asyncToGenerator(function* (address) {
|
|
128
|
-
|
|
119
|
+
var _isValidTransparentAddress = _asyncToGenerator(function* (address, network) {
|
|
120
|
+
if (network === void 0) {
|
|
121
|
+
network = 'mainnet';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
var result = yield RNZcash.isValidTransparentAddress(address, network);
|
|
129
125
|
return result;
|
|
130
126
|
});
|
|
131
127
|
|
|
132
|
-
function isValidTransparentAddress(_x10) {
|
|
128
|
+
function isValidTransparentAddress(_x9, _x10) {
|
|
133
129
|
return _isValidTransparentAddress.apply(this, arguments);
|
|
134
130
|
}
|
|
135
131
|
|
|
@@ -366,16 +362,10 @@ var Synchronizer = /*#__PURE__*/function () {
|
|
|
366
362
|
;
|
|
367
363
|
|
|
368
364
|
_proto.subscribe = function subscribe(_ref) {
|
|
369
|
-
var
|
|
370
|
-
|
|
371
|
-
onTransactionsChanged = _ref.onTransactionsChanged,
|
|
372
|
-
onUpdate = _ref.onUpdate,
|
|
373
|
-
onPendingTransactionUpdated = _ref.onPendingTransactionUpdated;
|
|
374
|
-
this.setListener('BalanceEvent', onShieldedBalanceChanged);
|
|
365
|
+
var onStatusChanged = _ref.onStatusChanged,
|
|
366
|
+
onUpdate = _ref.onUpdate;
|
|
375
367
|
this.setListener('StatusEvent', onStatusChanged);
|
|
376
|
-
this.setListener('TransactionEvent', onTransactionsChanged);
|
|
377
368
|
this.setListener('UpdateEvent', onUpdate);
|
|
378
|
-
this.setListener('PendingTransactionUpdated', onPendingTransactionUpdated);
|
|
379
369
|
};
|
|
380
370
|
|
|
381
371
|
_proto.setListener = function setListener(eventName, callback) {
|