better-near-auth 1.2.1 → 1.4.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/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +156 -34
- package/dist/client.js.map +1 -1
- package/package.json +1 -1
- package/skills/client/SKILL.md +130 -29
- package/skills/relay/SKILL.md +3 -3
- package/skills/siwn/SKILL.md +1 -1
- package/skills/tanstack/SKILL.md +356 -0
package/dist/client.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface SIWNClientActions {
|
|
|
27
27
|
publicKey: string | null;
|
|
28
28
|
networkId: string;
|
|
29
29
|
} | null;
|
|
30
|
+
isWalletConnected: () => boolean;
|
|
31
|
+
ensureConnected: () => Promise<boolean>;
|
|
30
32
|
disconnect: () => Promise<void>;
|
|
31
33
|
link: (callbacks?: AuthCallbacks) => Promise<void>;
|
|
32
34
|
unlink: (params: {
|
|
@@ -63,6 +65,7 @@ export interface SIWNClientPlugin extends BetterAuthClientPlugin {
|
|
|
63
65
|
publicKey: string | null;
|
|
64
66
|
networkId: string;
|
|
65
67
|
} | null>>;
|
|
68
|
+
walletConnected: ReturnType<typeof atom<boolean>>;
|
|
66
69
|
};
|
|
67
70
|
getActions: ($fetch: BetterFetch, $store: ClientStore, options: BetterAuthClientOptions | undefined) => SIWNClientActions;
|
|
68
71
|
}
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -5,12 +5,11 @@ import { atom } from "nanostores";
|
|
|
5
5
|
import {} from "./types.js";
|
|
6
6
|
export const siwnClient = (config) => {
|
|
7
7
|
const nearState = atom(null);
|
|
8
|
+
const walletConnected = atom(false);
|
|
8
9
|
const network = config.networkId || "mainnet";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
wallet: fromNearConnect(connector),
|
|
13
|
-
});
|
|
10
|
+
let connector = null;
|
|
11
|
+
let near = null;
|
|
12
|
+
let clientInitialized = false;
|
|
14
13
|
const handleAccountConnection = async (accountId, publicKey) => {
|
|
15
14
|
if (!accountId)
|
|
16
15
|
return;
|
|
@@ -19,44 +18,134 @@ export const siwnClient = (config) => {
|
|
|
19
18
|
publicKey: publicKey || null,
|
|
20
19
|
networkId: network,
|
|
21
20
|
});
|
|
21
|
+
walletConnected.set(true);
|
|
22
22
|
};
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
23
|
+
const initClient = ($fetch) => {
|
|
24
|
+
if (clientInitialized)
|
|
25
|
+
return true;
|
|
26
|
+
if (typeof globalThis.window === "undefined")
|
|
27
|
+
return false;
|
|
28
|
+
connector = new NearConnector({ network });
|
|
29
|
+
near = new Near({
|
|
30
|
+
network,
|
|
31
|
+
wallet: fromNearConnect(connector),
|
|
32
|
+
});
|
|
33
|
+
connector.on("wallet:signIn", async (data) => {
|
|
34
|
+
const accountId = data.accounts?.[0]?.accountId;
|
|
35
|
+
const publicKey = data.accounts?.[0]?.publicKey;
|
|
36
|
+
if (accountId) {
|
|
37
|
+
await handleAccountConnection(accountId, publicKey);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
connector.on("wallet:signOut", () => {
|
|
41
|
+
walletConnected.set(false);
|
|
42
|
+
const state = nearState.get();
|
|
43
|
+
if (state) {
|
|
44
|
+
nearState.set({ accountId: state.accountId, publicKey: null, networkId: state.networkId });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
connector.getConnectedWallet().then(({ accounts }) => {
|
|
48
|
+
const account = accounts?.[0];
|
|
49
|
+
if (account?.accountId && !nearState.get()) {
|
|
50
|
+
nearState.set({
|
|
51
|
+
accountId: account.accountId,
|
|
52
|
+
publicKey: account.publicKey ?? null,
|
|
53
|
+
networkId: network,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (account?.accountId) {
|
|
57
|
+
walletConnected.set(true);
|
|
58
|
+
}
|
|
59
|
+
}).catch(() => { });
|
|
60
|
+
if ($fetch) {
|
|
61
|
+
restoreFromSession($fetch);
|
|
28
62
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
});
|
|
63
|
+
clientInitialized = true;
|
|
64
|
+
return true;
|
|
65
|
+
};
|
|
66
|
+
let sessionRestored = false;
|
|
67
|
+
const restoreFromSession = async ($fetch) => {
|
|
68
|
+
if (sessionRestored)
|
|
69
|
+
return;
|
|
70
|
+
const state = nearState.get();
|
|
71
|
+
if (state?.accountId) {
|
|
72
|
+
sessionRestored = true;
|
|
73
|
+
return;
|
|
41
74
|
}
|
|
42
|
-
|
|
75
|
+
try {
|
|
76
|
+
const res = await $fetch("/near/list-accounts", { method: "GET" });
|
|
77
|
+
const accounts = res.data?.accounts;
|
|
78
|
+
if (accounts?.length) {
|
|
79
|
+
const primary = accounts.find((a) => a.isPrimary) || accounts[0];
|
|
80
|
+
if (primary) {
|
|
81
|
+
nearState.set({
|
|
82
|
+
accountId: primary.accountId,
|
|
83
|
+
publicKey: primary.publicKey ?? null,
|
|
84
|
+
networkId: primary.network,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch { }
|
|
90
|
+
sessionRestored = true;
|
|
91
|
+
};
|
|
92
|
+
const requireConnector = () => {
|
|
93
|
+
if (!connector)
|
|
94
|
+
throw new Error("Wallet not initialized — this operation requires a browser environment");
|
|
95
|
+
return connector;
|
|
96
|
+
};
|
|
97
|
+
const requireNear = () => {
|
|
98
|
+
if (!near)
|
|
99
|
+
throw new Error("Wallet not initialized — this operation requires a browser environment");
|
|
100
|
+
return near;
|
|
101
|
+
};
|
|
102
|
+
const ensureWalletConnected = async () => {
|
|
103
|
+
const conn = requireConnector();
|
|
104
|
+
if (walletConnected.get()) {
|
|
105
|
+
try {
|
|
106
|
+
const { accounts } = await conn.getConnectedWallet();
|
|
107
|
+
if (accounts?.length)
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
catch { }
|
|
111
|
+
}
|
|
112
|
+
return new Promise((resolve) => {
|
|
113
|
+
const signInHandler = (data) => {
|
|
114
|
+
const accountId = data.accounts?.[0]?.accountId;
|
|
115
|
+
const publicKey = data.accounts?.[0]?.publicKey;
|
|
116
|
+
if (accountId) {
|
|
117
|
+
handleAccountConnection(accountId, publicKey);
|
|
118
|
+
resolve(true);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
conn.on("wallet:signIn", signInHandler);
|
|
122
|
+
conn.connect().catch(() => { }).finally(() => {
|
|
123
|
+
conn.off("wallet:signIn", signInHandler);
|
|
124
|
+
if (!walletConnected.get()) {
|
|
125
|
+
resolve(false);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
};
|
|
43
130
|
const signWithWallet = async () => {
|
|
131
|
+
const conn = requireConnector();
|
|
132
|
+
const nearClient = requireNear();
|
|
44
133
|
const nonceBytes = generateNonce();
|
|
45
134
|
const nonceHex = hex.encode(nonceBytes);
|
|
46
135
|
const message = `Sign in to ${config.recipient}`;
|
|
47
136
|
let connectedWallet = null;
|
|
48
137
|
try {
|
|
49
|
-
connectedWallet = await
|
|
138
|
+
connectedWallet = await conn.getConnectedWallet();
|
|
50
139
|
}
|
|
51
140
|
catch { }
|
|
52
141
|
if (connectedWallet?.accounts?.length) {
|
|
53
|
-
const signedMessage = await
|
|
142
|
+
const signedMessage = await nearClient.signMessage({
|
|
54
143
|
message,
|
|
55
144
|
recipient: config.recipient,
|
|
56
145
|
nonce: nonceBytes,
|
|
57
146
|
});
|
|
58
147
|
if (!signedMessage?.accountId) {
|
|
59
|
-
throw new Error("Wallet
|
|
148
|
+
throw new Error("Wallet sign-in was cancelled or failed");
|
|
60
149
|
}
|
|
61
150
|
return {
|
|
62
151
|
signedMessage,
|
|
@@ -76,9 +165,9 @@ export const siwnClient = (config) => {
|
|
|
76
165
|
};
|
|
77
166
|
}
|
|
78
167
|
};
|
|
79
|
-
|
|
168
|
+
conn.on("wallet:signInAndSignMessage", handler);
|
|
80
169
|
try {
|
|
81
|
-
await
|
|
170
|
+
await conn.connect({
|
|
82
171
|
signMessageParams: {
|
|
83
172
|
message,
|
|
84
173
|
recipient: config.recipient,
|
|
@@ -87,10 +176,10 @@ export const siwnClient = (config) => {
|
|
|
87
176
|
});
|
|
88
177
|
}
|
|
89
178
|
finally {
|
|
90
|
-
|
|
179
|
+
conn.off("wallet:signInAndSignMessage", handler);
|
|
91
180
|
}
|
|
92
181
|
if (!result.value) {
|
|
93
|
-
throw new Error("Wallet
|
|
182
|
+
throw new Error("Wallet sign-in was cancelled or failed");
|
|
94
183
|
}
|
|
95
184
|
return {
|
|
96
185
|
signedMessage: result.value.signedMessage,
|
|
@@ -102,9 +191,16 @@ export const siwnClient = (config) => {
|
|
|
102
191
|
const buildSignedDelegateActionInternal = async (receiverId, buildActions) => {
|
|
103
192
|
const state = nearState.get();
|
|
104
193
|
if (!state?.accountId) {
|
|
105
|
-
throw new Error("No
|
|
194
|
+
throw new Error("No NEAR account found — please sign in with your NEAR wallet");
|
|
195
|
+
}
|
|
196
|
+
if (!walletConnected.get()) {
|
|
197
|
+
const reconnected = await ensureWalletConnected();
|
|
198
|
+
if (!reconnected) {
|
|
199
|
+
throw new Error("Wallet connection required — please approve the connection to sign");
|
|
200
|
+
}
|
|
106
201
|
}
|
|
107
|
-
const
|
|
202
|
+
const nearClient = requireNear();
|
|
203
|
+
const builder = buildActions(nearClient.transaction(state.accountId), receiverId);
|
|
108
204
|
const { payload } = await builder.delegate();
|
|
109
205
|
return payload;
|
|
110
206
|
};
|
|
@@ -113,8 +209,10 @@ export const siwnClient = (config) => {
|
|
|
113
209
|
$InferServerPlugin: {},
|
|
114
210
|
getAtoms: (_$fetch) => ({
|
|
115
211
|
nearState,
|
|
212
|
+
walletConnected,
|
|
116
213
|
}),
|
|
117
214
|
getActions: ($fetch, _$store, _options) => {
|
|
215
|
+
initClient($fetch);
|
|
118
216
|
return {
|
|
119
217
|
near: {
|
|
120
218
|
nonce: async (params, fetchOptions) => {
|
|
@@ -150,8 +248,28 @@ export const siwnClient = (config) => {
|
|
|
150
248
|
return state?.accountId || null;
|
|
151
249
|
},
|
|
152
250
|
getState: () => nearState.get(),
|
|
251
|
+
isWalletConnected: () => walletConnected.get(),
|
|
252
|
+
ensureConnected: async () => {
|
|
253
|
+
if (!clientInitialized) {
|
|
254
|
+
if (!initClient())
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
if (walletConnected.get()) {
|
|
258
|
+
try {
|
|
259
|
+
const { accounts } = await requireConnector().getConnectedWallet();
|
|
260
|
+
if (accounts?.length)
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
catch (err) {
|
|
264
|
+
console.error("[siwn] restoreFromSession failed:", err instanceof Error ? err.message : err);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return ensureWalletConnected();
|
|
268
|
+
},
|
|
153
269
|
disconnect: async () => {
|
|
154
|
-
|
|
270
|
+
if (connector)
|
|
271
|
+
await connector.disconnect();
|
|
272
|
+
walletConnected.set(false);
|
|
155
273
|
nearState.set(null);
|
|
156
274
|
},
|
|
157
275
|
link: async (callbacks) => {
|
|
@@ -216,7 +334,11 @@ export const siwnClient = (config) => {
|
|
|
216
334
|
method: "GET",
|
|
217
335
|
});
|
|
218
336
|
},
|
|
219
|
-
client
|
|
337
|
+
get client() {
|
|
338
|
+
if (!near)
|
|
339
|
+
throw new Error("Wallet not initialized — this operation requires a browser environment");
|
|
340
|
+
return near;
|
|
341
|
+
},
|
|
220
342
|
},
|
|
221
343
|
signIn: {
|
|
222
344
|
near: async (callbacks) => {
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/skills/client/SKILL.md
CHANGED
|
@@ -8,7 +8,7 @@ description: >
|
|
|
8
8
|
using authClient.near.* methods, or building delegate actions for gasless relay.
|
|
9
9
|
type: core
|
|
10
10
|
library: better-near-auth
|
|
11
|
-
library_version: "1.1
|
|
11
|
+
library_version: "1.2.1"
|
|
12
12
|
sources:
|
|
13
13
|
- "elliotBraem/better-near-auth:src/client.ts"
|
|
14
14
|
- "elliotBraem/better-near-auth:src/types.ts"
|
|
@@ -20,8 +20,21 @@ sources:
|
|
|
20
20
|
|
|
21
21
|
Client-side plugin for NEAR wallet authentication and gasless relay. Connects to NEAR wallets via NearConnect, provides `authClient.near.*` actions for sign-in, account management, profile lookup, and delegate action building.
|
|
22
22
|
|
|
23
|
+
## SSR Behavior
|
|
24
|
+
|
|
25
|
+
`siwnClient()` is SSR-safe. Wallet resources (`NearConnector`, `Near`, event listeners) are lazily initialized on first client-side access — they do not run at construction time. On the server:
|
|
26
|
+
|
|
27
|
+
- `getAccountId()` returns `null` (no session restore yet)
|
|
28
|
+
- `getState()` returns `null`
|
|
29
|
+
- `isWalletConnected()` returns `false`
|
|
30
|
+
- `buildSignedDelegateAction`, `signWithWallet`, `ensureConnected` throw "Wallet not initialized — this operation requires a browser environment"
|
|
31
|
+
- `near.client` getter throws on access
|
|
32
|
+
- HTTP-only methods (`nonce`, `verify`, `view`, `relayTransaction`, etc.) work normally via `$fetch`
|
|
33
|
+
|
|
23
34
|
## Setup
|
|
24
35
|
|
|
36
|
+
### Simple app (module singleton)
|
|
37
|
+
|
|
25
38
|
```typescript
|
|
26
39
|
import { createAuthClient } from "better-auth/client";
|
|
27
40
|
import { siwnClient } from "better-near-auth/client";
|
|
@@ -36,6 +49,36 @@ export const authClient = createAuthClient({
|
|
|
36
49
|
});
|
|
37
50
|
```
|
|
38
51
|
|
|
52
|
+
### SSR app (router context)
|
|
53
|
+
|
|
54
|
+
For TanStack Router with server rendering, create the auth client once in your router setup and access via context:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// auth.ts
|
|
58
|
+
import { createAuthClient as createBetterAuthClient } from "better-auth/react";
|
|
59
|
+
import { siwnClient } from "better-near-auth/client";
|
|
60
|
+
import { useRouter } from "@tanstack/react-router";
|
|
61
|
+
|
|
62
|
+
export function createAuthClient() {
|
|
63
|
+
return createBetterAuthClient({
|
|
64
|
+
plugins: [siwnClient({ recipient: getAccount(), networkId: getNetworkId() })],
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type AuthClient = ReturnType<typeof createAuthClient>;
|
|
69
|
+
|
|
70
|
+
export function useAuthClient(): AuthClient {
|
|
71
|
+
return useRouter().options.context.authClient;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// hydrate.tsx — create once, put in router context
|
|
75
|
+
const { router } = createRouter({
|
|
76
|
+
context: { authClient: createAuthClient() },
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
A module-level singleton is shared across SSR requests, causing data leaks. Router context gives one client per request on server, one per app on client.
|
|
81
|
+
|
|
39
82
|
The `recipient` must match the server's `siwn()` recipient exactly. `networkId` defaults to `"mainnet"`.
|
|
40
83
|
|
|
41
84
|
## Core Patterns
|
|
@@ -77,12 +120,36 @@ console.log("Status:", status.data.status);
|
|
|
77
120
|
|
|
78
121
|
The `buildSignedDelegateAction` callback receives a `TransactionBuilder` from near-kit and the `receiverId`. Use `builder.functionCall()` to construct actions. The builder calls `.delegate()` internally and returns a base64 payload string.
|
|
79
122
|
|
|
123
|
+
`buildSignedDelegateAction` automatically calls `ensureConnected()` if the wallet is disconnected, prompting the user to reconnect.
|
|
124
|
+
|
|
125
|
+
### Direct send (user pays gas)
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// Must ensure wallet is connected before .send()
|
|
129
|
+
await authClient.near.ensureConnected();
|
|
130
|
+
return authClient.near.client
|
|
131
|
+
.transaction(accountId)
|
|
132
|
+
.functionCall(contractId, "method", args, {
|
|
133
|
+
gas: Gas.Tgas(30),
|
|
134
|
+
attachedDeposit: BigInt(0),
|
|
135
|
+
})
|
|
136
|
+
.send({ waitUntil: "FINAL" });
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Wallet extensions (Meteor, HERE) may disconnect after the initial sign-in popup. Always call `ensureConnected()` before `.send()` — it opens a reconnection prompt if needed. `buildSignedDelegateAction` does this automatically, but direct `.send()` does not.
|
|
140
|
+
|
|
80
141
|
### Wallet state and profile management
|
|
81
142
|
|
|
82
143
|
```typescript
|
|
83
|
-
// Get current account
|
|
144
|
+
// Get current account (persists across wallet disconnects)
|
|
84
145
|
const accountId = authClient.near.getAccountId(); // string | null
|
|
85
146
|
|
|
147
|
+
// Check if signing operations are available
|
|
148
|
+
const canSign = authClient.near.isWalletConnected(); // boolean
|
|
149
|
+
|
|
150
|
+
// Prompt wallet reconnection if disconnected
|
|
151
|
+
const connected = await authClient.near.ensureConnected(); // Promise<boolean>
|
|
152
|
+
|
|
86
153
|
// Get full wallet state
|
|
87
154
|
const state = authClient.near.getState(); // { accountId, publicKey, networkId } | null
|
|
88
155
|
|
|
@@ -94,6 +161,8 @@ const aliceProfile = await authClient.near.getProfile("alice.near");
|
|
|
94
161
|
await authClient.near.disconnect();
|
|
95
162
|
```
|
|
96
163
|
|
|
164
|
+
When the wallet disconnects externally (user signs out from wallet UI), `nearState` preserves `accountId` but clears `publicKey`. Use `isWalletConnected()` to check if signing operations are available, and `getAccountId()` for display purposes (works even when disconnected).
|
|
165
|
+
|
|
97
166
|
### Account linking and contract view calls
|
|
98
167
|
|
|
99
168
|
```typescript
|
|
@@ -127,8 +196,10 @@ const result = await authClient.near.view({
|
|
|
127
196
|
| `verify(params)` | `Promise<Response<VerifyResponse>>` | Verify NEP-413 signature |
|
|
128
197
|
| `getProfile(accountId?)` | `Promise<Response<Profile>>` | Get NEAR profile |
|
|
129
198
|
| `view(params)` | `Promise<Response<ViewResponse>>` | Server-side contract view call |
|
|
130
|
-
| `getAccountId()` | `string \| null` | Currently connected account ID |
|
|
199
|
+
| `getAccountId()` | `string \| null` | Currently connected account ID (persists across disconnects) |
|
|
131
200
|
| `getState()` | `{ accountId, publicKey, networkId } \| null` | Wallet state |
|
|
201
|
+
| `isWalletConnected()` | `boolean` | Whether wallet is actively connected |
|
|
202
|
+
| `ensureConnected()` | `Promise<boolean>` | Reconnect wallet if disconnected |
|
|
132
203
|
| `disconnect()` | `Promise<void>` | Disconnect wallet |
|
|
133
204
|
| `link(callbacks?)` | `Promise<void>` | Link NEAR account to session |
|
|
134
205
|
| `unlink(params)` | `Promise<Response>` | Unlink NEAR account |
|
|
@@ -138,7 +209,7 @@ const result = await authClient.near.view({
|
|
|
138
209
|
| `getRelayStatus(txHash)` | `Promise<Response<RelayStatusResponse>>` | Check relayed tx status |
|
|
139
210
|
| `getRelayerInfo()` | `Promise<Response<RelayerInfo>>` | Get relayer info and balance |
|
|
140
211
|
| `relayHistory()` | `Promise<Response<RelayHistoryResponse>>` | List relayed transactions |
|
|
141
|
-
| `client` | `Near` | Access near-kit Near instance
|
|
212
|
+
| `client` | `Near` | Access near-kit Near instance (throws on server) |
|
|
142
213
|
|
|
143
214
|
### authClient.signIn
|
|
144
215
|
|
|
@@ -157,6 +228,41 @@ interface AuthCallbacks {
|
|
|
157
228
|
|
|
158
229
|
## Common Mistakes
|
|
159
230
|
|
|
231
|
+
### CRITICAL Creating multiple siwnClient instances
|
|
232
|
+
|
|
233
|
+
Wrong:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
// Factory that creates new client each call
|
|
237
|
+
function getAuthClient(config) {
|
|
238
|
+
return createAuthClient({
|
|
239
|
+
plugins: [siwnClient({ recipient: getAccount(config) })],
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
// Each call = new nearState atom = wallet state lost
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Correct:
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// Single module-level instance (simple apps)
|
|
249
|
+
export const authClient = createAuthClient({
|
|
250
|
+
plugins: [siwnClient({ recipient: "myapp.near" })],
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// OR: router context singleton (SSR apps)
|
|
254
|
+
export function createAuthClient() {
|
|
255
|
+
return createBetterAuthClient({
|
|
256
|
+
plugins: [siwnClient({ recipient: getAccount() })],
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
// Create once in router setup, access via context
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`siwnClient()` creates stateful singletons: a `nearState` atom, a `walletConnected` atom, a `NearConnector` with event listeners, and a `Near` instance. Multiple instances means wallet sign-in populates one atom while your app reads from another. Always create exactly one `siwnClient()` per app lifecycle.
|
|
263
|
+
|
|
264
|
+
Source: src/client.ts:64-72
|
|
265
|
+
|
|
160
266
|
### CRITICAL Recipient mismatch between server and client
|
|
161
267
|
|
|
162
268
|
Wrong:
|
|
@@ -181,39 +287,32 @@ siwnClient({ recipient: "myapp.com" });
|
|
|
181
287
|
|
|
182
288
|
The client embeds the recipient in the signed message. The server verifies against its own recipient. A mismatch causes the verify endpoint to reject the signature with "Unauthorized: Invalid signature" — which is confusing because the signature is valid, just for a different recipient.
|
|
183
289
|
|
|
184
|
-
Source: src/client.ts:
|
|
290
|
+
Source: src/client.ts:108, src/index.ts:225
|
|
185
291
|
|
|
186
292
|
See also: siwn/SKILL.md — server plugin recipient configuration
|
|
187
293
|
|
|
188
|
-
### HIGH
|
|
294
|
+
### HIGH Using near.client.send() without ensuring wallet connection
|
|
189
295
|
|
|
190
296
|
Wrong:
|
|
191
297
|
|
|
192
298
|
```typescript
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
(builder, receiverId) => builder.functionCall(receiverId, "method", {})
|
|
197
|
-
);
|
|
299
|
+
authClient.near.client.transaction(accountId)
|
|
300
|
+
.functionCall(contract, "method", args, opts)
|
|
301
|
+
.send(); // fails if wallet disconnected after sign-in
|
|
198
302
|
```
|
|
199
303
|
|
|
200
304
|
Correct:
|
|
201
305
|
|
|
202
306
|
```typescript
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
const payload = await authClient.near.buildSignedDelegateAction(
|
|
209
|
-
"myapp.near",
|
|
210
|
-
(builder, receiverId) => builder.functionCall(receiverId, "method", {})
|
|
211
|
-
);
|
|
307
|
+
await authClient.near.ensureConnected(); // reconnects wallet if needed
|
|
308
|
+
authClient.near.client.transaction(accountId)
|
|
309
|
+
.functionCall(contract, "method", args, opts)
|
|
310
|
+
.send();
|
|
212
311
|
```
|
|
213
312
|
|
|
214
|
-
|
|
313
|
+
Wallet extensions (Meteor, HERE) may disconnect after the initial sign-in popup. `ensureConnected()` opens a reconnection prompt if needed. `buildSignedDelegateAction` calls this automatically, but direct `.send()` does not.
|
|
215
314
|
|
|
216
|
-
Source: src/client.ts:
|
|
315
|
+
Source: src/client.ts:249-253, src/client.ts:310-317
|
|
217
316
|
|
|
218
317
|
### HIGH Constructing transactions with wrong builder pattern
|
|
219
318
|
|
|
@@ -242,7 +341,7 @@ const result = await authClient.near.relayTransaction({ payload });
|
|
|
242
341
|
|
|
243
342
|
Delegate actions must be built through `buildSignedDelegateAction`, which uses near-kit's `TransactionBuilder.delegate()` method. Direct `.send()` broadcasts from the client account and requires the user to pay gas — defeating the gasless relay purpose.
|
|
244
343
|
|
|
245
|
-
Source: src/client.ts:
|
|
344
|
+
Source: src/client.ts:240-260
|
|
246
345
|
|
|
247
346
|
See also: relay/SKILL.md — relay endpoint validation and whitelisting
|
|
248
347
|
|
|
@@ -273,7 +372,7 @@ await authClient.signIn.near({
|
|
|
273
372
|
|
|
274
373
|
`signIn.near()` handles wallet connection, NEP-413 message signing, nonce management, and server verification in a single call. Calling `verify` directly requires manually constructing all parameters and does not handle wallet connection.
|
|
275
374
|
|
|
276
|
-
Source: src/client.ts:
|
|
375
|
+
Source: src/client.ts:402-437
|
|
277
376
|
|
|
278
377
|
### MEDIUM Not subscribing to wallet disconnect events
|
|
279
378
|
|
|
@@ -291,11 +390,13 @@ Correct:
|
|
|
291
390
|
import { useStore } from "nanostores/react";
|
|
292
391
|
const { nearState } = authClient.$store;
|
|
293
392
|
const state = useStore(nearState);
|
|
294
|
-
// state
|
|
295
|
-
|
|
393
|
+
// state preserves accountId when wallet disconnects
|
|
394
|
+
// publicKey becomes null, walletConnected becomes false
|
|
296
395
|
|
|
297
|
-
|
|
396
|
+
// Or check signing availability:
|
|
397
|
+
const canSign = authClient.near.isWalletConnected();
|
|
398
|
+
```
|
|
298
399
|
|
|
299
|
-
|
|
400
|
+
When the wallet disconnects externally (user signs out from wallet UI), `nearState` preserves `accountId` but clears `publicKey` and sets `walletConnected` to false. Use `isWalletConnected()` to check if signing operations are available, and `getAccountId()` for display purposes (works even when disconnected).
|
|
300
401
|
|
|
301
|
-
|
|
402
|
+
Source: src/client.ts:65-66, src/client.ts:102-108
|
package/skills/relay/SKILL.md
CHANGED
|
@@ -8,7 +8,7 @@ description: >
|
|
|
8
8
|
configuring RotatingKeyStore for high-throughput relay.
|
|
9
9
|
type: core
|
|
10
10
|
library: better-near-auth
|
|
11
|
-
library_version: "1.1
|
|
11
|
+
library_version: "1.2.1"
|
|
12
12
|
sources:
|
|
13
13
|
- "elliotBraem/better-near-auth:src/index.ts"
|
|
14
14
|
- "elliotBraem/better-near-auth:src/utils.ts"
|
|
@@ -189,7 +189,7 @@ siwn({
|
|
|
189
189
|
// Send NEAR to that account ID to fund the relayer
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
-
The ephemeral mode generates an implicit account (hex of public key) with zero balance. Without funding, every relay attempt fails with an insufficient balance error from the NEAR RPC. Alternatively, use explicit mode with a pre-funded named account.
|
|
192
|
+
The ephemeral mode generates an implicit account (hex of public key) with zero balance. Without funding, every relay attempt fails with an insufficient balance error from the NEAR RPC. The server catches this at src/index.ts:952-958 and surfaces it as `"Relay failed"` — check server logs for the actual RPC error. Alternatively, use explicit mode with a pre-funded named account.
|
|
193
193
|
|
|
194
194
|
Source: src/index.ts:179-181, maintainer interview
|
|
195
195
|
|
|
@@ -250,7 +250,7 @@ const payload = await authClient.near.buildSignedDelegateAction(
|
|
|
250
250
|
const result = await authClient.near.relayTransaction({ payload });
|
|
251
251
|
```
|
|
252
252
|
|
|
253
|
-
Delegate actions must be built using the near-kit `TransactionBuilder` with `.delegate()`, not `.send()` directly. The wallet signs a delegate action; the relayer submits it on-chain.
|
|
253
|
+
Delegate actions must be built using the near-kit `TransactionBuilder` with `.delegate()`, not `.send()` directly. The wallet signs a delegate action; the relayer submits it on-chain. For direct sends (user pays gas), call `authClient.near.ensureConnected()` first — wallet extensions may disconnect between sign-in and signing.
|
|
254
254
|
|
|
255
255
|
Source: src/client.ts:172-185, maintainer interview
|
|
256
256
|
|
package/skills/siwn/SKILL.md
CHANGED
|
@@ -8,7 +8,7 @@ description: >
|
|
|
8
8
|
or debugging NEP-413 verify or nonce issues.
|
|
9
9
|
type: core
|
|
10
10
|
library: better-near-auth
|
|
11
|
-
library_version: "1.1
|
|
11
|
+
library_version: "1.2.1"
|
|
12
12
|
sources:
|
|
13
13
|
- "elliotBraem/better-near-auth:src/index.ts"
|
|
14
14
|
- "elliotBraem/better-near-auth:src/profile.ts"
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tanstack
|
|
3
|
+
description: >
|
|
4
|
+
Integrate better-near-auth with TanStack Router (SSR or CSR). Set up auth
|
|
5
|
+
client as a router context singleton, useAuthClient hook, session query
|
|
6
|
+
options, inferred types from AuthClient, and ensureConnected before signing.
|
|
7
|
+
Load when scaffolding a new TanStack Router app with better-near-auth,
|
|
8
|
+
wiring auth into router context, or debugging wallet state loss after
|
|
9
|
+
sign-in in SSR/CSR TanStack apps.
|
|
10
|
+
type: framework
|
|
11
|
+
library: better-near-auth
|
|
12
|
+
library_version: "1.2.1"
|
|
13
|
+
sources:
|
|
14
|
+
- "elliotBraem/better-near-auth:src/client.ts"
|
|
15
|
+
- "elliotBraem/better-near-auth:examples/auth.everything.dev/ui/src/auth.ts"
|
|
16
|
+
- "elliotBraem/better-near-auth:examples/auth.everything.dev/ui/src/app.ts"
|
|
17
|
+
- "elliotBraem/better-near-auth:examples/auth.everything.dev/ui/src/hydrate.tsx"
|
|
18
|
+
- "elliotBraem/better-near-auth:examples/auth.everything.dev/ui/src/router.tsx"
|
|
19
|
+
- "elliotBraem/better-near-auth:examples/auth.everything.dev/ui/src/router.server.tsx"
|
|
20
|
+
- "elliotBraem/better-near-auth:examples/browser-2-server/apps/web/src/lib/auth-client.ts"
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Better-Near-Auth — TanStack Router Integration
|
|
24
|
+
|
|
25
|
+
Integration pattern for better-near-auth with TanStack Router apps, covering both CSR (client-side only) and SSR (server-rendered) setups. Establishes the auth client as a router context singleton, provides hooks and query options, and ensures wallet state survives page navigation and hydration.
|
|
26
|
+
|
|
27
|
+
## Architecture: Two Patterns
|
|
28
|
+
|
|
29
|
+
### Pattern A: Module singleton (CSR only)
|
|
30
|
+
|
|
31
|
+
For apps without SSR — config is known at build time or from env vars:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// lib/auth-client.ts
|
|
35
|
+
import { createAuthClient } from "better-auth/react";
|
|
36
|
+
import { siwnClient } from "better-near-auth/client";
|
|
37
|
+
|
|
38
|
+
export const authClient = createAuthClient({
|
|
39
|
+
baseURL: import.meta.env.VITE_SERVER_URL || "http://localhost:3000",
|
|
40
|
+
plugins: [
|
|
41
|
+
siwnClient({ recipient: "myapp.near", networkId: "mainnet" }),
|
|
42
|
+
],
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Import directly in any component or route. Simple, correct for CSR.
|
|
47
|
+
|
|
48
|
+
### Pattern B: Router context singleton (SSR or CSR with runtime config)
|
|
49
|
+
|
|
50
|
+
For TanStack Router apps with SSR, Module Federation, or runtime config (`window.__RUNTIME_CONFIG__`):
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// auth.ts — single file for client factory, types, hooks, and query options
|
|
54
|
+
import { createAuthClient as createBetterAuthClient } from "better-auth/react";
|
|
55
|
+
import { siwnClient } from "better-near-auth/client";
|
|
56
|
+
import { useRouter } from "@tanstack/react-router";
|
|
57
|
+
import { useQuery } from "@tanstack/react-query";
|
|
58
|
+
import type { Auth } from "./auth-types.gen";
|
|
59
|
+
import { getAccount, getHostUrl, getNetworkId } from "@/app";
|
|
60
|
+
|
|
61
|
+
export function createAuthClient() {
|
|
62
|
+
return createBetterAuthClient({
|
|
63
|
+
baseURL: getHostUrl(),
|
|
64
|
+
fetchOptions: { credentials: "include" },
|
|
65
|
+
plugins: [
|
|
66
|
+
siwnClient({ recipient: getAccount(), networkId: getNetworkId() }),
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export type AuthClient = ReturnType<typeof createAuthClient>;
|
|
72
|
+
export type SessionData = AuthClient["$Infer"]["Session"];
|
|
73
|
+
|
|
74
|
+
export function useAuthClient(): AuthClient {
|
|
75
|
+
return useRouter().options.context.authClient;
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The auth client is created once in the router setup (not per component call) and accessed via context:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// hydrate.tsx
|
|
83
|
+
import { createAuthClient } from "./auth";
|
|
84
|
+
|
|
85
|
+
const { router } = createRouter({
|
|
86
|
+
context: {
|
|
87
|
+
authClient: createAuthClient(),
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// router.server.tsx — same pattern
|
|
92
|
+
context: {
|
|
93
|
+
authClient: createAuthClient(),
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Type Inference from AuthClient
|
|
98
|
+
|
|
99
|
+
Don't manually define `Organization`, `Passkey`, or other entity types. Infer them from the client's API responses:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
type UnwrapListResponse<T> = T extends (...args: any[]) => Promise<{
|
|
103
|
+
data: (infer U)[] | null; error: any
|
|
104
|
+
}> ? U : never;
|
|
105
|
+
|
|
106
|
+
export type Organization = UnwrapListResponse<AuthClient["organization"]["list"]>;
|
|
107
|
+
export type Passkey = UnwrapListResponse<AuthClient["passkey"]["listUserPasskeys"]>;
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
This automatically includes any additional fields the server configured. Single source of truth: the `AuthClient` type, which is itself derived from the plugin list.
|
|
111
|
+
|
|
112
|
+
## Session Query Options
|
|
113
|
+
|
|
114
|
+
Always pass the auth client directly — never thread `runtimeConfig` through query options:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
export function sessionQueryOptions(
|
|
118
|
+
authClient: AuthClient,
|
|
119
|
+
initialSession?: SessionData | null,
|
|
120
|
+
) {
|
|
121
|
+
return {
|
|
122
|
+
queryKey: ["session"],
|
|
123
|
+
queryFn: async () => {
|
|
124
|
+
const { data: session } = await authClient.getSession();
|
|
125
|
+
return session ?? null;
|
|
126
|
+
},
|
|
127
|
+
staleTime: 60 * 1000,
|
|
128
|
+
gcTime: 10 * 60 * 1000,
|
|
129
|
+
initialData: initialSession,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
In `beforeLoad`/`loader` (not components), use `context.authClient`:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
beforeLoad: async ({ context }) => {
|
|
138
|
+
const session = await context.queryClient.ensureQueryData(
|
|
139
|
+
sessionQueryOptions(context.authClient, context.session),
|
|
140
|
+
);
|
|
141
|
+
if (!session?.user) {
|
|
142
|
+
throw redirect({ to: "/login" });
|
|
143
|
+
}
|
|
144
|
+
return { session };
|
|
145
|
+
},
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
In components, use `useAuthClient()`:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
const auth = useAuthClient();
|
|
152
|
+
const { data } = await auth.organization.list();
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Router Context Setup
|
|
156
|
+
|
|
157
|
+
### Define RouterContext with authClient
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
// app.ts
|
|
161
|
+
import type { AuthClient, SessionData } from "./auth";
|
|
162
|
+
|
|
163
|
+
export interface RouterContext extends BaseRouterContext {
|
|
164
|
+
apiClient: ApiClient;
|
|
165
|
+
authClient: AuthClient;
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Wire in router files
|
|
170
|
+
|
|
171
|
+
Both `router.tsx` (client) and `router.server.tsx` (server) must include `authClient` in context:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
context: {
|
|
175
|
+
queryClient,
|
|
176
|
+
authClient: opts.context.authClient,
|
|
177
|
+
apiClient: opts.context.apiClient,
|
|
178
|
+
runtimeConfig: opts.context.runtimeConfig,
|
|
179
|
+
session: opts.context.session,
|
|
180
|
+
},
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Remove runtimeConfig from component props
|
|
184
|
+
|
|
185
|
+
Components no longer need `runtimeConfig` props for auth. They use `useAuthClient()` instead. Remove `runtimeConfig` prop threading from:
|
|
186
|
+
- Route components that pass it to child components
|
|
187
|
+
- Shared components like `UserNav`, `OrgSwitcher`, `RelayFeed`, `NearProfile`
|
|
188
|
+
|
|
189
|
+
## Wallet State and Signing
|
|
190
|
+
|
|
191
|
+
### ensureConnected before signing
|
|
192
|
+
|
|
193
|
+
Wallet extensions (Meteor, HERE) may disconnect after the initial sign-in popup. Always call `ensureConnected()` before any signing operation:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// Relay mode — automatic (buildSignedDelegateAction calls ensureConnected internally)
|
|
197
|
+
const payload = await authClient.near.buildSignedDelegateAction(...);
|
|
198
|
+
|
|
199
|
+
// Direct mode — manual
|
|
200
|
+
await authClient.near.ensureConnected();
|
|
201
|
+
authClient.near.client.transaction(accountId)
|
|
202
|
+
.functionCall(contract, "method", args, opts)
|
|
203
|
+
.send({ waitUntil: "FINAL" });
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### nearState persists accountId across disconnects
|
|
207
|
+
|
|
208
|
+
When the wallet disconnects externally:
|
|
209
|
+
- `getAccountId()` still returns the accountId (from session restore)
|
|
210
|
+
- `isWalletConnected()` returns false
|
|
211
|
+
- `publicKey` is cleared from state
|
|
212
|
+
|
|
213
|
+
This means UI can display the user's NEAR account even when the wallet is disconnected. Signing operations automatically prompt reconnection.
|
|
214
|
+
|
|
215
|
+
## SSR Safety
|
|
216
|
+
|
|
217
|
+
`siwnClient()` is SSR-safe — wallet resources are lazily initialized on first client-side access. On the server they sit dormant. This means `createAuthClient()` can safely run in `router.server.tsx` without accessing browser APIs.
|
|
218
|
+
|
|
219
|
+
Methods that work on server (via `$fetch` only): `nonce`, `verify`, `view`, `relayTransaction`, `getRelayStatus`, `getRelayerInfo`, `relayHistory`, `getProfile`, `listAccounts`.
|
|
220
|
+
|
|
221
|
+
Methods that throw on server: `buildSignedDelegateAction`, `ensureConnected`, `signIn.near`, `link`, `disconnect`.
|
|
222
|
+
|
|
223
|
+
Properties that return defaults on server: `getAccountId()` → `null`, `getState()` → `null`, `isWalletConnected()` → `false`.
|
|
224
|
+
|
|
225
|
+
## File Consolidation
|
|
226
|
+
|
|
227
|
+
Replace three separate files with one `auth.ts`:
|
|
228
|
+
|
|
229
|
+
| Before | After |
|
|
230
|
+
| ------ | ----- |
|
|
231
|
+
| `lib/auth-client.ts` (factory + types) | `auth.ts` (factory + types + hooks + queries) |
|
|
232
|
+
| `lib/session.ts` (query options) | `auth.ts` |
|
|
233
|
+
| `lib/auth-hooks.ts` (relay history hook) | `auth.ts` |
|
|
234
|
+
|
|
235
|
+
The consolidated `auth.ts` is ~80 lines and eliminates all `runtimeConfig` parameter threading.
|
|
236
|
+
|
|
237
|
+
## Common Mistakes
|
|
238
|
+
|
|
239
|
+
### CRITICAL Creating multiple siwnClient instances via factory
|
|
240
|
+
|
|
241
|
+
Wrong:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
function getAuthClient(config) {
|
|
245
|
+
return createAuthClient({
|
|
246
|
+
plugins: [siwnClient({ recipient: getAccount(config) })],
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
// Every call creates new nearState atom — wallet state lost
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Correct:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// Module singleton (CSR)
|
|
256
|
+
export const authClient = createAuthClient({
|
|
257
|
+
plugins: [siwnClient({ recipient: "myapp.near" })],
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// OR: Router context singleton (SSR)
|
|
261
|
+
export function createAuthClient() {
|
|
262
|
+
return createBetterAuthClient({
|
|
263
|
+
plugins: [siwnClient({ recipient: getAccount() })],
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
// Create once in router setup, access via useAuthClient()
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
`siwnClient()` creates stateful singletons: `nearState` atom, `walletConnected` atom, `NearConnector` with event listeners, `Near` instance. Multiple instances means wallet sign-in populates one atom while your app reads from another. Always create exactly one per app lifecycle.
|
|
270
|
+
|
|
271
|
+
Source: src/client.ts:64-72
|
|
272
|
+
|
|
273
|
+
See also: client/SKILL.md — CRITICAL singleton requirement
|
|
274
|
+
|
|
275
|
+
### HIGH Threading runtimeConfig through query options and component props
|
|
276
|
+
|
|
277
|
+
Wrong:
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
// session.ts
|
|
281
|
+
export const sessionQueryOptions = (initialSession, runtimeConfig) => ({
|
|
282
|
+
queryFn: () => getAuthClient(runtimeConfig).getSession(),
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Component
|
|
286
|
+
<UserNav runtimeConfig={runtimeConfig} />
|
|
287
|
+
// Inside UserNav: const auth = getAuthClient(runtimeConfig);
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Correct:
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// auth.ts
|
|
294
|
+
export const sessionQueryOptions = (authClient, initialSession?) => ({
|
|
295
|
+
queryFn: () => authClient.getSession(),
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// Component
|
|
299
|
+
function UserNav() {
|
|
300
|
+
const auth = useAuthClient();
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
`runtimeConfig` was threaded through props and query options solely to create auth client instances. With router context, the auth client is a singleton accessed via `useAuthClient()`. No config threading needed.
|
|
305
|
+
|
|
306
|
+
Source: auth.ts:54-67
|
|
307
|
+
|
|
308
|
+
### HIGH Using near.client.send() without ensureConnected
|
|
309
|
+
|
|
310
|
+
Wrong:
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
authClient.near.client.transaction(accountId)
|
|
314
|
+
.functionCall(contract, "method", args, opts)
|
|
315
|
+
.send(); // fails if wallet disconnected after sign-in
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Correct:
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
await authClient.near.ensureConnected();
|
|
322
|
+
authClient.near.client.transaction(accountId)
|
|
323
|
+
.functionCall(contract, "method", args, opts)
|
|
324
|
+
.send();
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Wallet extensions disconnect between sign-in and subsequent signing. `buildSignedDelegateAction` calls `ensureConnected` automatically, but direct `.send()` does not.
|
|
328
|
+
|
|
329
|
+
Source: src/client.ts:249-253
|
|
330
|
+
|
|
331
|
+
### MEDIUM Module-level singleton in SSR causes cross-request state leaks
|
|
332
|
+
|
|
333
|
+
Wrong (SSR):
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
// Module-level singleton — shared across all server requests
|
|
337
|
+
export const authClient = createAuthClient({
|
|
338
|
+
plugins: [siwnClient({ recipient: "myapp.near" })],
|
|
339
|
+
});
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Correct (SSR):
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
// Factory — one instance per router/request
|
|
346
|
+
export function createAuthClient() {
|
|
347
|
+
return createBetterAuthClient({
|
|
348
|
+
plugins: [siwnClient({ recipient: getAccount() })],
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
// Created in createRouter() context
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
On the server, a module-level singleton's `$fetch` and session state would be shared across concurrent requests. Router context isolates one client per request on server, one per app on client.
|
|
355
|
+
|
|
356
|
+
Source: router.server.tsx:60-71
|