@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.
- package/README.md +67 -0
- package/android/build.gradle +37 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/org/thru/walletnative/ThruWebViewBridgeModule.kt +77 -0
- package/app.plugin.cjs +101 -0
- package/dist/BrowserSDK-CpRFiJsW.d.ts +409 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +941 -0
- package/dist/index.js.map +1 -0
- package/dist/native/react.d.ts +109 -0
- package/dist/native/react.js +2381 -0
- package/dist/native/react.js.map +1 -0
- package/dist/native.d.ts +329 -0
- package/dist/native.js +1126 -0
- package/dist/native.js.map +1 -0
- package/dist/react-ui.d.ts +5 -0
- package/dist/react-ui.js +266 -0
- package/dist/react-ui.js.map +1 -0
- package/dist/react.d.ts +66 -0
- package/dist/react.js +1151 -0
- package/dist/react.js.map +1 -0
- package/expo-module.config.json +6 -0
- package/package.json +114 -0
- package/src/BrowserSDK.ts +315 -0
- package/src/index.ts +27 -0
- package/src/interfaces/IThruChain.ts +37 -0
- package/src/interfaces/accounts.ts +61 -0
- package/src/interfaces/index.ts +9 -0
- package/src/interfaces/types.ts +95 -0
- package/src/native/NativeSDK.test.ts +819 -0
- package/src/native/NativeSDK.ts +773 -0
- package/src/native/index.ts +39 -0
- package/src/native/provider/NativeProvider.ts +363 -0
- package/src/native/provider/WebViewBridge.test.ts +339 -0
- package/src/native/provider/WebViewBridge.ts +339 -0
- package/src/native/provider/chains/ThruChain.ts +85 -0
- package/src/native/provider/shell.html +88 -0
- package/src/native/provider/shell.test.ts +56 -0
- package/src/native/provider/shell.ts +111 -0
- package/src/native/provider/shims-html.d.ts +4 -0
- package/src/native/react/ThruContext.ts +37 -0
- package/src/native/react/ThruProvider.tsx +168 -0
- package/src/native/react/ThruWalletSheet.tsx +1162 -0
- package/src/native/react/android-webauthn.ts +37 -0
- package/src/native/react/hooks/useAccounts.ts +35 -0
- package/src/native/react/hooks/useThru.ts +11 -0
- package/src/native/react/hooks/useWallet.ts +71 -0
- package/src/native/react/hooks/useWalletAvailability.ts +31 -0
- package/src/native/react/hooks/waitForWallet.ts +21 -0
- package/src/native/react/index.ts +29 -0
- package/src/protocol/index.ts +2 -0
- package/src/protocol/postMessage.ts +283 -0
- package/src/protocol/walletState.ts +12 -0
- package/src/provider/EmbeddedProvider.ts +330 -0
- package/src/provider/IframeManager.ts +438 -0
- package/src/provider/chains/ThruChain.ts +86 -0
- package/src/provider/index.ts +17 -0
- package/src/provider/types/messages.ts +37 -0
- package/src/react/ThruContext.ts +31 -0
- package/src/react/ThruProvider.tsx +169 -0
- package/src/react/hooks/useAccounts.ts +38 -0
- package/src/react/hooks/useThru.ts +11 -0
- package/src/react/hooks/useWallet.ts +81 -0
- package/src/react/index.ts +30 -0
- package/src/react-ui/ThruAccountSwitcher.tsx +187 -0
- package/src/react-ui/custom.d.ts +8 -0
- package/src/react-ui/index.ts +1 -0
- package/src/static/logo.png +0 -0
- package/src/static/logomark_red.svg +11 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* Thin TypeScript shim over the Android Expo Module that wires
|
|
2
|
+
* react-native-webview to androidx.webkit's
|
|
3
|
+
* `setWebAuthnSupport`. On non-Android platforms (iOS, web)
|
|
4
|
+
* this is a no-op - WKWebView gets WebAuthn for free once the host
|
|
5
|
+
* declares `WKAppBoundDomains` (handled by our Expo config plugin). */
|
|
6
|
+
|
|
7
|
+
import { Platform } from 'react-native';
|
|
8
|
+
import { requireOptionalNativeModule } from 'expo-modules-core';
|
|
9
|
+
|
|
10
|
+
/* `requireOptionalNativeModule` returns null when the module isn't
|
|
11
|
+
* linked (e.g. Expo Go without the dev client, or non-Android). */
|
|
12
|
+
interface ThruWebViewBridgeNativeModule {
|
|
13
|
+
enableWebAuthnSupport: (viewTag?: number | null) => Promise<boolean>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const Native = requireOptionalNativeModule(
|
|
17
|
+
'ThruWebViewBridge'
|
|
18
|
+
) as ThruWebViewBridgeNativeModule | null;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Tell the mounted WebView to route WebAuthn calls through Credential
|
|
22
|
+
* Manager. Returns true if the call landed, false on
|
|
23
|
+
* platforms where it isn't needed or supported.
|
|
24
|
+
*
|
|
25
|
+
* Idempotent; safe to call on every WebView mount.
|
|
26
|
+
*/
|
|
27
|
+
export async function enableWebAuthnSupport(viewTag?: number | null): Promise<boolean> {
|
|
28
|
+
if (Platform.OS !== 'android') return false; /* iOS / web: no-op. */
|
|
29
|
+
if (!Native) return false; /* Module not linked (Expo Go fallback). */
|
|
30
|
+
try {
|
|
31
|
+
return await Native.enableWebAuthnSupport(viewTag);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
// eslint-disable-next-line no-console
|
|
34
|
+
console.warn('[@thru/wallet/native/react] enableWebAuthnSupport failed:', err);
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import type { WalletAccount } from "../../../interfaces";
|
|
3
|
+
import { useThru } from './useThru';
|
|
4
|
+
|
|
5
|
+
export interface UseAccountsOptions {
|
|
6
|
+
/** Fired whenever the active account flips (initial pick or switch). */
|
|
7
|
+
onAccountSelect?: (account: WalletAccount) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* useAccounts - mirror of @thru/wallet/react's useAccounts. Subscribes to
|
|
12
|
+
* `selectedAccount` flips and invokes the consumer's callback on real
|
|
13
|
+
* changes (deduped against the previous address).
|
|
14
|
+
*/
|
|
15
|
+
export function useAccounts({ onAccountSelect }: UseAccountsOptions = {}) {
|
|
16
|
+
const { accounts, selectedAccount, isConnected, isConnecting } = useThru();
|
|
17
|
+
const lastSeen = useRef<string | null>(null);
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (!selectedAccount) {
|
|
21
|
+
lastSeen.current = null;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (lastSeen.current === selectedAccount.address) return;
|
|
25
|
+
lastSeen.current = selectedAccount.address;
|
|
26
|
+
onAccountSelect?.(selectedAccount);
|
|
27
|
+
}, [selectedAccount, onAccountSelect]);
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
accounts,
|
|
31
|
+
selectedAccount,
|
|
32
|
+
isConnected,
|
|
33
|
+
isConnecting,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { ThruContext, type ThruContextValue } from '../ThruContext';
|
|
3
|
+
|
|
4
|
+
/** Returns the full ThruContextValue. Throws if used outside <ThruProvider>. */
|
|
5
|
+
export function useThru(): ThruContextValue {
|
|
6
|
+
const ctx = useContext(ThruContext);
|
|
7
|
+
if (!ctx) {
|
|
8
|
+
throw new Error('useThru must be used inside <ThruProvider>');
|
|
9
|
+
}
|
|
10
|
+
return ctx;
|
|
11
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import type { ConnectResult, IThruChain } from "../../../interfaces";
|
|
3
|
+
import type { ConnectOptions, SignInOptions } from "../../NativeSDK";
|
|
4
|
+
import { useThru } from './useThru';
|
|
5
|
+
import { waitForWallet } from './waitForWallet';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* useWallet - mirror of @thru/wallet/react's useWallet. The `wallet` field
|
|
9
|
+
* exposes the chain interface (`provider.thru`); `connect` /
|
|
10
|
+
* `disconnect` proxy through the SDK.
|
|
11
|
+
*/
|
|
12
|
+
export function useWallet() {
|
|
13
|
+
const {
|
|
14
|
+
wallet,
|
|
15
|
+
isConnected,
|
|
16
|
+
isConnecting,
|
|
17
|
+
accounts,
|
|
18
|
+
selectedAccount,
|
|
19
|
+
selectAccount,
|
|
20
|
+
manageAccounts,
|
|
21
|
+
walletAvailability,
|
|
22
|
+
} = useThru();
|
|
23
|
+
const walletRef = useRef(wallet);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
walletRef.current = wallet;
|
|
27
|
+
}, [wallet]);
|
|
28
|
+
|
|
29
|
+
const connect = useCallback(async (options?: ConnectOptions): Promise<ConnectResult> => {
|
|
30
|
+
const ready =
|
|
31
|
+
walletRef.current ?? (await waitForWallet(() => walletRef.current));
|
|
32
|
+
return ready.connect(options);
|
|
33
|
+
}, []);
|
|
34
|
+
|
|
35
|
+
const signIn = useCallback(async (options: SignInOptions): Promise<ConnectResult> => {
|
|
36
|
+
const ready =
|
|
37
|
+
walletRef.current ?? (await waitForWallet(() => walletRef.current));
|
|
38
|
+
return ready.signIn(options);
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
const disconnect = useCallback(async (): Promise<void> => {
|
|
42
|
+
const ready =
|
|
43
|
+
walletRef.current ?? (await waitForWallet(() => walletRef.current));
|
|
44
|
+
await ready.disconnect();
|
|
45
|
+
}, []);
|
|
46
|
+
|
|
47
|
+
const refreshWalletAvailability = useCallback(async (options?: ConnectOptions) => {
|
|
48
|
+
const ready =
|
|
49
|
+
walletRef.current ?? (await waitForWallet(() => walletRef.current));
|
|
50
|
+
return ready.refreshWalletAvailability(options);
|
|
51
|
+
}, []);
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
/** Chain interface (`provider.thru`); undefined until connected. */
|
|
55
|
+
wallet: wallet?.thru as IThruChain | undefined,
|
|
56
|
+
accounts,
|
|
57
|
+
connect,
|
|
58
|
+
signIn,
|
|
59
|
+
disconnect,
|
|
60
|
+
isConnected: isConnected && !!wallet,
|
|
61
|
+
isConnecting,
|
|
62
|
+
selectedAccount,
|
|
63
|
+
selectAccount,
|
|
64
|
+
manageAccounts,
|
|
65
|
+
walletAvailability,
|
|
66
|
+
hasPasskey: walletAvailability.hasPasskey,
|
|
67
|
+
hasWalletAccount: walletAvailability.hasWalletAccount,
|
|
68
|
+
isWalletAvailabilityLoading: walletAvailability.status === 'checking',
|
|
69
|
+
refreshWalletAvailability,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import type { ConnectOptions } from "../../NativeSDK";
|
|
3
|
+
import { useThru } from './useThru';
|
|
4
|
+
import { waitForWallet } from './waitForWallet';
|
|
5
|
+
|
|
6
|
+
export function useWalletAvailability() {
|
|
7
|
+
const { wallet, walletAvailability } = useThru();
|
|
8
|
+
const walletRef = useRef(wallet);
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
walletRef.current = wallet;
|
|
12
|
+
}, [wallet]);
|
|
13
|
+
|
|
14
|
+
const refreshWalletAvailability = async (options?: ConnectOptions) => {
|
|
15
|
+
const ready =
|
|
16
|
+
walletRef.current ?? (await waitForWallet(() => walletRef.current));
|
|
17
|
+
return ready.refreshWalletAvailability(options);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
walletAvailability,
|
|
22
|
+
refreshWalletAvailability,
|
|
23
|
+
hasPasskey: walletAvailability.hasPasskey,
|
|
24
|
+
hasWalletAccount: walletAvailability.hasWalletAccount,
|
|
25
|
+
isAuthorized: walletAvailability.isAuthorized,
|
|
26
|
+
isWalletAvailabilityLoading: walletAvailability.status === 'checking',
|
|
27
|
+
accounts: walletAvailability.accounts,
|
|
28
|
+
selectedAccount: walletAvailability.selectedAccount,
|
|
29
|
+
error: walletAvailability.error,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { NativeSDK } from "../../NativeSDK";
|
|
2
|
+
|
|
3
|
+
/** Spin until the SDK exists or `timeout` ms passes. */
|
|
4
|
+
export function waitForWallet(
|
|
5
|
+
getWallet: () => NativeSDK | null,
|
|
6
|
+
timeout = 5000,
|
|
7
|
+
interval = 100
|
|
8
|
+
): Promise<NativeSDK> {
|
|
9
|
+
return new Promise((resolve, reject) => {
|
|
10
|
+
const start = Date.now();
|
|
11
|
+
const check = () => {
|
|
12
|
+
const sdk = getWallet();
|
|
13
|
+
if (sdk) return resolve(sdk);
|
|
14
|
+
if (Date.now() - start > timeout) {
|
|
15
|
+
return reject(new Error('NativeSDK not initialized in time'));
|
|
16
|
+
}
|
|
17
|
+
setTimeout(check, interval);
|
|
18
|
+
};
|
|
19
|
+
check();
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export { ThruProvider } from './ThruProvider';
|
|
2
|
+
export type { ThruProviderProps } from './ThruProvider';
|
|
3
|
+
export { ThruContext } from './ThruContext';
|
|
4
|
+
export type { ThruContextValue } from './ThruContext';
|
|
5
|
+
|
|
6
|
+
export { ThruWalletSheet } from './ThruWalletSheet';
|
|
7
|
+
export type {
|
|
8
|
+
ThruWalletSheetProps,
|
|
9
|
+
ThruWalletSheetHandle,
|
|
10
|
+
} from './ThruWalletSheet';
|
|
11
|
+
|
|
12
|
+
export { useWallet } from './hooks/useWallet';
|
|
13
|
+
export { useWalletAvailability } from './hooks/useWalletAvailability';
|
|
14
|
+
export { useAccounts } from './hooks/useAccounts';
|
|
15
|
+
export { useThru } from './hooks/useThru';
|
|
16
|
+
|
|
17
|
+
export { enableWebAuthnSupport } from './android-webauthn';
|
|
18
|
+
|
|
19
|
+
export type {
|
|
20
|
+
WalletAccount,
|
|
21
|
+
ConnectResult,
|
|
22
|
+
} from "../../interfaces";
|
|
23
|
+
|
|
24
|
+
export type {
|
|
25
|
+
IosWebViewMode,
|
|
26
|
+
NativeSDKStorage,
|
|
27
|
+
WalletAvailability,
|
|
28
|
+
} from "../NativeSDK";
|
|
29
|
+
export type { ManageAccountsResult } from "../../protocol";
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AppMetadata,
|
|
3
|
+
ConnectResult,
|
|
4
|
+
ThruSigningContext,
|
|
5
|
+
WalletAccount,
|
|
6
|
+
} from "../interfaces";
|
|
7
|
+
|
|
8
|
+
export const POST_MESSAGE_REQUEST_TYPES = {
|
|
9
|
+
CONNECT: "connect",
|
|
10
|
+
DISCONNECT: "disconnect",
|
|
11
|
+
SIGN_MESSAGE: "signMessage",
|
|
12
|
+
SIGN_TRANSACTION: "signTransaction",
|
|
13
|
+
GET_ACCOUNTS: "getAccounts",
|
|
14
|
+
GET_CONNECTION_STATE: "getConnectionState",
|
|
15
|
+
GET_SIGNING_CONTEXT: "getSigningContext",
|
|
16
|
+
SELECT_ACCOUNT: "selectAccount",
|
|
17
|
+
MANAGE_ACCOUNTS: "manageAccounts",
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
export type RequestType =
|
|
21
|
+
(typeof POST_MESSAGE_REQUEST_TYPES)[keyof typeof POST_MESSAGE_REQUEST_TYPES];
|
|
22
|
+
|
|
23
|
+
export const EMBEDDED_PROVIDER_EVENTS = {
|
|
24
|
+
CONNECT_START: "connect_start",
|
|
25
|
+
CONNECT: "connect",
|
|
26
|
+
DISCONNECT: "disconnect",
|
|
27
|
+
CONNECT_ERROR: "connect_error",
|
|
28
|
+
ERROR: "error",
|
|
29
|
+
LOCK: "lock",
|
|
30
|
+
UI_SHOW: "ui_show",
|
|
31
|
+
ACCOUNT_CHANGED: "account_changed",
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
export type EmbeddedProviderEvent =
|
|
35
|
+
(typeof EMBEDDED_PROVIDER_EVENTS)[keyof typeof EMBEDDED_PROVIDER_EVENTS];
|
|
36
|
+
|
|
37
|
+
export const POST_MESSAGE_EVENT_TYPE = "event" as const;
|
|
38
|
+
|
|
39
|
+
export const IFRAME_READY_EVENT = "iframe:ready" as const;
|
|
40
|
+
|
|
41
|
+
export const DEFAULT_IFRAME_URL = "http://localhost:3000/embedded";
|
|
42
|
+
|
|
43
|
+
const REQUEST_ID_PREFIX = "req";
|
|
44
|
+
|
|
45
|
+
export const createRequestId = (prefix: string = REQUEST_ID_PREFIX): string => {
|
|
46
|
+
const random = Math.random().toString(36).slice(2, 11);
|
|
47
|
+
return `${prefix}_${Date.now()}_${random}`;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
interface BaseRequest {
|
|
51
|
+
id: string;
|
|
52
|
+
origin: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ConnectRequestMessage extends BaseRequest {
|
|
56
|
+
type: typeof POST_MESSAGE_REQUEST_TYPES.CONNECT;
|
|
57
|
+
payload: ConnectRequestPayload;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface DisconnectRequestMessage extends BaseRequest {
|
|
61
|
+
type: typeof POST_MESSAGE_REQUEST_TYPES.DISCONNECT;
|
|
62
|
+
payload?: undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface SignMessageRequestMessage extends BaseRequest {
|
|
66
|
+
type: typeof POST_MESSAGE_REQUEST_TYPES.SIGN_MESSAGE;
|
|
67
|
+
payload: SignMessagePayload;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface SignTransactionRequestMessage extends BaseRequest {
|
|
71
|
+
type: typeof POST_MESSAGE_REQUEST_TYPES.SIGN_TRANSACTION;
|
|
72
|
+
payload: SignTransactionPayload;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface GetAccountsRequestMessage extends BaseRequest {
|
|
76
|
+
type: typeof POST_MESSAGE_REQUEST_TYPES.GET_ACCOUNTS;
|
|
77
|
+
payload?: undefined;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface GetConnectionStateRequestMessage extends BaseRequest {
|
|
81
|
+
type: typeof POST_MESSAGE_REQUEST_TYPES.GET_CONNECTION_STATE;
|
|
82
|
+
payload: ConnectRequestPayload;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface GetSigningContextRequestMessage extends BaseRequest {
|
|
86
|
+
type: typeof POST_MESSAGE_REQUEST_TYPES.GET_SIGNING_CONTEXT;
|
|
87
|
+
payload?: undefined;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface SelectAccountRequestMessage extends BaseRequest {
|
|
91
|
+
type: typeof POST_MESSAGE_REQUEST_TYPES.SELECT_ACCOUNT;
|
|
92
|
+
payload: SelectAccountPayload;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface ManageAccountsRequestMessage extends BaseRequest {
|
|
96
|
+
type: typeof POST_MESSAGE_REQUEST_TYPES.MANAGE_ACCOUNTS;
|
|
97
|
+
payload?: undefined;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export type PostMessageRequest =
|
|
101
|
+
| ConnectRequestMessage
|
|
102
|
+
| DisconnectRequestMessage
|
|
103
|
+
| SignMessageRequestMessage
|
|
104
|
+
| SignTransactionRequestMessage
|
|
105
|
+
| GetAccountsRequestMessage
|
|
106
|
+
| GetConnectionStateRequestMessage
|
|
107
|
+
| GetSigningContextRequestMessage
|
|
108
|
+
| SelectAccountRequestMessage
|
|
109
|
+
| ManageAccountsRequestMessage;
|
|
110
|
+
|
|
111
|
+
export interface DisconnectResult {
|
|
112
|
+
// Empty object keeps compatibility with existing consumers expecting a success payload
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface GetAccountsResult {
|
|
116
|
+
accounts: WalletAccount[];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface GetConnectionStateResult {
|
|
120
|
+
isAuthorized: boolean;
|
|
121
|
+
isConnected: boolean;
|
|
122
|
+
isUnlocked: boolean;
|
|
123
|
+
hasPasskey: boolean;
|
|
124
|
+
hasWalletAccount: boolean;
|
|
125
|
+
accounts: WalletAccount[];
|
|
126
|
+
selectedAccount: WalletAccount | null;
|
|
127
|
+
metadata: AppMetadata | null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface SelectAccountPayload {
|
|
131
|
+
publicKey: string;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface SelectAccountResult {
|
|
135
|
+
account: WalletAccount;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface ManageAccountsResult {
|
|
139
|
+
accounts: WalletAccount[];
|
|
140
|
+
selectedAccount: WalletAccount | null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
type RequestResultMap = {
|
|
144
|
+
[POST_MESSAGE_REQUEST_TYPES.CONNECT]: ConnectResult;
|
|
145
|
+
[POST_MESSAGE_REQUEST_TYPES.DISCONNECT]: DisconnectResult;
|
|
146
|
+
[POST_MESSAGE_REQUEST_TYPES.SIGN_MESSAGE]: SignMessageResult;
|
|
147
|
+
[POST_MESSAGE_REQUEST_TYPES.SIGN_TRANSACTION]: SignTransactionResult;
|
|
148
|
+
[POST_MESSAGE_REQUEST_TYPES.GET_ACCOUNTS]: GetAccountsResult;
|
|
149
|
+
[POST_MESSAGE_REQUEST_TYPES.GET_CONNECTION_STATE]: GetConnectionStateResult;
|
|
150
|
+
[POST_MESSAGE_REQUEST_TYPES.GET_SIGNING_CONTEXT]: GetSigningContextResult;
|
|
151
|
+
[POST_MESSAGE_REQUEST_TYPES.SELECT_ACCOUNT]: SelectAccountResult;
|
|
152
|
+
[POST_MESSAGE_REQUEST_TYPES.MANAGE_ACCOUNTS]: ManageAccountsResult;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
interface ResponseErrorPayload {
|
|
156
|
+
code: ErrorCode;
|
|
157
|
+
message: string;
|
|
158
|
+
data?: unknown;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
type SuccessResponse<TType extends RequestType> = {
|
|
162
|
+
id: string;
|
|
163
|
+
success: true;
|
|
164
|
+
result: RequestResultMap[TType];
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
type ErrorResponse = {
|
|
168
|
+
id: string;
|
|
169
|
+
success: false;
|
|
170
|
+
error: ResponseErrorPayload;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
export type PostMessageResponse<TType extends RequestType = RequestType> =
|
|
174
|
+
| SuccessResponse<TType>
|
|
175
|
+
| ErrorResponse;
|
|
176
|
+
|
|
177
|
+
export type SuccessfulPostMessageResponse<
|
|
178
|
+
TType extends RequestType = RequestType,
|
|
179
|
+
> = Extract<PostMessageResponse<TType>, { success: true }>;
|
|
180
|
+
|
|
181
|
+
export type InferPostMessageResponse<TRequest extends PostMessageRequest> =
|
|
182
|
+
PostMessageResponse<TRequest["type"]>;
|
|
183
|
+
|
|
184
|
+
export type InferSuccessfulPostMessageResponse<
|
|
185
|
+
TRequest extends PostMessageRequest,
|
|
186
|
+
> = SuccessfulPostMessageResponse<TRequest["type"]>;
|
|
187
|
+
|
|
188
|
+
export interface PostMessageEvent<
|
|
189
|
+
TEvent extends EmbeddedProviderEvent = EmbeddedProviderEvent,
|
|
190
|
+
TData = any,
|
|
191
|
+
> {
|
|
192
|
+
type: typeof POST_MESSAGE_EVENT_TYPE;
|
|
193
|
+
event: TEvent;
|
|
194
|
+
data?: TData;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export const ErrorCode = {
|
|
198
|
+
USER_REJECTED: "USER_REJECTED",
|
|
199
|
+
WALLET_LOCKED: "WALLET_LOCKED",
|
|
200
|
+
INVALID_PASSWORD: "INVALID_PASSWORD",
|
|
201
|
+
ALREADY_CONNECTED: "ALREADY_CONNECTED",
|
|
202
|
+
ACCOUNT_NOT_FOUND: "ACCOUNT_NOT_FOUND",
|
|
203
|
+
ACCOUNT_CHANGED: "ACCOUNT_CHANGED",
|
|
204
|
+
INVALID_TRANSACTION: "INVALID_TRANSACTION",
|
|
205
|
+
TRANSACTION_FAILED: "TRANSACTION_FAILED",
|
|
206
|
+
INSUFFICIENT_FUNDS: "INSUFFICIENT_FUNDS",
|
|
207
|
+
NETWORK_ERROR: "NETWORK_ERROR",
|
|
208
|
+
TIMEOUT: "TIMEOUT",
|
|
209
|
+
UNKNOWN_ERROR: "UNKNOWN_ERROR",
|
|
210
|
+
} as const;
|
|
211
|
+
|
|
212
|
+
export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
213
|
+
|
|
214
|
+
export type ConnectMetadataInput = Partial<AppMetadata>;
|
|
215
|
+
|
|
216
|
+
export type ConnectIntent = "default" | "switch-account";
|
|
217
|
+
|
|
218
|
+
export interface ConnectRequestPayload {
|
|
219
|
+
metadata?: ConnectMetadataInput;
|
|
220
|
+
preferredAccountAddress?: string;
|
|
221
|
+
intent?: ConnectIntent;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export type { AppMetadata, ConnectResult };
|
|
225
|
+
|
|
226
|
+
export interface SignMessagePayload {
|
|
227
|
+
message: string | number[];
|
|
228
|
+
accountIndex?: number;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export interface SignMessageResult {
|
|
232
|
+
signature: number[];
|
|
233
|
+
publicKey: string;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Wallet-managed instruction signing intent.
|
|
238
|
+
*
|
|
239
|
+
* Dapps provide the instruction data and account context. The wallet owns
|
|
240
|
+
* signing strategy details such as passkey validation, fee payer choice,
|
|
241
|
+
* account ordering, headers, nonces, and final wire layout. Review metadata
|
|
242
|
+
* is treated as untrusted display-only data.
|
|
243
|
+
*/
|
|
244
|
+
export interface SignTransactionPayload {
|
|
245
|
+
walletAddress?: string;
|
|
246
|
+
programAddress: string;
|
|
247
|
+
instructionData: string;
|
|
248
|
+
readWriteAddresses?: string[];
|
|
249
|
+
readOnlyAddresses?: string[];
|
|
250
|
+
review?: TransactionReviewPayload;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export interface SignTransactionResult {
|
|
254
|
+
signedTransaction: string;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export interface TransactionReviewSimulation {
|
|
258
|
+
before?: string;
|
|
259
|
+
after?: string;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export interface TransactionReviewAbiReflection {
|
|
263
|
+
label?: string;
|
|
264
|
+
kind?: string | null;
|
|
265
|
+
typeName?: string;
|
|
266
|
+
value?: unknown;
|
|
267
|
+
rawHex?: string;
|
|
268
|
+
source?: string;
|
|
269
|
+
error?: string;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export interface TransactionReviewPayload {
|
|
273
|
+
appName?: string;
|
|
274
|
+
programAddress?: string;
|
|
275
|
+
abiName?: string;
|
|
276
|
+
instruction?: string;
|
|
277
|
+
simulation?: TransactionReviewSimulation;
|
|
278
|
+
abiReflection?: TransactionReviewAbiReflection;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export interface GetSigningContextResult {
|
|
282
|
+
signingContext: ThruSigningContext;
|
|
283
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { normalizeWalletAccountResult } from "../interfaces";
|
|
2
|
+
import type { GetConnectionStateResult } from "./postMessage";
|
|
3
|
+
|
|
4
|
+
export function normalizeConnectionStateResult(
|
|
5
|
+
result: GetConnectionStateResult,
|
|
6
|
+
): GetConnectionStateResult {
|
|
7
|
+
if (!result.isAuthorized || !result.hasPasskey) {
|
|
8
|
+
return { ...result, accounts: [], selectedAccount: null };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return normalizeWalletAccountResult(result);
|
|
12
|
+
}
|