@waaskey/react 0.1.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.
@@ -0,0 +1,258 @@
1
+ import { Waaskey, WaaskeyOptions, Chain, Balance, CreateWalletParams, CreateWalletOptions, Wallet, SendParams, SendResult, Signature, EmbeddedSession } from '@waaskey/sdk';
2
+ export * from '@waaskey/sdk';
3
+ import * as react from 'react';
4
+ import { ReactNode, ReactElement } from 'react';
5
+
6
+ /**
7
+ * Design tokens for the Waaskey widget kit (#17). One source for colours, radius and
8
+ * typography so every component (ConnectModal, WalletWidget, SignPrompt, FundWidget) and the
9
+ * React Native package share the same theme. White-label by passing a partial `theme` to the
10
+ * provider; light/dark are both first-class.
11
+ */
12
+ interface WaasTheme {
13
+ /** Primary action / brand colour. */
14
+ accent: string;
15
+ /** Foreground on the accent (button text). */
16
+ accentForeground: string;
17
+ /** Surface/background. */
18
+ background: string;
19
+ /** Primary text. */
20
+ foreground: string;
21
+ /** Secondary/subtle text. */
22
+ muted: string;
23
+ /** Borders / dividers. */
24
+ border: string;
25
+ /** Error text. */
26
+ danger: string;
27
+ /** Corner radius (CSS length on web). */
28
+ radius: string;
29
+ /** Base font family. */
30
+ fontFamily: string;
31
+ }
32
+ declare const lightTheme: WaasTheme;
33
+ declare const darkTheme: WaasTheme;
34
+ declare const defaultTheme: WaasTheme;
35
+ /** Merge a partial override onto a base theme (white-label). */
36
+ declare function resolveTheme(override?: Partial<WaasTheme>, base?: WaasTheme): WaasTheme;
37
+
38
+ /** Provide either a ready {@link Waaskey} client or the options to construct one, plus an optional theme. */
39
+ type WaaskeyProviderProps = ({
40
+ client: Waaskey;
41
+ } | {
42
+ options: WaaskeyOptions;
43
+ }) & {
44
+ /** Partial theme override (white-label) merged onto the default light theme. */
45
+ theme?: Partial<WaasTheme>;
46
+ children?: ReactNode;
47
+ };
48
+ /**
49
+ * Makes a {@link Waaskey} client (and the kit {@link WaasTheme}) available to the hooks and
50
+ * components (`useWaaskey`/`useWaas`, `useTheme`, `<ConnectModal>`, `<WalletWidget>`, …).
51
+ * Pass a `client` you built, or `options` to construct one (memoized). SSR-safe (no browser
52
+ * APIs at construction). Written with `createElement` so the package needs no JSX build step.
53
+ */
54
+ declare function WaaskeyProvider(props: WaaskeyProviderProps): ReactElement;
55
+ /** Ergonomic alias of {@link WaaskeyProvider} — the documented kit entry point (`<WaasProvider>`). */
56
+ declare const WaasProvider: typeof WaaskeyProvider;
57
+ type WaasProviderProps = WaaskeyProviderProps;
58
+
59
+ /** React context holding the configured {@link Waaskey} client. Provided by {@link WaaskeyProvider}. */
60
+ declare const WaaskeyContext: react.Context<Waaskey | null>;
61
+
62
+ /** Theme made available by {@link WaaskeyProvider} / `WaasProvider`. Defaults to the light theme. */
63
+ declare const ThemeContext: react.Context<WaasTheme>;
64
+ /** The active {@link WaasTheme} from context (falls back to the default light theme). */
65
+ declare function useTheme(): WaasTheme;
66
+
67
+ /** Loading/error/data triple for an async read — render all three states. */
68
+ interface AsyncState<T> {
69
+ data?: T;
70
+ error?: Error;
71
+ loading: boolean;
72
+ }
73
+ /** The {@link Waaskey} client from context. Throws if used outside {@link WaaskeyProvider}. */
74
+ declare function useWaaskey(): Waaskey;
75
+ /**
76
+ * The unified kit surface (#12): the {@link Waaskey} client + active theme, plus the `auth`
77
+ * resource for convenience. Sugar over `useWaaskey()` + `useTheme()` for the Privy-style DX.
78
+ */
79
+ declare function useWaas(): {
80
+ client: Waaskey;
81
+ theme: WaasTheme;
82
+ auth: Waaskey['auth'];
83
+ };
84
+ /** Imperatively create a wallet (non-custodial keygen). Returns the action + its async state. */
85
+ declare function useCreateWallet(): {
86
+ create: (params: CreateWalletParams, options?: CreateWalletOptions) => Promise<Wallet>;
87
+ wallet?: Wallet;
88
+ error?: Error;
89
+ isPending: boolean;
90
+ };
91
+ /** Load a wallet by id (re-fetches when `id` changes); exposes `refresh`. */
92
+ declare function useWallet(id: string | undefined): AsyncState<Wallet> & {
93
+ refresh: () => Promise<void>;
94
+ };
95
+ /** Read an address's native balance on a chain, client-side (no backend); exposes `refresh`. */
96
+ declare function useBalance(chain: Chain | undefined, address: string | undefined): AsyncState<Balance> & {
97
+ refresh: () => Promise<void>;
98
+ };
99
+ /** Read an address's native balance across several chains at once; exposes `refresh`. */
100
+ declare function useBalances(chains: Chain[], address: string | undefined): AsyncState<Balance[]> & {
101
+ refresh: () => Promise<void>;
102
+ };
103
+ /** Status of a {@link useSend} action. */
104
+ type SendStatus = 'idle' | 'pending' | 'sent' | 'error';
105
+ /**
106
+ * Imperatively send a transaction from a wallet, exposing an optimistic status
107
+ * (`idle → pending → sent | error`) the UI renders. The platform co-signs (MPC) and returns
108
+ * the **signed raw tx** (`result.signedTx`) — WaaS never broadcasts; the client submits it
109
+ * (e.g. `waaskey.broadcast(result.signedTx, { rpcUrl })` or your own node).
110
+ */
111
+ declare function useSend(walletId: string | undefined): {
112
+ send: (params: SendParams) => Promise<SendResult>;
113
+ status: SendStatus;
114
+ result?: SendResult;
115
+ error?: Error;
116
+ reset: () => void;
117
+ };
118
+ /** Load a wallet's signing activity (newest first) — raw signs and send/sweep signed txs; exposes `refresh`. */
119
+ declare function useSignatures(walletId: string | undefined): AsyncState<Signature[]> & {
120
+ refresh: () => Promise<void>;
121
+ };
122
+
123
+ /** Step of the email-OTP login flow. */
124
+ type LoginStep = 'email' | 'code' | 'done';
125
+ interface UseLogin {
126
+ step: LoginStep;
127
+ /** The email entered at the first step. */
128
+ email: string;
129
+ /** The session once login completes. */
130
+ session?: EmbeddedSession;
131
+ loading: boolean;
132
+ error?: Error;
133
+ /** Send a one-time code to `email` (→ `code` step). */
134
+ start: (email: string) => Promise<void>;
135
+ /** Verify the code (→ `done` step on success). */
136
+ verify: (code: string) => Promise<void>;
137
+ /** Back to the email step (clears error). */
138
+ reset: () => void;
139
+ }
140
+ /**
141
+ * Headless email-OTP login (#6/#13): drives `waaskey.auth.email.start` → `.verify`,
142
+ * tracking `step`/`loading`/`error` so a UI (e.g. `<ConnectModal>`) — or a custom one —
143
+ * can render all states. The established session is also held on `waaskey.auth`.
144
+ */
145
+ declare function useLogin(): UseLogin;
146
+
147
+ /**
148
+ * Render `text` to a QR-code data URL using `qrcode` (an optional peer dependency, lazy-loaded).
149
+ * Returns `undefined` until ready, or when `qrcode` isn't installed — callers should always also
150
+ * show the raw text (address) so receive works without the dependency.
151
+ */
152
+ declare function useQrCode(text: string | undefined): string | undefined;
153
+
154
+ /** Per-instance theme override for {@link ConnectModal} (merged onto the provider theme). */
155
+ type ConnectModalTheme = Partial<WaasTheme>;
156
+ interface ConnectModalProps {
157
+ /** Whether the modal is shown. */
158
+ open: boolean;
159
+ /** Close requested (backdrop / ✕ / after connect). */
160
+ onClose: () => void;
161
+ /** Called with the session once login completes. */
162
+ onConnect?: (session: EmbeddedSession) => void;
163
+ /** Heading copy. */
164
+ title?: string;
165
+ theme?: ConnectModalTheme;
166
+ }
167
+ /**
168
+ * Drop-in email-OTP login modal (#13). Runs `useLogin` (→ `waaskey.auth`), rendering the
169
+ * email → code → done steps with loading/error states; calls `onConnect` with the session.
170
+ * Themeable via inline tokens, accessible (labelled dialog, focus, Esc to close); written
171
+ * with `createElement` so the package needs no JSX build step.
172
+ */
173
+ declare function ConnectModal({ open, onClose, onConnect, title, theme }: ConnectModalProps): ReactElement | null;
174
+
175
+ /** Per-instance theme override for {@link WalletWidget} (merged onto the provider theme). */
176
+ type WalletWidgetTheme = Partial<WaasTheme>;
177
+ interface WalletWidgetProps {
178
+ /** Waaskey wallet id to render. */
179
+ walletId: string;
180
+ /** Chains to show native balances for (e.g. `['ethereum', 'base']`). */
181
+ chains: Chain[];
182
+ /** Backend chain id the Send tab submits to (e.g. `'evm:11155111'`). Defaults to `'evm:1'`. */
183
+ sendChainId?: string;
184
+ /** Decimals used to parse the human send amount into base units. Defaults to 18 (EVM native). */
185
+ sendDecimals?: number;
186
+ /** Called after a successful send. */
187
+ onSent?: (result: SendResult) => void;
188
+ theme?: WalletWidgetTheme;
189
+ }
190
+ /**
191
+ * Drop-in embedded-wallet panel (#14): balances/assets, receive (address + QR), send
192
+ * (amount + address with optimistic pending/sent/failed states), and activity (tx history).
193
+ * Built on the headless hooks (`useBalances`/`useSend`/`useSignatures`) — use those directly
194
+ * for a custom UI. `createElement`-only, so the package needs no JSX build step.
195
+ */
196
+ declare function WalletWidget({ walletId, chains, sendChainId, sendDecimals, onSent, theme }: WalletWidgetProps): ReactElement;
197
+
198
+ /** A signature/approval request the app raises for the user to confirm. */
199
+ type SignRequest = {
200
+ kind: 'sign';
201
+ walletId: string;
202
+ digest: string;
203
+ title?: string;
204
+ } | {
205
+ kind: 'send';
206
+ walletId: string;
207
+ tx: SendParams;
208
+ title?: string;
209
+ };
210
+ /** What a confirmed request resolves to — a signature hex (`sign`) or the broadcast result (`send`). */
211
+ type SignOutcome = string | SendResult;
212
+ /**
213
+ * Promise-based signing/approval prompt (#15) — the Privy "confirm transaction" modal.
214
+ *
215
+ * `requestSignature(req)` opens the prompt and resolves when the user approves (after the MPC
216
+ * sign/broadcast completes), or rejects when they cancel. Render the returned `prompt` element
217
+ * once near the app root. The approval drives the real action over the relay; an error is
218
+ * recoverable (retry/cancel), never an indefinite spinner.
219
+ */
220
+ declare function useSignPrompt(): {
221
+ requestSignature: (req: SignRequest) => Promise<SignOutcome>;
222
+ prompt: ReactElement | null;
223
+ };
224
+ interface SignPromptProps {
225
+ request: SignRequest;
226
+ status: 'idle' | 'pending' | 'error';
227
+ error?: Error;
228
+ onApprove: () => void;
229
+ onReject: () => void;
230
+ }
231
+ /** The approval modal UI (used by {@link useSignPrompt}; exported for fully custom wiring). */
232
+ declare function SignPrompt({ request, status, error, onApprove, onReject }: SignPromptProps): ReactElement;
233
+
234
+ interface FundWidgetProps {
235
+ /** Wallet address the purchased crypto is delivered to. */
236
+ walletAddress: string;
237
+ /** Chain id, e.g. `evm:1`. */
238
+ chainId: string;
239
+ /** Crypto to buy. Defaults to `ETH`. */
240
+ cryptoCurrency?: string;
241
+ /** Fiat to pay with. */
242
+ fiatCurrency?: string;
243
+ /** Pre-fill the fiat amount. */
244
+ fiatAmount?: number;
245
+ /** Button copy. */
246
+ label?: string;
247
+ /** Called after the user returns from the on-ramp — a good place to refresh the balance. */
248
+ onComplete?: () => void;
249
+ }
250
+ /**
251
+ * Drop-in funding widget (#16) — buy crypto into the embedded wallet via a provider on-ramp
252
+ * (Transak, …). Fetches a provider widget URL from the API and opens it; on return the user
253
+ * confirms, firing `onComplete` so the host can refresh the balance. Themeable; the underlying
254
+ * `waaskey.onramp.widgetUrl(...)` works on web + React Native (only the open step is platform UI).
255
+ */
256
+ declare function FundWidget({ walletAddress, chainId, cryptoCurrency, fiatCurrency, fiatAmount, label, onComplete }: FundWidgetProps): ReactElement;
257
+
258
+ export { type AsyncState, ConnectModal, type ConnectModalProps, type ConnectModalTheme, FundWidget, type FundWidgetProps, type LoginStep, type SendStatus, type SignOutcome, SignPrompt, type SignPromptProps, type SignRequest, ThemeContext, type UseLogin, WaasProvider, type WaasProviderProps, type WaasTheme, WaaskeyContext, WaaskeyProvider, type WaaskeyProviderProps, WalletWidget, type WalletWidgetProps, type WalletWidgetTheme, darkTheme, defaultTheme, lightTheme, resolveTheme, useBalance, useBalances, useCreateWallet, useLogin, useQrCode, useSend, useSignPrompt, useSignatures, useTheme, useWaas, useWaaskey, useWallet };