@hfunlabs/hypurr-connect 0.1.9 → 0.1.10

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 CHANGED
@@ -45,10 +45,16 @@ import { HypurrConnectProvider } from "@hfunlabs/hypurr-connect";
45
45
 
46
46
  const config = {
47
47
  isTestnet: false,
48
+ grpcUrl: "https://grpc.hypurr.fun",
48
49
  telegram: {
49
- botUsername: "YourBot",
50
- botId: "123456789",
51
- useWidget: true,
50
+ authHubUrl: "https://auth.hypurr.fun/login",
51
+ scope: [
52
+ "telegram:user:read",
53
+ "telegram:wallet:read",
54
+ "telegram:wallet:write",
55
+ "telegram:trade:read",
56
+ "telegram:trade:write",
57
+ ],
52
58
  },
53
59
  };
54
60
 
@@ -112,45 +118,47 @@ function AppShell() {
112
118
 
113
119
  ```typescript
114
120
  interface HypurrConnectConfig {
121
+ grpcUrl?: string; // gRPC-web base URL (default: https://grpc.hypurr.fun)
115
122
  grpcTimeout?: number; // Request timeout in ms (default: 15000)
116
123
  isTestnet?: boolean; // Use testnet endpoints (default: false)
117
124
  telegram: {
118
- botUsername: string; // Telegram bot username (required for the widget)
119
- botId?: string; // Telegram bot ID (required for the popup OAuth flow)
120
- useWidget: boolean; // true = inline Telegram Login Widget, false = popup OAuth
125
+ authHubUrl?: string; // Auth hub URL (default: https://auth.hypurr.fun/login)
126
+ returnTo?: string | (() => string); // Callback URL (default: current page)
127
+ scope?: string | string[]; // Requested JWT scopes
121
128
  };
122
129
  }
123
130
  ```
124
131
 
125
- When `useWidget` is `true`, the login modal renders Telegram's official [Login Widget](https://core.telegram.org/widgets/login) inline — no popup window is opened. This avoids popup-blocker issues and shows users the familiar Telegram button directly inside the modal. The widget requires `botUsername` and that your domain is linked to the bot via `/setdomain` in [@BotFather](https://t.me/botfather).
126
-
127
- When `useWidget` is `false` (or omitted), the popup OAuth flow is used, which requires `botId`.
132
+ The SDK no longer renders Telegram's login widget or opens `oauth.telegram.org`
133
+ directly. Telegram login is delegated to the Hypurr auth hub in a popup, and the
134
+ popup posts the scoped JWT back to the original page.
128
135
 
129
136
  ### Dependencies
130
137
 
131
- This package depends on [`hypurr-grpc`](https://gitlab.com/hypurr/hypurr-grpc) (public GitLab repo) for generated protobuf service clients. It is installed directly from Git — no registry auth is needed.
138
+ This package depends on [`hypurr-grpc`](https://gitlab.com/hypurr/hypurr-grpc)
139
+ for generated protobuf service clients.
132
140
 
133
141
  ## Authentication Flows
134
142
 
135
143
  ### Telegram Login
136
144
 
137
- Two modes are available, controlled by `config.telegram.useWidget`:
138
-
139
- **Widget mode** (`useWidget: true`) — recommended:
140
-
141
- 1. The `LoginModal` renders Telegram's official [Login Widget](https://core.telegram.org/widgets/login) inline
142
- 2. User clicks the widget button and authorizes with Telegram
143
- 3. The widget calls the `onAuth` callback with the user's auth data
144
- 4. The provider calls the Hypurr gRPC backend (`telegramUser`) to fetch the user's wallet address and ID
145
- 5. An `ExchangeClient` is created with `GrpcExchangeTransport` all exchange actions are signed **server-side** by the Hypurr backend
146
- 6. Session is persisted in localStorage (`hypurr-connect-tg-user`)
147
-
148
- **Popup mode** (`useWidget: false`):
149
-
150
- 1. User clicks "Telegram" in the `LoginModal`
151
- 2. A popup opens to `oauth.telegram.org` with the configured bot
152
- 3. User authorizes; Telegram posts auth data back via `postMessage`
153
- 4. Steps 4–6 are identical to widget mode
145
+ 1. User clicks "Telegram" in the `LoginModal`.
146
+ 2. The SDK opens the configured auth hub in a popup with `return_to`, `state`,
147
+ and requested `scope`.
148
+ 3. The auth hub performs Telegram login and redirects back to `return_to` with
149
+ a scoped JWT.
150
+ 4. The popup callback page posts `{ token, state }` to the opener with
151
+ `postMessage` and closes.
152
+ 5. The opener validates `state`, stores the JWT, and calls the Hypurr gRPC
153
+ backend with `Authorization: Bearer <jwt>` metadata.
154
+ 6. An `ExchangeClient` is created with `GrpcExchangeTransport`; exchange
155
+ actions are still signed server-side by the Hypurr backend.
156
+ 7. The JWT session is persisted in localStorage (`hypurr-connect-tg-jwt`).
157
+
158
+ If the popup is blocked, the SDK falls back to a full-page redirect. The
159
+ default `returnTo` is the current page with auth query params removed; custom
160
+ `returnTo` URLs should load the app and mount `HypurrConnectProvider` so the
161
+ popup callback bridge can run.
154
162
 
155
163
  ### EOA Wallet Login
156
164
 
@@ -191,7 +199,12 @@ function ConnectWallet() {
191
199
  // exchange is ready — L1 and user-signed actions both work
192
200
  if (exchange) {
193
201
  // L1 action — agent signs silently (auto-provisioned if needed)
194
- await exchange.order({ orders: [/* ... */], grouping: "na" });
202
+ await exchange.order({
203
+ orders: [
204
+ /* ... */
205
+ ],
206
+ grouping: "na",
207
+ });
195
208
 
196
209
  // User-signed action — wallet popup appears
197
210
  await exchange.usdSend({ destination: "0x...", amount: "100" });
@@ -344,38 +357,40 @@ Returns the full auth and exchange state. Throws if used outside `HypurrConnectP
344
357
 
345
358
  ### `HypurrConnectState`
346
359
 
347
- | Property | Type | Description |
348
- | ------------------ | ------------------------------------------------------------------------- | ---------------------------------------------------------------- |
349
- | `user` | `HypurrUser \| null` | Current authenticated user (reflects selected wallet) |
350
- | `isLoggedIn` | `boolean` | Whether a user is authenticated |
351
- | `isLoading` | `boolean` | Whether auth is in progress |
352
- | `error` | `string \| null` | Last auth or dead-agent error message |
353
- | `authMethod` | `AuthMethod` | `"telegram"`, `"eoa"`, or `null` |
354
- | `exchange` | `ExchangeClient \| null` | Hyperliquid exchange client (L1 + user-signed actions for EOA) |
355
- | `wallets` | `HyperliquidWallet[]` | All wallets for the Telegram user (empty for EOA) |
356
- | `selectedWalletId` | `number` | ID of the currently active wallet |
357
- | `selectWallet` | `(walletId: number) => void` | Switch the active wallet |
358
- | `createWallet` | `(name: string) => Promise<HyperliquidWallet>` | Create a new wallet (Telegram only) |
359
- | `deleteWallet` | `(walletId: number) => Promise<void>` | Delete a wallet (Telegram only) |
360
- | `refreshWallets` | `() => void` | Re-fetch wallets and packs from the server |
361
- | `packs` | `TelegramChatWalletPack[]` | Wallet packs for the Telegram user |
362
- | `createWalletPack` | `(name: string) => Promise<number>` | Create a wallet pack; returns the new pack ID |
363
- | `addPackLabel` | `(params) => Promise<void>` | Add a labeled wallet to a pack |
364
- | `modifyPackLabel` | `(params) => Promise<void>` | Rename a label within a pack |
365
- | `removePackLabel` | `(params) => Promise<void>` | Remove a label from a pack |
366
- | `loginModalOpen` | `boolean` | Whether the login modal is visible |
367
- | `openLoginModal` | `() => void` | Show the login modal |
368
- | `closeLoginModal` | `() => void` | Hide the login modal |
369
- | `connectEoa` | `(address: \`0x\${string}\`, signer?: EoaSigner) => void` | Connect EOA wallet (sync); pass signer to enable user-signed actions and auto-provisioning |
370
- | `approveAgent` | `(signTypedDataAsync: SignTypedDataFn, chainId: number) => Promise<void>` | Approve a named agent key (async, triggers wallet prompt) |
371
- | `logout` | `() => void` | Clear all auth state and localStorage |
372
- | `agent` | `StoredAgent \| null` | Current agent key (EOA flow only) |
373
- | `agentReady` | `boolean` | Whether the exchange client can sign (true for TG, or EOA+agent) |
374
- | `clearAgent` | `() => void` | Remove the agent key from state and storage |
375
- | `botId` | `string` | Telegram bot ID from config |
376
- | `authDataMap` | `Record<string, string>` | Raw Telegram auth data as key-value pairs |
377
- | `telegramClient` | `TelegramClient` | Low-level gRPC client for the Telegram service |
378
- | `staticClient` | `StaticClient` | Low-level gRPC client for the Static service |
360
+ | Property | Type | Description |
361
+ | -------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
362
+ | `user` | `HypurrUser \| null` | Current authenticated user (reflects selected wallet) |
363
+ | `isLoggedIn` | `boolean` | Whether a user is authenticated |
364
+ | `isLoading` | `boolean` | Whether auth is in progress |
365
+ | `error` | `string \| null` | Last auth or dead-agent error message |
366
+ | `authMethod` | `AuthMethod` | `"telegram"`, `"eoa"`, or `null` |
367
+ | `exchange` | `ExchangeClient \| null` | Hyperliquid exchange client (L1 + user-signed actions for EOA) |
368
+ | `wallets` | `HyperliquidWallet[]` | All wallets for the Telegram user (empty for EOA) |
369
+ | `selectedWalletId` | `number` | ID of the currently active wallet |
370
+ | `selectWallet` | `(walletId: number) => void` | Switch the active wallet |
371
+ | `createWallet` | `(name: string) => Promise<HyperliquidWallet>` | Create a new wallet (Telegram only) |
372
+ | `deleteWallet` | `(walletId: number) => Promise<void>` | Delete a wallet (Telegram only) |
373
+ | `refreshWallets` | `() => void` | Re-fetch wallets and packs from the server |
374
+ | `packs` | `TelegramChatWalletPack[]` | Wallet packs for the Telegram user |
375
+ | `createWalletPack` | `(name: string) => Promise<number>` | Create a wallet pack; returns the new pack ID |
376
+ | `addPackLabel` | `(params) => Promise<void>` | Add a labeled wallet to a pack |
377
+ | `modifyPackLabel` | `(params) => Promise<void>` | Rename a label within a pack |
378
+ | `removePackLabel` | `(params) => Promise<void>` | Remove a label from a pack |
379
+ | `loginModalOpen` | `boolean` | Whether the login modal is visible |
380
+ | `openLoginModal` | `() => void` | Show the login modal |
381
+ | `closeLoginModal` | `() => void` | Hide the login modal |
382
+ | `connectEoa` | `(address: \`0x\${string}\`, signer?: EoaSigner) => void` | Connect EOA wallet (sync); pass signer to enable user-signed actions and auto-provisioning |
383
+ | `approveAgent` | `(signTypedDataAsync: SignTypedDataFn, chainId: number) => Promise<void>` | Approve a named agent key (async, triggers wallet prompt) |
384
+ | `logout` | `() => void` | Clear all auth state and localStorage |
385
+ | `agent` | `StoredAgent \| null` | Current agent key (EOA flow only) |
386
+ | `agentReady` | `boolean` | Whether the exchange client can sign (true for TG, or EOA+agent) |
387
+ | `clearAgent` | `() => void` | Remove the agent key from state and storage |
388
+ | `botId` | `string` | Deprecated legacy Telegram bot ID from config |
389
+ | `authDataMap` | `Record<string, string>` | Deprecated; empty when using hub JWT auth |
390
+ | `authToken` | `string \| null` | JWT returned by the auth hub |
391
+ | `telegramRpcOptions` | `RpcOptions \| undefined` | gRPC call options containing `Authorization: Bearer <jwt>` metadata |
392
+ | `telegramClient` | `TelegramClient` | Low-level gRPC client for the Telegram service |
393
+ | `staticClient` | `StaticClient` | Low-level gRPC client for the Static service |
379
394
 
380
395
  ### Types
381
396
 
@@ -504,14 +519,14 @@ class GrpcExchangeTransport implements IRequestTransport {
504
519
  }
505
520
  ```
506
521
 
507
- - **`exchange` endpoint** — Serializes the action to bytes and calls `telegramClient.hyperliquidCoreAction()` via gRPC. The Hypurr backend validates the auth data and signs the action server-side.
522
+ - **`exchange` endpoint** — Serializes the action to bytes and calls `telegramClient.hyperliquidCoreAction()` via gRPC. The Hypurr backend validates the hub JWT and signs the action server-side.
508
523
  - **`info` / `explorer` endpoints** — Proxied directly to the Hyperliquid HTTP API.
509
524
 
510
525
  ```typescript
511
526
  interface GrpcExchangeTransportConfig {
512
527
  isTestnet?: boolean;
513
528
  telegramClient: TelegramClient;
514
- authDataMap: Record<string, string>;
529
+ rpcOptions?: RpcOptions;
515
530
  walletId: number;
516
531
  }
517
532
  ```
@@ -526,13 +541,14 @@ Creates a gRPC-Web client for the Telegram service.
526
541
 
527
542
  Creates a gRPC-Web client for the Static service.
528
543
 
529
- Both use `GrpcWebFetchTransport` with the configured `baseUrl`, `timeout`, and `origin` metadata.
544
+ Both use `GrpcWebFetchTransport` with `config.grpcUrl` as `baseUrl` and
545
+ `config.grpcTimeout` as `timeout`.
530
546
 
531
547
  ## localStorage Keys
532
548
 
533
549
  | Key | Content |
534
550
  | -------------------------------- | -------------------------------------------------------------- |
535
- | `hypurr-connect-tg-user` | Serialized `TelegramLoginData` (persists Telegram session) |
551
+ | `hypurr-connect-tg-jwt` | Hub-issued JWT for Telegram gRPC calls |
536
552
  | `hypurr-connect-agent:{address}` | Serialized `StoredAgent` (persists EOA agent keys per address) |
537
553
 
538
554
  ## Architecture
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import { ExchangeClient, IRequestTransport } from '@hfunlabs/hyperliquid';
4
+ import { RpcOptions } from '@protobuf-ts/runtime-rpc';
4
5
  import { StaticClient } from 'hypurr-grpc/ts/hypurr/static/static_service.client';
5
6
  import { HyperliquidTwapCreateRequest, HyperliquidTwapModifyRequest, HyperliquidScaleCreateRequest } from 'hypurr-grpc/ts/hypurr/telegram/telegram_service';
6
7
  import { TelegramClient } from 'hypurr-grpc/ts/hypurr/telegram/telegram_service.client';
@@ -12,16 +13,28 @@ import { HyperliquidWallet } from 'hypurr-grpc/ts/hypurr/wallet';
12
13
  export { HyperliquidWallet } from 'hypurr-grpc/ts/hypurr/wallet';
13
14
 
14
15
  interface HypurrConnectConfig {
16
+ /** gRPC-web base URL. Defaults to https://grpc.hypurr.fun. */
17
+ grpcUrl?: string;
15
18
  grpcTimeout?: number;
16
19
  isTestnet?: boolean;
17
20
  /** Polling interval in ms for TWAP/Scale session updates. Default 5000. Set 0 to disable. */
18
21
  sessionPollInterval?: number;
19
22
  telegram: {
20
- botUsername: string;
23
+ /** Deprecated for the hub flow; retained for older consumers. */
24
+ botUsername?: string;
25
+ /** Deprecated for the hub flow; retained for older consumers. */
21
26
  botId?: string;
22
- useWidget: boolean;
27
+ /** Deprecated: Telegram login is now handled by the auth hub. */
28
+ useWidget?: boolean;
29
+ /** Auth hub login URL. Defaults to https://auth.hypurr.fun/login. */
30
+ authHubUrl?: string;
31
+ /** Optional callback URL. Defaults to the current page without auth query params. */
32
+ returnTo?: string | (() => string);
33
+ /** Requested hub scopes. Defaults to the scopes required by this SDK. */
34
+ scope?: string | string[];
23
35
  };
24
36
  }
37
+ /** @deprecated Telegram login is handled by the auth hub; raw Telegram data is no longer used by the provider. */
25
38
  interface TelegramLoginData {
26
39
  id: number;
27
40
  first_name: string;
@@ -136,7 +149,10 @@ interface HypurrConnectState {
136
149
  agentReady: boolean;
137
150
  clearAgent: () => void;
138
151
  botId: string;
152
+ /** Deprecated: JWT auth leaves authData empty; use `telegramRpcOptions` for low-level calls. */
139
153
  authDataMap: Record<string, string>;
154
+ authToken: string | null;
155
+ telegramRpcOptions?: RpcOptions;
140
156
  telegramClient: TelegramClient;
141
157
  staticClient: StaticClient;
142
158
  }
@@ -153,20 +169,10 @@ interface LoginModalProps {
153
169
  }
154
170
  declare function LoginModal({ onConnectWallet, walletIcon }: LoginModalProps): react_jsx_runtime.JSX.Element;
155
171
 
156
- interface TelegramLoginWidgetProps {
157
- botUsername: string;
158
- onAuth: (data: TelegramLoginData) => void;
159
- buttonSize?: "large" | "medium" | "small";
160
- cornerRadius?: number;
161
- showUserPhoto?: boolean;
162
- requestAccess?: boolean;
163
- }
164
- declare function TelegramLoginWidget({ botUsername, onAuth, buttonSize, cornerRadius, showUserPhoto, requestAccess, }: TelegramLoginWidgetProps): react_jsx_runtime.JSX.Element;
165
-
166
172
  interface GrpcExchangeTransportConfig {
167
173
  isTestnet?: boolean;
168
174
  telegramClient: TelegramClient;
169
- authDataMap: Record<string, string>;
175
+ rpcOptions?: RpcOptions;
170
176
  walletId: number;
171
177
  onAuthError?: () => void;
172
178
  }
@@ -180,7 +186,7 @@ interface GrpcExchangeTransportConfig {
180
186
  declare class GrpcExchangeTransport implements IRequestTransport {
181
187
  isTestnet: boolean;
182
188
  private telegramClient;
183
- private authDataMap;
189
+ private rpcOptions?;
184
190
  private walletId;
185
191
  private infoUrl;
186
192
  private onAuthError?;
@@ -193,4 +199,4 @@ declare class GrpcExchangeTransport implements IRequestTransport {
193
199
  declare function createTelegramClient(config: HypurrConnectConfig): TelegramClient;
194
200
  declare function createStaticClient(config: HypurrConnectConfig): StaticClient;
195
201
 
196
- export { type AuthMethod, type EoaSigner, GrpcExchangeTransport, type GrpcExchangeTransportConfig, type HypurrConnectConfig, HypurrConnectProvider, type HypurrConnectState, type HypurrUser, LoginModal, type LoginModalProps, type ScaleCreateParams, type SignTypedDataFn, type StoredAgent, type TelegramLoginData, TelegramLoginWidget, type TelegramLoginWidgetProps, type TwapCreateParams, type TwapModifyParams, createEoaSigner, createStaticClient, createTelegramClient, useHypurrConnect };
202
+ export { type AuthMethod, type EoaSigner, GrpcExchangeTransport, type GrpcExchangeTransportConfig, type HypurrConnectConfig, HypurrConnectProvider, type HypurrConnectState, type HypurrUser, LoginModal, type LoginModalProps, type ScaleCreateParams, type SignTypedDataFn, type StoredAgent, type TelegramLoginData, type TwapCreateParams, type TwapModifyParams, createEoaSigner, createStaticClient, createTelegramClient, useHypurrConnect };