@thru/wallet 0.2.22

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.
Files changed (69) hide show
  1. package/README.md +67 -0
  2. package/android/build.gradle +37 -0
  3. package/android/src/main/AndroidManifest.xml +1 -0
  4. package/android/src/main/java/org/thru/walletnative/ThruWebViewBridgeModule.kt +77 -0
  5. package/app.plugin.cjs +101 -0
  6. package/dist/BrowserSDK-CpRFiJsW.d.ts +409 -0
  7. package/dist/index.d.ts +23 -0
  8. package/dist/index.js +941 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/native/react.d.ts +109 -0
  11. package/dist/native/react.js +2381 -0
  12. package/dist/native/react.js.map +1 -0
  13. package/dist/native.d.ts +329 -0
  14. package/dist/native.js +1126 -0
  15. package/dist/native.js.map +1 -0
  16. package/dist/react-ui.d.ts +5 -0
  17. package/dist/react-ui.js +266 -0
  18. package/dist/react-ui.js.map +1 -0
  19. package/dist/react.d.ts +66 -0
  20. package/dist/react.js +1151 -0
  21. package/dist/react.js.map +1 -0
  22. package/expo-module.config.json +6 -0
  23. package/package.json +114 -0
  24. package/src/BrowserSDK.ts +315 -0
  25. package/src/index.ts +27 -0
  26. package/src/interfaces/IThruChain.ts +37 -0
  27. package/src/interfaces/accounts.ts +61 -0
  28. package/src/interfaces/index.ts +9 -0
  29. package/src/interfaces/types.ts +95 -0
  30. package/src/native/NativeSDK.test.ts +819 -0
  31. package/src/native/NativeSDK.ts +773 -0
  32. package/src/native/index.ts +39 -0
  33. package/src/native/provider/NativeProvider.ts +363 -0
  34. package/src/native/provider/WebViewBridge.test.ts +339 -0
  35. package/src/native/provider/WebViewBridge.ts +339 -0
  36. package/src/native/provider/chains/ThruChain.ts +85 -0
  37. package/src/native/provider/shell.html +88 -0
  38. package/src/native/provider/shell.test.ts +56 -0
  39. package/src/native/provider/shell.ts +111 -0
  40. package/src/native/provider/shims-html.d.ts +4 -0
  41. package/src/native/react/ThruContext.ts +37 -0
  42. package/src/native/react/ThruProvider.tsx +168 -0
  43. package/src/native/react/ThruWalletSheet.tsx +1162 -0
  44. package/src/native/react/android-webauthn.ts +37 -0
  45. package/src/native/react/hooks/useAccounts.ts +35 -0
  46. package/src/native/react/hooks/useThru.ts +11 -0
  47. package/src/native/react/hooks/useWallet.ts +71 -0
  48. package/src/native/react/hooks/useWalletAvailability.ts +31 -0
  49. package/src/native/react/hooks/waitForWallet.ts +21 -0
  50. package/src/native/react/index.ts +29 -0
  51. package/src/protocol/index.ts +2 -0
  52. package/src/protocol/postMessage.ts +283 -0
  53. package/src/protocol/walletState.ts +12 -0
  54. package/src/provider/EmbeddedProvider.ts +330 -0
  55. package/src/provider/IframeManager.ts +438 -0
  56. package/src/provider/chains/ThruChain.ts +86 -0
  57. package/src/provider/index.ts +17 -0
  58. package/src/provider/types/messages.ts +37 -0
  59. package/src/react/ThruContext.ts +31 -0
  60. package/src/react/ThruProvider.tsx +169 -0
  61. package/src/react/hooks/useAccounts.ts +38 -0
  62. package/src/react/hooks/useThru.ts +11 -0
  63. package/src/react/hooks/useWallet.ts +81 -0
  64. package/src/react/index.ts +30 -0
  65. package/src/react-ui/ThruAccountSwitcher.tsx +187 -0
  66. package/src/react-ui/custom.d.ts +8 -0
  67. package/src/react-ui/index.ts +1 -0
  68. package/src/static/logo.png +0 -0
  69. package/src/static/logomark_red.svg +11 -0
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # @thru/wallet
2
+
3
+ Low-level browser SDK for embedding the Thru wallet experience. It manages the iframe-based embedded provider, forwards lifecycle events, and exposes a ready-to-use `Thru` RPC client alongside wallet account management utilities.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @thru/wallet
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```ts
14
+ import { BrowserSDK } from '@thru/wallet';
15
+
16
+ // Configure the wallet iframe location and the RPC endpoint to talk to
17
+ const sdk = new BrowserSDK({
18
+ iframeUrl: 'https://wallet.thru.org/embedded',
19
+ rpcUrl: 'https://grpc-web.alphanet.thruput.org',
20
+ });
21
+
22
+ await sdk.initialize(); // injects the iframe once
23
+
24
+ // Observe lifecycle events
25
+ sdk.on('connect', ({ accounts }) => {
26
+ console.log('Connected accounts', accounts);
27
+ });
28
+ sdk.on('disconnect', () => console.log('Wallet disconnected'));
29
+ sdk.on('error', (err) => console.error('Wallet error', err));
30
+
31
+ // Trigger the wallet connect flow
32
+ const result = await sdk.connect();
33
+ const primary = result.accounts[0];
34
+
35
+ // Use the embedded Thru RPC client
36
+ const thru = sdk.getThru();
37
+ const account = await thru.accounts.get(primary.address);
38
+
39
+ // Disconnect when finished
40
+ await sdk.disconnect();
41
+ ```
42
+
43
+ ### Key Capabilities
44
+
45
+ - Handles iframe creation and cleanup (`initialize`, `destroy`)
46
+ - Connection helpers (`connect`, `disconnect`, `isConnected`, `selectAccount`)
47
+ - Event emitter for wallet state changes (`connect`, `disconnect`, `lock`, `error`, `accountChanged`)
48
+ - Access to a typed Thru RPC client via `sdk.getThru()` for querying on-chain data or submitting transactions
49
+
50
+ ## React Native
51
+
52
+ React Native apps use the native wallet entrypoints from this same package:
53
+
54
+ ```tsx
55
+ import { ThruProvider, ThruWalletSheet } from '@thru/wallet/native/react';
56
+
57
+ export default function Root() {
58
+ return (
59
+ <ThruProvider config={{ walletUrl: 'https://wallet.thru.org/embedded' }}>
60
+ <App />
61
+ <ThruWalletSheet />
62
+ </ThruProvider>
63
+ );
64
+ }
65
+ ```
66
+
67
+ Expo apps should install the config plugin from `@thru/wallet/native/plugin`.
@@ -0,0 +1,37 @@
1
+ apply plugin: 'com.android.library'
2
+ apply plugin: 'kotlin-android'
3
+ apply plugin: 'maven-publish'
4
+
5
+ group = 'org.thru.walletnative'
6
+ version = '0.0.1'
7
+
8
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
9
+ apply from: expoModulesCorePlugin
10
+ applyKotlinExpoModulesCorePlugin()
11
+
12
+ useCoreDependencies()
13
+ useExpoPublishing()
14
+
15
+ useDefaultAndroidSdkVersions()
16
+
17
+ android {
18
+ namespace = "org.thru.walletnative"
19
+
20
+ defaultConfig {
21
+ versionCode 1
22
+ versionName "0.0.1"
23
+ }
24
+
25
+ publishing {
26
+ multipleVariants {
27
+ withSourcesJar()
28
+ withJavadocJar()
29
+ allVariants()
30
+ }
31
+ }
32
+ }
33
+
34
+ dependencies {
35
+ implementation project(':expo-modules-core')
36
+ implementation 'androidx.webkit:webkit:1.14.0'
37
+ }
@@ -0,0 +1 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android" />
@@ -0,0 +1,77 @@
1
+ package org.thru.walletnative
2
+
3
+ import android.view.View
4
+ import android.view.ViewGroup
5
+ import android.webkit.WebView
6
+ import androidx.webkit.WebSettingsCompat
7
+ import androidx.webkit.WebViewFeature
8
+ import expo.modules.kotlin.modules.Module
9
+ import expo.modules.kotlin.modules.ModuleDefinition
10
+ import kotlinx.coroutines.Dispatchers
11
+ import kotlinx.coroutines.runBlocking
12
+ import kotlinx.coroutines.withContext
13
+
14
+ /**
15
+ * Bridges react-native-webview's `WebView` to androidx.webkit's
16
+ * `WebSettingsCompat.setWebAuthenticationSupport`, which is required
17
+ * for `navigator.credentials.create/get` to succeed inside the WebView.
18
+ * This module does not create or read passkeys itself; it only flips the
19
+ * WebView setting so the wallet page can own the WebAuthn request.
20
+ *
21
+ * react-native-webview does not call this itself today
22
+ * (https://github.com/react-native-webview/react-native-webview/issues/3807),
23
+ * so the host (ThruWalletSheet) calls our `enableWebAuthnSupport`
24
+ * function after the WebView mounts.
25
+ *
26
+ * The Gradle deps (`androidx.webkit:webkit:1.14.0`,
27
+ * `androidx.credentials:credentials*`) are pulled in by our Expo
28
+ * config plugin; no extra host-app wiring required.
29
+ */
30
+ class ThruWebViewBridgeModule : Module() {
31
+ override fun definition() = ModuleDefinition {
32
+ Name("ThruWebViewBridge")
33
+
34
+ /**
35
+ * Resolve the mounted react-native-webview by native view tag, find
36
+ * the WebView inside it, and enable WebAuthn support on it.
37
+ * Returns true if the call landed; false if the feature isn't
38
+ * supported on this WebView (e.g. ancient WebView version), no
39
+ * view tag was provided, or no WebView was found.
40
+ */
41
+ AsyncFunction("enableWebAuthnSupport") { viewTag: Int? ->
42
+ runBlocking {
43
+ withContext(Dispatchers.Main) {
44
+ val rootView = appContext.currentActivity?.window?.decorView
45
+ ?: return@withContext false
46
+ val targetView = viewTag?.let { rootView.findViewById<View>(it) }
47
+ ?: return@withContext false
48
+ val webView = findWebView(targetView)
49
+ ?: return@withContext false
50
+
51
+ if (!WebViewFeature.isFeatureSupported(WebViewFeature.WEB_AUTHENTICATION)) {
52
+ return@withContext false
53
+ }
54
+ WebSettingsCompat.setWebAuthenticationSupport(
55
+ webView.settings,
56
+ WebSettingsCompat.WEB_AUTHENTICATION_SUPPORT_FOR_APP,
57
+ )
58
+ true
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ /** react-native-webview wraps the WebView in an RNCWebView container;
65
+ * walk the descendants to find the first WebView. */
66
+ private fun findWebView(view: View?): WebView? {
67
+ if (view == null) return null
68
+ if (view is WebView) return view
69
+ if (view is ViewGroup) {
70
+ for (i in 0 until view.childCount) {
71
+ val found = findWebView(view.getChildAt(i))
72
+ if (found != null) return found
73
+ }
74
+ }
75
+ return null
76
+ }
77
+ }
package/app.plugin.cjs ADDED
@@ -0,0 +1,101 @@
1
+ /* Expo entrypoint for the config plugin. Keep this file dependency-free so
2
+ Expo can load it from a clean workspace before package build artifacts exist. */
3
+
4
+ const DEFAULT_RP_DOMAIN = "wallet.thru.org";
5
+ const APP_BOUND_DOMAIN_CAP = 10;
6
+ const MIN_ANDROID_SDK_FOR_PASSKEYS = 28;
7
+ const ANDROID_SYSTEM_BRIGHTNESS_PERMISSION =
8
+ "android.permission.WRITE_SETTINGS";
9
+ const IOS_ASSOCIATED_DOMAIN_MODES = new Set([
10
+ "developer",
11
+ "managed",
12
+ "developer+managed",
13
+ ]);
14
+
15
+ const ANDROID_CREDENTIAL_MANAGER_DEPS = [
16
+ "androidx.credentials:credentials:1.5.0",
17
+ "androidx.credentials:credentials-play-services-auth:1.5.0",
18
+ "androidx.webkit:webkit:1.14.0",
19
+ ];
20
+
21
+ function withThruWalletNative(config, opts = {}) {
22
+ const rpDomain = opts.rpDomain || DEFAULT_RP_DOMAIN;
23
+ const associatedDomainMode = opts.iosAssociatedDomainMode;
24
+ if (
25
+ associatedDomainMode &&
26
+ !IOS_ASSOCIATED_DOMAIN_MODES.has(associatedDomainMode)
27
+ ) {
28
+ throw new Error(
29
+ `[@thru/wallet/native/plugin] Invalid iosAssociatedDomainMode "${associatedDomainMode}". Expected developer, managed, or developer+managed.`,
30
+ );
31
+ }
32
+
33
+ if (!config.ios) config.ios = {};
34
+ if (!config.ios.infoPlist) config.ios.infoPlist = {};
35
+
36
+ const existingAppBoundDomains = Array.isArray(
37
+ config.ios.infoPlist.WKAppBoundDomains,
38
+ )
39
+ ? config.ios.infoPlist.WKAppBoundDomains
40
+ : [];
41
+ if (!existingAppBoundDomains.includes(rpDomain)) {
42
+ if (existingAppBoundDomains.length >= APP_BOUND_DOMAIN_CAP) {
43
+ throw new Error(
44
+ `[@thru/wallet/native/plugin] WKAppBoundDomains is capped at ${APP_BOUND_DOMAIN_CAP} entries; cannot add ${rpDomain}. Drop an unused domain from your Info.plist before adding the wallet.`,
45
+ );
46
+ }
47
+ config.ios.infoPlist.WKAppBoundDomains = [
48
+ ...existingAppBoundDomains,
49
+ rpDomain,
50
+ ];
51
+ }
52
+
53
+ const webCredentialsDomain = associatedDomainMode
54
+ ? `webcredentials:${rpDomain}?mode=${associatedDomainMode}`
55
+ : `webcredentials:${rpDomain}`;
56
+ const associatedDomains = Array.isArray(config.ios.associatedDomains)
57
+ ? config.ios.associatedDomains
58
+ : [];
59
+ if (!associatedDomains.includes(webCredentialsDomain)) {
60
+ config.ios.associatedDomains = [
61
+ ...associatedDomains,
62
+ webCredentialsDomain,
63
+ ];
64
+ }
65
+
66
+ if (!config.android) config.android = {};
67
+ const currentMin = config.android.minSdkVersion || 0;
68
+ if (currentMin < MIN_ANDROID_SDK_FOR_PASSKEYS) {
69
+ config.android.minSdkVersion = MIN_ANDROID_SDK_FOR_PASSKEYS;
70
+ }
71
+
72
+ const existingPermissions = Array.isArray(config.android.permissions)
73
+ ? config.android.permissions.slice()
74
+ : [];
75
+ if (!existingPermissions.includes(ANDROID_SYSTEM_BRIGHTNESS_PERMISSION)) {
76
+ existingPermissions.push(ANDROID_SYSTEM_BRIGHTNESS_PERMISSION);
77
+ }
78
+ config.android.permissions = existingPermissions;
79
+
80
+ const existingDeps = Array.isArray(config.android.extraDependencies)
81
+ ? config.android.extraDependencies.slice()
82
+ : [];
83
+ for (const dep of ANDROID_CREDENTIAL_MANAGER_DEPS) {
84
+ if (!existingDeps.includes(dep)) existingDeps.push(dep);
85
+ }
86
+ config.android.extraDependencies = existingDeps;
87
+
88
+ config.android.extraProguardRules = [
89
+ config.android.extraProguardRules,
90
+ "-keep class androidx.credentials.** { *; }",
91
+ "-keep class androidx.webkit.** { *; }",
92
+ "-keep class com.google.android.gms.fido.** { *; }",
93
+ ]
94
+ .filter(Boolean)
95
+ .join("\n");
96
+
97
+ return config;
98
+ }
99
+
100
+ module.exports = withThruWalletNative;
101
+ module.exports.default = withThruWalletNative;
@@ -0,0 +1,409 @@
1
+ import { Thru } from '@thru/sdk/client';
2
+
3
+ declare const AddressType: {
4
+ readonly THRU: "thru";
5
+ };
6
+ type AddressType = (typeof AddressType)[keyof typeof AddressType];
7
+ interface WalletAccount {
8
+ accountType: AddressType;
9
+ address: string;
10
+ label: string;
11
+ }
12
+ interface AppMetadata {
13
+ appId: string;
14
+ appName: string;
15
+ appUrl: string;
16
+ imageUrl?: string;
17
+ }
18
+ interface ConnectResult {
19
+ walletId?: string;
20
+ accounts: WalletAccount[];
21
+ selectedAccount?: WalletAccount | null;
22
+ status?: "pending" | "completed";
23
+ metadata?: AppMetadata;
24
+ }
25
+ declare const ThruTransactionEncoding: {
26
+ readonly SIGNING_PAYLOAD_BASE64: "signing_payload_base64";
27
+ readonly RAW_TRANSACTION_BASE64: "raw_transaction_base64";
28
+ };
29
+ type ThruTransactionEncoding = (typeof ThruTransactionEncoding)[keyof typeof ThruTransactionEncoding];
30
+ interface ThruSigningContext {
31
+ mode: "managed_fee_payer";
32
+ selectedAccountPublicKey: string | null;
33
+ feePayerPublicKey: string;
34
+ signerPublicKey: string;
35
+ acceptedInputEncodings: ThruTransactionEncoding[];
36
+ outputEncoding: typeof ThruTransactionEncoding.RAW_TRANSACTION_BASE64;
37
+ }
38
+ interface ThruTransactionReviewSimulation {
39
+ before?: string;
40
+ after?: string;
41
+ }
42
+ interface ThruTransactionReviewAbiReflection {
43
+ label?: string;
44
+ kind?: string | null;
45
+ typeName?: string;
46
+ value?: unknown;
47
+ rawHex?: string;
48
+ source?: string;
49
+ error?: string;
50
+ }
51
+ interface ThruTransactionReviewPayload {
52
+ appName?: string;
53
+ programAddress?: string;
54
+ abiName?: string;
55
+ instruction?: string;
56
+ simulation?: ThruTransactionReviewSimulation;
57
+ abiReflection?: ThruTransactionReviewAbiReflection;
58
+ }
59
+ interface ThruTransactionIntent {
60
+ walletAddress?: string;
61
+ programAddress: string;
62
+ instructionData: string;
63
+ readWriteAddresses?: string[];
64
+ readOnlyAddresses?: string[];
65
+ review?: ThruTransactionReviewPayload;
66
+ }
67
+ interface ConnectedApp {
68
+ accountId: number;
69
+ appId: string;
70
+ origin: string;
71
+ metadata: AppMetadata;
72
+ connectedAt: number;
73
+ updatedAt: number;
74
+ }
75
+ interface SignMessageParams {
76
+ message: string | Uint8Array;
77
+ networkId: string;
78
+ }
79
+ interface SignMessageResult$1 {
80
+ signature: Uint8Array;
81
+ publicKey: string;
82
+ }
83
+
84
+ /**
85
+ * Minimal Thru chain interface exposed to SDK consumers.
86
+ * The concrete implementation will evolve as the Thru transaction
87
+ * flow is fleshed out, but maintaining a dedicated contract now
88
+ * keeps the Surface area aligned with other chain adapters.
89
+ */
90
+ interface IThruChain {
91
+ /** Indicates whether the wallet has approved a Thru connection. */
92
+ readonly connected: boolean;
93
+ /**
94
+ * Initiate a Thru connection flow. Resolves with the connected address once
95
+ * the user has approved the request.
96
+ */
97
+ connect(): Promise<{
98
+ publicKey: string;
99
+ }>;
100
+ /** Disconnect the currently connected Thru account. */
101
+ disconnect(): Promise<void>;
102
+ /**
103
+ * Return the current embedded signing contract for Thru transactions.
104
+ *
105
+ * The selected account is the managed wallet account shown to the user.
106
+ * The fee payer / signer can differ when the wallet routes transactions
107
+ * through an embedded manager profile.
108
+ */
109
+ getSigningContext(): Promise<ThruSigningContext>;
110
+ /**
111
+ * Sign a wallet-managed transaction intent and return canonical raw
112
+ * transaction bytes encoded as base64. The wallet owns fee payer choice,
113
+ * account ordering, headers, nonces, and final wire layout.
114
+ */
115
+ signTransaction(transaction: ThruTransactionIntent): Promise<string>;
116
+ }
117
+
118
+ declare const POST_MESSAGE_REQUEST_TYPES: {
119
+ readonly CONNECT: "connect";
120
+ readonly DISCONNECT: "disconnect";
121
+ readonly SIGN_MESSAGE: "signMessage";
122
+ readonly SIGN_TRANSACTION: "signTransaction";
123
+ readonly GET_ACCOUNTS: "getAccounts";
124
+ readonly GET_CONNECTION_STATE: "getConnectionState";
125
+ readonly GET_SIGNING_CONTEXT: "getSigningContext";
126
+ readonly SELECT_ACCOUNT: "selectAccount";
127
+ readonly MANAGE_ACCOUNTS: "manageAccounts";
128
+ };
129
+ type RequestType = (typeof POST_MESSAGE_REQUEST_TYPES)[keyof typeof POST_MESSAGE_REQUEST_TYPES];
130
+ declare const EMBEDDED_PROVIDER_EVENTS: {
131
+ readonly CONNECT_START: "connect_start";
132
+ readonly CONNECT: "connect";
133
+ readonly DISCONNECT: "disconnect";
134
+ readonly CONNECT_ERROR: "connect_error";
135
+ readonly ERROR: "error";
136
+ readonly LOCK: "lock";
137
+ readonly UI_SHOW: "ui_show";
138
+ readonly ACCOUNT_CHANGED: "account_changed";
139
+ };
140
+ type EmbeddedProviderEvent = (typeof EMBEDDED_PROVIDER_EVENTS)[keyof typeof EMBEDDED_PROVIDER_EVENTS];
141
+ declare const POST_MESSAGE_EVENT_TYPE: "event";
142
+ declare const IFRAME_READY_EVENT: "iframe:ready";
143
+ declare const DEFAULT_IFRAME_URL = "http://localhost:3000/embedded";
144
+ declare const createRequestId: (prefix?: string) => string;
145
+ interface BaseRequest {
146
+ id: string;
147
+ origin: string;
148
+ }
149
+ interface ConnectRequestMessage extends BaseRequest {
150
+ type: typeof POST_MESSAGE_REQUEST_TYPES.CONNECT;
151
+ payload: ConnectRequestPayload;
152
+ }
153
+ interface DisconnectRequestMessage extends BaseRequest {
154
+ type: typeof POST_MESSAGE_REQUEST_TYPES.DISCONNECT;
155
+ payload?: undefined;
156
+ }
157
+ interface SignMessageRequestMessage extends BaseRequest {
158
+ type: typeof POST_MESSAGE_REQUEST_TYPES.SIGN_MESSAGE;
159
+ payload: SignMessagePayload;
160
+ }
161
+ interface SignTransactionRequestMessage extends BaseRequest {
162
+ type: typeof POST_MESSAGE_REQUEST_TYPES.SIGN_TRANSACTION;
163
+ payload: SignTransactionPayload;
164
+ }
165
+ interface GetAccountsRequestMessage extends BaseRequest {
166
+ type: typeof POST_MESSAGE_REQUEST_TYPES.GET_ACCOUNTS;
167
+ payload?: undefined;
168
+ }
169
+ interface GetConnectionStateRequestMessage extends BaseRequest {
170
+ type: typeof POST_MESSAGE_REQUEST_TYPES.GET_CONNECTION_STATE;
171
+ payload: ConnectRequestPayload;
172
+ }
173
+ interface GetSigningContextRequestMessage extends BaseRequest {
174
+ type: typeof POST_MESSAGE_REQUEST_TYPES.GET_SIGNING_CONTEXT;
175
+ payload?: undefined;
176
+ }
177
+ interface SelectAccountRequestMessage extends BaseRequest {
178
+ type: typeof POST_MESSAGE_REQUEST_TYPES.SELECT_ACCOUNT;
179
+ payload: SelectAccountPayload;
180
+ }
181
+ interface ManageAccountsRequestMessage extends BaseRequest {
182
+ type: typeof POST_MESSAGE_REQUEST_TYPES.MANAGE_ACCOUNTS;
183
+ payload?: undefined;
184
+ }
185
+ type PostMessageRequest = ConnectRequestMessage | DisconnectRequestMessage | SignMessageRequestMessage | SignTransactionRequestMessage | GetAccountsRequestMessage | GetConnectionStateRequestMessage | GetSigningContextRequestMessage | SelectAccountRequestMessage | ManageAccountsRequestMessage;
186
+ interface DisconnectResult {
187
+ }
188
+ interface GetAccountsResult {
189
+ accounts: WalletAccount[];
190
+ }
191
+ interface GetConnectionStateResult {
192
+ isAuthorized: boolean;
193
+ isConnected: boolean;
194
+ isUnlocked: boolean;
195
+ hasPasskey: boolean;
196
+ hasWalletAccount: boolean;
197
+ accounts: WalletAccount[];
198
+ selectedAccount: WalletAccount | null;
199
+ metadata: AppMetadata | null;
200
+ }
201
+ interface SelectAccountPayload {
202
+ publicKey: string;
203
+ }
204
+ interface SelectAccountResult {
205
+ account: WalletAccount;
206
+ }
207
+ interface ManageAccountsResult {
208
+ accounts: WalletAccount[];
209
+ selectedAccount: WalletAccount | null;
210
+ }
211
+ type RequestResultMap = {
212
+ [POST_MESSAGE_REQUEST_TYPES.CONNECT]: ConnectResult;
213
+ [POST_MESSAGE_REQUEST_TYPES.DISCONNECT]: DisconnectResult;
214
+ [POST_MESSAGE_REQUEST_TYPES.SIGN_MESSAGE]: SignMessageResult;
215
+ [POST_MESSAGE_REQUEST_TYPES.SIGN_TRANSACTION]: SignTransactionResult;
216
+ [POST_MESSAGE_REQUEST_TYPES.GET_ACCOUNTS]: GetAccountsResult;
217
+ [POST_MESSAGE_REQUEST_TYPES.GET_CONNECTION_STATE]: GetConnectionStateResult;
218
+ [POST_MESSAGE_REQUEST_TYPES.GET_SIGNING_CONTEXT]: GetSigningContextResult;
219
+ [POST_MESSAGE_REQUEST_TYPES.SELECT_ACCOUNT]: SelectAccountResult;
220
+ [POST_MESSAGE_REQUEST_TYPES.MANAGE_ACCOUNTS]: ManageAccountsResult;
221
+ };
222
+ interface ResponseErrorPayload {
223
+ code: ErrorCode;
224
+ message: string;
225
+ data?: unknown;
226
+ }
227
+ type SuccessResponse<TType extends RequestType> = {
228
+ id: string;
229
+ success: true;
230
+ result: RequestResultMap[TType];
231
+ };
232
+ type ErrorResponse = {
233
+ id: string;
234
+ success: false;
235
+ error: ResponseErrorPayload;
236
+ };
237
+ type PostMessageResponse<TType extends RequestType = RequestType> = SuccessResponse<TType> | ErrorResponse;
238
+ type SuccessfulPostMessageResponse<TType extends RequestType = RequestType> = Extract<PostMessageResponse<TType>, {
239
+ success: true;
240
+ }>;
241
+ type InferPostMessageResponse<TRequest extends PostMessageRequest> = PostMessageResponse<TRequest["type"]>;
242
+ type InferSuccessfulPostMessageResponse<TRequest extends PostMessageRequest> = SuccessfulPostMessageResponse<TRequest["type"]>;
243
+ interface PostMessageEvent<TEvent extends EmbeddedProviderEvent = EmbeddedProviderEvent, TData = any> {
244
+ type: typeof POST_MESSAGE_EVENT_TYPE;
245
+ event: TEvent;
246
+ data?: TData;
247
+ }
248
+ declare const ErrorCode: {
249
+ readonly USER_REJECTED: "USER_REJECTED";
250
+ readonly WALLET_LOCKED: "WALLET_LOCKED";
251
+ readonly INVALID_PASSWORD: "INVALID_PASSWORD";
252
+ readonly ALREADY_CONNECTED: "ALREADY_CONNECTED";
253
+ readonly ACCOUNT_NOT_FOUND: "ACCOUNT_NOT_FOUND";
254
+ readonly ACCOUNT_CHANGED: "ACCOUNT_CHANGED";
255
+ readonly INVALID_TRANSACTION: "INVALID_TRANSACTION";
256
+ readonly TRANSACTION_FAILED: "TRANSACTION_FAILED";
257
+ readonly INSUFFICIENT_FUNDS: "INSUFFICIENT_FUNDS";
258
+ readonly NETWORK_ERROR: "NETWORK_ERROR";
259
+ readonly TIMEOUT: "TIMEOUT";
260
+ readonly UNKNOWN_ERROR: "UNKNOWN_ERROR";
261
+ };
262
+ type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
263
+ type ConnectMetadataInput = Partial<AppMetadata>;
264
+ type ConnectIntent = "default" | "switch-account";
265
+ interface ConnectRequestPayload {
266
+ metadata?: ConnectMetadataInput;
267
+ preferredAccountAddress?: string;
268
+ intent?: ConnectIntent;
269
+ }
270
+
271
+ interface SignMessagePayload {
272
+ message: string | number[];
273
+ accountIndex?: number;
274
+ }
275
+ interface SignMessageResult {
276
+ signature: number[];
277
+ publicKey: string;
278
+ }
279
+ /**
280
+ * Wallet-managed instruction signing intent.
281
+ *
282
+ * Dapps provide the instruction data and account context. The wallet owns
283
+ * signing strategy details such as passkey validation, fee payer choice,
284
+ * account ordering, headers, nonces, and final wire layout. Review metadata
285
+ * is treated as untrusted display-only data.
286
+ */
287
+ interface SignTransactionPayload {
288
+ walletAddress?: string;
289
+ programAddress: string;
290
+ instructionData: string;
291
+ readWriteAddresses?: string[];
292
+ readOnlyAddresses?: string[];
293
+ review?: TransactionReviewPayload;
294
+ }
295
+ interface SignTransactionResult {
296
+ signedTransaction: string;
297
+ }
298
+ interface TransactionReviewSimulation {
299
+ before?: string;
300
+ after?: string;
301
+ }
302
+ interface TransactionReviewAbiReflection {
303
+ label?: string;
304
+ kind?: string | null;
305
+ typeName?: string;
306
+ value?: unknown;
307
+ rawHex?: string;
308
+ source?: string;
309
+ error?: string;
310
+ }
311
+ interface TransactionReviewPayload {
312
+ appName?: string;
313
+ programAddress?: string;
314
+ abiName?: string;
315
+ instruction?: string;
316
+ simulation?: TransactionReviewSimulation;
317
+ abiReflection?: TransactionReviewAbiReflection;
318
+ }
319
+ interface GetSigningContextResult {
320
+ signingContext: ThruSigningContext;
321
+ }
322
+
323
+ interface BrowserSDKConfig {
324
+ iframeUrl?: string;
325
+ addressTypes?: AddressType[];
326
+ rpcUrl?: string;
327
+ }
328
+ interface ConnectOptions {
329
+ metadata?: ConnectMetadataInput;
330
+ }
331
+ type SDKEvent = 'connect' | 'disconnect' | 'lock' | 'error' | 'accountChanged';
332
+ type EventCallback = (...args: any[]) => void;
333
+ /**
334
+ * Browser SDK - Main entry point for dApp developers
335
+ * Wraps EmbeddedProvider with a clean, simple API
336
+ */
337
+ declare class BrowserSDK {
338
+ private provider;
339
+ private eventListeners;
340
+ private initialized;
341
+ private thruClient;
342
+ private connectInFlight;
343
+ private lastConnectResult;
344
+ constructor(config?: BrowserSDKConfig);
345
+ /**
346
+ * Initialize the SDK (creates iframe)
347
+ * Must be called before using the SDK
348
+ */
349
+ initialize(): Promise<void>;
350
+ /**
351
+ * Connect to wallet
352
+ * Shows wallet modal and requests connection
353
+ */
354
+ connect(options?: ConnectOptions): Promise<ConnectResult>;
355
+ /**
356
+ * Mount the wallet iframe inline in a container.
357
+ */
358
+ mountInline(container: HTMLElement): Promise<void>;
359
+ /**
360
+ * Disconnect from wallet
361
+ */
362
+ disconnect(): Promise<void>;
363
+ /**
364
+ * Check if connected
365
+ */
366
+ isConnected(): boolean;
367
+ /**
368
+ * Get all accounts
369
+ */
370
+ getAccounts(): WalletAccount[];
371
+ getSelectedAccount(): WalletAccount | null;
372
+ selectAccount(publicKey: string): Promise<WalletAccount>;
373
+ manageAccounts(): Promise<ManageAccountsResult>;
374
+ /**
375
+ * Get Thru chain API (iframe-backed signer)
376
+ */
377
+ get thru(): IThruChain;
378
+ /**
379
+ * Event emitter: on
380
+ */
381
+ on(event: SDKEvent, callback: EventCallback): void;
382
+ /**
383
+ * Event emitter: off
384
+ */
385
+ off(event: SDKEvent, callback: EventCallback): void;
386
+ /**
387
+ * Event emitter: once (listen once and auto-remove)
388
+ */
389
+ once(event: SDKEvent, callback: EventCallback): void;
390
+ /**
391
+ * Emit event to all listeners
392
+ */
393
+ private emit;
394
+ /**
395
+ * Set up event forwarding from provider to SDK
396
+ */
397
+ private setupEventForwarding;
398
+ /**
399
+ * Destroy SDK and cleanup
400
+ */
401
+ destroy(): void;
402
+ private resolveMetadata;
403
+ private resolveAppUrl;
404
+ private deriveAppName;
405
+ getThru(): Thru;
406
+ private refreshCachedAccounts;
407
+ }
408
+
409
+ export { type TransactionReviewSimulation as $, AddressType as A, BrowserSDK as B, type ConnectIntent as C, DEFAULT_IFRAME_URL as D, EMBEDDED_PROVIDER_EVENTS as E, type SelectAccountPayload as F, type GetAccountsRequestMessage as G, type SelectAccountRequestMessage as H, IFRAME_READY_EVENT as I, type SelectAccountResult as J, type SignMessageParams as K, type SignMessagePayload as L, type ManageAccountsRequestMessage as M, type SignMessageRequestMessage as N, type SignMessageResult$1 as O, POST_MESSAGE_EVENT_TYPE as P, type SignTransactionPayload as Q, type RequestType as R, type SDKEvent as S, type SignTransactionRequestMessage as T, type SignTransactionResult as U, type SuccessfulPostMessageResponse as V, type ThruSigningContext as W, ThruTransactionEncoding as X, type ThruTransactionIntent as Y, type TransactionReviewAbiReflection as Z, type TransactionReviewPayload as _, type AppMetadata as a, type WalletAccount as a0, createRequestId as a1, type BrowserSDKConfig as b, type ConnectMetadataInput as c, type ConnectOptions as d, type ConnectRequestMessage as e, type ConnectRequestPayload as f, type ConnectResult as g, type ConnectedApp as h, type DisconnectRequestMessage as i, type DisconnectResult as j, type EmbeddedProviderEvent as k, ErrorCode as l, type EventCallback as m, type GetAccountsResult as n, type GetConnectionStateRequestMessage as o, type GetConnectionStateResult as p, type GetSigningContextRequestMessage as q, type GetSigningContextResult as r, type IThruChain as s, type InferPostMessageResponse as t, type InferSuccessfulPostMessageResponse as u, type ManageAccountsResult as v, POST_MESSAGE_REQUEST_TYPES as w, type PostMessageEvent as x, type PostMessageRequest as y, type PostMessageResponse as z };