@t402/extensions 2.0.0 → 2.3.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 +1 -1
- package/dist/cjs/bazaar/index.d.ts +3 -547
- package/dist/cjs/bazaar/index.js.map +1 -1
- package/dist/cjs/index-DYNleT-u.d.ts +547 -0
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.js +424 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/sign-in-with-x/index.d.ts +360 -1
- package/dist/cjs/sign-in-with-x/index.js +433 -0
- package/dist/cjs/sign-in-with-x/index.js.map +1 -1
- package/dist/esm/bazaar/index.d.mts +3 -547
- package/dist/esm/chunk-D7SENN2L.mjs +413 -0
- package/dist/esm/chunk-D7SENN2L.mjs.map +1 -0
- package/dist/esm/index-DYNleT-u.d.mts +547 -0
- package/dist/esm/index.d.mts +2 -1
- package/dist/esm/index.mjs +30 -1
- package/dist/esm/sign-in-with-x/index.d.mts +360 -1
- package/dist/esm/sign-in-with-x/index.mjs +32 -1
- package/package.json +16 -5
- package/dist/esm/chunk-MKFJ5AA3.mjs +0 -1
- package/dist/esm/chunk-MKFJ5AA3.mjs.map +0 -1
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
// src/sign-in-with-x/server.ts
|
|
2
|
+
import { randomBytes } from "crypto";
|
|
3
|
+
import { keccak_256 } from "@noble/hashes/sha3";
|
|
4
|
+
import { secp256k1 } from "@noble/curves/secp256k1";
|
|
5
|
+
import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
|
|
6
|
+
var SIWX_SCHEMA = {
|
|
7
|
+
type: "object",
|
|
8
|
+
required: ["domain", "address", "uri", "version", "chainId", "nonce", "issuedAt", "signature"],
|
|
9
|
+
properties: {
|
|
10
|
+
domain: { type: "string" },
|
|
11
|
+
address: { type: "string" },
|
|
12
|
+
statement: { type: "string" },
|
|
13
|
+
uri: { type: "string" },
|
|
14
|
+
version: { type: "string" },
|
|
15
|
+
chainId: { type: "string" },
|
|
16
|
+
nonce: { type: "string" },
|
|
17
|
+
issuedAt: { type: "string", format: "date-time" },
|
|
18
|
+
expirationTime: { type: "string", format: "date-time" },
|
|
19
|
+
notBefore: { type: "string", format: "date-time" },
|
|
20
|
+
requestId: { type: "string" },
|
|
21
|
+
resources: { type: "array", items: { type: "string" } },
|
|
22
|
+
signature: { type: "string" }
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var EIP1271_MAGIC_VALUE = "0x1626ba7e";
|
|
26
|
+
function extractDomain(resourceUri) {
|
|
27
|
+
try {
|
|
28
|
+
const url = new URL(resourceUri);
|
|
29
|
+
return url.host;
|
|
30
|
+
} catch {
|
|
31
|
+
return resourceUri.replace(/^https?:\/\//, "").split("/")[0];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function generateNonce() {
|
|
35
|
+
return randomBytes(16).toString("hex");
|
|
36
|
+
}
|
|
37
|
+
function declareSIWxExtension(options) {
|
|
38
|
+
const domain = extractDomain(options.resourceUri);
|
|
39
|
+
const now = /* @__PURE__ */ new Date();
|
|
40
|
+
const expirationTime = options.expirationTime || new Date(now.getTime() + 5 * 60 * 1e3).toISOString();
|
|
41
|
+
const info = {
|
|
42
|
+
domain,
|
|
43
|
+
uri: options.resourceUri,
|
|
44
|
+
statement: options.statement,
|
|
45
|
+
version: options.version || "1",
|
|
46
|
+
chainId: options.network,
|
|
47
|
+
nonce: generateNonce(),
|
|
48
|
+
issuedAt: now.toISOString(),
|
|
49
|
+
expirationTime,
|
|
50
|
+
resources: [options.resourceUri],
|
|
51
|
+
signatureScheme: options.signatureScheme
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
info,
|
|
55
|
+
schema: SIWX_SCHEMA
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function parseSIWxHeader(header) {
|
|
59
|
+
if (!header) {
|
|
60
|
+
throw new Error("Missing SIWx header");
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const decoded = Buffer.from(header, "base64").toString("utf-8");
|
|
64
|
+
const payload = JSON.parse(decoded);
|
|
65
|
+
const required = [
|
|
66
|
+
"domain",
|
|
67
|
+
"address",
|
|
68
|
+
"uri",
|
|
69
|
+
"version",
|
|
70
|
+
"chainId",
|
|
71
|
+
"nonce",
|
|
72
|
+
"issuedAt",
|
|
73
|
+
"signature"
|
|
74
|
+
];
|
|
75
|
+
for (const field of required) {
|
|
76
|
+
if (!(field in payload)) {
|
|
77
|
+
throw new Error(`Missing required field: ${field}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return payload;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (error instanceof SyntaxError) {
|
|
83
|
+
throw new Error("Invalid SIWx header: malformed JSON");
|
|
84
|
+
}
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function validateSIWxMessage(message, expectedResourceUri, options = {}) {
|
|
89
|
+
const { maxAge = 5 * 60 * 1e3, checkNonce } = options;
|
|
90
|
+
const expectedDomain = extractDomain(expectedResourceUri);
|
|
91
|
+
if (message.domain !== expectedDomain) {
|
|
92
|
+
return {
|
|
93
|
+
valid: false,
|
|
94
|
+
error: `Domain mismatch: expected ${expectedDomain}, got ${message.domain}`
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (message.uri !== expectedResourceUri) {
|
|
98
|
+
return {
|
|
99
|
+
valid: false,
|
|
100
|
+
error: `URI mismatch: expected ${expectedResourceUri}, got ${message.uri}`
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (message.version !== "1") {
|
|
104
|
+
return { valid: false, error: `Unsupported version: ${message.version}` };
|
|
105
|
+
}
|
|
106
|
+
const issuedAt = new Date(message.issuedAt);
|
|
107
|
+
const now = /* @__PURE__ */ new Date();
|
|
108
|
+
if (now.getTime() - issuedAt.getTime() > maxAge) {
|
|
109
|
+
return { valid: false, error: "Message has expired (issuedAt too old)" };
|
|
110
|
+
}
|
|
111
|
+
if (message.expirationTime) {
|
|
112
|
+
const expiration = new Date(message.expirationTime);
|
|
113
|
+
if (expiration < now) {
|
|
114
|
+
return { valid: false, error: "Message has expired" };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (message.notBefore) {
|
|
118
|
+
const notBefore = new Date(message.notBefore);
|
|
119
|
+
if (notBefore > now) {
|
|
120
|
+
return { valid: false, error: "Message not yet valid (notBefore in future)" };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (checkNonce && !checkNonce(message.nonce)) {
|
|
124
|
+
return { valid: false, error: "Invalid nonce (replay attack detected)" };
|
|
125
|
+
}
|
|
126
|
+
return { valid: true };
|
|
127
|
+
}
|
|
128
|
+
async function verifySIWxSignature(message, signature, options = {}) {
|
|
129
|
+
const { checkSmartWallet = false } = options;
|
|
130
|
+
try {
|
|
131
|
+
const messageText = constructMessage(message);
|
|
132
|
+
const messageHash = hashMessage(messageText);
|
|
133
|
+
const recoveredAddress = recoverAddress(messageHash, signature);
|
|
134
|
+
if (recoveredAddress.toLowerCase() !== message.address.toLowerCase()) {
|
|
135
|
+
if (checkSmartWallet && options.provider) {
|
|
136
|
+
const isValidSmartWallet = await verifySmartWalletSignature(
|
|
137
|
+
message.address,
|
|
138
|
+
messageHash,
|
|
139
|
+
signature,
|
|
140
|
+
options.provider
|
|
141
|
+
);
|
|
142
|
+
if (isValidSmartWallet) {
|
|
143
|
+
return { valid: true, address: message.address };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
valid: false,
|
|
148
|
+
address: recoveredAddress,
|
|
149
|
+
error: `Signature mismatch: expected ${message.address}, recovered ${recoveredAddress}`
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return { valid: true, address: recoveredAddress };
|
|
153
|
+
} catch (error) {
|
|
154
|
+
return {
|
|
155
|
+
valid: false,
|
|
156
|
+
error: `Signature verification failed: ${error instanceof Error ? error.message : "unknown error"}`
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function constructMessage(payload) {
|
|
161
|
+
const lines = [];
|
|
162
|
+
lines.push(`${payload.domain} wants you to sign in with your ${payload.chainId} account:`);
|
|
163
|
+
lines.push(payload.address);
|
|
164
|
+
lines.push("");
|
|
165
|
+
if (payload.statement) {
|
|
166
|
+
lines.push(payload.statement);
|
|
167
|
+
lines.push("");
|
|
168
|
+
}
|
|
169
|
+
lines.push(`URI: ${payload.uri}`);
|
|
170
|
+
lines.push(`Version: ${payload.version}`);
|
|
171
|
+
lines.push(`Chain ID: ${payload.chainId}`);
|
|
172
|
+
lines.push(`Nonce: ${payload.nonce}`);
|
|
173
|
+
lines.push(`Issued At: ${payload.issuedAt}`);
|
|
174
|
+
if (payload.expirationTime) {
|
|
175
|
+
lines.push(`Expiration Time: ${payload.expirationTime}`);
|
|
176
|
+
}
|
|
177
|
+
if (payload.notBefore) {
|
|
178
|
+
lines.push(`Not Before: ${payload.notBefore}`);
|
|
179
|
+
}
|
|
180
|
+
if (payload.requestId) {
|
|
181
|
+
lines.push(`Request ID: ${payload.requestId}`);
|
|
182
|
+
}
|
|
183
|
+
if (payload.resources && payload.resources.length > 0) {
|
|
184
|
+
lines.push("Resources:");
|
|
185
|
+
for (const resource of payload.resources) {
|
|
186
|
+
lines.push(`- ${resource}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return lines.join("\n");
|
|
190
|
+
}
|
|
191
|
+
function hashMessage(message) {
|
|
192
|
+
const messageBytes = new TextEncoder().encode(message);
|
|
193
|
+
const prefix = `Ethereum Signed Message:
|
|
194
|
+
${messageBytes.length}`;
|
|
195
|
+
const prefixBytes = new TextEncoder().encode(prefix);
|
|
196
|
+
const combined = new Uint8Array(prefixBytes.length + messageBytes.length);
|
|
197
|
+
combined.set(prefixBytes, 0);
|
|
198
|
+
combined.set(messageBytes, prefixBytes.length);
|
|
199
|
+
const hash = keccak_256(combined);
|
|
200
|
+
return "0x" + bytesToHex(hash);
|
|
201
|
+
}
|
|
202
|
+
function recoverAddress(messageHash, signature) {
|
|
203
|
+
const sigHex = signature.startsWith("0x") ? signature.slice(2) : signature;
|
|
204
|
+
const hashHex = messageHash.startsWith("0x") ? messageHash.slice(2) : messageHash;
|
|
205
|
+
if (sigHex.length !== 130) {
|
|
206
|
+
throw new Error(`Invalid signature length: expected 130 hex chars, got ${sigHex.length}`);
|
|
207
|
+
}
|
|
208
|
+
const r = BigInt("0x" + sigHex.slice(0, 64));
|
|
209
|
+
const s = BigInt("0x" + sigHex.slice(64, 128));
|
|
210
|
+
let v = parseInt(sigHex.slice(128, 130), 16);
|
|
211
|
+
if (v >= 27) {
|
|
212
|
+
v -= 27;
|
|
213
|
+
}
|
|
214
|
+
if (v !== 0 && v !== 1) {
|
|
215
|
+
throw new Error(`Invalid recovery id: ${v}`);
|
|
216
|
+
}
|
|
217
|
+
const sig = new secp256k1.Signature(r, s).addRecoveryBit(v);
|
|
218
|
+
const hashBytes = hexToBytes(hashHex);
|
|
219
|
+
const publicKey = sig.recoverPublicKey(hashBytes);
|
|
220
|
+
const pubKeyBytes = publicKey.toRawBytes(false).slice(1);
|
|
221
|
+
const addressHash = keccak_256(pubKeyBytes);
|
|
222
|
+
const addressBytes = addressHash.slice(-20);
|
|
223
|
+
const address = "0x" + bytesToHex(addressBytes);
|
|
224
|
+
return toChecksumAddress(address);
|
|
225
|
+
}
|
|
226
|
+
function toChecksumAddress(address) {
|
|
227
|
+
const addr = address.toLowerCase().replace("0x", "");
|
|
228
|
+
const hash = bytesToHex(keccak_256(new TextEncoder().encode(addr)));
|
|
229
|
+
let checksummed = "0x";
|
|
230
|
+
for (let i = 0; i < 40; i++) {
|
|
231
|
+
if (parseInt(hash[i], 16) >= 8) {
|
|
232
|
+
checksummed += addr[i].toUpperCase();
|
|
233
|
+
} else {
|
|
234
|
+
checksummed += addr[i];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return checksummed;
|
|
238
|
+
}
|
|
239
|
+
async function verifySmartWalletSignature(walletAddress, messageHash, signature, provider) {
|
|
240
|
+
function isEthProvider(p) {
|
|
241
|
+
return typeof p === "object" && p !== null && "request" in p;
|
|
242
|
+
}
|
|
243
|
+
if (!isEthProvider(provider)) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
const hashHex = messageHash.startsWith("0x") ? messageHash : "0x" + messageHash;
|
|
248
|
+
const sigHex = signature.startsWith("0x") ? signature : "0x" + signature;
|
|
249
|
+
const data = "0x1626ba7e" + hashHex.slice(2).padStart(64, "0") + // bytes32 hash
|
|
250
|
+
"0000000000000000000000000000000000000000000000000000000000000040" + // offset to bytes
|
|
251
|
+
(sigHex.length / 2 - 1).toString(16).padStart(64, "0") + // bytes length
|
|
252
|
+
sigHex.slice(2).padEnd(Math.ceil((sigHex.length - 2) / 64) * 64, "0");
|
|
253
|
+
const result = await provider.request({
|
|
254
|
+
method: "eth_call",
|
|
255
|
+
params: [{ to: walletAddress, data }, "latest"]
|
|
256
|
+
});
|
|
257
|
+
return result.toLowerCase().startsWith(EIP1271_MAGIC_VALUE);
|
|
258
|
+
} catch {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
async function verifyEIP6492Signature(walletAddress, messageHash, signature, provider) {
|
|
263
|
+
const EIP6492_SUFFIX = "6492649264926492649264926492649264926492649264926492649264926492";
|
|
264
|
+
const sigHex = signature.startsWith("0x") ? signature.slice(2) : signature;
|
|
265
|
+
if (sigHex.endsWith(EIP6492_SUFFIX)) {
|
|
266
|
+
console.warn("EIP-6492 deployment signatures not yet fully implemented");
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
return verifySmartWalletSignature(walletAddress, messageHash, signature, provider);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/sign-in-with-x/client.ts
|
|
273
|
+
function encodeSIWxHeader(payload) {
|
|
274
|
+
const json = JSON.stringify(payload);
|
|
275
|
+
if (typeof Buffer !== "undefined") {
|
|
276
|
+
return Buffer.from(json, "utf-8").toString("base64");
|
|
277
|
+
}
|
|
278
|
+
return btoa(json);
|
|
279
|
+
}
|
|
280
|
+
function createSIWxMessage(serverInfo, address) {
|
|
281
|
+
const payload = {
|
|
282
|
+
domain: serverInfo.domain,
|
|
283
|
+
address,
|
|
284
|
+
statement: serverInfo.statement,
|
|
285
|
+
uri: serverInfo.uri,
|
|
286
|
+
version: serverInfo.version,
|
|
287
|
+
chainId: serverInfo.chainId,
|
|
288
|
+
nonce: serverInfo.nonce,
|
|
289
|
+
issuedAt: serverInfo.issuedAt,
|
|
290
|
+
expirationTime: serverInfo.expirationTime,
|
|
291
|
+
notBefore: serverInfo.notBefore,
|
|
292
|
+
requestId: serverInfo.requestId,
|
|
293
|
+
resources: serverInfo.resources,
|
|
294
|
+
signature: ""
|
|
295
|
+
// Will be added after signing
|
|
296
|
+
};
|
|
297
|
+
return constructMessage(payload);
|
|
298
|
+
}
|
|
299
|
+
function createSIWxTypedData(serverInfo, address) {
|
|
300
|
+
const chainIdParts = serverInfo.chainId.split(":");
|
|
301
|
+
const chainIdNum = chainIdParts.length > 1 ? parseInt(chainIdParts[1], 10) : parseInt(chainIdParts[0], 10);
|
|
302
|
+
return {
|
|
303
|
+
domain: {
|
|
304
|
+
name: serverInfo.domain,
|
|
305
|
+
version: serverInfo.version,
|
|
306
|
+
chainId: chainIdNum
|
|
307
|
+
},
|
|
308
|
+
types: {
|
|
309
|
+
SIWx: [
|
|
310
|
+
{ name: "domain", type: "string" },
|
|
311
|
+
{ name: "address", type: "address" },
|
|
312
|
+
{ name: "statement", type: "string" },
|
|
313
|
+
{ name: "uri", type: "string" },
|
|
314
|
+
{ name: "version", type: "string" },
|
|
315
|
+
{ name: "chainId", type: "string" },
|
|
316
|
+
{ name: "nonce", type: "string" },
|
|
317
|
+
{ name: "issuedAt", type: "string" },
|
|
318
|
+
{ name: "expirationTime", type: "string" },
|
|
319
|
+
{ name: "resources", type: "string[]" }
|
|
320
|
+
]
|
|
321
|
+
},
|
|
322
|
+
primaryType: "SIWx",
|
|
323
|
+
message: {
|
|
324
|
+
domain: serverInfo.domain,
|
|
325
|
+
address,
|
|
326
|
+
statement: serverInfo.statement || "",
|
|
327
|
+
uri: serverInfo.uri,
|
|
328
|
+
version: serverInfo.version,
|
|
329
|
+
chainId: serverInfo.chainId,
|
|
330
|
+
nonce: serverInfo.nonce,
|
|
331
|
+
issuedAt: serverInfo.issuedAt,
|
|
332
|
+
expirationTime: serverInfo.expirationTime || "",
|
|
333
|
+
resources: serverInfo.resources || []
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
async function signSIWxMessage(message, signer, options) {
|
|
338
|
+
const scheme = options?.signatureScheme || "eip191";
|
|
339
|
+
switch (scheme) {
|
|
340
|
+
case "eip191":
|
|
341
|
+
if (!signer.signMessage) {
|
|
342
|
+
throw new Error("Signer does not support personal_sign (EIP-191)");
|
|
343
|
+
}
|
|
344
|
+
return signer.signMessage(message);
|
|
345
|
+
case "eip712":
|
|
346
|
+
if (!signer.signTypedData) {
|
|
347
|
+
throw new Error("Signer does not support signTypedData (EIP-712)");
|
|
348
|
+
}
|
|
349
|
+
if (!options?.serverInfo) {
|
|
350
|
+
throw new Error("EIP-712 signing requires serverInfo in options");
|
|
351
|
+
}
|
|
352
|
+
const typedData = createSIWxTypedData(options.serverInfo, signer.address);
|
|
353
|
+
return signer.signTypedData(typedData);
|
|
354
|
+
case "eip1271":
|
|
355
|
+
case "eip6492":
|
|
356
|
+
if (!signer.signMessage) {
|
|
357
|
+
throw new Error("Signer does not support signing");
|
|
358
|
+
}
|
|
359
|
+
return signer.signMessage(message);
|
|
360
|
+
case "siws":
|
|
361
|
+
if (!signer.signMessage) {
|
|
362
|
+
throw new Error("Signer does not support signing");
|
|
363
|
+
}
|
|
364
|
+
return signer.signMessage(message);
|
|
365
|
+
case "sep10":
|
|
366
|
+
throw new Error("Stellar SEP-10 signing not yet implemented");
|
|
367
|
+
default:
|
|
368
|
+
throw new Error(`Unknown signature scheme: ${scheme}`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
async function createSIWxPayload(serverExtension, signer) {
|
|
372
|
+
const { info } = serverExtension;
|
|
373
|
+
const message = createSIWxMessage(info, signer.address);
|
|
374
|
+
const signature = await signSIWxMessage(message, signer, {
|
|
375
|
+
signatureScheme: info.signatureScheme,
|
|
376
|
+
serverInfo: info
|
|
377
|
+
});
|
|
378
|
+
return {
|
|
379
|
+
domain: info.domain,
|
|
380
|
+
address: signer.address,
|
|
381
|
+
statement: info.statement,
|
|
382
|
+
uri: info.uri,
|
|
383
|
+
version: info.version,
|
|
384
|
+
chainId: info.chainId,
|
|
385
|
+
nonce: info.nonce,
|
|
386
|
+
issuedAt: info.issuedAt,
|
|
387
|
+
expirationTime: info.expirationTime,
|
|
388
|
+
notBefore: info.notBefore,
|
|
389
|
+
requestId: info.requestId,
|
|
390
|
+
resources: info.resources,
|
|
391
|
+
signature
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
var SIWX_EXTENSION_KEY = "siwx";
|
|
395
|
+
var SIWX_HEADER_NAME = "X-T402-SIWx";
|
|
396
|
+
|
|
397
|
+
export {
|
|
398
|
+
declareSIWxExtension,
|
|
399
|
+
parseSIWxHeader,
|
|
400
|
+
validateSIWxMessage,
|
|
401
|
+
verifySIWxSignature,
|
|
402
|
+
constructMessage,
|
|
403
|
+
hashMessage,
|
|
404
|
+
verifyEIP6492Signature,
|
|
405
|
+
encodeSIWxHeader,
|
|
406
|
+
createSIWxMessage,
|
|
407
|
+
createSIWxTypedData,
|
|
408
|
+
signSIWxMessage,
|
|
409
|
+
createSIWxPayload,
|
|
410
|
+
SIWX_EXTENSION_KEY,
|
|
411
|
+
SIWX_HEADER_NAME
|
|
412
|
+
};
|
|
413
|
+
//# sourceMappingURL=chunk-D7SENN2L.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/sign-in-with-x/server.ts","../../src/sign-in-with-x/client.ts"],"sourcesContent":["/**\n * Sign-In-With-X (SIWx) Server-Side Implementation\n *\n * Provides functions for servers to declare SIWx requirements,\n * parse client headers, and verify signatures.\n */\n\nimport { randomBytes } from \"crypto\";\nimport { keccak_256 } from \"@noble/hashes/sha3\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils\";\nimport {\n SIWxExtension,\n SIWxExtensionInfo,\n SIWxPayload,\n DeclareSIWxOptions,\n ValidateSIWxOptions,\n VerifySIWxOptions,\n SIWxValidationResult,\n SIWxVerificationResult,\n} from \"./types.js\";\n\n/**\n * JSON Schema for SIWx payload validation.\n */\nconst SIWX_SCHEMA = {\n type: \"object\",\n required: [\"domain\", \"address\", \"uri\", \"version\", \"chainId\", \"nonce\", \"issuedAt\", \"signature\"],\n properties: {\n domain: { type: \"string\" },\n address: { type: \"string\" },\n statement: { type: \"string\" },\n uri: { type: \"string\" },\n version: { type: \"string\" },\n chainId: { type: \"string\" },\n nonce: { type: \"string\" },\n issuedAt: { type: \"string\", format: \"date-time\" },\n expirationTime: { type: \"string\", format: \"date-time\" },\n notBefore: { type: \"string\", format: \"date-time\" },\n requestId: { type: \"string\" },\n resources: { type: \"array\", items: { type: \"string\" } },\n signature: { type: \"string\" },\n },\n};\n\n/**\n * EIP-1271 magic value for valid signatures.\n */\nconst EIP1271_MAGIC_VALUE = \"0x1626ba7e\";\n\n/**\n * Extracts domain from a resource URI.\n *\n * @param resourceUri - Full resource URI (e.g., \"https://api.example.com/resource\")\n * @returns Domain without protocol (e.g., \"api.example.com\")\n */\nfunction extractDomain(resourceUri: string): string {\n try {\n const url = new URL(resourceUri);\n return url.host;\n } catch {\n // Fallback for non-URL formats\n return resourceUri.replace(/^https?:\\/\\//, \"\").split(\"/\")[0];\n }\n}\n\n/**\n * Generates a cryptographically secure nonce.\n *\n * @returns 32-byte hex-encoded nonce\n */\nfunction generateNonce(): string {\n return randomBytes(16).toString(\"hex\");\n}\n\n/**\n * Declares a SIWx extension for server responses.\n *\n * @param options - Extension declaration options\n * @returns SIWx extension object ready for response\n *\n * @example\n * ```typescript\n * const extension = declareSIWxExtension({\n * resourceUri: \"https://api.example.com/premium\",\n * network: \"eip155:8453\",\n * statement: \"Sign in to access premium content\",\n * });\n * ```\n */\nexport function declareSIWxExtension(options: DeclareSIWxOptions): SIWxExtension {\n const domain = extractDomain(options.resourceUri);\n const now = new Date();\n const expirationTime =\n options.expirationTime || new Date(now.getTime() + 5 * 60 * 1000).toISOString();\n\n const info: SIWxExtensionInfo = {\n domain,\n uri: options.resourceUri,\n statement: options.statement,\n version: options.version || \"1\",\n chainId: options.network,\n nonce: generateNonce(),\n issuedAt: now.toISOString(),\n expirationTime,\n resources: [options.resourceUri],\n signatureScheme: options.signatureScheme,\n };\n\n return {\n info,\n schema: SIWX_SCHEMA,\n };\n}\n\n/**\n * Parses a SIWx header from client request.\n *\n * The header format is base64-encoded JSON.\n *\n * @param header - Base64-encoded SIWx header value\n * @returns Parsed SIWx payload\n * @throws Error if header is invalid\n *\n * @example\n * ```typescript\n * const payload = parseSIWxHeader(request.headers['x-t402-siwx']);\n * ```\n */\nexport function parseSIWxHeader(header: string): SIWxPayload {\n if (!header) {\n throw new Error(\"Missing SIWx header\");\n }\n\n try {\n const decoded = Buffer.from(header, \"base64\").toString(\"utf-8\");\n const payload = JSON.parse(decoded) as SIWxPayload;\n\n // Validate required fields\n const required = [\n \"domain\",\n \"address\",\n \"uri\",\n \"version\",\n \"chainId\",\n \"nonce\",\n \"issuedAt\",\n \"signature\",\n ];\n for (const field of required) {\n if (!(field in payload)) {\n throw new Error(`Missing required field: ${field}`);\n }\n }\n\n return payload;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(\"Invalid SIWx header: malformed JSON\");\n }\n throw error;\n }\n}\n\n/**\n * Validates a SIWx message against expected values.\n *\n * @param message - The SIWx payload to validate\n * @param expectedResourceUri - Expected resource URI (domain validated from this)\n * @param options - Validation options\n * @returns Validation result\n *\n * @example\n * ```typescript\n * const result = validateSIWxMessage(payload, \"https://api.example.com/premium\", {\n * maxAge: 5 * 60 * 1000, // 5 minutes\n * checkNonce: (nonce) => usedNonces.has(nonce) === false,\n * });\n * ```\n */\nexport function validateSIWxMessage(\n message: SIWxPayload,\n expectedResourceUri: string,\n options: ValidateSIWxOptions = {},\n): SIWxValidationResult {\n const { maxAge = 5 * 60 * 1000, checkNonce } = options;\n\n // Validate domain matches\n const expectedDomain = extractDomain(expectedResourceUri);\n if (message.domain !== expectedDomain) {\n return {\n valid: false,\n error: `Domain mismatch: expected ${expectedDomain}, got ${message.domain}`,\n };\n }\n\n // Validate URI matches\n if (message.uri !== expectedResourceUri) {\n return {\n valid: false,\n error: `URI mismatch: expected ${expectedResourceUri}, got ${message.uri}`,\n };\n }\n\n // Validate version\n if (message.version !== \"1\") {\n return { valid: false, error: `Unsupported version: ${message.version}` };\n }\n\n // Validate issuedAt is not too old\n const issuedAt = new Date(message.issuedAt);\n const now = new Date();\n if (now.getTime() - issuedAt.getTime() > maxAge) {\n return { valid: false, error: \"Message has expired (issuedAt too old)\" };\n }\n\n // Validate expirationTime if present\n if (message.expirationTime) {\n const expiration = new Date(message.expirationTime);\n if (expiration < now) {\n return { valid: false, error: \"Message has expired\" };\n }\n }\n\n // Validate notBefore if present\n if (message.notBefore) {\n const notBefore = new Date(message.notBefore);\n if (notBefore > now) {\n return { valid: false, error: \"Message not yet valid (notBefore in future)\" };\n }\n }\n\n // Custom nonce validation\n if (checkNonce && !checkNonce(message.nonce)) {\n return { valid: false, error: \"Invalid nonce (replay attack detected)\" };\n }\n\n return { valid: true };\n}\n\n/**\n * Verifies a SIWx signature.\n *\n * Supports EIP-191 personal signatures and can optionally verify\n * smart wallet signatures via EIP-1271/6492.\n *\n * @param message - The SIWx payload to verify\n * @param signature - The signature to verify (hex-encoded)\n * @param options - Verification options\n * @returns Verification result with recovered address\n *\n * @example\n * ```typescript\n * const result = await verifySIWxSignature(payload, payload.signature, {\n * checkSmartWallet: true,\n * provider: web3Provider,\n * });\n * ```\n */\nexport async function verifySIWxSignature(\n message: SIWxPayload,\n signature: string,\n options: VerifySIWxOptions = {},\n): Promise<SIWxVerificationResult> {\n const { checkSmartWallet = false } = options;\n\n try {\n // Reconstruct the CAIP-122 message that was signed\n const messageText = constructMessage(message);\n\n // Hash the message with Ethereum prefix\n const messageHash = hashMessage(messageText);\n\n // Try to recover the signer address\n const recoveredAddress = recoverAddress(messageHash, signature);\n\n // Check if recovered address matches claimed address\n if (recoveredAddress.toLowerCase() !== message.address.toLowerCase()) {\n // If smart wallet checking is enabled, try EIP-1271 verification\n if (checkSmartWallet && options.provider) {\n const isValidSmartWallet = await verifySmartWalletSignature(\n message.address,\n messageHash,\n signature,\n options.provider,\n );\n\n if (isValidSmartWallet) {\n return { valid: true, address: message.address };\n }\n }\n\n return {\n valid: false,\n address: recoveredAddress,\n error: `Signature mismatch: expected ${message.address}, recovered ${recoveredAddress}`,\n };\n }\n\n return { valid: true, address: recoveredAddress };\n } catch (error) {\n return {\n valid: false,\n error: `Signature verification failed: ${error instanceof Error ? error.message : \"unknown error\"}`,\n };\n }\n}\n\n/**\n * Constructs the CAIP-122 message string from payload.\n *\n * @param payload - SIWx payload\n * @returns CAIP-122 formatted message string\n */\nexport function constructMessage(payload: SIWxPayload): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`${payload.domain} wants you to sign in with your ${payload.chainId} account:`);\n lines.push(payload.address);\n lines.push(\"\");\n\n // Statement (optional)\n if (payload.statement) {\n lines.push(payload.statement);\n lines.push(\"\");\n }\n\n // Required fields\n lines.push(`URI: ${payload.uri}`);\n lines.push(`Version: ${payload.version}`);\n lines.push(`Chain ID: ${payload.chainId}`);\n lines.push(`Nonce: ${payload.nonce}`);\n lines.push(`Issued At: ${payload.issuedAt}`);\n\n // Optional fields\n if (payload.expirationTime) {\n lines.push(`Expiration Time: ${payload.expirationTime}`);\n }\n if (payload.notBefore) {\n lines.push(`Not Before: ${payload.notBefore}`);\n }\n if (payload.requestId) {\n lines.push(`Request ID: ${payload.requestId}`);\n }\n\n // Resources\n if (payload.resources && payload.resources.length > 0) {\n lines.push(\"Resources:\");\n for (const resource of payload.resources) {\n lines.push(`- ${resource}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Hashes a message with the Ethereum signed message prefix (EIP-191).\n *\n * @param message - Message to hash\n * @returns Hex-encoded keccak256 hash with 0x prefix\n */\nexport function hashMessage(message: string): string {\n const messageBytes = new TextEncoder().encode(message);\n const prefix = `\\x19Ethereum Signed Message:\\n${messageBytes.length}`;\n const prefixBytes = new TextEncoder().encode(prefix);\n\n // Concatenate prefix and message\n const combined = new Uint8Array(prefixBytes.length + messageBytes.length);\n combined.set(prefixBytes, 0);\n combined.set(messageBytes, prefixBytes.length);\n\n // Hash with keccak256\n const hash = keccak_256(combined);\n return \"0x\" + bytesToHex(hash);\n}\n\n/**\n * Recovers the signer address from an EIP-191 signature.\n *\n * @param messageHash - Keccak256 hash of the prefixed message (with 0x prefix)\n * @param signature - Hex-encoded signature (65 bytes: r + s + v)\n * @returns Checksummed Ethereum address\n */\nfunction recoverAddress(messageHash: string, signature: string): string {\n // Remove 0x prefix if present\n const sigHex = signature.startsWith(\"0x\") ? signature.slice(2) : signature;\n const hashHex = messageHash.startsWith(\"0x\") ? messageHash.slice(2) : messageHash;\n\n if (sigHex.length !== 130) {\n throw new Error(`Invalid signature length: expected 130 hex chars, got ${sigHex.length}`);\n }\n\n // Parse signature components\n const r = BigInt(\"0x\" + sigHex.slice(0, 64));\n const s = BigInt(\"0x\" + sigHex.slice(64, 128));\n let v = parseInt(sigHex.slice(128, 130), 16);\n\n // Normalize v to 0 or 1 (EIP-155 compatibility)\n if (v >= 27) {\n v -= 27;\n }\n\n if (v !== 0 && v !== 1) {\n throw new Error(`Invalid recovery id: ${v}`);\n }\n\n // Create signature object\n const sig = new secp256k1.Signature(r, s).addRecoveryBit(v);\n\n // Recover public key\n const hashBytes = hexToBytes(hashHex);\n const publicKey = sig.recoverPublicKey(hashBytes);\n\n // Get uncompressed public key (65 bytes) and remove the 04 prefix\n const pubKeyBytes = publicKey.toRawBytes(false).slice(1);\n\n // Hash public key to get address\n const addressHash = keccak_256(pubKeyBytes);\n\n // Take last 20 bytes\n const addressBytes = addressHash.slice(-20);\n const address = \"0x\" + bytesToHex(addressBytes);\n\n // Return checksummed address\n return toChecksumAddress(address);\n}\n\n/**\n * Converts an Ethereum address to checksummed format (EIP-55).\n *\n * @param address - Ethereum address (with or without 0x prefix)\n * @returns Checksummed address with 0x prefix\n */\nfunction toChecksumAddress(address: string): string {\n const addr = address.toLowerCase().replace(\"0x\", \"\");\n const hash = bytesToHex(keccak_256(new TextEncoder().encode(addr)));\n\n let checksummed = \"0x\";\n for (let i = 0; i < 40; i++) {\n if (parseInt(hash[i], 16) >= 8) {\n checksummed += addr[i].toUpperCase();\n } else {\n checksummed += addr[i];\n }\n }\n\n return checksummed;\n}\n\n/**\n * Verifies a smart wallet signature using EIP-1271.\n *\n * @param walletAddress - Smart wallet contract address\n * @param messageHash - Hash of the message that was signed\n * @param signature - The signature to verify\n * @param provider - Ethereum provider with call capability\n * @returns True if signature is valid according to the smart wallet\n */\nasync function verifySmartWalletSignature(\n walletAddress: string,\n messageHash: string,\n signature: string,\n provider: unknown,\n): Promise<boolean> {\n // Type guard for provider\n interface EthProvider {\n request(args: { method: string; params: unknown[] }): Promise<unknown>;\n }\n\n /**\n * Type guard for Ethereum provider interface\n *\n * @param p - Value to check\n * @returns True if value is an EthProvider\n */\n function isEthProvider(p: unknown): p is EthProvider {\n return typeof p === \"object\" && p !== null && \"request\" in p;\n }\n\n if (!isEthProvider(provider)) {\n return false;\n }\n\n try {\n // EIP-1271 isValidSignature(bytes32 hash, bytes signature) returns bytes4\n const hashHex = messageHash.startsWith(\"0x\") ? messageHash : \"0x\" + messageHash;\n const sigHex = signature.startsWith(\"0x\") ? signature : \"0x\" + signature;\n\n // Encode function call\n // isValidSignature(bytes32,bytes) selector: 0x1626ba7e\n const data =\n \"0x1626ba7e\" +\n hashHex.slice(2).padStart(64, \"0\") + // bytes32 hash\n \"0000000000000000000000000000000000000000000000000000000000000040\" + // offset to bytes\n (sigHex.length / 2 - 1).toString(16).padStart(64, \"0\") + // bytes length\n sigHex.slice(2).padEnd(Math.ceil((sigHex.length - 2) / 64) * 64, \"0\"); // bytes data\n\n const result = (await provider.request({\n method: \"eth_call\",\n params: [{ to: walletAddress, data }, \"latest\"],\n })) as string;\n\n // Check if result matches magic value\n return result.toLowerCase().startsWith(EIP1271_MAGIC_VALUE);\n } catch {\n return false;\n }\n}\n\n/**\n * Verifies a signature using EIP-6492 (universal signature verification).\n *\n * This supports both deployed and undeployed smart wallets.\n *\n * @param walletAddress - Wallet address (may be counterfactual)\n * @param messageHash - Hash of the message that was signed\n * @param signature - The signature (may include deployment data)\n * @param provider - Ethereum provider\n * @returns True if signature is valid\n */\nexport async function verifyEIP6492Signature(\n walletAddress: string,\n messageHash: string,\n signature: string,\n provider: unknown,\n): Promise<boolean> {\n // EIP-6492 signatures end with the magic suffix\n const EIP6492_SUFFIX = \"6492649264926492649264926492649264926492649264926492649264926492\";\n const sigHex = signature.startsWith(\"0x\") ? signature.slice(2) : signature;\n\n if (sigHex.endsWith(EIP6492_SUFFIX)) {\n // This is an EIP-6492 signature with deployment data\n // For full implementation, we would need to:\n // 1. Deploy the wallet contract to a local fork\n // 2. Then call isValidSignature\n // This requires more complex provider interaction\n console.warn(\"EIP-6492 deployment signatures not yet fully implemented\");\n return false;\n }\n\n // Fall back to standard EIP-1271 verification\n return verifySmartWalletSignature(walletAddress, messageHash, signature, provider);\n}\n","/**\n * Sign-In-With-X (SIWx) Client-Side Implementation\n *\n * Provides functions for clients to create and sign SIWx messages.\n */\n\nimport {\n SIWxPayload,\n SIWxExtension,\n SIWxExtensionInfo,\n SIWxSigner,\n SignatureScheme,\n} from \"./types.js\";\nimport { constructMessage } from \"./server.js\";\n\n/**\n * Encodes a SIWx payload for transmission in HTTP header.\n *\n * @param payload - The SIWx payload to encode\n * @returns Base64-encoded JSON string\n *\n * @example\n * ```typescript\n * const header = encodeSIWxHeader(payload);\n * fetch(url, {\n * headers: { 'X-T402-SIWx': header }\n * });\n * ```\n */\nexport function encodeSIWxHeader(payload: SIWxPayload): string {\n const json = JSON.stringify(payload);\n // Use Buffer in Node.js or btoa in browser\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(json, \"utf-8\").toString(\"base64\");\n }\n return btoa(json);\n}\n\n/**\n * Creates a CAIP-122 formatted message string from server info.\n *\n * @param serverInfo - Extension info from server\n * @param address - Wallet address signing the message\n * @returns CAIP-122 formatted message string ready for signing\n *\n * @example\n * ```typescript\n * const message = createSIWxMessage(extension.info, wallet.address);\n * const signature = await wallet.signMessage(message);\n * ```\n */\nexport function createSIWxMessage(serverInfo: SIWxExtensionInfo, address: string): string {\n // Create a temporary payload for message construction\n const payload: SIWxPayload = {\n domain: serverInfo.domain,\n address,\n statement: serverInfo.statement,\n uri: serverInfo.uri,\n version: serverInfo.version,\n chainId: serverInfo.chainId,\n nonce: serverInfo.nonce,\n issuedAt: serverInfo.issuedAt,\n expirationTime: serverInfo.expirationTime,\n notBefore: serverInfo.notBefore,\n requestId: serverInfo.requestId,\n resources: serverInfo.resources,\n signature: \"\", // Will be added after signing\n };\n\n return constructMessage(payload);\n}\n\n/**\n * Creates EIP-712 typed data for SIWx signing.\n *\n * @param serverInfo - Extension info from server\n * @param address - Wallet address signing the message\n * @returns EIP-712 typed data object\n */\nexport function createSIWxTypedData(\n serverInfo: SIWxExtensionInfo,\n address: string,\n): {\n domain: {\n name: string;\n version: string;\n chainId: number;\n };\n types: {\n SIWx: Array<{ name: string; type: string }>;\n };\n primaryType: \"SIWx\";\n message: Record<string, unknown>;\n} {\n // Extract chain ID number from CAIP-2 format (e.g., \"eip155:8453\" -> 8453)\n const chainIdParts = serverInfo.chainId.split(\":\");\n const chainIdNum =\n chainIdParts.length > 1 ? parseInt(chainIdParts[1], 10) : parseInt(chainIdParts[0], 10);\n\n return {\n domain: {\n name: serverInfo.domain,\n version: serverInfo.version,\n chainId: chainIdNum,\n },\n types: {\n SIWx: [\n { name: \"domain\", type: \"string\" },\n { name: \"address\", type: \"address\" },\n { name: \"statement\", type: \"string\" },\n { name: \"uri\", type: \"string\" },\n { name: \"version\", type: \"string\" },\n { name: \"chainId\", type: \"string\" },\n { name: \"nonce\", type: \"string\" },\n { name: \"issuedAt\", type: \"string\" },\n { name: \"expirationTime\", type: \"string\" },\n { name: \"resources\", type: \"string[]\" },\n ],\n },\n primaryType: \"SIWx\",\n message: {\n domain: serverInfo.domain,\n address,\n statement: serverInfo.statement || \"\",\n uri: serverInfo.uri,\n version: serverInfo.version,\n chainId: serverInfo.chainId,\n nonce: serverInfo.nonce,\n issuedAt: serverInfo.issuedAt,\n expirationTime: serverInfo.expirationTime || \"\",\n resources: serverInfo.resources || [],\n },\n };\n}\n\n/**\n * Signs a SIWx message using the provided signer.\n *\n * @param message - CAIP-122 formatted message to sign\n * @param signer - Wallet/signer interface with signMessage\n * @param options - Signing options\n * @param options.signatureScheme - Signature scheme to use\n * @param options.serverInfo - Server info for verification\n * @returns Hex-encoded signature\n *\n * @example\n * ```typescript\n * const signature = await signSIWxMessage(message, wallet, {\n * signatureScheme: 'eip191'\n * });\n * ```\n */\nexport async function signSIWxMessage(\n message: string,\n signer: SIWxSigner,\n options?: { signatureScheme?: SignatureScheme; serverInfo?: SIWxExtensionInfo },\n): Promise<string> {\n const scheme = options?.signatureScheme || \"eip191\";\n\n switch (scheme) {\n case \"eip191\":\n if (!signer.signMessage) {\n throw new Error(\"Signer does not support personal_sign (EIP-191)\");\n }\n return signer.signMessage(message);\n\n case \"eip712\":\n if (!signer.signTypedData) {\n throw new Error(\"Signer does not support signTypedData (EIP-712)\");\n }\n if (!options?.serverInfo) {\n throw new Error(\"EIP-712 signing requires serverInfo in options\");\n }\n const typedData = createSIWxTypedData(options.serverInfo, signer.address);\n return signer.signTypedData(typedData);\n\n case \"eip1271\":\n case \"eip6492\":\n // Smart wallet signatures go through the same signMessage path\n // but verification happens on-chain\n if (!signer.signMessage) {\n throw new Error(\"Signer does not support signing\");\n }\n return signer.signMessage(message);\n\n case \"siws\":\n // Sign-In With Solana uses Ed25519 signatures\n if (!signer.signMessage) {\n throw new Error(\"Signer does not support signing\");\n }\n // Solana wallets typically implement signMessage that handles the encoding\n return signer.signMessage(message);\n\n case \"sep10\":\n throw new Error(\"Stellar SEP-10 signing not yet implemented\");\n\n default:\n throw new Error(`Unknown signature scheme: ${scheme}`);\n }\n}\n\n/**\n * Creates a complete SIWx payload from server extension and signer.\n *\n * This is the main entry point for clients - it handles message construction,\n * signing, and payload assembly.\n *\n * @param serverExtension - Extension from server's 402 response\n * @param signer - Wallet/signer interface\n * @returns Complete signed SIWx payload ready for header encoding\n *\n * @example\n * ```typescript\n * // Get extension from server 402 response\n * const extension = paymentRequirements.extensions?.siwx;\n *\n * // Create signed payload\n * const payload = await createSIWxPayload(extension, wallet);\n *\n * // Encode and send with retry\n * const header = encodeSIWxHeader(payload);\n * fetch(url, {\n * headers: { 'X-T402-SIWx': header }\n * });\n * ```\n */\nexport async function createSIWxPayload(\n serverExtension: SIWxExtension,\n signer: SIWxSigner,\n): Promise<SIWxPayload> {\n const { info } = serverExtension;\n\n // Create the message to sign\n const message = createSIWxMessage(info, signer.address);\n\n // Sign the message\n const signature = await signSIWxMessage(message, signer, {\n signatureScheme: info.signatureScheme,\n serverInfo: info,\n });\n\n // Assemble the complete payload\n return {\n domain: info.domain,\n address: signer.address,\n statement: info.statement,\n uri: info.uri,\n version: info.version,\n chainId: info.chainId,\n nonce: info.nonce,\n issuedAt: info.issuedAt,\n expirationTime: info.expirationTime,\n notBefore: info.notBefore,\n requestId: info.requestId,\n resources: info.resources,\n signature,\n };\n}\n\n/**\n * Extension key for SIWx in payment requirements.\n */\nexport const SIWX_EXTENSION_KEY = \"siwx\";\n\n/**\n * HTTP header name for SIWx payload.\n */\nexport const SIWX_HEADER_NAME = \"X-T402-SIWx\";\n"],"mappings":"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","names":[]}
|