react-native-pirate-wallet 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE-MIT ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pirate Chain Developers
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,537 @@
1
+ # react-native-pirate-wallet
2
+
3
+ `react-native-pirate-wallet` is the React Native wrapper for the unified Pirate wallet backend.
4
+
5
+ It exposes one JS API over the same native service layer used by the Android SDK and iOS SDK.
6
+
7
+ The package is meant for React Native wallets such as Edge Wallet.
8
+
9
+ Repo-level build and integration notes:
10
+
11
+ - `docs/react-native-plugin.md`
12
+
13
+ ## What it wraps
14
+
15
+ - Android: JNI bridge over `libpirate_ffi_native.so`
16
+ - iOS: Objective-C bridge over `PirateWalletNative.xcframework`
17
+ - JS: typed wallet wrapper plus a polling synchronizer
18
+
19
+ The JS surface mirrors the SDK boundary used by the native Android and iOS SDKs.
20
+
21
+ ## Account-scoped wallet storage
22
+
23
+ Configure wallet storage before any wallet operation:
24
+
25
+ ```js
26
+ const sdk = createPirateWalletSdk()
27
+
28
+ await sdk.configureAccountStorage({
29
+ accountId: edgeAccountIdHash,
30
+ passphrase: edgeAccountDerivedSecret
31
+ })
32
+ ```
33
+
34
+ The native module creates an app-private directory for that account and asks the
35
+ Rust service to open or create that account's wallet namespace. The selected
36
+ directory contains:
37
+
38
+ - `wallet_registry.db`
39
+ - per-wallet database files
40
+ - database salts
41
+ - sealed database key files
42
+
43
+ The passphrase unlocks both the registry and the per-wallet databases in that
44
+ namespace. It must be unique per local account and derived from high-entropy
45
+ account secret material. Do not use a hardcoded passphrase, a public account ID,
46
+ email address, or device ID as the passphrase.
47
+
48
+ By default, Android derives the directory under:
49
+
50
+ ```text
51
+ Context.filesDir/pirate_wallet/accounts/<sanitized-account-id>
52
+ ```
53
+
54
+ iOS derives the directory under:
55
+
56
+ ```text
57
+ Application Support/PirateWallet/accounts/<sanitized-account-id>
58
+ ```
59
+
60
+ Integrations that need to provide their own app-private path may pass
61
+ `storagePath`:
62
+
63
+ ```js
64
+ await sdk.configureAccountStorage({
65
+ accountId: edgeAccountIdHash,
66
+ storagePath: accountPrivatePath,
67
+ passphrase: edgeAccountDerivedSecret
68
+ })
69
+ ```
70
+
71
+ ## Repo layout
72
+
73
+ - `android/`
74
+ - `example/`
75
+ - `ios/`
76
+ - `scripts/`
77
+ - `src/`
78
+
79
+ The Android native libraries are distributed in the exact-version
80
+ `react-native-pirate-wallet-android` companion package.
81
+
82
+ ## Preparing native artifacts in this repo
83
+
84
+ Before testing or packaging this plugin from the monorepo, stage the native artifacts:
85
+
86
+ ```bash
87
+ bash scripts/prepare-react-native-plugin.sh
88
+ ```
89
+
90
+ That copies:
91
+
92
+ - Android JNI libraries into `bindings/react-native-pirate-wallet-android/`
93
+ - the iOS XCFramework into this package
94
+
95
+ There is also a minimal consumer app in:
96
+
97
+ - `bindings/react-native-pirate-wallet/example/`
98
+
99
+ That app is used to verify install, autolinking, and a couple of real native calls.
100
+
101
+ ## Public JS surface
102
+
103
+ Main exports:
104
+
105
+ - `PirateWalletSdk`
106
+ - `PirateWalletSynchronizer`
107
+ - `createPirateWalletSdk()`
108
+
109
+ The synchronizer is implemented in JS and polls the native service through the bridge. It does not depend on native event emitters.
110
+
111
+ ## RPC and API reference
112
+
113
+ The JS wrapper is a typed layer over the native `invoke(requestJson, pretty)` bridge.
114
+
115
+ Low-level entry points:
116
+
117
+ - `sdk.invoke(requestJson, pretty = false)`
118
+ - sends a raw JSON request to the native bridge
119
+ - returns a JSON envelope string
120
+ - `sdk.configureAccountStorage({ accountId, passphrase, storagePath? })`
121
+ - RPC: `configure_wallet_storage`
122
+ - selects an account-specific registry/database directory
123
+ - creates the registry with `passphrase` if it does not exist
124
+ - unlocks the existing registry with `passphrase` if it already exists
125
+ - clears loaded registry state, active wallet state, DB caches, and sync caches
126
+ before switching namespaces
127
+ - `sdk.buildInfoJson(pretty = false)`
128
+ - raw JSON envelope for `get_build_info`
129
+ - `sdk.buildInfo()`
130
+ - RPC: `get_build_info`
131
+ - returns:
132
+ - `version`
133
+ - `gitCommit`
134
+ - `buildDate`
135
+ - `rustVersion`
136
+ - `targetTriple`
137
+ - `createPirateWalletSdk()`
138
+ - returns a new `PirateWalletSdk` instance backed by the linked native module
139
+
140
+ The typed JS methods below unwrap the native JSON envelope and return the `result` value directly.
141
+
142
+ ### Amount wire format
143
+
144
+ All arrrtoshi amount values on the JSON wire are decimal strings, not JSON
145
+ numbers. This includes balances, transaction amounts, fees, pending
146
+ transaction totals, payment disclosure amounts, and `parseAmount()` results.
147
+ Amount request fields accept decimal strings, safe integer numbers, or
148
+ `bigint`; the JS wrapper serializes them as strings before calling native code.
149
+
150
+ ### Wallet lifecycle
151
+
152
+ - `walletRegistryExists()`
153
+ - RPC: `wallet_registry_exists`
154
+ - returns `boolean`
155
+ - `listWallets()`
156
+ - RPC: `list_wallets`
157
+ - returns `WalletMeta[]`
158
+ - `getActiveWalletId()`
159
+ - RPC: `get_active_wallet`
160
+ - returns `string | null`
161
+ - `getActiveWallet()`
162
+ - helper over `getActiveWalletId()` and `listWallets()`
163
+ - returns `WalletMeta | null`
164
+ - `getWallet(walletId)`
165
+ - helper over `listWallets()`
166
+ - returns `WalletMeta | null`
167
+ - `createWallet(requestOrName, birthdayHeight?)`
168
+ - RPC: `create_wallet`
169
+ - request fields:
170
+ - `name`
171
+ - optional `birthdayHeight`
172
+ - optional `mnemonicLanguage`
173
+ - returns wallet id string
174
+ - `restoreWallet(requestOrName, mnemonic?, birthdayHeight?, mnemonicLanguage?)`
175
+ - RPC: `restore_wallet`
176
+ - request fields:
177
+ - `name`
178
+ - `mnemonic`
179
+ - optional `birthdayHeight`
180
+ - optional `mnemonicLanguage`
181
+ - returns wallet id string
182
+ - `importViewingWallet(requestOrName, saplingViewingKey?, ironwoodViewingKey?, birthdayHeight)`
183
+ - RPC: `import_viewing_wallet`
184
+ - request fields:
185
+ - `name`
186
+ - optional `saplingViewingKey`
187
+ - optional `ironwoodViewingKey`
188
+ - `birthdayHeight`
189
+ - returns wallet id string
190
+ - `switchWallet(walletId)`
191
+ - RPC: `switch_wallet`
192
+ - returns acknowledgement object
193
+ - `renameWallet(walletId, newName)`
194
+ - RPC: `rename_wallet`
195
+ - returns acknowledgement object
196
+ - `deleteWallet(walletId)`
197
+ - RPC: `delete_wallet`
198
+ - returns acknowledgement object
199
+ - `setWalletBirthdayHeight(walletId, birthdayHeight)`
200
+ - RPC: `set_wallet_birthday_height`
201
+ - returns acknowledgement object
202
+ - `getLatestBirthdayHeight(walletId)`
203
+ - helper over `getWallet(walletId)`
204
+ - returns `number | null`
205
+
206
+ #### Active wallet and wallet IDs
207
+
208
+ Wallet metadata is stored in the backend registry. The registry also persists
209
+ an active wallet ID, which acts as the SDK's current-wallet pointer for flows
210
+ that need one. Integrations that already keep their own wallet selection can
211
+ call wallet-scoped methods directly with `walletId`.
212
+
213
+ `switchWallet(walletId)` updates the active-wallet pointer, records last-used
214
+ metadata, and stops sync for the previously active wallet. Multi-wallet sync
215
+ should be driven by wallet-scoped synchronizers rather than by switching the
216
+ active wallet between running wallets.
217
+
218
+ ### Mnemonic, formatting, and network
219
+
220
+ - `generateMnemonic(wordCount?, mnemonicLanguage?)`
221
+ - RPC: `generate_mnemonic`
222
+ - returns mnemonic string
223
+ - `validateMnemonic(mnemonic, mnemonicLanguage?)`
224
+ - RPC: `validate_mnemonic`
225
+ - returns `boolean`
226
+ - `inspectMnemonic(mnemonic)`
227
+ - RPC: `inspect_mnemonic`
228
+ - returns:
229
+ - `isValid`
230
+ - `detectedLanguage`
231
+ - `ambiguousLanguages`
232
+ - `wordCount`
233
+ - `getNetworkInfo()`
234
+ - RPC: `get_network_info`
235
+ - returns:
236
+ - `name`
237
+ - `coinType`
238
+ - `rpcPort`
239
+ - `defaultBirthday`
240
+ - `formatAmount(arrrtoshis)`
241
+ - RPC: `format_amount`
242
+ - returns formatted string
243
+ - `parseAmount(arrr)`
244
+ - RPC: `parse_amount`
245
+ - returns integer arrrtoshis as a decimal string
246
+
247
+ ### Validation
248
+
249
+ - `isValidShieldedAddr(address)`
250
+ - RPC: `is_valid_shielded_address`
251
+ - returns `boolean`
252
+ - `validateAddress(address)`
253
+ - RPC: `validate_address`
254
+ - returns:
255
+ - `isValid`
256
+ - `addressType`
257
+ - `reason`
258
+ - `validateConsensusBranch(walletId)`
259
+ - RPC: `validate_consensus_branch`
260
+ - returns:
261
+ - `sdkBranchId`
262
+ - `serverBranchId`
263
+ - `isValid`
264
+ - `hasServerBranch`
265
+ - `hasSdkBranch`
266
+ - `isServerNewer`
267
+ - `isSdkNewer`
268
+ - `errorMessage`
269
+
270
+ Consensus branch IDs are opaque. Use `isValid` for compatibility; the two
271
+ `*Newer` fields remain for wire compatibility and are always `false`.
272
+
273
+ ### Addresses and balances
274
+
275
+ Receive-address APIs are shielded and wallet-scoped:
276
+
277
+ - `getCurrentReceiveAddress(walletId)`
278
+ - helper over `getCurrentAddress(walletId)`
279
+ - `getCurrentAddress(walletId)`
280
+ - RPC: `current_receive_address`
281
+ - returns the current external receive address without rotating it
282
+ - `getNextReceiveAddress(walletId)`
283
+ - helper over `getNextAddress(walletId)`
284
+ - `getNextAddress(walletId)`
285
+ - RPC: `next_receive_address`
286
+ - rotates to and returns the next external receive address
287
+ - `listAddresses(walletId)`
288
+ - RPC: `list_addresses`
289
+ - returns generated external receive addresses
290
+ - `listAddressBalances(walletId, keyId?)`
291
+ - RPC: `list_address_balances`
292
+ - returns per-address balance entries
293
+
294
+ These APIs return shielded receive addresses. Newly generated addresses use
295
+ Sapling before Ironwood activation and Ironwood after activation. The current
296
+ address can still be an older Sapling address until the wallet rotates, and
297
+ `listAddresses(walletId)` can contain both Sapling and Ironwood receive
298
+ addresses over time.
299
+
300
+ - `getBalance(walletId)`
301
+ - RPC: `get_balance`
302
+ - returns decimal-string amount fields:
303
+ - `total`
304
+ - `spendable`
305
+ - `pending`
306
+ - `getShieldedPoolBalances(walletId)`
307
+ - RPC: `get_shielded_pool_balances`
308
+ - returns:
309
+ - `sapling`
310
+ - `ironwood`
311
+ - `getSpendabilityStatus(walletId)`
312
+ - RPC: `get_spendability_status`
313
+ - returns:
314
+ - `spendable`
315
+ - `rescanRequired`
316
+ - `targetHeight`
317
+ - `anchorHeight`
318
+ - `validatedAnchorHeight`
319
+ - `repairQueued`
320
+ - `reasonCode`
321
+
322
+ ### Transactions
323
+
324
+ - `listTransactions(walletId, limit?)`
325
+ - RPC: `list_transactions`
326
+ - returns transaction array
327
+ - `fetchTransactionMemo(walletId, txId, outputIndex?)`
328
+ - RPC: `fetch_transaction_memo`
329
+ - returns `string | null`
330
+ - `getTransactionDetails(walletId, txId)`
331
+ - RPC: `get_transaction_details`
332
+ - returns transaction detail object or `null`
333
+ - `exportPaymentDisclosures(walletId, txId)`
334
+ - RPC: `export_payment_disclosures`
335
+ - returns all recoverable payment disclosures for a sent transaction
336
+ - `exportSaplingPaymentDisclosure(walletId, txId, outputIndex)`
337
+ - RPC: `export_sapling_payment_disclosure`
338
+ - returns one Sapling output disclosure string
339
+ - `exportIronwoodPaymentDisclosure(walletId, txId, actionIndex)`
340
+ - RPC: `export_ironwood_payment_disclosure`
341
+ - returns one Ironwood action disclosure string
342
+ - `verifyPaymentDisclosure(walletId, disclosure)`
343
+ - RPC: `verify_payment_disclosure`
344
+ - decrypts one Sapling or Ironwood disclosure using the wallet's configured lightwalletd endpoint
345
+
346
+ `PaymentDisclosure` includes `disclosureType`, `txid`, `outputIndex`, `address`,
347
+ `amount`, optional `memo`, and the shareable `disclosure` string.
348
+ `verifyPaymentDisclosure` returns the same decrypted payment fields plus
349
+ `memoHex`.
350
+ - `getFeeInfo()`
351
+ - RPC: `get_fee_info`
352
+ - returns decimal-string fee fields plus `memoFeeMultiplier`:
353
+ - `defaultFee`
354
+ - `minFee`
355
+ - `maxFee`
356
+ - `feePerOutput`
357
+ - `memoFeeMultiplier`
358
+
359
+ ### Sync
360
+
361
+ - `startSync(walletIdOrRequest, mode = 'Compact')`
362
+ - RPC: `start_sync`
363
+ - request fields:
364
+ - `walletId`
365
+ - `mode`
366
+ - returns acknowledgement object
367
+ - `getSyncStatus(walletId)`
368
+ - RPC: `sync_status`
369
+ - returns:
370
+ - `localHeight`
371
+ - `targetHeight`
372
+ - `percent`
373
+ - `eta`
374
+ - `stage`
375
+ - `lastCheckpoint`
376
+ - `blocksPerSecond`
377
+ - `notesDecrypted`
378
+ - `lastBatchMs`
379
+ - `cancelSync(walletId)`
380
+ - RPC: `cancel_sync`
381
+ - returns acknowledgement object
382
+ - `rescan(walletIdOrRequest, fromHeight?)`
383
+ - RPC: `rescan`
384
+ - request fields:
385
+ - `walletId`
386
+ - `fromHeight`
387
+ - returns acknowledgement object
388
+
389
+ Each wallet has its own sync state. Apps can run more than one wallet sync by
390
+ creating synchronizers for different wallet IDs, subject to normal device,
391
+ network, and lightwalletd resource limits. Compact block ranges are cached per
392
+ endpoint, so later scans for another wallet on the same endpoint can reuse
393
+ previously fetched ranges.
394
+
395
+ ### Send flow
396
+
397
+ - `buildTransaction(walletIdOrRequest, outputs?, fee?)`
398
+ - RPC: `build_tx`
399
+ - request fields:
400
+ - `walletId`
401
+ - `outputs`
402
+ - optional `fee`
403
+ - each output contains:
404
+ - `addr`
405
+ - `amount`
406
+ - optional `memo`
407
+ - returns pending transaction object
408
+ - `signTransaction(walletId, pending)`
409
+ - RPC: `sign_tx`
410
+ - returns signed transaction object
411
+ - `broadcastTransaction(signed)`
412
+ - RPC: `broadcast_tx`
413
+ - returns transaction id string
414
+ - `send(walletId, outputsOrOutput, fee?)`
415
+ - helper over `buildTransaction()`, `signTransaction()`, and `broadcastTransaction()`
416
+ - returns transaction id string
417
+
418
+ `buildTransaction()`, `signTransaction()`, and `send()` are wallet-scoped.
419
+ `broadcastTransaction(signed)` only receives the signed transaction payload; if
420
+ endpoint configuration is needed during broadcast, the service uses the active
421
+ wallet.
422
+
423
+ Change-address selection is automatic. Sapling-only change uses legacy
424
+ same-address change before Ironwood activation and Sapling internal change after
425
+ activation; Ironwood spends or outputs use Ironwood internal change.
426
+
427
+ ### Viewing keys and watch-only
428
+
429
+ - `exportSaplingViewingKey(walletId)`
430
+ - RPC: `export_sapling_viewing_key`
431
+ - returns Sapling viewing key string
432
+ - `exportIronwoodViewingKey(walletId)`
433
+ - RPC: `export_ironwood_viewing_key`
434
+ - returns Ironwood viewing key string
435
+ - `importSaplingViewingKeyAsWatchOnly(requestOrName, saplingViewingKey?, birthdayHeight?)`
436
+ - RPC: `import_sapling_viewing_key_as_watch_only`
437
+ - returns wallet id string
438
+ - `getWatchOnlyCapabilities(walletId)`
439
+ - RPC: `get_watch_only_capabilities`
440
+ - returns capability object
441
+
442
+ ### Advanced key management
443
+
444
+ These methods live under `sdk.advancedKeyManagement`.
445
+
446
+ - `listKeyGroups(walletId)`
447
+ - RPC: `list_key_groups`
448
+ - returns key group array
449
+ - `exportKeyGroupKeys(walletId, keyId)`
450
+ - RPC: `export_key_group_keys`
451
+ - returns:
452
+ - `keyId`
453
+ - `saplingViewingKey`
454
+ - `ironwoodViewingKey`
455
+ - `saplingSpendingKey`
456
+ - `ironwoodSpendingKey`
457
+ - `importSpendingKey(requestOrWalletId, birthdayHeight?, saplingSpendingKey?, ironwoodSpendingKey?)`
458
+ - RPC: `import_spending_key`
459
+ - returns key id number
460
+ - `exportSeed(walletId, mnemonicLanguage?)`
461
+ - RPC: `export_seed_raw`
462
+ - returns mnemonic string
463
+
464
+ ### Mnemonic language values
465
+
466
+ Where `mnemonicLanguage` is supported, the accepted values are:
467
+
468
+ - `english`
469
+ - `chinese_simplified`
470
+ - `chinese_traditional`
471
+ - `french`
472
+ - `italian`
473
+ - `japanese`
474
+ - `korean`
475
+ - `spanish`
476
+
477
+ Behavior:
478
+
479
+ - if omitted during `restoreWallet()` or `validateMnemonic()`, the backend attempts autodetection
480
+ - if omitted during `exportSeed()`, the wallet's original stored mnemonic language is used
481
+ - if provided during export, the same seed entropy is re-rendered in the requested language
482
+
483
+ ### Synchronizer
484
+
485
+ Create a synchronizer with:
486
+
487
+ - `createSynchronizer(walletId, config?)`
488
+
489
+ Public state:
490
+
491
+ - `status`
492
+ - `progress`
493
+ - `syncStatus`
494
+ - `latestBirthdayHeight`
495
+ - `balance`
496
+ - `transactions`
497
+ - `lastError`
498
+
499
+ Methods:
500
+
501
+ - `currentSnapshot()`
502
+ - `isRunning()`
503
+ - `isSyncing()`
504
+ - `isComplete()`
505
+ - `start()`
506
+ - `stop()`
507
+ - `refresh()`
508
+ - `close()`
509
+ - `subscribe(callbacks?)`
510
+
511
+ `stop()` and `close()` both cancel backend sync for the wallet. In React Native code,
512
+ `await synchronizer.close()` instead of treating `close()` as a local timer-only cleanup step.
513
+
514
+ A synchronizer is scoped to one wallet ID. Create one synchronizer per wallet
515
+ when running multi-wallet sync.
516
+
517
+ Callback hooks:
518
+
519
+ - `onStatusChanged`
520
+ - `onUpdate`
521
+ - `onError`
522
+
523
+ ## Install in a React Native app
524
+
525
+ Install the package in the app and run CocoaPods as usual:
526
+
527
+ ```bash
528
+ npm install react-native-pirate-wallet
529
+ cd ios && pod install
530
+ ```
531
+
532
+ On Android, npm installs the exact-version
533
+ `react-native-pirate-wallet-android` companion automatically. The wrapper
534
+ autolinks as a standard React Native native module and adds the companion's JNI
535
+ libraries to the build.
536
+
537
+ On iOS, the podspec links the vendored `PirateWalletNative.xcframework`.
@@ -0,0 +1,82 @@
1
+ buildscript {
2
+ def kotlinVersion = rootProject.ext.has('kotlinVersion')
3
+ ? rootProject.ext.get('kotlinVersion')
4
+ : '2.2.21'
5
+
6
+ repositories {
7
+ google()
8
+ mavenCentral()
9
+ }
10
+
11
+ dependencies {
12
+ classpath 'com.android.tools.build:gradle:8.13.2'
13
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
14
+ }
15
+ }
16
+
17
+ apply plugin: 'com.android.library'
18
+ apply plugin: 'kotlin-android'
19
+
20
+ def safeExtGet(prop, fallback) {
21
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
22
+ }
23
+
24
+ def androidBinaryPackages = [
25
+ 'react-native-pirate-wallet-android',
26
+ 'react-native-pirate-wallet-android-x86_64',
27
+ ]
28
+ def androidJniLibsDirs = androidBinaryPackages.collect { packageName ->
29
+ def candidates = [
30
+ file("../node_modules/${packageName}/android/src/main/jniLibs"),
31
+ file("../../${packageName}/android/src/main/jniLibs"),
32
+ ]
33
+ def jniLibsDir = candidates.find { it.isDirectory() }
34
+ if (jniLibsDir == null) {
35
+ throw new GradleException(
36
+ "${packageName} must be installed before building Android"
37
+ )
38
+ }
39
+ jniLibsDir
40
+ }
41
+
42
+ android {
43
+ namespace "com.pirate.wallet.reactnative"
44
+ compileSdkVersion safeExtGet('compileSdkVersion', 36)
45
+
46
+ defaultConfig {
47
+ minSdkVersion safeExtGet('minSdkVersion', 24)
48
+ targetSdkVersion safeExtGet('targetSdkVersion', 36)
49
+ consumerProguardFiles 'consumer-rules.pro'
50
+ }
51
+
52
+ compileOptions {
53
+ sourceCompatibility JavaVersion.VERSION_17
54
+ targetCompatibility JavaVersion.VERSION_17
55
+ }
56
+
57
+ kotlinOptions {
58
+ jvmTarget = '17'
59
+ }
60
+
61
+ sourceSets {
62
+ main {
63
+ jniLibs.srcDirs androidJniLibsDirs
64
+ }
65
+ }
66
+
67
+ lintOptions {
68
+ abortOnError false
69
+ }
70
+ }
71
+
72
+ repositories {
73
+ google()
74
+ mavenCentral()
75
+ maven {
76
+ url("${rootProject.projectDir}/../node_modules/react-native/android")
77
+ }
78
+ }
79
+
80
+ dependencies {
81
+ implementation 'com.facebook.react:react-native:+'
82
+ }
@@ -0,0 +1 @@
1
+
@@ -0,0 +1 @@
1
+ <manifest />