@tuwaio/quasar-sdk 0.1.2 → 0.1.4

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.
Files changed (2) hide show
  1. package/README.md +67 -37
  2. package/package.json +16 -9
package/README.md CHANGED
@@ -31,10 +31,10 @@ It operates strictly on the server (Node.js, Next.js Server Actions, or Edge fun
31
31
  ## 💾 Installation
32
32
 
33
33
  ```bash
34
- pnpm add @tuwaio/quasar-sdk ofetch @tuwaio/pulsar-core
34
+ pnpm add @tuwaio/quasar-sdk ofetch @tuwaio/pulsar-core @tuwaio/siwx-core @tuwaio/siwx-server @tuwaio/siwx-react
35
35
  ```
36
36
 
37
- _Note: `ofetch` and `@tuwaio/pulsar-core` are required as peer dependencies to ensure ultra-fast HTTP requests and strict TypeScript compatibility._
37
+ _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._
38
38
 
39
39
  ---
40
40
 
@@ -43,9 +43,11 @@ _Note: `ofetch` and `@tuwaio/pulsar-core` are required as peer dependencies to e
43
43
  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).
44
44
 
45
45
  ```typescript
46
- import { Quasar } from '@tuwaio/quasar-sdk';
47
- import { verifySiwxPayload, type SiwxSession } from '@tuwaio/sdk/siwx/server';
48
- import type { Transaction } from '@tuwaio/sdk/pulsar';
46
+ import { cookies } from 'next/headers';
47
+ import { Quasar, type Transaction } from '@tuwaio/quasar-sdk';
48
+ import { isSessionMatchingTarget } from '@tuwaio/sdk/siwx';
49
+ import { getSiwxServerSession } from '@tuwaio/sdk/siwx/server';
50
+ import { sessionStore } from '@/lib/authStores';
49
51
 
50
52
  // Initialize Quasar with your Secret Key from the Dashboard
51
53
  const quasar = new Quasar({ secretKey: process.env.QUASAR_SDK_SK ?? '' });
@@ -53,12 +55,19 @@ const quasar = new Quasar({ secretKey: process.env.QUASAR_SDK_SK ?? '' });
53
55
  /**
54
56
  * Example Next.js Server Action to Sync a Transaction
55
57
  */
56
- export async function syncTransaction(tx: Transaction, sessionData: SiwxSession) {
57
- // 1. Verify the client's signature (prevent unauthorized spoofing)
58
- const isValid = await verifySiwxPayload(sessionData);
59
- if (!isValid) throw new Error('Invalid signature.');
60
-
61
- // 2. Sync the transaction securely to the Quasar Cloud
58
+ export async function syncTransaction(tx: Transaction) {
59
+ const session = await getSiwxServerSession({
60
+ cookieSource: await cookies(),
61
+ sessionStore,
62
+ });
63
+ if (!session) throw new Error('Unauthorized: No active session.');
64
+
65
+ // Verify that the transaction sender matches the authenticated session address
66
+ if (tx.from && !isSessionMatchingTarget(session, tx.from, tx.chainId)) {
67
+ throw new Error('Forbidden: Session address mismatch.');
68
+ }
69
+
70
+ // Sync the transaction securely to the Quasar Cloud
62
71
  await quasar.pulsar.syncCreate(tx, 'My Application');
63
72
  return { success: true };
64
73
  }
@@ -66,12 +75,20 @@ export async function syncTransaction(tx: Transaction, sessionData: SiwxSession)
66
75
  /**
67
76
  * Example Next.js Server Action to Fetch History
68
77
  */
69
- export async function getHistory(
70
- params: { walletAddress: string; page: number; limit: number; appName: string },
71
- sessionData: SiwxSession,
72
- ) {
73
- const isValid = await verifySiwxPayload(sessionData);
74
- if (!isValid) throw new Error('Invalid signature.');
78
+ export async function getHistory(params: {
79
+ walletAddress: string;
80
+ page?: number;
81
+ limit?: number;
82
+ appName?: string;
83
+ chainId?: string;
84
+ }) {
85
+ const session = await getSiwxServerSession({
86
+ cookieSource: await cookies(),
87
+ sessionStore,
88
+ });
89
+ if (!session || !isSessionMatchingTarget(session, params.walletAddress, params.chainId)) {
90
+ throw new Error('Unauthorized: Session address mismatch.');
91
+ }
75
92
 
76
93
  // Return the paginated transaction history
77
94
  return quasar.pulsar.getHistory(params);
@@ -82,11 +99,11 @@ export async function getHistory(
82
99
 
83
100
  ## 🔐 Frontend Authentication (SIWX)
84
101
 
85
- The Quasar SDK relies on the standard **SIWX (CAIP-122)** protocol for authenticating requests.
102
+ The Quasar SDK relies on the standard **SIWX (CAIP-122)** protocol for authenticating client requests.
86
103
 
87
- You should use the headless `useSatelliteSiwxAutoAuth` hook provided by `@tuwaio/sdk/siwx` on your frontend. This hook automatically prompts users to sign a CAIP-122 message when they connect their wallet, and establishes a secure session with your backend.
104
+ 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.
88
105
 
89
- For detailed frontend integration, see the [SIWX Documentation](https://sdk.docs.tuwa.io/quasar-cloud/react-bridges).
106
+ For detailed frontend integration, see the [SIWX Documentation](https://siwx.docs.tuwa.io/).
90
107
 
91
108
  ---
92
109
 
@@ -116,29 +133,49 @@ export type TransactionUnion = SwapTx;
116
133
 
117
134
  ### 2. Secure Server Proxy (`actions.ts`)
118
135
 
119
- Proxy calls to Quasar Cloud using your backend to protect secret keys.
136
+ Proxy calls to Quasar Cloud using your backend to protect secret keys. Never accept client-side session credentials in Server Actions.
120
137
 
121
138
  ```ts
