better-near-auth 1.9.0 → 1.10.1

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
@@ -51,37 +51,36 @@ npm install better-near-auth
51
51
  });
52
52
  ```
53
53
 
54
- **Relayer Configuration Options:**
55
-
56
- ```ts
57
- // Ephemeral mode (default) - auto-generated keypair
58
- relayer: true
59
-
60
- // Ephemeral with custom settings
61
- relayer: {
62
- whitelistedContracts: ["myapp.near"],
63
- maxGasPerTransaction: "300000000000000",
64
- maxDepositPerTransaction: "0",
65
- }
66
-
67
- // Explicit mode - bring your own key
68
- relayer: {
69
- accountId: "relayer.myapp.near",
70
- privateKey: process.env.RELAYER_PRIVATE_KEY,
71
- whitelistedContracts: ["myapp.near"],
72
- }
73
-
74
- // Per-network configuration
75
- relayer: {
76
- mainnet: {
77
- whitelistedContracts: ["myapp.near"],
78
- },
79
- testnet: {
80
- whitelistedContracts: ["myapp.testnet"],
81
- maxGasPerTransaction: "100000000000000", // lower for testing
82
- },
83
- }
84
- ```
54
+ **Relayer Configuration Options:**
55
+
56
+ ```ts
57
+ // Ephemeral mode - omit accountId to auto-generate a keypair on first startup
58
+ relayer: {
59
+ whitelistedContracts: ["myapp.near"],
60
+ maxGasPerTransaction: "300000000000000",
61
+ }
62
+
63
+ // Explicit mode - provide accountId and privateKey
64
+ relayer: {
65
+ accountId: "relayer.myapp.near",
66
+ privateKey: process.env.RELAYER_PRIVATE_KEY,
67
+ whitelistedContracts: ["myapp.near"],
68
+ }
69
+
70
+ // Per-network configuration
71
+ relayer: {
72
+ mainnet: {
73
+ accountId: "relayer.myapp.near",
74
+ privateKey: process.env.RELAYER_PRIVATE_KEY_MAINNET,
75
+ },
76
+ testnet: {
77
+ accountId: "relayer.myapp.testnet",
78
+ privateKey: process.env.RELAYER_PRIVATE_KEY_TESTNET,
79
+ },
80
+ }
81
+ ```
82
+
83
+ If `accountId` is set but no `privateKey` is provided, the SIWN plugin logs a warning and falls back to ephemeral mode.
85
84
 
86
85
  3. Generate the schema to add the necessary fields and tables to the database.
87
86
 
@@ -213,42 +212,30 @@ await authClient.near.disconnect();
213
212
 
214
213
  #### Relayer Configuration
215
214
 
216
- The relayer can be configured in several ways:
217
-
218
- | Value | Mode | Description |
219
- |---|---|---|
220
- | `true` | Ephemeral | Auto-generated ED25519 keypair (default) |
221
- | `RelayerEphemeralConfig` | Ephemeral | Ephemeral with custom settings |
222
- | `RelayerExplicitConfig` | Explicit | Bring your own key |
223
- | `RelayerDualNetworkConfig` | Mixed | Per-network configuration |
224
-
225
- **Ephemeral Config (`RelayerEphemeralConfig`):**
215
+ The relayer takes a single flat object (`RelayerConfig`) — `accountId` is the only runtime discriminator. If `accountId` is set, the relayer runs in explicit mode using the resolved `privateKey`. Otherwise, an ED25519 keypair is generated on first startup (ephemeral mode).
226
216
 
227
217
  | Option | Type | Default | Description |
228
218
  |---|---|---|---|
219
+ | `accountId` | `string` | — | Named relayer account. If set, the relayer runs in explicit mode using `privateKey`. |
220
+ | `privateKey` | `string` | — | Base64 / ed25519-format private key. Only used in explicit mode (`accountId` set). |
229
221
  | `whitelistedContracts` | `string[]` | — | Restrict relay to these contracts |
230
222
  | `maxGasPerTransaction` | `string` | — | Max gas per relayed tx |
231
223
  | `maxDepositPerTransaction` | `string` | — | Max deposit per relayed tx |
232
224
 
233
- **Explicit Config (`RelayerExplicitConfig`):**
225
+ To configure mainnet and testnet independently, pass a `RelayerDualNetworkConfig`:
234
226
 
235
- | Option | Type | Default | Description |
236
- |---|---|---|---|
237
- | `accountId` | `string` | — | Named relayer account (required) |
238
- | `privateKey` | `string` | — | Base64 private key (required) |
239
- | `privateKeys` | `string[]` | — | Multiple keys for rotation |
240
- | `whitelistedContracts` | `string[]` | — | Restrict relay to these contracts |
241
- | `maxGasPerTransaction` | `string` | — | Max gas per relayed tx |
242
- | `maxDepositPerTransaction` | `string` | — | Max deposit per relayed tx |
243
-
244
- **Dual Network Config (`RelayerDualNetworkConfig`):**
227
+ ```ts
228
+ siwn({
229
+ relayer: {
230
+ mainnet: { accountId: "relayer.near" },
231
+ testnet: { accountId: "relayer.testnet" },
232
+ },
233
+ });
234
+ ```
245
235
 
246
- | Option | Type | Default | Description |
247
- |---|---|---|---|
248
- | `mainnet` | `RelayerEphemeralConfig \| RelayerExplicitConfig` | — | Mainnet relayer config |
249
- | `testnet` | `RelayerEphemeralConfig \| RelayerExplicitConfig` | — | Testnet relayer config |
236
+ When `accountId` is not set, an ED25519 keypair is generated on first startup, the implicit account ID is derived from the public key, and the private key is encrypted with AES-256-GCM (using `BETTER_AUTH_SECRET` as KEK via HKDF-SHA256) and stored in the database. The same keypair is recovered on restart.
250
237
 
251
- When using `relayer: true` or ephemeral config (no `accountId`/`privateKey`), an ED25519 keypair is generated on first startup, the implicit account ID is derived from the public key, and the private key is encrypted with AES-256-GCM (using `BETTER_AUTH_SECRET` as KEK via HKDF-SHA256) and stored in the database. The same keypair is recovered on restart.
238
+ If `accountId` is set but no `privateKey` is provided, the SIWN plugin logs a warning and falls back to ephemeral mode.
252
239
 
253
240
  ### Client Options
254
241
 
@@ -392,7 +379,7 @@ export const auth = betterAuth({
392
379
  // Ephemeral mode (simplest)
393
380
  relayer: true,
394
381
 
395
- // OR explicit mode
382
+ // OR explicit mode (privateKey provided directly)
396
383
  relayer: {
397
384
  accountId: "relayer.myapp.near",
398
385
  privateKey: process.env.RELAYER_PRIVATE_KEY,
@@ -404,9 +391,13 @@ export const auth = betterAuth({
404
391
  // OR per-network configuration
405
392
  relayer: {
406
393
  mainnet: {
394
+ accountId: "relayer.myapp.near",
395
+ privateKey: process.env.RELAYER_PRIVATE_KEY_MAINNET,
407
396
  whitelistedContracts: ["myapp.near"],
408
397
  },
409
398
  testnet: {
399
+ accountId: "relayer.myapp.testnet",
400
+ privateKey: process.env.RELAYER_PRIVATE_KEY_TESTNET,
410
401
  whitelistedContracts: ["myapp.testnet"],
411
402
  maxGasPerTransaction: "100000000000000",
412
403
  },
@@ -451,8 +442,9 @@ The plugin detects the network from the account ID:
451
442
  | Relay fails with "insufficient balance" | Fund the relayer account with NEAR |
452
443
  | Relay fails with "contract not whitelisted" | Add `receiverId` to `whitelistedContracts` |
453
444
  | Relayer not initializing (ephemeral mode) | Ensure `BETTER_AUTH_SECRET` is set; check startup logs for `[siwn] Relayer initialized` |
454
- | Empty `relayer_key` table | Relayer config not being passed; use `relayer: true` or provide config object |
445
+ | Empty `relayer_key` table | Relayer config not being passed; omit `accountId` to use ephemeral mode |
455
446
  | "BETTER_AUTH_SECRET required" error | Required for ephemeral mode encryption; generate a secure random string |
447
+ | `accountId` set but mode shows `ephemeral` | Your `privateKey` was not passed to the SIWN plugin — provide it directly or via the host's per-network private key secret |
456
448
 
457
449
  ## Examples
458
450
 
package/dist/index.d.ts CHANGED
@@ -2,26 +2,18 @@ import type { DBAdapter } from "better-auth/types";
2
2
  import z from "zod";
3
3
  import { type AccountId, type DualNetworkConfig, type ListAccountsResponseT, type ListedNearAccount, type Profile, type SubAccountConfig } from "./types.js";
4
4
  export * from "./types.js";
5
- interface RelayerEphemeralConfig {
6
- accountId?: never;
7
- privateKey?: never;
8
- whitelistedContracts?: string[];
9
- maxGasPerTransaction?: string;
10
- maxDepositPerTransaction?: string;
11
- }
12
- interface RelayerExplicitConfig {
13
- accountId: string;
14
- privateKey: string;
15
- privateKeys?: string[];
5
+ interface RelayerConfig {
6
+ accountId?: string;
7
+ privateKey?: string;
16
8
  whitelistedContracts?: string[];
17
9
  maxGasPerTransaction?: string;
18
10
  maxDepositPerTransaction?: string;
19
11
  }
20
12
  interface RelayerDualNetworkConfig {
21
- mainnet?: RelayerEphemeralConfig | RelayerExplicitConfig;
22
- testnet?: RelayerEphemeralConfig | RelayerExplicitConfig;
13
+ mainnet?: RelayerConfig;
14
+ testnet?: RelayerConfig;
23
15
  }
24
- export type RelayerConfig = true | RelayerEphemeralConfig | RelayerExplicitConfig | RelayerDualNetworkConfig;
16
+ export type { RelayerConfig, RelayerDualNetworkConfig };
25
17
  export interface SIWNPluginOptions {
26
18
  recipient?: string;
27
19
  recipients?: DualNetworkConfig<string>;
@@ -35,7 +27,7 @@ export interface SIWNPluginOptions {
35
27
  }) => Promise<boolean>;
36
28
  apiKey?: string;
37
29
  rpcUrl?: string | DualNetworkConfig<string>;
38
- relayer?: RelayerConfig | DualNetworkConfig<RelayerConfig>;
30
+ relayer?: RelayerConfig | RelayerDualNetworkConfig;
39
31
  secrets?: {
40
32
  parentKey?: string | DualNetworkConfig<string>;
41
33
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { APIError, createAuthEndpoint, createAuthMiddleware, getSessionFromCtx, sessionMiddleware } from "better-auth/api";
2
2
  import { setSessionCookie } from "better-auth/cookies";
3
- import { InMemoryKeyStore, Near, RotatingKeyStore, decodeSignedDelegateAction, generateKey, generateNonce, parseKey, verifyNep413Signature } from "near-kit";
3
+ import { InMemoryKeyStore, Near, decodeSignedDelegateAction, generateKey, generateNonce, parseKey, verifyNep413Signature } from "near-kit";
4
4
  import { base58, hex } from "@scure/base";
5
5
  import z$1, { z } from "zod";
6
6
  import { AccountIdSchema } from "near-kit/schemas";
@@ -362,6 +362,9 @@ function buildListAccountsResponse(nearAccounts) {
362
362
  availableAccounts: accounts.filter((account) => account.isAvailable).map((account) => ({ ...account }))
363
363
  };
364
364
  }
365
+ function isRelayerDualNetworkConfig(cfg) {
366
+ return typeof cfg === "object" && cfg !== null && "mainnet" in cfg && typeof cfg.mainnet === "object";
367
+ }
365
368
  function createNear(network, headers, rpcUrl, keyStore) {
366
369
  const config = { headers };
367
370
  if (rpcUrl) config.network = {
@@ -377,19 +380,12 @@ async function initRelayer(relayerConfig, network, adapter, secret, apiKey, rpcU
377
380
  const headers = {};
378
381
  if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
379
382
  let networkConfig;
380
- if (relayerConfig === true) networkConfig = {};
381
- else if ("mainnet" in relayerConfig || "testnet" in relayerConfig) {
382
- const dualConfig = relayerConfig;
383
- networkConfig = network === "mainnet" ? dualConfig.mainnet : dualConfig.testnet;
384
- if (!networkConfig) return null;
385
- } else networkConfig = relayerConfig;
386
- if ("accountId" in networkConfig && networkConfig.accountId && (networkConfig.privateKey || networkConfig.privateKeys)) {
387
- const keys = networkConfig.privateKeys ?? (networkConfig.privateKey ? [networkConfig.privateKey] : []);
388
- let keyStore;
389
- if (keys.length === 1) keyStore = new InMemoryKeyStore({ [networkConfig.accountId]: keys[0] });
390
- else keyStore = new RotatingKeyStore({ [networkConfig.accountId]: keys });
391
- const near = createNear(network, headers, rpcUrl, keyStore);
392
- const explicitPublicKey = parseKey(keys[0]);
383
+ if (isRelayerDualNetworkConfig(relayerConfig)) networkConfig = network === "mainnet" ? relayerConfig.mainnet : relayerConfig.testnet;
384
+ else networkConfig = relayerConfig;
385
+ if (!networkConfig) return null;
386
+ if (networkConfig.accountId && networkConfig.privateKey) {
387
+ const near = createNear(network, headers, rpcUrl, new InMemoryKeyStore({ [networkConfig.accountId]: networkConfig.privateKey }));
388
+ const explicitPublicKey = parseKey(networkConfig.privateKey);
393
389
  return {
394
390
  near,
395
391
  accountId: networkConfig.accountId,
@@ -401,6 +397,7 @@ async function initRelayer(relayerConfig, network, adapter, secret, apiKey, rpcU
401
397
  maxDepositPerTransaction: networkConfig.maxDepositPerTransaction
402
398
  };
403
399
  }
400
+ if (networkConfig.accountId && !networkConfig.privateKey) console.warn(`[siwn] Relayer accountId "${networkConfig.accountId}" is set for ${network} but no privateKey was provided. Falling back to ephemeral mode. Set the relayer privateKey in your SIWN plugin options to use explicit mode.`);
404
401
  const existing = await adapter.findOne({
405
402
  model: "relayerKey",
406
403
  where: [{
@@ -510,8 +507,7 @@ const siwn = (options) => {
510
507
  };
511
508
  const getRelayerConfig = (network) => {
512
509
  if (!options.relayer) return void 0;
513
- if (options.relayer === true) return true;
514
- if ("mainnet" in options.relayer || "testnet" in options.relayer) return options.relayer[network];
510
+ if (isRelayerDualNetworkConfig(options.relayer)) return options.relayer[network];
515
511
  return options.relayer;
516
512
  };
517
513
  const getRpcUrl = (network) => {
@@ -534,11 +530,9 @@ const siwn = (options) => {
534
530
  if (fromSecrets) return fromSecrets;
535
531
  const relayerCfg = getRelayerConfig(network);
536
532
  const subAccountCfg = getSubAccountConfig(network);
537
- if (!relayerCfg || relayerCfg === true) return void 0;
538
- if ("mainnet" in relayerCfg || "testnet" in relayerCfg) return void 0;
539
- const explicitCfg = relayerCfg;
540
- const parent = subAccountCfg?.parentAccount ?? explicitCfg.accountId;
541
- if (parent && parent === explicitCfg.accountId) return explicitCfg.privateKey ?? explicitCfg.privateKeys?.[0];
533
+ if (!relayerCfg || !relayerCfg.accountId || !relayerCfg.privateKey) return void 0;
534
+ const parent = subAccountCfg?.parentAccount ?? relayerCfg.accountId;
535
+ if (parent && parent === relayerCfg.accountId) return relayerCfg.privateKey;
542
536
  };
543
537
  const primaryNetwork = getSupportedNetworks()[0];
544
538
  const relayerStates = /* @__PURE__ */ new Map();
@@ -1178,16 +1172,14 @@ const siwn = (options) => {
1178
1172
  status: 401
1179
1173
  });
1180
1174
  const relayerConfigForNetwork = getRelayerConfig(network);
1181
- const isDualNetwork = relayerConfigForNetwork && typeof relayerConfigForNetwork === "object" && ("mainnet" in relayerConfigForNetwork || "testnet" in relayerConfigForNetwork);
1182
- const configWithLimits = relayerConfigForNetwork && typeof relayerConfigForNetwork === "object" && !isDualNetwork ? relayerConfigForNetwork : void 0;
1183
- const whitelistedContracts = configWithLimits?.whitelistedContracts;
1175
+ const whitelistedContracts = relayerConfigForNetwork?.whitelistedContracts;
1184
1176
  if (whitelistedContracts?.length) {
1185
1177
  if (!whitelistedContracts.includes(delegateAction.receiverId)) throw new APIError("FORBIDDEN", {
1186
1178
  message: `Contract ${delegateAction.receiverId} is not whitelisted for relay`,
1187
1179
  status: 403
1188
1180
  });
1189
1181
  }
1190
- const maxGasPerTransaction = configWithLimits?.maxGasPerTransaction;
1182
+ const maxGasPerTransaction = relayerConfigForNetwork?.maxGasPerTransaction;
1191
1183
  if (maxGasPerTransaction) {
1192
1184
  const totalGas = delegateAction.actions.reduce((sum, a) => {
1193
1185
  return sum + ("functionCall" in a ? a.functionCall.gas : 0n);
@@ -1197,7 +1189,7 @@ const siwn = (options) => {
1197
1189
  status: 400
1198
1190
  });
1199
1191
  }
1200
- const maxDepositPerTransaction = configWithLimits?.maxDepositPerTransaction;
1192
+ const maxDepositPerTransaction = relayerConfigForNetwork?.maxDepositPerTransaction;
1201
1193
  if (maxDepositPerTransaction) {
1202
1194
  const totalDeposit = delegateAction.actions.reduce((sum, a) => {
1203
1195
  if ("functionCall" in a) return sum + a.functionCall.deposit;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["z"],"sources":["../src/profile.ts","../src/schema.ts","../src/types.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["import type { AccountId, Profile, SocialImage } from \"./types.js\";\n\nconst FALLBACK_URL =\n\t\"https://ipfs.near.social/ipfs/bafkreidn5fb2oygegqaldx7ycdmhu4owcrmoxd7ekbzfmeakkobz2ja7qy\";\n\nfunction getNetworkFromAccountId(accountId: string): \"mainnet\" | \"testnet\" {\n\treturn accountId.endsWith('.testnet') ? 'testnet' : 'mainnet';\n}\n\nfunction getImageUrl(\n\timage: SocialImage | undefined,\n\tfallback?: string,\n): string {\n\tif (image?.url) return image.url;\n\tif (image?.ipfs_cid) return `https://ipfs.near.social/ipfs/${image.ipfs_cid}`;\n\treturn fallback || FALLBACK_URL;\n}\n\ninterface SocialApiResponse {\n\t[accountId: string]: {\n\t\tprofile?: Profile;\n\t};\n}\n\ninterface KvEntry {\n\tvalue: Record<string, unknown> | string;\n\tblock_height?: number;\n\tblock_hash?: string;\n\ttimestamp_nanosec?: string;\n}\n\ninterface KvResponse {\n\tentries: KvEntry[];\n}\n\nasync function defaultGetProfile(accountId: AccountId, apiKey?: string): Promise<Profile | null> {\n\tconst network = getNetworkFromAccountId(accountId);\n\n\ttry {\n\t\tconst kvUrl = network === \"testnet\"\n\t\t\t? \"https://kv.test.fastnear.com\"\n\t\t\t: \"https://kv.main.fastnear.com\";\n\n\t\tconst effectiveApiKey = apiKey || process.env.FASTNEAR_API_KEY;\n\t\tconst headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n\t\tif (effectiveApiKey) {\n\t\t\theaders[\"Authorization\"] = `Bearer ${effectiveApiKey}`;\n\t\t}\n\n\t\tconst response = await fetch(\n\t\t\t`${kvUrl}/v0/latest/social.near/${accountId}/profile/**`,\n\t\t\t{ headers },\n\t\t);\n\n\t\tif (response.ok) {\n\t\t\tconst data = await response.json() as KvResponse;\n\t\t\tconst entry = data?.entries?.[0];\n\t\t\tif (entry?.value) {\n\t\t\t\ttry {\n\t\t\t\t\tconst profile = typeof entry.value === \"string\"\n\t\t\t\t\t\t? JSON.parse(entry.value)\n\t\t\t\t\t\t: entry.value;\n\t\t\t\t\tif (profile?.name || profile?.description || profile?.image) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tname: profile.name,\n\t\t\t\t\t\t\tdescription: profile.description,\n\t\t\t\t\t\t\timage: profile.image,\n\t\t\t\t\t\t\tbackgroundImage: profile.backgroundImage,\n\t\t\t\t\t\t\tlinktree: profile.linktree,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\n\t\tconst apiBase = {\n\t\t\tmainnet: \"https://api.near.social\",\n\t\t\ttestnet: \"https://test.api.near.social\",\n\t\t}[network];\n\n\t\tconst keys = [`${accountId}/profile/**`];\n\n\t\tconst fallbackResponse = await fetch(`${apiBase}/get`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ keys })\n\t\t});\n\n\t\tif (!fallbackResponse.ok) {\n\t\t\tthrow new Error(`HTTP error! status: ${fallbackResponse.status}`);\n\t\t}\n\n\t\tconst fallbackData = await fallbackResponse.json() as SocialApiResponse;\n\t\tconst profile: Profile | undefined = fallbackData?.[accountId]?.profile;\n\n\t\tif (profile) {\n\t\t\treturn {\n\t\t\t\tname: profile.name,\n\t\t\t\tdescription: profile.description,\n\t\t\t\timage: profile.image,\n\t\t\t\tbackgroundImage: profile.backgroundImage,\n\t\t\t\tlinktree: profile.linktree\n\t\t\t};\n\t\t}\n\t\treturn null;\n\t} catch (error) {\n\t\treturn null;\n\t}\n}\n\nexport { defaultGetProfile, getImageUrl, getNetworkFromAccountId };\n","import type { BetterAuthPluginDBSchema } from \"better-auth/db\";\n\nexport const schema = {\n\tnearAccount: {\n\t\tfields: {\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\taccountId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tnetwork: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tpublicKey: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tisPrimary: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdefaultValue: false,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t},\n\t},\n\trelayedTransaction: {\n\t\tfields: {\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t},\n\t\t\ttxHash: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tsenderId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\treceiverId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tnetwork: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tstatus: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tgasUsed: {\n\t\t\t\ttype: \"string\",\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tupdatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t},\n\t\t},\n\t},\n\trelayerKey: {\n\t\tfields: {\n\t\t\taccountId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tencryptedPrivateKey: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tiv: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tpublicKey: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tnetwork: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tlastUsedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n","import { z } from \"zod\";\nimport { AccountIdSchema, type AccountId } from \"near-kit/schemas\";\nimport type { AccountState, Near, TransactionBuilder } from \"near-kit\";\n\nexport type { AccountId };\n\nexport interface NearAccount {\n\tid: string;\n\tuserId: string;\n\taccountId: string;\n\tnetwork: \"mainnet\" | \"testnet\";\n\tpublicKey: string;\n\tisPrimary: boolean;\n\tcreatedAt: Date;\n}\n\nexport interface ListedNearAccount extends NearAccount {\n\tproviderId: \"siwn\";\n\tisActive: boolean;\n\tisAvailable: boolean;\n}\n\nexport interface ListAccountsResponseT {\n\taccounts: ListedNearAccount[];\n\tactiveAccount: ListedNearAccount | null;\n\tavailableAccounts: ListedNearAccount[];\n}\n\nexport interface SetPrimaryAccountResponseT extends ListAccountsResponseT {\n\tsuccess: boolean;\n\taccountId: string;\n\tnetwork: \"mainnet\" | \"testnet\";\n\tmessage: string;\n}\n\nexport const socialImageSchema = z.object({\n\turl: z.string().optional(),\n\tipfs_cid: z.string().optional(),\n});\n\nexport const profileSchema = z.object({\n\tname: z.string().optional(),\n\tdescription: z.string().optional(),\n\timage: socialImageSchema.optional(),\n\tbackgroundImage: socialImageSchema.optional(),\n\tlinktree: z.record(z.string(), z.string()).optional(),\n});\n\nexport type SocialImage = z.infer<typeof socialImageSchema>;\nexport type Profile = z.infer<typeof profileSchema>;\n\nconst signedMessageSchema = z.object({\n\taccountId: z.string(),\n\tpublicKey: z.string(),\n\tsignature: z.string(),\n\tstate: z.string().optional(),\n});\n\nexport const LinkAccountRequest = z.object({\n\tsignedMessage: signedMessageSchema,\n\tmessage: z.string(),\n\trecipient: z.string(),\n\tnonce: z.string(),\n\taccountId: AccountIdSchema,\n\tcallbackUrl: z.string().optional(),\n});\n\nexport const SetPrimaryAccountRequest = z.object({\n\taccountId: AccountIdSchema,\n\tnetwork: z.enum([\"mainnet\", \"testnet\"]).optional(),\n});\n\nexport const NonceRequest = z.object({\n\taccountId: AccountIdSchema,\n\tnetworkId: z.union([z.literal(\"mainnet\"), z.literal(\"testnet\")])\n});\n\nexport const VerifyRequest = z.object({\n\tsignedMessage: signedMessageSchema,\n\tmessage: z.string(),\n\trecipient: z.string(),\n\tnonce: z.string(),\n\taccountId: AccountIdSchema,\n\tcallbackUrl: z.string().optional(),\n});\n\nexport const RelayRequest = z.object({\n\tpayload: z.string(),\n});\nexport type RelayRequestT = z.infer<typeof RelayRequest>;\n\nexport const RelayResponse = z.object({\n\ttxHash: z.string(),\n\tstatus: z.enum([\"pending\", \"completed\", \"failed\"]),\n});\nexport type RelayResponseT = z.infer<typeof RelayResponse>;\n\nexport const RelayStatusResponse = z.object({\n\tstatus: z.enum([\"pending\", \"completed\", \"failed\"]),\n\tgasUsed: z.string().optional(),\n\toutcome: z.unknown().optional(),\n});\nexport type RelayStatusResponseT = z.infer<typeof RelayStatusResponse>;\n\nexport const ViewContractRequest = z.object({\n\tcontractId: z.string(),\n\tmethodName: z.string(),\n\targs: z.record(z.string(), z.any()).optional(),\n});\nexport type ViewContractRequestT = z.infer<typeof ViewContractRequest>;\n\nexport const NonceResponse = z.object({ nonce: z.string() });\nexport const VerifyResponse = z.object({\n\ttoken: z.string(),\n\tsuccess: z.literal(true),\n\tuser: z.object({\n\t\tid: z.string(),\n\t\taccountId: AccountIdSchema,\n\t\tnetwork: z.union([z.literal(\"mainnet\"), z.literal(\"testnet\")]),\n\t}),\n});\nexport const ProfileResponse = profileSchema.nullable();\nexport const ViewContractResponse = z.object({ result: z.unknown() });\n\nexport const ProfileRequest = z.object({\n\taccountId: AccountIdSchema.optional(),\n});\nexport type ProfileRequestT = z.infer<typeof ProfileRequest>;\n\nexport type NonceRequestT = z.infer<typeof NonceRequest>;\nexport type NonceResponseT = z.infer<typeof NonceResponse>;\nexport type SetPrimaryAccountRequestT = z.infer<typeof SetPrimaryAccountRequest>;\nexport type VerifyRequestT = z.infer<typeof VerifyRequest>;\nexport type VerifyResponseT = z.infer<typeof VerifyResponse>;\nexport type ProfileResponseT = z.infer<typeof ProfileResponse>;\nexport type ViewContractResponseT = z.infer<typeof ViewContractResponse>;\n\nexport const RelayedTransactionSchema = z.object({\n\tid: z.string(),\n\tuserId: z.string(),\n\ttxHash: z.string(),\n\tsenderId: z.string(),\n\treceiverId: z.string(),\n\tnetwork: z.string(),\n\tstatus: z.string(),\n\tgasUsed: z.string().optional(),\n\tcreatedAt: z.string(),\n\tupdatedAt: z.string().optional(),\n});\nexport type RelayedTransactionT = z.infer<typeof RelayedTransactionSchema>;\n\nexport const RelayHistoryResponse = z.object({\n\ttransactions: z.array(RelayedTransactionSchema),\n});\nexport type RelayHistoryResponseT = z.infer<typeof RelayHistoryResponse>;\n\nexport interface RelayedTransactionRecord {\n\tid: string;\n\tuserId: string;\n\ttxHash: string;\n\tsenderId: string;\n\treceiverId: string;\n\tnetwork: \"mainnet\" | \"testnet\";\n\tstatus: string;\n\tgasUsed?: string;\n\tcreatedAt: Date;\n\tupdatedAt: Date;\n}\n\nexport interface RelayerInfo extends AccountState {\n\taccountId: string;\n\tmode: \"ephemeral\" | \"explicit\";\n\tnetwork: \"mainnet\" | \"testnet\";\n\tpublicKey: string;\n\thasKey: boolean;\n\tcreatedAt?: Date;\n\tlastUsedAt?: Date;\n\tparentAccount?: string;\n\tsubAccountAvailable?: boolean;\n}\n\nexport interface DualNetworkConfig<T> {\n\tmainnet: T;\n\ttestnet: T;\n}\n\nexport const GetRelayerInfoRequest = z.object({\n\tnetwork: z.enum([\"mainnet\", \"testnet\"]).optional(),\n});\nexport type GetRelayerInfoRequestT = z.infer<typeof GetRelayerInfoRequest>;\n\nexport interface SubAccountRelayerFCAKConfig {\n\treceiverId: string;\n\tmethodNames?: string[];\n\tallowance?: string;\n}\n\nexport interface SubAccountTxCtx {\n\tnewAccountId: string;\n\tparentAccount: string;\n\tuserPublicKey: string;\n\tuserAccountId: string;\n\tuserId: string;\n\tnetwork: \"mainnet\" | \"testnet\";\n}\n\nexport interface SubAccountLifecycleCtx extends SubAccountTxCtx {\n\tnear: Near;\n}\n\nexport interface SubAccountConfig {\n\tparentAccount?: string;\n\tminDeposit?: string;\n\tparentHasFullAccess?: boolean;\n\tdeploy?:\n\t\t| { wasm: Uint8Array }\n\t\t| { fromPublished: { accountId?: string; codeHash?: string } };\n\tinit?: {\n\t\tmethodName: string;\n\t\targs: object | ((ctx: SubAccountTxCtx) => object);\n\t};\n\textendTx?: (tx: TransactionBuilder, ctx: SubAccountTxCtx) => TransactionBuilder;\n\tonCreated?: (ctx: SubAccountLifecycleCtx) => Promise<void>;\n\tonRollback?: (ctx: SubAccountLifecycleCtx) => Promise<void>;\n\taddRelayerFCAK?: boolean;\n\trelayerFCAK?: SubAccountRelayerFCAKConfig;\n}\n\nexport const SUB_ACCOUNT_LABEL_REGEX = /^([a-z\\d]+[-_])*[a-z\\d]+$/;\n\nexport const SubAccountNameSchema = z\n\t.string()\n\t.min(2, \"Sub-account name must be at least 2 characters\")\n\t.max(64, \"Sub-account name must be at most 64 characters\")\n\t.regex(SUB_ACCOUNT_LABEL_REGEX, \"Sub-account name must contain only lowercase alphanumeric characters, hyphens, and underscores (no leading/trailing hyphens or underscores)\");\n\nexport const CreateSubAccountRequest = z.object({\n\tsubAccountName: SubAccountNameSchema,\n\tnetwork: z.enum([\"mainnet\", \"testnet\"]).optional(),\n\tpublicKey: z.string(),\n});\nexport type CreateSubAccountRequestT = z.infer<typeof CreateSubAccountRequest>;\n\nexport const CreateSubAccountResponse = z.object({\n\tsuccess: z.literal(true),\n\taccountId: z.string(),\n\tnetwork: z.enum([\"mainnet\", \"testnet\"]),\n\tpublicKey: z.string(),\n\tmessage: z.string(),\n});\nexport type CreateSubAccountResponseT = z.infer<typeof CreateSubAccountResponse>;\n\nexport const CheckSubAccountAvailabilityRequest = z.object({\n\tsubAccountName: SubAccountNameSchema,\n\tnetwork: z.enum([\"mainnet\", \"testnet\"]).optional(),\n});\nexport type CheckSubAccountAvailabilityRequestT = z.infer<typeof CheckSubAccountAvailabilityRequest>;\n\nexport const CheckSubAccountAvailabilityResponse = z.object({\n\tavailable: z.boolean(),\n\taccountId: z.string(),\n\tparentAccount: z.string().optional(),\n\treason: z.enum([\"taken\", \"invalid\", \"too-long\", \"not-configured\"]).optional(),\n});\nexport type CheckSubAccountAvailabilityResponseT = z.infer<typeof CheckSubAccountAvailabilityResponse>;\n","export function bytesToBase64(bytes: Uint8Array): string {\n\treturn btoa(String.fromCharCode(...bytes));\n}\n\nfunction base64ToBytes(base64: string): Uint8Array {\n\treturn Uint8Array.from(atob(base64), c => c.charCodeAt(0));\n}\n\nexport function bytesToHex(bytes: Uint8Array): string {\n\treturn Array.from(bytes).map(b => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport function hexToBytes(hex: string): Uint8Array {\n\tconst bytes = new Uint8Array(hex.length / 2);\n\tfor (let i = 0; i < hex.length; i += 2) {\n\t\tbytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);\n\t}\n\treturn bytes;\n}\n\nasync function deriveAesKey(secret: string): Promise<CryptoKey> {\n\tconst keyMaterial = await crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tnew TextEncoder().encode(secret),\n\t\t{ name: \"HKDF\" },\n\t\tfalse,\n\t\t[\"deriveKey\"],\n\t);\n\treturn crypto.subtle.deriveKey(\n\t\t{\n\t\t\tname: \"HKDF\",\n\t\t\thash: \"SHA-256\",\n\t\t\tsalt: new TextEncoder().encode(\"better-near-auth-relayer\"),\n\t\t\tinfo: new Uint8Array(0),\n\t\t},\n\t\tkeyMaterial,\n\t\t{ name: \"AES-GCM\", length: 256 },\n\t\tfalse,\n\t\t[\"encrypt\", \"decrypt\"],\n\t);\n}\n\nexport async function encryptPrivateKey(\n\tprivateKey: Uint8Array,\n\tsecret: string,\n): Promise<{ encrypted: string; iv: string }> {\n\tconst aesKey = await deriveAesKey(secret);\n\tconst iv = crypto.getRandomValues(new Uint8Array(12));\n\tconst encrypted = await crypto.subtle.encrypt(\n\t\t{ name: \"AES-GCM\", iv },\n\t\taesKey,\n\t\tprivateKey as Uint8Array<ArrayBuffer>,\n\t);\n\treturn {\n\t\tencrypted: bytesToBase64(new Uint8Array(encrypted)),\n\t\tiv: bytesToBase64(iv),\n\t};\n}\n\nexport async function decryptPrivateKey(\n\tencrypted: string,\n\tiv: string,\n\tsecret: string,\n): Promise<Uint8Array> {\n\tconst aesKey = await deriveAesKey(secret);\n\tconst decrypted = await crypto.subtle.decrypt(\n\t\t{ name: \"AES-GCM\", iv: base64ToBytes(iv) as Uint8Array<ArrayBuffer> },\n\t\taesKey,\n\t\tbase64ToBytes(encrypted) as Uint8Array<ArrayBuffer>,\n\t);\n\treturn new Uint8Array(decrypted);\n}\n","import { APIError, createAuthEndpoint, createAuthMiddleware, getSessionFromCtx, sessionMiddleware } from \"better-auth/api\";\nimport { setSessionCookie } from \"better-auth/cookies\";\nimport type { Account, User, DBAdapter } from \"better-auth/types\";\n// Explicit type imports for declaration emit\nimport type {} from \"@better-auth/core/env\";\nimport type {} from \"@better-auth/core/oauth2\";\nimport type {} from \"better-call\";\n\nimport { Near, generateNonce, generateKey, parseKey, verifyNep413Signature, decodeSignedDelegateAction, InMemoryKeyStore, RotatingKeyStore } from \"near-kit\";\nimport type { SignedDelegateAction, PrivateKey } from \"near-kit\";\nimport { hex, base58 } from \"@scure/base\";\nimport z from \"zod\";\nimport { defaultGetProfile, getImageUrl, getNetworkFromAccountId } from \"./profile.js\";\nimport { schema } from \"./schema.js\";\nimport {\n\ttype AccountId,\n\ttype DualNetworkConfig,\n\ttype ListAccountsResponseT,\n\ttype ListedNearAccount,\n\ttype NearAccount,\n\ttype Profile,\n\ttype RelayerInfo,\n\ttype RelayedTransactionRecord,\n\ttype SubAccountConfig,\n\tLinkAccountRequest,\n\tNonceRequest,\n\tNonceResponse,\n\tProfileRequest,\n\tProfileResponse,\n\tVerifyRequest,\n\tVerifyResponse,\n\tRelayRequest,\n\tRelayResponse,\n\tRelayStatusResponse,\n\tSetPrimaryAccountRequest,\n\tViewContractRequest,\n\tViewContractResponse,\n\tGetRelayerInfoRequest,\n\tCreateSubAccountRequest,\n\tCreateSubAccountResponse,\n\tCheckSubAccountAvailabilityRequest,\n\tCheckSubAccountAvailabilityResponse,\n\ttype SubAccountTxCtx,\n\ttype SubAccountLifecycleCtx,\n} from \"./types.js\";\nexport * from \"./types.js\";\nimport {\n\tbytesToHex,\n\tencryptPrivateKey,\n\tdecryptPrivateKey,\n} from \"./utils.js\";\n\nasync function hashNonce(nonce: Uint8Array): Promise<string> {\n\tconst data = new TextEncoder().encode(hex.encode(nonce));\n\tconst hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\treturn hex.encode(new Uint8Array(hashBuffer));\n}\n\nfunction deriveEmail(accountId: string, recipient: string): string {\n\tif (accountId.endsWith(\".near\")) {\n\t\tconst localPart = accountId.slice(0, -5);\n\t\tif (!localPart.includes(\".\")) {\n\t\t\treturn `${localPart}@near.email`;\n\t\t}\n\t}\n\tconst randomId = crypto.randomUUID().slice(0, 8);\n\treturn `temp-${randomId}@${recipient}`;\n}\n\nfunction nearAccountKey(account: Pick<NearAccount, \"accountId\" | \"network\">): string {\n\treturn `${account.accountId}:${account.network}`;\n}\n\nfunction getCreatedAtTime(account: NearAccount): number {\n\treturn account.createdAt instanceof Date\n\t\t? account.createdAt.getTime()\n\t\t: new Date(account.createdAt).getTime();\n}\n\nfunction buildListAccountsResponse(nearAccounts: NearAccount[]): ListAccountsResponseT {\n\tconst activeAccount = nearAccounts.find((account) => account.isPrimary) ?? nearAccounts[0] ?? null;\n\tconst activeKey = activeAccount ? nearAccountKey(activeAccount) : null;\n\tconst accounts: ListedNearAccount[] = nearAccounts\n\t\t.map((account) => {\n\t\t\tconst isActive = activeKey === nearAccountKey(account);\n\t\t\treturn {\n\t\t\t\t...account,\n\t\t\t\tproviderId: \"siwn\" as const,\n\t\t\t\tisActive,\n\t\t\t\tisAvailable: !isActive,\n\t\t\t};\n\t\t})\n\t\t.sort((a, b) => {\n\t\t\tif (a.isActive !== b.isActive) return a.isActive ? -1 : 1;\n\t\t\treturn getCreatedAtTime(a) - getCreatedAtTime(b);\n\t\t});\n\tconst listedActiveAccount = accounts.find((account) => account.isActive) ?? null;\n\n\treturn {\n\t\taccounts,\n\t\tactiveAccount: listedActiveAccount ? { ...listedActiveAccount } : null,\n\t\tavailableAccounts: accounts\n\t\t\t.filter((account) => account.isAvailable)\n\t\t\t.map((account) => ({ ...account })),\n\t};\n}\n\ninterface RelayerEphemeralConfig {\n\taccountId?: never;\n\tprivateKey?: never;\n\twhitelistedContracts?: string[];\n\tmaxGasPerTransaction?: string;\n\tmaxDepositPerTransaction?: string;\n}\n\ninterface RelayerExplicitConfig {\n\taccountId: string;\n\tprivateKey: string;\n\tprivateKeys?: string[];\n\twhitelistedContracts?: string[];\n\tmaxGasPerTransaction?: string;\n\tmaxDepositPerTransaction?: string;\n}\n\ninterface RelayerDualNetworkConfig {\n\tmainnet?: RelayerEphemeralConfig | RelayerExplicitConfig;\n\ttestnet?: RelayerEphemeralConfig | RelayerExplicitConfig;\n}\n\nexport type RelayerConfig =\n\t| true\n\t| RelayerEphemeralConfig\n\t| RelayerExplicitConfig\n\t| RelayerDualNetworkConfig;\n\ninterface RelayerState {\n\tnear: Near;\n\taccountId: string;\n\tnetwork: \"mainnet\" | \"testnet\";\n\tmode: \"ephemeral\" | \"explicit\";\n\tpublicKey: string;\n\twhitelistedContracts?: string[];\n\tmaxGasPerTransaction?: string;\n\tmaxDepositPerTransaction?: string;\n\tcreatedAt?: Date;\n\tlastUsedAt?: Date;\n}\n\nfunction createNear(\n\tnetwork: \"mainnet\" | \"testnet\",\n\theaders: Record<string, string>,\n\trpcUrl?: string,\n\tkeyStore?: InMemoryKeyStore | RotatingKeyStore,\n): Near {\n\tconst config: ConstructorParameters<typeof Near>[0] = { headers };\n\tif (rpcUrl) {\n\t\tconfig.network = { rpcUrl, networkId: network };\n\t} else {\n\t\tconfig.network = network;\n\t}\n\tif (keyStore) {\n\t\tconfig.keyStore = keyStore;\n\t}\n\treturn new Near(config);\n}\n\nasync function initRelayer(\n\trelayerConfig: RelayerConfig | undefined,\n\tnetwork: \"mainnet\" | \"testnet\",\n\tadapter: DBAdapter,\n\tsecret: string | undefined,\n\tapiKey?: string,\n\trpcUrl?: string,\n): Promise<RelayerState | null> {\n\tif (!relayerConfig) return null;\n\n\tconst headers: Record<string, string> = {};\n\tif (apiKey) {\n\t\theaders[\"Authorization\"] = `Bearer ${apiKey}`;\n\t}\n\n\tlet networkConfig: RelayerEphemeralConfig | RelayerExplicitConfig | undefined;\n\t\n\tif (relayerConfig === true) {\n\t\tnetworkConfig = {};\n\t} else if (\"mainnet\" in relayerConfig || \"testnet\" in relayerConfig) {\n\t\tconst dualConfig = relayerConfig as RelayerDualNetworkConfig;\n\t\tnetworkConfig = network === \"mainnet\" ? dualConfig.mainnet : dualConfig.testnet;\n\t\tif (!networkConfig) return null;\n\t} else {\n\t\tnetworkConfig = relayerConfig as RelayerEphemeralConfig | RelayerExplicitConfig;\n\t}\n\n\tif (\"accountId\" in networkConfig && networkConfig.accountId && (networkConfig.privateKey || networkConfig.privateKeys)) {\n\t\tconst keys = networkConfig.privateKeys ?? (networkConfig.privateKey ? [networkConfig.privateKey] : []);\n\t\tlet keyStore: InMemoryKeyStore | RotatingKeyStore;\n\n\t\tif (keys.length === 1) {\n\t\t\tkeyStore = new InMemoryKeyStore({\n\t\t\t\t[networkConfig.accountId]: keys[0]!,\n\t\t\t});\n\t\t} else {\n\t\t\tkeyStore = new RotatingKeyStore({\n\t\t\t\t[networkConfig.accountId]: keys as string[],\n\t\t\t});\n\t\t}\n\n\t\tconst near = createNear(network, headers, rpcUrl, keyStore);\n\t\tconst explicitPublicKey = parseKey(keys[0]!);\n\t\treturn {\n\t\t\tnear,\n\t\t\taccountId: networkConfig.accountId,\n\t\t\tnetwork,\n\t\t\tmode: \"explicit\",\n\t\t\tpublicKey: explicitPublicKey.publicKey.toString(),\n\t\t\twhitelistedContracts: networkConfig.whitelistedContracts,\n\t\t\tmaxGasPerTransaction: networkConfig.maxGasPerTransaction,\n\t\t\tmaxDepositPerTransaction: networkConfig.maxDepositPerTransaction,\n\t\t};\n\t}\n\n\tconst existing = await adapter.findOne<{ encryptedPrivateKey: string; iv: string; createdAt: Date; lastUsedAt: Date }>({\n\t\tmodel: \"relayerKey\",\n\t\twhere: [{ field: \"network\", operator: \"eq\", value: network }],\n\t});\n\n\tif (existing) {\n\t\tif (!secret) throw new Error(\"BETTER_AUTH_SECRET required for relayer key decryption\");\n\t\tconst privateKeyBytes = await decryptPrivateKey(existing.encryptedPrivateKey, existing.iv, secret);\n\t\tconst keyPair = parseKey(`ed25519:${base58.encode(privateKeyBytes)}`);\n\t\tconst accountId = bytesToHex(keyPair.publicKey.data);\n\n\t\tconsole.log(`[siwn] Relayer recovered: ${accountId} (${network})`);\n\n\t\tconst keyStore = new InMemoryKeyStore();\n\t\tawait keyStore.add(accountId, keyPair);\n\n\t\tconst near = createNear(network, headers, rpcUrl, keyStore);\n\t\treturn {\n\t\t\tnear,\n\t\t\taccountId,\n\t\t\tnetwork,\n\t\t\tmode: \"ephemeral\",\n\t\t\tpublicKey: keyPair.publicKey.toString(),\n\t\t\twhitelistedContracts: networkConfig.whitelistedContracts,\n\t\t\tmaxGasPerTransaction: networkConfig.maxGasPerTransaction,\n\t\t\tmaxDepositPerTransaction: networkConfig.maxDepositPerTransaction,\n\t\t\tcreatedAt: existing.createdAt,\n\t\t\tlastUsedAt: existing.lastUsedAt,\n\t\t};\n\t}\n\n\tconst keyPair = generateKey();\n\tif (!secret) throw new Error(\"BETTER_AUTH_SECRET required for relayer key encryption\");\n\tconst privateKeyBytes = keyPair.secretKey.startsWith(\"ed25519:\")\n\t\t? base58.decode(keyPair.secretKey.slice(8))\n\t\t: new Uint8Array(0);\n\n\tconst publicKeyBase58 = keyPair.publicKey.toString().replace(\"ed25519:\", \"\");\n\tconst accountId = bytesToHex(keyPair.publicKey.data);\n\tconst createdAt = new Date();\n\n\tconst { encrypted, iv } = await encryptPrivateKey(privateKeyBytes, secret);\n\n\tawait adapter.create({\n\t\t\tmodel: \"relayerKey\",\n\t\t\tdata: {\n\t\t\t\taccountId,\n\t\t\t\tencryptedPrivateKey: encrypted,\n\t\t\t\tiv,\n\t\t\t\tpublicKey: `ed25519:${publicKeyBase58}`,\n\t\t\t\tnetwork,\n\t\t\t\tcreatedAt,\n\t\t\t\tlastUsedAt: createdAt,\n\t\t\t},\n\t\t});\n\n\tconsole.log(`[siwn] Relayer created in EPHEMERAL mode: ${accountId} (${network})`);\n\tconsole.log(`[siwn] Fund this account with NEAR to enable gasless relay`);\n\tconsole.log(`[siwn] Private key is encrypted in DB — persists across restarts`);\n\n\tconst keyStore = new InMemoryKeyStore();\n\tawait keyStore.add(accountId, keyPair);\n\n\tconst near = createNear(network, headers, rpcUrl, keyStore);\n\treturn {\n\t\tnear,\n\t\taccountId,\n\t\tnetwork,\n\t\tmode: \"ephemeral\",\n\t\tpublicKey: keyPair.publicKey.toString(),\n\t\twhitelistedContracts: networkConfig.whitelistedContracts,\n\t\tmaxGasPerTransaction: networkConfig.maxGasPerTransaction,\n\t\tmaxDepositPerTransaction: networkConfig.maxDepositPerTransaction,\n\t\tcreatedAt,\n\t\tlastUsedAt: createdAt,\n\t};\n}\n\nasync function relayOnChain(\n\tpayload: string,\n\trelayerState: RelayerState,\n): Promise<{ txHash: string }> {\n\tconst userAction = decodeSignedDelegateAction(payload);\n\n\tconst result = await relayerState.near\n\t\t.transaction(relayerState.accountId)\n\t\t.signedDelegateAction(userAction)\n\t\t.send({ waitUntil: \"EXECUTED\" });\n\n\treturn { txHash: result.transaction.hash };\n}\n\nasync function defaultValidateLimitedAccessKey(\n\taccountId: string,\n\tpublicKey: string,\n\trecipient: string,\n\tnear: Near,\n): Promise<boolean> {\n\tconst key = await near.getAccessKey(accountId, publicKey);\n\tif (!key) return false;\n\tif (key.permission === \"FullAccess\") return true;\n\tif (\"FunctionCall\" in key.permission) {\n\t\treturn key.permission.FunctionCall.receiver_id === recipient;\n\t}\n\treturn false;\n}\n\nfunction isImplicitAccount(accountId: string): boolean {\n\treturn /^[0-9a-f]{64}$/.test(accountId);\n}\n\nfunction resolveParentAccount(\n\tsubAccountCfg: SubAccountConfig | undefined,\n\tparentKey: string | undefined,\n\trState: RelayerState | null,\n): { parentAccount: string | null; subAccountAvailable: boolean } {\n\tconst parent = subAccountCfg?.parentAccount ?? rState?.accountId;\n\tif (!parent || isImplicitAccount(parent)) {\n\t\treturn { parentAccount: null, subAccountAvailable: false };\n\t}\n\tif (!rState && !parentKey) {\n\t\treturn { parentAccount: null, subAccountAvailable: false };\n\t}\n\treturn { parentAccount: parent, subAccountAvailable: true };\n}\n\nexport interface SIWNPluginOptions {\n\trecipient?: string;\n\trecipients?: DualNetworkConfig<string>;\n\trequireFullAccessKey?: boolean;\n\tgetNonce?: () => Promise<Uint8Array>;\n\tgetProfile?: (accountId: AccountId) => Promise<Profile | null>;\n\tvalidateLimitedAccessKey?: (args: {\n\t\taccountId: AccountId;\n\t\tpublicKey: string;\n\t\trecipient?: string;\n\t}) => Promise<boolean>;\n\tapiKey?: string;\n\trpcUrl?: string | DualNetworkConfig<string>;\n\trelayer?: RelayerConfig | DualNetworkConfig<RelayerConfig>;\n\tsecrets?: {\n\t\tparentKey?: string | DualNetworkConfig<string>;\n\t};\n\tsubAccount?: SubAccountConfig | DualNetworkConfig<SubAccountConfig>;\n}\n\nexport const siwn = (options: SIWNPluginOptions) => {\n\tif (!options.recipient && !options.recipients) {\n\t\tthrow new Error(\"Either 'recipient' or 'recipients' must be provided to siwn plugin\");\n\t}\n\n\tconst apiKey = options.apiKey;\n\n\tconst getRecipient = (network: \"mainnet\" | \"testnet\"): string => {\n\t\tif (options.recipients) return options.recipients[network];\n\t\treturn options.recipient!;\n\t};\n\n\tconst getSupportedNetworks = (): (\"mainnet\" | \"testnet\")[] => {\n\t\tif (options.recipients) return [\"mainnet\", \"testnet\"];\n\t\tif (options.recipient) return [getNetworkFromAccountId(options.recipient)];\n\t\treturn [\"mainnet\"];\n\t};\n\n\tconst getRelayerConfig = (network: \"mainnet\" | \"testnet\"): RelayerConfig | undefined => {\n\t\tif (!options.relayer) return undefined;\n\t\tif (options.relayer === true) return true;\n\t\tif (\"mainnet\" in options.relayer || \"testnet\" in options.relayer) {\n\t\t\treturn (options.relayer as RelayerDualNetworkConfig)[network];\n\t\t}\n\t\treturn options.relayer as RelayerConfig;\n\t};\n\n\tconst getRpcUrl = (network: \"mainnet\" | \"testnet\"): string | undefined => {\n\t\tif (!options.rpcUrl) return undefined;\n\t\tif (typeof options.rpcUrl === \"object\") return (options.rpcUrl as DualNetworkConfig<string>)[network];\n\t\treturn options.rpcUrl as string;\n\t};\n\n\tconst getSubAccountConfig = (network: \"mainnet\" | \"testnet\"): SubAccountConfig | undefined => {\n\t\tif (!options.subAccount) return undefined;\n\t\tif (\"mainnet\" in options.subAccount && typeof options.subAccount.mainnet === \"object\") {\n\t\t\treturn (options.subAccount as DualNetworkConfig<SubAccountConfig>)[network];\n\t\t}\n\t\treturn options.subAccount as SubAccountConfig;\n\t};\n\n\tconst getParentKey = (network: \"mainnet\" | \"testnet\"): string | undefined => {\n\t\tif (!options.secrets?.parentKey) return undefined;\n\t\tif (typeof options.secrets.parentKey === \"object\") {\n\t\t\treturn (options.secrets.parentKey as DualNetworkConfig<string>)[network];\n\t\t}\n\t\treturn options.secrets.parentKey as string;\n\t};\n\n\tconst getRawParentKey = (network: \"mainnet\" | \"testnet\"): string | undefined => {\n\t\tconst fromSecrets = getParentKey(network);\n\t\tif (fromSecrets) return fromSecrets;\n\t\tconst relayerCfg = getRelayerConfig(network);\n\t\tconst subAccountCfg = getSubAccountConfig(network);\n\t\t\n\t\tif (!relayerCfg || relayerCfg === true) return undefined;\n\t\tif (\"mainnet\" in relayerCfg || \"testnet\" in relayerCfg) return undefined;\n\t\t\n\t\tconst explicitCfg = relayerCfg as RelayerExplicitConfig;\n\t\tconst parent = subAccountCfg?.parentAccount ?? explicitCfg.accountId;\n\t\tif (parent && parent === explicitCfg.accountId) {\n\t\t\treturn explicitCfg.privateKey ?? explicitCfg.privateKeys?.[0];\n\t\t}\n\t\treturn undefined;\n\t};\n\n\tconst primaryNetwork = getSupportedNetworks()[0];\n\tconst relayerStates = new Map<\"mainnet\" | \"testnet\", RelayerState | null>();\n\tconst relayerInitPromises = new Map<\"mainnet\" | \"testnet\", Promise<RelayerState | null>>();\n\n\tconst headers: Record<string, string> = {};\n\tif (apiKey) {\n\t\theaders[\"Authorization\"] = `Bearer ${apiKey}`;\n\t}\n\n\tconst ensureRelayer = async (adapter: DBAdapter, secret: string | undefined, network: \"mainnet\" | \"testnet\") => {\n\t\tif (relayerStates.has(network)) return relayerStates.get(network) ?? null;\n\n\t\tconst existingInit = relayerInitPromises.get(network);\n\t\tif (existingInit) return existingInit;\n\n\t\tconst relayerCfg = getRelayerConfig(network);\n\t\tconst networkRpcUrl = getRpcUrl(network);\n\n\tconst initPromise = initRelayer(relayerCfg, network, adapter, secret, apiKey, networkRpcUrl)\n\t\t.then((state) => {\n\t\t\trelayerStates.set(network, state);\n\t\t\trelayerInitPromises.delete(network);\n\t\t\tif (state) {\n\t\t\t\tconsole.log(`[siwn] Relayer initialized: ${state.accountId} (${network}, ${state.mode})`);\n\t\t\t\tif (state.mode === \"ephemeral\") {\n\t\t\t\t\tconsole.log(`[siwn] Fund this account with NEAR to enable gasless relay`);\n\t\t\t\t\tconsole.log(`[siwn] Private key is encrypted in DB — persists across restarts`);\n\t\t\t\t}\n\t\t\t} else if (relayerCfg) {\n\t\t\t\tconsole.warn(`[siwn] Relayer config provided but not initialized for ${network}. Check BETTER_AUTH_SECRET for ephemeral mode.`);\n\t\t\t}\n\t\t\treturn state;\n\t\t})\n\t\t.catch((error) => {\n\t\t\trelayerInitPromises.delete(network);\n\t\t\tconsole.error(`[siwn] Failed to initialize relayer for ${network}:`, error);\n\t\t\tthrow error;\n\t\t});\n\n\t\trelayerInitPromises.set(network, initPromise);\n\t\treturn initPromise;\n\t};\n\n\tconst getNear = (network: \"mainnet\" | \"testnet\") => {\n\t\tconst networkRpcUrl = getRpcUrl(network);\n\t\tif (networkRpcUrl) {\n\t\t\treturn new Near({ network: { rpcUrl: networkRpcUrl, networkId: network }, headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined });\n\t\t}\n\t\treturn new Near({ network, headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined });\n\t};\n\n\treturn ({\n\t\tid: \"siwn\",\n\t\tschema,\n\t\thooks: {\n\t\t\tafter: [\n\t\t\t\t{\n\t\t\t\t\tmatcher: (context: { path?: string; method?: string }) => context.path === \"/auth/session\" && context.method === \"GET\",\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\tconst session = ctx.context.session;\n\t\t\t\t\t\tif (session) {\n\t\t\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (nearAccount) {\n\t\t\t\t\t\t\t\tctx.context.session = {\n\t\t\t\t\t\t\t\t\t...session,\n\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t...session.user,\n\t\t\t\t\t\t\t\t\t\tnearAccount: nearAccount\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn { context: ctx };\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\tendpoints: {\n\t\t\tlinkNearAccount: createAuthEndpoint(\n\t\t\t\t\"/near/link-account\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: LinkAccountRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t\trequireRequest: true,\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { signedMessage, message, recipient, nonce, accountId, callbackUrl } = ctx.body;\n\t\t\t\t\tconst network = getNetworkFromAccountId(accountId);\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tif (!session) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Must be logged in to link NEAR account\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\t\tconst nonceBytes = hex.decode(nonce);\n\n\t\t\t\t\t\tconst isValid = await verifyNep413Signature(\n\t\t\t\t\t\tsignedMessage,\n\t\t\t\t\t\t{ message, recipient, nonce: nonceBytes, callbackUrl },\n\t\t\t\t\t\t\t{ near, maxAge: 15 * 60 * 1000 },\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (!isValid) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Invalid signature\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (signedMessage.accountId !== accountId) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Account ID mismatch\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst publicKey = signedMessage.publicKey;\n\n\t\t\t\t\t\tif (!options.requireFullAccessKey && options.validateLimitedAccessKey) {\n\t\t\t\t\t\t\tconst isValidKey = await options.validateLimitedAccessKey({\n\t\t\t\t\t\t\t\taccountId: accountId,\n\t\t\t\t\t\t\t\tpublicKey: publicKey,\n\t\t\t\t\t\t\t\trecipient: options.recipient\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (!isValidKey) {\n\t\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Invalid function call access key\",\n\t\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst existingNearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t\t{ field: \"network\", operator: \"eq\", value: network },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (existingNearAccount) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: \"This NEAR account is already linked to another user\",\n\t\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst existingPrimaryAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t\tpublicKey: publicKey,\n\t\t\t\t\t\t\t\tisPrimary: !existingPrimaryAccount,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\t\tproviderId: \"siwn\",\n\t\t\t\t\t\t\taccountId: `${accountId}:${network}`,\n\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\tmessage: \"NEAR account successfully linked\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tif (error instanceof APIError) throw error;\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Something went wrong. Please try again later.\",\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : \"Unknown error\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t\tunlinkNearAccount: createAuthEndpoint(\n\t\t\t\t\"/near/unlink-account\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: z.object({\n\t\t\t\t\t\taccountId: z.string(),\n\t\t\t\t\t\tnetwork: z.enum([\"mainnet\", \"testnet\"]).optional(),\n\t\t\t\t\t}),\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { accountId, network: providedNetwork } = ctx.body;\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tif (!session) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Must be logged in to unlink NEAR account\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst network = providedNetwork || getNetworkFromAccountId(accountId);\n\n\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t{ field: \"network\", operator: \"eq\", value: network },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!nearAccount) {\n\t\t\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\t\t\tmessage: \"NEAR account not found or not linked to your user\",\n\t\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst accounts = await ctx.context.adapter.findMany({\n\t\t\t\t\t\tmodel: \"account\",\n\t\t\t\t\t\twhere: [{ field: \"userId\", operator: \"eq\", value: session.user.id }],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (accounts.length <= 1) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: \"Cannot unlink last authentication method. Link another account first.\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (nearAccount.isPrimary) {\n\t\t\t\t\t\tconst otherNearAccounts: NearAccount[] = await ctx.context.adapter.findMany({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"ne\", value: accountId },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (otherNearAccounts.length > 0) {\n\t\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{ field: \"id\", operator: \"eq\", value: otherNearAccounts[0]!.id },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\tupdate: { isPrimary: true },\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tawait ctx.context.adapter.delete({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t{ field: \"network\", operator: \"eq\", value: network },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst accountToDelete: Account | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"account\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"providerId\", operator: \"eq\", value: \"siwn\" },\n\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: `${accountId}:${network}` },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (accountToDelete) {\n\t\t\t\t\t\tawait ctx.context.internalAdapter.deleteAccount(accountToDelete.id);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\taccountId,\n\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\tmessage: \"NEAR account successfully unlinked\"\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t),\n\t\t\tlistNearAccounts: createAuthEndpoint(\n\t\t\t\t\"/near/list-accounts\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tconst nearAccounts: NearAccount[] = await ctx.context.adapter.findMany({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [{ field: \"userId\", operator: \"eq\", value: session.user.id }],\n\t\t\t\t\t});\n\n\t\t\t\t\treturn ctx.json(buildListAccountsResponse(nearAccounts));\n\t\t\t\t},\n\t\t\t),\n\t\t\tsetPrimaryNearAccount: createAuthEndpoint(\n\t\t\t\t\"/near/set-primary-account\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: SetPrimaryAccountRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { accountId, network: providedNetwork } = ctx.body;\n\t\t\t\t\tconst session = ctx.context.session;\n\t\t\t\t\tconst network = providedNetwork || getNetworkFromAccountId(accountId);\n\n\t\t\t\t\tconst targetAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t{ field: \"network\", operator: \"eq\", value: network },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!targetAccount) {\n\t\t\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\t\t\tmessage: \"NEAR account not found or not linked to your user\",\n\t\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nearAccounts: NearAccount[] = await ctx.context.adapter.findMany({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [{ field: \"userId\", operator: \"eq\", value: session.user.id }],\n\t\t\t\t\t});\n\n\t\t\t\t\tawait Promise.all(nearAccounts.map((account) => ctx.context.adapter.update({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [{ field: \"id\", operator: \"eq\", value: account.id }],\n\t\t\t\t\t\tupdate: { isPrimary: nearAccountKey(account) === nearAccountKey(targetAccount) },\n\t\t\t\t\t})));\n\n\t\t\t\t\tconst updatedNearAccounts: NearAccount[] = await ctx.context.adapter.findMany({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [{ field: \"userId\", operator: \"eq\", value: session.user.id }],\n\t\t\t\t\t});\n\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\taccountId,\n\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\tmessage: \"Primary NEAR account updated\",\n\t\t\t\t\t\t...buildListAccountsResponse(updatedNearAccounts),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t),\n\t\t\tgetSiwnNonce: createAuthEndpoint(\n\t\t\t\t\"/near/nonce\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: NonceRequest,\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { accountId, networkId } = ctx.body;\n\t\t\t\t\tconst network = getNetworkFromAccountId(accountId);\n\n\t\t\t\t\tif (networkId !== network) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: \"Network ID mismatch with account ID\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\tconst exists = await near.accountExists(accountId);\n\t\t\t\t\tif (!exists) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: \"Account does not exist on-chain\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nonce = options.getNonce ? await options.getNonce() : generateNonce();\n\n\t\t\t\t\tconst nonceString = hex.encode(nonce);\n\n\t\t\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\t\t\tidentifier: `siwn:${accountId}:${network}`,\n\t\t\t\t\t\tvalue: nonceString,\n\t\t\t\t\t\texpiresAt: new Date(Date.now() + 15 * 60 * 1000),\n\t\t\t\t\t});\n\n\t\t\t\t\treturn ctx.json(NonceResponse.parse({ nonce: nonceString }));\n\t\t\t\t},\n\t\t\t),\n\t\t\tgetSiwnProfile: createAuthEndpoint(\n\t\t\t\t\"/near/profile\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: ProfileRequest,\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { accountId } = ctx.body;\n\t\t\t\t\tlet targetAccountId = accountId;\n\n\t\t\t\t\tif (!targetAccountId) {\n\t\t\t\t\t\tconst result = await getSessionFromCtx(ctx);\n\t\t\t\t\t\tconst session = result?.session;\n\t\t\t\t\t\tif (!session) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Session required when no accountId provided\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (!nearAccount) {\n\t\t\t\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\t\t\t\tmessage: \"No NEAR account found for user\",\n\t\t\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttargetAccountId = nearAccount.accountId;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst profile = await (options.getProfile || ((id: AccountId) => defaultGetProfile(id, apiKey)))(targetAccountId);\n\t\t\t\t\treturn ctx.json(ProfileResponse.parse(profile));\n\t\t\t\t},\n\t\t\t),\n\t\t\tverifySiwnMessage: createAuthEndpoint(\n\t\t\t\t\"/near/verify\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: VerifyRequest,\n\t\t\t\t\trequireRequest: true,\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst {\n\t\t\t\t\t\tsignedMessage,\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t\trecipient,\n\t\t\t\t\t\tnonce,\n\t\t\t\t\t\taccountId,\n\t\t\t\t\t\tcallbackUrl,\n\t\t\t\t\t} = ctx.body;\n\t\t\t\t\tconst network = getNetworkFromAccountId(accountId);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\t\tconst nonceBytes = hex.decode(nonce);\n\n\t\t\t\t\t\tconst isValid = await verifyNep413Signature(\n\t\t\t\t\t\tsignedMessage,\n\t\t\t\t\t\t{ message, recipient, nonce: nonceBytes, callbackUrl },\n\t\t\t\t\t\t\t{ near, maxAge: 15 * 60 * 1000 },\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (!isValid) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Invalid signature\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (signedMessage.accountId !== accountId) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Account ID mismatch\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst publicKey = signedMessage.publicKey;\n\n\t\t\t\t\t\tconst nonceHash = await hashNonce(nonceBytes);\n\n\t\t\t\t\t\tconst existingNonce = await ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t\t\t`siwn-nonce:${nonceHash}`\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (existingNonce) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Nonce already used (replay attack detected)\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t\tcode: \"UNAUTHORIZED_NONCE_REPLAY\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\t\t\t\tidentifier: `siwn-nonce:${nonceHash}`,\n\t\t\t\t\t\t\tvalue: \"used\",\n\t\t\t\t\t\t\texpiresAt: new Date(Date.now() + 15 * 60 * 1000),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (!options.requireFullAccessKey) {\n\t\t\t\t\t\t\tconst validateKey = options.validateLimitedAccessKey\n\t\t\t\t\t\t\t\t|| ((args: { accountId: string; publicKey: string; recipient?: string }) =>\n\t\t\t\t\t\t\t\t\tdefaultValidateLimitedAccessKey(args.accountId, args.publicKey, args.recipient || getRecipient(network), near));\n\n\t\t\t\t\t\t\tconst isValidKey = await validateKey({\n\t\t\t\t\t\t\t\taccountId: accountId,\n\t\t\t\t\t\t\t\tpublicKey: publicKey,\n\t\t\t\t\t\t\t\trecipient: options.recipient\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (!isValidKey) {\n\t\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Invalid function call access key\",\n\t\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet user: User | null = null;\n\n\t\t\t\t\t\tconst existingNearAccount: NearAccount | null =\n\t\t\t\t\t\t\tawait ctx.context.adapter.findOne({\n\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t\t\t{ field: \"network\", operator: \"eq\", value: network },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (existingNearAccount) {\n\t\t\t\t\t\t\tuser = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t\t\t\t\t\toperator: \"eq\",\n\t\t\t\t\t\t\t\t\t\tvalue: existingNearAccount.userId,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst anyNearAccount: NearAccount | null =\n\t\t\t\t\t\t\t\tawait ctx.context.adapter.findOne({\n\t\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (anyNearAccount) {\n\t\t\t\t\t\t\t\tuser = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t\t\t\t\t\t\toperator: \"eq\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: anyNearAccount.userId,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!user) {\n\t\t\t\t\t\t\tconst userEmail = deriveEmail(accountId, getRecipient(network));\n\n\t\t\t\t\t\t\tconst profile = await (options.getProfile || ((id: AccountId) => defaultGetProfile(id, apiKey)))(accountId);\n\n\t\t\t\t\t\t\tuser = await ctx.context.internalAdapter.createUser({\n\t\t\t\t\t\t\t\tname: profile?.name ?? accountId,\n\t\t\t\t\t\t\t\temail: userEmail,\n\t\t\t\t\t\t\t\timage: profile?.image ? getImageUrl(profile.image) : \"\",\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t\t\tpublicKey: publicKey,\n\t\t\t\t\t\t\t\t\tisPrimary: true,\n\t\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t\t\tproviderId: \"siwn\",\n\t\t\t\t\t\t\t\taccountId: `${accountId}:${network}`,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!existingNearAccount) {\n\t\t\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t\t\t\tpublicKey: publicKey,\n\t\t\t\t\t\t\t\t\t\tisPrimary: false,\n\t\t\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t\t\t\tproviderId: \"siwn\",\n\t\t\t\t\t\t\t\t\taccountId: `${accountId}:${network}`,\n\t\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait ensureRelayer(ctx.context.adapter, ctx.context.secret, network);\n\n\t\t\t\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\t\t\tuser.id\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (!session) {\n\t\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\t\tmessage: \"Internal Server Error\",\n\t\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait setSessionCookie(ctx, { session, user });\n\n\t\t\t\t\t\treturn ctx.json(VerifyResponse.parse({\n\t\t\t\t\t\t\ttoken: session.token,\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\tid: user.id,\n\t\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}));\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tif (error instanceof APIError) throw error;\n\t\t\t\t\t\tconst msg = error instanceof Error ? error.message : \"Unknown error\";\n\t\t\t\t\t\tconst at = error instanceof Error && error.stack ? error.stack.split(\"\\n\").slice(1, 3).map(s => s.trim()).join(\" <- \") : \"\";\n\t\t\t\t\t\tconsole.error(`[siwn] Verify error: ${msg}${at ? ` (${at})` : \"\"}`);\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Something went wrong. Please try again later.\",\n\t\t\t\t\t\t\terror: msg,\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t\trelayNearTransaction: createAuthEndpoint(\n\t\t\t\t\"/near/relay\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: RelayRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { payload } = ctx.body;\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tif (!session) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Must be authenticated to relay transactions\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!nearAccount) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"No NEAR account linked to session\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst network = nearAccount.network as \"mainnet\" | \"testnet\";\n\t\t\t\t\tconst rState = await ensureRelayer(ctx.context.adapter, ctx.context.secret, network);\n\n\t\t\t\t\tif (!rState) {\n\t\t\t\t\t\tthrow new APIError(\"SERVICE_UNAVAILABLE\", {\n\t\t\t\t\t\t\tmessage: \"Relayer not configured\",\n\t\t\t\t\t\t\tstatus: 503,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst decoded: SignedDelegateAction = decodeSignedDelegateAction(payload);\n\t\t\t\t\t\tconst delegateAction = decoded.signedDelegate.delegateAction;\n\n\t\t\t\t\t\tif (delegateAction.senderId !== nearAccount.accountId) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Delegate action sender does not match session account\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst relayerConfigForNetwork = getRelayerConfig(network);\n\t\t\t\t\t\tconst isDualNetwork = relayerConfigForNetwork && typeof relayerConfigForNetwork === \"object\" && (\"mainnet\" in relayerConfigForNetwork || \"testnet\" in relayerConfigForNetwork);\n\t\t\t\t\t\tconst isSimpleConfig = relayerConfigForNetwork && typeof relayerConfigForNetwork === \"object\" && !isDualNetwork;\n\t\t\t\t\t\tconst configWithLimits = isSimpleConfig ? relayerConfigForNetwork as RelayerEphemeralConfig | RelayerExplicitConfig : undefined;\n\t\t\t\t\t\tconst whitelistedContracts = configWithLimits?.whitelistedContracts;\n\t\t\t\t\t\tif (whitelistedContracts?.length) {\n\t\t\t\t\t\t\tif (!whitelistedContracts.includes(delegateAction.receiverId)) {\n\t\t\t\t\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\t\t\t\t\tmessage: `Contract ${delegateAction.receiverId} is not whitelisted for relay`,\n\t\t\t\t\t\t\t\t\tstatus: 403,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst maxGasPerTransaction = configWithLimits?.maxGasPerTransaction;\n\t\t\t\t\t\tif (maxGasPerTransaction) {\n\t\t\t\t\t\t\tconst totalGas = delegateAction.actions.reduce((sum: bigint, a) => {\n\t\t\t\t\t\t\t\treturn sum + (\"functionCall\" in a ? a.functionCall.gas : 0n);\n\t\t\t\t\t\t\t}, 0n);\n\t\t\t\t\t\t\tif (totalGas > BigInt(maxGasPerTransaction)) {\n\t\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\t\tmessage: `Transaction gas (${totalGas}) exceeds relayer limit (${maxGasPerTransaction})`,\n\t\t\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst maxDepositPerTransaction = configWithLimits?.maxDepositPerTransaction;\n\t\t\t\t\t\tif (maxDepositPerTransaction) {\n\t\t\t\t\t\t\tconst totalDeposit = delegateAction.actions.reduce((sum: bigint, a) => {\n\t\t\t\t\t\t\t\tif (\"functionCall\" in a) return sum + a.functionCall.deposit;\n\t\t\t\t\t\t\t\tif (\"transfer\" in a) return sum + a.transfer.deposit;\n\t\t\t\t\t\t\t\treturn sum;\n\t\t\t\t\t\t\t}, 0n);\n\t\t\t\t\t\t\tif (totalDeposit > BigInt(maxDepositPerTransaction)) {\n\t\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\t\tmessage: `Transaction deposit (${totalDeposit}) exceeds relayer limit (${maxDepositPerTransaction})`,\n\t\t\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst result = await relayOnChain(payload, rState);\n\n\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\tmodel: \"relayedTransaction\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\t\t\ttxHash: result.txHash,\n\t\t\t\t\t\t\t\tsenderId: delegateAction.senderId,\n\t\t\t\t\t\t\t\treceiverId: delegateAction.receiverId,\n\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\n\t\t\t\t\tif (rState.mode === \"ephemeral\") {\n\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\tmodel: \"relayerKey\",\n\t\t\t\t\t\t\twhere: [{ field: \"network\", operator: \"eq\", value: network }],\n\t\t\t\t\t\t\tupdate: { lastUsedAt: new Date() },\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t\treturn ctx.json(RelayResponse.parse({\n\t\t\t\t\t\t\ttxHash: result.txHash,\n\t\t\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t\t}));\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tif (error instanceof APIError) throw error;\n\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\tmessage: error instanceof Error ? error.message : \"Relay failed\",\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t\tgetRelayStatus: createAuthEndpoint(\n\t\t\t\t\"/near/relay-status/:txHash\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst txHash = (ctx.params as Record<string, string>)?.txHash;\n\t\t\t\t\tif (!txHash) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: \"Transaction hash required\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tconst relayedTx = await ctx.context.adapter.findOne<RelayedTransactionRecord>({\n\t\t\t\t\t\tmodel: \"relayedTransaction\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"txHash\", operator: \"eq\", value: txHash },\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!relayedTx) {\n\t\t\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\t\t\tmessage: \"Transaction not found or not owned by this user\",\n\t\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst network = relayedTx.network;\n\t\t\t\t\tconst senderId = relayedTx.senderId;\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\t\tconst txResult = await near.getTransactionStatus(txHash, senderId);\n\n\t\t\t\t\t\tconst txStatus = txResult.status;\n\t\t\t\t\t\tif (txStatus && typeof txStatus === \"object\") {\n\t\t\t\t\t\t\tconst hasSuccess = \"SuccessValue\" in txStatus || \"SuccessReceiptId\" in txStatus;\n\t\t\t\t\t\t\tconst hasFailure = \"Failure\" in txStatus;\n\t\t\t\t\t\t\tconst status = hasSuccess ? \"completed\" : hasFailure ? \"failed\" : \"pending\";\n\n\t\t\t\t\t\t\tif (status !== \"pending\") {\n\t\t\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\t\t\tmodel: \"relayedTransaction\",\n\t\t\t\t\t\t\t\t\twhere: [{ field: \"txHash\", operator: \"eq\", value: txHash }],\n\t\t\t\t\t\t\t\t\tupdate: { status },\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst gasUsed = txResult.transaction_outcome?.outcome?.gas_burnt?.toString();\n\n\t\t\t\t\t\t\treturn ctx.json(RelayStatusResponse.parse({\n\t\t\t\t\t\t\t\tstatus,\n\t\t\t\t\t\t\t\tgasUsed,\n\t\t\t\t\t\t\t\toutcome: txResult,\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn ctx.json(RelayStatusResponse.parse({ status: \"pending\" }));\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\treturn ctx.json(RelayStatusResponse.parse({ status: \"pending\" }));\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t\tgetRelayerInfo: createAuthEndpoint(\n\t\t\t\t\"/near/relayer-info\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: GetRelayerInfoRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { network: requestedNetwork } = ctx.body;\n\t\t\t\t\tconst targetNetwork = (requestedNetwork ?? primaryNetwork) as \"mainnet\" | \"testnet\";\n\t\t\t\t\tconst rState = await ensureRelayer(ctx.context.adapter, ctx.context.secret, targetNetwork);\n\n\t\t\t\t\tif (!rState) {\n\t\t\t\t\t\treturn ctx.json({ enabled: false, subAccountAvailable: false } satisfies Partial<RelayerInfo> & { enabled: boolean });\n\t\t\t\t\t}\n\n\t\t\t\t\tconst subAccountCfg = getSubAccountConfig(targetNetwork);\n\t\t\t\t\tconst parentKey = getParentKey(targetNetwork);\nconst { parentAccount, subAccountAvailable } = resolveParentAccount(subAccountCfg, parentKey, rState);\n\n\t\t\t\t\tconst near = getNear(rState.network);\n\t\t\t\t\tlet account;\n\t\t\t\t\ttry {\n\t\t\t\t\t\taccount = await near.getAccount(rState.accountId);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\taccount = {\n\t\t\t\t\t\t\tbalance: \"0\",\n\t\t\t\t\t\t\tavailable: \"0\",\n\t\t\t\t\t\t\tstaked: \"0\",\n\t\t\t\t\t\t\tstorageUsage: \"0\",\n\t\t\t\t\t\t\tstorageBytes: 0,\n\t\t\t\t\t\t\thasContract: false,\n\t\t\t\t\t\t\tcodeHash: \"\",\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\taccountId: rState.accountId,\n\t\t\t\t\t\tmode: rState.mode,\n\t\t\t\t\t\tnetwork: rState.network,\n\t\t\t\t\t\tpublicKey: rState.publicKey,\n\t\t\t\t\t\tbalance: account.balance,\n\t\t\t\t\t\tavailable: account.available,\n\t\t\t\t\t\tstaked: account.staked,\n\t\t\t\t\t\tstorageUsage: account.storageUsage,\n\t\t\t\t\t\tstorageBytes: account.storageBytes,\n\t\t\t\t\t\thasContract: account.hasContract,\n\t\t\t\t\t\thasKey: true,\n\t\t\t\t\t\tcreatedAt: rState.createdAt,\n\t\t\t\t\t\tlastUsedAt: rState.lastUsedAt,\n\t\t\t\t\t\tparentAccount: parentAccount ?? undefined,\n\t\t\t\t\t\tsubAccountAvailable,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t),\n\t\t\tgetRelayHistory: createAuthEndpoint(\n\t\t\t\t\"/near/relay-history\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tlet transactions: RelayedTransactionRecord[] = [];\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = await ctx.context.adapter.findMany<RelayedTransactionRecord>({\n\t\t\t\t\t\t\tmodel: \"relayedTransaction\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t\ttransactions = result || [];\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(\"relay-history findMany error:\", err);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst sorted = transactions.sort((a, b) => {\n\t\t\t\t\t\tconst aTime = a.createdAt instanceof Date ? a.createdAt.getTime() : new Date(a.createdAt ?? 0).getTime();\n\t\t\t\t\t\tconst bTime = b.createdAt instanceof Date ? b.createdAt.getTime() : new Date(b.createdAt ?? 0).getTime();\n\t\t\t\t\t\treturn bTime - aTime;\n\t\t\t\t\t});\n\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\ttransactions: sorted.map((tx) => ({\n\t\t\t\t\t\t\tid: String(tx.id ?? \"\"),\n\t\t\t\t\t\t\tuserId: String(tx.userId ?? \"\"),\n\t\t\t\t\t\t\ttxHash: String(tx.txHash ?? \"\"),\n\t\t\t\t\t\t\tsenderId: String(tx.senderId ?? \"\"),\n\t\t\t\t\t\t\treceiverId: String(tx.receiverId ?? \"\"),\n\t\t\t\t\t\t\tnetwork: String(tx.network ?? \"mainnet\"),\n\t\t\t\t\t\t\tstatus: String(tx.status ?? \"pending\"),\n\t\t\t\t\t\t\tgasUsed: tx.gasUsed ? String(tx.gasUsed) : undefined,\n\t\t\t\t\t\t\tcreatedAt: tx.createdAt instanceof Date ? tx.createdAt.toISOString() : tx.createdAt ? String(tx.createdAt) : new Date().toISOString(),\n\t\t\t\t\t\t\tupdatedAt: tx.updatedAt instanceof Date ? tx.updatedAt.toISOString() : tx.updatedAt ? String(tx.updatedAt) : undefined,\n\t\t\t\t\t\t})),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t),\n\t\t\tviewContract: createAuthEndpoint(\n\t\t\t\t\"/near/view\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: ViewContractRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { contractId, methodName, args } = ctx.body;\n\t\t\t\t\tconst session = ctx.context.session;\n\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst network = (nearAccount?.network || primaryNetwork) as \"mainnet\" | \"testnet\";\n\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\tlet result: unknown;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresult = await near.view(contractId, methodName, args ?? {});\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tif (error instanceof APIError) throw error;\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: error instanceof Error ? error.message : \"Unknown error\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json(ViewContractResponse.parse({ result }));\n\t\t\t\t},\n\t\t\t),\n\t\t\tcreateSubAccount: createAuthEndpoint(\n\t\t\t\t\"/near/create-sub-account\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: CreateSubAccountRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { subAccountName, network: providedNetwork, publicKey } = ctx.body;\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tif (!session) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Must be authenticated to create a sub-account\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst network = (providedNetwork || nearAccount?.network || primaryNetwork) as \"mainnet\" | \"testnet\";\n\t\t\t\t\tconst subAccountCfg = getSubAccountConfig(network);\n\t\t\t\t\tconst userAccountId = nearAccount?.accountId ?? \"\";\n\t\t\t\t\tconst parentKey = getParentKey(network);\n\t\t\t\t\tconst rState = await ensureRelayer(ctx.context.adapter, ctx.context.secret, network);\n\t\t\t\t\tconst { parentAccount, subAccountAvailable } = resolveParentAccount(subAccountCfg, parentKey, rState);\n\n\t\t\t\t\tif (!subAccountAvailable || !parentAccount) {\n\t\t\t\t\t\tconst configuredParent = subAccountCfg?.parentAccount;\n\t\t\t\t\t\tlet msg: string;\n\t\t\t\t\t\tif (configuredParent && !parentKey) {\n\t\t\t\t\t\t\tmsg = `Sub-account creation unavailable on ${network}: parent key not configured for ${configuredParent}. Set NEAR_SUB_ACCOUNT_PARENT_KEY_${network.toUpperCase()} in your environment, or use an explicit relayer with a named account.`;\n\t\t\t\t\t\t} else if (!configuredParent) {\n\t\t\t\t\t\t\tmsg = `Sub-account creation unavailable on ${network}: no parent account configured. Set subAccount.${network}.parentAccount in your SIWN plugin options, or use an explicit relayer with a named account.`;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmsg = `Sub-account creation unavailable on ${network}: requires a named parent account with a parent key, or an explicit relayer with a named account.`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow new APIError(\"SERVICE_UNAVAILABLE\", {\n\t\t\t\t\t\t\tmessage: msg,\n\t\t\t\t\t\t\tstatus: 503,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst effectiveParentKey = getRawParentKey(network);\n\t\t\t\t\tif (parentAccount !== rState?.accountId && !effectiveParentKey) {\n\t\t\t\t\t\tthrow new APIError(\"SERVICE_UNAVAILABLE\", {\n\t\t\t\t\t\t\tmessage: \"Sub-account parent differs from relayer account. Provide secrets.parentKey to sign as the parent account.\",\n\t\t\t\t\t\t\tstatus: 503,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst newAccountId = `${subAccountName}.${parentAccount}`;\n\t\t\t\t\tconst minDeposit = subAccountCfg?.minDeposit || \"0.1 NEAR\";\n\n\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\tconst exists = await near.accountExists(newAccountId);\n\t\t\t\t\tif (exists) {\n\t\t\t\t\t\tthrow new APIError(\"CONFLICT\", {\n\t\t\t\t\t\t\tmessage: `Account ${newAccountId} already exists on ${network}`,\n\t\t\t\t\t\t\tstatus: 409,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst txCtx: SubAccountTxCtx = {\n\t\t\t\t\t\tnewAccountId,\n\t\t\t\t\t\tparentAccount,\n\t\t\t\t\t\tuserPublicKey: publicKey,\n\t\t\t\t\t\tuserAccountId,\n\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\tnetwork,\n\t\t\t\t\t};\n\n\t\t\t\t\tconst signingNear = rState?.near ?? near;\n\t\t\t\t\tlet txBuilder = signingNear\n\t\t\t\t\t\t.transaction(parentAccount)\n\t\t\t\t\t\t.createAccount(newAccountId)\n\t\t\t\t\t\t.addKey(publicKey, { type: \"fullAccess\" });\n\n\t\t\t\t\tif (subAccountCfg?.parentHasFullAccess) {\n\t\t\t\t\t\tconst parentPublicKey = parentAccount === rState?.accountId\n\t\t\t\t\t\t\t? rState.publicKey\n\t\t\t\t\t\t\t: parseKey(effectiveParentKey!).publicKey.toString();\n\t\t\t\t\t\ttxBuilder = txBuilder.addKey(parentPublicKey, { type: \"fullAccess\" });\n\t\t\t\t\t}\n\n\t\t\t\t\tif (subAccountCfg?.addRelayerFCAK !== false && subAccountCfg?.relayerFCAK && rState) {\n\t\t\t\t\t\tconst fcakPermission: { type: \"functionCall\"; receiverId: string; methodNames?: string[]; allowance?: string } = {\n\t\t\t\t\t\t\ttype: \"functionCall\",\n\t\t\t\t\t\t\treceiverId: subAccountCfg.relayerFCAK.receiverId,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (subAccountCfg.relayerFCAK.methodNames) {\n\t\t\t\t\t\t\tfcakPermission.methodNames = subAccountCfg.relayerFCAK.methodNames;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (subAccountCfg.relayerFCAK.allowance) {\n\t\t\t\t\t\t\tfcakPermission.allowance = subAccountCfg.relayerFCAK.allowance as `${number} NEAR` | `${bigint} yocto`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttxBuilder.addKey(rState.publicKey, fcakPermission as any);\n\t\t\t\t\t}\n\n\t\t\t\t\ttxBuilder.transfer(newAccountId, minDeposit as `${number} NEAR`);\n\n\t\t\t\t\tif (subAccountCfg?.deploy) {\n\t\t\t\t\t\tif (\"wasm\" in subAccountCfg.deploy) {\n\t\t\t\t\t\t\ttxBuilder = txBuilder.deployContract(newAccountId, subAccountCfg.deploy.wasm);\n\t\t\t\t\t\t} else if (\"fromPublished\" in subAccountCfg.deploy) {\n\t\t\t\t\t\t\ttxBuilder = txBuilder.deployFromPublished(subAccountCfg.deploy.fromPublished as any);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (subAccountCfg?.init) {\n\t\t\t\t\t\tconst initArgs = typeof subAccountCfg.init.args === \"function\"\n\t\t\t\t\t\t\t? subAccountCfg.init.args(txCtx)\n\t\t\t\t\t\t\t: subAccountCfg.init.args;\n\t\t\t\t\t\ttxBuilder = txBuilder.functionCall(newAccountId, subAccountCfg.init.methodName, initArgs);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (subAccountCfg?.extendTx) {\n\t\t\t\t\t\ttxBuilder = subAccountCfg.extendTx(txBuilder, txCtx) as typeof txBuilder;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (effectiveParentKey) {\n\t\t\t\t\t\ttxBuilder = txBuilder.signWith(effectiveParentKey as PrivateKey);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst cleanupDb = async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst existing = await ctx.context.adapter.findOne<{ id: string }>({\n\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\twhere: [{ field: \"accountId\", operator: \"eq\", value: newAccountId }],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (existing) {\n\t\t\t\t\t\t\t\tawait ctx.context.adapter.delete({ model: \"nearAccount\", where: [{ field: \"id\", operator: \"eq\", value: existing.id }] });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch { }\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait ctx.context.internalAdapter.deleteAccount(`${newAccountId}:${network}`);\n\t\t\t\t\t\t} catch { }\n\t\t\t\t\t};\n\n\t\t\t\t\tconst lifecycleCtx: SubAccountLifecycleCtx = { ...txCtx, near: signingNear };\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait txBuilder.send({ waitUntil: \"EXECUTED\" });\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tconst msg = error instanceof Error ? error.message : \"Unknown error\";\n\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\tmessage: `Failed to create sub-account: ${msg}`,\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\t\t\taccountId: newAccountId,\n\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t\tpublicKey,\n\t\t\t\t\t\t\t\tisPrimary: false,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\t\tproviderId: \"siwn\",\n\t\t\t\t\t\t\taccountId: `${newAccountId}:${network}`,\n\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (subAccountCfg?.onCreated) {\n\t\t\t\t\t\t\tawait subAccountCfg.onCreated(lifecycleCtx);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tawait cleanupDb();\n\t\t\t\t\t\tif (subAccountCfg?.onRollback) {\n\t\t\t\t\t\t\ttry { await subAccountCfg.onRollback(lifecycleCtx); } catch { }\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst key = getRawParentKey(network);\n\t\t\t\t\t\t\t\tif (key) {\n\t\t\t\t\t\t\t\t\tconst rollbackNear = getNear(network);\n\t\t\t\t\t\t\t\t\tawait rollbackNear\n\t\t\t\t\t\t\t\t\t\t.transaction(newAccountId)\n\t\t\t\t\t\t\t\t\t\t.deleteAccount({ beneficiary: parentAccount })\n\t\t\t\t\t\t\t\t\t\t.signWith(key as PrivateKey)\n\t\t\t\t\t\t\t\t\t\t.send({ waitUntil: \"EXECUTED\" });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch { }\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst msg = error instanceof Error ? error.message : \"Unknown error\";\n\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\tmessage: `Sub-account created but post-creation failed: ${msg}`,\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\treturn ctx.json(CreateSubAccountResponse.parse({\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\taccountId: newAccountId,\n\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\tpublicKey,\n\t\t\t\t\t\tmessage: `Sub-account ${newAccountId} created on ${network}`,\n\t\t\t\t\t}));\n\t\t\t\t},\n\t\t\t),\n\t\tcheckSubAccountAvailability: createAuthEndpoint(\n\t\t\t\"/near/check-sub-account-availability\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: CheckSubAccountAvailabilityRequest,\n\t\t\t\tuse: [sessionMiddleware],\n\t\t\t},\n\t\t\tasync (ctx) => {\n\t\t\t\tconst { subAccountName, network: providedNetwork } = ctx.body;\n\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\tif (!session) {\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: \"Must be authenticated to check sub-account availability\",\n\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\twhere: [\n\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t],\n\t\t\t\t});\n\n\t\t\t\tif (!nearAccount) {\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: \"Must have a linked NEAR wallet to check sub-account availability\",\n\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst network = (providedNetwork || nearAccount.network || primaryNetwork) as \"mainnet\" | \"testnet\";\n\t\t\t\tconst subAccountCfg = getSubAccountConfig(network);\n\t\t\t\tconst parentAccount = subAccountCfg?.parentAccount ?? null;\n\n\t\t\t\tif (!parentAccount || isImplicitAccount(parentAccount)) {\n\t\t\t\t\treturn ctx.json(CheckSubAccountAvailabilityResponse.parse({\n\t\t\t\t\t\tavailable: false,\n\t\t\t\t\t\taccountId: \"\",\n\t\t\t\t\t\treason: \"not-configured\",\n\t\t\t\t\t}));\n\t\t\t\t}\n\n\t\t\t\tconst accountId = `${subAccountName}.${parentAccount}`;\n\n\t\t\t\tif (accountId.length > 64) {\n\t\t\t\t\treturn ctx.json(CheckSubAccountAvailabilityResponse.parse({\n\t\t\t\t\t\tavailable: false,\n\t\t\t\t\t\taccountId,\n\t\t\t\t\t\tparentAccount,\n\t\t\t\t\t\treason: \"too-long\",\n\t\t\t\t\t}));\n\t\t\t\t}\n\n\t\t\t\tconst near = getNear(network);\n\t\t\t\tconst exists = await near.accountExists(accountId);\n\n\t\t\t\treturn ctx.json(CheckSubAccountAvailabilityResponse.parse({\n\t\t\t\t\tavailable: !exists,\n\t\t\t\t\taccountId,\n\t\t\t\t\tparentAccount,\n\t\t\t\t\treason: exists ? \"taken\" : undefined,\n\t\t\t\t}));\n\t\t\t},\n\t\t),\n\t\t},\n\t});\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["z"],"sources":["../src/profile.ts","../src/schema.ts","../src/types.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["import type { AccountId, Profile, SocialImage } from \"./types.js\";\n\nconst FALLBACK_URL =\n\t\"https://ipfs.near.social/ipfs/bafkreidn5fb2oygegqaldx7ycdmhu4owcrmoxd7ekbzfmeakkobz2ja7qy\";\n\nfunction getNetworkFromAccountId(accountId: string): \"mainnet\" | \"testnet\" {\n\treturn accountId.endsWith('.testnet') ? 'testnet' : 'mainnet';\n}\n\nfunction getImageUrl(\n\timage: SocialImage | undefined,\n\tfallback?: string,\n): string {\n\tif (image?.url) return image.url;\n\tif (image?.ipfs_cid) return `https://ipfs.near.social/ipfs/${image.ipfs_cid}`;\n\treturn fallback || FALLBACK_URL;\n}\n\ninterface SocialApiResponse {\n\t[accountId: string]: {\n\t\tprofile?: Profile;\n\t};\n}\n\ninterface KvEntry {\n\tvalue: Record<string, unknown> | string;\n\tblock_height?: number;\n\tblock_hash?: string;\n\ttimestamp_nanosec?: string;\n}\n\ninterface KvResponse {\n\tentries: KvEntry[];\n}\n\nasync function defaultGetProfile(accountId: AccountId, apiKey?: string): Promise<Profile | null> {\n\tconst network = getNetworkFromAccountId(accountId);\n\n\ttry {\n\t\tconst kvUrl = network === \"testnet\"\n\t\t\t? \"https://kv.test.fastnear.com\"\n\t\t\t: \"https://kv.main.fastnear.com\";\n\n\t\tconst effectiveApiKey = apiKey || process.env.FASTNEAR_API_KEY;\n\t\tconst headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n\t\tif (effectiveApiKey) {\n\t\t\theaders[\"Authorization\"] = `Bearer ${effectiveApiKey}`;\n\t\t}\n\n\t\tconst response = await fetch(\n\t\t\t`${kvUrl}/v0/latest/social.near/${accountId}/profile/**`,\n\t\t\t{ headers },\n\t\t);\n\n\t\tif (response.ok) {\n\t\t\tconst data = await response.json() as KvResponse;\n\t\t\tconst entry = data?.entries?.[0];\n\t\t\tif (entry?.value) {\n\t\t\t\ttry {\n\t\t\t\t\tconst profile = typeof entry.value === \"string\"\n\t\t\t\t\t\t? JSON.parse(entry.value)\n\t\t\t\t\t\t: entry.value;\n\t\t\t\t\tif (profile?.name || profile?.description || profile?.image) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tname: profile.name,\n\t\t\t\t\t\t\tdescription: profile.description,\n\t\t\t\t\t\t\timage: profile.image,\n\t\t\t\t\t\t\tbackgroundImage: profile.backgroundImage,\n\t\t\t\t\t\t\tlinktree: profile.linktree,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\n\t\tconst apiBase = {\n\t\t\tmainnet: \"https://api.near.social\",\n\t\t\ttestnet: \"https://test.api.near.social\",\n\t\t}[network];\n\n\t\tconst keys = [`${accountId}/profile/**`];\n\n\t\tconst fallbackResponse = await fetch(`${apiBase}/get`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ keys })\n\t\t});\n\n\t\tif (!fallbackResponse.ok) {\n\t\t\tthrow new Error(`HTTP error! status: ${fallbackResponse.status}`);\n\t\t}\n\n\t\tconst fallbackData = await fallbackResponse.json() as SocialApiResponse;\n\t\tconst profile: Profile | undefined = fallbackData?.[accountId]?.profile;\n\n\t\tif (profile) {\n\t\t\treturn {\n\t\t\t\tname: profile.name,\n\t\t\t\tdescription: profile.description,\n\t\t\t\timage: profile.image,\n\t\t\t\tbackgroundImage: profile.backgroundImage,\n\t\t\t\tlinktree: profile.linktree\n\t\t\t};\n\t\t}\n\t\treturn null;\n\t} catch (error) {\n\t\treturn null;\n\t}\n}\n\nexport { defaultGetProfile, getImageUrl, getNetworkFromAccountId };\n","import type { BetterAuthPluginDBSchema } from \"better-auth/db\";\n\nexport const schema = {\n\tnearAccount: {\n\t\tfields: {\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\taccountId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tnetwork: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tpublicKey: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tisPrimary: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdefaultValue: false,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t},\n\t},\n\trelayedTransaction: {\n\t\tfields: {\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t},\n\t\t\ttxHash: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tsenderId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\treceiverId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tnetwork: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tstatus: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tgasUsed: {\n\t\t\t\ttype: \"string\",\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tupdatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t},\n\t\t},\n\t},\n\trelayerKey: {\n\t\tfields: {\n\t\t\taccountId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tencryptedPrivateKey: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tiv: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tpublicKey: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tnetwork: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tlastUsedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n","import { z } from \"zod\";\nimport { AccountIdSchema, type AccountId } from \"near-kit/schemas\";\nimport type { AccountState, Near, TransactionBuilder } from \"near-kit\";\n\nexport type { AccountId };\n\nexport interface NearAccount {\n\tid: string;\n\tuserId: string;\n\taccountId: string;\n\tnetwork: \"mainnet\" | \"testnet\";\n\tpublicKey: string;\n\tisPrimary: boolean;\n\tcreatedAt: Date;\n}\n\nexport interface ListedNearAccount extends NearAccount {\n\tproviderId: \"siwn\";\n\tisActive: boolean;\n\tisAvailable: boolean;\n}\n\nexport interface ListAccountsResponseT {\n\taccounts: ListedNearAccount[];\n\tactiveAccount: ListedNearAccount | null;\n\tavailableAccounts: ListedNearAccount[];\n}\n\nexport interface SetPrimaryAccountResponseT extends ListAccountsResponseT {\n\tsuccess: boolean;\n\taccountId: string;\n\tnetwork: \"mainnet\" | \"testnet\";\n\tmessage: string;\n}\n\nexport const socialImageSchema = z.object({\n\turl: z.string().optional(),\n\tipfs_cid: z.string().optional(),\n});\n\nexport const profileSchema = z.object({\n\tname: z.string().optional(),\n\tdescription: z.string().optional(),\n\timage: socialImageSchema.optional(),\n\tbackgroundImage: socialImageSchema.optional(),\n\tlinktree: z.record(z.string(), z.string()).optional(),\n});\n\nexport type SocialImage = z.infer<typeof socialImageSchema>;\nexport type Profile = z.infer<typeof profileSchema>;\n\nconst signedMessageSchema = z.object({\n\taccountId: z.string(),\n\tpublicKey: z.string(),\n\tsignature: z.string(),\n\tstate: z.string().optional(),\n});\n\nexport const LinkAccountRequest = z.object({\n\tsignedMessage: signedMessageSchema,\n\tmessage: z.string(),\n\trecipient: z.string(),\n\tnonce: z.string(),\n\taccountId: AccountIdSchema,\n\tcallbackUrl: z.string().optional(),\n});\n\nexport const SetPrimaryAccountRequest = z.object({\n\taccountId: AccountIdSchema,\n\tnetwork: z.enum([\"mainnet\", \"testnet\"]).optional(),\n});\n\nexport const NonceRequest = z.object({\n\taccountId: AccountIdSchema,\n\tnetworkId: z.union([z.literal(\"mainnet\"), z.literal(\"testnet\")])\n});\n\nexport const VerifyRequest = z.object({\n\tsignedMessage: signedMessageSchema,\n\tmessage: z.string(),\n\trecipient: z.string(),\n\tnonce: z.string(),\n\taccountId: AccountIdSchema,\n\tcallbackUrl: z.string().optional(),\n});\n\nexport const RelayRequest = z.object({\n\tpayload: z.string(),\n});\nexport type RelayRequestT = z.infer<typeof RelayRequest>;\n\nexport const RelayResponse = z.object({\n\ttxHash: z.string(),\n\tstatus: z.enum([\"pending\", \"completed\", \"failed\"]),\n});\nexport type RelayResponseT = z.infer<typeof RelayResponse>;\n\nexport const RelayStatusResponse = z.object({\n\tstatus: z.enum([\"pending\", \"completed\", \"failed\"]),\n\tgasUsed: z.string().optional(),\n\toutcome: z.unknown().optional(),\n});\nexport type RelayStatusResponseT = z.infer<typeof RelayStatusResponse>;\n\nexport const ViewContractRequest = z.object({\n\tcontractId: z.string(),\n\tmethodName: z.string(),\n\targs: z.record(z.string(), z.any()).optional(),\n});\nexport type ViewContractRequestT = z.infer<typeof ViewContractRequest>;\n\nexport const NonceResponse = z.object({ nonce: z.string() });\nexport const VerifyResponse = z.object({\n\ttoken: z.string(),\n\tsuccess: z.literal(true),\n\tuser: z.object({\n\t\tid: z.string(),\n\t\taccountId: AccountIdSchema,\n\t\tnetwork: z.union([z.literal(\"mainnet\"), z.literal(\"testnet\")]),\n\t}),\n});\nexport const ProfileResponse = profileSchema.nullable();\nexport const ViewContractResponse = z.object({ result: z.unknown() });\n\nexport const ProfileRequest = z.object({\n\taccountId: AccountIdSchema.optional(),\n});\nexport type ProfileRequestT = z.infer<typeof ProfileRequest>;\n\nexport type NonceRequestT = z.infer<typeof NonceRequest>;\nexport type NonceResponseT = z.infer<typeof NonceResponse>;\nexport type SetPrimaryAccountRequestT = z.infer<typeof SetPrimaryAccountRequest>;\nexport type VerifyRequestT = z.infer<typeof VerifyRequest>;\nexport type VerifyResponseT = z.infer<typeof VerifyResponse>;\nexport type ProfileResponseT = z.infer<typeof ProfileResponse>;\nexport type ViewContractResponseT = z.infer<typeof ViewContractResponse>;\n\nexport const RelayedTransactionSchema = z.object({\n\tid: z.string(),\n\tuserId: z.string(),\n\ttxHash: z.string(),\n\tsenderId: z.string(),\n\treceiverId: z.string(),\n\tnetwork: z.string(),\n\tstatus: z.string(),\n\tgasUsed: z.string().optional(),\n\tcreatedAt: z.string(),\n\tupdatedAt: z.string().optional(),\n});\nexport type RelayedTransactionT = z.infer<typeof RelayedTransactionSchema>;\n\nexport const RelayHistoryResponse = z.object({\n\ttransactions: z.array(RelayedTransactionSchema),\n});\nexport type RelayHistoryResponseT = z.infer<typeof RelayHistoryResponse>;\n\nexport interface RelayedTransactionRecord {\n\tid: string;\n\tuserId: string;\n\ttxHash: string;\n\tsenderId: string;\n\treceiverId: string;\n\tnetwork: \"mainnet\" | \"testnet\";\n\tstatus: string;\n\tgasUsed?: string;\n\tcreatedAt: Date;\n\tupdatedAt: Date;\n}\n\nexport interface RelayerInfo extends AccountState {\n\taccountId: string;\n\tmode: \"ephemeral\" | \"explicit\";\n\tnetwork: \"mainnet\" | \"testnet\";\n\tpublicKey: string;\n\thasKey: boolean;\n\tcreatedAt?: Date;\n\tlastUsedAt?: Date;\n\tparentAccount?: string;\n\tsubAccountAvailable?: boolean;\n}\n\nexport interface DualNetworkConfig<T> {\n\tmainnet: T;\n\ttestnet: T;\n}\n\nexport const GetRelayerInfoRequest = z.object({\n\tnetwork: z.enum([\"mainnet\", \"testnet\"]).optional(),\n});\nexport type GetRelayerInfoRequestT = z.infer<typeof GetRelayerInfoRequest>;\n\nexport interface SubAccountRelayerFCAKConfig {\n\treceiverId: string;\n\tmethodNames?: string[];\n\tallowance?: string;\n}\n\nexport interface SubAccountTxCtx {\n\tnewAccountId: string;\n\tparentAccount: string;\n\tuserPublicKey: string;\n\tuserAccountId: string;\n\tuserId: string;\n\tnetwork: \"mainnet\" | \"testnet\";\n}\n\nexport interface SubAccountLifecycleCtx extends SubAccountTxCtx {\n\tnear: Near;\n}\n\nexport interface SubAccountConfig {\n\tparentAccount?: string;\n\tminDeposit?: string;\n\tparentHasFullAccess?: boolean;\n\tdeploy?:\n\t\t| { wasm: Uint8Array }\n\t\t| { fromPublished: { accountId?: string; codeHash?: string } };\n\tinit?: {\n\t\tmethodName: string;\n\t\targs: object | ((ctx: SubAccountTxCtx) => object);\n\t};\n\textendTx?: (tx: TransactionBuilder, ctx: SubAccountTxCtx) => TransactionBuilder;\n\tonCreated?: (ctx: SubAccountLifecycleCtx) => Promise<void>;\n\tonRollback?: (ctx: SubAccountLifecycleCtx) => Promise<void>;\n\taddRelayerFCAK?: boolean;\n\trelayerFCAK?: SubAccountRelayerFCAKConfig;\n}\n\nexport const SUB_ACCOUNT_LABEL_REGEX = /^([a-z\\d]+[-_])*[a-z\\d]+$/;\n\nexport const SubAccountNameSchema = z\n\t.string()\n\t.min(2, \"Sub-account name must be at least 2 characters\")\n\t.max(64, \"Sub-account name must be at most 64 characters\")\n\t.regex(SUB_ACCOUNT_LABEL_REGEX, \"Sub-account name must contain only lowercase alphanumeric characters, hyphens, and underscores (no leading/trailing hyphens or underscores)\");\n\nexport const CreateSubAccountRequest = z.object({\n\tsubAccountName: SubAccountNameSchema,\n\tnetwork: z.enum([\"mainnet\", \"testnet\"]).optional(),\n\tpublicKey: z.string(),\n});\nexport type CreateSubAccountRequestT = z.infer<typeof CreateSubAccountRequest>;\n\nexport const CreateSubAccountResponse = z.object({\n\tsuccess: z.literal(true),\n\taccountId: z.string(),\n\tnetwork: z.enum([\"mainnet\", \"testnet\"]),\n\tpublicKey: z.string(),\n\tmessage: z.string(),\n});\nexport type CreateSubAccountResponseT = z.infer<typeof CreateSubAccountResponse>;\n\nexport const CheckSubAccountAvailabilityRequest = z.object({\n\tsubAccountName: SubAccountNameSchema,\n\tnetwork: z.enum([\"mainnet\", \"testnet\"]).optional(),\n});\nexport type CheckSubAccountAvailabilityRequestT = z.infer<typeof CheckSubAccountAvailabilityRequest>;\n\nexport const CheckSubAccountAvailabilityResponse = z.object({\n\tavailable: z.boolean(),\n\taccountId: z.string(),\n\tparentAccount: z.string().optional(),\n\treason: z.enum([\"taken\", \"invalid\", \"too-long\", \"not-configured\"]).optional(),\n});\nexport type CheckSubAccountAvailabilityResponseT = z.infer<typeof CheckSubAccountAvailabilityResponse>;\n","export function bytesToBase64(bytes: Uint8Array): string {\n\treturn btoa(String.fromCharCode(...bytes));\n}\n\nfunction base64ToBytes(base64: string): Uint8Array {\n\treturn Uint8Array.from(atob(base64), c => c.charCodeAt(0));\n}\n\nexport function bytesToHex(bytes: Uint8Array): string {\n\treturn Array.from(bytes).map(b => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport function hexToBytes(hex: string): Uint8Array {\n\tconst bytes = new Uint8Array(hex.length / 2);\n\tfor (let i = 0; i < hex.length; i += 2) {\n\t\tbytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);\n\t}\n\treturn bytes;\n}\n\nasync function deriveAesKey(secret: string): Promise<CryptoKey> {\n\tconst keyMaterial = await crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tnew TextEncoder().encode(secret),\n\t\t{ name: \"HKDF\" },\n\t\tfalse,\n\t\t[\"deriveKey\"],\n\t);\n\treturn crypto.subtle.deriveKey(\n\t\t{\n\t\t\tname: \"HKDF\",\n\t\t\thash: \"SHA-256\",\n\t\t\tsalt: new TextEncoder().encode(\"better-near-auth-relayer\"),\n\t\t\tinfo: new Uint8Array(0),\n\t\t},\n\t\tkeyMaterial,\n\t\t{ name: \"AES-GCM\", length: 256 },\n\t\tfalse,\n\t\t[\"encrypt\", \"decrypt\"],\n\t);\n}\n\nexport async function encryptPrivateKey(\n\tprivateKey: Uint8Array,\n\tsecret: string,\n): Promise<{ encrypted: string; iv: string }> {\n\tconst aesKey = await deriveAesKey(secret);\n\tconst iv = crypto.getRandomValues(new Uint8Array(12));\n\tconst encrypted = await crypto.subtle.encrypt(\n\t\t{ name: \"AES-GCM\", iv },\n\t\taesKey,\n\t\tprivateKey as Uint8Array<ArrayBuffer>,\n\t);\n\treturn {\n\t\tencrypted: bytesToBase64(new Uint8Array(encrypted)),\n\t\tiv: bytesToBase64(iv),\n\t};\n}\n\nexport async function decryptPrivateKey(\n\tencrypted: string,\n\tiv: string,\n\tsecret: string,\n): Promise<Uint8Array> {\n\tconst aesKey = await deriveAesKey(secret);\n\tconst decrypted = await crypto.subtle.decrypt(\n\t\t{ name: \"AES-GCM\", iv: base64ToBytes(iv) as Uint8Array<ArrayBuffer> },\n\t\taesKey,\n\t\tbase64ToBytes(encrypted) as Uint8Array<ArrayBuffer>,\n\t);\n\treturn new Uint8Array(decrypted);\n}\n","import { APIError, createAuthEndpoint, createAuthMiddleware, getSessionFromCtx, sessionMiddleware } from \"better-auth/api\";\nimport { setSessionCookie } from \"better-auth/cookies\";\nimport type { Account, User, DBAdapter } from \"better-auth/types\";\n// Explicit type imports for declaration emit\nimport type {} from \"@better-auth/core/env\";\nimport type {} from \"@better-auth/core/oauth2\";\nimport type {} from \"better-call\";\n\nimport { Near, generateNonce, generateKey, parseKey, verifyNep413Signature, decodeSignedDelegateAction, InMemoryKeyStore } from \"near-kit\";\nimport type { SignedDelegateAction, PrivateKey } from \"near-kit\";\nimport { hex, base58 } from \"@scure/base\";\nimport z from \"zod\";\nimport { defaultGetProfile, getImageUrl, getNetworkFromAccountId } from \"./profile.js\";\nimport { schema } from \"./schema.js\";\nimport {\n\ttype AccountId,\n\ttype DualNetworkConfig,\n\ttype ListAccountsResponseT,\n\ttype ListedNearAccount,\n\ttype NearAccount,\n\ttype Profile,\n\ttype RelayerInfo,\n\ttype RelayedTransactionRecord,\n\ttype SubAccountConfig,\n\tLinkAccountRequest,\n\tNonceRequest,\n\tNonceResponse,\n\tProfileRequest,\n\tProfileResponse,\n\tVerifyRequest,\n\tVerifyResponse,\n\tRelayRequest,\n\tRelayResponse,\n\tRelayStatusResponse,\n\tSetPrimaryAccountRequest,\n\tViewContractRequest,\n\tViewContractResponse,\n\tGetRelayerInfoRequest,\n\tCreateSubAccountRequest,\n\tCreateSubAccountResponse,\n\tCheckSubAccountAvailabilityRequest,\n\tCheckSubAccountAvailabilityResponse,\n\ttype SubAccountTxCtx,\n\ttype SubAccountLifecycleCtx,\n} from \"./types.js\";\nexport * from \"./types.js\";\nimport {\n\tbytesToHex,\n\tencryptPrivateKey,\n\tdecryptPrivateKey,\n} from \"./utils.js\";\n\nasync function hashNonce(nonce: Uint8Array): Promise<string> {\n\tconst data = new TextEncoder().encode(hex.encode(nonce));\n\tconst hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\treturn hex.encode(new Uint8Array(hashBuffer));\n}\n\nfunction deriveEmail(accountId: string, recipient: string): string {\n\tif (accountId.endsWith(\".near\")) {\n\t\tconst localPart = accountId.slice(0, -5);\n\t\tif (!localPart.includes(\".\")) {\n\t\t\treturn `${localPart}@near.email`;\n\t\t}\n\t}\n\tconst randomId = crypto.randomUUID().slice(0, 8);\n\treturn `temp-${randomId}@${recipient}`;\n}\n\nfunction nearAccountKey(account: Pick<NearAccount, \"accountId\" | \"network\">): string {\n\treturn `${account.accountId}:${account.network}`;\n}\n\nfunction getCreatedAtTime(account: NearAccount): number {\n\treturn account.createdAt instanceof Date\n\t\t? account.createdAt.getTime()\n\t\t: new Date(account.createdAt).getTime();\n}\n\nfunction buildListAccountsResponse(nearAccounts: NearAccount[]): ListAccountsResponseT {\n\tconst activeAccount = nearAccounts.find((account) => account.isPrimary) ?? nearAccounts[0] ?? null;\n\tconst activeKey = activeAccount ? nearAccountKey(activeAccount) : null;\n\tconst accounts: ListedNearAccount[] = nearAccounts\n\t\t.map((account) => {\n\t\t\tconst isActive = activeKey === nearAccountKey(account);\n\t\t\treturn {\n\t\t\t\t...account,\n\t\t\t\tproviderId: \"siwn\" as const,\n\t\t\t\tisActive,\n\t\t\t\tisAvailable: !isActive,\n\t\t\t};\n\t\t})\n\t\t.sort((a, b) => {\n\t\t\tif (a.isActive !== b.isActive) return a.isActive ? -1 : 1;\n\t\t\treturn getCreatedAtTime(a) - getCreatedAtTime(b);\n\t\t});\n\tconst listedActiveAccount = accounts.find((account) => account.isActive) ?? null;\n\n\treturn {\n\t\taccounts,\n\t\tactiveAccount: listedActiveAccount ? { ...listedActiveAccount } : null,\n\t\tavailableAccounts: accounts\n\t\t\t.filter((account) => account.isAvailable)\n\t\t\t.map((account) => ({ ...account })),\n\t};\n}\n\ninterface RelayerConfig {\n\taccountId?: string;\n\tprivateKey?: string;\n\twhitelistedContracts?: string[];\n\tmaxGasPerTransaction?: string;\n\tmaxDepositPerTransaction?: string;\n}\n\ninterface RelayerDualNetworkConfig {\n\tmainnet?: RelayerConfig;\n\ttestnet?: RelayerConfig;\n}\n\nexport type { RelayerConfig, RelayerDualNetworkConfig };\n\ninterface RelayerState {\n\tnear: Near;\n\taccountId: string;\n\tnetwork: \"mainnet\" | \"testnet\";\n\tmode: \"ephemeral\" | \"explicit\";\n\tpublicKey: string;\n\twhitelistedContracts?: string[];\n\tmaxGasPerTransaction?: string;\n\tmaxDepositPerTransaction?: string;\n\tcreatedAt?: Date;\n\tlastUsedAt?: Date;\n}\n\nfunction isRelayerDualNetworkConfig(\n\tcfg: RelayerConfig | RelayerDualNetworkConfig,\n): cfg is RelayerDualNetworkConfig {\n\treturn (\n\t\ttypeof cfg === \"object\" &&\n\t\tcfg !== null &&\n\t\t\"mainnet\" in cfg &&\n\t\ttypeof (cfg as RelayerDualNetworkConfig).mainnet === \"object\"\n\t);\n}\n\nfunction createNear(\n\tnetwork: \"mainnet\" | \"testnet\",\n\theaders: Record<string, string>,\n\trpcUrl?: string,\n\tkeyStore?: InMemoryKeyStore,\n): Near {\n\tconst config: ConstructorParameters<typeof Near>[0] = { headers };\n\tif (rpcUrl) {\n\t\tconfig.network = { rpcUrl, networkId: network };\n\t} else {\n\t\tconfig.network = network;\n\t}\n\tif (keyStore) {\n\t\tconfig.keyStore = keyStore;\n\t}\n\treturn new Near(config);\n}\n\nasync function initRelayer(\n\trelayerConfig: RelayerConfig | RelayerDualNetworkConfig | undefined,\n\tnetwork: \"mainnet\" | \"testnet\",\n\tadapter: DBAdapter,\n\tsecret: string | undefined,\n\tapiKey?: string,\n\trpcUrl?: string,\n): Promise<RelayerState | null> {\n\tif (!relayerConfig) return null;\n\n\tconst headers: Record<string, string> = {};\n\tif (apiKey) {\n\t\theaders[\"Authorization\"] = `Bearer ${apiKey}`;\n\t}\n\n\tlet networkConfig: RelayerConfig | undefined;\n\tif (isRelayerDualNetworkConfig(relayerConfig)) {\n\t\tnetworkConfig = network === \"mainnet\" ? relayerConfig.mainnet : relayerConfig.testnet;\n\t} else {\n\t\tnetworkConfig = relayerConfig;\n\t}\n\tif (!networkConfig) return null;\n\n\tif (networkConfig.accountId && networkConfig.privateKey) {\n\t\tconst keyStore = new InMemoryKeyStore({\n\t\t\t[networkConfig.accountId]: networkConfig.privateKey,\n\t\t});\n\n\t\tconst near = createNear(network, headers, rpcUrl, keyStore);\n\t\tconst explicitPublicKey = parseKey(networkConfig.privateKey);\n\t\treturn {\n\t\t\tnear,\n\t\t\taccountId: networkConfig.accountId,\n\t\t\tnetwork,\n\t\t\tmode: \"explicit\",\n\t\t\tpublicKey: explicitPublicKey.publicKey.toString(),\n\t\t\twhitelistedContracts: networkConfig.whitelistedContracts,\n\t\t\tmaxGasPerTransaction: networkConfig.maxGasPerTransaction,\n\t\t\tmaxDepositPerTransaction: networkConfig.maxDepositPerTransaction,\n\t\t};\n\t}\n\n\tif (networkConfig.accountId && !networkConfig.privateKey) {\n\t\tconsole.warn(\n\t\t\t`[siwn] Relayer accountId \"${networkConfig.accountId}\" is set for ${network} but no privateKey was provided. Falling back to ephemeral mode. Set the relayer privateKey in your SIWN plugin options to use explicit mode.`,\n\t\t);\n\t}\n\n\tconst existing = await adapter.findOne<{ encryptedPrivateKey: string; iv: string; createdAt: Date; lastUsedAt: Date }>({\n\t\tmodel: \"relayerKey\",\n\t\twhere: [{ field: \"network\", operator: \"eq\", value: network }],\n\t});\n\n\tif (existing) {\n\t\tif (!secret) throw new Error(\"BETTER_AUTH_SECRET required for relayer key decryption\");\n\t\tconst privateKeyBytes = await decryptPrivateKey(existing.encryptedPrivateKey, existing.iv, secret);\n\t\tconst keyPair = parseKey(`ed25519:${base58.encode(privateKeyBytes)}`);\n\t\tconst accountId = bytesToHex(keyPair.publicKey.data);\n\n\t\tconsole.log(`[siwn] Relayer recovered: ${accountId} (${network})`);\n\n\t\tconst keyStore = new InMemoryKeyStore();\n\t\tawait keyStore.add(accountId, keyPair);\n\n\t\tconst near = createNear(network, headers, rpcUrl, keyStore);\n\t\treturn {\n\t\t\tnear,\n\t\t\taccountId,\n\t\t\tnetwork,\n\t\t\tmode: \"ephemeral\",\n\t\t\tpublicKey: keyPair.publicKey.toString(),\n\t\t\twhitelistedContracts: networkConfig.whitelistedContracts,\n\t\t\tmaxGasPerTransaction: networkConfig.maxGasPerTransaction,\n\t\t\tmaxDepositPerTransaction: networkConfig.maxDepositPerTransaction,\n\t\t\tcreatedAt: existing.createdAt,\n\t\t\tlastUsedAt: existing.lastUsedAt,\n\t\t};\n\t}\n\n\tconst keyPair = generateKey();\n\tif (!secret) throw new Error(\"BETTER_AUTH_SECRET required for relayer key encryption\");\n\tconst privateKeyBytes = keyPair.secretKey.startsWith(\"ed25519:\")\n\t\t? base58.decode(keyPair.secretKey.slice(8))\n\t\t: new Uint8Array(0);\n\n\tconst publicKeyBase58 = keyPair.publicKey.toString().replace(\"ed25519:\", \"\");\n\tconst accountId = bytesToHex(keyPair.publicKey.data);\n\tconst createdAt = new Date();\n\n\tconst { encrypted, iv } = await encryptPrivateKey(privateKeyBytes, secret);\n\n\tawait adapter.create({\n\t\t\tmodel: \"relayerKey\",\n\t\t\tdata: {\n\t\t\t\taccountId,\n\t\t\t\tencryptedPrivateKey: encrypted,\n\t\t\t\tiv,\n\t\t\t\tpublicKey: `ed25519:${publicKeyBase58}`,\n\t\t\t\tnetwork,\n\t\t\t\tcreatedAt,\n\t\t\t\tlastUsedAt: createdAt,\n\t\t\t},\n\t\t});\n\n\tconsole.log(`[siwn] Relayer created in EPHEMERAL mode: ${accountId} (${network})`);\n\tconsole.log(`[siwn] Fund this account with NEAR to enable gasless relay`);\n\tconsole.log(`[siwn] Private key is encrypted in DB — persists across restarts`);\n\n\tconst keyStore = new InMemoryKeyStore();\n\tawait keyStore.add(accountId, keyPair);\n\n\tconst near = createNear(network, headers, rpcUrl, keyStore);\n\treturn {\n\t\tnear,\n\t\taccountId,\n\t\tnetwork,\n\t\tmode: \"ephemeral\",\n\t\tpublicKey: keyPair.publicKey.toString(),\n\t\twhitelistedContracts: networkConfig.whitelistedContracts,\n\t\tmaxGasPerTransaction: networkConfig.maxGasPerTransaction,\n\t\tmaxDepositPerTransaction: networkConfig.maxDepositPerTransaction,\n\t\tcreatedAt,\n\t\tlastUsedAt: createdAt,\n\t};\n}\n\nasync function relayOnChain(\n\tpayload: string,\n\trelayerState: RelayerState,\n): Promise<{ txHash: string }> {\n\tconst userAction = decodeSignedDelegateAction(payload);\n\n\tconst result = await relayerState.near\n\t\t.transaction(relayerState.accountId)\n\t\t.signedDelegateAction(userAction)\n\t\t.send({ waitUntil: \"EXECUTED\" });\n\n\treturn { txHash: result.transaction.hash };\n}\n\nasync function defaultValidateLimitedAccessKey(\n\taccountId: string,\n\tpublicKey: string,\n\trecipient: string,\n\tnear: Near,\n): Promise<boolean> {\n\tconst key = await near.getAccessKey(accountId, publicKey);\n\tif (!key) return false;\n\tif (key.permission === \"FullAccess\") return true;\n\tif (\"FunctionCall\" in key.permission) {\n\t\treturn key.permission.FunctionCall.receiver_id === recipient;\n\t}\n\treturn false;\n}\n\nfunction isImplicitAccount(accountId: string): boolean {\n\treturn /^[0-9a-f]{64}$/.test(accountId);\n}\n\nfunction resolveParentAccount(\n\tsubAccountCfg: SubAccountConfig | undefined,\n\tparentKey: string | undefined,\n\trState: RelayerState | null,\n): { parentAccount: string | null; subAccountAvailable: boolean } {\n\tconst parent = subAccountCfg?.parentAccount ?? rState?.accountId;\n\tif (!parent || isImplicitAccount(parent)) {\n\t\treturn { parentAccount: null, subAccountAvailable: false };\n\t}\n\tif (!rState && !parentKey) {\n\t\treturn { parentAccount: null, subAccountAvailable: false };\n\t}\n\treturn { parentAccount: parent, subAccountAvailable: true };\n}\n\nexport interface SIWNPluginOptions {\n\trecipient?: string;\n\trecipients?: DualNetworkConfig<string>;\n\trequireFullAccessKey?: boolean;\n\tgetNonce?: () => Promise<Uint8Array>;\n\tgetProfile?: (accountId: AccountId) => Promise<Profile | null>;\n\tvalidateLimitedAccessKey?: (args: {\n\t\taccountId: AccountId;\n\t\tpublicKey: string;\n\t\trecipient?: string;\n\t}) => Promise<boolean>;\n\tapiKey?: string;\n\trpcUrl?: string | DualNetworkConfig<string>;\n\trelayer?: RelayerConfig | RelayerDualNetworkConfig;\n\tsecrets?: {\n\t\tparentKey?: string | DualNetworkConfig<string>;\n\t};\n\tsubAccount?: SubAccountConfig | DualNetworkConfig<SubAccountConfig>;\n}\n\nexport const siwn = (options: SIWNPluginOptions) => {\n\tif (!options.recipient && !options.recipients) {\n\t\tthrow new Error(\"Either 'recipient' or 'recipients' must be provided to siwn plugin\");\n\t}\n\n\tconst apiKey = options.apiKey;\n\n\tconst getRecipient = (network: \"mainnet\" | \"testnet\"): string => {\n\t\tif (options.recipients) return options.recipients[network];\n\t\treturn options.recipient!;\n\t};\n\n\tconst getSupportedNetworks = (): (\"mainnet\" | \"testnet\")[] => {\n\t\tif (options.recipients) return [\"mainnet\", \"testnet\"];\n\t\tif (options.recipient) return [getNetworkFromAccountId(options.recipient)];\n\t\treturn [\"mainnet\"];\n\t};\n\n\tconst getRelayerConfig = (network: \"mainnet\" | \"testnet\"): RelayerConfig | undefined => {\n\t\tif (!options.relayer) return undefined;\n\t\tif (isRelayerDualNetworkConfig(options.relayer)) {\n\t\t\treturn options.relayer[network];\n\t\t}\n\t\treturn options.relayer;\n\t};\n\n\tconst getRpcUrl = (network: \"mainnet\" | \"testnet\"): string | undefined => {\n\t\tif (!options.rpcUrl) return undefined;\n\t\tif (typeof options.rpcUrl === \"object\") return (options.rpcUrl as DualNetworkConfig<string>)[network];\n\t\treturn options.rpcUrl as string;\n\t};\n\n\tconst getSubAccountConfig = (network: \"mainnet\" | \"testnet\"): SubAccountConfig | undefined => {\n\t\tif (!options.subAccount) return undefined;\n\t\tif (\"mainnet\" in options.subAccount && typeof options.subAccount.mainnet === \"object\") {\n\t\t\treturn (options.subAccount as DualNetworkConfig<SubAccountConfig>)[network];\n\t\t}\n\t\treturn options.subAccount as SubAccountConfig;\n\t};\n\n\tconst getParentKey = (network: \"mainnet\" | \"testnet\"): string | undefined => {\n\t\tif (!options.secrets?.parentKey) return undefined;\n\t\tif (typeof options.secrets.parentKey === \"object\") {\n\t\t\treturn (options.secrets.parentKey as DualNetworkConfig<string>)[network];\n\t\t}\n\t\treturn options.secrets.parentKey as string;\n\t};\n\n\tconst getRawParentKey = (network: \"mainnet\" | \"testnet\"): string | undefined => {\n\t\tconst fromSecrets = getParentKey(network);\n\t\tif (fromSecrets) return fromSecrets;\n\t\tconst relayerCfg = getRelayerConfig(network);\n\t\tconst subAccountCfg = getSubAccountConfig(network);\n\n\t\tif (!relayerCfg || !relayerCfg.accountId || !relayerCfg.privateKey) return undefined;\n\n\t\tconst parent = subAccountCfg?.parentAccount ?? relayerCfg.accountId;\n\t\tif (parent && parent === relayerCfg.accountId) {\n\t\t\treturn relayerCfg.privateKey;\n\t\t}\n\t\treturn undefined;\n\t};\n\n\tconst primaryNetwork = getSupportedNetworks()[0];\n\tconst relayerStates = new Map<\"mainnet\" | \"testnet\", RelayerState | null>();\n\tconst relayerInitPromises = new Map<\"mainnet\" | \"testnet\", Promise<RelayerState | null>>();\n\n\tconst headers: Record<string, string> = {};\n\tif (apiKey) {\n\t\theaders[\"Authorization\"] = `Bearer ${apiKey}`;\n\t}\n\n\tconst ensureRelayer = async (adapter: DBAdapter, secret: string | undefined, network: \"mainnet\" | \"testnet\") => {\n\t\tif (relayerStates.has(network)) return relayerStates.get(network) ?? null;\n\n\t\tconst existingInit = relayerInitPromises.get(network);\n\t\tif (existingInit) return existingInit;\n\n\t\tconst relayerCfg = getRelayerConfig(network);\n\t\tconst networkRpcUrl = getRpcUrl(network);\n\n\tconst initPromise = initRelayer(relayerCfg, network, adapter, secret, apiKey, networkRpcUrl)\n\t\t.then((state) => {\n\t\t\trelayerStates.set(network, state);\n\t\t\trelayerInitPromises.delete(network);\n\t\t\tif (state) {\n\t\t\t\tconsole.log(`[siwn] Relayer initialized: ${state.accountId} (${network}, ${state.mode})`);\n\t\t\t\tif (state.mode === \"ephemeral\") {\n\t\t\t\t\tconsole.log(`[siwn] Fund this account with NEAR to enable gasless relay`);\n\t\t\t\t\tconsole.log(`[siwn] Private key is encrypted in DB — persists across restarts`);\n\t\t\t\t}\n\t\t\t} else if (relayerCfg) {\n\t\t\t\tconsole.warn(`[siwn] Relayer config provided but not initialized for ${network}. Check BETTER_AUTH_SECRET for ephemeral mode.`);\n\t\t\t}\n\t\t\treturn state;\n\t\t})\n\t\t.catch((error) => {\n\t\t\trelayerInitPromises.delete(network);\n\t\t\tconsole.error(`[siwn] Failed to initialize relayer for ${network}:`, error);\n\t\t\tthrow error;\n\t\t});\n\n\t\trelayerInitPromises.set(network, initPromise);\n\t\treturn initPromise;\n\t};\n\n\tconst getNear = (network: \"mainnet\" | \"testnet\") => {\n\t\tconst networkRpcUrl = getRpcUrl(network);\n\t\tif (networkRpcUrl) {\n\t\t\treturn new Near({ network: { rpcUrl: networkRpcUrl, networkId: network }, headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined });\n\t\t}\n\t\treturn new Near({ network, headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined });\n\t};\n\n\treturn ({\n\t\tid: \"siwn\",\n\t\tschema,\n\t\thooks: {\n\t\t\tafter: [\n\t\t\t\t{\n\t\t\t\t\tmatcher: (context: { path?: string; method?: string }) => context.path === \"/auth/session\" && context.method === \"GET\",\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\tconst session = ctx.context.session;\n\t\t\t\t\t\tif (session) {\n\t\t\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (nearAccount) {\n\t\t\t\t\t\t\t\tctx.context.session = {\n\t\t\t\t\t\t\t\t\t...session,\n\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t...session.user,\n\t\t\t\t\t\t\t\t\t\tnearAccount: nearAccount\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn { context: ctx };\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\tendpoints: {\n\t\t\tlinkNearAccount: createAuthEndpoint(\n\t\t\t\t\"/near/link-account\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: LinkAccountRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t\trequireRequest: true,\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { signedMessage, message, recipient, nonce, accountId, callbackUrl } = ctx.body;\n\t\t\t\t\tconst network = getNetworkFromAccountId(accountId);\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tif (!session) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Must be logged in to link NEAR account\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\t\tconst nonceBytes = hex.decode(nonce);\n\n\t\t\t\t\t\tconst isValid = await verifyNep413Signature(\n\t\t\t\t\t\tsignedMessage,\n\t\t\t\t\t\t{ message, recipient, nonce: nonceBytes, callbackUrl },\n\t\t\t\t\t\t\t{ near, maxAge: 15 * 60 * 1000 },\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (!isValid) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Invalid signature\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (signedMessage.accountId !== accountId) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Account ID mismatch\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst publicKey = signedMessage.publicKey;\n\n\t\t\t\t\t\tif (!options.requireFullAccessKey && options.validateLimitedAccessKey) {\n\t\t\t\t\t\t\tconst isValidKey = await options.validateLimitedAccessKey({\n\t\t\t\t\t\t\t\taccountId: accountId,\n\t\t\t\t\t\t\t\tpublicKey: publicKey,\n\t\t\t\t\t\t\t\trecipient: options.recipient\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (!isValidKey) {\n\t\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Invalid function call access key\",\n\t\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst existingNearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t\t{ field: \"network\", operator: \"eq\", value: network },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (existingNearAccount) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: \"This NEAR account is already linked to another user\",\n\t\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst existingPrimaryAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t\tpublicKey: publicKey,\n\t\t\t\t\t\t\t\tisPrimary: !existingPrimaryAccount,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\t\tproviderId: \"siwn\",\n\t\t\t\t\t\t\taccountId: `${accountId}:${network}`,\n\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\tmessage: \"NEAR account successfully linked\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tif (error instanceof APIError) throw error;\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Something went wrong. Please try again later.\",\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : \"Unknown error\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t\tunlinkNearAccount: createAuthEndpoint(\n\t\t\t\t\"/near/unlink-account\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: z.object({\n\t\t\t\t\t\taccountId: z.string(),\n\t\t\t\t\t\tnetwork: z.enum([\"mainnet\", \"testnet\"]).optional(),\n\t\t\t\t\t}),\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { accountId, network: providedNetwork } = ctx.body;\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tif (!session) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Must be logged in to unlink NEAR account\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst network = providedNetwork || getNetworkFromAccountId(accountId);\n\n\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t{ field: \"network\", operator: \"eq\", value: network },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!nearAccount) {\n\t\t\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\t\t\tmessage: \"NEAR account not found or not linked to your user\",\n\t\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst accounts = await ctx.context.adapter.findMany({\n\t\t\t\t\t\tmodel: \"account\",\n\t\t\t\t\t\twhere: [{ field: \"userId\", operator: \"eq\", value: session.user.id }],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (accounts.length <= 1) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: \"Cannot unlink last authentication method. Link another account first.\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (nearAccount.isPrimary) {\n\t\t\t\t\t\tconst otherNearAccounts: NearAccount[] = await ctx.context.adapter.findMany({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"ne\", value: accountId },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (otherNearAccounts.length > 0) {\n\t\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{ field: \"id\", operator: \"eq\", value: otherNearAccounts[0]!.id },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\tupdate: { isPrimary: true },\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tawait ctx.context.adapter.delete({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t{ field: \"network\", operator: \"eq\", value: network },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst accountToDelete: Account | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"account\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"providerId\", operator: \"eq\", value: \"siwn\" },\n\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: `${accountId}:${network}` },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (accountToDelete) {\n\t\t\t\t\t\tawait ctx.context.internalAdapter.deleteAccount(accountToDelete.id);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\taccountId,\n\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\tmessage: \"NEAR account successfully unlinked\"\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t),\n\t\t\tlistNearAccounts: createAuthEndpoint(\n\t\t\t\t\"/near/list-accounts\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tconst nearAccounts: NearAccount[] = await ctx.context.adapter.findMany({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [{ field: \"userId\", operator: \"eq\", value: session.user.id }],\n\t\t\t\t\t});\n\n\t\t\t\t\treturn ctx.json(buildListAccountsResponse(nearAccounts));\n\t\t\t\t},\n\t\t\t),\n\t\t\tsetPrimaryNearAccount: createAuthEndpoint(\n\t\t\t\t\"/near/set-primary-account\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: SetPrimaryAccountRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { accountId, network: providedNetwork } = ctx.body;\n\t\t\t\t\tconst session = ctx.context.session;\n\t\t\t\t\tconst network = providedNetwork || getNetworkFromAccountId(accountId);\n\n\t\t\t\t\tconst targetAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t{ field: \"network\", operator: \"eq\", value: network },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!targetAccount) {\n\t\t\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\t\t\tmessage: \"NEAR account not found or not linked to your user\",\n\t\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nearAccounts: NearAccount[] = await ctx.context.adapter.findMany({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [{ field: \"userId\", operator: \"eq\", value: session.user.id }],\n\t\t\t\t\t});\n\n\t\t\t\t\tawait Promise.all(nearAccounts.map((account) => ctx.context.adapter.update({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [{ field: \"id\", operator: \"eq\", value: account.id }],\n\t\t\t\t\t\tupdate: { isPrimary: nearAccountKey(account) === nearAccountKey(targetAccount) },\n\t\t\t\t\t})));\n\n\t\t\t\t\tconst updatedNearAccounts: NearAccount[] = await ctx.context.adapter.findMany({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [{ field: \"userId\", operator: \"eq\", value: session.user.id }],\n\t\t\t\t\t});\n\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\taccountId,\n\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\tmessage: \"Primary NEAR account updated\",\n\t\t\t\t\t\t...buildListAccountsResponse(updatedNearAccounts),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t),\n\t\t\tgetSiwnNonce: createAuthEndpoint(\n\t\t\t\t\"/near/nonce\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: NonceRequest,\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { accountId, networkId } = ctx.body;\n\t\t\t\t\tconst network = getNetworkFromAccountId(accountId);\n\n\t\t\t\t\tif (networkId !== network) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: \"Network ID mismatch with account ID\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\tconst exists = await near.accountExists(accountId);\n\t\t\t\t\tif (!exists) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: \"Account does not exist on-chain\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nonce = options.getNonce ? await options.getNonce() : generateNonce();\n\n\t\t\t\t\tconst nonceString = hex.encode(nonce);\n\n\t\t\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\t\t\tidentifier: `siwn:${accountId}:${network}`,\n\t\t\t\t\t\tvalue: nonceString,\n\t\t\t\t\t\texpiresAt: new Date(Date.now() + 15 * 60 * 1000),\n\t\t\t\t\t});\n\n\t\t\t\t\treturn ctx.json(NonceResponse.parse({ nonce: nonceString }));\n\t\t\t\t},\n\t\t\t),\n\t\t\tgetSiwnProfile: createAuthEndpoint(\n\t\t\t\t\"/near/profile\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: ProfileRequest,\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { accountId } = ctx.body;\n\t\t\t\t\tlet targetAccountId = accountId;\n\n\t\t\t\t\tif (!targetAccountId) {\n\t\t\t\t\t\tconst result = await getSessionFromCtx(ctx);\n\t\t\t\t\t\tconst session = result?.session;\n\t\t\t\t\t\tif (!session) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Session required when no accountId provided\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (!nearAccount) {\n\t\t\t\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\t\t\t\tmessage: \"No NEAR account found for user\",\n\t\t\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttargetAccountId = nearAccount.accountId;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst profile = await (options.getProfile || ((id: AccountId) => defaultGetProfile(id, apiKey)))(targetAccountId);\n\t\t\t\t\treturn ctx.json(ProfileResponse.parse(profile));\n\t\t\t\t},\n\t\t\t),\n\t\t\tverifySiwnMessage: createAuthEndpoint(\n\t\t\t\t\"/near/verify\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: VerifyRequest,\n\t\t\t\t\trequireRequest: true,\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst {\n\t\t\t\t\t\tsignedMessage,\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t\trecipient,\n\t\t\t\t\t\tnonce,\n\t\t\t\t\t\taccountId,\n\t\t\t\t\t\tcallbackUrl,\n\t\t\t\t\t} = ctx.body;\n\t\t\t\t\tconst network = getNetworkFromAccountId(accountId);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\t\tconst nonceBytes = hex.decode(nonce);\n\n\t\t\t\t\t\tconst isValid = await verifyNep413Signature(\n\t\t\t\t\t\tsignedMessage,\n\t\t\t\t\t\t{ message, recipient, nonce: nonceBytes, callbackUrl },\n\t\t\t\t\t\t\t{ near, maxAge: 15 * 60 * 1000 },\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (!isValid) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Invalid signature\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (signedMessage.accountId !== accountId) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Account ID mismatch\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst publicKey = signedMessage.publicKey;\n\n\t\t\t\t\t\tconst nonceHash = await hashNonce(nonceBytes);\n\n\t\t\t\t\t\tconst existingNonce = await ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\t\t\t`siwn-nonce:${nonceHash}`\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (existingNonce) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Nonce already used (replay attack detected)\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t\tcode: \"UNAUTHORIZED_NONCE_REPLAY\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\t\t\t\tidentifier: `siwn-nonce:${nonceHash}`,\n\t\t\t\t\t\t\tvalue: \"used\",\n\t\t\t\t\t\t\texpiresAt: new Date(Date.now() + 15 * 60 * 1000),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (!options.requireFullAccessKey) {\n\t\t\t\t\t\t\tconst validateKey = options.validateLimitedAccessKey\n\t\t\t\t\t\t\t\t|| ((args: { accountId: string; publicKey: string; recipient?: string }) =>\n\t\t\t\t\t\t\t\t\tdefaultValidateLimitedAccessKey(args.accountId, args.publicKey, args.recipient || getRecipient(network), near));\n\n\t\t\t\t\t\t\tconst isValidKey = await validateKey({\n\t\t\t\t\t\t\t\taccountId: accountId,\n\t\t\t\t\t\t\t\tpublicKey: publicKey,\n\t\t\t\t\t\t\t\trecipient: options.recipient\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (!isValidKey) {\n\t\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\t\tmessage: \"Unauthorized: Invalid function call access key\",\n\t\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet user: User | null = null;\n\n\t\t\t\t\t\tconst existingNearAccount: NearAccount | null =\n\t\t\t\t\t\t\tawait ctx.context.adapter.findOne({\n\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t\t\t{ field: \"network\", operator: \"eq\", value: network },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (existingNearAccount) {\n\t\t\t\t\t\t\tuser = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t\t\t\t\t\toperator: \"eq\",\n\t\t\t\t\t\t\t\t\t\tvalue: existingNearAccount.userId,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst anyNearAccount: NearAccount | null =\n\t\t\t\t\t\t\t\tawait ctx.context.adapter.findOne({\n\t\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t\t{ field: \"accountId\", operator: \"eq\", value: accountId },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (anyNearAccount) {\n\t\t\t\t\t\t\t\tuser = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t\t\t\t\t\t\toperator: \"eq\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: anyNearAccount.userId,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!user) {\n\t\t\t\t\t\t\tconst userEmail = deriveEmail(accountId, getRecipient(network));\n\n\t\t\t\t\t\t\tconst profile = await (options.getProfile || ((id: AccountId) => defaultGetProfile(id, apiKey)))(accountId);\n\n\t\t\t\t\t\t\tuser = await ctx.context.internalAdapter.createUser({\n\t\t\t\t\t\t\t\tname: profile?.name ?? accountId,\n\t\t\t\t\t\t\t\temail: userEmail,\n\t\t\t\t\t\t\t\timage: profile?.image ? getImageUrl(profile.image) : \"\",\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t\t\tpublicKey: publicKey,\n\t\t\t\t\t\t\t\t\tisPrimary: true,\n\t\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t\t\tproviderId: \"siwn\",\n\t\t\t\t\t\t\t\taccountId: `${accountId}:${network}`,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (!existingNearAccount) {\n\t\t\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t\t\t\tpublicKey: publicKey,\n\t\t\t\t\t\t\t\t\t\tisPrimary: false,\n\t\t\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t\t\t\tproviderId: \"siwn\",\n\t\t\t\t\t\t\t\t\taccountId: `${accountId}:${network}`,\n\t\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait ensureRelayer(ctx.context.adapter, ctx.context.secret, network);\n\n\t\t\t\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\t\t\tuser.id\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (!session) {\n\t\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\t\tmessage: \"Internal Server Error\",\n\t\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tawait setSessionCookie(ctx, { session, user });\n\n\t\t\t\t\t\treturn ctx.json(VerifyResponse.parse({\n\t\t\t\t\t\t\ttoken: session.token,\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\tid: user.id,\n\t\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}));\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tif (error instanceof APIError) throw error;\n\t\t\t\t\t\tconst msg = error instanceof Error ? error.message : \"Unknown error\";\n\t\t\t\t\t\tconst at = error instanceof Error && error.stack ? error.stack.split(\"\\n\").slice(1, 3).map(s => s.trim()).join(\" <- \") : \"\";\n\t\t\t\t\t\tconsole.error(`[siwn] Verify error: ${msg}${at ? ` (${at})` : \"\"}`);\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Something went wrong. Please try again later.\",\n\t\t\t\t\t\t\terror: msg,\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t\trelayNearTransaction: createAuthEndpoint(\n\t\t\t\t\"/near/relay\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: RelayRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { payload } = ctx.body;\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tif (!session) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Must be authenticated to relay transactions\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!nearAccount) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"No NEAR account linked to session\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst network = nearAccount.network as \"mainnet\" | \"testnet\";\n\t\t\t\t\tconst rState = await ensureRelayer(ctx.context.adapter, ctx.context.secret, network);\n\n\t\t\t\t\tif (!rState) {\n\t\t\t\t\t\tthrow new APIError(\"SERVICE_UNAVAILABLE\", {\n\t\t\t\t\t\t\tmessage: \"Relayer not configured\",\n\t\t\t\t\t\t\tstatus: 503,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst decoded: SignedDelegateAction = decodeSignedDelegateAction(payload);\n\t\t\t\t\t\tconst delegateAction = decoded.signedDelegate.delegateAction;\n\n\t\t\t\t\t\tif (delegateAction.senderId !== nearAccount.accountId) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"Delegate action sender does not match session account\",\n\t\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst relayerConfigForNetwork = getRelayerConfig(network);\n\t\t\t\t\t\tconst whitelistedContracts = relayerConfigForNetwork?.whitelistedContracts;\n\t\t\t\t\t\tif (whitelistedContracts?.length) {\n\t\t\t\t\t\t\tif (!whitelistedContracts.includes(delegateAction.receiverId)) {\n\t\t\t\t\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\t\t\t\t\tmessage: `Contract ${delegateAction.receiverId} is not whitelisted for relay`,\n\t\t\t\t\t\t\t\t\tstatus: 403,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst maxGasPerTransaction = relayerConfigForNetwork?.maxGasPerTransaction;\n\t\t\t\t\t\tif (maxGasPerTransaction) {\n\t\t\t\t\t\t\tconst totalGas = delegateAction.actions.reduce((sum: bigint, a) => {\n\t\t\t\t\t\t\t\treturn sum + (\"functionCall\" in a ? a.functionCall.gas : 0n);\n\t\t\t\t\t\t\t}, 0n);\n\t\t\t\t\t\t\tif (totalGas > BigInt(maxGasPerTransaction)) {\n\t\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\t\tmessage: `Transaction gas (${totalGas}) exceeds relayer limit (${maxGasPerTransaction})`,\n\t\t\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst maxDepositPerTransaction = relayerConfigForNetwork?.maxDepositPerTransaction;\n\t\t\t\t\t\tif (maxDepositPerTransaction) {\n\t\t\t\t\t\t\tconst totalDeposit = delegateAction.actions.reduce((sum: bigint, a) => {\n\t\t\t\t\t\t\t\tif (\"functionCall\" in a) return sum + a.functionCall.deposit;\n\t\t\t\t\t\t\t\tif (\"transfer\" in a) return sum + a.transfer.deposit;\n\t\t\t\t\t\t\t\treturn sum;\n\t\t\t\t\t\t\t}, 0n);\n\t\t\t\t\t\t\tif (totalDeposit > BigInt(maxDepositPerTransaction)) {\n\t\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\t\tmessage: `Transaction deposit (${totalDeposit}) exceeds relayer limit (${maxDepositPerTransaction})`,\n\t\t\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst result = await relayOnChain(payload, rState);\n\n\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\tmodel: \"relayedTransaction\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\t\t\ttxHash: result.txHash,\n\t\t\t\t\t\t\t\tsenderId: delegateAction.senderId,\n\t\t\t\t\t\t\t\treceiverId: delegateAction.receiverId,\n\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\n\t\t\t\t\tif (rState.mode === \"ephemeral\") {\n\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\tmodel: \"relayerKey\",\n\t\t\t\t\t\t\twhere: [{ field: \"network\", operator: \"eq\", value: network }],\n\t\t\t\t\t\t\tupdate: { lastUsedAt: new Date() },\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t\treturn ctx.json(RelayResponse.parse({\n\t\t\t\t\t\t\ttxHash: result.txHash,\n\t\t\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t\t}));\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tif (error instanceof APIError) throw error;\n\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\tmessage: error instanceof Error ? error.message : \"Relay failed\",\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t\tgetRelayStatus: createAuthEndpoint(\n\t\t\t\t\"/near/relay-status/:txHash\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst txHash = (ctx.params as Record<string, string>)?.txHash;\n\t\t\t\t\tif (!txHash) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: \"Transaction hash required\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tconst relayedTx = await ctx.context.adapter.findOne<RelayedTransactionRecord>({\n\t\t\t\t\t\tmodel: \"relayedTransaction\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"txHash\", operator: \"eq\", value: txHash },\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!relayedTx) {\n\t\t\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\t\t\tmessage: \"Transaction not found or not owned by this user\",\n\t\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst network = relayedTx.network;\n\t\t\t\t\tconst senderId = relayedTx.senderId;\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\t\tconst txResult = await near.getTransactionStatus(txHash, senderId);\n\n\t\t\t\t\t\tconst txStatus = txResult.status;\n\t\t\t\t\t\tif (txStatus && typeof txStatus === \"object\") {\n\t\t\t\t\t\t\tconst hasSuccess = \"SuccessValue\" in txStatus || \"SuccessReceiptId\" in txStatus;\n\t\t\t\t\t\t\tconst hasFailure = \"Failure\" in txStatus;\n\t\t\t\t\t\t\tconst status = hasSuccess ? \"completed\" : hasFailure ? \"failed\" : \"pending\";\n\n\t\t\t\t\t\t\tif (status !== \"pending\") {\n\t\t\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\t\t\tmodel: \"relayedTransaction\",\n\t\t\t\t\t\t\t\t\twhere: [{ field: \"txHash\", operator: \"eq\", value: txHash }],\n\t\t\t\t\t\t\t\t\tupdate: { status },\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst gasUsed = txResult.transaction_outcome?.outcome?.gas_burnt?.toString();\n\n\t\t\t\t\t\t\treturn ctx.json(RelayStatusResponse.parse({\n\t\t\t\t\t\t\t\tstatus,\n\t\t\t\t\t\t\t\tgasUsed,\n\t\t\t\t\t\t\t\toutcome: txResult,\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn ctx.json(RelayStatusResponse.parse({ status: \"pending\" }));\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\treturn ctx.json(RelayStatusResponse.parse({ status: \"pending\" }));\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t\tgetRelayerInfo: createAuthEndpoint(\n\t\t\t\t\"/near/relayer-info\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: GetRelayerInfoRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { network: requestedNetwork } = ctx.body;\n\t\t\t\t\tconst targetNetwork = (requestedNetwork ?? primaryNetwork) as \"mainnet\" | \"testnet\";\n\t\t\t\t\tconst rState = await ensureRelayer(ctx.context.adapter, ctx.context.secret, targetNetwork);\n\n\t\t\t\t\tif (!rState) {\n\t\t\t\t\t\treturn ctx.json({ enabled: false, subAccountAvailable: false } satisfies Partial<RelayerInfo> & { enabled: boolean });\n\t\t\t\t\t}\n\n\t\t\t\t\tconst subAccountCfg = getSubAccountConfig(targetNetwork);\n\t\t\t\t\tconst parentKey = getParentKey(targetNetwork);\nconst { parentAccount, subAccountAvailable } = resolveParentAccount(subAccountCfg, parentKey, rState);\n\n\t\t\t\t\tconst near = getNear(rState.network);\n\t\t\t\t\tlet account;\n\t\t\t\t\ttry {\n\t\t\t\t\t\taccount = await near.getAccount(rState.accountId);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\taccount = {\n\t\t\t\t\t\t\tbalance: \"0\",\n\t\t\t\t\t\t\tavailable: \"0\",\n\t\t\t\t\t\t\tstaked: \"0\",\n\t\t\t\t\t\t\tstorageUsage: \"0\",\n\t\t\t\t\t\t\tstorageBytes: 0,\n\t\t\t\t\t\t\thasContract: false,\n\t\t\t\t\t\t\tcodeHash: \"\",\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\taccountId: rState.accountId,\n\t\t\t\t\t\tmode: rState.mode,\n\t\t\t\t\t\tnetwork: rState.network,\n\t\t\t\t\t\tpublicKey: rState.publicKey,\n\t\t\t\t\t\tbalance: account.balance,\n\t\t\t\t\t\tavailable: account.available,\n\t\t\t\t\t\tstaked: account.staked,\n\t\t\t\t\t\tstorageUsage: account.storageUsage,\n\t\t\t\t\t\tstorageBytes: account.storageBytes,\n\t\t\t\t\t\thasContract: account.hasContract,\n\t\t\t\t\t\thasKey: true,\n\t\t\t\t\t\tcreatedAt: rState.createdAt,\n\t\t\t\t\t\tlastUsedAt: rState.lastUsedAt,\n\t\t\t\t\t\tparentAccount: parentAccount ?? undefined,\n\t\t\t\t\t\tsubAccountAvailable,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t),\n\t\t\tgetRelayHistory: createAuthEndpoint(\n\t\t\t\t\"/near/relay-history\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tlet transactions: RelayedTransactionRecord[] = [];\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = await ctx.context.adapter.findMany<RelayedTransactionRecord>({\n\t\t\t\t\t\t\tmodel: \"relayedTransaction\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t\ttransactions = result || [];\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(\"relay-history findMany error:\", err);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst sorted = transactions.sort((a, b) => {\n\t\t\t\t\t\tconst aTime = a.createdAt instanceof Date ? a.createdAt.getTime() : new Date(a.createdAt ?? 0).getTime();\n\t\t\t\t\t\tconst bTime = b.createdAt instanceof Date ? b.createdAt.getTime() : new Date(b.createdAt ?? 0).getTime();\n\t\t\t\t\t\treturn bTime - aTime;\n\t\t\t\t\t});\n\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\ttransactions: sorted.map((tx) => ({\n\t\t\t\t\t\t\tid: String(tx.id ?? \"\"),\n\t\t\t\t\t\t\tuserId: String(tx.userId ?? \"\"),\n\t\t\t\t\t\t\ttxHash: String(tx.txHash ?? \"\"),\n\t\t\t\t\t\t\tsenderId: String(tx.senderId ?? \"\"),\n\t\t\t\t\t\t\treceiverId: String(tx.receiverId ?? \"\"),\n\t\t\t\t\t\t\tnetwork: String(tx.network ?? \"mainnet\"),\n\t\t\t\t\t\t\tstatus: String(tx.status ?? \"pending\"),\n\t\t\t\t\t\t\tgasUsed: tx.gasUsed ? String(tx.gasUsed) : undefined,\n\t\t\t\t\t\t\tcreatedAt: tx.createdAt instanceof Date ? tx.createdAt.toISOString() : tx.createdAt ? String(tx.createdAt) : new Date().toISOString(),\n\t\t\t\t\t\t\tupdatedAt: tx.updatedAt instanceof Date ? tx.updatedAt.toISOString() : tx.updatedAt ? String(tx.updatedAt) : undefined,\n\t\t\t\t\t\t})),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t),\n\t\t\tviewContract: createAuthEndpoint(\n\t\t\t\t\"/near/view\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: ViewContractRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { contractId, methodName, args } = ctx.body;\n\t\t\t\t\tconst session = ctx.context.session;\n\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst network = (nearAccount?.network || primaryNetwork) as \"mainnet\" | \"testnet\";\n\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\tlet result: unknown;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresult = await near.view(contractId, methodName, args ?? {});\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tif (error instanceof APIError) throw error;\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: error instanceof Error ? error.message : \"Unknown error\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json(ViewContractResponse.parse({ result }));\n\t\t\t\t},\n\t\t\t),\n\t\t\tcreateSubAccount: createAuthEndpoint(\n\t\t\t\t\"/near/create-sub-account\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: CreateSubAccountRequest,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst { subAccountName, network: providedNetwork, publicKey } = ctx.body;\n\t\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\t\tif (!session) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\tmessage: \"Must be authenticated to create a sub-account\",\n\t\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst network = (providedNetwork || nearAccount?.network || primaryNetwork) as \"mainnet\" | \"testnet\";\n\t\t\t\t\tconst subAccountCfg = getSubAccountConfig(network);\n\t\t\t\t\tconst userAccountId = nearAccount?.accountId ?? \"\";\n\t\t\t\t\tconst parentKey = getParentKey(network);\n\t\t\t\t\tconst rState = await ensureRelayer(ctx.context.adapter, ctx.context.secret, network);\n\t\t\t\t\tconst { parentAccount, subAccountAvailable } = resolveParentAccount(subAccountCfg, parentKey, rState);\n\n\t\t\t\t\tif (!subAccountAvailable || !parentAccount) {\n\t\t\t\t\t\tconst configuredParent = subAccountCfg?.parentAccount;\n\t\t\t\t\t\tlet msg: string;\n\t\t\t\t\t\tif (configuredParent && !parentKey) {\n\t\t\t\t\t\t\tmsg = `Sub-account creation unavailable on ${network}: parent key not configured for ${configuredParent}. Set NEAR_SUB_ACCOUNT_PARENT_KEY_${network.toUpperCase()} in your environment, or use an explicit relayer with a named account.`;\n\t\t\t\t\t\t} else if (!configuredParent) {\n\t\t\t\t\t\t\tmsg = `Sub-account creation unavailable on ${network}: no parent account configured. Set subAccount.${network}.parentAccount in your SIWN plugin options, or use an explicit relayer with a named account.`;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmsg = `Sub-account creation unavailable on ${network}: requires a named parent account with a parent key, or an explicit relayer with a named account.`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow new APIError(\"SERVICE_UNAVAILABLE\", {\n\t\t\t\t\t\t\tmessage: msg,\n\t\t\t\t\t\t\tstatus: 503,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst effectiveParentKey = getRawParentKey(network);\n\t\t\t\t\tif (parentAccount !== rState?.accountId && !effectiveParentKey) {\n\t\t\t\t\t\tthrow new APIError(\"SERVICE_UNAVAILABLE\", {\n\t\t\t\t\t\t\tmessage: \"Sub-account parent differs from relayer account. Provide secrets.parentKey to sign as the parent account.\",\n\t\t\t\t\t\t\tstatus: 503,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst newAccountId = `${subAccountName}.${parentAccount}`;\n\t\t\t\t\tconst minDeposit = subAccountCfg?.minDeposit || \"0.1 NEAR\";\n\n\t\t\t\t\tconst near = getNear(network);\n\t\t\t\t\tconst exists = await near.accountExists(newAccountId);\n\t\t\t\t\tif (exists) {\n\t\t\t\t\t\tthrow new APIError(\"CONFLICT\", {\n\t\t\t\t\t\t\tmessage: `Account ${newAccountId} already exists on ${network}`,\n\t\t\t\t\t\t\tstatus: 409,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst txCtx: SubAccountTxCtx = {\n\t\t\t\t\t\tnewAccountId,\n\t\t\t\t\t\tparentAccount,\n\t\t\t\t\t\tuserPublicKey: publicKey,\n\t\t\t\t\t\tuserAccountId,\n\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\tnetwork,\n\t\t\t\t\t};\n\n\t\t\t\t\tconst signingNear = rState?.near ?? near;\n\t\t\t\t\tlet txBuilder = signingNear\n\t\t\t\t\t\t.transaction(parentAccount)\n\t\t\t\t\t\t.createAccount(newAccountId)\n\t\t\t\t\t\t.addKey(publicKey, { type: \"fullAccess\" });\n\n\t\t\t\t\tif (subAccountCfg?.parentHasFullAccess) {\n\t\t\t\t\t\tconst parentPublicKey = parentAccount === rState?.accountId\n\t\t\t\t\t\t\t? rState.publicKey\n\t\t\t\t\t\t\t: parseKey(effectiveParentKey!).publicKey.toString();\n\t\t\t\t\t\ttxBuilder = txBuilder.addKey(parentPublicKey, { type: \"fullAccess\" });\n\t\t\t\t\t}\n\n\t\t\t\t\tif (subAccountCfg?.addRelayerFCAK !== false && subAccountCfg?.relayerFCAK && rState) {\n\t\t\t\t\t\tconst fcakPermission: { type: \"functionCall\"; receiverId: string; methodNames?: string[]; allowance?: string } = {\n\t\t\t\t\t\t\ttype: \"functionCall\",\n\t\t\t\t\t\t\treceiverId: subAccountCfg.relayerFCAK.receiverId,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (subAccountCfg.relayerFCAK.methodNames) {\n\t\t\t\t\t\t\tfcakPermission.methodNames = subAccountCfg.relayerFCAK.methodNames;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (subAccountCfg.relayerFCAK.allowance) {\n\t\t\t\t\t\t\tfcakPermission.allowance = subAccountCfg.relayerFCAK.allowance as `${number} NEAR` | `${bigint} yocto`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttxBuilder.addKey(rState.publicKey, fcakPermission as any);\n\t\t\t\t\t}\n\n\t\t\t\t\ttxBuilder.transfer(newAccountId, minDeposit as `${number} NEAR`);\n\n\t\t\t\t\tif (subAccountCfg?.deploy) {\n\t\t\t\t\t\tif (\"wasm\" in subAccountCfg.deploy) {\n\t\t\t\t\t\t\ttxBuilder = txBuilder.deployContract(newAccountId, subAccountCfg.deploy.wasm);\n\t\t\t\t\t\t} else if (\"fromPublished\" in subAccountCfg.deploy) {\n\t\t\t\t\t\t\ttxBuilder = txBuilder.deployFromPublished(subAccountCfg.deploy.fromPublished as any);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (subAccountCfg?.init) {\n\t\t\t\t\t\tconst initArgs = typeof subAccountCfg.init.args === \"function\"\n\t\t\t\t\t\t\t? subAccountCfg.init.args(txCtx)\n\t\t\t\t\t\t\t: subAccountCfg.init.args;\n\t\t\t\t\t\ttxBuilder = txBuilder.functionCall(newAccountId, subAccountCfg.init.methodName, initArgs);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (subAccountCfg?.extendTx) {\n\t\t\t\t\t\ttxBuilder = subAccountCfg.extendTx(txBuilder, txCtx) as typeof txBuilder;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (effectiveParentKey) {\n\t\t\t\t\t\ttxBuilder = txBuilder.signWith(effectiveParentKey as PrivateKey);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst cleanupDb = async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst existing = await ctx.context.adapter.findOne<{ id: string }>({\n\t\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\t\twhere: [{ field: \"accountId\", operator: \"eq\", value: newAccountId }],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (existing) {\n\t\t\t\t\t\t\t\tawait ctx.context.adapter.delete({ model: \"nearAccount\", where: [{ field: \"id\", operator: \"eq\", value: existing.id }] });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch { }\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait ctx.context.internalAdapter.deleteAccount(`${newAccountId}:${network}`);\n\t\t\t\t\t\t} catch { }\n\t\t\t\t\t};\n\n\t\t\t\t\tconst lifecycleCtx: SubAccountLifecycleCtx = { ...txCtx, near: signingNear };\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait txBuilder.send({ waitUntil: \"EXECUTED\" });\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tconst msg = error instanceof Error ? error.message : \"Unknown error\";\n\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\tmessage: `Failed to create sub-account: ${msg}`,\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\t\t\taccountId: newAccountId,\n\t\t\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\t\t\tpublicKey,\n\t\t\t\t\t\t\t\tisPrimary: false,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\t\t\t\tuserId: session.user.id,\n\t\t\t\t\t\t\tproviderId: \"siwn\",\n\t\t\t\t\t\t\taccountId: `${newAccountId}:${network}`,\n\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (subAccountCfg?.onCreated) {\n\t\t\t\t\t\t\tawait subAccountCfg.onCreated(lifecycleCtx);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tawait cleanupDb();\n\t\t\t\t\t\tif (subAccountCfg?.onRollback) {\n\t\t\t\t\t\t\ttry { await subAccountCfg.onRollback(lifecycleCtx); } catch { }\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst key = getRawParentKey(network);\n\t\t\t\t\t\t\t\tif (key) {\n\t\t\t\t\t\t\t\t\tconst rollbackNear = getNear(network);\n\t\t\t\t\t\t\t\t\tawait rollbackNear\n\t\t\t\t\t\t\t\t\t\t.transaction(newAccountId)\n\t\t\t\t\t\t\t\t\t\t.deleteAccount({ beneficiary: parentAccount })\n\t\t\t\t\t\t\t\t\t\t.signWith(key as PrivateKey)\n\t\t\t\t\t\t\t\t\t\t.send({ waitUntil: \"EXECUTED\" });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch { }\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst msg = error instanceof Error ? error.message : \"Unknown error\";\n\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\tmessage: `Sub-account created but post-creation failed: ${msg}`,\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\treturn ctx.json(CreateSubAccountResponse.parse({\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\taccountId: newAccountId,\n\t\t\t\t\t\tnetwork,\n\t\t\t\t\t\tpublicKey,\n\t\t\t\t\t\tmessage: `Sub-account ${newAccountId} created on ${network}`,\n\t\t\t\t\t}));\n\t\t\t\t},\n\t\t\t),\n\t\tcheckSubAccountAvailability: createAuthEndpoint(\n\t\t\t\"/near/check-sub-account-availability\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: CheckSubAccountAvailabilityRequest,\n\t\t\t\tuse: [sessionMiddleware],\n\t\t\t},\n\t\t\tasync (ctx) => {\n\t\t\t\tconst { subAccountName, network: providedNetwork } = ctx.body;\n\t\t\t\tconst session = ctx.context.session;\n\n\t\t\t\tif (!session) {\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: \"Must be authenticated to check sub-account availability\",\n\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst nearAccount: NearAccount | null = await ctx.context.adapter.findOne({\n\t\t\t\t\tmodel: \"nearAccount\",\n\t\t\t\t\twhere: [\n\t\t\t\t\t\t{ field: \"userId\", operator: \"eq\", value: session.user.id },\n\t\t\t\t\t\t{ field: \"isPrimary\", operator: \"eq\", value: true },\n\t\t\t\t\t],\n\t\t\t\t});\n\n\t\t\t\tif (!nearAccount) {\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: \"Must have a linked NEAR wallet to check sub-account availability\",\n\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst network = (providedNetwork || nearAccount.network || primaryNetwork) as \"mainnet\" | \"testnet\";\n\t\t\t\tconst subAccountCfg = getSubAccountConfig(network);\n\t\t\t\tconst parentAccount = subAccountCfg?.parentAccount ?? null;\n\n\t\t\t\tif (!parentAccount || isImplicitAccount(parentAccount)) {\n\t\t\t\t\treturn ctx.json(CheckSubAccountAvailabilityResponse.parse({\n\t\t\t\t\t\tavailable: false,\n\t\t\t\t\t\taccountId: \"\",\n\t\t\t\t\t\treason: \"not-configured\",\n\t\t\t\t\t}));\n\t\t\t\t}\n\n\t\t\t\tconst accountId = `${subAccountName}.${parentAccount}`;\n\n\t\t\t\tif (accountId.length > 64) {\n\t\t\t\t\treturn ctx.json(CheckSubAccountAvailabilityResponse.parse({\n\t\t\t\t\t\tavailable: false,\n\t\t\t\t\t\taccountId,\n\t\t\t\t\t\tparentAccount,\n\t\t\t\t\t\treason: \"too-long\",\n\t\t\t\t\t}));\n\t\t\t\t}\n\n\t\t\t\tconst near = getNear(network);\n\t\t\t\tconst exists = await near.accountExists(accountId);\n\n\t\t\t\treturn ctx.json(CheckSubAccountAvailabilityResponse.parse({\n\t\t\t\t\tavailable: !exists,\n\t\t\t\t\taccountId,\n\t\t\t\t\tparentAccount,\n\t\t\t\t\treason: exists ? \"taken\" : undefined,\n\t\t\t\t}));\n\t\t\t},\n\t\t),\n\t\t},\n\t});\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-near-auth",
