@tuwaio/quasar-sdk 0.1.3 → 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 +64 -33
  2. package/package.json +9 -8
package/README.md CHANGED
@@ -43,8 +43,11 @@ _Note: `ofetch` and `@tuwaio/pulsar-core` are required peer dependencies. The `@
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 { cookies } from 'next/headers';
46
47
  import { Quasar, type Transaction } from '@tuwaio/quasar-sdk';
47
- import { verifySiwxPayload, type SiwxSession } from '@tuwaio/sdk/siwx/server';
48
+ import { isSessionMatchingTarget } from '@tuwaio/sdk/siwx';
49
+ import { getSiwxServerSession } from '@tuwaio/sdk/siwx/server';
50
+ import { sessionStore } from '@/lib/authStores';
48
51
 
49
52
  // Initialize Quasar with your Secret Key from the Dashboard
50
53
  const quasar = new Quasar({ secretKey: process.env.QUASAR_SDK_SK ?? '' });
@@ -52,12 +55,19 @@ const quasar = new Quasar({ secretKey: process.env.QUASAR_SDK_SK ?? '' });
52
55
  /**
53
56
  * Example Next.js Server Action to Sync a Transaction
54
57
  */
55
- export async function syncTransaction(tx: Transaction, sessionData: SiwxSession) {
56
- // 1. Verify the client's signature (prevent unauthorized spoofing)
57
- const isValid = await verifySiwxPayload(sessionData);
58
- if (!isValid) throw new Error('Invalid signature.');
59
-
60
- // 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
61
71
  await quasar.pulsar.syncCreate(tx, 'My Application');
62
72
  return { success: true };
63
73
  }
@@ -65,12 +75,20 @@ export async function syncTransaction(tx: Transaction, sessionData: SiwxSession)
65
75
  /**
66
76
  * Example Next.js Server Action to Fetch History
67
77
  */
68
- export async function getHistory(
69
- params: { walletAddress: string; page: number; limit: number; appName: string },
70
- sessionData: SiwxSession,
71
- ) {
72
- const isValid = await verifySiwxPayload(sessionData);
73
- 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
+ }
74
92
 
75
93
  // Return the paginated transaction history
76
94
  return quasar.pulsar.getHistory(params);
@@ -81,11 +99,11 @@ export async function getHistory(
81
99
 
82
100
  ## 🔐 Frontend Authentication (SIWX)
83
101
 
84
- 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.
85
103
 
86
- 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.
87
105
 
88
- 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/).
89
107
 
90
108
  ---
91
109
 
@@ -115,29 +133,49 @@ export type TransactionUnion = SwapTx;
115
133
 
116
134
  ### 2. Secure Server Proxy (`actions.ts`)
117
135
 
118
- 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.
119
137
 
120
138
  ```ts
121
139
  // src/app/actions.ts
122
140
  'use server';
123
141
 
142
+ import { cookies } from 'next/headers';
124
143
  import { Quasar } from '@tuwaio/quasar-sdk';
125
- 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';
126
147
  import { TransactionUnion } from '@/types';
127
148
 
128
149
  const quasar = new Quasar({ secretKey: process.env.QUASAR_SDK_SK ?? '' });
129
150
 
130
- export async function syncTransaction(tx: TransactionUnion, sessionData: SiwxSession) {
131
- const isValid = await verifySiwxPayload(sessionData);
132
- 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
+ }
133
160
 
134
161
  await quasar.pulsar.syncCreate(tx, 'My App');
135
162
  return { success: true };
136
163
  }
137
164
 
138
- export async function getHistory(params: any, sessionData: SiwxSession) {
139
- const isValid = await verifySiwxPayload(sessionData);
140
- 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
+ }
141
179
 
142
180
  return quasar.pulsar.getHistory(params);
143
181
  }
@@ -150,7 +188,6 @@ export async function getHistory(params: any, sessionData: SiwxSession) {
150
188
  import { createPulsarStore, createTxInMemoryStore, createBoundedUseStore } from '@tuwaio/sdk/pulsar';
151
189
  import { pulsarEvmAdapter } from '@tuwaio/evm-sdk/pulsar';
152
190
  import { pulsarSolanaAdapter } from '@tuwaio/solana-sdk/pulsar';
153
- import { useSiwxSessionStore } from '@tuwaio/sdk/siwx';
154
191
  import { preFlightTxCheck } from '@tuwaio/quasar-sdk';
155
192
 
156
193
  import { getHistory, syncTransaction } from '@/app/actions';
@@ -169,10 +206,7 @@ const initialStore = createPulsarStore<TransactionUnion>({
169
206
  onRemoteCreate: async (tx) => {
170
207
  try {
171
208
  // Syncs the new transaction to Quasar via Next.js Server Actions
172
- const session = useSiwxSessionStore.getState().session;
173
- if (session) {
174
- await syncTransaction(tx as TransactionUnion, session);
175
- }
209
+ await syncTransaction(tx as TransactionUnion);
176
210
  } catch (err) {
177
211
  console.error('[PulsarHook] Remote sync failed:', err);
178
212
  }
@@ -186,10 +220,7 @@ const pulsarInMemoryStore = createTxInMemoryStore<TransactionUnion>({
186
220
  localTransactionsPool: initialStore.getState().transactionsPool,
187
221
  getHistory: async ({ page, walletAddress }) => {
188
222
  try {
189
- const session = useSiwxSessionStore.getState().session;
190
- if (!session) return null;
191
-
192
- const history = await getHistory({ walletAddress, page, limit: 10, appName: 'My App' }, session);
223
+ const history = await getHistory({ walletAddress, page, limit: 10, appName: 'My App' });
193
224
 
194
225
  if (!history) return null;
195
226
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuwaio/quasar-sdk",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "private": false,
5
5
  "author": "Oleksandr Tkach",
6
6
  "license": "Apache-2.0",
@@ -82,9 +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",
86
- "@tuwaio/siwx-core": "^0.1.0",
87
- "@tuwaio/siwx-server": "^0.1.0"
85
+ "@tuwaio/siwx-react": "^0.2.0",
86
+ "@tuwaio/siwx-core": "^0.2.0",
87
+ "@tuwaio/siwx-server": "^0.2.1"
88
88
  },
89
89
  "peerDependenciesMeta": {
90
90
  "@tuwaio/pulsar-core": {
@@ -108,12 +108,13 @@
108
108
  "ofetch": "^1.5.1",
109
109
  "tsup": "^8.5.1",
110
110
  "typescript": "^6.0.3",
111
- "@tuwaio/siwx-react": "^0.1.1",
112
- "@tuwaio/siwx-core": "^0.1.0",
113
- "@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"
114
114
  },
115
115
  "scripts": {
116
116
  "start": "tsup src/index.ts --watch",
117
- "build": "tsup"
117
+ "build": "tsup",
118
+ "test": "node --import tsx --test src/__tests__/*.test.ts"
118
119
  }
119
120
  }