@tuwaio/quasar-sdk 0.1.11 → 0.2.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.
package/README.md CHANGED
@@ -1,509 +1,102 @@
1
1
  # @tuwaio/quasar-sdk
2
2
 
3
3
  [![NPM Version](https://img.shields.io/npm/v/@tuwaio/quasar-sdk.svg)](https://www.npmjs.com/package/@tuwaio/quasar-sdk)
4
- [![License](https://img.shields.io/npm/l/@tuwaio/quasar-sdk.svg)](./LICENSE)
4
+ [![License](https://img.shields.io/npm/l/@tuwaio/quasar-sdk.svg)](https://github.com/TuwaIO/sdk/blob/main/packages/quasar-sdk/LICENSE)
5
5
 
6
- <p align="center">
7
- <img src="https://cdn.jsdelivr.net/gh/TuwaIO/workflows@main/preview/repos/quasar_sdk.png" alt="Quasar SDK Architecture" width="100%" />
8
- </p>
9
-
10
- > The official **Layer 5 (L5)** server-side Node.js & Edge SDK for the **TUWA Quasar Cloud**.
11
-
12
- ---
13
-
14
- ## 🏛️ What is `@tuwaio/quasar-sdk`?
15
-
16
- `@tuwaio/quasar-sdk` is **Layer 5 (L5)** of the TUWA ecosystem architecture — the official backend companion to the TUWA client libraries. It serves as the gateway to the **Quasar Cloud Engine**, allowing your server to securely push transaction logs, query paginated transaction histories, and sync infrastructure states.
17
-
18
- It operates strictly on the server (Node.js, Next.js Server Actions, or Edge functions) and uses Secret Keys to communicate with Quasar's iron-dome guarded endpoints.
6
+ `@tuwaio/quasar-sdk` is the Layer 5 (L5) package of the **TUWA SDK**: the client of the API of **Quasar**, the TUWA backend that tracks the transactions of your app on the server and keeps their history. It works with Quasar Cloud (`https://api.tuwa.io`) and with a self-hosted Quasar server. It has three parts: the `Quasar` client for your server, a check for the browser (`@tuwaio/quasar-sdk/react`), and the `quasar-sdk` CLI that relays webhooks to `localhost`.
19
7
 
20
8
  ---
21
9
 
22
- ## ✨ Key Features
10
+ ## 🏛️ Core Capabilities
23
11
 
24
- - **☁️ Cloud Sync**: Automatically persist pending and terminal transaction states to the Quasar Database for cross-device history.
25
- - **⚡ Native Webhook Local Dev Relay**: Stream production webhooks directly to your local machine via CLI with zero tunnels (no ngrok/cloudflared required).
26
- - **🔐 Headless SIWX (CAIP-122) Auth Ready**: Seamlessly pairs with `@tuwaio/sdk/siwx/server` for strict cryptographic verification of user sessions before allowing database writes.
27
- - **⚡ Edge Ready**: Uses `ofetch` and lightweight cryptography to run seamlessly in Cloudflare Workers and Vercel Edge.
28
- - **📦 InMemory Sync**: Perfectly pairs with `@tuwaio/sdk/pulsar` (`createTxInMemoryStore`) to fetch history and hydrate local React states.
12
+ - **Transaction sync:** `quasar.pulsar.syncCreate` sends a transaction created by Pulsar to Quasar, which tracks it until it reaches a final status (so the status survives a closed tab) and sends your webhooks.
13
+ - **History:** `quasar.pulsar.getHistory` returns the transactions of your app, newest first, filtered by wallet address, chain, status, transaction key or application name.
14
+ - **Errors:** every failed request throws a `QuasarSDKError` with the HTTP `status`.
15
+ - **Pre-flight check:** `preFlightTxCheck` from `@tuwaio/quasar-sdk/react` stops a Pulsar transaction in the browser when the user is not signed in with SIWX or the Quasar API does not respond.
16
+ - **Webhook relay:** `npx @tuwaio/quasar-sdk listen` receives the deliveries of a webhook endpoint with a `localhost` URL and posts them to your local app, without a tunnel.
29
17
 
30
18
  ---
31
19
 
32
20
  ## 💾 Installation
33
21
 
34
22
  ```bash
35
- pnpm add @tuwaio/quasar-sdk ofetch @tuwaio/pulsar-core @tuwaio/siwx-core @tuwaio/siwx-server @tuwaio/siwx-react
36
- ```
37
-
38
- _Note: `ofetch` and `@tuwaio/pulsar-core` are required peer dependencies. The `@tuwaio/siwx-*` packages are required if you intend to use the headless SIWX (CAIP-122) authentication integrations._
39
-
40
- ---
41
-
42
- ## ⚡ Quasar Webhook Local Dev Relay (Native CLI)
43
-
44
- Testing Web3 webhooks locally against live cloud indexers usually requires spinning up temporary third-party tunnels (`ngrok`, `cloudflared`), pasting ephemeral URLs into dashboard forms, and restarting your workflow when tunnels expire.
45
-
46
- The **Quasar SDK CLI** provides a zero-tunnel local development relay. When you configure a `localhost` webhook endpoint in the Quasar Dashboard, Quasar Cloud streams incoming events to your local machine via real-time Server-Sent Events (SSE).
47
-
48
- ### 1. Zero-Config Local Development
49
-
50
- Add your webhook signing secret from the Quasar Dashboard to `.env.local` or `.env`:
51
-
52
- ```env
53
- # Signing secret copied from the Quasar Dashboard webhook endpoint
54
- QUASAR_WEBHOOK_SECRET=whsec_...
55
-
56
- # Optional Quasar API base URL (defaults to https://api.tuwa.io)
57
- NEXT_PUBLIC_QUASAR_BASE_URL=https://api.tuwa.io
23
+ pnpm add @tuwaio/quasar-sdk @tuwaio/pulsar-core
58
24
  ```
59
25
 
60
- Run the relay listener in your terminal:
61
-
62
- ```bash
63
- npx @tuwaio/quasar-sdk listen
64
- ```
26
+ | Import path | Provides | Peer dependencies |
27
+ | -------------------------- | ---------------------------------------------------------------------------- | -------------------------------------------------------- |
28
+ | `@tuwaio/quasar-sdk` | `Quasar`, `PulsarModule`, `QuasarSDKError`, the endpoint constants and types | `@tuwaio/pulsar-core` (>=0.7), for the transaction types |
29
+ | `@tuwaio/quasar-sdk/react` | `preFlightTxCheck` | Also `@tuwaio/siwx-react` (>=0.3, optional for the root) |
65
30
 
66
- The CLI automatically reads `QUASAR_WEBHOOK_SECRET` and starts forwarding webhook payloads to the default Cosmos Playground endpoint (`http://localhost:3000/api/webhooks/quasar`).
67
-
68
- ### 2. Custom Forwarding & CLI Options
69
-
70
- ```bash
71
- # Forward to a custom port or path
72
- npx @tuwaio/quasar-sdk listen --forward-to http://localhost:8080/api/webhooks
73
-
74
- # Provide secret explicitly via flags
75
- npx @tuwaio/quasar-sdk listen --secret whsec_... --forward-to http://localhost:3000/api/webhooks/quasar
76
-
77
- # Specify custom .env file
78
- npx @tuwaio/quasar-sdk listen --env-file .env.development
79
- ```
80
-
81
- | Flag | Shorthand | Description | Default |
82
- | :------------- | :-------- | :-------------------------------------------- | :------------------------------------------ |
83
- | `--secret` | `-s` | Webhook endpoint signing secret (`whsec_...`) | `QUASAR_WEBHOOK_SECRET` |
84
- | `--forward-to` | `-f` | Local destination endpoint | `http://localhost:3000/api/webhooks/quasar` |
85
- | `--api-url` | `-a` | Quasar Cloud API base URL | `https://api.tuwa.io` |
86
- | `--env-file` | `-e` | Custom path to `.env` file | Auto-detected (`.env.local`, `.env`) |
87
- | `--help` | `-h` | Display help instructions | — |
88
- | `--version` | `-v` | Display CLI version | — |
89
-
90
- ### 3. Local Webhook Route Handler (Next.js Example)
91
-
92
- ```typescript
93
- // app/api/webhooks/quasar/route.ts
94
- import { NextResponse } from 'next/server';
95
- import crypto from 'node:crypto';
96
-
97
- export async function POST(req: Request) {
98
- const secret = process.env.QUASAR_WEBHOOK_SECRET;
99
- if (!secret) {
100
- return NextResponse.json({ error: 'Server misconfigured' }, { status: 500 });
101
- }
102
-
103
- const rawBody = await req.text();
104
- const signature = req.headers.get('x-quasar-signature');
105
- const event = req.headers.get('x-quasar-event');
106
-
107
- // Verify HMAC-SHA256 signature
108
- const expectedSignature = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
109
-
110
- if (signature !== expectedSignature) {
111
- return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
112
- }
113
-
114
- const payload = JSON.parse(rawBody);
115
- console.log(`[Webhook Received] ${event}:`, payload);
116
-
117
- return NextResponse.json({ received: true });
118
- }
119
- ```
31
+ The root entry point imports neither React nor SIWX packages, so it runs in Node.js, Next.js Server Actions and route handlers, and Edge runtimes. Its HTTP client, `ofetch`, is a dependency.
120
32
 
121
33
  ---
122
34
 
123
- ## 🚀 Quick Start (Node.js / Edge)
35
+ ## 🚀 Usage
124
36
 
125
- This is a basic example of how to interact with the Quasar Cloud directly from your secure backend environments (like Next.js API Routes, Server Actions, or NestJS).
37
+ Create the client on the server with the secret key of your Quasar app (`sk_live_...` or `sk_test_...`, from the dashboard). Never create it in the browser: the key authorizes writes to your app.
38
+
39
+ ```ts
40
+ 'use server';
126
41
 
127
- ```typescript
128
- import { cookies } from 'next/headers';
129
42
  import { Quasar, type Transaction } from '@tuwaio/quasar-sdk';
130
- import { isSessionMatchingTarget } from '@tuwaio/sdk/siwx';
131
- import { getSiwxServerSession } from '@tuwaio/sdk/siwx/server';
132
- import { sessionStore } from '@/lib/authStores';
133
43
 
134
- // Initialize Quasar with your Secret Key from the Dashboard
135
- const quasar = new Quasar({ secretKey: process.env.QUASAR_SDK_SK ?? '' });
44
+ const quasar = new Quasar({ secretKey: process.env.QUASAR_SECRET_KEY ?? '' });
136
45
 
137
- /**
138
- * Example Next.js Server Action to Sync a Transaction
139
- */
140
46
  export async function syncTransaction(tx: Transaction) {
141
- const session = await getSiwxServerSession({
142
- cookieSource: await cookies(),
143
- sessionStore,
144
- });
145
- if (!session) throw new Error('Unauthorized: No active session.');
146
-
147
- // Verify that the transaction sender matches the authenticated session address
148
- if (tx.from && !isSessionMatchingTarget(session, tx.from, tx.chainId)) {
149
- throw new Error('Forbidden: Session address mismatch.');
150
- }
151
-
152
- // Sync the transaction securely to the Quasar Cloud
153
- await quasar.pulsar.syncCreate(tx, 'My Application');
154
- return { success: true };
47
+ const { txKey } = await quasar.pulsar.syncCreate(tx, 'my-app');
48
+ return txKey;
155
49
  }
156
50
 
157
- /**
158
- * Example Next.js Server Action to Fetch History
159
- */
160
- export async function getHistory(params: {
161
- walletAddress: string;
162
- page?: number;
163
- limit?: number;
164
- appName?: string;
165
- chainId?: string;
166
- }) {
167
- const session = await getSiwxServerSession({
168
- cookieSource: await cookies(),
169
- sessionStore,
170
- });
171
- if (!session || !isSessionMatchingTarget(session, params.walletAddress, params.chainId)) {
172
- throw new Error('Unauthorized: Session address mismatch.');
173
- }
174
-
175
- // Return the paginated transaction history
176
- return quasar.pulsar.getHistory(params);
51
+ export async function getHistory(walletAddress: string, page = 1) {
52
+ return quasar.pulsar.getHistory({ walletAddress, page, limit: 10, appName: 'my-app' });
177
53
  }
178
54
  ```
179
55
 
180
- ---
181
-
182
- ## 🔐 Frontend Authentication (SIWX)
183
-
184
- The Quasar SDK relies on the standard **SIWX (CAIP-122)** protocol for authenticating client requests.
185
-
186
- You can use the headless `<NovaSiwxWatcher />` component or `useSiwx` / `useSiwxSession` hooks provided by `@tuwaio/sdk/siwx` (and `@tuwaio/sdk/nova-connect`). The auto-auth watcher automatically prompts users to sign a CAIP-122 message when they connect their wallet and synchronizes active session state.
187
-
188
- For detailed frontend integration, see the [SIWX Documentation](https://siwx.docs.tuwa.io/).
189
-
190
- ---
191
-
192
- ## 🌍 The Full Flow (Production Architecture)
193
-
194
- To see how incredibly powerful `@tuwaio/quasar-sdk` is when combined with `@tuwaio/sdk`, here is a complete architectural overview without any skipped steps. Notice how the **Pulsar Store** and **Headless SIWX** dance together effortlessly:
195
-
196
- ### 1. Define Your Transaction Types (`types.ts`)
197
-
198
- First, define the strict union of all possible transactions your app supports.
199
-
200
- ```ts
201
- // src/types.ts
202
- import type { Transaction } from '@tuwaio/sdk/pulsar';
203
-
204
- export enum AppTxType {
205
- SWAP = 'SWAP',
206
- }
207
-
208
- export type SwapTx = Transaction & {
209
- type: AppTxType.SWAP;
210
- payload: { tokenIn: string; tokenOut: string; amount: number };
211
- };
212
-
213
- export type TransactionUnion = SwapTx;
214
- ```
215
-
216
- ### 2. Secure Server Proxy (`actions.ts`)
217
-
218
- Proxy calls to Quasar Cloud using your backend to protect secret keys. Never accept client-side session credentials in Server Actions.
219
-
220
- ```ts
221
- // src/app/actions.ts
222
- 'use server';
56
+ Before calling Quasar for a user, check on the server that the user owns the wallet (for example with `getSiwxServerSession` and `isSessionMatchingTarget` from `@tuwaio/siwx-server`), so nobody can sync or read the transactions of another address. The complete flow — SIWX sessions, the Pulsar callbacks `onRemoteCreate` and `beforeTxProcess`, the history in Nova Transactions — is the **[Quasar transaction sync guide](https://docs.tuwa.io/guides/quasar-transaction-sync)**; Quasar itself (apps and keys, quotas, webhooks, self-hosting) is described in the **[Quasar docs](https://docs.tuwa.io/quasar)**.
223
57
 
224
- import { cookies } from 'next/headers';
225
- import { Quasar } from '@tuwaio/quasar-sdk';
226
- import { isSessionMatchingTarget } from '@tuwaio/sdk/siwx';
227
- import { getSiwxServerSession } from '@tuwaio/sdk/siwx/server';
228
- import { sessionStore } from '@/lib/authStores';
229
- import { TransactionUnion } from '@/types';
230
-
231
- const quasar = new Quasar({ secretKey: process.env.QUASAR_SDK_SK ?? '' });
232
-
233
- export async function syncTransaction(tx: TransactionUnion) {
234
- const session = await getSiwxServerSession({
235
- cookieSource: await cookies(),
236
- sessionStore,
237
- });
238
- if (!session) throw new Error('Unauthorized: No active session.');
239
- if (tx.from && !isSessionMatchingTarget(session, tx.from, tx.chainId)) {
240
- throw new Error('Forbidden: Session address mismatch.');
241
- }
242
-
243
- await quasar.pulsar.syncCreate(tx, 'My App');
244
- return { success: true };
245
- }
58
+ ### Webhook relay
246
59
 
247
- export async function getHistory(params: {
248
- walletAddress: string;
249
- page?: number;
250
- limit?: number;
251
- appName?: string;
252
- chainId?: string;
253
- }) {
254
- const session = await getSiwxServerSession({
255
- cookieSource: await cookies(),
256
- sessionStore,
257
- });
258
- if (!session || !isSessionMatchingTarget(session, params.walletAddress, params.chainId)) {
259
- throw new Error('Unauthorized: Session address mismatch.');
260
- }
261
-
262
- return quasar.pulsar.getHistory(params);
263
- }
264
- ```
60
+ Add a webhook endpoint with a `localhost` URL in the Quasar dashboard, put its signing secret in `.env.local` and start the relay next to your dev server:
265
61
 
266
- ```ts
267
- // src/hooks/usePulsarStore.ts
268
- 'use client';
269
-
270
- import { createPulsarStore, createTxInMemoryStore, createBoundedUseStore } from '@tuwaio/sdk/pulsar';
271
- import { pulsarEvmAdapter } from '@tuwaio/evm-sdk/pulsar';
272
- import { pulsarSolanaAdapter } from '@tuwaio/solana-sdk/pulsar';
273
- import { preFlightTxCheck } from '@tuwaio/quasar-sdk';
274
-
275
- import { getHistory, syncTransaction } from '@/app/actions';
276
- import { wagmiConfig, appEVMChains, solanaRPCUrls } from '@/configs/appConfig';
277
- import { TransactionUnion } from '@/types';
278
-
279
- const storageName = 'transactions-tracking-storage';
280
-
281
- const initialStore = createPulsarStore<TransactionUnion>({
282
- name: storageName,
283
- adapter: [pulsarEvmAdapter(wagmiConfig, appEVMChains), pulsarSolanaAdapter({ rpcUrls: solanaRPCUrls })],
284
- beforeTxProcess: async () => {
285
- // Ensures we have a valid SIWX session and Quasar Cloud is reachable before executing blockchain logic
286
- await preFlightTxCheck();
287
- },
288
- onRemoteCreate: async (tx) => {
289
- try {
290
- // Syncs the new transaction to Quasar via Next.js Server Actions
291
- await syncTransaction(tx as TransactionUnion);
292
- } catch (err) {
293
- console.error('[PulsarHook] Remote sync failed:', err);
294
- }
295
- },
296
- });
297
-
298
- export const usePulsarStore = createBoundedUseStore(initialStore);
299
-
300
- // Wrap with inMemoryStore to enable remote history fetching & pagination
301
- const pulsarInMemoryStore = createTxInMemoryStore<TransactionUnion>({
302
- localTransactionsPool: initialStore.getState().transactionsPool,
303
- getHistory: async ({ page, walletAddress }) => {
304
- try {
305
- const history = await getHistory({ walletAddress, page, limit: 10, appName: 'My App' });
306
-
307
- if (!history) return null;
308
-
309
- return { ...history, docs: history.docs as TransactionUnion[] };
310
- } catch (error) {
311
- console.error('[PulsarHook] Failed to fetch history:', error);
312
- throw error;
313
- }
314
- },
315
- onHistoryFetched: async (remoteTxs) => {
316
- await initialStore.getState().injectExternalPendingTxs(remoteTxs);
317
- },
318
- });
319
-
320
- initialStore.subscribe((state) => pulsarInMemoryStore.getState().syncWithLocalPool(state.transactionsPool));
321
-
322
- export const usePulsarInMemoryStore = createBoundedUseStore(pulsarInMemoryStore);
323
- ```
324
-
325
- ### 4. Nova Transactions Provider (`NovaTransactionsProvider.tsx`)
326
-
327
- ```tsx
328
- // src/providers/NovaTransactionsProvider.tsx
329
- 'use client';
330
-
331
- import { useSatelliteConnectStore } from '@tuwaio/sdk/satellite';
332
- import { useInitializeTransactionsPool, type TxInMemoryPagination } from '@tuwaio/sdk/pulsar';
333
- import { getAdapterFromConnectorType } from '@tuwaio/sdk/orbit';
334
- import { NovaTransactionsProvider as NTP } from '@tuwaio/sdk/nova-transactions/providers';
335
- import { usePulsarInMemoryStore, usePulsarStore } from '@/hooks/usePulsarStore';
336
-
337
- export function NovaTransactionsProvider({ pagination }: { pagination: TxInMemoryPagination }) {
338
- const initialTx = usePulsarStore((state) => state.initialTx);
339
- const closeTxTrackedModal = usePulsarStore((state) => state.closeTxTrackedModal);
340
- const executeTxAction = usePulsarStore((state) => state.executeTxAction);
341
- const initializeTransactionsPool = usePulsarStore((state) => state.initializeTransactionsPool);
342
-
343
- const activeConnection = useSatelliteConnectStore((state) => state.activeConnection);
344
- const getAdapter = usePulsarStore((state) => state.getAdapter);
345
- const transactionsPool = usePulsarInMemoryStore((state) => state.transactionsPool);
346
-
347
- useInitializeTransactionsPool({ initializeTransactionsPool });
348
-
349
- return (
350
- <NTP
351
- transactionsPool={transactionsPool}
352
- initialTx={initialTx}
353
- closeTxTrackedModal={closeTxTrackedModal}
354
- executeTxAction={executeTxAction}
355
- connectedWalletAddress={activeConnection?.isConnected ? activeConnection.address : undefined}
356
- connectedAdapterType={getAdapterFromConnectorType(activeConnection?.connectorType ?? 'evm:')}
357
- adapter={getAdapter()}
358
- pagination={pagination}
359
- />
360
- );
361
- }
62
+ ```bash
63
+ # .env.local: QUASAR_WEBHOOK_SECRET=whsec_...
64
+ npx @tuwaio/quasar-sdk listen --forward-to http://localhost:3000/api/webhooks/quasar
362
65
  ```
363
66
 
364
- ### 5. The Seamless UI Integration (`AppProviders.tsx`)
365
-
366
- ```tsx
367
- // src/providers/AppProviders.tsx
368
- 'use client';
369
-
370
- import { SatelliteConnectProvider, useSatelliteConnection } from '@tuwaio/sdk/satellite';
371
- import { NovaConnectProvider } from '@tuwaio/sdk/nova-connect';
372
- import { satelliteEVMAdapter } from '@tuwaio/evm-sdk/satellite';
373
- import { EVMConnectorsWatcher } from '@tuwaio/evm-sdk/nova-connect';
374
- import { satelliteSolanaAdapter } from '@tuwaio/solana-sdk/satellite';
375
- import { SolanaConnectorsWatcher } from '@tuwaio/solana-sdk/nova-connect';
376
- import { useSiwx, useSiwxSession } from '@tuwaio/sdk/siwx';
377
- import { isSafeApp, getAdapterFromConnectorType, OrbitAdapter } from '@tuwaio/sdk/orbit';
378
-
379
- import { appEVMChains, solanaRPCUrls, wagmiConfig } from '@/configs/appConfig';
380
- import { usePulsarInMemoryStore, usePulsarStore } from '@/hooks/usePulsarStore';
381
- import { NovaTransactionsProvider } from '@/providers/NovaTransactionsProvider';
382
-
383
- export function AppProviders({ children }: { children: React.ReactNode }) {
384
- const getAdapter = usePulsarStore((state) => state.getAdapter);
385
- const transactionsPool = usePulsarInMemoryStore((state) => state.transactionsPool);
386
-
387
- const isLoading = usePulsarInMemoryStore((state) => state.isLoading);
388
- const isError = usePulsarInMemoryStore((state) => state.isError);
389
- const currentPage = usePulsarInMemoryStore((state) => state.currentPage);
390
- const hasMore = usePulsarInMemoryStore((state) => state.hasMore);
391
- const fetchNextPage = usePulsarInMemoryStore((state) => state.fetchNextPage);
392
- const fetchInitial = usePulsarInMemoryStore((state) => state.fetchInitial);
393
-
394
- const pagination = { isLoading, isError, currentPage, hasMore, fetchNextPage };
395
-
396
- // Watch SIWX session to keep connection state aligned
397
- const siwxSession = useSiwxSession();
398
- const { signIn } = useSiwx();
399
-
400
- return (
401
- <SatelliteConnectProvider
402
- adapter={[satelliteEVMAdapter(wagmiConfig, appEVMChains), satelliteSolanaAdapter({ rpcUrls: solanaRPCUrls })]}
403
- autoConnect={true}
404
- callbackAfterConnected={async (connection) => {
405
- const isEVM = getAdapterFromConnectorType(connection.connectorType) === OrbitAdapter.EVM;
406
- if (isEVM && isSafeApp) return;
407
-
408
- // Trigger SIWX flow
409
- await signIn();
410
-
411
- // Fetch history slightly after connection and sign-in
412
- setTimeout(() => fetchInitial(connection.address), 2000);
413
- }}
414
- >
415
- <EVMConnectorsWatcher wagmiConfig={wagmiConfig} siwx={siwxSession} />
416
- <SolanaConnectorsWatcher siwx={siwxSession} />
417
-
418
- <NovaTransactionsProvider pagination={pagination} />
419
-
420
- <NovaConnectProvider
421
- appChains={appEVMChains}
422
- solanaRPCUrls={solanaRPCUrls}
423
- transactionPool={transactionsPool}
424
- pulsarAdapter={getAdapter()}
425
- withImpersonated
426
- withBalance
427
- withChain
428
- pagination={pagination}
429
- >
430
- {children}
431
- </NovaConnectProvider>
432
- </SatelliteConnectProvider>
433
- );
434
- }
435
- ```
67
+ | Flag | Short | Default |
68
+ | -------------- | ----- | --------------------------------------------------------------------------------- |
69
+ | `--secret` | `-s` | `QUASAR_WEBHOOK_SECRET` from the environment or the `.env` file |
70
+ | `--forward-to` | `-f` | `QUASAR_WEBHOOK_FORWARD_TO`, else `http://localhost:3000/api/webhooks/quasar` |
71
+ | `--api-url` | `-a` | `NEXT_PUBLIC_QUASAR_BASE_URL` or `QUASAR_BASE_URL`, else `https://api.tuwa.io` |
72
+ | `--env-file` | `-e` | The first of `.env.local`, `.env.development` and `.env` in the working directory |
73
+ | `--help` | `-h` | |
74
+ | `--version` | `-v` | |
436
75
 
437
- ### 6. Creating a Transaction (Usage)
438
-
439
- Now you can safely execute strictly-typed, cross-chain transactions anywhere in your app. The store automatically routes the transaction to the correct adapter, and Quasar syncs it to the cloud.
440
-
441
- ```tsx
442
- // src/components/SwapButton.tsx
443
- 'use client';
444
-
445
- import { getAdapterFromConnectorType, OrbitAdapter } from '@tuwaio/sdk/orbit';
446
- import { useSatelliteConnectStore } from '@tuwaio/sdk/satellite';
447
- import { TxActionButton } from '@tuwaio/sdk/nova-transactions';
448
- import { usePulsarStore, usePulsarInMemoryStore } from '@/hooks/usePulsarStore';
449
- import { AppTxType } from '@/types';
450
-
451
- export function SwapButton() {
452
- const executeTxAction = usePulsarStore((s) => s.executeTxAction);
453
- const getLastTxKey = usePulsarStore((s) => s.getLastTxKey);
454
- const transactionsPool = usePulsarInMemoryStore((s) => s.transactionsPool);
455
- const activeConnection = useSatelliteConnectStore((s) => s.activeConnection);
456
-
457
- const handleSwapAction = async () => {
458
- // Dynamically determine the adapter based on the currently connected wallet
459
- const adapterType = getAdapterFromConnectorType(activeConnection?.connectorType ?? 'evm:');
460
-
461
- await executeTxAction({
462
- actionFunction: async () => {
463
- /* your wagmi/solana contract call */
464
- },
465
- params: {
466
- adapter: adapterType,
467
- type: AppTxType.SWAP,
468
- title: 'Token Swap',
469
- desiredChainID: adapterType === OrbitAdapter.EVM ? 1 : undefined,
470
- payload: { tokenIn: 'USDC', tokenOut: adapterType === OrbitAdapter.EVM ? 'ETH' : 'SOL', amount: 100 },
471
- },
472
- });
473
- };
474
-
475
- return (
476
- <TxActionButton
477
- action={handleSwapAction}
478
- getLastTxKey={getLastTxKey}
479
- transactionsPool={transactionsPool}
480
- walletAddress={activeConnection?.address}
481
- >
482
- Cross-Chain Swap
483
- </TxActionButton>
484
- );
485
- }
486
- ```
76
+ The relay posts each delivery with the `x-quasar-signature`, `x-quasar-event` and `x-quasar-delivery-id` headers and the same body as a direct delivery, so your endpoint verifies the signature the same way. It reconnects with a backoff of up to 15 seconds and stops on a `401` (wrong secret) or `404` (no endpoint with that secret).
487
77
 
488
78
  ---
489
79
 
490
- ## 📦 Available Namespaces
80
+ ## 🗄️ Browser Storage
491
81
 
492
- This package provides the following server-side utilities and React helpers:
82
+ Nothing is written. `preFlightTxCheck` reads the SIWX session from the store of `@tuwaio/siwx-react`, which keeps it in `localStorage` under `siwx-react:session`.
493
83
 
494
- - `Quasar` — The main server-side client class instance used to access `quasar.pulsar.*` methods.
495
- - `preFlightTxCheck` — A client-side helper to ensure the user has a valid SIWX session and Quasar Cloud is reachable before prompting wallet signatures.
84
+ ## 🌐 External Services
496
85
 
497
- ---
86
+ | Part | Host | Request |
87
+ | ------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
88
+ | `Quasar` client | `baseUrl` (default `https://api.tuwa.io`) | `POST /v1/engine/pulsar/sync` and `GET /v1/engine/pulsar/history`, with the secret key in the `x-tuwa-secret-key` header |
89
+ | `preFlightTxCheck` | Its `customApiUrl` (default `https://api.tuwa.io`) | `GET /v1/engine/monitoring/health`, without credentials |
90
+ | `quasar-sdk listen` | `--api-url` (default `https://api.tuwa.io`), then `--forward-to` | A Server-Sent Events stream from `/v1/engine/webhooks/listen` with the signing secret in the `x-webhook-secret` header; a `POST` to the local URL for each delivery |
498
91
 
499
- ## 🤝 Contributing & Support
92
+ The transactions you sync, with their `payload`, are stored by Quasar.
500
93
 
501
- Contributions are welcome! Please read our main **[Contribution Guidelines](https://github.com/TuwaIO/workflows/blob/main/CONTRIBUTING.md)**.
94
+ ---
502
95
 
503
- If you find this library useful, please consider supporting its development. Every contribution helps!
96
+ ## 📚 API Reference
504
97
 
505
- [**➡️ View Support Options**](https://github.com/TuwaIO/workflows/blob/main/Donation.md)
98
+ Every export, with signatures and types generated from the source, is documented at **[sdk.docs.tuwa.io/packages/quasar-sdk](https://sdk.docs.tuwa.io/packages/quasar-sdk)**. The HTTP API is described in the **[Quasar API reference](https://docs.tuwa.io/quasar/api)**.
506
99
 
507
100
  ## 📄 License
508
101
 
509
- This project is licensed under the **Apache-2.0 License** - see the [LICENSE](./LICENSE) file for details.
102
+ Licensed under the **Apache-2.0 License**. See the [LICENSE](https://github.com/TuwaIO/sdk/blob/main/packages/quasar-sdk/LICENSE) file for details.
@@ -0,0 +1,2 @@
1
+ 'use strict';var t="https://api.tuwa.io",n="/v1/engine/pulsar/sync",o="/v1/engine/pulsar/history";
2
+ exports.a=t;exports.b=n;exports.c=o;
@@ -0,0 +1,2 @@
1
+ var t="https://api.tuwa.io",n="/v1/engine/pulsar/sync",o="/v1/engine/pulsar/history";
2
+ export{t as a,n as b,o as c};