122
139
  // src/app/actions.ts
123
140
  'use server';
124
141
 
142
+ import { cookies } from 'next/headers';
125
143
  import { Quasar } from '@tuwaio/quasar-sdk';
126
- import { verifySiwxPayload, type SiwxSession } from '@tuwaio/sdk/siwx/server';
144
+ import { isSessionMatchingTarget } from '@tuwaio/sdk/siwx';
145
+ import { getSiwxServerSession } from '@tuwaio/sdk/siwx/server';
146
+ import { sessionStore } from '@/lib/authStores';
127
147
  import { TransactionUnion } from '@/types';
128
148
 
129
149
  const quasar = new Quasar({ secretKey: process.env.QUASAR_SDK_SK ?? '' });
130
150
 
131
- export async function syncTransaction(tx: TransactionUnion, sessionData: SiwxSession) {
132
- const isValid = await verifySiwxPayload(sessionData);
133
- if (!isValid) throw new Error('Invalid signature.');
151
+ export async function syncTransaction(tx: TransactionUnion) {
152
+ const session = await getSiwxServerSession({
153
+ cookieSource: await cookies(),
154
+ sessionStore,
155
+ });
156
+ if (!session) throw new Error('Unauthorized: No active session.');
157
+ if (tx.from && !isSessionMatchingTarget(session, tx.from, tx.chainId)) {
158
+ throw new Error('Forbidden: Session address mismatch.');
159
+ }
134
160
 
135
161
  await quasar.pulsar.syncCreate(tx, 'My App');
136
162
  return { success: true };
137
163
  }
138
164
 
139
- export async function getHistory(params: any, sessionData: SiwxSession) {
140
- const isValid = await verifySiwxPayload(sessionData);
141
- if (!isValid) throw new Error('Invalid signature.');
165
+ export async function getHistory(params: {
166
+ walletAddress: string;
167
+ page?: number;
168
+ limit?: number;
169
+ appName?: string;
170
+ chainId?: string;
171
+ }) {
172
+ const session = await getSiwxServerSession({
173
+ cookieSource: await cookies(),
174
+ sessionStore,
175
+ });
176
+ if (!session || !isSessionMatchingTarget(session, params.walletAddress, params.chainId)) {
177
+ throw new Error('Unauthorized: Session address mismatch.');
178
+ }
142
179
 
143
180
  return quasar.pulsar.getHistory(params);
144
181
  }
@@ -151,7 +188,6 @@ export async function getHistory(params: any, sessionData: SiwxSession) {
151
188
  import { createPulsarStore, createTxInMemoryStore, createBoundedUseStore } from '@tuwaio/sdk/pulsar';
152
189
  import { pulsarEvmAdapter } from '@tuwaio/evm-sdk/pulsar';
153
190
  import { pulsarSolanaAdapter } from '@tuwaio/solana-sdk/pulsar';
154
- import { useSiwxSessionStore } from '@tuwaio/sdk/siwx';
155
191
  import { preFlightTxCheck } from '@tuwaio/quasar-sdk';
156
192
 
157
193
  import { getHistory, syncTransaction } from '@/app/actions';
@@ -170,10 +206,7 @@ const initialStore = createPulsarStore<TransactionUnion>({
170
206
  onRemoteCreate: async (tx) => {
171
207
  try {
172
208
  // Syncs the new transaction to Quasar via Next.js Server Actions
173
- const session = useSiwxSessionStore.getState().session;
174
- if (session) {
175
- await syncTransaction(tx as TransactionUnion, session);
176
- }
209
+ await syncTransaction(tx as TransactionUnion);
177
210
  } catch (err) {
178
211
  console.error('[PulsarHook] Remote sync failed:', err);
179
212
  }
@@ -187,10 +220,7 @@ const pulsarInMemoryStore = createTxInMemoryStore<TransactionUnion>({
187
220
  localTransactionsPool: initialStore.getState().transactionsPool,
188
221
  getHistory: async ({ page, walletAddress }) => {
189
222
  try {
190
- const session = useSiwxSessionStore.getState().session;
191
- if (!session) return null;
192
-
193
- const history = await getHistory({ walletAddress, page, limit: 10, appName: 'My App' }, session);
223
+ const history = await getHistory({ walletAddress, page, limit: 10, appName: 'My App' });
194
224
 
195
225
  if (!history) return null;
196
226
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuwaio/quasar-sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "private": false,
5
5
  "author": "Oleksandr Tkach",
6
6
  "license": "Apache-2.0",
@@ -82,7 +82,9 @@
82
82
  "peerDependencies": {
83
83
  "@tuwaio/pulsar-core": "^0.6.11",
84
84
  "ofetch": "^1.5.1",
85
- "@tuwaio/siwx-react": "^0.1.0"
85
+ "@tuwaio/siwx-react": "^0.2.0",
86
+ "@tuwaio/siwx-core": "^0.2.0",
87
+ "@tuwaio/siwx-server": "^0.2.1"
86
88
  },
87
89
  "peerDependenciesMeta": {
88
90
  "@tuwaio/pulsar-core": {
@@ -91,23 +93,28 @@
91
93
  "ofetch": {
92
94
  "optional": false
93
95
  },
96
+ "@tuwaio/siwx-core": {
97
+ "optional": true
98
+ },
99
+ "@tuwaio/siwx-server": {
100
+ "optional": true
101
+ },
94
102
  "@tuwaio/siwx-react": {
95
103
  "optional": true
96
104
  }
97
105
  },
98
106
  "devDependencies": {
99
- "@tuwaio/pulsar-core": "^0.6.11",
107
+ "@tuwaio/pulsar-core": "^0.6.12",
100
108
  "ofetch": "^1.5.1",
101
109
  "tsup": "^8.5.1",
102
110
  "typescript": "^6.0.3",
103
- "@tuwaio/siwx-react": "^0.1.0"
104
- },
105
- "dependencies": {
106
- "@tuwaio/siwx-core": "^0.1.0",
107
- "@tuwaio/siwx-server": "^0.1.0"
111
+ "@tuwaio/siwx-react": "^0.2.0",
112
+ "@tuwaio/siwx-core": "^0.2.0",
113
+ "@tuwaio/siwx-server": "^0.2.1"
108
114
  },
109
115
  "scripts": {
110
116
  "start": "tsup src/index.ts --watch",
111
- "build": "tsup"
117
+ "build": "tsup",
118
+ "test": "node --import tsx --test src/__tests__/*.test.ts"
112
119
  }
113
120
  }