@naculus/connect-native 0.4.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Naculus
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,84 @@
1
+ # @naculus/connect-native
2
+
3
+ Naculus Connect for React Native. The React hooks from
4
+ `@naculus/connect-appkit-react` run unchanged; this package supplies the
5
+ native pieces `Web3ConnectProvider` needs.
6
+
7
+ ```tsx
8
+ // index.js — before anything else
9
+ import "@walletconnect/react-native-compat";
10
+
11
+ // App.tsx
12
+ import AsyncStorage from "@react-native-async-storage/async-storage";
13
+ import * as SecureStore from "expo-secure-store";
14
+ import { Linking, Platform } from "react-native";
15
+ import { transact } from "@solana-mobile/mobile-wallet-adapter-protocol-kit";
16
+ import { EIP1193Provider, Wallets } from "@mobile-wallet-protocol/client";
17
+ import { Web3ConnectProvider } from "@naculus/connect-appkit-react";
18
+ import {
19
+ asyncStorageSessionStorage,
20
+ coinbaseMobileWallet,
21
+ createMobileWalletAdapterWallet,
22
+ keystoreWalletStorage,
23
+ nativeWalletConnect,
24
+ setupNaculusNative,
25
+ } from "@naculus/connect-native";
26
+
27
+ setupNaculusNative(Platform.OS);
28
+
29
+ const config = {
30
+ projectId, // WalletConnect Cloud
31
+ metadata,
32
+ sessionStorage: asyncStorageSessionStorage(AsyncStorage),
33
+ walletConnect: nativeWalletConnect(Linking),
34
+ enableSolana: true,
35
+ solanaWallets: [
36
+ createMobileWalletAdapterWallet({
37
+ transact,
38
+ identity: { name: "My App", uri: "https://myapp.example" },
39
+ chain: "solana:mainnet",
40
+ }),
41
+ ],
42
+ injectedProviders: [
43
+ coinbaseMobileWallet(
44
+ new EIP1193Provider({ metadata: { name: "My App" }, wallet: Wallets.CoinbaseSmartWallet }),
45
+ ),
46
+ ],
47
+ enableEmbedded: true,
48
+ embeddedConfig: {
49
+ storage: keystoreWalletStorage({ secureStore: SecureStore, asyncStorage: AsyncStorage }),
50
+ },
51
+ };
52
+
53
+ export default () => <Web3ConnectProvider config={config}>{/* … */}</Web3ConnectProvider>;
54
+ ```
55
+
56
+ Every native module is passed in by the app, so each peer is optional:
57
+ install only what you use.
58
+
59
+ | Piece | Peer | What it does |
60
+ |---|---|---|
61
+ | `setupNaculusNative(Platform.OS)` | `react-native` | Tells connect-core it runs natively (sessions record `native-ios` / `native-android`; mobile-capable connectors are preferred) |
62
+ | `asyncStorageSessionStorage` / `asyncStorageAdapter` | `@react-native-async-storage/async-storage` | Session persistence |
63
+ | `nativeWalletConnect(Linking)`, `installedWallets` | `@walletconnect/react-native-compat` | WalletConnect deep links via `Linking.openURL`; relay storage in AsyncStorage (import the compat package first) |
64
+ | `createMobileWalletAdapterWallet` | `@solana-mobile/mobile-wallet-adapter-protocol-kit` | Solana Mobile Wallet Adapter (Android) as a Wallet Standard wallet |
65
+ | `coinbaseMobileWallet(provider)` | `@mobile-wallet-protocol/client` | Coinbase Wallet over Mobile Wallet Protocol, connected with `connectInjected("coinbase-mwp")` |
66
+ | `keystoreWalletStorage` | `expo-secure-store` | Embedded wallet record sealed by wallet-engine (AES-256-GCM) under a Keychain / Keystore key (this device, when unlocked) |
67
+
68
+ **Keep `config` stable** (module scope or `useMemo`): `Web3ConnectProvider`
69
+ rebuilds its client when these objects change identity.
70
+
71
+ **Randomness:** `crypto.getRandomValues` must exist —
72
+ `@walletconnect/react-native-compat` installs `react-native-get-random-values`;
73
+ import it first. The embedded wallet's key generation fails closed without it.
74
+
75
+ **Clusters:** the MWA wallet's `chain` must match `solanaDefaultChain`; a
76
+ mismatch fails on send rather than paying on another cluster.
77
+
78
+ **Embedded wallet isolation.** React Native has no Web Worker, so the
79
+ embedded wallet signs on the JS thread; the web build's worker isolation does
80
+ not apply. What the Keystore adds is that the sealed record is useless off the
81
+ device and the key never touches AsyncStorage.
82
+
83
+ **Not included:** UI components (the web components are DOM-only — use the
84
+ hooks and your own views) and passkeys.
package/dist/index.cjs ADDED
@@ -0,0 +1,366 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ asyncStorageAdapter: () => asyncStorageAdapter,
24
+ asyncStorageSessionStorage: () => asyncStorageSessionStorage,
25
+ base58Encode: () => base58Encode,
26
+ coinbaseMobileWallet: () => coinbaseMobileWallet,
27
+ createMobileWalletAdapterWallet: () => createMobileWalletAdapterWallet,
28
+ installedWallets: () => installedWallets,
29
+ keystoreWalletStorage: () => keystoreWalletStorage,
30
+ kitTransactionFromWire: () => kitTransactionFromWire,
31
+ nativeWalletConnect: () => nativeWalletConnect,
32
+ setupNaculusNative: () => setupNaculusNative,
33
+ wireFromKitTransaction: () => wireFromKitTransaction
34
+ });
35
+ module.exports = __toCommonJS(src_exports);
36
+
37
+ // src/codec.ts
38
+ var B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
39
+ function base58Encode(bytes) {
40
+ let zeros = 0;
41
+ while (zeros < bytes.length && bytes[zeros] === 0) zeros++;
42
+ let value = 0n;
43
+ for (const byte of bytes) value = value * 256n + BigInt(byte);
44
+ let out = "";
45
+ while (value > 0n) {
46
+ out = B58[Number(value % 58n)] + out;
47
+ value /= 58n;
48
+ }
49
+ return "1".repeat(zeros) + out;
50
+ }
51
+ function base64Decode(value) {
52
+ return Uint8Array.from(atob(value), (c) => c.charCodeAt(0));
53
+ }
54
+
55
+ // src/coinbase.ts
56
+ function coinbaseMobileWallet(provider, info = {}) {
57
+ return {
58
+ info: {
59
+ uuid: info.uuid ?? "coinbase-mwp",
60
+ name: info.name ?? "Coinbase Wallet",
61
+ icon: info.icon ?? "data:image/svg+xml;base64,",
62
+ rdns: info.rdns ?? "com.coinbase.wallet"
63
+ },
64
+ provider
65
+ };
66
+ }
67
+
68
+ // src/keystore.ts
69
+ var import_wallet_engine = require("@naculus/wallet-engine");
70
+ function keystoreWalletStorage(options) {
71
+ const { secureStore, asyncStorage } = options;
72
+ const name = options.name ?? "naculus_wallet";
73
+ const keyName = `${name}.key`;
74
+ const recordName = `${name}.sealed`;
75
+ const access = secureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY !== void 0 ? { keychainAccessible: secureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY } : void 0;
76
+ return new import_wallet_engine.KeyStoreStorageAdapter({
77
+ slot: name,
78
+ keyStore: {
79
+ load: () => secureStore.getItemAsync(keyName, access),
80
+ save: (value) => secureStore.setItemAsync(keyName, value, access),
81
+ delete: () => secureStore.deleteItemAsync(keyName)
82
+ },
83
+ blobStore: {
84
+ read: () => asyncStorage.getItem(recordName),
85
+ write: (value) => asyncStorage.setItem(recordName, value),
86
+ remove: () => asyncStorage.removeItem(recordName)
87
+ }
88
+ });
89
+ }
90
+
91
+ // src/mwa.ts
92
+ var import_connect_core = require("@naculus/connect-core");
93
+ var SIGNATURE_LENGTH = 64;
94
+ function kitTransactionFromWire(wire) {
95
+ const tx = (0, import_connect_core.parseSolanaTransaction)(wire);
96
+ const signatures = {};
97
+ for (let i = 0; i < tx.numRequiredSignatures; i++) {
98
+ const signature = tx.signatures[i];
99
+ signatures[tx.accountKeys[i]] = signature.some((b) => b !== 0) ? signature : null;
100
+ }
101
+ return { messageBytes: tx.message, signatures };
102
+ }
103
+ function wireFromKitTransaction(tx) {
104
+ const count = Object.keys(tx.signatures).length;
105
+ if (count === 0 || count > 127) {
106
+ throw new import_connect_core.WalletError("invalid_input", "Unexpected signature count.");
107
+ }
108
+ const unsigned = new Uint8Array(1 + 64 * count + tx.messageBytes.length);
109
+ unsigned[0] = count;
110
+ unsigned.set(tx.messageBytes, 1 + 64 * count);
111
+ const parsed = (0, import_connect_core.parseSolanaTransaction)(unsigned);
112
+ const out = unsigned.slice();
113
+ parsed.accountKeys.slice(0, parsed.numRequiredSignatures).forEach((k, i) => {
114
+ const signature = tx.signatures[k];
115
+ if (!signature) return;
116
+ if (signature.length !== 64) {
117
+ throw new import_connect_core.WalletError(
118
+ "signature_rejected",
119
+ "The wallet returned a malformed signature."
120
+ );
121
+ }
122
+ out.set(signature, 1 + 64 * i);
123
+ });
124
+ return out;
125
+ }
126
+ function createMobileWalletAdapterWallet(options) {
127
+ const { transact, identity, chain } = options;
128
+ let authToken;
129
+ let account = null;
130
+ const listeners = /* @__PURE__ */ new Set();
131
+ const authorize = async (wallet) => {
132
+ const result = await wallet.authorize({
133
+ identity,
134
+ chain,
135
+ ...authToken ? { auth_token: authToken } : {}
136
+ });
137
+ authToken = result.auth_token;
138
+ const first = result.accounts[0];
139
+ if (!first) {
140
+ throw new import_connect_core.WalletError(
141
+ "wallet_unavailable",
142
+ "The wallet returned no account."
143
+ );
144
+ }
145
+ const publicKey = base64Decode(first.address);
146
+ if (publicKey.length !== 32) {
147
+ throw new import_connect_core.WalletError(
148
+ "wallet_unavailable",
149
+ "The wallet returned a malformed account."
150
+ );
151
+ }
152
+ const previous = account?.address;
153
+ account = {
154
+ address: base58Encode(publicKey),
155
+ base64: first.address,
156
+ publicKey
157
+ };
158
+ if (previous !== void 0 && previous !== account.address) {
159
+ for (const listener of listeners) {
160
+ listener({ accounts: [standardAccount()] });
161
+ }
162
+ }
163
+ return account;
164
+ };
165
+ const standardAccount = () => {
166
+ if (!account) {
167
+ throw new import_connect_core.WalletError("session_expired", "Connect the wallet first.");
168
+ }
169
+ return {
170
+ address: account.address,
171
+ publicKey: account.publicKey,
172
+ chains: [chain],
173
+ features: [
174
+ "solana:signMessage",
175
+ "solana:signTransaction",
176
+ "solana:signAndSendTransaction"
177
+ ]
178
+ };
179
+ };
180
+ return {
181
+ version: "1.0.0",
182
+ name: options.name ?? "Mobile Wallet Adapter",
183
+ icon: options.icon ?? "data:image/svg+xml;base64,",
184
+ chains: [chain],
185
+ get accounts() {
186
+ return account ? [standardAccount()] : [];
187
+ },
188
+ features: {
189
+ "standard:connect": {
190
+ version: "1.0.0",
191
+ connect: async () => {
192
+ await transact((wallet) => authorize(wallet));
193
+ for (const listener of listeners)
194
+ listener({ accounts: [standardAccount()] });
195
+ return { accounts: [standardAccount()] };
196
+ }
197
+ },
198
+ "standard:disconnect": {
199
+ version: "1.0.0",
200
+ disconnect: async () => {
201
+ const token = authToken;
202
+ authToken = void 0;
203
+ account = null;
204
+ for (const listener of listeners) listener({ accounts: [] });
205
+ if (token) {
206
+ await transact(
207
+ (wallet) => wallet.deauthorize({ auth_token: token })
208
+ ).catch(() => {
209
+ });
210
+ }
211
+ }
212
+ },
213
+ "standard:events": {
214
+ version: "1.0.0",
215
+ on: (_event, listener) => {
216
+ listeners.add(listener);
217
+ return () => listeners.delete(listener);
218
+ }
219
+ },
220
+ "solana:signMessage": {
221
+ version: "1.0.0",
222
+ signMessage: async (message) => transact(async (wallet) => {
223
+ const { base64 } = await authorize(wallet);
224
+ const [signed] = await wallet.signMessages({
225
+ addresses: [base64],
226
+ payloads: [message]
227
+ });
228
+ if (!signed || signed.length < SIGNATURE_LENGTH) {
229
+ throw new import_connect_core.WalletError(
230
+ "signature_rejected",
231
+ "No signature returned."
232
+ );
233
+ }
234
+ return { signature: signed.slice(-SIGNATURE_LENGTH) };
235
+ })
236
+ },
237
+ "solana:signTransaction": {
238
+ version: "1.0.0",
239
+ signTransaction: async (transaction) => transact(async (wallet) => {
240
+ await authorize(wallet);
241
+ const [signed] = await wallet.signTransactions({
242
+ transactions: [kitTransactionFromWire(transaction)]
243
+ });
244
+ if (!signed) {
245
+ throw new import_connect_core.WalletError(
246
+ "signature_rejected",
247
+ "No transaction returned."
248
+ );
249
+ }
250
+ return { signedTransaction: wireFromKitTransaction(signed) };
251
+ })
252
+ },
253
+ "solana:signAndSendTransaction": {
254
+ version: "1.0.0",
255
+ signAndSendTransaction: async (transaction) => transact(async (wallet) => {
256
+ await authorize(wallet);
257
+ const [signature] = await wallet.signAndSendTransactions({
258
+ transactions: [kitTransactionFromWire(transaction)]
259
+ });
260
+ if (!signature) {
261
+ throw new import_connect_core.WalletError("tx_failed", "No signature returned.");
262
+ }
263
+ return { signature: base58Encode(signature) };
264
+ })
265
+ }
266
+ }
267
+ };
268
+ }
269
+
270
+ // src/platform.ts
271
+ var import_connect_core2 = require("@naculus/connect-core");
272
+ function setupNaculusNative(os) {
273
+ if (os === "ios") (0, import_connect_core2.setPlatformOverride)("native-ios");
274
+ else if (os === "android") (0, import_connect_core2.setPlatformOverride)("native-android");
275
+ else (0, import_connect_core2.setPlatformOverride)(null);
276
+ }
277
+
278
+ // src/storage.ts
279
+ function asyncStorageAdapter(storage, prefix = "naculus:") {
280
+ const k = (key) => `${prefix}${key}`;
281
+ return {
282
+ async get(key) {
283
+ const raw = await storage.getItem(k(key));
284
+ if (raw === null) return null;
285
+ try {
286
+ return JSON.parse(raw);
287
+ } catch {
288
+ return null;
289
+ }
290
+ },
291
+ async set(key, value) {
292
+ await storage.setItem(k(key), JSON.stringify(value));
293
+ },
294
+ async remove(key) {
295
+ await storage.removeItem(k(key));
296
+ },
297
+ async clear() {
298
+ const keys = (await storage.getAllKeys()).filter(
299
+ (key) => key.startsWith(prefix)
300
+ );
301
+ if (keys.length > 0) await storage.multiRemove(keys);
302
+ },
303
+ async has(key) {
304
+ return await storage.getItem(k(key)) !== null;
305
+ },
306
+ isAvailable() {
307
+ return true;
308
+ }
309
+ };
310
+ }
311
+ function asyncStorageSessionStorage(storage, key = "naculus_web3_session") {
312
+ return {
313
+ async load() {
314
+ const raw = await storage.getItem(key);
315
+ if (raw === null) return null;
316
+ try {
317
+ return JSON.parse(raw);
318
+ } catch {
319
+ await storage.removeItem(key);
320
+ return null;
321
+ }
322
+ },
323
+ async save(session) {
324
+ await storage.setItem(key, JSON.stringify(session));
325
+ },
326
+ async clear() {
327
+ await storage.removeItem(key);
328
+ }
329
+ };
330
+ }
331
+
332
+ // src/walletconnect.ts
333
+ function nativeWalletConnect(linking) {
334
+ return {
335
+ openUrl: async (url) => {
336
+ await linking.openURL(url);
337
+ }
338
+ };
339
+ }
340
+ async function installedWallets(linking, wallets) {
341
+ const checks = await Promise.all(
342
+ wallets.map(async (wallet) => {
343
+ try {
344
+ return await linking.canOpenURL(wallet.deepLink);
345
+ } catch {
346
+ return false;
347
+ }
348
+ })
349
+ );
350
+ return wallets.filter((_, i) => checks[i]);
351
+ }
352
+ // Annotate the CommonJS export names for ESM import in node:
353
+ 0 && (module.exports = {
354
+ asyncStorageAdapter,
355
+ asyncStorageSessionStorage,
356
+ base58Encode,
357
+ coinbaseMobileWallet,
358
+ createMobileWalletAdapterWallet,
359
+ installedWallets,
360
+ keystoreWalletStorage,
361
+ kitTransactionFromWire,
362
+ nativeWalletConnect,
363
+ setupNaculusNative,
364
+ wireFromKitTransaction
365
+ });
366
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/codec.ts","../src/coinbase.ts","../src/keystore.ts","../src/mwa.ts","../src/platform.ts","../src/storage.ts","../src/walletconnect.ts"],"sourcesContent":["export { base58Encode } from \"./codec\";\nexport { coinbaseMobileWallet } from \"./coinbase\";\nexport {\n type KeystoreWalletStorageOptions,\n keystoreWalletStorage,\n} from \"./keystore\";\nexport {\n createMobileWalletAdapterWallet,\n kitTransactionFromWire,\n type MobileWalletAdapterOptions,\n type MwaAppIdentity,\n type MwaTransact,\n type MwaWalletLike,\n wireFromKitTransaction,\n} from \"./mwa\";\nexport { setupNaculusNative } from \"./platform\";\nexport { asyncStorageAdapter, asyncStorageSessionStorage } from \"./storage\";\nexport type { AsyncStorageLike, LinkingLike, SecureStoreLike } from \"./types\";\nexport {\n installedWallets,\n nativeWalletConnect,\n type WalletLinkTarget,\n} from \"./walletconnect\";\n","const B58 = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\n/** base58 (Bitcoin alphabet), as Solana addresses and signatures use. */\nexport function base58Encode(bytes: Uint8Array): string {\n let zeros = 0;\n while (zeros < bytes.length && bytes[zeros] === 0) zeros++;\n let value = 0n;\n for (const byte of bytes) value = value * 256n + BigInt(byte);\n let out = \"\";\n while (value > 0n) {\n out = B58[Number(value % 58n)] + out;\n value /= 58n;\n }\n return \"1\".repeat(zeros) + out;\n}\n\nexport function base64Encode(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\nexport function base64Decode(value: string): Uint8Array {\n return Uint8Array.from(atob(value), (c) => c.charCodeAt(0));\n}\n","import type { InjectedProviderRegistration } from \"@naculus/connect-appkit-react\";\n\n/**\n * Coinbase Wallet on React Native through Mobile Wallet Protocol. The app\n * builds the provider — `new EIP1193Provider({ metadata, wallet:\n * Wallets.CoinbaseSmartWallet })` from `@mobile-wallet-protocol/client` —\n * and this registers it as an injected wallet (pass in\n * `config.injectedProviders`); connect with `connectInjected(\"coinbase-mwp\")`.\n */\nexport function coinbaseMobileWallet(\n provider: unknown,\n info: Partial<InjectedProviderRegistration[\"info\"]> = {},\n): InjectedProviderRegistration {\n return {\n info: {\n uuid: info.uuid ?? \"coinbase-mwp\",\n name: info.name ?? \"Coinbase Wallet\",\n icon: info.icon ?? \"data:image/svg+xml;base64,\",\n rdns: info.rdns ?? \"com.coinbase.wallet\",\n },\n provider,\n };\n}\n","import {\n KeyStoreStorageAdapter,\n type StorageAdapter,\n} from \"@naculus/wallet-engine\";\nimport type { AsyncStorageLike, SecureStoreLike } from \"./types\";\n\n/**\n * The embedded wallet's storage on a phone: wallet-engine's\n * `KeyStoreStorageAdapter` with its key in iOS Keychain / Android Keystore\n * (`expo-secure-store`, this device only, when unlocked) and the sealed record\n * in AsyncStorage. Sealing happens inside wallet-engine; this only moves two\n * opaque strings. Pass as `embeddedConfig.storage`.\n *\n * Isolation is weaker than the web's worker: React Native has no Web Worker,\n * so signing runs on the JS thread. The Keystore makes the sealed record\n * useless off the device and keeps the key out of AsyncStorage. Needs\n * `crypto.getRandomValues` (`react-native-get-random-values`, which\n * `@walletconnect/react-native-compat` installs).\n */\nexport interface KeystoreWalletStorageOptions {\n secureStore: SecureStoreLike;\n asyncStorage: AsyncStorageLike;\n /** Names both the Keystore entry and the AsyncStorage record. */\n name?: string;\n}\n\nexport function keystoreWalletStorage(\n options: KeystoreWalletStorageOptions,\n): StorageAdapter {\n const { secureStore, asyncStorage } = options;\n const name = options.name ?? \"naculus_wallet\";\n const keyName = `${name}.key`;\n const recordName = `${name}.sealed`;\n const access =\n secureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY !== undefined\n ? { keychainAccessible: secureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY }\n : undefined;\n return new KeyStoreStorageAdapter({\n slot: name,\n keyStore: {\n load: () => secureStore.getItemAsync(keyName, access),\n save: (value) => secureStore.setItemAsync(keyName, value, access),\n delete: () => secureStore.deleteItemAsync(keyName),\n },\n blobStore: {\n read: () => asyncStorage.getItem(recordName),\n write: (value) => asyncStorage.setItem(recordName, value),\n remove: () => asyncStorage.removeItem(recordName),\n },\n });\n}\n","import { parseSolanaTransaction, WalletError } from \"@naculus/connect-core\";\nimport { base58Encode, base64Decode } from \"./codec\";\n\n/**\n * Solana Mobile Wallet Adapter as a Wallet Standard wallet, for\n * connector-solana's `registerWallet` (pass it in `config.solanaWallets`).\n *\n * Each operation opens one MWA session with `transact` (from\n * `@solana-mobile/mobile-wallet-adapter-protocol-kit`, passed in by the app),\n * re-authorizes with the stored auth token and asks the wallet app. Wire\n * transactions become the Kit `{ messageBytes, signatures }` objects that\n * package expects and back; the signer order is taken from the message.\n */\n\n/** MWA's app identity, shown by the wallet. */\nexport interface MwaAppIdentity {\n name?: string;\n uri?: string;\n icon?: string;\n}\n\ntype KitTransaction = {\n messageBytes: Uint8Array;\n signatures: Record<string, Uint8Array | null>;\n};\n\n/** The members of the Kit `KitMobileWallet` used here. */\nexport interface MwaWalletLike {\n authorize(params: {\n identity: MwaAppIdentity;\n chain?: string;\n auth_token?: string;\n }): Promise<{\n accounts: readonly { address: string; label?: string }[];\n auth_token: string;\n }>;\n deauthorize(params: { auth_token: string }): Promise<unknown>;\n signMessages(params: {\n addresses: string[];\n payloads: Uint8Array[];\n }): Promise<Uint8Array[]>;\n signTransactions(params: {\n transactions: KitTransaction[];\n }): Promise<KitTransaction[]>;\n signAndSendTransactions(params: {\n transactions: KitTransaction[];\n }): Promise<Uint8Array[]>;\n}\n\nexport type MwaTransact = <T>(\n callback: (wallet: MwaWalletLike) => Promise<T>,\n) => Promise<T>;\n\nexport interface MobileWalletAdapterOptions {\n transact: MwaTransact;\n identity: MwaAppIdentity;\n /** MWA 2.0 chain id: `solana:mainnet`, `solana:devnet` or `solana:testnet`. */\n chain: \"solana:mainnet\" | \"solana:devnet\" | \"solana:testnet\";\n name?: string;\n icon?: string;\n}\n\nconst SIGNATURE_LENGTH = 64;\n\n/** Wire transaction → Kit transaction (signatures keyed by signer address). */\nexport function kitTransactionFromWire(wire: Uint8Array): KitTransaction {\n const tx = parseSolanaTransaction(wire);\n const signatures: Record<string, Uint8Array | null> = {};\n for (let i = 0; i < tx.numRequiredSignatures; i++) {\n const signature = tx.signatures[i] as Uint8Array;\n signatures[tx.accountKeys[i] as string] = signature.some((b) => b !== 0)\n ? signature\n : null;\n }\n return { messageBytes: tx.message, signatures };\n}\n\n/** Kit transaction → wire, in the message's signer order. */\nexport function wireFromKitTransaction(tx: KitTransaction): Uint8Array {\n const count = Object.keys(tx.signatures).length;\n if (count === 0 || count > 127) {\n throw new WalletError(\"invalid_input\", \"Unexpected signature count.\");\n }\n const unsigned = new Uint8Array(1 + 64 * count + tx.messageBytes.length);\n unsigned[0] = count;\n unsigned.set(tx.messageBytes, 1 + 64 * count);\n const parsed = parseSolanaTransaction(unsigned);\n const out = unsigned.slice();\n parsed.accountKeys.slice(0, parsed.numRequiredSignatures).forEach((k, i) => {\n const signature = tx.signatures[k];\n if (!signature) return;\n if (signature.length !== 64) {\n throw new WalletError(\n \"signature_rejected\",\n \"The wallet returned a malformed signature.\",\n );\n }\n out.set(signature, 1 + 64 * i);\n });\n return out;\n}\n\nexport function createMobileWalletAdapterWallet(\n options: MobileWalletAdapterOptions,\n) {\n const { transact, identity, chain } = options;\n let authToken: string | undefined;\n let account: {\n address: string;\n base64: string;\n publicKey: Uint8Array;\n } | null = null;\n const listeners = new Set<(change: unknown) => void>();\n\n const authorize = async (wallet: MwaWalletLike) => {\n const result = await wallet.authorize({\n identity,\n chain,\n ...(authToken ? { auth_token: authToken } : {}),\n });\n authToken = result.auth_token;\n const first = result.accounts[0];\n if (!first) {\n throw new WalletError(\n \"wallet_unavailable\",\n \"The wallet returned no account.\",\n );\n }\n const publicKey = base64Decode(first.address);\n if (publicKey.length !== 32) {\n throw new WalletError(\n \"wallet_unavailable\",\n \"The wallet returned a malformed account.\",\n );\n }\n const previous = account?.address;\n account = {\n address: base58Encode(publicKey),\n base64: first.address,\n publicKey,\n };\n // The user may pick another account when the wallet re-authorizes: tell\n // the connector, so the session never shows one account while another\n // signs (as the official wallet-standard-mobile adapter does).\n if (previous !== undefined && previous !== account.address) {\n for (const listener of listeners) {\n listener({ accounts: [standardAccount()] });\n }\n }\n return account;\n };\n\n const standardAccount = () => {\n if (!account) {\n throw new WalletError(\"session_expired\", \"Connect the wallet first.\");\n }\n return {\n address: account.address,\n publicKey: account.publicKey,\n chains: [chain],\n features: [\n \"solana:signMessage\",\n \"solana:signTransaction\",\n \"solana:signAndSendTransaction\",\n ],\n };\n };\n\n return {\n version: \"1.0.0\" as const,\n name: options.name ?? \"Mobile Wallet Adapter\",\n icon: options.icon ?? \"data:image/svg+xml;base64,\",\n chains: [chain],\n get accounts() {\n return account ? [standardAccount()] : [];\n },\n features: {\n \"standard:connect\": {\n version: \"1.0.0\",\n connect: async () => {\n await transact((wallet) => authorize(wallet));\n for (const listener of listeners)\n listener({ accounts: [standardAccount()] });\n return { accounts: [standardAccount()] };\n },\n },\n \"standard:disconnect\": {\n version: \"1.0.0\",\n disconnect: async () => {\n const token = authToken;\n authToken = undefined;\n account = null;\n for (const listener of listeners) listener({ accounts: [] });\n if (token) {\n await transact((wallet) =>\n wallet.deauthorize({ auth_token: token }),\n ).catch(() => {});\n }\n },\n },\n \"standard:events\": {\n version: \"1.0.0\",\n on: (_event: string, listener: (change: unknown) => void) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n },\n \"solana:signMessage\": {\n version: \"1.0.0\",\n signMessage: async (message: Uint8Array) =>\n transact(async (wallet) => {\n const { base64 } = await authorize(wallet);\n const [signed] = await wallet.signMessages({\n addresses: [base64],\n payloads: [message],\n });\n if (!signed || signed.length < SIGNATURE_LENGTH) {\n throw new WalletError(\n \"signature_rejected\",\n \"No signature returned.\",\n );\n }\n // MWA returns the message with the signature appended.\n return { signature: signed.slice(-SIGNATURE_LENGTH) };\n }),\n },\n \"solana:signTransaction\": {\n version: \"1.0.0\",\n signTransaction: async (transaction: Uint8Array) =>\n transact(async (wallet) => {\n await authorize(wallet);\n const [signed] = await wallet.signTransactions({\n transactions: [kitTransactionFromWire(transaction)],\n });\n if (!signed) {\n throw new WalletError(\n \"signature_rejected\",\n \"No transaction returned.\",\n );\n }\n return { signedTransaction: wireFromKitTransaction(signed) };\n }),\n },\n \"solana:signAndSendTransaction\": {\n version: \"1.0.0\",\n signAndSendTransaction: async (transaction: Uint8Array) =>\n transact(async (wallet) => {\n await authorize(wallet);\n const [signature] = await wallet.signAndSendTransactions({\n transactions: [kitTransactionFromWire(transaction)],\n });\n if (!signature) {\n throw new WalletError(\"tx_failed\", \"No signature returned.\");\n }\n return { signature: base58Encode(signature) };\n }),\n },\n },\n };\n}\n","import { setPlatformOverride } from \"@naculus/connect-core\";\n\n/**\n * Tell connect-core it runs in a native app (`Platform.OS` from\n * react-native). React Native cannot be told apart from a browser by\n * `navigator`; without this, connectors record sessions as `desktop-web` and\n * the connector manager does not prefer mobile-capable connectors.\n */\nexport function setupNaculusNative(os: string): void {\n if (os === \"ios\") setPlatformOverride(\"native-ios\");\n else if (os === \"android\") setPlatformOverride(\"native-android\");\n else setPlatformOverride(null);\n}\n","import type {\n SessionStorage,\n StorageAdapter,\n UniversalWalletSession,\n} from \"@naculus/connect-core\";\nimport type { AsyncStorageLike } from \"./types\";\n\n/** connect-core `StorageAdapter` over AsyncStorage, under a key prefix. */\nexport function asyncStorageAdapter(\n storage: AsyncStorageLike,\n prefix = \"naculus:\",\n): StorageAdapter {\n const k = (key: string) => `${prefix}${key}`;\n return {\n async get<T>(key: string): Promise<T | null> {\n const raw = await storage.getItem(k(key));\n if (raw === null) return null;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n },\n async set<T>(key: string, value: T): Promise<void> {\n await storage.setItem(k(key), JSON.stringify(value));\n },\n async remove(key: string): Promise<void> {\n await storage.removeItem(k(key));\n },\n async clear(): Promise<void> {\n const keys = (await storage.getAllKeys()).filter((key) =>\n key.startsWith(prefix),\n );\n if (keys.length > 0) await storage.multiRemove(keys);\n },\n async has(key: string): Promise<boolean> {\n return (await storage.getItem(k(key))) !== null;\n },\n isAvailable(): boolean {\n return true;\n },\n };\n}\n\n/**\n * Where `Web3ConnectProvider` persists the connected session on React\n * Native (pass as `config.sessionStorage`); the web default is localStorage.\n */\nexport function asyncStorageSessionStorage(\n storage: AsyncStorageLike,\n key = \"naculus_web3_session\",\n): SessionStorage {\n return {\n async load(): Promise<UniversalWalletSession | null> {\n const raw = await storage.getItem(key);\n if (raw === null) return null;\n try {\n return JSON.parse(raw) as UniversalWalletSession;\n } catch {\n // An unreadable record is no session, not a crash at startup.\n await storage.removeItem(key);\n return null;\n }\n },\n async save(session: UniversalWalletSession): Promise<void> {\n await storage.setItem(key, JSON.stringify(session));\n },\n async clear(): Promise<void> {\n await storage.removeItem(key);\n },\n };\n}\n","import type { NativeWalletConnectOptions } from \"@naculus/connect-appkit-react\";\nimport type { LinkingLike } from \"./types\";\n\n/**\n * WalletConnect on React Native: deep links open through `Linking`. The\n * SignClient builds itself; with `@walletconnect/react-native-compat`\n * imported first in the app's entry file, its storage is AsyncStorage.\n */\nexport function nativeWalletConnect(\n linking: LinkingLike,\n): NativeWalletConnectOptions {\n return {\n openUrl: async (url) => {\n await linking.openURL(url);\n },\n };\n}\n\nexport interface WalletLinkTarget {\n id: string;\n name: string;\n /** Deep-link base the WalletConnect URI is appended to, e.g. `metamask://wc`. */\n deepLink: string;\n}\n\n/**\n * The wallets whose apps are installed. iOS answers only for schemes listed\n * under `LSApplicationQueriesSchemes` in Info.plist, Android only for those in\n * the manifest's `<queries>`; anything else reads as not installed.\n */\nexport async function installedWallets(\n linking: LinkingLike,\n wallets: readonly WalletLinkTarget[],\n): Promise<WalletLinkTarget[]> {\n const checks = await Promise.all(\n wallets.map(async (wallet) => {\n try {\n return await linking.canOpenURL(wallet.deepLink);\n } catch {\n return false;\n }\n }),\n );\n return wallets.filter((_, i) => checks[i]);\n}\n"],"mappings":"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","names":["import_connect_core"]}