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 +21 -0
- package/README.md +537 -0
- package/android/build.gradle +82 -0
- package/android/consumer-rules.pro +1 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/com/pirate/wallet/reactnative/PirateWalletReactNativeModule.kt +96 -0
- package/android/src/main/java/com/pirate/wallet/reactnative/PirateWalletReactNativePackage.kt +14 -0
- package/ios/PirateWalletReactNative.m +172 -0
- package/ios/PirateWalletReactNative.swift +40 -0
- package/package.json +64 -0
- package/react-native-pirate-wallet.podspec +19 -0
- package/react-native.config.js +10 -0
- package/scripts/assemble-ios-framework.js +124 -0
- package/scripts/resolve-android-packages.js +75 -0
- package/scripts/verify-package.js +128 -0
- package/src/index.d.ts +245 -0
- package/src/index.js +876 -0
- package/test/smoke.js +220 -0
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 />
|