@pinklemon8/better-auth-siws 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +183 -0
- package/dist/chunk-AUDIM6MZ.js +30 -0
- package/dist/chunk-AUDIM6MZ.js.map +1 -0
- package/dist/chunk-Q7TSFSYW.js +42 -0
- package/dist/chunk-Q7TSFSYW.js.map +1 -0
- package/dist/client.cjs +106 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +86 -0
- package/dist/client.d.ts +86 -0
- package/dist/client.js +69 -0
- package/dist/client.js.map +1 -0
- package/dist/crypto-BQgenqov.d.cts +90 -0
- package/dist/crypto-BQgenqov.d.ts +90 -0
- package/dist/index.cjs +262 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +54 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +189 -0
- package/dist/index.js.map +1 -0
- package/dist/link.cjs +208 -0
- package/dist/link.cjs.map +1 -0
- package/dist/link.d.cts +46 -0
- package/dist/link.d.ts +46 -0
- package/dist/link.js +148 -0
- package/dist/link.js.map +1 -0
- package/dist/react/index.cjs +361 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.js +335 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +87 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import {
|
|
2
|
+
deserializeOutput,
|
|
3
|
+
serializeOutput
|
|
4
|
+
} from "./chunk-AUDIM6MZ.js";
|
|
5
|
+
import {
|
|
6
|
+
generateNonce,
|
|
7
|
+
verifySIWS
|
|
8
|
+
} from "./chunk-Q7TSFSYW.js";
|
|
9
|
+
|
|
10
|
+
// src/index.ts
|
|
11
|
+
import { createAuthEndpoint, APIError } from "better-auth/api";
|
|
12
|
+
import { setSessionCookie } from "better-auth/cookies";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
var siws = (options) => ({
|
|
15
|
+
id: "siws",
|
|
16
|
+
endpoints: {
|
|
17
|
+
getSiwsNonce: createAuthEndpoint(
|
|
18
|
+
"/siws/nonce",
|
|
19
|
+
{
|
|
20
|
+
method: "POST",
|
|
21
|
+
body: z.object({
|
|
22
|
+
walletAddress: z.string().min(32).max(44)
|
|
23
|
+
})
|
|
24
|
+
},
|
|
25
|
+
async (ctx) => {
|
|
26
|
+
const { walletAddress } = ctx.body;
|
|
27
|
+
const nonce = generateNonce();
|
|
28
|
+
const expiryMs = options?.nonceExpiryMs ?? 5 * 60 * 1e3;
|
|
29
|
+
await ctx.context.internalAdapter.createVerificationValue({
|
|
30
|
+
identifier: `siws:${walletAddress}`,
|
|
31
|
+
value: nonce,
|
|
32
|
+
expiresAt: new Date(Date.now() + expiryMs)
|
|
33
|
+
});
|
|
34
|
+
const host = ctx.headers?.get("host") || "localhost:3000";
|
|
35
|
+
const protocol = host.includes("localhost") ? "http" : "https";
|
|
36
|
+
const domain = host;
|
|
37
|
+
const uri = `${protocol}://${host}`;
|
|
38
|
+
return ctx.json({
|
|
39
|
+
nonce,
|
|
40
|
+
domain,
|
|
41
|
+
uri,
|
|
42
|
+
statement: options?.statement ?? "Sign in with your Solana wallet. This will not trigger a blockchain transaction or cost any gas fee.",
|
|
43
|
+
chainId: options?.chainId ?? "mainnet",
|
|
44
|
+
issuedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
),
|
|
48
|
+
verifySiwsSignature: createAuthEndpoint(
|
|
49
|
+
"/siws/verify",
|
|
50
|
+
{
|
|
51
|
+
method: "POST",
|
|
52
|
+
body: z.object({
|
|
53
|
+
output: z.object({
|
|
54
|
+
account: z.object({
|
|
55
|
+
address: z.string(),
|
|
56
|
+
publicKey: z.array(z.number())
|
|
57
|
+
}),
|
|
58
|
+
signature: z.array(z.number()),
|
|
59
|
+
signedMessage: z.array(z.number())
|
|
60
|
+
}),
|
|
61
|
+
input: z.object({
|
|
62
|
+
domain: z.string(),
|
|
63
|
+
address: z.string().optional(),
|
|
64
|
+
statement: z.string().optional(),
|
|
65
|
+
uri: z.string().optional(),
|
|
66
|
+
version: z.string().optional(),
|
|
67
|
+
chainId: z.string().optional(),
|
|
68
|
+
nonce: z.string().optional(),
|
|
69
|
+
issuedAt: z.string().optional(),
|
|
70
|
+
expirationTime: z.string().optional(),
|
|
71
|
+
notBefore: z.string().optional(),
|
|
72
|
+
requestId: z.string().optional(),
|
|
73
|
+
resources: z.array(z.string()).optional()
|
|
74
|
+
})
|
|
75
|
+
}),
|
|
76
|
+
requireRequest: true
|
|
77
|
+
},
|
|
78
|
+
async (ctx) => {
|
|
79
|
+
const { output, input } = ctx.body;
|
|
80
|
+
const walletAddress = output.account.address;
|
|
81
|
+
const verification = await ctx.context.internalAdapter.findVerificationValue(
|
|
82
|
+
`siws:${walletAddress}`
|
|
83
|
+
);
|
|
84
|
+
if (!verification || /* @__PURE__ */ new Date() > verification.expiresAt) {
|
|
85
|
+
throw new APIError("UNAUTHORIZED", {
|
|
86
|
+
message: "Invalid or expired nonce"
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
const solanaOutput = deserializeOutput(output);
|
|
90
|
+
const isValid = verifySIWS(input, solanaOutput);
|
|
91
|
+
if (!isValid) {
|
|
92
|
+
throw new APIError("UNAUTHORIZED", {
|
|
93
|
+
message: "Invalid signature"
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
await ctx.context.internalAdapter.deleteVerificationValue(
|
|
97
|
+
verification.id
|
|
98
|
+
);
|
|
99
|
+
const linkedAccount = await ctx.context.adapter.findOne({
|
|
100
|
+
model: "account",
|
|
101
|
+
where: [
|
|
102
|
+
{ field: "providerId", operator: "eq", value: "solana" },
|
|
103
|
+
{ field: "accountId", operator: "eq", value: walletAddress }
|
|
104
|
+
]
|
|
105
|
+
});
|
|
106
|
+
if (!linkedAccount) {
|
|
107
|
+
if (options?.anonymous) {
|
|
108
|
+
const user2 = await ctx.context.internalAdapter.createUser({
|
|
109
|
+
name: walletAddress,
|
|
110
|
+
email: `${walletAddress}@solana.wallet`,
|
|
111
|
+
image: ""
|
|
112
|
+
});
|
|
113
|
+
await ctx.context.internalAdapter.createAccount({
|
|
114
|
+
userId: user2.id,
|
|
115
|
+
providerId: "solana",
|
|
116
|
+
accountId: walletAddress,
|
|
117
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
118
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
119
|
+
});
|
|
120
|
+
const session2 = await ctx.context.internalAdapter.createSession(
|
|
121
|
+
user2.id,
|
|
122
|
+
ctx
|
|
123
|
+
);
|
|
124
|
+
if (!session2) {
|
|
125
|
+
throw new APIError("INTERNAL_SERVER_ERROR", {
|
|
126
|
+
message: "Failed to create session"
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
await setSessionCookie(ctx, { session: session2, user: user2 });
|
|
130
|
+
return ctx.json({
|
|
131
|
+
success: true,
|
|
132
|
+
user: {
|
|
133
|
+
id: user2.id,
|
|
134
|
+
name: user2.name,
|
|
135
|
+
email: user2.email
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
throw new APIError("UNAUTHORIZED", {
|
|
140
|
+
message: "No account linked to this wallet. Please sign in with email first and link your wallet.",
|
|
141
|
+
code: "WALLET_NOT_LINKED"
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
const user = await ctx.context.adapter.findOne({
|
|
145
|
+
model: "user",
|
|
146
|
+
where: [
|
|
147
|
+
{ field: "id", operator: "eq", value: linkedAccount.userId }
|
|
148
|
+
]
|
|
149
|
+
});
|
|
150
|
+
if (!user) {
|
|
151
|
+
throw new APIError("UNAUTHORIZED", {
|
|
152
|
+
message: "User not found"
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (user.banned) {
|
|
156
|
+
throw new APIError("FORBIDDEN", {
|
|
157
|
+
message: "Your account has been banned"
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
const session = await ctx.context.internalAdapter.createSession(
|
|
161
|
+
user.id,
|
|
162
|
+
ctx
|
|
163
|
+
);
|
|
164
|
+
if (!session) {
|
|
165
|
+
throw new APIError("INTERNAL_SERVER_ERROR", {
|
|
166
|
+
message: "Failed to create session"
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
await setSessionCookie(ctx, { session, user });
|
|
170
|
+
return ctx.json({
|
|
171
|
+
success: true,
|
|
172
|
+
user: {
|
|
173
|
+
id: user.id,
|
|
174
|
+
name: user.name,
|
|
175
|
+
email: user.email
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
export {
|
|
183
|
+
deserializeOutput,
|
|
184
|
+
generateNonce,
|
|
185
|
+
serializeOutput,
|
|
186
|
+
siws,
|
|
187
|
+
verifySIWS
|
|
188
|
+
};
|
|
189
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { createAuthEndpoint, APIError } from \"better-auth/api\";\nimport { setSessionCookie } from \"better-auth/cookies\";\nimport { z } from \"zod\";\nimport { generateNonce, verifySIWS } from \"./crypto\";\nimport { deserializeOutput } from \"./types\";\nimport type { SiwsPluginOptions } from \"./types\";\n\nexport type { SiwsPluginOptions };\nexport { generateNonce, verifySIWS } from \"./crypto\";\nexport { serializeOutput, deserializeOutput } from \"./types\";\nexport type {\n SiwsNonceResponse,\n SiwsVerifyRequest,\n SiwsVerifyResponse,\n SiwsLinkedWallet,\n SerializedSolanaOutput,\n} from \"./types\";\n\nexport const siws = (options?: SiwsPluginOptions) => ({\n id: \"siws\" as const,\n endpoints: {\n getSiwsNonce: createAuthEndpoint(\n \"/siws/nonce\",\n {\n method: \"POST\",\n body: z.object({\n walletAddress: z.string().min(32).max(44),\n }),\n },\n async (ctx) => {\n const { walletAddress } = ctx.body;\n const nonce = generateNonce();\n const expiryMs = options?.nonceExpiryMs ?? 5 * 60 * 1000;\n\n await ctx.context.internalAdapter.createVerificationValue({\n identifier: `siws:${walletAddress}`,\n value: nonce,\n expiresAt: new Date(Date.now() + expiryMs),\n });\n\n const host = ctx.headers?.get(\"host\") || \"localhost:3000\";\n const protocol = host.includes(\"localhost\") ? \"http\" : \"https\";\n const domain = host;\n const uri = `${protocol}://${host}`;\n\n return ctx.json({\n nonce,\n domain,\n uri,\n statement:\n options?.statement ??\n \"Sign in with your Solana wallet. This will not trigger a blockchain transaction or cost any gas fee.\",\n chainId: options?.chainId ?? \"mainnet\",\n issuedAt: new Date().toISOString(),\n });\n }\n ),\n\n verifySiwsSignature: createAuthEndpoint(\n \"/siws/verify\",\n {\n method: \"POST\",\n body: z.object({\n output: z.object({\n account: z.object({\n address: z.string(),\n publicKey: z.array(z.number()),\n }),\n signature: z.array(z.number()),\n signedMessage: z.array(z.number()),\n }),\n input: z.object({\n domain: z.string(),\n address: z.string().optional(),\n statement: z.string().optional(),\n uri: z.string().optional(),\n version: z.string().optional(),\n chainId: z.string().optional(),\n nonce: z.string().optional(),\n issuedAt: z.string().optional(),\n expirationTime: z.string().optional(),\n notBefore: z.string().optional(),\n requestId: z.string().optional(),\n resources: z.array(z.string()).optional(),\n }),\n }),\n requireRequest: true,\n },\n async (ctx: any) => {\n const { output, input } = ctx.body;\n const walletAddress = output.account.address;\n\n const verification =\n await ctx.context.internalAdapter.findVerificationValue(\n `siws:${walletAddress}`\n );\n\n if (!verification || new Date() > verification.expiresAt) {\n throw new APIError(\"UNAUTHORIZED\", {\n message: \"Invalid or expired nonce\",\n });\n }\n\n const solanaOutput = deserializeOutput(output);\n const isValid = verifySIWS(input, solanaOutput);\n\n if (!isValid) {\n throw new APIError(\"UNAUTHORIZED\", {\n message: \"Invalid signature\",\n });\n }\n\n await ctx.context.internalAdapter.deleteVerificationValue(\n verification.id\n );\n\n const linkedAccount = (await ctx.context.adapter.findOne({\n model: \"account\",\n where: [\n { field: \"providerId\", operator: \"eq\", value: \"solana\" },\n { field: \"accountId\", operator: \"eq\", value: walletAddress },\n ],\n })) as { userId: string } | null;\n\n if (!linkedAccount) {\n if (options?.anonymous) {\n const user = await ctx.context.internalAdapter.createUser({\n name: walletAddress,\n email: `${walletAddress}@solana.wallet`,\n image: \"\",\n });\n\n await ctx.context.internalAdapter.createAccount({\n userId: user.id,\n providerId: \"solana\",\n accountId: walletAddress,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n\n const session = await ctx.context.internalAdapter.createSession(\n user.id,\n ctx\n );\n\n if (!session) {\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: \"Failed to create session\",\n });\n }\n\n await setSessionCookie(ctx, { session, user });\n\n return ctx.json({\n success: true,\n user: {\n id: user.id,\n name: user.name,\n email: user.email,\n },\n });\n }\n\n throw new APIError(\"UNAUTHORIZED\", {\n message:\n \"No account linked to this wallet. Please sign in with email first and link your wallet.\",\n code: \"WALLET_NOT_LINKED\",\n });\n }\n\n const user = (await ctx.context.adapter.findOne({\n model: \"user\",\n where: [\n { field: \"id\", operator: \"eq\", value: linkedAccount.userId },\n ],\n })) as {\n id: string;\n name: string;\n email: string;\n emailVerified: boolean;\n image?: string | null;\n banned?: boolean;\n createdAt: Date;\n updatedAt: Date;\n } | null;\n\n if (!user) {\n throw new APIError(\"UNAUTHORIZED\", {\n message: \"User not found\",\n });\n }\n\n if (user.banned) {\n throw new APIError(\"FORBIDDEN\", {\n message: \"Your account has been banned\",\n });\n }\n\n const session = await ctx.context.internalAdapter.createSession(\n user.id,\n ctx\n );\n\n if (!session) {\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: \"Failed to create session\",\n });\n }\n\n await setSessionCookie(ctx, { session, user });\n\n return ctx.json({\n success: true,\n user: {\n id: user.id,\n name: user.name,\n email: user.email,\n },\n });\n }\n ),\n },\n});\n"],"mappings":"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","names":["user","session"]}
|
package/dist/link.cjs
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/link.ts
|
|
21
|
+
var link_exports = {};
|
|
22
|
+
__export(link_exports, {
|
|
23
|
+
createSignInInput: () => createSignInInput,
|
|
24
|
+
generateNonce: () => generateNonce,
|
|
25
|
+
siwsLink: () => siwsLink,
|
|
26
|
+
verifySIWS: () => verifySIWS
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(link_exports);
|
|
29
|
+
var import_api = require("better-auth/api");
|
|
30
|
+
var import_api2 = require("better-auth/api");
|
|
31
|
+
var import_zod = require("zod");
|
|
32
|
+
|
|
33
|
+
// src/crypto.ts
|
|
34
|
+
var import_wallet_standard_util = require("@solana/wallet-standard-util");
|
|
35
|
+
function generateNonce() {
|
|
36
|
+
const array = new Uint8Array(16);
|
|
37
|
+
crypto.getRandomValues(array);
|
|
38
|
+
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
39
|
+
}
|
|
40
|
+
function createSignInInput(domain, nonce, options) {
|
|
41
|
+
return {
|
|
42
|
+
domain,
|
|
43
|
+
statement: options?.statement ?? "Sign in with your Solana wallet. This will not trigger a blockchain transaction or cost any gas fee.",
|
|
44
|
+
version: "1",
|
|
45
|
+
nonce,
|
|
46
|
+
chainId: options?.chainId ?? "mainnet",
|
|
47
|
+
issuedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function verifySIWS(input, output) {
|
|
51
|
+
try {
|
|
52
|
+
const reconstructed = {
|
|
53
|
+
account: {
|
|
54
|
+
...output.account,
|
|
55
|
+
publicKey: output.account.publicKey instanceof Uint8Array ? output.account.publicKey : new Uint8Array(output.account.publicKey),
|
|
56
|
+
chains: output.account.chains ?? [],
|
|
57
|
+
features: output.account.features ?? []
|
|
58
|
+
},
|
|
59
|
+
signature: output.signature instanceof Uint8Array ? output.signature : new Uint8Array(output.signature),
|
|
60
|
+
signedMessage: output.signedMessage instanceof Uint8Array ? output.signedMessage : new Uint8Array(output.signedMessage)
|
|
61
|
+
};
|
|
62
|
+
return (0, import_wallet_standard_util.verifySignIn)(input, reconstructed);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error("SIWS verification error:", error);
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/link.ts
|
|
70
|
+
var siwsLink = (_options) => ({
|
|
71
|
+
id: "siws-link",
|
|
72
|
+
endpoints: {
|
|
73
|
+
linkSolanaWallet: (0, import_api.createAuthEndpoint)(
|
|
74
|
+
"/siws/link",
|
|
75
|
+
{
|
|
76
|
+
method: "POST",
|
|
77
|
+
body: import_zod.z.object({
|
|
78
|
+
input: import_zod.z.object({
|
|
79
|
+
domain: import_zod.z.string(),
|
|
80
|
+
statement: import_zod.z.string().optional(),
|
|
81
|
+
version: import_zod.z.string().optional(),
|
|
82
|
+
nonce: import_zod.z.string().optional(),
|
|
83
|
+
chainId: import_zod.z.string().optional(),
|
|
84
|
+
issuedAt: import_zod.z.string().optional()
|
|
85
|
+
}),
|
|
86
|
+
output: import_zod.z.object({
|
|
87
|
+
account: import_zod.z.object({
|
|
88
|
+
address: import_zod.z.string(),
|
|
89
|
+
publicKey: import_zod.z.array(import_zod.z.number())
|
|
90
|
+
}),
|
|
91
|
+
signature: import_zod.z.array(import_zod.z.number()),
|
|
92
|
+
signedMessage: import_zod.z.array(import_zod.z.number())
|
|
93
|
+
})
|
|
94
|
+
}),
|
|
95
|
+
requireRequest: true
|
|
96
|
+
},
|
|
97
|
+
async (ctx) => {
|
|
98
|
+
const session = await (0, import_api2.getSessionFromCtx)(ctx);
|
|
99
|
+
if (!session?.user) {
|
|
100
|
+
throw new import_api.APIError("UNAUTHORIZED", { message: "Not authenticated" });
|
|
101
|
+
}
|
|
102
|
+
const { input, output } = ctx.body;
|
|
103
|
+
const walletAddress = output.account.address;
|
|
104
|
+
const isValid = verifySIWS(input, output);
|
|
105
|
+
if (!isValid) {
|
|
106
|
+
throw new import_api.APIError("BAD_REQUEST", {
|
|
107
|
+
message: "Invalid signature"
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const existing = await ctx.context.adapter.findOne({
|
|
111
|
+
model: "account",
|
|
112
|
+
where: [
|
|
113
|
+
{ field: "providerId", operator: "eq", value: "solana" },
|
|
114
|
+
{ field: "accountId", operator: "eq", value: walletAddress }
|
|
115
|
+
]
|
|
116
|
+
});
|
|
117
|
+
if (existing) {
|
|
118
|
+
if (existing.userId === session.user.id) {
|
|
119
|
+
throw new import_api.APIError("BAD_REQUEST", {
|
|
120
|
+
message: "This wallet is already linked to your account"
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
throw new import_api.APIError("BAD_REQUEST", {
|
|
124
|
+
message: "This wallet is already linked to another account"
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
await ctx.context.internalAdapter.createAccount({
|
|
128
|
+
userId: session.user.id,
|
|
129
|
+
providerId: "solana",
|
|
130
|
+
accountId: walletAddress,
|
|
131
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
132
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
133
|
+
});
|
|
134
|
+
return ctx.json({ success: true, walletAddress });
|
|
135
|
+
}
|
|
136
|
+
),
|
|
137
|
+
unlinkSolanaWallet: (0, import_api.createAuthEndpoint)(
|
|
138
|
+
"/siws/unlink",
|
|
139
|
+
{
|
|
140
|
+
method: "POST",
|
|
141
|
+
body: import_zod.z.object({
|
|
142
|
+
walletAddress: import_zod.z.string().min(32).max(44)
|
|
143
|
+
}),
|
|
144
|
+
requireRequest: true
|
|
145
|
+
},
|
|
146
|
+
async (ctx) => {
|
|
147
|
+
const session = await (0, import_api2.getSessionFromCtx)(ctx);
|
|
148
|
+
if (!session?.user) {
|
|
149
|
+
throw new import_api.APIError("UNAUTHORIZED", { message: "Not authenticated" });
|
|
150
|
+
}
|
|
151
|
+
const { walletAddress } = ctx.body;
|
|
152
|
+
const account = await ctx.context.adapter.findOne({
|
|
153
|
+
model: "account",
|
|
154
|
+
where: [
|
|
155
|
+
{ field: "providerId", operator: "eq", value: "solana" },
|
|
156
|
+
{ field: "accountId", operator: "eq", value: walletAddress },
|
|
157
|
+
{ field: "userId", operator: "eq", value: session.user.id }
|
|
158
|
+
]
|
|
159
|
+
});
|
|
160
|
+
if (!account) {
|
|
161
|
+
throw new import_api.APIError("NOT_FOUND", {
|
|
162
|
+
message: "Wallet not found on your account"
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
await ctx.context.adapter.delete({
|
|
166
|
+
model: "account",
|
|
167
|
+
where: [
|
|
168
|
+
{ field: "id", operator: "eq", value: account.id }
|
|
169
|
+
]
|
|
170
|
+
});
|
|
171
|
+
return ctx.json({ success: true });
|
|
172
|
+
}
|
|
173
|
+
),
|
|
174
|
+
getLinkedSolanaWallets: (0, import_api.createAuthEndpoint)(
|
|
175
|
+
"/siws/wallets",
|
|
176
|
+
{
|
|
177
|
+
method: "GET",
|
|
178
|
+
requireRequest: true
|
|
179
|
+
},
|
|
180
|
+
async (ctx) => {
|
|
181
|
+
const session = await (0, import_api2.getSessionFromCtx)(ctx);
|
|
182
|
+
if (!session?.user) {
|
|
183
|
+
throw new import_api.APIError("UNAUTHORIZED", { message: "Not authenticated" });
|
|
184
|
+
}
|
|
185
|
+
const accounts = await ctx.context.adapter.findMany({
|
|
186
|
+
model: "account",
|
|
187
|
+
where: [
|
|
188
|
+
{ field: "providerId", operator: "eq", value: "solana" },
|
|
189
|
+
{ field: "userId", operator: "eq", value: session.user.id }
|
|
190
|
+
]
|
|
191
|
+
});
|
|
192
|
+
const wallets = accounts.map((a) => ({
|
|
193
|
+
walletAddress: a.accountId,
|
|
194
|
+
createdAt: a.createdAt
|
|
195
|
+
}));
|
|
196
|
+
return ctx.json({ wallets });
|
|
197
|
+
}
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
202
|
+
0 && (module.exports = {
|
|
203
|
+
createSignInInput,
|
|
204
|
+
generateNonce,
|
|
205
|
+
siwsLink,
|
|
206
|
+
verifySIWS
|
|
207
|
+
});
|
|
208
|
+
//# sourceMappingURL=link.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/link.ts","../src/crypto.ts"],"sourcesContent":["import { createAuthEndpoint, APIError } from \"better-auth/api\";\nimport { getSessionFromCtx } from \"better-auth/api\";\nimport { z } from \"zod\";\nimport { verifySIWS } from \"./crypto\";\nimport type { SiwsPluginOptions } from \"./types\";\n\nexport { verifySIWS } from \"./crypto\";\nexport { generateNonce, createSignInInput } from \"./crypto\";\nexport type { SiwsLinkedWallet, SiwsLinkRequest } from \"./types\";\n\nexport const siwsLink = (_options?: Pick<SiwsPluginOptions, \"chainId\">) => ({\n id: \"siws-link\" as const,\n endpoints: {\n linkSolanaWallet: createAuthEndpoint(\n \"/siws/link\",\n {\n method: \"POST\",\n body: z.object({\n input: z.object({\n domain: z.string(),\n statement: z.string().optional(),\n version: z.string().optional(),\n nonce: z.string().optional(),\n chainId: z.string().optional(),\n issuedAt: z.string().optional(),\n }),\n output: z.object({\n account: z.object({\n address: z.string(),\n publicKey: z.array(z.number()),\n }),\n signature: z.array(z.number()),\n signedMessage: z.array(z.number()),\n }),\n }),\n requireRequest: true,\n },\n async (ctx: any) => {\n const session = await getSessionFromCtx(ctx);\n if (!session?.user) {\n throw new APIError(\"UNAUTHORIZED\", { message: \"Not authenticated\" });\n }\n\n const { input, output } = ctx.body;\n const walletAddress = output.account.address;\n\n const isValid = verifySIWS(input, output);\n if (!isValid) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Invalid signature\",\n });\n }\n\n const existing = await ctx.context.adapter.findOne({\n model: \"account\",\n where: [\n { field: \"providerId\", operator: \"eq\", value: \"solana\" },\n { field: \"accountId\", operator: \"eq\", value: walletAddress },\n ],\n });\n\n if (existing) {\n if ((existing as any).userId === session.user.id) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"This wallet is already linked to your account\",\n });\n }\n throw new APIError(\"BAD_REQUEST\", {\n message: \"This wallet is already linked to another account\",\n });\n }\n\n await ctx.context.internalAdapter.createAccount({\n userId: session.user.id,\n providerId: \"solana\",\n accountId: walletAddress,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n\n return ctx.json({ success: true, walletAddress });\n }\n ),\n\n unlinkSolanaWallet: createAuthEndpoint(\n \"/siws/unlink\",\n {\n method: \"POST\",\n body: z.object({\n walletAddress: z.string().min(32).max(44),\n }),\n requireRequest: true,\n },\n async (ctx: any) => {\n const session = await getSessionFromCtx(ctx);\n if (!session?.user) {\n throw new APIError(\"UNAUTHORIZED\", { message: \"Not authenticated\" });\n }\n\n const { walletAddress } = ctx.body;\n\n const account = await ctx.context.adapter.findOne({\n model: \"account\",\n where: [\n { field: \"providerId\", operator: \"eq\", value: \"solana\" },\n { field: \"accountId\", operator: \"eq\", value: walletAddress },\n { field: \"userId\", operator: \"eq\", value: session.user.id },\n ],\n });\n\n if (!account) {\n throw new APIError(\"NOT_FOUND\", {\n message: \"Wallet not found on your account\",\n });\n }\n\n await ctx.context.adapter.delete({\n model: \"account\",\n where: [\n { field: \"id\", operator: \"eq\", value: (account as any).id },\n ],\n });\n\n return ctx.json({ success: true });\n }\n ),\n\n getLinkedSolanaWallets: createAuthEndpoint(\n \"/siws/wallets\",\n {\n method: \"GET\",\n requireRequest: true,\n },\n async (ctx: any) => {\n const session = await getSessionFromCtx(ctx);\n if (!session?.user) {\n throw new APIError(\"UNAUTHORIZED\", { message: \"Not authenticated\" });\n }\n\n const accounts = await ctx.context.adapter.findMany({\n model: \"account\",\n where: [\n { field: \"providerId\", operator: \"eq\", value: \"solana\" },\n { field: \"userId\", operator: \"eq\", value: session.user.id },\n ],\n });\n\n const wallets = (accounts as any[]).map((a) => ({\n walletAddress: a.accountId,\n createdAt: a.createdAt,\n }));\n\n return ctx.json({ wallets });\n }\n ),\n },\n});\n","import type { SolanaSignInInput, SolanaSignInOutput } from \"@solana/wallet-standard-features\";\nimport { verifySignIn } from \"@solana/wallet-standard-util\";\n\nexport function generateNonce(): string {\n const array = new Uint8Array(16);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport function createSignInInput(\n domain: string,\n nonce: string,\n options?: { statement?: string; chainId?: string }\n): SolanaSignInInput {\n return {\n domain,\n statement:\n options?.statement ??\n \"Sign in with your Solana wallet. This will not trigger a blockchain transaction or cost any gas fee.\",\n version: \"1\",\n nonce,\n chainId: options?.chainId ?? \"mainnet\",\n issuedAt: new Date().toISOString(),\n };\n}\n\nexport function verifySIWS(\n input: SolanaSignInInput,\n output: SolanaSignInOutput | { account: { publicKey: number[] | Uint8Array; address: string }; signature: number[] | Uint8Array; signedMessage: number[] | Uint8Array }\n): boolean {\n try {\n const reconstructed: SolanaSignInOutput = {\n account: {\n ...output.account,\n publicKey:\n output.account.publicKey instanceof Uint8Array\n ? output.account.publicKey\n : new Uint8Array(output.account.publicKey),\n chains: (output.account as any).chains ?? [],\n features: (output.account as any).features ?? [],\n },\n signature:\n output.signature instanceof Uint8Array\n ? output.signature\n : new Uint8Array(output.signature),\n signedMessage:\n output.signedMessage instanceof Uint8Array\n ? output.signedMessage\n : new Uint8Array(output.signedMessage),\n };\n return verifySignIn(input, reconstructed);\n } catch (error) {\n console.error(\"SIWS verification error:\", error);\n return false;\n }\n}\n"],"mappings":"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","names":["import_api"]}
|
package/dist/link.d.cts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as better_call from 'better-call';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { b as SiwsPluginOptions } from './crypto-BQgenqov.cjs';
|
|
4
|
+
export { h as SiwsLinkRequest, c as SiwsLinkedWallet, i as createSignInInput, g as generateNonce, v as verifySIWS } from './crypto-BQgenqov.cjs';
|
|
5
|
+
import '@solana/wallet-standard-features';
|
|
6
|
+
|
|
7
|
+
declare const siwsLink: (_options?: Pick<SiwsPluginOptions, "chainId">) => {
|
|
8
|
+
id: "siws-link";
|
|
9
|
+
endpoints: {
|
|
10
|
+
linkSolanaWallet: better_call.StrictEndpoint<"/siws/link", {
|
|
11
|
+
method: "POST";
|
|
12
|
+
body: z.ZodObject<{
|
|
13
|
+
input: z.ZodObject<{
|
|
14
|
+
domain: z.ZodString;
|
|
15
|
+
statement: z.ZodOptional<z.ZodString>;
|
|
16
|
+
version: z.ZodOptional<z.ZodString>;
|
|
17
|
+
nonce: z.ZodOptional<z.ZodString>;
|
|
18
|
+
chainId: z.ZodOptional<z.ZodString>;
|
|
19
|
+
issuedAt: z.ZodOptional<z.ZodString>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
output: z.ZodObject<{
|
|
22
|
+
account: z.ZodObject<{
|
|
23
|
+
address: z.ZodString;
|
|
24
|
+
publicKey: z.ZodArray<z.ZodNumber>;
|
|
25
|
+
}, z.core.$strip>;
|
|
26
|
+
signature: z.ZodArray<z.ZodNumber>;
|
|
27
|
+
signedMessage: z.ZodArray<z.ZodNumber>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
requireRequest: true;
|
|
31
|
+
}, any>;
|
|
32
|
+
unlinkSolanaWallet: better_call.StrictEndpoint<"/siws/unlink", {
|
|
33
|
+
method: "POST";
|
|
34
|
+
body: z.ZodObject<{
|
|
35
|
+
walletAddress: z.ZodString;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
requireRequest: true;
|
|
38
|
+
}, any>;
|
|
39
|
+
getLinkedSolanaWallets: better_call.StrictEndpoint<"/siws/wallets", {
|
|
40
|
+
method: "GET";
|
|
41
|
+
requireRequest: true;
|
|
42
|
+
}, any>;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { siwsLink };
|
package/dist/link.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as better_call from 'better-call';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { b as SiwsPluginOptions } from './crypto-BQgenqov.js';
|
|
4
|
+
export { h as SiwsLinkRequest, c as SiwsLinkedWallet, i as createSignInInput, g as generateNonce, v as verifySIWS } from './crypto-BQgenqov.js';
|
|
5
|
+
import '@solana/wallet-standard-features';
|
|
6
|
+
|
|
7
|
+
declare const siwsLink: (_options?: Pick<SiwsPluginOptions, "chainId">) => {
|
|
8
|
+
id: "siws-link";
|
|
9
|
+
endpoints: {
|
|
10
|
+
linkSolanaWallet: better_call.StrictEndpoint<"/siws/link", {
|
|
11
|
+
method: "POST";
|
|
12
|
+
body: z.ZodObject<{
|
|
13
|
+
input: z.ZodObject<{
|
|
14
|
+
domain: z.ZodString;
|
|
15
|
+
statement: z.ZodOptional<z.ZodString>;
|
|
16
|
+
version: z.ZodOptional<z.ZodString>;
|
|
17
|
+
nonce: z.ZodOptional<z.ZodString>;
|
|
18
|
+
chainId: z.ZodOptional<z.ZodString>;
|
|
19
|
+
issuedAt: z.ZodOptional<z.ZodString>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
output: z.ZodObject<{
|
|
22
|
+
account: z.ZodObject<{
|
|
23
|
+
address: z.ZodString;
|
|
24
|
+
publicKey: z.ZodArray<z.ZodNumber>;
|
|
25
|
+
}, z.core.$strip>;
|
|
26
|
+
signature: z.ZodArray<z.ZodNumber>;
|
|
27
|
+
signedMessage: z.ZodArray<z.ZodNumber>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
requireRequest: true;
|
|
31
|
+
}, any>;
|
|
32
|
+
unlinkSolanaWallet: better_call.StrictEndpoint<"/siws/unlink", {
|
|
33
|
+
method: "POST";
|
|
34
|
+
body: z.ZodObject<{
|
|
35
|
+
walletAddress: z.ZodString;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
requireRequest: true;
|
|
38
|
+
}, any>;
|
|
39
|
+
getLinkedSolanaWallets: better_call.StrictEndpoint<"/siws/wallets", {
|
|
40
|
+
method: "GET";
|
|
41
|
+
requireRequest: true;
|
|
42
|
+
}, any>;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { siwsLink };
|