3
- "version": "1.9.0",
3
+ "version": "1.10.1",
4
4
  "description": "Sign in with NEAR (SIWN) plugin for Better Auth",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -9,7 +9,7 @@ description: >
9
9
  metadata:
10
10
  type: core
11
11
  library: better-near-auth
12
- library_version: "1.9.0"
12
+ library_version: "1.10.1"
13
13
  sources:
14
14
  - "elliotBraem/better-near-auth:src/client.ts"
15
15
  - "elliotBraem/better-near-auth:src/types.ts"
@@ -4,12 +4,11 @@ description: >
4
4
  Configure the gasless NEP-366 delegate action relayer in ephemeral or explicit
5
5
  mode, relay signed delegate actions on-chain, enforce contract whitelisting and
6
6
  gas/deposit limits, check relay status and history, and use the contract view
7
- endpoint. Load when setting up relayer config, debugging relay failures, or
8
- configuring RotatingKeyStore for high-throughput relay.
7
+ endpoint. Load when setting up relayer config or debugging relay failures.
9
8
  metadata:
10
9
  type: core
11
10
  library: better-near-auth
12
- library_version: "1.9.0"
11
+ library_version: "1.10.1"
13
12
  sources:
14
13
  - "elliotBraem/better-near-auth:src/index.ts"
