@horus-wallet/sdk-react 0.1.0-beta.2

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.
@@ -0,0 +1,314 @@
1
+ import { ReactNode, ButtonHTMLAttributes } from 'react';
2
+
3
+ /**
4
+ * Public types for `@horus-wallet/sdk-react`.
5
+ *
6
+ * The React package targets the partner's BACKEND-PROXY pattern:
7
+ * partner runs a thin proxy on their server (which holds the
8
+ * `hk_sk_*` secret) and the React hooks call that proxy. Each hook's
9
+ * `apiBase` defaults to `/api/horus` — partners can override via
10
+ * provider config. v0.2 will add a publishable-key tier that lets
11
+ * the React SDK call Horus directly without the partner-backend hop.
12
+ */
13
+ /** Tokens returned from any successful auth flow. */
14
+ interface AuthTokens {
15
+ idToken: string;
16
+ refreshToken: string;
17
+ expiresIn: number;
18
+ /** Local epoch-seconds when the cached idToken expires. Computed on receipt. */
19
+ localExpiresAt: number;
20
+ localId: string;
21
+ email?: string;
22
+ emailVerified?: boolean;
23
+ displayName?: string;
24
+ photoUrl?: string;
25
+ providerId?: string;
26
+ }
27
+ /** Subset of the tokens that's safe to expose to consuming hooks. */
28
+ interface User {
29
+ uid: string;
30
+ email?: string;
31
+ emailVerified?: boolean;
32
+ displayName?: string;
33
+ photoUrl?: string;
34
+ /** Provider id from the sign-in path: 'password' | 'emailLink' | 'google.com' | etc. */
35
+ providerId?: string;
36
+ }
37
+ type AuthState = {
38
+ status: 'loading';
39
+ } | {
40
+ status: 'unauthenticated';
41
+ } | {
42
+ status: 'authenticated';
43
+ user: User;
44
+ tokens: AuthTokens;
45
+ };
46
+ /** Branding the partner can pass to the popup-opened auth flows. Mirrors the SDK's HorusAuthBranding shape. */
47
+ interface HorusBranding {
48
+ logoUrl?: string;
49
+ brandName?: string;
50
+ primaryColor?: string;
51
+ backgroundColor?: string;
52
+ fontFamily?: string;
53
+ termsUrl?: string;
54
+ privacyUrl?: string;
55
+ showPoweredByHorus?: boolean;
56
+ }
57
+ /** Configuration for `<HorusProvider>`. */
58
+ interface HorusProviderConfig {
59
+ /** Server-assigned id of the partner's app. Used by the popup for white-label policy lookup. */
60
+ appId: string;
61
+ /**
62
+ * URL prefix where the partner's backend exposes the Horus proxy
63
+ * routes. Defaults to `/api/horus`. The proxy routes the SDK
64
+ * expects:
65
+ * - POST {apiBase}/auth/email/signin → tokens
66
+ * - POST {apiBase}/auth/email/signup → tokens
67
+ * - POST {apiBase}/auth/email-link/send → ok
68
+ * - POST {apiBase}/auth/email-link/verify → tokens
69
+ * - POST {apiBase}/auth/oauth → tokens (federate Google/Apple/etc.)
70
+ * - POST {apiBase}/auth/refresh → tokens
71
+ * - GET {apiBase}/wallets → wallets list
72
+ * - GET {apiBase}/wallets/:network → wallet details
73
+ * - POST {apiBase}/sign-message → signature
74
+ * - POST {apiBase}/transfer/native → tx hash
75
+ * - POST {apiBase}/transfer/token → tx hash
76
+ *
77
+ * The README shows a reference backend implementation in <50 lines.
78
+ */
79
+ apiBase?: string;
80
+ /**
81
+ * Auth-page URL. Defaults to `https://auth.horuswallet.com`. The
82
+ * popup-based loginWithGoogle / loginWithEmailLink / loginWithPhone
83
+ * methods open this URL.
84
+ */
85
+ authPageUrl?: string;
86
+ /** Per-popup branding — passed to HorusAuth. White-label tier is gated server-side. */
87
+ branding?: HorusBranding;
88
+ /** Where to persist tokens between page loads. Default 'localStorage'. */
89
+ tokenStorage?: 'localStorage' | 'sessionStorage' | 'memory';
90
+ /**
91
+ * If a fetch returns 401, retry once after refreshing the token.
92
+ * Default true. Disable when you're handling expiry manually.
93
+ */
94
+ autoRefresh?: boolean;
95
+ }
96
+
97
+ /**
98
+ * Provider component — partner wraps their app once, hooks Just Work
99
+ * everywhere underneath.
100
+ *
101
+ * <HorusProvider appId="app_acme123">
102
+ * <App />
103
+ * </HorusProvider>
104
+ *
105
+ * Reads tokens from the configured store on mount, exposes them via
106
+ * Context, and refreshes proactively when they near expiry. Multiple
107
+ * tabs stay in sync via a `storage` event listener.
108
+ */
109
+
110
+ interface HorusProviderProps extends HorusProviderConfig {
111
+ children: ReactNode;
112
+ }
113
+ declare function HorusProvider(props: HorusProviderProps): JSX.Element;
114
+
115
+ /**
116
+ * The main auth hook. Returns the current state plus every sign-in
117
+ * method we expose. Mirrors Privy's `usePrivy()` shape so partners
118
+ * coming from there have a familiar API.
119
+ *
120
+ * const {
121
+ * ready, // SDK initialized
122
+ * authenticated, // true if user is signed in
123
+ * user, // { uid, email, ... } or undefined
124
+ * loginWithEmail,
125
+ * signUpWithEmail,
126
+ * loginWithGoogle, // popup
127
+ * loginWithEmailLink,
128
+ * loginWithPhone, // popup (SMS verification via auth.horuswallet.com)
129
+ * sendEmailLink,
130
+ * verifyEmailLink,
131
+ * logout,
132
+ * refresh,
133
+ * } = useHorusAuth();
134
+ */
135
+
136
+ interface EmailPasswordInput {
137
+ email: string;
138
+ password: string;
139
+ }
140
+ interface SendEmailLinkInput {
141
+ email: string;
142
+ /** URL on the partner's site that the magic-link returns to. */
143
+ continueUrl: string;
144
+ }
145
+ interface VerifyEmailLinkInput {
146
+ email: string;
147
+ oobCode: string;
148
+ }
149
+ interface UseHorusAuthResult {
150
+ /** True once the provider has hydrated from storage. */
151
+ ready: boolean;
152
+ /** True if there's a valid cached idToken. */
153
+ authenticated: boolean;
154
+ /** Current user's identity claims, or undefined when unauthenticated. */
155
+ user: User | undefined;
156
+ /** Email + password sign-in. */
157
+ loginWithEmail: (input: EmailPasswordInput) => Promise<User>;
158
+ /** Email + password sign-up. */
159
+ signUpWithEmail: (input: EmailPasswordInput) => Promise<User>;
160
+ /** Send a magic link to the given email. Two-step — call verifyEmailLink with the oobCode after the user clicks. */
161
+ sendEmailLink: (input: SendEmailLinkInput) => Promise<void>;
162
+ /** Complete a magic-link sign-in given the oobCode the partner extracted from the redirect URL. */
163
+ verifyEmailLink: (input: VerifyEmailLinkInput) => Promise<User>;
164
+ /** Open the auth.horuswallet.com popup for Google sign-in. */
165
+ loginWithGoogle: () => Promise<User>;
166
+ /** Open the popup for email-link UI (alternative to send/verify if the partner doesn't have a redirect page). */
167
+ loginWithEmailLink: () => Promise<User>;
168
+ /** Open the popup for phone (SMS) sign-in. */
169
+ loginWithPhone: (opts?: {
170
+ phone?: string;
171
+ }) => Promise<User>;
172
+ /** Sign out — clears tokens locally; partner's backend should also revoke if applicable. */
173
+ logout: () => void;
174
+ /** Manually refresh the cached idToken. */
175
+ refresh: () => Promise<AuthTokens>;
176
+ }
177
+ declare function useHorusAuth(): UseHorusAuthResult;
178
+
179
+ /**
180
+ * Convenience hook — partners that only want the current user object
181
+ * without the full auth surface. Returns `undefined` when
182
+ * unauthenticated; never throws.
183
+ */
184
+
185
+ declare function useUser(): User | undefined;
186
+
187
+ /**
188
+ * `useWallets()` — fetches the signed-in user's wallets from the
189
+ * partner's backend proxy. Refetches when auth state changes.
190
+ *
191
+ * Mirror of Privy's `useWallets()` — partners coming from there get
192
+ * a familiar `{ wallets, ready }` shape. Each wallet is a thin
193
+ * descriptor; signing happens via `useSignMessage` / `useTransfer`
194
+ * (kept as separate hooks so a single re-render of one doesn't
195
+ * invalidate the other).
196
+ */
197
+ interface WalletDescriptor {
198
+ network: string;
199
+ networkType?: string;
200
+ /** Public address — chain-specific shape (0x… for EVM, base58 for ICP, etc.). */
201
+ publicKey: string;
202
+ defaultReceivingAddress?: string;
203
+ hasPassword?: boolean;
204
+ }
205
+ interface UseWalletsResult {
206
+ ready: boolean;
207
+ wallets: WalletDescriptor[];
208
+ /** Manual refetch — useful after wallets.create or import. */
209
+ refresh: () => Promise<void>;
210
+ /** Last error from the load, if any. */
211
+ error: Error | undefined;
212
+ }
213
+ declare function useWallets(): UseWalletsResult;
214
+
215
+ /**
216
+ * `useSignMessage()` — signs a UTF-8 message with the user's wallet.
217
+ * EVM applies EIP-191 prefix server-side; Casper raw-signs; other
218
+ * chains follow their conventions. Returns a stable callback that
219
+ * `useState`-loop-friendly forms can wire to a submit handler.
220
+ */
221
+ interface SignMessageInput {
222
+ network: string;
223
+ networkType: 'MAINNET' | 'TESTNET';
224
+ message: string;
225
+ walletIndex?: number;
226
+ /** Wallet password if the user has one. Many partners prompt + pass inline. */
227
+ password?: string;
228
+ }
229
+ interface UseSignMessageResult {
230
+ signMessage: (input: SignMessageInput) => Promise<string>;
231
+ /** True while a signature request is in flight. */
232
+ pending: boolean;
233
+ /** Last error, if any. Cleared on the next attempt. */
234
+ error: Error | undefined;
235
+ }
236
+ declare function useSignMessage(): UseSignMessageResult;
237
+
238
+ /**
239
+ * `useTransfer()` — native + token transfer helpers backed by the
240
+ * partner's proxy. Each variant returns `{ pending, error }` so
241
+ * forms can drive disabled-state without local plumbing.
242
+ */
243
+ interface NativeTransferInput {
244
+ network: string;
245
+ networkType: 'MAINNET' | 'TESTNET';
246
+ /** One or more recipient addresses. */
247
+ recipients: string[];
248
+ /** Amount in the chain's smallest unit (wei / sats / motes / e8s). String / bigint / number. */
249
+ amount: string | bigint | number;
250
+ walletIndex?: number;
251
+ password?: string;
252
+ }
253
+ interface TokenTransferInput {
254
+ network: string;
255
+ networkType: 'MAINNET' | 'TESTNET';
256
+ tokenAddress: string;
257
+ recipient: string;
258
+ amount: string | bigint | number;
259
+ walletIndex?: number;
260
+ password?: string;
261
+ }
262
+ interface UseTransferResult {
263
+ native: (input: NativeTransferInput) => Promise<{
264
+ txHash: string;
265
+ }>;
266
+ token: (input: TokenTransferInput) => Promise<{
267
+ txHash: string;
268
+ }>;
269
+ pending: boolean;
270
+ error: Error | undefined;
271
+ }
272
+ declare function useTransfer(): UseTransferResult;
273
+
274
+ /**
275
+ * `<HorusLoginButton>` — the simplest "drop in and ship" component.
276
+ * Renders a styled button that opens the auth.horuswallet.com popup
277
+ * for the configured flow. Partners that want full UI control build
278
+ * their own button + call `useHorusAuth()` methods directly.
279
+ *
280
+ * <HorusLoginButton flow="google">Continue with Google</HorusLoginButton>
281
+ *
282
+ * Picks up branding + appId from the HorusProvider automatically.
283
+ * Auto-disables itself while the popup is open so a double-click
284
+ * doesn't open a second window.
285
+ */
286
+
287
+ type PopupFlow = 'google' | 'email_link' | 'phone';
288
+ interface HorusLoginButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick' | 'onError'> {
289
+ /** Which flow to open. Defaults to 'google' — the most common one-click signup. */
290
+ flow?: PopupFlow;
291
+ /** Pre-fill for the phone flow. Ignored otherwise. */
292
+ phone?: string;
293
+ /** Called after a successful sign-in. Receives the new user. */
294
+ onAuthenticated?: (user: ReturnType<typeof useHorusAuth>['user']) => void;
295
+ /** Called on user cancel / popup-blocked / auth error. */
296
+ onError?: (err: Error) => void;
297
+ children?: ReactNode;
298
+ }
299
+ declare function HorusLoginButton({ flow, phone, onAuthenticated, onError, children, disabled, style, ...rest }: HorusLoginButtonProps): JSX.Element;
300
+
301
+ /**
302
+ * Fetch wrapper for calls to the partner's backend proxy. Handles
303
+ * the auto-refresh-on-401 dance + JSON serialization + a typed
304
+ * error so consuming hooks can branch on `err.status`.
305
+ */
306
+
307
+ declare class HorusHttpError extends Error {
308
+ readonly status: number;
309
+ readonly code?: string;
310
+ readonly body: unknown;
311
+ constructor(status: number, message: string, body: unknown, code?: string);
312
+ }
313
+
314
+ export { type AuthState, type AuthTokens, type HorusBranding, HorusHttpError, HorusLoginButton, type HorusLoginButtonProps, HorusProvider, type HorusProviderConfig, type HorusProviderProps, type NativeTransferInput, type SignMessageInput, type TokenTransferInput, type UseHorusAuthResult, type User, type WalletDescriptor, useHorusAuth, useSignMessage, useTransfer, useUser, useWallets };
@@ -0,0 +1,314 @@
1
+ import { ReactNode, ButtonHTMLAttributes } from 'react';
2
+
3
+ /**
4
+ * Public types for `@horus-wallet/sdk-react`.
5
+ *
6
+ * The React package targets the partner's BACKEND-PROXY pattern:
7
+ * partner runs a thin proxy on their server (which holds the
8
+ * `hk_sk_*` secret) and the React hooks call that proxy. Each hook's
9
+ * `apiBase` defaults to `/api/horus` — partners can override via
10
+ * provider config. v0.2 will add a publishable-key tier that lets
11
+ * the React SDK call Horus directly without the partner-backend hop.
12
+ */
13
+ /** Tokens returned from any successful auth flow. */
14
+ interface AuthTokens {
15
+ idToken: string;
16
+ refreshToken: string;
17
+ expiresIn: number;
18
+ /** Local epoch-seconds when the cached idToken expires. Computed on receipt. */
19
+ localExpiresAt: number;
20
+ localId: string;
21
+ email?: string;
22
+ emailVerified?: boolean;
23
+ displayName?: string;
24
+ photoUrl?: string;
25
+ providerId?: string;
26
+ }
27
+ /** Subset of the tokens that's safe to expose to consuming hooks. */
28
+ interface User {
29
+ uid: string;
30
+ email?: string;
31
+ emailVerified?: boolean;
32
+ displayName?: string;
33
+ photoUrl?: string;
34
+ /** Provider id from the sign-in path: 'password' | 'emailLink' | 'google.com' | etc. */
35
+ providerId?: string;
36
+ }
37
+ type AuthState = {
38
+ status: 'loading';
39
+ } | {
40
+ status: 'unauthenticated';
41
+ } | {
42
+ status: 'authenticated';
43
+ user: User;
44
+ tokens: AuthTokens;
45
+ };
46
+ /** Branding the partner can pass to the popup-opened auth flows. Mirrors the SDK's HorusAuthBranding shape. */
47
+ interface HorusBranding {
48
+ logoUrl?: string;
49
+ brandName?: string;
50
+ primaryColor?: string;
51
+ backgroundColor?: string;
52
+ fontFamily?: string;
53
+ termsUrl?: string;
54
+ privacyUrl?: string;
55
+ showPoweredByHorus?: boolean;
56
+ }
57
+ /** Configuration for `<HorusProvider>`. */
58
+ interface HorusProviderConfig {
59
+ /** Server-assigned id of the partner's app. Used by the popup for white-label policy lookup. */
60
+ appId: string;
61
+ /**
62
+ * URL prefix where the partner's backend exposes the Horus proxy
63
+ * routes. Defaults to `/api/horus`. The proxy routes the SDK
64
+ * expects:
65
+ * - POST {apiBase}/auth/email/signin → tokens
66
+ * - POST {apiBase}/auth/email/signup → tokens
67
+ * - POST {apiBase}/auth/email-link/send → ok
68
+ * - POST {apiBase}/auth/email-link/verify → tokens
69
+ * - POST {apiBase}/auth/oauth → tokens (federate Google/Apple/etc.)
70
+ * - POST {apiBase}/auth/refresh → tokens
71
+ * - GET {apiBase}/wallets → wallets list
72
+ * - GET {apiBase}/wallets/:network → wallet details
73
+ * - POST {apiBase}/sign-message → signature
74
+ * - POST {apiBase}/transfer/native → tx hash
75
+ * - POST {apiBase}/transfer/token → tx hash
76
+ *
77
+ * The README shows a reference backend implementation in <50 lines.
78
+ */
79
+ apiBase?: string;
80
+ /**
81
+ * Auth-page URL. Defaults to `https://auth.horuswallet.com`. The
82
+ * popup-based loginWithGoogle / loginWithEmailLink / loginWithPhone
83
+ * methods open this URL.
84
+ */
85
+ authPageUrl?: string;
86
+ /** Per-popup branding — passed to HorusAuth. White-label tier is gated server-side. */
87
+ branding?: HorusBranding;
88
+ /** Where to persist tokens between page loads. Default 'localStorage'. */
89
+ tokenStorage?: 'localStorage' | 'sessionStorage' | 'memory';
90
+ /**
91
+ * If a fetch returns 401, retry once after refreshing the token.
92
+ * Default true. Disable when you're handling expiry manually.
93
+ */
94
+ autoRefresh?: boolean;
95
+ }
96
+
97
+ /**
98
+ * Provider component — partner wraps their app once, hooks Just Work
99
+ * everywhere underneath.
100
+ *
101
+ * <HorusProvider appId="app_acme123">
102
+ * <App />
103
+ * </HorusProvider>
104
+ *
105
+ * Reads tokens from the configured store on mount, exposes them via
106
+ * Context, and refreshes proactively when they near expiry. Multiple
107
+ * tabs stay in sync via a `storage` event listener.
108
+ */
109
+
110
+ interface HorusProviderProps extends HorusProviderConfig {
111
+ children: ReactNode;
112
+ }
113
+ declare function HorusProvider(props: HorusProviderProps): JSX.Element;
114
+
115
+ /**
116
+ * The main auth hook. Returns the current state plus every sign-in
117
+ * method we expose. Mirrors Privy's `usePrivy()` shape so partners
118
+ * coming from there have a familiar API.
119
+ *
120
+ * const {
121
+ * ready, // SDK initialized
122
+ * authenticated, // true if user is signed in
123
+ * user, // { uid, email, ... } or undefined
124
+ * loginWithEmail,
125
+ * signUpWithEmail,
126
+ * loginWithGoogle, // popup
127
+ * loginWithEmailLink,
128
+ * loginWithPhone, // popup (SMS verification via auth.horuswallet.com)
129
+ * sendEmailLink,
130
+ * verifyEmailLink,
131
+ * logout,
132
+ * refresh,
133
+ * } = useHorusAuth();
134
+ */
135
+
136
+ interface EmailPasswordInput {
137
+ email: string;
138
+ password: string;
139
+ }
140
+ interface SendEmailLinkInput {
141
+ email: string;
142
+ /** URL on the partner's site that the magic-link returns to. */
143
+ continueUrl: string;
144
+ }
145
+ interface VerifyEmailLinkInput {
146
+ email: string;
147
+ oobCode: string;
148
+ }
149
+ interface UseHorusAuthResult {
150
+ /** True once the provider has hydrated from storage. */
151
+ ready: boolean;
152
+ /** True if there's a valid cached idToken. */
153
+ authenticated: boolean;
154
+ /** Current user's identity claims, or undefined when unauthenticated. */
155
+ user: User | undefined;
156
+ /** Email + password sign-in. */
157
+ loginWithEmail: (input: EmailPasswordInput) => Promise<User>;
158
+ /** Email + password sign-up. */
159
+ signUpWithEmail: (input: EmailPasswordInput) => Promise<User>;
160
+ /** Send a magic link to the given email. Two-step — call verifyEmailLink with the oobCode after the user clicks. */
161
+ sendEmailLink: (input: SendEmailLinkInput) => Promise<void>;
162
+ /** Complete a magic-link sign-in given the oobCode the partner extracted from the redirect URL. */
163
+ verifyEmailLink: (input: VerifyEmailLinkInput) => Promise<User>;
164
+ /** Open the auth.horuswallet.com popup for Google sign-in. */
165
+ loginWithGoogle: () => Promise<User>;
166
+ /** Open the popup for email-link UI (alternative to send/verify if the partner doesn't have a redirect page). */
167
+ loginWithEmailLink: () => Promise<User>;
168
+ /** Open the popup for phone (SMS) sign-in. */
169
+ loginWithPhone: (opts?: {
170
+ phone?: string;
171
+ }) => Promise<User>;
172
+ /** Sign out — clears tokens locally; partner's backend should also revoke if applicable. */
173
+ logout: () => void;
174
+ /** Manually refresh the cached idToken. */
175
+ refresh: () => Promise<AuthTokens>;
176
+ }
177
+ declare function useHorusAuth(): UseHorusAuthResult;
178
+
179
+ /**
180
+ * Convenience hook — partners that only want the current user object
181
+ * without the full auth surface. Returns `undefined` when
182
+ * unauthenticated; never throws.
183
+ */
184
+
185
+ declare function useUser(): User | undefined;
186
+
187
+ /**
188
+ * `useWallets()` — fetches the signed-in user's wallets from the
189
+ * partner's backend proxy. Refetches when auth state changes.
190
+ *
191
+ * Mirror of Privy's `useWallets()` — partners coming from there get
192
+ * a familiar `{ wallets, ready }` shape. Each wallet is a thin
193
+ * descriptor; signing happens via `useSignMessage` / `useTransfer`
194
+ * (kept as separate hooks so a single re-render of one doesn't
195
+ * invalidate the other).
196
+ */
197
+ interface WalletDescriptor {
198
+ network: string;
199
+ networkType?: string;
200
+ /** Public address — chain-specific shape (0x… for EVM, base58 for ICP, etc.). */
201
+ publicKey: string;
202
+ defaultReceivingAddress?: string;
203
+ hasPassword?: boolean;
204
+ }
205
+ interface UseWalletsResult {
206
+ ready: boolean;
207
+ wallets: WalletDescriptor[];
208
+ /** Manual refetch — useful after wallets.create or import. */
209
+ refresh: () => Promise<void>;
210
+ /** Last error from the load, if any. */
211
+ error: Error | undefined;
212
+ }
213
+ declare function useWallets(): UseWalletsResult;
214
+
215
+ /**
216
+ * `useSignMessage()` — signs a UTF-8 message with the user's wallet.
217
+ * EVM applies EIP-191 prefix server-side; Casper raw-signs; other
218
+ * chains follow their conventions. Returns a stable callback that
219
+ * `useState`-loop-friendly forms can wire to a submit handler.
220
+ */
221
+ interface SignMessageInput {
222
+ network: string;
223
+ networkType: 'MAINNET' | 'TESTNET';
224
+ message: string;
225
+ walletIndex?: number;
226
+ /** Wallet password if the user has one. Many partners prompt + pass inline. */
227
+ password?: string;
228
+ }
229
+ interface UseSignMessageResult {
230
+ signMessage: (input: SignMessageInput) => Promise<string>;
231
+ /** True while a signature request is in flight. */
232
+ pending: boolean;
233
+ /** Last error, if any. Cleared on the next attempt. */
234
+ error: Error | undefined;
235
+ }
236
+ declare function useSignMessage(): UseSignMessageResult;
237
+
238
+ /**
239
+ * `useTransfer()` — native + token transfer helpers backed by the
240
+ * partner's proxy. Each variant returns `{ pending, error }` so
241
+ * forms can drive disabled-state without local plumbing.
242
+ */
243
+ interface NativeTransferInput {
244
+ network: string;
245
+ networkType: 'MAINNET' | 'TESTNET';
246
+ /** One or more recipient addresses. */
247
+ recipients: string[];
248
+ /** Amount in the chain's smallest unit (wei / sats / motes / e8s). String / bigint / number. */
249
+ amount: string | bigint | number;
250
+ walletIndex?: number;
251
+ password?: string;
252
+ }
253
+ interface TokenTransferInput {
254
+ network: string;
255
+ networkType: 'MAINNET' | 'TESTNET';
256
+ tokenAddress: string;
257
+ recipient: string;
258
+ amount: string | bigint | number;
259
+ walletIndex?: number;
260
+ password?: string;
261
+ }
262
+ interface UseTransferResult {
263
+ native: (input: NativeTransferInput) => Promise<{
264
+ txHash: string;
265
+ }>;
266
+ token: (input: TokenTransferInput) => Promise<{
267
+ txHash: string;
268
+ }>;
269
+ pending: boolean;
270
+ error: Error | undefined;
271
+ }
272
+ declare function useTransfer(): UseTransferResult;
273
+
274
+ /**
275
+ * `<HorusLoginButton>` — the simplest "drop in and ship" component.
276
+ * Renders a styled button that opens the auth.horuswallet.com popup
277
+ * for the configured flow. Partners that want full UI control build
278
+ * their own button + call `useHorusAuth()` methods directly.
279
+ *
280
+ * <HorusLoginButton flow="google">Continue with Google</HorusLoginButton>
281
+ *
282
+ * Picks up branding + appId from the HorusProvider automatically.
283
+ * Auto-disables itself while the popup is open so a double-click
284
+ * doesn't open a second window.
285
+ */
286
+
287
+ type PopupFlow = 'google' | 'email_link' | 'phone';
288
+ interface HorusLoginButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick' | 'onError'> {
289
+ /** Which flow to open. Defaults to 'google' — the most common one-click signup. */
290
+ flow?: PopupFlow;
291
+ /** Pre-fill for the phone flow. Ignored otherwise. */
292
+ phone?: string;
293
+ /** Called after a successful sign-in. Receives the new user. */
294
+ onAuthenticated?: (user: ReturnType<typeof useHorusAuth>['user']) => void;
295
+ /** Called on user cancel / popup-blocked / auth error. */
296
+ onError?: (err: Error) => void;
297
+ children?: ReactNode;
298
+ }
299
+ declare function HorusLoginButton({ flow, phone, onAuthenticated, onError, children, disabled, style, ...rest }: HorusLoginButtonProps): JSX.Element;
300
+
301
+ /**
302
+ * Fetch wrapper for calls to the partner's backend proxy. Handles
303
+ * the auto-refresh-on-401 dance + JSON serialization + a typed
304
+ * error so consuming hooks can branch on `err.status`.
305
+ */
306
+
307
+ declare class HorusHttpError extends Error {
308
+ readonly status: number;
309
+ readonly code?: string;
310
+ readonly body: unknown;
311
+ constructor(status: number, message: string, body: unknown, code?: string);
312
+ }
313
+
314
+ export { type AuthState, type AuthTokens, type HorusBranding, HorusHttpError, HorusLoginButton, type HorusLoginButtonProps, HorusProvider, type HorusProviderConfig, type HorusProviderProps, type NativeTransferInput, type SignMessageInput, type TokenTransferInput, type UseHorusAuthResult, type User, type WalletDescriptor, useHorusAuth, useSignMessage, useTransfer, useUser, useWallets };