react-native-rgb 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/LICENSE +20 -0
- package/README.md +165 -0
- package/Rgb.podspec +23 -0
- package/android/build.gradle +80 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/rgb/AppConstants.kt +57 -0
- package/android/src/main/java/com/rgb/RgbModule.kt +1959 -0
- package/android/src/main/java/com/rgb/RgbPackage.kt +33 -0
- package/android/src/main/java/com/rgb/WalletStore.kt +49 -0
- package/ios/AppConstants.swift +71 -0
- package/ios/Rgb.h +5 -0
- package/ios/Rgb.mm +1740 -0
- package/ios/Rgb.swift +1916 -0
- package/ios/RgbLib.swift +7615 -0
- package/ios/WalletStore.swift +61 -0
- package/lib/module/Interfaces.js +65 -0
- package/lib/module/Interfaces.js.map +1 -0
- package/lib/module/NativeRgb.js +5 -0
- package/lib/module/NativeRgb.js.map +1 -0
- package/lib/module/RgbError.js +65 -0
- package/lib/module/RgbError.js.map +1 -0
- package/lib/module/Wallet.js +854 -0
- package/lib/module/Wallet.js.map +1 -0
- package/lib/module/index.js +39 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/Interfaces.d.ts +390 -0
- package/lib/typescript/src/Interfaces.d.ts.map +1 -0
- package/lib/typescript/src/NativeRgb.d.ts +417 -0
- package/lib/typescript/src/NativeRgb.d.ts.map +1 -0
- package/lib/typescript/src/RgbError.d.ts +28 -0
- package/lib/typescript/src/RgbError.d.ts.map +1 -0
- package/lib/typescript/src/Wallet.d.ts +648 -0
- package/lib/typescript/src/Wallet.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +28 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +174 -0
- package/src/Interfaces.ts +376 -0
- package/src/NativeRgb.ts +630 -0
- package/src/RgbError.ts +84 -0
- package/src/Wallet.ts +1118 -0
- package/src/index.tsx +46 -0
|
@@ -0,0 +1,1959 @@
|
|
|
1
|
+
package com.rgb
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.facebook.react.bridge.Arguments
|
|
5
|
+
import com.facebook.react.bridge.Promise
|
|
6
|
+
import com.facebook.react.bridge.ReadableArray
|
|
7
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
8
|
+
import com.facebook.react.bridge.WritableMap
|
|
9
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
10
|
+
import kotlinx.coroutines.CoroutineScope
|
|
11
|
+
import kotlinx.coroutines.Dispatchers
|
|
12
|
+
import kotlinx.coroutines.SupervisorJob
|
|
13
|
+
import kotlinx.coroutines.launch
|
|
14
|
+
import kotlinx.coroutines.withContext
|
|
15
|
+
import org.rgbtools.AssetSchema
|
|
16
|
+
import org.rgbtools.Assignment
|
|
17
|
+
import org.rgbtools.BitcoinNetwork
|
|
18
|
+
import org.rgbtools.DatabaseType
|
|
19
|
+
import org.rgbtools.RefreshFilter
|
|
20
|
+
import org.rgbtools.Recipient
|
|
21
|
+
import org.rgbtools.RefreshTransferStatus
|
|
22
|
+
import org.rgbtools.Wallet
|
|
23
|
+
import org.rgbtools.WalletData
|
|
24
|
+
import org.rgbtools.WitnessData
|
|
25
|
+
import org.rgbtools.generateKeys
|
|
26
|
+
import org.rgbtools.restoreKeys
|
|
27
|
+
import com.facebook.react.bridge.ReadableMap
|
|
28
|
+
import com.facebook.react.bridge.ReadableType
|
|
29
|
+
import org.rgbtools.Token
|
|
30
|
+
import org.rgbtools.Invoice
|
|
31
|
+
|
|
32
|
+
@ReactModule(name = RgbModule.NAME)
|
|
33
|
+
class RgbModule(reactContext: ReactApplicationContext) :
|
|
34
|
+
NativeRgbSpec(reactContext) {
|
|
35
|
+
private val coroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
|
36
|
+
private val TAG = "RNRgb"
|
|
37
|
+
|
|
38
|
+
init {
|
|
39
|
+
AppConstants.ensureInitialized(reactContext)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
override fun getName(): String {
|
|
43
|
+
return NAME
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
companion object {
|
|
47
|
+
const val NAME = "Rgb"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private suspend fun resolvePromise(promise: Promise, result: String) {
|
|
51
|
+
withContext(Dispatchers.Main) {
|
|
52
|
+
promise.resolve(result)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private fun getErrorClassName(exception: Exception): String {
|
|
57
|
+
val className = exception.javaClass.name
|
|
58
|
+
// Handle nested classes (separated by $)
|
|
59
|
+
val parts = className.split('$')
|
|
60
|
+
// Take the last part and split by . to get simple name
|
|
61
|
+
val lastPart = parts.last().split('.').last()
|
|
62
|
+
return lastPart
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private fun parseErrorMessage(message: String?): String {
|
|
66
|
+
if (message == null) return "Unknown error"
|
|
67
|
+
// Remove "details=" prefix if present
|
|
68
|
+
return if (message.startsWith("details=", ignoreCase = true)) {
|
|
69
|
+
message.substring(8).trim()
|
|
70
|
+
} else {
|
|
71
|
+
message
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
override fun generateKeys(bitcoinNetwork: String, promise: Promise) {
|
|
76
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
77
|
+
try {
|
|
78
|
+
val network = when (bitcoinNetwork) {
|
|
79
|
+
"MAINNET" -> BitcoinNetwork.MAINNET
|
|
80
|
+
"TESTNET" -> BitcoinNetwork.TESTNET
|
|
81
|
+
"TESTNET4" -> BitcoinNetwork.TESTNET4
|
|
82
|
+
"REGTEST" -> BitcoinNetwork.REGTEST
|
|
83
|
+
"SIGNET" -> BitcoinNetwork.SIGNET
|
|
84
|
+
else -> throw IllegalArgumentException("Unknown BitcoinNetwork: $bitcoinNetwork")
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
val keys = generateKeys(bitcoinNetwork = network)
|
|
88
|
+
val result = Arguments.createMap()
|
|
89
|
+
result.putString("mnemonic", keys.mnemonic)
|
|
90
|
+
result.putString("xpub", keys.xpub)
|
|
91
|
+
result.putString("accountXpubVanilla", keys.accountXpubVanilla)
|
|
92
|
+
result.putString("accountXpubColored", keys.accountXpubColored)
|
|
93
|
+
result.putString("masterFingerprint", keys.masterFingerprint)
|
|
94
|
+
promise.resolve(result)
|
|
95
|
+
} catch (e: Exception) {
|
|
96
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
override fun restoreKeys(bitcoinNetwork: String, mnemonic: String, promise: Promise) {
|
|
102
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
103
|
+
try {
|
|
104
|
+
val network = when (bitcoinNetwork) {
|
|
105
|
+
"MAINNET" -> BitcoinNetwork.MAINNET
|
|
106
|
+
"TESTNET" -> BitcoinNetwork.TESTNET
|
|
107
|
+
"TESTNET4" -> BitcoinNetwork.TESTNET4
|
|
108
|
+
"REGTEST" -> BitcoinNetwork.REGTEST
|
|
109
|
+
"SIGNET" -> BitcoinNetwork.SIGNET
|
|
110
|
+
else -> throw IllegalArgumentException("Unknown BitcoinNetwork: $bitcoinNetwork")
|
|
111
|
+
}
|
|
112
|
+
val keys = restoreKeys(bitcoinNetwork = network, mnemonic = mnemonic)
|
|
113
|
+
val result = Arguments.createMap()
|
|
114
|
+
result.putString("mnemonic", keys.mnemonic)
|
|
115
|
+
result.putString("xpub", keys.xpub)
|
|
116
|
+
result.putString("accountXpubVanilla", keys.accountXpubVanilla)
|
|
117
|
+
result.putString("accountXpubColored", keys.accountXpubColored)
|
|
118
|
+
result.putString("masterFingerprint", keys.masterFingerprint)
|
|
119
|
+
promise.resolve(result)
|
|
120
|
+
} catch (e: Exception) {
|
|
121
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private fun getNetwork(network: String): BitcoinNetwork {
|
|
127
|
+
return when (network) {
|
|
128
|
+
"MAINNET" -> BitcoinNetwork.MAINNET
|
|
129
|
+
"TESTNET" -> BitcoinNetwork.TESTNET
|
|
130
|
+
"TESTNET4" -> BitcoinNetwork.TESTNET4
|
|
131
|
+
"REGTEST" -> BitcoinNetwork.REGTEST
|
|
132
|
+
"SIGNET" -> BitcoinNetwork.SIGNET
|
|
133
|
+
else -> throw IllegalArgumentException("Unknown BitcoinNetwork: $network")
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private fun getAssetSchema(schema: String): AssetSchema {
|
|
138
|
+
return when (schema) {
|
|
139
|
+
"NIA" -> AssetSchema.NIA
|
|
140
|
+
"UDA" -> AssetSchema.UDA
|
|
141
|
+
"CFA" -> AssetSchema.CFA
|
|
142
|
+
"IFA" -> AssetSchema.IFA
|
|
143
|
+
else -> throw IllegalArgumentException("Unknown AssetSchema: $schema")
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
override fun initializeWallet(
|
|
148
|
+
network: String,
|
|
149
|
+
accountXpubVanilla: String,
|
|
150
|
+
accountXpubColored: String,
|
|
151
|
+
mnemonic: String,
|
|
152
|
+
masterFingerprint: String,
|
|
153
|
+
supportedSchemas: ReadableArray,
|
|
154
|
+
maxAllocationsPerUtxo: Double,
|
|
155
|
+
vanillaKeychain: Double,
|
|
156
|
+
promise: Promise
|
|
157
|
+
) {
|
|
158
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
159
|
+
try {
|
|
160
|
+
val rgbDir = AppConstants.rgbDir
|
|
161
|
+
?: throw IllegalStateException("RGB directory not initialized. Call AppConstants.initContext() first.")
|
|
162
|
+
|
|
163
|
+
val rgbNetwork = getNetwork(network)
|
|
164
|
+
val schemaList = mutableListOf<AssetSchema>()
|
|
165
|
+
for (i in 0 until supportedSchemas.size()) {
|
|
166
|
+
val schemaStr = supportedSchemas.getString(i)
|
|
167
|
+
schemaList.add(getAssetSchema(schemaStr ?: throw IllegalArgumentException("Invalid schema at index $i")))
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
val walletData = WalletData(
|
|
171
|
+
dataDir = rgbDir.absolutePath,
|
|
172
|
+
bitcoinNetwork = rgbNetwork,
|
|
173
|
+
databaseType = DatabaseType.SQLITE,
|
|
174
|
+
maxAllocationsPerUtxo = maxAllocationsPerUtxo.toInt().toUInt(),
|
|
175
|
+
accountXpubVanilla = accountXpubVanilla,
|
|
176
|
+
accountXpubColored = accountXpubColored,
|
|
177
|
+
mnemonic = mnemonic,
|
|
178
|
+
masterFingerprint = masterFingerprint,
|
|
179
|
+
vanillaKeychain = vanillaKeychain.toInt().toUByte(),
|
|
180
|
+
supportedSchemas = schemaList
|
|
181
|
+
)
|
|
182
|
+
val wallet = Wallet(walletData)
|
|
183
|
+
val walletId = WalletStore.create(wallet)
|
|
184
|
+
withContext(Dispatchers.Main) {
|
|
185
|
+
promise.resolve(walletId)
|
|
186
|
+
}
|
|
187
|
+
} catch (e: Exception) {
|
|
188
|
+
Log.e(TAG, "initializeWallet error: ${e.message}", e)
|
|
189
|
+
withContext(Dispatchers.Main) {
|
|
190
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
override fun goOnline(
|
|
197
|
+
walletId: Double,
|
|
198
|
+
skipConsistencyCheck: Boolean,
|
|
199
|
+
indexerUrl: String,
|
|
200
|
+
promise: Promise
|
|
201
|
+
) {
|
|
202
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
203
|
+
try {
|
|
204
|
+
val session = WalletStore.get(walletId.toInt())
|
|
205
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
206
|
+
|
|
207
|
+
val online = session.wallet.goOnline(
|
|
208
|
+
skipConsistencyCheck = skipConsistencyCheck,
|
|
209
|
+
indexerUrl = indexerUrl
|
|
210
|
+
)
|
|
211
|
+
WalletStore.setOnline(walletId.toInt(), online)
|
|
212
|
+
|
|
213
|
+
withContext(Dispatchers.Main) {
|
|
214
|
+
promise.resolve(null)
|
|
215
|
+
}
|
|
216
|
+
} catch (e: Exception) {
|
|
217
|
+
Log.e(TAG, "goOnline error: ${e.message}", e)
|
|
218
|
+
withContext(Dispatchers.Main) {
|
|
219
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
override fun getBtcBalance(
|
|
226
|
+
walletId: Double,
|
|
227
|
+
skipSync: Boolean,
|
|
228
|
+
promise: Promise
|
|
229
|
+
) {
|
|
230
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
231
|
+
try {
|
|
232
|
+
val session = WalletStore.get(walletId.toInt())
|
|
233
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
234
|
+
|
|
235
|
+
val btcBalance = session.wallet.getBtcBalance(
|
|
236
|
+
online = session.online,
|
|
237
|
+
skipSync = skipSync
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
val result = Arguments.createMap()
|
|
241
|
+
|
|
242
|
+
val vanilla = Arguments.createMap()
|
|
243
|
+
vanilla.putDouble("settled", btcBalance.vanilla.settled.toDouble())
|
|
244
|
+
vanilla.putDouble("future", btcBalance.vanilla.future.toDouble())
|
|
245
|
+
vanilla.putDouble("spendable", btcBalance.vanilla.spendable.toDouble())
|
|
246
|
+
|
|
247
|
+
val colored = Arguments.createMap()
|
|
248
|
+
colored.putDouble("settled", btcBalance.colored.settled.toDouble())
|
|
249
|
+
colored.putDouble("future", btcBalance.colored.future.toDouble())
|
|
250
|
+
colored.putDouble("spendable", btcBalance.colored.spendable.toDouble())
|
|
251
|
+
|
|
252
|
+
result.putMap("vanilla", vanilla)
|
|
253
|
+
result.putMap("colored", colored)
|
|
254
|
+
|
|
255
|
+
withContext(Dispatchers.Main) {
|
|
256
|
+
promise.resolve(result)
|
|
257
|
+
}
|
|
258
|
+
} catch (e: Exception) {
|
|
259
|
+
Log.e(TAG, "getBtcBalance error: ${e.message}", e)
|
|
260
|
+
withContext(Dispatchers.Main) {
|
|
261
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
override fun walletClose(walletId: Double, promise: Promise) {
|
|
268
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
269
|
+
try {
|
|
270
|
+
WalletStore.remove(walletId.toInt())
|
|
271
|
+
withContext(Dispatchers.Main) {
|
|
272
|
+
promise.resolve(null)
|
|
273
|
+
}
|
|
274
|
+
} catch (e: Exception) {
|
|
275
|
+
Log.e(TAG, "walletClose error: ${e.message}", e)
|
|
276
|
+
withContext(Dispatchers.Main) {
|
|
277
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Helper functions for type conversions
|
|
284
|
+
private fun getAssignment(assignmentMap: ReadableMap): Assignment {
|
|
285
|
+
val type = assignmentMap.getString("type") ?: throw IllegalArgumentException("Assignment type is required")
|
|
286
|
+
return when (type) {
|
|
287
|
+
"FUNGIBLE" -> {
|
|
288
|
+
val amount = assignmentMap.getDouble("amount").toULong()
|
|
289
|
+
Assignment.Fungible(amount)
|
|
290
|
+
}
|
|
291
|
+
"NON_FUNGIBLE" -> Assignment.NonFungible
|
|
292
|
+
"INFLATION_RIGHT" -> {
|
|
293
|
+
val amount = assignmentMap.getDouble("amount").toULong()
|
|
294
|
+
Assignment.InflationRight(amount)
|
|
295
|
+
}
|
|
296
|
+
"REPLACE_RIGHT" -> Assignment.ReplaceRight
|
|
297
|
+
"ANY" -> Assignment.Any
|
|
298
|
+
else -> throw IllegalArgumentException("Unknown Assignment type: $type")
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
private fun getRefreshFilter(filterMap: ReadableMap): RefreshFilter {
|
|
303
|
+
val statusStr = filterMap.getString("status") ?: throw IllegalArgumentException("RefreshFilter status is required")
|
|
304
|
+
val status = when (statusStr.uppercase()) {
|
|
305
|
+
"WAITING_COUNTERPARTY" -> RefreshTransferStatus.WAITING_COUNTERPARTY
|
|
306
|
+
"WAITING_CONFIRMATIONS" -> RefreshTransferStatus.WAITING_CONFIRMATIONS
|
|
307
|
+
else -> throw IllegalArgumentException("Unknown RefreshTransferStatus: $statusStr")
|
|
308
|
+
}
|
|
309
|
+
val incoming = filterMap.getBoolean("incoming")
|
|
310
|
+
return RefreshFilter(status, incoming)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private fun getRecipient(recipientMap: ReadableMap): Recipient {
|
|
314
|
+
val recipientId = recipientMap.getString("recipientId") ?: throw IllegalArgumentException("Recipient recipientId is required")
|
|
315
|
+
val assignmentMap = recipientMap.getMap("assignment") ?: throw IllegalArgumentException("Recipient assignment is required")
|
|
316
|
+
val assignment = getAssignment(assignmentMap)
|
|
317
|
+
|
|
318
|
+
val transportEndpointsArray = recipientMap.getArray("transportEndpoints") ?: throw IllegalArgumentException("Recipient transportEndpoints is required")
|
|
319
|
+
val transportEndpoints = mutableListOf<String>()
|
|
320
|
+
for (i in 0 until transportEndpointsArray.size()) {
|
|
321
|
+
transportEndpoints.add(transportEndpointsArray.getString(i) ?: "")
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
val witnessData = if (recipientMap.hasKey("witnessData") && recipientMap.getType("witnessData") == ReadableType.Map) {
|
|
325
|
+
val witnessDataMap = recipientMap.getMap("witnessData")
|
|
326
|
+
?: throw IllegalArgumentException("WitnessData map is null")
|
|
327
|
+
|
|
328
|
+
val amountSat = witnessDataMap.getDouble("amountSat").toULong()
|
|
329
|
+
val blinding = if (witnessDataMap.hasKey("blinding") && !witnessDataMap.isNull("blinding")) {
|
|
330
|
+
witnessDataMap.getDouble("blinding").toULong()
|
|
331
|
+
} else {
|
|
332
|
+
null
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
WitnessData(amountSat, blinding)
|
|
336
|
+
} else {
|
|
337
|
+
null
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return Recipient(recipientId, witnessData, assignment, transportEndpoints)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
private fun balanceToMap(balance: org.rgbtools.Balance): WritableMap {
|
|
344
|
+
val map = Arguments.createMap()
|
|
345
|
+
map.putDouble("settled", balance.settled.toDouble())
|
|
346
|
+
map.putDouble("future", balance.future.toDouble())
|
|
347
|
+
map.putDouble("spendable", balance.spendable.toDouble())
|
|
348
|
+
return map
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
private fun assetCfaToMap(asset: org.rgbtools.AssetCfa): WritableMap {
|
|
352
|
+
val map = Arguments.createMap()
|
|
353
|
+
map.putString("assetId", asset.assetId)
|
|
354
|
+
map.putString("name", asset.name)
|
|
355
|
+
asset.details?.let { map.putString("details", it) }
|
|
356
|
+
map.putInt("precision", asset.precision.toInt())
|
|
357
|
+
map.putDouble("issuedSupply", asset.issuedSupply.toDouble())
|
|
358
|
+
map.putDouble("timestamp", asset.timestamp.toDouble())
|
|
359
|
+
map.putDouble("addedAt", asset.addedAt.toDouble())
|
|
360
|
+
map.putMap("balance", balanceToMap(asset.balance))
|
|
361
|
+
asset.media?.let { media ->
|
|
362
|
+
val mediaMap = Arguments.createMap()
|
|
363
|
+
mediaMap.putString("filePath", media.filePath)
|
|
364
|
+
mediaMap.putString("mime", media.mime)
|
|
365
|
+
mediaMap.putString("digest", media.digest)
|
|
366
|
+
map.putMap("media", mediaMap)
|
|
367
|
+
}
|
|
368
|
+
return map
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
private fun assetIfaToMap(asset: org.rgbtools.AssetIfa): WritableMap {
|
|
372
|
+
val map = Arguments.createMap()
|
|
373
|
+
map.putString("assetId", asset.assetId)
|
|
374
|
+
map.putString("ticker", asset.ticker)
|
|
375
|
+
map.putString("name", asset.name)
|
|
376
|
+
asset.details?.let { map.putString("details", it) }
|
|
377
|
+
map.putInt("precision", asset.precision.toInt())
|
|
378
|
+
map.putDouble("initialSupply", asset.initialSupply.toDouble())
|
|
379
|
+
map.putDouble("maxSupply", asset.maxSupply.toDouble())
|
|
380
|
+
map.putDouble("knownCirculatingSupply", asset.knownCirculatingSupply.toDouble())
|
|
381
|
+
map.putDouble("timestamp", asset.timestamp.toDouble())
|
|
382
|
+
map.putDouble("addedAt", asset.addedAt.toDouble())
|
|
383
|
+
map.putMap("balance", balanceToMap(asset.balance))
|
|
384
|
+
asset.media?.let { media ->
|
|
385
|
+
val mediaMap = Arguments.createMap()
|
|
386
|
+
mediaMap.putString("filePath", media.filePath)
|
|
387
|
+
mediaMap.putString("mime", media.mime)
|
|
388
|
+
mediaMap.putString("digest", media.digest)
|
|
389
|
+
map.putMap("media", mediaMap)
|
|
390
|
+
}
|
|
391
|
+
asset.rejectListUrl?.let { map.putString("rejectListUrl", it) }
|
|
392
|
+
return map
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private fun assetNiaToMap(asset: org.rgbtools.AssetNia): WritableMap {
|
|
396
|
+
val map = Arguments.createMap()
|
|
397
|
+
map.putString("assetId", asset.assetId)
|
|
398
|
+
map.putString("ticker", asset.ticker)
|
|
399
|
+
map.putString("name", asset.name)
|
|
400
|
+
map.putInt("precision", asset.precision.toInt())
|
|
401
|
+
map.putDouble("issuedSupply", asset.issuedSupply.toDouble())
|
|
402
|
+
map.putDouble("timestamp", asset.timestamp.toDouble())
|
|
403
|
+
map.putDouble("addedAt", asset.addedAt.toDouble())
|
|
404
|
+
map.putMap("balance", balanceToMap(asset.balance))
|
|
405
|
+
asset.media?.let { media ->
|
|
406
|
+
val mediaMap = Arguments.createMap()
|
|
407
|
+
mediaMap.putString("filePath", media.filePath)
|
|
408
|
+
mediaMap.putString("mime", media.mime)
|
|
409
|
+
mediaMap.putString("digest", media.digest)
|
|
410
|
+
map.putMap("media", mediaMap)
|
|
411
|
+
}
|
|
412
|
+
return map
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
private fun assetUdaToMap(asset: org.rgbtools.AssetUda): WritableMap {
|
|
416
|
+
val map = Arguments.createMap()
|
|
417
|
+
map.putString("assetId", asset.assetId)
|
|
418
|
+
map.putString("ticker", asset.ticker)
|
|
419
|
+
map.putString("name", asset.name)
|
|
420
|
+
asset.details?.let { map.putString("details", it) }
|
|
421
|
+
map.putInt("precision", asset.precision.toInt())
|
|
422
|
+
map.putDouble("timestamp", asset.timestamp.toDouble())
|
|
423
|
+
map.putDouble("addedAt", asset.addedAt.toDouble())
|
|
424
|
+
map.putMap("balance", balanceToMap(asset.balance))
|
|
425
|
+
asset.token?.let { tokenLight ->
|
|
426
|
+
val token = Arguments.createMap()
|
|
427
|
+
token.putInt("index", tokenLight.index.toInt())
|
|
428
|
+
tokenLight.ticker?.let { token.putString("ticker", it) }
|
|
429
|
+
tokenLight.name?.let { token.putString("name", it) }
|
|
430
|
+
tokenLight.details?.let { token.putString("details", it) }
|
|
431
|
+
token.putBoolean("embeddedMedia", tokenLight.embeddedMedia)
|
|
432
|
+
|
|
433
|
+
tokenLight.media?.let { media ->
|
|
434
|
+
val mediaMap = Arguments.createMap()
|
|
435
|
+
mediaMap.putString("filePath", media.filePath)
|
|
436
|
+
mediaMap.putString("mime", media.mime)
|
|
437
|
+
mediaMap.putString("digest", media.digest)
|
|
438
|
+
token.putMap("media", mediaMap)
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
val attachmentsArray = Arguments.createArray()
|
|
442
|
+
tokenLight.attachments.forEach { (key, media) ->
|
|
443
|
+
val attachmentMap = Arguments.createMap()
|
|
444
|
+
attachmentMap.putInt("key", key.toInt())
|
|
445
|
+
attachmentMap.putString("filePath", media.filePath)
|
|
446
|
+
attachmentMap.putString("mime", media.mime)
|
|
447
|
+
attachmentMap.putString("digest", media.digest)
|
|
448
|
+
attachmentsArray.pushMap(attachmentMap)
|
|
449
|
+
}
|
|
450
|
+
token.putArray("attachments", attachmentsArray)
|
|
451
|
+
token.putBoolean("reserves", tokenLight.reserves)
|
|
452
|
+
map.putMap("token", token)
|
|
453
|
+
}
|
|
454
|
+
return map
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
private fun operationResultToMap(result: org.rgbtools.OperationResult): WritableMap {
|
|
458
|
+
val map = Arguments.createMap()
|
|
459
|
+
map.putString("txid", result.txid)
|
|
460
|
+
map.putInt("batchTransferIdx", result.batchTransferIdx)
|
|
461
|
+
return map
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
private fun receiveDataToMap(data: org.rgbtools.ReceiveData): WritableMap {
|
|
465
|
+
val map = Arguments.createMap()
|
|
466
|
+
map.putString("invoice", data.invoice)
|
|
467
|
+
map.putString("recipientId", data.recipientId)
|
|
468
|
+
data.expirationTimestamp?.let { map.putDouble("expirationTimestamp", it.toDouble()) }
|
|
469
|
+
map.putInt("batchTransferIdx", data.batchTransferIdx)
|
|
470
|
+
return map
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Wallet methods
|
|
474
|
+
override fun backup(walletId: Double, backupPath: String, password: String, promise: Promise) {
|
|
475
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
476
|
+
try {
|
|
477
|
+
val session = WalletStore.get(walletId.toInt())
|
|
478
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
479
|
+
|
|
480
|
+
session.wallet.backup(backupPath, password)
|
|
481
|
+
|
|
482
|
+
withContext(Dispatchers.Main) {
|
|
483
|
+
promise.resolve(null)
|
|
484
|
+
}
|
|
485
|
+
} catch (e: Exception) {
|
|
486
|
+
Log.e(TAG, "backup error: ${e.message}", e)
|
|
487
|
+
withContext(Dispatchers.Main) {
|
|
488
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
override fun backupInfo(walletId: Double, promise: Promise) {
|
|
495
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
496
|
+
try {
|
|
497
|
+
val session = WalletStore.get(walletId.toInt())
|
|
498
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
499
|
+
|
|
500
|
+
val hasBackup = session.wallet.backupInfo()
|
|
501
|
+
|
|
502
|
+
withContext(Dispatchers.Main) {
|
|
503
|
+
promise.resolve(hasBackup)
|
|
504
|
+
}
|
|
505
|
+
} catch (e: Exception) {
|
|
506
|
+
Log.e(TAG, "backupInfo error: ${e.message}", e)
|
|
507
|
+
withContext(Dispatchers.Main) {
|
|
508
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
override fun blindReceive(
|
|
515
|
+
walletId: Double,
|
|
516
|
+
assetId: String?,
|
|
517
|
+
assignment: ReadableMap,
|
|
518
|
+
durationSeconds: Double?,
|
|
519
|
+
transportEndpoints: ReadableArray,
|
|
520
|
+
minConfirmations: Double,
|
|
521
|
+
promise: Promise
|
|
522
|
+
) {
|
|
523
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
524
|
+
try {
|
|
525
|
+
val session = WalletStore.get(walletId.toInt())
|
|
526
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
527
|
+
|
|
528
|
+
val assignmentObj = getAssignment(assignment)
|
|
529
|
+
val endpoints = mutableListOf<String>()
|
|
530
|
+
for (i in 0 until transportEndpoints.size()) {
|
|
531
|
+
endpoints.add(transportEndpoints.getString(i) ?: "")
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
val receiveData = session.wallet.blindReceive(
|
|
535
|
+
assetId,
|
|
536
|
+
assignmentObj,
|
|
537
|
+
durationSeconds?.toInt()?.toUInt(),
|
|
538
|
+
endpoints,
|
|
539
|
+
minConfirmations.toInt().toUByte()
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
withContext(Dispatchers.Main) {
|
|
543
|
+
promise.resolve(receiveDataToMap(receiveData))
|
|
544
|
+
}
|
|
545
|
+
} catch (e: Exception) {
|
|
546
|
+
Log.e(TAG, "blindReceive error: ${e.message}", e)
|
|
547
|
+
withContext(Dispatchers.Main) {
|
|
548
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
override fun createUtxos(
|
|
555
|
+
walletId: Double,
|
|
556
|
+
upTo: Boolean,
|
|
557
|
+
num: Double?,
|
|
558
|
+
size: Double?,
|
|
559
|
+
feeRate: Double,
|
|
560
|
+
skipSync: Boolean,
|
|
561
|
+
promise: Promise
|
|
562
|
+
) {
|
|
563
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
564
|
+
try {
|
|
565
|
+
val session = WalletStore.get(walletId.toInt())
|
|
566
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
567
|
+
|
|
568
|
+
val online = session.online
|
|
569
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
570
|
+
|
|
571
|
+
val count = session.wallet.createUtxos(
|
|
572
|
+
online,
|
|
573
|
+
upTo,
|
|
574
|
+
num?.toInt()?.toUByte(),
|
|
575
|
+
size?.toInt()?.toUInt(),
|
|
576
|
+
feeRate.toULong(),
|
|
577
|
+
skipSync
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
withContext(Dispatchers.Main) {
|
|
581
|
+
promise.resolve(count.toInt())
|
|
582
|
+
}
|
|
583
|
+
} catch (e: Exception) {
|
|
584
|
+
Log.e(TAG, "createUtxos error: ${e.message}", e)
|
|
585
|
+
withContext(Dispatchers.Main) {
|
|
586
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
override fun createUtxosBegin(
|
|
593
|
+
walletId: Double,
|
|
594
|
+
upTo: Boolean,
|
|
595
|
+
num: Double?,
|
|
596
|
+
size: Double?,
|
|
597
|
+
feeRate: Double,
|
|
598
|
+
skipSync: Boolean,
|
|
599
|
+
promise: Promise
|
|
600
|
+
) {
|
|
601
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
602
|
+
try {
|
|
603
|
+
val session = WalletStore.get(walletId.toInt())
|
|
604
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
605
|
+
|
|
606
|
+
val online = session.online
|
|
607
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
608
|
+
|
|
609
|
+
val psbt = session.wallet.createUtxosBegin(
|
|
610
|
+
online,
|
|
611
|
+
upTo,
|
|
612
|
+
num?.toInt()?.toUByte(),
|
|
613
|
+
size?.toInt()?.toUInt(),
|
|
614
|
+
feeRate.toULong(),
|
|
615
|
+
skipSync
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
withContext(Dispatchers.Main) {
|
|
619
|
+
promise.resolve(psbt)
|
|
620
|
+
}
|
|
621
|
+
} catch (e: Exception) {
|
|
622
|
+
Log.e(TAG, "createUtxosBegin error: ${e.message}", e)
|
|
623
|
+
withContext(Dispatchers.Main) {
|
|
624
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
override fun createUtxosEnd(
|
|
631
|
+
walletId: Double,
|
|
632
|
+
signedPsbt: String,
|
|
633
|
+
skipSync: Boolean,
|
|
634
|
+
promise: Promise
|
|
635
|
+
) {
|
|
636
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
637
|
+
try {
|
|
638
|
+
val session = WalletStore.get(walletId.toInt())
|
|
639
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
640
|
+
|
|
641
|
+
val online = session.online
|
|
642
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
643
|
+
|
|
644
|
+
val count = session.wallet.createUtxosEnd(online, signedPsbt, skipSync)
|
|
645
|
+
|
|
646
|
+
withContext(Dispatchers.Main) {
|
|
647
|
+
promise.resolve(count.toInt())
|
|
648
|
+
}
|
|
649
|
+
} catch (e: Exception) {
|
|
650
|
+
Log.e(TAG, "createUtxosEnd error: ${e.message}", e)
|
|
651
|
+
withContext(Dispatchers.Main) {
|
|
652
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
override fun deleteTransfers(
|
|
659
|
+
walletId: Double,
|
|
660
|
+
batchTransferIdx: Double?,
|
|
661
|
+
noAssetOnly: Boolean,
|
|
662
|
+
promise: Promise
|
|
663
|
+
) {
|
|
664
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
665
|
+
try {
|
|
666
|
+
val session = WalletStore.get(walletId.toInt())
|
|
667
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
668
|
+
|
|
669
|
+
val deleted = session.wallet.deleteTransfers(
|
|
670
|
+
batchTransferIdx?.toInt(),
|
|
671
|
+
noAssetOnly
|
|
672
|
+
)
|
|
673
|
+
|
|
674
|
+
withContext(Dispatchers.Main) {
|
|
675
|
+
promise.resolve(deleted)
|
|
676
|
+
}
|
|
677
|
+
} catch (e: Exception) {
|
|
678
|
+
Log.e(TAG, "deleteTransfers error: ${e.message}", e)
|
|
679
|
+
withContext(Dispatchers.Main) {
|
|
680
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
override fun drainTo(
|
|
687
|
+
walletId: Double,
|
|
688
|
+
address: String,
|
|
689
|
+
destroyAssets: Boolean,
|
|
690
|
+
feeRate: Double,
|
|
691
|
+
promise: Promise
|
|
692
|
+
) {
|
|
693
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
694
|
+
try {
|
|
695
|
+
val session = WalletStore.get(walletId.toInt())
|
|
696
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
697
|
+
|
|
698
|
+
val online = session.online
|
|
699
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
700
|
+
|
|
701
|
+
val txid = session.wallet.drainTo(online, address, destroyAssets, feeRate.toULong())
|
|
702
|
+
|
|
703
|
+
withContext(Dispatchers.Main) {
|
|
704
|
+
promise.resolve(txid)
|
|
705
|
+
}
|
|
706
|
+
} catch (e: Exception) {
|
|
707
|
+
Log.e(TAG, "drainTo error: ${e.message}", e)
|
|
708
|
+
withContext(Dispatchers.Main) {
|
|
709
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
override fun drainToBegin(
|
|
716
|
+
walletId: Double,
|
|
717
|
+
address: String,
|
|
718
|
+
destroyAssets: Boolean,
|
|
719
|
+
feeRate: Double,
|
|
720
|
+
promise: Promise
|
|
721
|
+
) {
|
|
722
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
723
|
+
try {
|
|
724
|
+
val session = WalletStore.get(walletId.toInt())
|
|
725
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
726
|
+
|
|
727
|
+
val online = session.online
|
|
728
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
729
|
+
|
|
730
|
+
val psbt = session.wallet.drainToBegin(online, address, destroyAssets, feeRate.toULong())
|
|
731
|
+
|
|
732
|
+
withContext(Dispatchers.Main) {
|
|
733
|
+
promise.resolve(psbt)
|
|
734
|
+
}
|
|
735
|
+
} catch (e: Exception) {
|
|
736
|
+
Log.e(TAG, "drainToBegin error: ${e.message}", e)
|
|
737
|
+
withContext(Dispatchers.Main) {
|
|
738
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
override fun drainToEnd(
|
|
745
|
+
walletId: Double,
|
|
746
|
+
signedPsbt: String,
|
|
747
|
+
promise: Promise
|
|
748
|
+
) {
|
|
749
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
750
|
+
try {
|
|
751
|
+
val session = WalletStore.get(walletId.toInt())
|
|
752
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
753
|
+
|
|
754
|
+
val online = session.online
|
|
755
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
756
|
+
|
|
757
|
+
val txid = session.wallet.drainToEnd(online, signedPsbt)
|
|
758
|
+
|
|
759
|
+
withContext(Dispatchers.Main) {
|
|
760
|
+
promise.resolve(txid)
|
|
761
|
+
}
|
|
762
|
+
} catch (e: Exception) {
|
|
763
|
+
Log.e(TAG, "drainToEnd error: ${e.message}", e)
|
|
764
|
+
withContext(Dispatchers.Main) {
|
|
765
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
override fun failTransfers(
|
|
772
|
+
walletId: Double,
|
|
773
|
+
batchTransferIdx: Double?,
|
|
774
|
+
noAssetOnly: Boolean,
|
|
775
|
+
skipSync: Boolean,
|
|
776
|
+
promise: Promise
|
|
777
|
+
) {
|
|
778
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
779
|
+
try {
|
|
780
|
+
val session = WalletStore.get(walletId.toInt())
|
|
781
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
782
|
+
|
|
783
|
+
val online = session.online
|
|
784
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
785
|
+
|
|
786
|
+
val failed = session.wallet.failTransfers(
|
|
787
|
+
online,
|
|
788
|
+
batchTransferIdx?.toInt(),
|
|
789
|
+
noAssetOnly,
|
|
790
|
+
skipSync
|
|
791
|
+
)
|
|
792
|
+
|
|
793
|
+
withContext(Dispatchers.Main) {
|
|
794
|
+
promise.resolve(failed)
|
|
795
|
+
}
|
|
796
|
+
} catch (e: Exception) {
|
|
797
|
+
Log.e(TAG, "failTransfers error: ${e.message}", e)
|
|
798
|
+
withContext(Dispatchers.Main) {
|
|
799
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
override fun finalizePsbt(walletId: Double, signedPsbt: String, promise: Promise) {
|
|
806
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
807
|
+
try {
|
|
808
|
+
val session = WalletStore.get(walletId.toInt())
|
|
809
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
810
|
+
|
|
811
|
+
val finalizedPsbt = session.wallet.finalizePsbt(signedPsbt)
|
|
812
|
+
|
|
813
|
+
withContext(Dispatchers.Main) {
|
|
814
|
+
promise.resolve(finalizedPsbt)
|
|
815
|
+
}
|
|
816
|
+
} catch (e: Exception) {
|
|
817
|
+
Log.e(TAG, "finalizePsbt error: ${e.message}", e)
|
|
818
|
+
withContext(Dispatchers.Main) {
|
|
819
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
override fun getAddress(walletId: Double, promise: Promise) {
|
|
826
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
827
|
+
try {
|
|
828
|
+
val session = WalletStore.get(walletId.toInt())
|
|
829
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
830
|
+
|
|
831
|
+
val address = session.wallet.getAddress()
|
|
832
|
+
|
|
833
|
+
withContext(Dispatchers.Main) {
|
|
834
|
+
promise.resolve(address)
|
|
835
|
+
}
|
|
836
|
+
} catch (e: Exception) {
|
|
837
|
+
Log.e(TAG, "getAddress error: ${e.message}", e)
|
|
838
|
+
withContext(Dispatchers.Main) {
|
|
839
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
override fun getAssetBalance(walletId: Double, assetId: String, promise: Promise) {
|
|
846
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
847
|
+
try {
|
|
848
|
+
val session = WalletStore.get(walletId.toInt())
|
|
849
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
850
|
+
|
|
851
|
+
val balance = session.wallet.getAssetBalance(assetId)
|
|
852
|
+
|
|
853
|
+
withContext(Dispatchers.Main) {
|
|
854
|
+
promise.resolve(balanceToMap(balance))
|
|
855
|
+
}
|
|
856
|
+
} catch (e: Exception) {
|
|
857
|
+
Log.e(TAG, "getAssetBalance error: ${e.message}", e)
|
|
858
|
+
withContext(Dispatchers.Main) {
|
|
859
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
override fun getAssetMetadata(walletId: Double, assetId: String, promise: Promise) {
|
|
866
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
867
|
+
try {
|
|
868
|
+
val session = WalletStore.get(walletId.toInt())
|
|
869
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
870
|
+
|
|
871
|
+
val metadata = session.wallet.getAssetMetadata(assetId)
|
|
872
|
+
val map = Arguments.createMap()
|
|
873
|
+
map.putString("assetId", assetId)
|
|
874
|
+
val assetSchemaString = when (metadata.assetSchema) {
|
|
875
|
+
AssetSchema.NIA -> "NIA"
|
|
876
|
+
AssetSchema.UDA -> "UDA"
|
|
877
|
+
AssetSchema.CFA -> "CFA"
|
|
878
|
+
AssetSchema.IFA -> "IFA"
|
|
879
|
+
}
|
|
880
|
+
map.putString("assetSchema", assetSchemaString)
|
|
881
|
+
map.putString("name", metadata.name)
|
|
882
|
+
map.putInt("precision", metadata.precision.toInt())
|
|
883
|
+
map.putDouble("initialSupply", metadata.initialSupply.toDouble())
|
|
884
|
+
map.putDouble("maxSupply", metadata.maxSupply.toDouble())
|
|
885
|
+
map.putDouble("knownCirculatingSupply", metadata.knownCirculatingSupply.toDouble())
|
|
886
|
+
map.putDouble("timestamp", metadata.timestamp.toDouble())
|
|
887
|
+
metadata.ticker?.let { map.putString("ticker", it) }
|
|
888
|
+
metadata.details?.let { map.putString("details", it) }
|
|
889
|
+
metadata.rejectListUrl?.let { map.putString("rejectListUrl", it) }
|
|
890
|
+
metadata.token?.let { token ->
|
|
891
|
+
val tokenMap = Arguments.createMap()
|
|
892
|
+
tokenMap.putInt("index", token.index.toInt())
|
|
893
|
+
token.ticker?.let { tokenMap.putString("ticker", it) }
|
|
894
|
+
token.name?.let { tokenMap.putString("name", it) }
|
|
895
|
+
token.details?.let { tokenMap.putString("details", it) }
|
|
896
|
+
token.embeddedMedia?.let { embeddedMedia ->
|
|
897
|
+
val embeddedMediaMap = Arguments.createMap()
|
|
898
|
+
embeddedMediaMap.putString("mime", embeddedMedia.mime)
|
|
899
|
+
val dataArray = Arguments.createArray()
|
|
900
|
+
embeddedMedia.data.forEach { dataArray.pushInt(it.toInt()) }
|
|
901
|
+
embeddedMediaMap.putArray("data", dataArray)
|
|
902
|
+
tokenMap.putMap("embeddedMedia", embeddedMediaMap)
|
|
903
|
+
}
|
|
904
|
+
token.media?.let { media ->
|
|
905
|
+
val mediaMap = Arguments.createMap()
|
|
906
|
+
mediaMap.putString("filePath", media.filePath)
|
|
907
|
+
mediaMap.putString("mime", media.mime)
|
|
908
|
+
mediaMap.putString("digest", media.digest)
|
|
909
|
+
tokenMap.putMap("media", mediaMap)
|
|
910
|
+
}
|
|
911
|
+
val attachmentsArray = Arguments.createArray()
|
|
912
|
+
token.attachments.forEach { (key, media) ->
|
|
913
|
+
val attachmentMap = Arguments.createMap()
|
|
914
|
+
attachmentMap.putInt("key", key.toInt())
|
|
915
|
+
attachmentMap.putString("filePath", media.filePath)
|
|
916
|
+
attachmentMap.putString("mime", media.mime)
|
|
917
|
+
attachmentMap.putString("digest", media.digest)
|
|
918
|
+
attachmentsArray.pushMap(attachmentMap)
|
|
919
|
+
}
|
|
920
|
+
tokenMap.putArray("attachments", attachmentsArray)
|
|
921
|
+
token.reserves?.let { reserves ->
|
|
922
|
+
val reservesMap = Arguments.createMap()
|
|
923
|
+
val utxoMap = Arguments.createMap()
|
|
924
|
+
utxoMap.putString("txid", reserves.utxo.txid)
|
|
925
|
+
utxoMap.putDouble("vout", reserves.utxo.vout.toDouble())
|
|
926
|
+
reservesMap.putMap("utxo", utxoMap)
|
|
927
|
+
val proofArray = Arguments.createArray()
|
|
928
|
+
reserves.proof.forEach { proofArray.pushInt(it.toInt()) }
|
|
929
|
+
reservesMap.putArray("proof", proofArray)
|
|
930
|
+
tokenMap.putMap("reserves", reservesMap)
|
|
931
|
+
}
|
|
932
|
+
map.putMap("token", tokenMap)
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
withContext(Dispatchers.Main) {
|
|
936
|
+
promise.resolve(map)
|
|
937
|
+
}
|
|
938
|
+
} catch (e: Exception) {
|
|
939
|
+
Log.e(TAG, "getAssetMetadata error: ${e.message}", e)
|
|
940
|
+
withContext(Dispatchers.Main) {
|
|
941
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
override fun getFeeEstimation(
|
|
948
|
+
walletId: Double,
|
|
949
|
+
blocks: Double,
|
|
950
|
+
promise: Promise
|
|
951
|
+
) {
|
|
952
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
953
|
+
try {
|
|
954
|
+
val session = WalletStore.get(walletId.toInt())
|
|
955
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
956
|
+
|
|
957
|
+
val online = session.online
|
|
958
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
959
|
+
|
|
960
|
+
val feeRate = session.wallet.getFeeEstimation(online, blocks.toInt().toUShort())
|
|
961
|
+
|
|
962
|
+
withContext(Dispatchers.Main) {
|
|
963
|
+
promise.resolve(feeRate)
|
|
964
|
+
}
|
|
965
|
+
} catch (e: Exception) {
|
|
966
|
+
Log.e(TAG, "getFeeEstimation error: ${e.message}", e)
|
|
967
|
+
withContext(Dispatchers.Main) {
|
|
968
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
override fun getMediaDir(walletId: Double, promise: Promise) {
|
|
975
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
976
|
+
try {
|
|
977
|
+
val session = WalletStore.get(walletId.toInt())
|
|
978
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
979
|
+
|
|
980
|
+
val mediaDir = session.wallet.getMediaDir()
|
|
981
|
+
|
|
982
|
+
withContext(Dispatchers.Main) {
|
|
983
|
+
promise.resolve(mediaDir)
|
|
984
|
+
}
|
|
985
|
+
} catch (e: Exception) {
|
|
986
|
+
Log.e(TAG, "getMediaDir error: ${e.message}", e)
|
|
987
|
+
withContext(Dispatchers.Main) {
|
|
988
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
override fun getWalletData(walletId: Double, promise: Promise) {
|
|
995
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
996
|
+
try {
|
|
997
|
+
val session = WalletStore.get(walletId.toInt())
|
|
998
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
999
|
+
|
|
1000
|
+
val walletData = session.wallet.getWalletData()
|
|
1001
|
+
val map = Arguments.createMap()
|
|
1002
|
+
map.putString("dataDir", walletData.dataDir)
|
|
1003
|
+
|
|
1004
|
+
val networkString = when (walletData.bitcoinNetwork) {
|
|
1005
|
+
BitcoinNetwork.MAINNET -> "MAINNET"
|
|
1006
|
+
BitcoinNetwork.TESTNET -> "TESTNET"
|
|
1007
|
+
BitcoinNetwork.TESTNET4 -> "TESTNET4"
|
|
1008
|
+
BitcoinNetwork.REGTEST -> "REGTEST"
|
|
1009
|
+
BitcoinNetwork.SIGNET -> "SIGNET"
|
|
1010
|
+
else -> {
|
|
1011
|
+
throw Exception("Unknown bitcoin network")
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
map.putString("bitcoinNetwork", networkString)
|
|
1015
|
+
|
|
1016
|
+
val dbTypeString = when (walletData.databaseType) {
|
|
1017
|
+
DatabaseType.SQLITE -> "SQLITE"
|
|
1018
|
+
}
|
|
1019
|
+
map.putString("databaseType", dbTypeString)
|
|
1020
|
+
|
|
1021
|
+
map.putDouble("maxAllocationsPerUtxo", walletData.maxAllocationsPerUtxo.toDouble())
|
|
1022
|
+
map.putString("accountXpubVanilla", walletData.accountXpubVanilla)
|
|
1023
|
+
map.putString("accountXpubColored", walletData.accountXpubColored)
|
|
1024
|
+
walletData.mnemonic?.let { map.putString("mnemonic", it) }
|
|
1025
|
+
map.putString("masterFingerprint", walletData.masterFingerprint)
|
|
1026
|
+
walletData.vanillaKeychain?.let { map.putInt("vanillaKeychain", it.toInt()) }
|
|
1027
|
+
val schemasArray = Arguments.createArray()
|
|
1028
|
+
walletData.supportedSchemas.forEach { schema ->
|
|
1029
|
+
val schemaString = when (schema) {
|
|
1030
|
+
AssetSchema.NIA -> "NIA"
|
|
1031
|
+
AssetSchema.UDA -> "UDA"
|
|
1032
|
+
AssetSchema.CFA -> "CFA"
|
|
1033
|
+
AssetSchema.IFA -> "IFA"
|
|
1034
|
+
}
|
|
1035
|
+
schemasArray.pushString(schemaString)
|
|
1036
|
+
}
|
|
1037
|
+
map.putArray("supportedSchemas", schemasArray)
|
|
1038
|
+
|
|
1039
|
+
withContext(Dispatchers.Main) {
|
|
1040
|
+
promise.resolve(map)
|
|
1041
|
+
}
|
|
1042
|
+
} catch (e: Exception) {
|
|
1043
|
+
Log.e(TAG, "getWalletData error: ${e.message}", e)
|
|
1044
|
+
withContext(Dispatchers.Main) {
|
|
1045
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
override fun getWalletDir(walletId: Double, promise: Promise) {
|
|
1052
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1053
|
+
try {
|
|
1054
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1055
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1056
|
+
|
|
1057
|
+
val walletDir = session.wallet.getWalletDir()
|
|
1058
|
+
|
|
1059
|
+
withContext(Dispatchers.Main) {
|
|
1060
|
+
promise.resolve(walletDir)
|
|
1061
|
+
}
|
|
1062
|
+
} catch (e: Exception) {
|
|
1063
|
+
Log.e(TAG, "getWalletDir error: ${e.message}", e)
|
|
1064
|
+
withContext(Dispatchers.Main) {
|
|
1065
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
override fun inflate(
|
|
1072
|
+
walletId: Double,
|
|
1073
|
+
assetId: String,
|
|
1074
|
+
inflationAmounts: ReadableArray,
|
|
1075
|
+
feeRate: Double,
|
|
1076
|
+
minConfirmations: Double,
|
|
1077
|
+
promise: Promise
|
|
1078
|
+
) {
|
|
1079
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1080
|
+
try {
|
|
1081
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1082
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1083
|
+
|
|
1084
|
+
val online = session.online
|
|
1085
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1086
|
+
|
|
1087
|
+
val amounts = mutableListOf<ULong>()
|
|
1088
|
+
for (i in 0 until inflationAmounts.size()) {
|
|
1089
|
+
amounts.add(inflationAmounts.getDouble(i).toULong())
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
val result = session.wallet.inflate(
|
|
1093
|
+
online,
|
|
1094
|
+
assetId,
|
|
1095
|
+
amounts,
|
|
1096
|
+
feeRate.toULong(),
|
|
1097
|
+
minConfirmations.toInt().toUByte()
|
|
1098
|
+
)
|
|
1099
|
+
|
|
1100
|
+
withContext(Dispatchers.Main) {
|
|
1101
|
+
promise.resolve(operationResultToMap(result))
|
|
1102
|
+
}
|
|
1103
|
+
} catch (e: Exception) {
|
|
1104
|
+
Log.e(TAG, "inflate error: ${e.message}", e)
|
|
1105
|
+
withContext(Dispatchers.Main) {
|
|
1106
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
override fun inflateBegin(
|
|
1113
|
+
walletId: Double,
|
|
1114
|
+
assetId: String,
|
|
1115
|
+
inflationAmounts: ReadableArray,
|
|
1116
|
+
feeRate: Double,
|
|
1117
|
+
minConfirmations: Double,
|
|
1118
|
+
promise: Promise
|
|
1119
|
+
) {
|
|
1120
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1121
|
+
try {
|
|
1122
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1123
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1124
|
+
|
|
1125
|
+
val online = session.online
|
|
1126
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1127
|
+
|
|
1128
|
+
val amounts = mutableListOf<ULong>()
|
|
1129
|
+
for (i in 0 until inflationAmounts.size()) {
|
|
1130
|
+
amounts.add(inflationAmounts.getDouble(i).toULong())
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
val psbt = session.wallet.inflateBegin(
|
|
1134
|
+
online,
|
|
1135
|
+
assetId,
|
|
1136
|
+
amounts,
|
|
1137
|
+
feeRate.toULong(),
|
|
1138
|
+
minConfirmations.toInt().toUByte()
|
|
1139
|
+
)
|
|
1140
|
+
|
|
1141
|
+
withContext(Dispatchers.Main) {
|
|
1142
|
+
promise.resolve(psbt)
|
|
1143
|
+
}
|
|
1144
|
+
} catch (e: Exception) {
|
|
1145
|
+
Log.e(TAG, "inflateBegin error: ${e.message}", e)
|
|
1146
|
+
withContext(Dispatchers.Main) {
|
|
1147
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
override fun inflateEnd(
|
|
1154
|
+
walletId: Double,
|
|
1155
|
+
signedPsbt: String,
|
|
1156
|
+
promise: Promise
|
|
1157
|
+
) {
|
|
1158
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1159
|
+
try {
|
|
1160
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1161
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1162
|
+
|
|
1163
|
+
val online = session.online
|
|
1164
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1165
|
+
|
|
1166
|
+
val result = session.wallet.inflateEnd(online, signedPsbt)
|
|
1167
|
+
|
|
1168
|
+
withContext(Dispatchers.Main) {
|
|
1169
|
+
promise.resolve(operationResultToMap(result))
|
|
1170
|
+
}
|
|
1171
|
+
} catch (e: Exception) {
|
|
1172
|
+
Log.e(TAG, "inflateEnd error: ${e.message}", e)
|
|
1173
|
+
withContext(Dispatchers.Main) {
|
|
1174
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
override fun issueAssetCfa(
|
|
1181
|
+
walletId: Double,
|
|
1182
|
+
name: String,
|
|
1183
|
+
details: String?,
|
|
1184
|
+
precision: Double,
|
|
1185
|
+
amounts: ReadableArray,
|
|
1186
|
+
filePath: String?,
|
|
1187
|
+
promise: Promise
|
|
1188
|
+
) {
|
|
1189
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1190
|
+
try {
|
|
1191
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1192
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1193
|
+
|
|
1194
|
+
val amountsList = mutableListOf<ULong>()
|
|
1195
|
+
for (i in 0 until amounts.size()) {
|
|
1196
|
+
amountsList.add(amounts.getDouble(i).toULong())
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
val asset = session.wallet.issueAssetCfa(
|
|
1200
|
+
name,
|
|
1201
|
+
details,
|
|
1202
|
+
precision.toInt().toUByte(),
|
|
1203
|
+
amountsList,
|
|
1204
|
+
filePath
|
|
1205
|
+
)
|
|
1206
|
+
|
|
1207
|
+
withContext(Dispatchers.Main) {
|
|
1208
|
+
promise.resolve(assetCfaToMap(asset))
|
|
1209
|
+
}
|
|
1210
|
+
} catch (e: Exception) {
|
|
1211
|
+
Log.e(TAG, "issueAssetCfa error: ${e.message}", e)
|
|
1212
|
+
withContext(Dispatchers.Main) {
|
|
1213
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
override fun issueAssetIfa(
|
|
1220
|
+
walletId: Double,
|
|
1221
|
+
ticker: String,
|
|
1222
|
+
name: String,
|
|
1223
|
+
precision: Double,
|
|
1224
|
+
amounts: ReadableArray,
|
|
1225
|
+
inflationAmounts: ReadableArray,
|
|
1226
|
+
replaceRightsNum: Double,
|
|
1227
|
+
rejectListUrl: String?,
|
|
1228
|
+
promise: Promise
|
|
1229
|
+
) {
|
|
1230
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1231
|
+
try {
|
|
1232
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1233
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1234
|
+
|
|
1235
|
+
val amountsList = mutableListOf<ULong>()
|
|
1236
|
+
for (i in 0 until amounts.size()) {
|
|
1237
|
+
amountsList.add(amounts.getDouble(i).toULong())
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
val inflationAmountsList = mutableListOf<ULong>()
|
|
1241
|
+
for (i in 0 until inflationAmounts.size()) {
|
|
1242
|
+
inflationAmountsList.add(inflationAmounts.getDouble(i).toULong())
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
val asset = session.wallet.issueAssetIfa(
|
|
1246
|
+
ticker,
|
|
1247
|
+
name,
|
|
1248
|
+
precision.toInt().toUByte(),
|
|
1249
|
+
amountsList,
|
|
1250
|
+
inflationAmountsList,
|
|
1251
|
+
replaceRightsNum.toInt().toUByte(),
|
|
1252
|
+
rejectListUrl
|
|
1253
|
+
)
|
|
1254
|
+
|
|
1255
|
+
withContext(Dispatchers.Main) {
|
|
1256
|
+
promise.resolve(assetIfaToMap(asset))
|
|
1257
|
+
}
|
|
1258
|
+
} catch (e: Exception) {
|
|
1259
|
+
Log.e(TAG, "issueAssetIfa error: ${e.message}", e)
|
|
1260
|
+
withContext(Dispatchers.Main) {
|
|
1261
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
override fun issueAssetNia(
|
|
1268
|
+
walletId: Double,
|
|
1269
|
+
ticker: String,
|
|
1270
|
+
name: String,
|
|
1271
|
+
precision: Double,
|
|
1272
|
+
amounts: ReadableArray,
|
|
1273
|
+
promise: Promise
|
|
1274
|
+
) {
|
|
1275
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1276
|
+
try {
|
|
1277
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1278
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1279
|
+
|
|
1280
|
+
val amountsList = mutableListOf<ULong>()
|
|
1281
|
+
for (i in 0 until amounts.size()) {
|
|
1282
|
+
amountsList.add(amounts.getDouble(i).toULong())
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
val asset = session.wallet.issueAssetNia(
|
|
1286
|
+
ticker,
|
|
1287
|
+
name,
|
|
1288
|
+
precision.toInt().toUByte(),
|
|
1289
|
+
amountsList
|
|
1290
|
+
)
|
|
1291
|
+
|
|
1292
|
+
withContext(Dispatchers.Main) {
|
|
1293
|
+
promise.resolve(assetNiaToMap(asset))
|
|
1294
|
+
}
|
|
1295
|
+
} catch (e: Exception) {
|
|
1296
|
+
Log.e(TAG, "issueAssetNia error: ${e.message}", e)
|
|
1297
|
+
withContext(Dispatchers.Main) {
|
|
1298
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
override fun issueAssetUda(
|
|
1305
|
+
walletId: Double,
|
|
1306
|
+
ticker: String,
|
|
1307
|
+
name: String,
|
|
1308
|
+
details: String?,
|
|
1309
|
+
precision: Double,
|
|
1310
|
+
mediaFilePath: String?,
|
|
1311
|
+
attachmentsFilePaths: ReadableArray,
|
|
1312
|
+
promise: Promise
|
|
1313
|
+
) {
|
|
1314
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1315
|
+
try {
|
|
1316
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1317
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1318
|
+
|
|
1319
|
+
val attachmentsList = mutableListOf<String>()
|
|
1320
|
+
for (i in 0 until attachmentsFilePaths.size()) {
|
|
1321
|
+
attachmentsList.add(attachmentsFilePaths.getString(i) ?: "")
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
val asset = session.wallet.issueAssetUda(
|
|
1325
|
+
ticker,
|
|
1326
|
+
name,
|
|
1327
|
+
details,
|
|
1328
|
+
precision.toInt().toUByte(),
|
|
1329
|
+
mediaFilePath,
|
|
1330
|
+
attachmentsList
|
|
1331
|
+
)
|
|
1332
|
+
|
|
1333
|
+
withContext(Dispatchers.Main) {
|
|
1334
|
+
promise.resolve(assetUdaToMap(asset))
|
|
1335
|
+
}
|
|
1336
|
+
} catch (e: Exception) {
|
|
1337
|
+
Log.e(TAG, "issueAssetUda error: ${e.message}", e)
|
|
1338
|
+
withContext(Dispatchers.Main) {
|
|
1339
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
override fun listAssets(
|
|
1346
|
+
walletId: Double,
|
|
1347
|
+
filterAssetSchemas: ReadableArray,
|
|
1348
|
+
promise: Promise
|
|
1349
|
+
) {
|
|
1350
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1351
|
+
try {
|
|
1352
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1353
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1354
|
+
|
|
1355
|
+
val schemaList = mutableListOf<AssetSchema>()
|
|
1356
|
+
for (i in 0 until filterAssetSchemas.size()) {
|
|
1357
|
+
val schemaStr = filterAssetSchemas.getString(i)
|
|
1358
|
+
schemaList.add(getAssetSchema(schemaStr ?: ""))
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
val assets = session.wallet.listAssets(schemaList)
|
|
1362
|
+
val result = Arguments.createMap()
|
|
1363
|
+
|
|
1364
|
+
val niaArray = Arguments.createArray()
|
|
1365
|
+
assets.nia?.forEach { asset ->
|
|
1366
|
+
niaArray.pushMap(assetNiaToMap(asset))
|
|
1367
|
+
}
|
|
1368
|
+
result.putArray("nia", niaArray)
|
|
1369
|
+
|
|
1370
|
+
val udaArray = Arguments.createArray()
|
|
1371
|
+
assets.uda?.forEach { asset ->
|
|
1372
|
+
udaArray.pushMap(assetUdaToMap(asset))
|
|
1373
|
+
}
|
|
1374
|
+
result.putArray("uda", udaArray)
|
|
1375
|
+
|
|
1376
|
+
val cfaArray = Arguments.createArray()
|
|
1377
|
+
assets.cfa?.forEach { asset ->
|
|
1378
|
+
cfaArray.pushMap(assetCfaToMap(asset))
|
|
1379
|
+
}
|
|
1380
|
+
result.putArray("cfa", cfaArray)
|
|
1381
|
+
|
|
1382
|
+
val ifaArray = Arguments.createArray()
|
|
1383
|
+
assets.ifa?.forEach { asset ->
|
|
1384
|
+
ifaArray.pushMap(assetIfaToMap(asset))
|
|
1385
|
+
}
|
|
1386
|
+
result.putArray("ifa", ifaArray)
|
|
1387
|
+
|
|
1388
|
+
withContext(Dispatchers.Main) {
|
|
1389
|
+
promise.resolve(result)
|
|
1390
|
+
}
|
|
1391
|
+
} catch (e: Exception) {
|
|
1392
|
+
Log.e(TAG, "listAssets error: ${e.message}", e)
|
|
1393
|
+
withContext(Dispatchers.Main) {
|
|
1394
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
override fun listTransactions(
|
|
1401
|
+
walletId: Double,
|
|
1402
|
+
skipSync: Boolean,
|
|
1403
|
+
promise: Promise
|
|
1404
|
+
) {
|
|
1405
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1406
|
+
try {
|
|
1407
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1408
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1409
|
+
|
|
1410
|
+
val online = session.online
|
|
1411
|
+
|
|
1412
|
+
val transactions = session.wallet.listTransactions(online, skipSync)
|
|
1413
|
+
val transactionsArray = Arguments.createArray()
|
|
1414
|
+
|
|
1415
|
+
transactions.forEach { tx ->
|
|
1416
|
+
val txMap = Arguments.createMap()
|
|
1417
|
+
val txTypeString = when (tx.transactionType) {
|
|
1418
|
+
org.rgbtools.TransactionType.RGB_SEND -> "RGB_SEND"
|
|
1419
|
+
org.rgbtools.TransactionType.DRAIN -> "DRAIN"
|
|
1420
|
+
org.rgbtools.TransactionType.CREATE_UTXOS -> "CREATE_UTXOS"
|
|
1421
|
+
org.rgbtools.TransactionType.USER -> "USER"
|
|
1422
|
+
}
|
|
1423
|
+
txMap.putString("transactionType", txTypeString)
|
|
1424
|
+
txMap.putString("txid", tx.txid)
|
|
1425
|
+
txMap.putDouble("received", tx.received.toDouble())
|
|
1426
|
+
txMap.putDouble("sent", tx.sent.toDouble())
|
|
1427
|
+
txMap.putDouble("fee", tx.fee.toDouble())
|
|
1428
|
+
tx.confirmationTime?.let { blockTime ->
|
|
1429
|
+
txMap.putDouble("confirmationTime", blockTime.timestamp.toDouble())
|
|
1430
|
+
}
|
|
1431
|
+
transactionsArray.pushMap(txMap)
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
withContext(Dispatchers.Main) {
|
|
1435
|
+
promise.resolve(transactionsArray)
|
|
1436
|
+
}
|
|
1437
|
+
} catch (e: Exception) {
|
|
1438
|
+
Log.e(TAG, "listTransactions error: ${e.message}", e)
|
|
1439
|
+
withContext(Dispatchers.Main) {
|
|
1440
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
override fun listTransfers(
|
|
1447
|
+
walletId: Double,
|
|
1448
|
+
assetId: String?,
|
|
1449
|
+
promise: Promise
|
|
1450
|
+
) {
|
|
1451
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1452
|
+
try {
|
|
1453
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1454
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1455
|
+
|
|
1456
|
+
val transfers = session.wallet.listTransfers(assetId)
|
|
1457
|
+
val transfersArray = Arguments.createArray()
|
|
1458
|
+
|
|
1459
|
+
transfers.forEach { transfer ->
|
|
1460
|
+
val transferMap = Arguments.createMap()
|
|
1461
|
+
transferMap.putInt("transferIdx", transfer.idx)
|
|
1462
|
+
transferMap.putInt("batchTransferIdx", transfer.batchTransferIdx)
|
|
1463
|
+
transferMap.putDouble("createdAt", transfer.createdAt.toDouble())
|
|
1464
|
+
transferMap.putDouble("updatedAt", transfer.updatedAt.toDouble())
|
|
1465
|
+
|
|
1466
|
+
val kindString = when (transfer.kind) {
|
|
1467
|
+
org.rgbtools.TransferKind.ISSUANCE -> "ISSUANCE"
|
|
1468
|
+
org.rgbtools.TransferKind.RECEIVE_BLIND -> "RECEIVE_BLIND"
|
|
1469
|
+
org.rgbtools.TransferKind.RECEIVE_WITNESS -> "RECEIVE_WITNESS"
|
|
1470
|
+
org.rgbtools.TransferKind.SEND -> "SEND"
|
|
1471
|
+
org.rgbtools.TransferKind.INFLATION -> "INFLATION"
|
|
1472
|
+
}
|
|
1473
|
+
transferMap.putString("kind", kindString)
|
|
1474
|
+
|
|
1475
|
+
val statusString = when (transfer.status) {
|
|
1476
|
+
org.rgbtools.TransferStatus.WAITING_COUNTERPARTY -> "WAITING_COUNTERPARTY"
|
|
1477
|
+
org.rgbtools.TransferStatus.WAITING_CONFIRMATIONS -> "WAITING_CONFIRMATIONS"
|
|
1478
|
+
org.rgbtools.TransferStatus.SETTLED -> "SETTLED"
|
|
1479
|
+
org.rgbtools.TransferStatus.FAILED -> "FAILED"
|
|
1480
|
+
}
|
|
1481
|
+
transferMap.putString("status", statusString)
|
|
1482
|
+
|
|
1483
|
+
transfer.txid?.let { transferMap.putString("txid", it) }
|
|
1484
|
+
transfer.recipientId?.let { transferMap.putString("recipientId", it) }
|
|
1485
|
+
transfer.receiveUtxo?.let {
|
|
1486
|
+
transferMap.putString("receiveUtxoTxid", it.txid)
|
|
1487
|
+
transferMap.putDouble("receiveUtxoVout", it.vout.toDouble())
|
|
1488
|
+
}
|
|
1489
|
+
transfer.changeUtxo?.let {
|
|
1490
|
+
transferMap.putString("changeUtxoTxid", it.txid)
|
|
1491
|
+
transferMap.putDouble("changeUtxoVout", it.vout.toDouble())
|
|
1492
|
+
}
|
|
1493
|
+
transfer.expiration?.let { transferMap.putDouble("expiration", it.toDouble()) }
|
|
1494
|
+
|
|
1495
|
+
val transportEndpointsStrings = transfer.transportEndpoints.map { it.endpoint }
|
|
1496
|
+
transferMap.putString("transportEndpoints", transportEndpointsStrings.joinToString(","))
|
|
1497
|
+
|
|
1498
|
+
transfer.invoiceString?.let { transferMap.putString("invoiceString", it) }
|
|
1499
|
+
transfer.consignmentPath?.let { transferMap.putString("consignmentPath", it) }
|
|
1500
|
+
|
|
1501
|
+
transferMap.putInt("assignmentsCount", transfer.assignments.size)
|
|
1502
|
+
|
|
1503
|
+
transfersArray.pushMap(transferMap)
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
withContext(Dispatchers.Main) {
|
|
1507
|
+
promise.resolve(transfersArray)
|
|
1508
|
+
}
|
|
1509
|
+
} catch (e: Exception) {
|
|
1510
|
+
Log.e(TAG, "listTransfers error: ${e.message}", e)
|
|
1511
|
+
withContext(Dispatchers.Main) {
|
|
1512
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
override fun listUnspents(
|
|
1519
|
+
walletId: Double,
|
|
1520
|
+
settledOnly: Boolean,
|
|
1521
|
+
skipSync: Boolean,
|
|
1522
|
+
promise: Promise
|
|
1523
|
+
) {
|
|
1524
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1525
|
+
try {
|
|
1526
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1527
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1528
|
+
|
|
1529
|
+
val online = session.online
|
|
1530
|
+
|
|
1531
|
+
val unspents = session.wallet.listUnspents(online, settledOnly, skipSync)
|
|
1532
|
+
val unspentsArray = Arguments.createArray()
|
|
1533
|
+
|
|
1534
|
+
unspents.forEach { unspent ->
|
|
1535
|
+
val unspentMap = Arguments.createMap()
|
|
1536
|
+
val utxoMap = Arguments.createMap()
|
|
1537
|
+
utxoMap.putString("txid", unspent.utxo.outpoint.txid)
|
|
1538
|
+
utxoMap.putDouble("vout", unspent.utxo.outpoint.vout.toDouble())
|
|
1539
|
+
utxoMap.putDouble("btcAmount", unspent.utxo.btcAmount.toDouble())
|
|
1540
|
+
utxoMap.putBoolean("colorable", unspent.utxo.colorable)
|
|
1541
|
+
utxoMap.putBoolean("exists", unspent.utxo.exists)
|
|
1542
|
+
unspentMap.putMap("utxo", utxoMap)
|
|
1543
|
+
unspentMap.putDouble("pendingBlinded", unspent.pendingBlinded.toDouble())
|
|
1544
|
+
unspentMap.putDouble("rgbAllocationsCount", unspent.rgbAllocations.size.toDouble())
|
|
1545
|
+
unspentsArray.pushMap(unspentMap)
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
withContext(Dispatchers.Main) {
|
|
1549
|
+
promise.resolve(unspentsArray)
|
|
1550
|
+
}
|
|
1551
|
+
} catch (e: Exception) {
|
|
1552
|
+
Log.e(TAG, "listUnspents error: ${e.message}", e)
|
|
1553
|
+
withContext(Dispatchers.Main) {
|
|
1554
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
override fun refresh(
|
|
1561
|
+
walletId: Double,
|
|
1562
|
+
assetId: String?,
|
|
1563
|
+
filter: ReadableArray,
|
|
1564
|
+
skipSync: Boolean,
|
|
1565
|
+
promise: Promise
|
|
1566
|
+
) {
|
|
1567
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1568
|
+
try {
|
|
1569
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1570
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1571
|
+
|
|
1572
|
+
val online = session.online
|
|
1573
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1574
|
+
|
|
1575
|
+
val filterList = mutableListOf<RefreshFilter>()
|
|
1576
|
+
for (i in 0 until filter.size()) {
|
|
1577
|
+
val filterMap = filter.getMap(i) ?: continue
|
|
1578
|
+
filterList.add(getRefreshFilter(filterMap))
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
val refreshed = session.wallet.refresh(online, assetId, filterList, skipSync)
|
|
1582
|
+
val result = Arguments.createMap()
|
|
1583
|
+
|
|
1584
|
+
refreshed.forEach { (idx, refreshedTransfer) ->
|
|
1585
|
+
val refreshedMap = Arguments.createMap()
|
|
1586
|
+
refreshedTransfer.updatedStatus?.let { status ->
|
|
1587
|
+
val statusString = when (status) {
|
|
1588
|
+
org.rgbtools.TransferStatus.WAITING_COUNTERPARTY -> "WAITING_COUNTERPARTY"
|
|
1589
|
+
org.rgbtools.TransferStatus.WAITING_CONFIRMATIONS -> "WAITING_CONFIRMATIONS"
|
|
1590
|
+
org.rgbtools.TransferStatus.SETTLED -> "SETTLED"
|
|
1591
|
+
org.rgbtools.TransferStatus.FAILED -> "FAILED"
|
|
1592
|
+
}
|
|
1593
|
+
refreshedMap.putString("updatedStatus", statusString)
|
|
1594
|
+
}
|
|
1595
|
+
refreshedTransfer.failure?.let {
|
|
1596
|
+
refreshedMap.putString("failure", it.toString())
|
|
1597
|
+
}
|
|
1598
|
+
result.putMap(idx.toString(), refreshedMap)
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
withContext(Dispatchers.Main) {
|
|
1602
|
+
promise.resolve(result)
|
|
1603
|
+
}
|
|
1604
|
+
} catch (e: Exception) {
|
|
1605
|
+
Log.e(TAG, "refresh error: ${e.message}", e)
|
|
1606
|
+
withContext(Dispatchers.Main) {
|
|
1607
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
override fun send(
|
|
1614
|
+
walletId: Double,
|
|
1615
|
+
recipientMap: ReadableMap,
|
|
1616
|
+
donation: Boolean,
|
|
1617
|
+
feeRate: Double,
|
|
1618
|
+
minConfirmations: Double,
|
|
1619
|
+
skipSync: Boolean,
|
|
1620
|
+
promise: Promise
|
|
1621
|
+
) {
|
|
1622
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1623
|
+
try {
|
|
1624
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1625
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1626
|
+
|
|
1627
|
+
val online = session.online
|
|
1628
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1629
|
+
|
|
1630
|
+
// Convert ReadableMap to Map<String, List<Recipient>>
|
|
1631
|
+
val recipientMapNative = mutableMapOf<String, List<Recipient>>()
|
|
1632
|
+
val keys = recipientMap.keySetIterator()
|
|
1633
|
+
while (keys.hasNextKey()) {
|
|
1634
|
+
val key = keys.nextKey()
|
|
1635
|
+
val recipientsArray = recipientMap.getArray(key) ?: continue
|
|
1636
|
+
val recipientsList = mutableListOf<Recipient>()
|
|
1637
|
+
for (i in 0 until recipientsArray.size()) {
|
|
1638
|
+
val recipientMapItem = recipientsArray.getMap(i) ?: continue
|
|
1639
|
+
recipientsList.add(getRecipient(recipientMapItem))
|
|
1640
|
+
}
|
|
1641
|
+
recipientMapNative[key] = recipientsList
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
val result = session.wallet.send(
|
|
1645
|
+
online,
|
|
1646
|
+
recipientMapNative,
|
|
1647
|
+
donation,
|
|
1648
|
+
feeRate.toULong(),
|
|
1649
|
+
minConfirmations.toInt().toUByte(),
|
|
1650
|
+
skipSync
|
|
1651
|
+
)
|
|
1652
|
+
|
|
1653
|
+
withContext(Dispatchers.Main) {
|
|
1654
|
+
promise.resolve(operationResultToMap(result))
|
|
1655
|
+
}
|
|
1656
|
+
} catch (e: Exception) {
|
|
1657
|
+
Log.e(TAG, "send error: ${e.message}", e)
|
|
1658
|
+
withContext(Dispatchers.Main) {
|
|
1659
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
override fun sendBegin(
|
|
1666
|
+
walletId: Double,
|
|
1667
|
+
recipientMap: ReadableMap,
|
|
1668
|
+
donation: Boolean,
|
|
1669
|
+
feeRate: Double,
|
|
1670
|
+
minConfirmations: Double,
|
|
1671
|
+
promise: Promise
|
|
1672
|
+
) {
|
|
1673
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1674
|
+
try {
|
|
1675
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1676
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1677
|
+
|
|
1678
|
+
val online = session.online
|
|
1679
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1680
|
+
|
|
1681
|
+
// Convert ReadableMap to Map<String, List<Recipient>>
|
|
1682
|
+
val recipientMapNative = mutableMapOf<String, List<Recipient>>()
|
|
1683
|
+
val keys = recipientMap.keySetIterator()
|
|
1684
|
+
while (keys.hasNextKey()) {
|
|
1685
|
+
val key = keys.nextKey()
|
|
1686
|
+
val recipientsArray = recipientMap.getArray(key) ?: continue
|
|
1687
|
+
val recipientsList = mutableListOf<Recipient>()
|
|
1688
|
+
for (i in 0 until recipientsArray.size()) {
|
|
1689
|
+
val recipientMapItem = recipientsArray.getMap(i) ?: continue
|
|
1690
|
+
recipientsList.add(getRecipient(recipientMapItem))
|
|
1691
|
+
}
|
|
1692
|
+
recipientMapNative[key] = recipientsList
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
val psbt = session.wallet.sendBegin(
|
|
1696
|
+
online,
|
|
1697
|
+
recipientMapNative,
|
|
1698
|
+
donation,
|
|
1699
|
+
feeRate.toULong(),
|
|
1700
|
+
minConfirmations.toInt().toUByte()
|
|
1701
|
+
)
|
|
1702
|
+
|
|
1703
|
+
withContext(Dispatchers.Main) {
|
|
1704
|
+
promise.resolve(psbt)
|
|
1705
|
+
}
|
|
1706
|
+
} catch (e: Exception) {
|
|
1707
|
+
Log.e(TAG, "sendBegin error: ${e.message}", e)
|
|
1708
|
+
withContext(Dispatchers.Main) {
|
|
1709
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
override fun sendBtc(
|
|
1716
|
+
walletId: Double,
|
|
1717
|
+
address: String,
|
|
1718
|
+
amount: Double,
|
|
1719
|
+
feeRate: Double,
|
|
1720
|
+
skipSync: Boolean,
|
|
1721
|
+
promise: Promise
|
|
1722
|
+
) {
|
|
1723
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1724
|
+
try {
|
|
1725
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1726
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1727
|
+
|
|
1728
|
+
val online = session.online
|
|
1729
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1730
|
+
|
|
1731
|
+
val txid = session.wallet.sendBtc(
|
|
1732
|
+
online,
|
|
1733
|
+
address,
|
|
1734
|
+
amount.toULong(),
|
|
1735
|
+
feeRate.toULong(),
|
|
1736
|
+
skipSync
|
|
1737
|
+
)
|
|
1738
|
+
|
|
1739
|
+
withContext(Dispatchers.Main) {
|
|
1740
|
+
promise.resolve(txid)
|
|
1741
|
+
}
|
|
1742
|
+
} catch (e: Exception) {
|
|
1743
|
+
Log.e(TAG, "sendBtc error: ${e.message}", e)
|
|
1744
|
+
withContext(Dispatchers.Main) {
|
|
1745
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
override fun sendBtcBegin(
|
|
1752
|
+
walletId: Double,
|
|
1753
|
+
address: String,
|
|
1754
|
+
amount: Double,
|
|
1755
|
+
feeRate: Double,
|
|
1756
|
+
skipSync: Boolean,
|
|
1757
|
+
promise: Promise
|
|
1758
|
+
) {
|
|
1759
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1760
|
+
try {
|
|
1761
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1762
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1763
|
+
|
|
1764
|
+
val online = session.online
|
|
1765
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1766
|
+
|
|
1767
|
+
val psbt = session.wallet.sendBtcBegin(
|
|
1768
|
+
online,
|
|
1769
|
+
address,
|
|
1770
|
+
amount.toULong(),
|
|
1771
|
+
feeRate.toULong(),
|
|
1772
|
+
skipSync
|
|
1773
|
+
)
|
|
1774
|
+
|
|
1775
|
+
withContext(Dispatchers.Main) {
|
|
1776
|
+
promise.resolve(psbt)
|
|
1777
|
+
}
|
|
1778
|
+
} catch (e: Exception) {
|
|
1779
|
+
Log.e(TAG, "sendBtcBegin error: ${e.message}", e)
|
|
1780
|
+
withContext(Dispatchers.Main) {
|
|
1781
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
override fun sendBtcEnd(
|
|
1788
|
+
walletId: Double,
|
|
1789
|
+
signedPsbt: String,
|
|
1790
|
+
skipSync: Boolean,
|
|
1791
|
+
promise: Promise
|
|
1792
|
+
) {
|
|
1793
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1794
|
+
try {
|
|
1795
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1796
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1797
|
+
|
|
1798
|
+
val online = session.online
|
|
1799
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1800
|
+
|
|
1801
|
+
val txid = session.wallet.sendBtcEnd(online, signedPsbt, skipSync)
|
|
1802
|
+
|
|
1803
|
+
withContext(Dispatchers.Main) {
|
|
1804
|
+
promise.resolve(txid)
|
|
1805
|
+
}
|
|
1806
|
+
} catch (e: Exception) {
|
|
1807
|
+
Log.e(TAG, "sendBtcEnd error: ${e.message}", e)
|
|
1808
|
+
withContext(Dispatchers.Main) {
|
|
1809
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
override fun sendEnd(
|
|
1816
|
+
walletId: Double,
|
|
1817
|
+
signedPsbt: String,
|
|
1818
|
+
skipSync: Boolean,
|
|
1819
|
+
promise: Promise
|
|
1820
|
+
) {
|
|
1821
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1822
|
+
try {
|
|
1823
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1824
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1825
|
+
|
|
1826
|
+
val online = session.online
|
|
1827
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1828
|
+
|
|
1829
|
+
val result = session.wallet.sendEnd(online, signedPsbt, skipSync)
|
|
1830
|
+
|
|
1831
|
+
withContext(Dispatchers.Main) {
|
|
1832
|
+
promise.resolve(operationResultToMap(result))
|
|
1833
|
+
}
|
|
1834
|
+
} catch (e: Exception) {
|
|
1835
|
+
Log.e(TAG, "sendEnd error: ${e.message}", e)
|
|
1836
|
+
withContext(Dispatchers.Main) {
|
|
1837
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
override fun signPsbt(walletId: Double, unsignedPsbt: String, promise: Promise) {
|
|
1844
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1845
|
+
try {
|
|
1846
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1847
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1848
|
+
|
|
1849
|
+
val signedPsbt = session.wallet.signPsbt(unsignedPsbt)
|
|
1850
|
+
|
|
1851
|
+
withContext(Dispatchers.Main) {
|
|
1852
|
+
promise.resolve(signedPsbt)
|
|
1853
|
+
}
|
|
1854
|
+
} catch (e: Exception) {
|
|
1855
|
+
Log.e(TAG, "signPsbt error: ${e.message}", e)
|
|
1856
|
+
withContext(Dispatchers.Main) {
|
|
1857
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
override fun sync(walletId: Double, promise: Promise) {
|
|
1864
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1865
|
+
try {
|
|
1866
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1867
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1868
|
+
|
|
1869
|
+
val online = session.online
|
|
1870
|
+
?: throw IllegalStateException("Wallet is not online")
|
|
1871
|
+
|
|
1872
|
+
session.wallet.sync(online)
|
|
1873
|
+
|
|
1874
|
+
withContext(Dispatchers.Main) {
|
|
1875
|
+
promise.resolve(null)
|
|
1876
|
+
}
|
|
1877
|
+
} catch (e: Exception) {
|
|
1878
|
+
Log.e(TAG, "sync error: ${e.message}", e)
|
|
1879
|
+
withContext(Dispatchers.Main) {
|
|
1880
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
override fun witnessReceive(
|
|
1887
|
+
walletId: Double,
|
|
1888
|
+
assetId: String?,
|
|
1889
|
+
assignment: ReadableMap,
|
|
1890
|
+
durationSeconds: Double?,
|
|
1891
|
+
transportEndpoints: ReadableArray,
|
|
1892
|
+
minConfirmations: Double,
|
|
1893
|
+
promise: Promise
|
|
1894
|
+
) {
|
|
1895
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1896
|
+
try {
|
|
1897
|
+
val session = WalletStore.get(walletId.toInt())
|
|
1898
|
+
?: throw IllegalStateException("Wallet with id $walletId not found")
|
|
1899
|
+
|
|
1900
|
+
val assignmentObj = getAssignment(assignment)
|
|
1901
|
+
val endpoints = mutableListOf<String>()
|
|
1902
|
+
for (i in 0 until transportEndpoints.size()) {
|
|
1903
|
+
endpoints.add(transportEndpoints.getString(i) ?: "")
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
val receiveData = session.wallet.witnessReceive(
|
|
1907
|
+
assetId,
|
|
1908
|
+
assignmentObj,
|
|
1909
|
+
durationSeconds?.toInt()?.toUInt(),
|
|
1910
|
+
endpoints,
|
|
1911
|
+
minConfirmations.toInt().toUByte()
|
|
1912
|
+
)
|
|
1913
|
+
|
|
1914
|
+
withContext(Dispatchers.Main) {
|
|
1915
|
+
promise.resolve(receiveDataToMap(receiveData))
|
|
1916
|
+
}
|
|
1917
|
+
} catch (e: Exception) {
|
|
1918
|
+
Log.e(TAG, "witnessReceive error: ${e.message}", e)
|
|
1919
|
+
withContext(Dispatchers.Main) {
|
|
1920
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
override fun decodeInvoice(invoice: String, promise: Promise) {
|
|
1927
|
+
coroutineScope.launch(Dispatchers.IO) {
|
|
1928
|
+
try {
|
|
1929
|
+
val invoiceData = Invoice(invoiceString = invoice).invoiceData()
|
|
1930
|
+
val map = Arguments.createMap()
|
|
1931
|
+
map.putString("invoice", invoice)
|
|
1932
|
+
map.putString("recipientId", invoiceData.recipientId)
|
|
1933
|
+
map.putString("assetSchema", invoiceData.assetSchema?.toString())
|
|
1934
|
+
map.putString("assetId", invoiceData.assetId)
|
|
1935
|
+
map.putString("assignment", invoiceData.assignment.toString())
|
|
1936
|
+
map.putString("assignmentName", invoiceData.assignmentName)
|
|
1937
|
+
map.putString("network", invoiceData.network.toString())
|
|
1938
|
+
val transportEndpointsStrings = invoiceData.transportEndpoints.map { it }
|
|
1939
|
+
map.putString("transportEndpoints", transportEndpointsStrings.joinToString(","))
|
|
1940
|
+
|
|
1941
|
+
invoiceData.expirationTimestamp?.let {
|
|
1942
|
+
map.putDouble("expirationTimestamp", it.toDouble())
|
|
1943
|
+
} ?: run {
|
|
1944
|
+
map.putNull("expirationTimestamp")
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
withContext(Dispatchers.Main) {
|
|
1948
|
+
promise.resolve(map)
|
|
1949
|
+
}
|
|
1950
|
+
} catch (e: Exception) {
|
|
1951
|
+
Log.e(TAG, "decodeInvoice error: ${e.message}", e)
|
|
1952
|
+
withContext(Dispatchers.Main) {
|
|
1953
|
+
promise.reject(getErrorClassName(e), parseErrorMessage(e.message), e)
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
}
|