15
14
  - "elliotBraem/better-near-auth:src/utils.ts"
@@ -34,7 +33,10 @@ export const auth = betterAuth({
34
33
  plugins: [
35
34
  siwn({
36
35
  recipient: "myapp.com",
37
- relayer: true, // auto-generates keypair on first startup
36
+ // Omit `accountId` to auto-generate the ephemeral keypair on first startup
37
+ relayer: {
38
+ whitelistedContracts: ["myapp.near"],
39
+ },
38
40
  }),
39
41
  ],
40
42
  });
@@ -56,6 +58,7 @@ The private key is encrypted with AES-256-GCM using `BETTER_AUTH_SECRET` as the
56
58
  siwn({
57
59
  recipient: "myapp.com",
58
60
  relayer: {
61
+ ephemeral: true, // explicit marker (optional)
59
62
  whitelistedContracts: ["myapp.near"],
60
63
  maxGasPerTransaction: "300000000000000", // 300 Tgas
61
64
  maxDepositPerTransaction: "0",
@@ -70,7 +73,7 @@ siwn({
70
73
  recipient: "myapp.com",
71
74
  relayer: {
72
75
  accountId: "relayer.myapp.near",
73
- privateKey: process.env.RELAYER_PRIVATE_KEY, // base64 ed25519:...
76
+ privateKey: process.env.RELAYER_PRIVATE_KEY, // ed25519:...
74
77
  whitelistedContracts: ["myapp.near"],
75
78
  maxGasPerTransaction: "300000000000000", // 300 Tgas
76
79
  maxDepositPerTransaction: "0",
@@ -88,9 +91,13 @@ siwn({
88
91
  },
89
92
  relayer: {
90
93
  mainnet: {
94
+ accountId: "relayer.myapp.near",
95
+ privateKey: process.env.RELAYER_PRIVATE_KEY_MAINNET,
91
96
  whitelistedContracts: ["myapp.near"],
92
97
  },
93
98
  testnet: {
99
+ accountId: "relayer.myapp.testnet",
100
+ privateKey: process.env.RELAYER_PRIVATE_KEY_TESTNET,
94
101
  whitelistedContracts: ["myapp.testnet"],
95
102
  maxGasPerTransaction: "100000000000000", // lower for testing
96
103
  },
@@ -98,26 +105,7 @@ siwn({
98
105
  });
99
106
  ```
100
107
 
101
- Creates separate ephemeral keys for each network with independent settings.
102
-
103
- ### Rotating keys (high-throughput)
104
-
105
- ```typescript
106
- siwn({
107
- recipient: "myapp.com",
108
- relayer: {
109
- accountId: "relayer.myapp.near",
110
- privateKeys: [
111
- process.env.RELAYER_KEY_1,
112
- process.env.RELAYER_KEY_2,
113
- process.env.RELAYER_KEY_3,
114
- ],
115
- whitelistedContracts: ["myapp.near"],
116
- },
117
- });
118
- ```
119
-
120
- Multiple keys cycle round-robin via `RotatingKeyStore`, eliminating nonce collisions for high-throughput relayers.
108
+ Each network gets its own keypair and policy. When `accountId` is omitted, ephemeral keys are generated independently per network.
121
109
 
122
110
  ## Core Patterns
123
111
 
@@ -181,42 +169,32 @@ View calls are read-only, authenticated, and executed server-side.
181
169
 
182
170
  ## Relayer Configuration
183
171
 
184
- The relayer can be configured in several ways:
172
+ The relayer takes a single `RelayerConfig` shape. The mode is determined at runtime by whether `accountId` is set:
185
173
 
186
- | Value | Mode | Description |
187
- |-------|------|-------------|
188
- | `true` | Ephemeral | Auto-generated ED25519 keypair (simplest) |
189
- | `RelayerEphemeralConfig` | Ephemeral | Ephemeral with custom settings |
190
- | `RelayerExplicitConfig` | Explicit | Bring your own key |
191
- | `RelayerDualNetworkConfig` | Mixed | Per-network configuration |
174
+ | Form | Mode | Description |
175
+ |------|------|-------------|
176
+ | `{ whitelistedContracts?: ... }` | Ephemeral | Auto-generated ED25519 keypair (simplest) |
177
+ | `{ accountId, privateKey, ... }` | Explicit | Bring your own key for a named account |
178
+ | `{ mainnet: {...}, testnet: {...} }` | Mixed | Per-network configuration |
192
179
 
193
- **Ephemeral Config (`RelayerEphemeralConfig`):**
180
+ **`RelayerConfig`:**
194
181
 
195
182
  | Option | Type | Default | Description |
196
183
  |--------|------|---------|-------------|
184
+ | `accountId` | `string` | — | Named relayer account. If set, the relayer runs in explicit mode using `privateKey`. |
185
+ | `privateKey` | `string` | — | ed25519:... private key. Required when `accountId` is set; otherwise the relayer logs a warning and falls back to ephemeral mode. |
197
186
  | `whitelistedContracts` | `string[]` | — | Restrict relay to these contract IDs |
198
187
  | `maxGasPerTransaction` | `string` | — | Max gas per relayed transaction (yoctoNEAR) |
199
188
  | `maxDepositPerTransaction` | `string` | — | Max deposit per relayed transaction (yoctoNEAR) |
200
189
 
201
- **Explicit Config (`RelayerExplicitConfig`):**
190
+ **`RelayerDualNetworkConfig`:**
202
191
 
203
192
  | Option | Type | Default | Description |
204
193
  |--------|------|---------|-------------|
205
- | `accountId` | `string` | — | Named relayer account (required) |
206
- | `privateKey` | `string` | — | Base64 ed25519:... (required) |
207
- | `privateKeys` | `string[]` | — | Multiple keys for RotatingKeyStore |
208
- | `whitelistedContracts` | `string[]` | — | Restrict relay to these contract IDs |
209
- | `maxGasPerTransaction` | `string` | — | Max gas per relayed transaction (yoctoNEAR) |
210
- | `maxDepositPerTransaction` | `string` | — | Max deposit per relayed transaction (yoctoNEAR) |
194
+ | `mainnet` | `RelayerConfig` | — | Per-network config. Independent ephemeral keys when `accountId` is omitted. |
195
+ | `testnet` | `RelayerConfig` | — | Per-network config. Independent ephemeral keys when `accountId` is omitted. |
211
196
 
212
- **Dual Network Config (`RelayerDualNetworkConfig`):**
213
-
214
- | Option | Type | Default | Description |
215
- |--------|------|---------|-------------|
216
- | `mainnet` | `RelayerEphemeralConfig \| RelayerExplicitConfig` | — | Mainnet relayer config |
217
- | `testnet` | `RelayerEphemeralConfig \| RelayerExplicitConfig` | — | Testnet relayer config |
218
-
219
- When using `relayer: true` or ephemeral config (no `accountId`/`privateKey`), an ED25519 keypair is generated on first startup, the implicit account ID is derived from the public key, and the private key is encrypted with AES-256-GCM (using `BETTER_AUTH_SECRET` as KEK via HKDF-SHA256) and stored in the database. The same keypair is recovered on restart.
197
+ When `accountId` is not set, an ED25519 keypair is generated on first startup, the implicit account ID is derived from the public key, and the private key is encrypted with AES-256-GCM (using `BETTER_AUTH_SECRET` as KEK via HKDF-SHA256) and stored in the database. The same keypair is recovered on restart.
220
198
 
221
199
  ## Encryption Details
222
200
 
@@ -229,48 +207,29 @@ When using `relayer: true` or ephemeral config (no `accountId`/`privateKey`), an
229
207
 
230
208
  ### CRITICAL Not funding the ephemeral relayer account
231
209
 
232
- Wrong:
233
-
234
210
  ```typescript
235
211
  siwn({
236
212
  recipient: "myapp.com",
237
- relayer: true, // ephemeral — but account has zero balance
238
- });
239
- // Server starts, relayer created, but every relay attempt fails
240
- ```
241
-
242
- Correct:
243
-
244
- ```typescript
245
- siwn({
246
- recipient: "myapp.com",
247
- relayer: true, // ephemeral
213
+ relayer: {
214
+ // Omit accountId to use ephemeral mode (account starts with zero balance)
215
+ whitelistedContracts: ["myapp.near"],
216
+ },
248
217
  });
249
218
  // After startup, check logs for the accountId:
250
219
  // [siwn] Relayer initialized: 7a3c4b5c... (mainnet, ephemeral)
251
- // Send NEAR to that account ID to fund the relayer
220
+ // Send NEAR to that account ID to fund the relayer — every relay attempt fails otherwise
252
221
  ```
253
222
 
254
- 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.
223
+ 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:1153-1160 and surfaces it as `"Relay failed"` — check server logs for the actual RPC error. Alternatively, use explicit mode with a pre-funded named account.
255
224
 
256
- Source: src/index.ts:179-181, maintainer interview
225
+ Source: src/index.ts:152-235, maintainer interview
257
226
 
258
227
  ### CRITICAL Empty relayer_key table (config not passed)
259
228
 
260
- Wrong:
261
-
262
- ```typescript
263
- // Config builder returns undefined when checking for accountId
264
- if (!siwn.relayer?.accountId) return undefined;
265
- // Relayer never initializes, relayer_key table stays empty
266
- ```
267
-
268
229
  Correct:
269
230
 
270
231
  ```typescript
271
- // Use relayer: true or provide config object
272
- relayer: true
273
- // OR
232
+ // Provide a config object — even an empty one enables ephemeral mode
274
233
  relayer: {
275
234
  whitelistedContracts: ["myapp.near"],
276
235
  }
@@ -354,7 +313,9 @@ Wrong:
354
313
  // No BETTER_AUTH_SECRET set — ephemeral key encryption uses empty string
355
314
  siwn({
356
315
  recipient: "myapp.com",
357
- relayer: true,
316
+ relayer: {
317
+ whitelistedContracts: ["myapp.near"],
318
+ },
358
319
  });
359
320
  ```
360
321
 
@@ -366,12 +327,14 @@ Correct:
366
327
  process.env.BETTER_AUTH_SECRET = "your-secure-secret";
367
328
  siwn({
368
329
  recipient: "myapp.com",
369
- relayer: true,
330
+ relayer: {
331
+ whitelistedContracts: ["myapp.near"],
332
+ },
370
333
  });
371
334
  ```
372
335
 
373
336
  The ephemeral relayer encrypts its private key using HKDF-SHA256 derived from `BETTER_AUTH_SECRET`. If missing, key derivation falls back to an empty string, which is insecure and may cause decryption failures on server restart.
374
337
 
375
- Source: src/utils.ts:21-41, src/index.ts:134
338
+ Source: src/utils.ts:21-41, src/index.ts:133
376
339
 
377
340
 
@@ -9,7 +9,7 @@ description: >
9
9
  metadata:
10
10
  type: core
11
11
  library: better-near-auth
12
- library_version: "1.9.0"
12
+ library_version: "1.10.1"
13
13
  sources:
14
14
  - "elliotBraem/better-near-auth:src/index.ts"
15
15
  - "elliotBraem/better-near-auth:src/profile.ts"
@@ -13,7 +13,7 @@ requires:
13
13
  metadata:
14
14
  type: framework
15
15
  library: better-near-auth
16
- library_version: "1.9.0"
16
+ library_version: "1.10.1"
17
17
  sources:
18
18
  - "elliotBraem/better-near-auth:src/client.ts"
19
19
  - "elliotBraem/better-near-auth:examples/auth.everything.dev/ui/src/lib/auth.ts"