@hfunlabs/hypurr-connect 0.1.9 → 0.1.11

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