@tma.js/init-data-node 2.0.6 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entries/node.cjs +1 -1
- package/dist/entries/node.js +2 -2
- package/dist/entries/{parsing-4VnIGv0b.cjs → parsing-BMJa8cb6.cjs} +21 -23
- package/dist/entries/parsing-BMJa8cb6.cjs.map +1 -0
- package/dist/entries/{parsing-Cjnt3_z4.js → parsing-Cn-1lfce.js} +21 -23
- package/dist/entries/parsing-Cn-1lfce.js.map +1 -0
- package/dist/entries/web.cjs +1 -1
- package/dist/entries/web.js +2 -2
- package/package.json +3 -3
- package/dist/entries/parsing-4VnIGv0b.cjs.map +0 -1
- package/dist/entries/parsing-Cjnt3_z4.js.map +0 -1
package/dist/entries/node.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const fpTs = require("fp-ts");
|
|
4
4
|
const node_crypto = require("node:crypto");
|
|
5
|
-
const parsing = require("./parsing-
|
|
5
|
+
const parsing = require("./parsing-BMJa8cb6.cjs");
|
|
6
6
|
const toolkit = require("@tma.js/toolkit");
|
|
7
7
|
function textToBuffer(text) {
|
|
8
8
|
return Buffer.from(typeof text === "string" ? text : new Uint8Array(text));
|
package/dist/entries/node.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { function as _function, either } from "fp-ts";
|
|
2
2
|
import { createHmac as createHmac$1 } from "node:crypto";
|
|
3
|
-
import { h as hashToken$1, s as signFp$1, a as signDataFp$1, v as validateFp$1, b as bufferToArrayBuffer } from "./parsing-
|
|
4
|
-
import { A, E, H, S, c, i, e, p, d, f, g } from "./parsing-
|
|
3
|
+
import { h as hashToken$1, s as signFp$1, a as signDataFp$1, v as validateFp$1, b as bufferToArrayBuffer } from "./parsing-Cn-1lfce.js";
|
|
4
|
+
import { A, E, H, S, c, i, e, p, d, f, g } from "./parsing-Cn-1lfce.js";
|
|
5
5
|
import { deepSnakeToCamelObjKeys } from "@tma.js/toolkit";
|
|
6
6
|
function textToBuffer(text) {
|
|
7
7
|
return Buffer.from(typeof text === "string" ? text : new Uint8Array(text));
|
|
@@ -3,30 +3,28 @@ const fpTs = require("fp-ts");
|
|
|
3
3
|
const transformers = require("@tma.js/transformers");
|
|
4
4
|
const betterPromises = require("better-promises");
|
|
5
5
|
const errorKid = require("error-kid");
|
|
6
|
-
class AuthDateInvalidError extends errorKid.errorClassWithData(
|
|
7
|
-
"AuthDateInvalidError",
|
|
8
|
-
(value) => ({ value }),
|
|
9
|
-
(value) => [`"auth_date" is invalid: ${value || "value is missing"}`]
|
|
10
|
-
) {
|
|
11
|
-
}
|
|
12
|
-
class SignatureInvalidError extends errorKid.errorClass("SignatureInvalidError") {
|
|
13
|
-
}
|
|
14
|
-
class HexStringLengthInvalidError extends errorKid.errorClass(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
(issuedAt, expiresAt) => ({ issuedAt, expiresAt }),
|
|
26
|
-
(issuedAt, expiresAt, now) => [
|
|
6
|
+
class AuthDateInvalidError extends errorKid.errorClassWithData({
|
|
7
|
+
name: "AuthDateInvalidError",
|
|
8
|
+
data: (value) => ({ value }),
|
|
9
|
+
super: (value) => [`"auth_date" is invalid: ${value || "value is missing"}`]
|
|
10
|
+
}) {
|
|
11
|
+
}
|
|
12
|
+
class SignatureInvalidError extends errorKid.errorClass({ name: "SignatureInvalidError" }) {
|
|
13
|
+
}
|
|
14
|
+
class HexStringLengthInvalidError extends errorKid.errorClass({ name: "HexStringLengthInvalidError" }) {
|
|
15
|
+
}
|
|
16
|
+
class SignatureMissingError extends errorKid.errorClass({
|
|
17
|
+
name: "SignatureMissingError",
|
|
18
|
+
super: (thirdParty) => [`"${thirdParty ? "signature" : "hash"}" parameter is missing`]
|
|
19
|
+
}) {
|
|
20
|
+
}
|
|
21
|
+
class ExpiredError extends errorKid.errorClassWithData({
|
|
22
|
+
name: "ExpiredError",
|
|
23
|
+
data: (issuedAt, expiresAt) => ({ issuedAt, expiresAt }),
|
|
24
|
+
super: (issuedAt, expiresAt, now) => [
|
|
27
25
|
`Init data expired. Issued at ${issuedAt.toISOString()}, expires at ${expiresAt.toISOString()}, now is ${now.toISOString()}`
|
|
28
26
|
]
|
|
29
|
-
) {
|
|
27
|
+
}) {
|
|
30
28
|
}
|
|
31
29
|
function hexToArrayBuffer(hexString) {
|
|
32
30
|
if (hexString.length % 2 !== 0) {
|
|
@@ -238,4 +236,4 @@ exports.signFp = signFp;
|
|
|
238
236
|
exports.validate3rd = validate3rd;
|
|
239
237
|
exports.validate3rdFp = validate3rdFp;
|
|
240
238
|
exports.validateFp = validateFp;
|
|
241
|
-
//# sourceMappingURL=parsing-
|
|
239
|
+
//# sourceMappingURL=parsing-BMJa8cb6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parsing-BMJa8cb6.cjs","sources":["../../src/errors.ts","../../src/buf-converters.ts","../../src/hashToken.ts","../../src/signDataFp.ts","../../src/signFp.ts","../../src/validation.ts","../../src/parsing.ts"],"sourcesContent":["import { errorClass, errorClassWithData } from 'error-kid';\n\nexport class AuthDateInvalidError extends errorClassWithData<\n { value: string | undefined },\n [value?: string]\n>({\n name: 'AuthDateInvalidError',\n data: value => ({ value }),\n super: value => [`\"auth_date\" is invalid: ${value || 'value is missing'}`],\n}) {\n}\n\nexport class SignatureInvalidError extends errorClass({ name: 'SignatureInvalidError' }) {\n}\n\nexport class HexStringLengthInvalidError extends errorClass({ name: 'HexStringLengthInvalidError' }) {\n}\n\nexport class SignatureMissingError extends errorClass<[thirdParty: boolean]>({\n name: 'SignatureMissingError',\n super: thirdParty => [`\"${thirdParty ? 'signature' : 'hash'}\" parameter is missing`],\n}) {\n}\n\nexport class ExpiredError extends errorClassWithData<\n { issuedAt: Date; expiresAt: Date },\n [issuedAt: Date, expiresAt: Date, now: Date]\n>({\n name: 'ExpiredError',\n data: (issuedAt, expiresAt) => ({ issuedAt, expiresAt }),\n super: (issuedAt, expiresAt, now) => [\n `Init data expired. Issued at ${issuedAt.toISOString()}, expires at ${expiresAt.toISOString()}, now is ${now.toISOString()}`,\n ],\n}) {\n}\n","import { either as E } from 'fp-ts';\n\nimport { HexStringLengthInvalidError } from './errors.js';\n\n/**\n * Converts a hex string to ArrayBuffer.\n * @param hexString - value to convert.\n */\nexport function hexToArrayBuffer(hexString: string): E.Either<\n InstanceType<typeof HexStringLengthInvalidError>,\n ArrayBuffer\n> {\n if (hexString.length % 2 !== 0) {\n return E.left(new HexStringLengthInvalidError());\n }\n const buffer = new ArrayBuffer(hexString.length / 2);\n const uint8Array = new Uint8Array(buffer);\n for (let i = 0; i < hexString.length; i += 2) {\n uint8Array[i / 2] = parseInt(hexString.substring(i, i + 2), 16);\n }\n return E.right(buffer);\n}\n\n/**\n * Converts array buffer to hex.\n * @param arrBuf - buffer to convert\n */\nexport function arrayBufferToHex(arrBuf: ArrayBuffer): string {\n return new Uint8Array(arrBuf).reduce((acc, byte) => {\n // Convert byte to hex and pad with zero if needed (e.g., \"0a\" instead of \"a\")\n return acc + byte.toString(16).padStart(2, '0');\n }, '');\n}\n\nexport function bufferToArrayBuffer(buf: Buffer) {\n const ab = new ArrayBuffer(buf.length);\n buf.copy(new Uint8Array(ab));\n return ab;\n}\n","import type { CreateHmacFn, Text } from './types.js';\n\nexport function hashToken<H extends CreateHmacFn<any>>(token: Text, createHmac: H): ReturnType<H> {\n return createHmac(token, 'WebAppData') as ReturnType<H>;\n}\n","import { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport { arrayBufferToHex, hexToArrayBuffer } from './buf-converters.js';\nimport { hashToken } from './hashToken.js';\nimport type { CreateHmacFn, Text } from './types.js';\n\nexport interface SignDataOptions {\n /**\n * True, if token is already hashed and doesn't require hashing using HMAC-SHA-256.\n */\n tokenHashed?: boolean;\n}\n\nexport type SignDataError = ReturnType<typeof hexToArrayBuffer> extends E.Either<infer U, any>\n ? U\n : never;\n\nexport function signDataFp(\n async: false,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<false>,\n options?: SignDataOptions,\n): E.Either<SignDataError, string>;\n\nexport function signDataFp(\n async: true,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<true>,\n options?: SignDataOptions,\n): TE.TaskEither<SignDataError, string>;\n\nexport function signDataFp(\n async: boolean,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<boolean>,\n options: SignDataOptions = {},\n):\n | E.Either<SignDataError, string>\n | TE.TaskEither<SignDataError, string> {\n const keyHmac = options.tokenHashed\n ? typeof key === 'string'\n // If a hashed token was passed, we assume that it is a HEX string. Not to mess with\n // the createHmac function, we should convert this HEX string to ArrayBuffer. Otherwise,\n // incorrect behavior will be met.\n ? hexToArrayBuffer(key)\n : E.right(key)\n // Otherwise we are hashing the token, but we want it to be a monad.\n : fn.pipe(\n E.right(hashToken(key, createHmac)),\n E.match(() => null as never, v => {\n return v instanceof Promise\n ? TE.tryCatch(() => v, err => err as never)\n : E.right(v);\n }),\n );\n\n if (async || typeof keyHmac === 'function') {\n return fn.pipe(\n typeof keyHmac === 'function' ? keyHmac : TE.fromEither(keyHmac),\n TE.chainW(v => TE.tryCatch(\n () => Promise.resolve(createHmac(data, v)).then(arrayBufferToHex),\n err => err as never,\n )),\n );\n }\n return fn.pipe(\n keyHmac,\n // In this branch createHmac can't be asynchronous. If it is, keyHmac would be Promise and the\n // result would be returned in the previous \"if\" statement.\n E.chain(v => E.right(\n arrayBufferToHex((createHmac as CreateHmacFn<false>)(data, v)),\n )),\n );\n}\n","import { type InitDataLike, serializeInitDataQuery } from '@tma.js/transformers';\nimport { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport type { Text } from './types.js';\n\nexport type SignableData =\n & Omit<InitDataLike, 'auth_date' | 'hash' | 'signature'>\n & { signature?: string };\n\nexport interface SignOptions {\n /**\n * True, if token is already hashed and doesn't require hashing using HMAC-SHA-256.\n */\n tokenHashed?: boolean;\n}\n\ninterface SignDataFpArg<Async extends boolean, Left> {\n (data: Text, key: Text, options?: SignOptions): Async extends true\n ? TE.TaskEither<Left, string>\n : E.Either<Left, string>;\n}\n\n/**\n * Signs specified init data.\n * @param data - init data to sign.\n * @param authDate - date, when this init data should be signed.\n * @param key - private key.\n * @param signData - function signing data.\n * @param options - additional options.\n * @returns Signed init data presented as query parameters.\n */\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<false, Left>,\n options?: SignOptions,\n): E.Either<Left, string>;\n\n/**\n * Signs specified init data.\n * @param data - init data to sign.\n * @param authDate - date, when this init data should be signed.\n * @param key - private key.\n * @param signData - function signing data.\n * @param options - additional options.\n * @returns Signed init data presented as query parameters.\n */\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<true, Left>,\n options?: SignOptions,\n): TE.TaskEither<Left, string>;\n\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<boolean, Left>,\n options?: SignOptions,\n): E.Either<Left, string> | TE.TaskEither<Left, string> {\n const query = new URLSearchParams(serializeInitDataQuery({\n ...data,\n auth_date: authDate,\n signature: data.signature || '',\n }));\n\n // Convert search params to pairs and sort the final array.\n const pairs = [...query.entries()]\n .map(([name, value]) => `${name}=${value}`)\n .sort();\n\n // Compute sign, append it to the params and return.\n const queryWithHash = (signature: string): string => {\n query.append('hash', signature);\n return query.toString();\n };\n\n const eitherHash = signData(pairs.join('\\n'), key, options);\n return typeof eitherHash === 'function'\n ? fn.pipe(eitherHash, TE.chain(hash => TE.right(queryWithHash(hash))))\n : fn.pipe(eitherHash, E.chain(hash => E.right(queryWithHash(hash))));\n}\n","import {\n BetterPromise,\n type BetterPromiseOptions,\n type BetterPromiseRejectReason,\n} from 'better-promises';\nimport { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport {\n AuthDateInvalidError,\n ExpiredError,\n SignatureInvalidError,\n SignatureMissingError,\n} from './errors.js';\nimport { Text } from './types.js';\n\ntype OmittedPromiseOptions = Omit<BetterPromiseOptions, 'abortOnResolve' | 'abortOnReject'>;\n\nexport type ValidateValue = string | URLSearchParams;\nexport type Validate3rdValue = string | URLSearchParams;\n\nexport type ValidateError =\n | SignatureMissingError\n | SignatureInvalidError\n | AuthDateInvalidError\n | ExpiredError;\nexport type ValidateAsyncError = ValidateError | BetterPromiseRejectReason;\nexport type Validate3rdError =\n | SignatureMissingError\n | SignatureInvalidError\n | AuthDateInvalidError\n | ExpiredError\n | BetterPromiseRejectReason;\n\ninterface ValidateSignDataFpArg<Async extends boolean, Left> {\n (data: Text, key: Text, options?: ValidateOptions): Async extends true\n ? TE.TaskEither<Left, string>\n : E.Either<Left, string>;\n}\n\ninterface SharedValidateOptions {\n /**\n * Time in seconds which states, how long from creation time init data is considered valid.\n *\n * In other words, in case when authDate + expiresIn is before current time, init data is\n * recognized as expired.\n *\n * In case this value is equal to 0, the function does not check init data expiration.\n * @default 86400 (1 day)\n */\n expiresIn?: number;\n}\n\nexport interface ValidateOptions extends SharedValidateOptions {\n /**\n * True, if token is already hashed.\n * @default false\n */\n tokenHashed?: boolean;\n}\n\nexport interface ValidateAsyncOptions extends ValidateOptions, OmittedPromiseOptions {\n}\n\nexport interface Validate3rdOptions extends SharedValidateOptions, OmittedPromiseOptions {\n /**\n * When true, uses the test environment public key to validate init data.\n * @default false\n */\n test?: boolean;\n}\n\n/**\n * Validates passed init data using a publicly known Ee25519 key.\n * @param value - value to check.\n * @param botId - bot identifier\n * @param options - additional validation options.\n */\nexport function validate3rdFp(\n value: Validate3rdValue,\n botId: number,\n options: Validate3rdOptions = {},\n): TE.TaskEither<Validate3rdError, void> {\n // Init data required params.\n let authDate: Date | undefined;\n let authDateString: string | undefined;\n let signature: string | undefined;\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n (typeof value === 'string' ? new URLSearchParams(value) : value).forEach((value, key) => {\n if (key === 'hash') {\n return;\n }\n if (key === 'signature') {\n signature = value;\n return;\n }\n if (key === 'auth_date') {\n authDateString = value;\n const authDateNum = parseInt(value, 10);\n if (!Number.isNaN(authDateNum)) {\n authDate = new Date(authDateNum * 1000);\n }\n }\n\n pairs.push(`${key}=${value}`);\n });\n\n // Signature and auth date always required.\n if (!signature) {\n return TE.left(new SignatureMissingError(true));\n }\n\n if (!authDate) {\n return TE.left(new AuthDateInvalidError(authDateString));\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n if (expiresIn > 0) {\n // Check if init data expired.\n const expiresAtTs = authDate.getTime() + (expiresIn * 1000);\n const nowTs = Date.now();\n if (expiresAtTs < nowTs) {\n return TE.left(new ExpiredError(authDate, new Date(expiresAtTs), new Date(nowTs)));\n }\n }\n\n return fn.pipe(\n TE.tryCatch(\n () => {\n return BetterPromise.fn(async () => {\n return crypto.subtle.verify(\n 'Ed25519',\n await crypto.subtle.importKey(\n 'raw',\n Buffer.from(\n options.test\n ? '40055058a4ee38156a06562e52eece92a771bcd8346a8c4615cb7376eddf72ec'\n : 'e7bf03a2fa4602af4580703d88dda5bb59f32ed8b02a56c187fe7d34caed242d',\n 'hex',\n ),\n 'Ed25519',\n false,\n ['verify'],\n ),\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n Buffer.from(signature as string, 'base64'),\n Buffer.from(`${botId}:WebAppData\\n${pairs.sort().join('\\n')}`),\n );\n }, options);\n },\n (e: unknown) => e,\n ),\n TE.chainW(isVerified => {\n return isVerified\n ? TE.right(undefined)\n : TE.left(new SignatureInvalidError());\n }),\n );\n}\n\n/**\n * @see validate3rdFp\n */\nexport function validate3rd(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): BetterPromise<void> {\n return BetterPromise.fn(async () => {\n await fn.pipe(\n validate3rdFp(value, botId, options),\n TE.mapLeft(error => {\n throw error;\n }),\n )();\n });\n}\n\n/**\n * @param value - value to check.\n * @param botId - bot identifier\n * @param options - additional validation options.\n * @returns True is specified init data is signed by Telegram.\n */\nexport function isValid3rdFp(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): TE.TaskEither<void, boolean> {\n return fn.pipe(validate3rdFp(value, botId, options), TE.match(\n () => E.right(false),\n () => E.right(true),\n ));\n}\n\n/**\n * @see isValid3rdFp\n */\nexport function isValid3rd(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): BetterPromise<boolean> {\n return BetterPromise.fn(() => fn.pipe(\n isValid3rdFp(value, botId, options),\n TE.match(() => false, v => v),\n )());\n}\n\nexport function validateFp<Left>(\n async: false,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<false, Left>,\n options?: ValidateOptions,\n): E.Either<Left | ValidateError, void>;\n\nexport function validateFp<Left>(\n async: true,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<true, Left>,\n options?: ValidateAsyncOptions,\n): TE.TaskEither<Left | ValidateAsyncError, void>;\n\nexport function validateFp<Left>(\n async: boolean,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<boolean, Left>,\n options: ValidateOptions | ValidateAsyncOptions = {},\n):\n | E.Either<Left | ValidateError, void>\n | TE.TaskEither<Left | ValidateAsyncError, void> {\n // Init data required params.\n let authDate: Date | undefined;\n let authDateString: string | undefined;\n let hash: string | undefined;\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n (typeof value === 'string' ? new URLSearchParams(value) : value).forEach((value, key) => {\n if (key === 'hash') {\n hash = value;\n return;\n }\n\n if (key === 'auth_date') {\n authDateString = value;\n const authDateNum = parseInt(value, 10);\n if (!Number.isNaN(authDateNum)) {\n authDate = new Date(authDateNum * 1000);\n }\n }\n\n pairs.push(`${key}=${value}`);\n });\n\n // Hash and auth date always required.\n if (!hash) {\n return (async ? TE.left : E.left)(new SignatureMissingError(false));\n }\n\n if (!authDate) {\n return (async ? TE.left : E.left)(new AuthDateInvalidError(authDateString));\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n if (expiresIn > 0) {\n // Check if init data expired.\n const expiresAtTs = authDate.getTime() + (expiresIn * 1000);\n const nowTs = Date.now();\n if (expiresAtTs < nowTs) {\n return (async ? TE.left : E.left)(\n new ExpiredError(authDate, new Date(expiresAtTs), new Date(nowTs)),\n );\n }\n }\n\n // According to docs, we sort all the pairs in alphabetical order.\n pairs.sort();\n\n const eitherSignature = signData(pairs.join('\\n'), token, options);\n const onLeft = (error: Left) => E.left(error);\n const onRight = (signature: string) => (\n signature === hash ? E.right(undefined) : E.left(new SignatureInvalidError())\n );\n\n return typeof eitherSignature === 'function'\n ? fn.pipe(eitherSignature, TE.matchW(onLeft, onRight))\n : fn.pipe(eitherSignature, E.matchW(onLeft, onRight));\n}\n","import {\n parseInitDataQuery,\n parseInitDataQueryFp,\n type ParseInitDataQueryError,\n} from '@tma.js/transformers';\n\n/**\n * Parses an incoming value as init data.\n */\nexport const parse = parseInitDataQuery;\n\n/**\n * Parses an incoming value as init data.\n */\nexport const parseFp = parseInitDataQueryFp;\n\nexport { ParseInitDataQueryError as ParseError };\n"],"names":["errorClassWithData","errorClass","E","fn","TE","serializeInitDataQuery","value","BetterPromise","parseInitDataQuery","parseInitDataQueryFp"],"mappings":"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"}
|
|
@@ -2,30 +2,28 @@ import { either, function as _function, taskEither } from "fp-ts";
|
|
|
2
2
|
import { serializeInitDataQuery, parseInitDataQuery, parseInitDataQueryFp } from "@tma.js/transformers";
|
|
3
3
|
import { BetterPromise } from "better-promises";
|
|
4
4
|
import { errorClassWithData, errorClass } from "error-kid";
|
|
5
|
-
class AuthDateInvalidError extends errorClassWithData(
|
|
6
|
-
"AuthDateInvalidError",
|
|
7
|
-
(value) => ({ value }),
|
|
8
|
-
(value) => [`"auth_date" is invalid: ${value || "value is missing"}`]
|
|
9
|
-
) {
|
|
10
|
-
}
|
|
11
|
-
class SignatureInvalidError extends errorClass("SignatureInvalidError") {
|
|
12
|
-
}
|
|
13
|
-
class HexStringLengthInvalidError extends errorClass(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
(issuedAt, expiresAt) => ({ issuedAt, expiresAt }),
|
|
25
|
-
(issuedAt, expiresAt, now) => [
|
|
5
|
+
class AuthDateInvalidError extends errorClassWithData({
|
|
6
|
+
name: "AuthDateInvalidError",
|
|
7
|
+
data: (value) => ({ value }),
|
|
8
|
+
super: (value) => [`"auth_date" is invalid: ${value || "value is missing"}`]
|
|
9
|
+
}) {
|
|
10
|
+
}
|
|
11
|
+
class SignatureInvalidError extends errorClass({ name: "SignatureInvalidError" }) {
|
|
12
|
+
}
|
|
13
|
+
class HexStringLengthInvalidError extends errorClass({ name: "HexStringLengthInvalidError" }) {
|
|
14
|
+
}
|
|
15
|
+
class SignatureMissingError extends errorClass({
|
|
16
|
+
name: "SignatureMissingError",
|
|
17
|
+
super: (thirdParty) => [`"${thirdParty ? "signature" : "hash"}" parameter is missing`]
|
|
18
|
+
}) {
|
|
19
|
+
}
|
|
20
|
+
class ExpiredError extends errorClassWithData({
|
|
21
|
+
name: "ExpiredError",
|
|
22
|
+
data: (issuedAt, expiresAt) => ({ issuedAt, expiresAt }),
|
|
23
|
+
super: (issuedAt, expiresAt, now) => [
|
|
26
24
|
`Init data expired. Issued at ${issuedAt.toISOString()}, expires at ${expiresAt.toISOString()}, now is ${now.toISOString()}`
|
|
27
25
|
]
|
|
28
|
-
) {
|
|
26
|
+
}) {
|
|
29
27
|
}
|
|
30
28
|
function hexToArrayBuffer(hexString) {
|
|
31
29
|
if (hexString.length % 2 !== 0) {
|
|
@@ -239,4 +237,4 @@ export {
|
|
|
239
237
|
signFp as s,
|
|
240
238
|
validateFp as v
|
|
241
239
|
};
|
|
242
|
-
//# sourceMappingURL=parsing-
|
|
240
|
+
//# sourceMappingURL=parsing-Cn-1lfce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parsing-Cn-1lfce.js","sources":["../../src/errors.ts","../../src/buf-converters.ts","../../src/hashToken.ts","../../src/signDataFp.ts","../../src/signFp.ts","../../src/validation.ts","../../src/parsing.ts"],"sourcesContent":["import { errorClass, errorClassWithData } from 'error-kid';\n\nexport class AuthDateInvalidError extends errorClassWithData<\n { value: string | undefined },\n [value?: string]\n>({\n name: 'AuthDateInvalidError',\n data: value => ({ value }),\n super: value => [`\"auth_date\" is invalid: ${value || 'value is missing'}`],\n}) {\n}\n\nexport class SignatureInvalidError extends errorClass({ name: 'SignatureInvalidError' }) {\n}\n\nexport class HexStringLengthInvalidError extends errorClass({ name: 'HexStringLengthInvalidError' }) {\n}\n\nexport class SignatureMissingError extends errorClass<[thirdParty: boolean]>({\n name: 'SignatureMissingError',\n super: thirdParty => [`\"${thirdParty ? 'signature' : 'hash'}\" parameter is missing`],\n}) {\n}\n\nexport class ExpiredError extends errorClassWithData<\n { issuedAt: Date; expiresAt: Date },\n [issuedAt: Date, expiresAt: Date, now: Date]\n>({\n name: 'ExpiredError',\n data: (issuedAt, expiresAt) => ({ issuedAt, expiresAt }),\n super: (issuedAt, expiresAt, now) => [\n `Init data expired. Issued at ${issuedAt.toISOString()}, expires at ${expiresAt.toISOString()}, now is ${now.toISOString()}`,\n ],\n}) {\n}\n","import { either as E } from 'fp-ts';\n\nimport { HexStringLengthInvalidError } from './errors.js';\n\n/**\n * Converts a hex string to ArrayBuffer.\n * @param hexString - value to convert.\n */\nexport function hexToArrayBuffer(hexString: string): E.Either<\n InstanceType<typeof HexStringLengthInvalidError>,\n ArrayBuffer\n> {\n if (hexString.length % 2 !== 0) {\n return E.left(new HexStringLengthInvalidError());\n }\n const buffer = new ArrayBuffer(hexString.length / 2);\n const uint8Array = new Uint8Array(buffer);\n for (let i = 0; i < hexString.length; i += 2) {\n uint8Array[i / 2] = parseInt(hexString.substring(i, i + 2), 16);\n }\n return E.right(buffer);\n}\n\n/**\n * Converts array buffer to hex.\n * @param arrBuf - buffer to convert\n */\nexport function arrayBufferToHex(arrBuf: ArrayBuffer): string {\n return new Uint8Array(arrBuf).reduce((acc, byte) => {\n // Convert byte to hex and pad with zero if needed (e.g., \"0a\" instead of \"a\")\n return acc + byte.toString(16).padStart(2, '0');\n }, '');\n}\n\nexport function bufferToArrayBuffer(buf: Buffer) {\n const ab = new ArrayBuffer(buf.length);\n buf.copy(new Uint8Array(ab));\n return ab;\n}\n","import type { CreateHmacFn, Text } from './types.js';\n\nexport function hashToken<H extends CreateHmacFn<any>>(token: Text, createHmac: H): ReturnType<H> {\n return createHmac(token, 'WebAppData') as ReturnType<H>;\n}\n","import { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport { arrayBufferToHex, hexToArrayBuffer } from './buf-converters.js';\nimport { hashToken } from './hashToken.js';\nimport type { CreateHmacFn, Text } from './types.js';\n\nexport interface SignDataOptions {\n /**\n * True, if token is already hashed and doesn't require hashing using HMAC-SHA-256.\n */\n tokenHashed?: boolean;\n}\n\nexport type SignDataError = ReturnType<typeof hexToArrayBuffer> extends E.Either<infer U, any>\n ? U\n : never;\n\nexport function signDataFp(\n async: false,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<false>,\n options?: SignDataOptions,\n): E.Either<SignDataError, string>;\n\nexport function signDataFp(\n async: true,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<true>,\n options?: SignDataOptions,\n): TE.TaskEither<SignDataError, string>;\n\nexport function signDataFp(\n async: boolean,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<boolean>,\n options: SignDataOptions = {},\n):\n | E.Either<SignDataError, string>\n | TE.TaskEither<SignDataError, string> {\n const keyHmac = options.tokenHashed\n ? typeof key === 'string'\n // If a hashed token was passed, we assume that it is a HEX string. Not to mess with\n // the createHmac function, we should convert this HEX string to ArrayBuffer. Otherwise,\n // incorrect behavior will be met.\n ? hexToArrayBuffer(key)\n : E.right(key)\n // Otherwise we are hashing the token, but we want it to be a monad.\n : fn.pipe(\n E.right(hashToken(key, createHmac)),\n E.match(() => null as never, v => {\n return v instanceof Promise\n ? TE.tryCatch(() => v, err => err as never)\n : E.right(v);\n }),\n );\n\n if (async || typeof keyHmac === 'function') {\n return fn.pipe(\n typeof keyHmac === 'function' ? keyHmac : TE.fromEither(keyHmac),\n TE.chainW(v => TE.tryCatch(\n () => Promise.resolve(createHmac(data, v)).then(arrayBufferToHex),\n err => err as never,\n )),\n );\n }\n return fn.pipe(\n keyHmac,\n // In this branch createHmac can't be asynchronous. If it is, keyHmac would be Promise and the\n // result would be returned in the previous \"if\" statement.\n E.chain(v => E.right(\n arrayBufferToHex((createHmac as CreateHmacFn<false>)(data, v)),\n )),\n );\n}\n","import { type InitDataLike, serializeInitDataQuery } from '@tma.js/transformers';\nimport { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport type { Text } from './types.js';\n\nexport type SignableData =\n & Omit<InitDataLike, 'auth_date' | 'hash' | 'signature'>\n & { signature?: string };\n\nexport interface SignOptions {\n /**\n * True, if token is already hashed and doesn't require hashing using HMAC-SHA-256.\n */\n tokenHashed?: boolean;\n}\n\ninterface SignDataFpArg<Async extends boolean, Left> {\n (data: Text, key: Text, options?: SignOptions): Async extends true\n ? TE.TaskEither<Left, string>\n : E.Either<Left, string>;\n}\n\n/**\n * Signs specified init data.\n * @param data - init data to sign.\n * @param authDate - date, when this init data should be signed.\n * @param key - private key.\n * @param signData - function signing data.\n * @param options - additional options.\n * @returns Signed init data presented as query parameters.\n */\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<false, Left>,\n options?: SignOptions,\n): E.Either<Left, string>;\n\n/**\n * Signs specified init data.\n * @param data - init data to sign.\n * @param authDate - date, when this init data should be signed.\n * @param key - private key.\n * @param signData - function signing data.\n * @param options - additional options.\n * @returns Signed init data presented as query parameters.\n */\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<true, Left>,\n options?: SignOptions,\n): TE.TaskEither<Left, string>;\n\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<boolean, Left>,\n options?: SignOptions,\n): E.Either<Left, string> | TE.TaskEither<Left, string> {\n const query = new URLSearchParams(serializeInitDataQuery({\n ...data,\n auth_date: authDate,\n signature: data.signature || '',\n }));\n\n // Convert search params to pairs and sort the final array.\n const pairs = [...query.entries()]\n .map(([name, value]) => `${name}=${value}`)\n .sort();\n\n // Compute sign, append it to the params and return.\n const queryWithHash = (signature: string): string => {\n query.append('hash', signature);\n return query.toString();\n };\n\n const eitherHash = signData(pairs.join('\\n'), key, options);\n return typeof eitherHash === 'function'\n ? fn.pipe(eitherHash, TE.chain(hash => TE.right(queryWithHash(hash))))\n : fn.pipe(eitherHash, E.chain(hash => E.right(queryWithHash(hash))));\n}\n","import {\n BetterPromise,\n type BetterPromiseOptions,\n type BetterPromiseRejectReason,\n} from 'better-promises';\nimport { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport {\n AuthDateInvalidError,\n ExpiredError,\n SignatureInvalidError,\n SignatureMissingError,\n} from './errors.js';\nimport { Text } from './types.js';\n\ntype OmittedPromiseOptions = Omit<BetterPromiseOptions, 'abortOnResolve' | 'abortOnReject'>;\n\nexport type ValidateValue = string | URLSearchParams;\nexport type Validate3rdValue = string | URLSearchParams;\n\nexport type ValidateError =\n | SignatureMissingError\n | SignatureInvalidError\n | AuthDateInvalidError\n | ExpiredError;\nexport type ValidateAsyncError = ValidateError | BetterPromiseRejectReason;\nexport type Validate3rdError =\n | SignatureMissingError\n | SignatureInvalidError\n | AuthDateInvalidError\n | ExpiredError\n | BetterPromiseRejectReason;\n\ninterface ValidateSignDataFpArg<Async extends boolean, Left> {\n (data: Text, key: Text, options?: ValidateOptions): Async extends true\n ? TE.TaskEither<Left, string>\n : E.Either<Left, string>;\n}\n\ninterface SharedValidateOptions {\n /**\n * Time in seconds which states, how long from creation time init data is considered valid.\n *\n * In other words, in case when authDate + expiresIn is before current time, init data is\n * recognized as expired.\n *\n * In case this value is equal to 0, the function does not check init data expiration.\n * @default 86400 (1 day)\n */\n expiresIn?: number;\n}\n\nexport interface ValidateOptions extends SharedValidateOptions {\n /**\n * True, if token is already hashed.\n * @default false\n */\n tokenHashed?: boolean;\n}\n\nexport interface ValidateAsyncOptions extends ValidateOptions, OmittedPromiseOptions {\n}\n\nexport interface Validate3rdOptions extends SharedValidateOptions, OmittedPromiseOptions {\n /**\n * When true, uses the test environment public key to validate init data.\n * @default false\n */\n test?: boolean;\n}\n\n/**\n * Validates passed init data using a publicly known Ee25519 key.\n * @param value - value to check.\n * @param botId - bot identifier\n * @param options - additional validation options.\n */\nexport function validate3rdFp(\n value: Validate3rdValue,\n botId: number,\n options: Validate3rdOptions = {},\n): TE.TaskEither<Validate3rdError, void> {\n // Init data required params.\n let authDate: Date | undefined;\n let authDateString: string | undefined;\n let signature: string | undefined;\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n (typeof value === 'string' ? new URLSearchParams(value) : value).forEach((value, key) => {\n if (key === 'hash') {\n return;\n }\n if (key === 'signature') {\n signature = value;\n return;\n }\n if (key === 'auth_date') {\n authDateString = value;\n const authDateNum = parseInt(value, 10);\n if (!Number.isNaN(authDateNum)) {\n authDate = new Date(authDateNum * 1000);\n }\n }\n\n pairs.push(`${key}=${value}`);\n });\n\n // Signature and auth date always required.\n if (!signature) {\n return TE.left(new SignatureMissingError(true));\n }\n\n if (!authDate) {\n return TE.left(new AuthDateInvalidError(authDateString));\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n if (expiresIn > 0) {\n // Check if init data expired.\n const expiresAtTs = authDate.getTime() + (expiresIn * 1000);\n const nowTs = Date.now();\n if (expiresAtTs < nowTs) {\n return TE.left(new ExpiredError(authDate, new Date(expiresAtTs), new Date(nowTs)));\n }\n }\n\n return fn.pipe(\n TE.tryCatch(\n () => {\n return BetterPromise.fn(async () => {\n return crypto.subtle.verify(\n 'Ed25519',\n await crypto.subtle.importKey(\n 'raw',\n Buffer.from(\n options.test\n ? '40055058a4ee38156a06562e52eece92a771bcd8346a8c4615cb7376eddf72ec'\n : 'e7bf03a2fa4602af4580703d88dda5bb59f32ed8b02a56c187fe7d34caed242d',\n 'hex',\n ),\n 'Ed25519',\n false,\n ['verify'],\n ),\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n Buffer.from(signature as string, 'base64'),\n Buffer.from(`${botId}:WebAppData\\n${pairs.sort().join('\\n')}`),\n );\n }, options);\n },\n (e: unknown) => e,\n ),\n TE.chainW(isVerified => {\n return isVerified\n ? TE.right(undefined)\n : TE.left(new SignatureInvalidError());\n }),\n );\n}\n\n/**\n * @see validate3rdFp\n */\nexport function validate3rd(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): BetterPromise<void> {\n return BetterPromise.fn(async () => {\n await fn.pipe(\n validate3rdFp(value, botId, options),\n TE.mapLeft(error => {\n throw error;\n }),\n )();\n });\n}\n\n/**\n * @param value - value to check.\n * @param botId - bot identifier\n * @param options - additional validation options.\n * @returns True is specified init data is signed by Telegram.\n */\nexport function isValid3rdFp(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): TE.TaskEither<void, boolean> {\n return fn.pipe(validate3rdFp(value, botId, options), TE.match(\n () => E.right(false),\n () => E.right(true),\n ));\n}\n\n/**\n * @see isValid3rdFp\n */\nexport function isValid3rd(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): BetterPromise<boolean> {\n return BetterPromise.fn(() => fn.pipe(\n isValid3rdFp(value, botId, options),\n TE.match(() => false, v => v),\n )());\n}\n\nexport function validateFp<Left>(\n async: false,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<false, Left>,\n options?: ValidateOptions,\n): E.Either<Left | ValidateError, void>;\n\nexport function validateFp<Left>(\n async: true,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<true, Left>,\n options?: ValidateAsyncOptions,\n): TE.TaskEither<Left | ValidateAsyncError, void>;\n\nexport function validateFp<Left>(\n async: boolean,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<boolean, Left>,\n options: ValidateOptions | ValidateAsyncOptions = {},\n):\n | E.Either<Left | ValidateError, void>\n | TE.TaskEither<Left | ValidateAsyncError, void> {\n // Init data required params.\n let authDate: Date | undefined;\n let authDateString: string | undefined;\n let hash: string | undefined;\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n (typeof value === 'string' ? new URLSearchParams(value) : value).forEach((value, key) => {\n if (key === 'hash') {\n hash = value;\n return;\n }\n\n if (key === 'auth_date') {\n authDateString = value;\n const authDateNum = parseInt(value, 10);\n if (!Number.isNaN(authDateNum)) {\n authDate = new Date(authDateNum * 1000);\n }\n }\n\n pairs.push(`${key}=${value}`);\n });\n\n // Hash and auth date always required.\n if (!hash) {\n return (async ? TE.left : E.left)(new SignatureMissingError(false));\n }\n\n if (!authDate) {\n return (async ? TE.left : E.left)(new AuthDateInvalidError(authDateString));\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n if (expiresIn > 0) {\n // Check if init data expired.\n const expiresAtTs = authDate.getTime() + (expiresIn * 1000);\n const nowTs = Date.now();\n if (expiresAtTs < nowTs) {\n return (async ? TE.left : E.left)(\n new ExpiredError(authDate, new Date(expiresAtTs), new Date(nowTs)),\n );\n }\n }\n\n // According to docs, we sort all the pairs in alphabetical order.\n pairs.sort();\n\n const eitherSignature = signData(pairs.join('\\n'), token, options);\n const onLeft = (error: Left) => E.left(error);\n const onRight = (signature: string) => (\n signature === hash ? E.right(undefined) : E.left(new SignatureInvalidError())\n );\n\n return typeof eitherSignature === 'function'\n ? fn.pipe(eitherSignature, TE.matchW(onLeft, onRight))\n : fn.pipe(eitherSignature, E.matchW(onLeft, onRight));\n}\n","import {\n parseInitDataQuery,\n parseInitDataQueryFp,\n type ParseInitDataQueryError,\n} from '@tma.js/transformers';\n\n/**\n * Parses an incoming value as init data.\n */\nexport const parse = parseInitDataQuery;\n\n/**\n * Parses an incoming value as init data.\n */\nexport const parseFp = parseInitDataQueryFp;\n\nexport { ParseInitDataQueryError as ParseError };\n"],"names":["E","fn","TE","value"],"mappings":"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"}
|
package/dist/entries/web.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const betterPromises = require("better-promises");
|
|
4
4
|
const fpTs = require("fp-ts");
|
|
5
|
-
const parsing = require("./parsing-
|
|
5
|
+
const parsing = require("./parsing-BMJa8cb6.cjs");
|
|
6
6
|
const toolkit = require("@tma.js/toolkit");
|
|
7
7
|
const createHmac = async (data, key) => {
|
|
8
8
|
const encoder = new TextEncoder();
|
package/dist/entries/web.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BetterPromise } from "better-promises";
|
|
2
2
|
import { function as _function, taskEither, either } from "fp-ts";
|
|
3
|
-
import { h as hashToken$1, A as AuthDateInvalidError, E as ExpiredError, S as SignatureInvalidError, c as SignatureMissingError, H as HexStringLengthInvalidError, s as signFp$1, a as signDataFp$1, v as validateFp$1 } from "./parsing-
|
|
4
|
-
import { i, e, p, d, f, g } from "./parsing-
|
|
3
|
+
import { h as hashToken$1, A as AuthDateInvalidError, E as ExpiredError, S as SignatureInvalidError, c as SignatureMissingError, H as HexStringLengthInvalidError, s as signFp$1, a as signDataFp$1, v as validateFp$1 } from "./parsing-Cn-1lfce.js";
|
|
4
|
+
import { i, e, p, d, f, g } from "./parsing-Cn-1lfce.js";
|
|
5
5
|
import { deepSnakeToCamelObjKeys } from "@tma.js/toolkit";
|
|
6
6
|
const createHmac = async (data, key) => {
|
|
7
7
|
const encoder = new TextEncoder();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tma.js/init-data-node",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.7",
|
|
4
4
|
"description": "TypeScript Node library to operate with Telegram init data.",
|
|
5
5
|
"author": "Vladislav Kibenko <wolfram.deus@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/Telegram-Mini-Apps/tma.js#readme",
|
|
@@ -51,10 +51,10 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"better-promises": "^1.0.0",
|
|
54
|
-
"error-kid": "^
|
|
54
|
+
"error-kid": "^2.0.0",
|
|
55
55
|
"fp-ts": "^2.16.11",
|
|
56
|
-
"@tma.js/transformers": "^1.1.3",
|
|
57
56
|
"@tma.js/toolkit": "^1.0.4",
|
|
57
|
+
"@tma.js/transformers": "^1.1.3",
|
|
58
58
|
"@tma.js/types": "^1.0.2"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parsing-4VnIGv0b.cjs","sources":["../../src/errors.ts","../../src/buf-converters.ts","../../src/hashToken.ts","../../src/signDataFp.ts","../../src/signFp.ts","../../src/validation.ts","../../src/parsing.ts"],"sourcesContent":["import { errorClass, errorClassWithData } from 'error-kid';\n\nexport class AuthDateInvalidError extends errorClassWithData<\n { value: string | undefined },\n [value?: string]\n>(\n 'AuthDateInvalidError',\n value => ({ value }),\n value => [`\"auth_date\" is invalid: ${value || 'value is missing'}`],\n) {\n}\n\nexport class SignatureInvalidError extends errorClass('SignatureInvalidError') {\n}\n\nexport class HexStringLengthInvalidError extends errorClass(\n 'HexStringLengthInvalidError',\n) {\n}\n\nexport class SignatureMissingError extends errorClass<[thirdParty: boolean]>(\n 'SignatureMissingError',\n thirdParty => [`\"${thirdParty ? 'signature' : 'hash'}\" parameter is missing`],\n) {\n}\n\nexport class ExpiredError extends errorClassWithData<\n { issuedAt: Date; expiresAt: Date },\n [issuedAt: Date, expiresAt: Date, now: Date]\n>(\n 'ExpiredError',\n (issuedAt, expiresAt) => ({ issuedAt, expiresAt }),\n (issuedAt, expiresAt, now) => [\n `Init data expired. Issued at ${issuedAt.toISOString()}, expires at ${expiresAt.toISOString()}, now is ${now.toISOString()}`,\n ],\n) {\n}\n","import { either as E } from 'fp-ts';\n\nimport { HexStringLengthInvalidError } from './errors.js';\n\n/**\n * Converts a hex string to ArrayBuffer.\n * @param hexString - value to convert.\n */\nexport function hexToArrayBuffer(hexString: string): E.Either<\n InstanceType<typeof HexStringLengthInvalidError>,\n ArrayBuffer\n> {\n if (hexString.length % 2 !== 0) {\n return E.left(new HexStringLengthInvalidError());\n }\n const buffer = new ArrayBuffer(hexString.length / 2);\n const uint8Array = new Uint8Array(buffer);\n for (let i = 0; i < hexString.length; i += 2) {\n uint8Array[i / 2] = parseInt(hexString.substring(i, i + 2), 16);\n }\n return E.right(buffer);\n}\n\n/**\n * Converts array buffer to hex.\n * @param arrBuf - buffer to convert\n */\nexport function arrayBufferToHex(arrBuf: ArrayBuffer): string {\n return new Uint8Array(arrBuf).reduce((acc, byte) => {\n // Convert byte to hex and pad with zero if needed (e.g., \"0a\" instead of \"a\")\n return acc + byte.toString(16).padStart(2, '0');\n }, '');\n}\n\nexport function bufferToArrayBuffer(buf: Buffer) {\n const ab = new ArrayBuffer(buf.length);\n buf.copy(new Uint8Array(ab));\n return ab;\n}\n","import type { CreateHmacFn, Text } from './types.js';\n\nexport function hashToken<H extends CreateHmacFn<any>>(token: Text, createHmac: H): ReturnType<H> {\n return createHmac(token, 'WebAppData') as ReturnType<H>;\n}\n","import { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport { arrayBufferToHex, hexToArrayBuffer } from './buf-converters.js';\nimport { hashToken } from './hashToken.js';\nimport type { CreateHmacFn, Text } from './types.js';\n\nexport interface SignDataOptions {\n /**\n * True, if token is already hashed and doesn't require hashing using HMAC-SHA-256.\n */\n tokenHashed?: boolean;\n}\n\nexport type SignDataError = ReturnType<typeof hexToArrayBuffer> extends E.Either<infer U, any>\n ? U\n : never;\n\nexport function signDataFp(\n async: false,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<false>,\n options?: SignDataOptions,\n): E.Either<SignDataError, string>;\n\nexport function signDataFp(\n async: true,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<true>,\n options?: SignDataOptions,\n): TE.TaskEither<SignDataError, string>;\n\nexport function signDataFp(\n async: boolean,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<boolean>,\n options: SignDataOptions = {},\n):\n | E.Either<SignDataError, string>\n | TE.TaskEither<SignDataError, string> {\n const keyHmac = options.tokenHashed\n ? typeof key === 'string'\n // If a hashed token was passed, we assume that it is a HEX string. Not to mess with\n // the createHmac function, we should convert this HEX string to ArrayBuffer. Otherwise,\n // incorrect behavior will be met.\n ? hexToArrayBuffer(key)\n : E.right(key)\n // Otherwise we are hashing the token, but we want it to be a monad.\n : fn.pipe(\n E.right(hashToken(key, createHmac)),\n E.match(() => null as never, v => {\n return v instanceof Promise\n ? TE.tryCatch(() => v, err => err as never)\n : E.right(v);\n }),\n );\n\n if (async || typeof keyHmac === 'function') {\n return fn.pipe(\n typeof keyHmac === 'function' ? keyHmac : TE.fromEither(keyHmac),\n TE.chainW(v => TE.tryCatch(\n () => Promise.resolve(createHmac(data, v)).then(arrayBufferToHex),\n err => err as never,\n )),\n );\n }\n return fn.pipe(\n keyHmac,\n // In this branch createHmac can't be asynchronous. If it is, keyHmac would be Promise and the\n // result would be returned in the previous \"if\" statement.\n E.chain(v => E.right(\n arrayBufferToHex((createHmac as CreateHmacFn<false>)(data, v)),\n )),\n );\n}\n","import { type InitDataLike, serializeInitDataQuery } from '@tma.js/transformers';\nimport { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport type { Text } from './types.js';\n\nexport type SignableData =\n & Omit<InitDataLike, 'auth_date' | 'hash' | 'signature'>\n & { signature?: string };\n\nexport interface SignOptions {\n /**\n * True, if token is already hashed and doesn't require hashing using HMAC-SHA-256.\n */\n tokenHashed?: boolean;\n}\n\ninterface SignDataFpArg<Async extends boolean, Left> {\n (data: Text, key: Text, options?: SignOptions): Async extends true\n ? TE.TaskEither<Left, string>\n : E.Either<Left, string>;\n}\n\n/**\n * Signs specified init data.\n * @param data - init data to sign.\n * @param authDate - date, when this init data should be signed.\n * @param key - private key.\n * @param signData - function signing data.\n * @param options - additional options.\n * @returns Signed init data presented as query parameters.\n */\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<false, Left>,\n options?: SignOptions,\n): E.Either<Left, string>;\n\n/**\n * Signs specified init data.\n * @param data - init data to sign.\n * @param authDate - date, when this init data should be signed.\n * @param key - private key.\n * @param signData - function signing data.\n * @param options - additional options.\n * @returns Signed init data presented as query parameters.\n */\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<true, Left>,\n options?: SignOptions,\n): TE.TaskEither<Left, string>;\n\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<boolean, Left>,\n options?: SignOptions,\n): E.Either<Left, string> | TE.TaskEither<Left, string> {\n const query = new URLSearchParams(serializeInitDataQuery({\n ...data,\n auth_date: authDate,\n signature: data.signature || '',\n }));\n\n // Convert search params to pairs and sort the final array.\n const pairs = [...query.entries()]\n .map(([name, value]) => `${name}=${value}`)\n .sort();\n\n // Compute sign, append it to the params and return.\n const queryWithHash = (signature: string): string => {\n query.append('hash', signature);\n return query.toString();\n };\n\n const eitherHash = signData(pairs.join('\\n'), key, options);\n return typeof eitherHash === 'function'\n ? fn.pipe(eitherHash, TE.chain(hash => TE.right(queryWithHash(hash))))\n : fn.pipe(eitherHash, E.chain(hash => E.right(queryWithHash(hash))));\n}\n","import {\n BetterPromise,\n type BetterPromiseOptions,\n type BetterPromiseRejectReason,\n} from 'better-promises';\nimport { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport {\n AuthDateInvalidError,\n ExpiredError,\n SignatureInvalidError,\n SignatureMissingError,\n} from './errors.js';\nimport { Text } from './types.js';\n\ntype OmittedPromiseOptions = Omit<BetterPromiseOptions, 'abortOnResolve' | 'abortOnReject'>;\n\nexport type ValidateValue = string | URLSearchParams;\nexport type Validate3rdValue = string | URLSearchParams;\n\nexport type ValidateError =\n | SignatureMissingError\n | SignatureInvalidError\n | AuthDateInvalidError\n | ExpiredError;\nexport type ValidateAsyncError = ValidateError | BetterPromiseRejectReason;\nexport type Validate3rdError =\n | SignatureMissingError\n | SignatureInvalidError\n | AuthDateInvalidError\n | ExpiredError\n | BetterPromiseRejectReason;\n\ninterface ValidateSignDataFpArg<Async extends boolean, Left> {\n (data: Text, key: Text, options?: ValidateOptions): Async extends true\n ? TE.TaskEither<Left, string>\n : E.Either<Left, string>;\n}\n\ninterface SharedValidateOptions {\n /**\n * Time in seconds which states, how long from creation time init data is considered valid.\n *\n * In other words, in case when authDate + expiresIn is before current time, init data is\n * recognized as expired.\n *\n * In case this value is equal to 0, the function does not check init data expiration.\n * @default 86400 (1 day)\n */\n expiresIn?: number;\n}\n\nexport interface ValidateOptions extends SharedValidateOptions {\n /**\n * True, if token is already hashed.\n * @default false\n */\n tokenHashed?: boolean;\n}\n\nexport interface ValidateAsyncOptions extends ValidateOptions, OmittedPromiseOptions {\n}\n\nexport interface Validate3rdOptions extends SharedValidateOptions, OmittedPromiseOptions {\n /**\n * When true, uses the test environment public key to validate init data.\n * @default false\n */\n test?: boolean;\n}\n\n/**\n * Validates passed init data using a publicly known Ee25519 key.\n * @param value - value to check.\n * @param botId - bot identifier\n * @param options - additional validation options.\n */\nexport function validate3rdFp(\n value: Validate3rdValue,\n botId: number,\n options: Validate3rdOptions = {},\n): TE.TaskEither<Validate3rdError, void> {\n // Init data required params.\n let authDate: Date | undefined;\n let authDateString: string | undefined;\n let signature: string | undefined;\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n (typeof value === 'string' ? new URLSearchParams(value) : value).forEach((value, key) => {\n if (key === 'hash') {\n return;\n }\n if (key === 'signature') {\n signature = value;\n return;\n }\n if (key === 'auth_date') {\n authDateString = value;\n const authDateNum = parseInt(value, 10);\n if (!Number.isNaN(authDateNum)) {\n authDate = new Date(authDateNum * 1000);\n }\n }\n\n pairs.push(`${key}=${value}`);\n });\n\n // Signature and auth date always required.\n if (!signature) {\n return TE.left(new SignatureMissingError(true));\n }\n\n if (!authDate) {\n return TE.left(new AuthDateInvalidError(authDateString));\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n if (expiresIn > 0) {\n // Check if init data expired.\n const expiresAtTs = authDate.getTime() + (expiresIn * 1000);\n const nowTs = Date.now();\n if (expiresAtTs < nowTs) {\n return TE.left(new ExpiredError(authDate, new Date(expiresAtTs), new Date(nowTs)));\n }\n }\n\n return fn.pipe(\n TE.tryCatch(\n () => {\n return BetterPromise.fn(async () => {\n return crypto.subtle.verify(\n 'Ed25519',\n await crypto.subtle.importKey(\n 'raw',\n Buffer.from(\n options.test\n ? '40055058a4ee38156a06562e52eece92a771bcd8346a8c4615cb7376eddf72ec'\n : 'e7bf03a2fa4602af4580703d88dda5bb59f32ed8b02a56c187fe7d34caed242d',\n 'hex',\n ),\n 'Ed25519',\n false,\n ['verify'],\n ),\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n Buffer.from(signature as string, 'base64'),\n Buffer.from(`${botId}:WebAppData\\n${pairs.sort().join('\\n')}`),\n );\n }, options);\n },\n (e: unknown) => e,\n ),\n TE.chainW(isVerified => {\n return isVerified\n ? TE.right(undefined)\n : TE.left(new SignatureInvalidError());\n }),\n );\n}\n\n/**\n * @see validate3rdFp\n */\nexport function validate3rd(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): BetterPromise<void> {\n return BetterPromise.fn(async () => {\n await fn.pipe(\n validate3rdFp(value, botId, options),\n TE.mapLeft(error => {\n throw error;\n }),\n )();\n });\n}\n\n/**\n * @param value - value to check.\n * @param botId - bot identifier\n * @param options - additional validation options.\n * @returns True is specified init data is signed by Telegram.\n */\nexport function isValid3rdFp(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): TE.TaskEither<void, boolean> {\n return fn.pipe(validate3rdFp(value, botId, options), TE.match(\n () => E.right(false),\n () => E.right(true),\n ));\n}\n\n/**\n * @see isValid3rdFp\n */\nexport function isValid3rd(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): BetterPromise<boolean> {\n return BetterPromise.fn(() => fn.pipe(\n isValid3rdFp(value, botId, options),\n TE.match(() => false, v => v),\n )());\n}\n\nexport function validateFp<Left>(\n async: false,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<false, Left>,\n options?: ValidateOptions,\n): E.Either<Left | ValidateError, void>;\n\nexport function validateFp<Left>(\n async: true,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<true, Left>,\n options?: ValidateAsyncOptions,\n): TE.TaskEither<Left | ValidateAsyncError, void>;\n\nexport function validateFp<Left>(\n async: boolean,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<boolean, Left>,\n options: ValidateOptions | ValidateAsyncOptions = {},\n):\n | E.Either<Left | ValidateError, void>\n | TE.TaskEither<Left | ValidateAsyncError, void> {\n // Init data required params.\n let authDate: Date | undefined;\n let authDateString: string | undefined;\n let hash: string | undefined;\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n (typeof value === 'string' ? new URLSearchParams(value) : value).forEach((value, key) => {\n if (key === 'hash') {\n hash = value;\n return;\n }\n\n if (key === 'auth_date') {\n authDateString = value;\n const authDateNum = parseInt(value, 10);\n if (!Number.isNaN(authDateNum)) {\n authDate = new Date(authDateNum * 1000);\n }\n }\n\n pairs.push(`${key}=${value}`);\n });\n\n // Hash and auth date always required.\n if (!hash) {\n return (async ? TE.left : E.left)(new SignatureMissingError(false));\n }\n\n if (!authDate) {\n return (async ? TE.left : E.left)(new AuthDateInvalidError(authDateString));\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n if (expiresIn > 0) {\n // Check if init data expired.\n const expiresAtTs = authDate.getTime() + (expiresIn * 1000);\n const nowTs = Date.now();\n if (expiresAtTs < nowTs) {\n return (async ? TE.left : E.left)(\n new ExpiredError(authDate, new Date(expiresAtTs), new Date(nowTs)),\n );\n }\n }\n\n // According to docs, we sort all the pairs in alphabetical order.\n pairs.sort();\n\n const eitherSignature = signData(pairs.join('\\n'), token, options);\n const onLeft = (error: Left) => E.left(error);\n const onRight = (signature: string) => (\n signature === hash ? E.right(undefined) : E.left(new SignatureInvalidError())\n );\n\n return typeof eitherSignature === 'function'\n ? fn.pipe(eitherSignature, TE.matchW(onLeft, onRight))\n : fn.pipe(eitherSignature, E.matchW(onLeft, onRight));\n}\n","import {\n parseInitDataQuery,\n parseInitDataQueryFp,\n type ParseInitDataQueryError,\n} from '@tma.js/transformers';\n\n/**\n * Parses an incoming value as init data.\n */\nexport const parse = parseInitDataQuery;\n\n/**\n * Parses an incoming value as init data.\n */\nexport const parseFp = parseInitDataQueryFp;\n\nexport { ParseInitDataQueryError as ParseError };\n"],"names":["errorClassWithData","errorClass","E","fn","TE","serializeInitDataQuery","value","BetterPromise","parseInitDataQuery","parseInitDataQueryFp"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parsing-Cjnt3_z4.js","sources":["../../src/errors.ts","../../src/buf-converters.ts","../../src/hashToken.ts","../../src/signDataFp.ts","../../src/signFp.ts","../../src/validation.ts","../../src/parsing.ts"],"sourcesContent":["import { errorClass, errorClassWithData } from 'error-kid';\n\nexport class AuthDateInvalidError extends errorClassWithData<\n { value: string | undefined },\n [value?: string]\n>(\n 'AuthDateInvalidError',\n value => ({ value }),\n value => [`\"auth_date\" is invalid: ${value || 'value is missing'}`],\n) {\n}\n\nexport class SignatureInvalidError extends errorClass('SignatureInvalidError') {\n}\n\nexport class HexStringLengthInvalidError extends errorClass(\n 'HexStringLengthInvalidError',\n) {\n}\n\nexport class SignatureMissingError extends errorClass<[thirdParty: boolean]>(\n 'SignatureMissingError',\n thirdParty => [`\"${thirdParty ? 'signature' : 'hash'}\" parameter is missing`],\n) {\n}\n\nexport class ExpiredError extends errorClassWithData<\n { issuedAt: Date; expiresAt: Date },\n [issuedAt: Date, expiresAt: Date, now: Date]\n>(\n 'ExpiredError',\n (issuedAt, expiresAt) => ({ issuedAt, expiresAt }),\n (issuedAt, expiresAt, now) => [\n `Init data expired. Issued at ${issuedAt.toISOString()}, expires at ${expiresAt.toISOString()}, now is ${now.toISOString()}`,\n ],\n) {\n}\n","import { either as E } from 'fp-ts';\n\nimport { HexStringLengthInvalidError } from './errors.js';\n\n/**\n * Converts a hex string to ArrayBuffer.\n * @param hexString - value to convert.\n */\nexport function hexToArrayBuffer(hexString: string): E.Either<\n InstanceType<typeof HexStringLengthInvalidError>,\n ArrayBuffer\n> {\n if (hexString.length % 2 !== 0) {\n return E.left(new HexStringLengthInvalidError());\n }\n const buffer = new ArrayBuffer(hexString.length / 2);\n const uint8Array = new Uint8Array(buffer);\n for (let i = 0; i < hexString.length; i += 2) {\n uint8Array[i / 2] = parseInt(hexString.substring(i, i + 2), 16);\n }\n return E.right(buffer);\n}\n\n/**\n * Converts array buffer to hex.\n * @param arrBuf - buffer to convert\n */\nexport function arrayBufferToHex(arrBuf: ArrayBuffer): string {\n return new Uint8Array(arrBuf).reduce((acc, byte) => {\n // Convert byte to hex and pad with zero if needed (e.g., \"0a\" instead of \"a\")\n return acc + byte.toString(16).padStart(2, '0');\n }, '');\n}\n\nexport function bufferToArrayBuffer(buf: Buffer) {\n const ab = new ArrayBuffer(buf.length);\n buf.copy(new Uint8Array(ab));\n return ab;\n}\n","import type { CreateHmacFn, Text } from './types.js';\n\nexport function hashToken<H extends CreateHmacFn<any>>(token: Text, createHmac: H): ReturnType<H> {\n return createHmac(token, 'WebAppData') as ReturnType<H>;\n}\n","import { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport { arrayBufferToHex, hexToArrayBuffer } from './buf-converters.js';\nimport { hashToken } from './hashToken.js';\nimport type { CreateHmacFn, Text } from './types.js';\n\nexport interface SignDataOptions {\n /**\n * True, if token is already hashed and doesn't require hashing using HMAC-SHA-256.\n */\n tokenHashed?: boolean;\n}\n\nexport type SignDataError = ReturnType<typeof hexToArrayBuffer> extends E.Either<infer U, any>\n ? U\n : never;\n\nexport function signDataFp(\n async: false,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<false>,\n options?: SignDataOptions,\n): E.Either<SignDataError, string>;\n\nexport function signDataFp(\n async: true,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<true>,\n options?: SignDataOptions,\n): TE.TaskEither<SignDataError, string>;\n\nexport function signDataFp(\n async: boolean,\n data: Text,\n key: Text,\n createHmac: CreateHmacFn<boolean>,\n options: SignDataOptions = {},\n):\n | E.Either<SignDataError, string>\n | TE.TaskEither<SignDataError, string> {\n const keyHmac = options.tokenHashed\n ? typeof key === 'string'\n // If a hashed token was passed, we assume that it is a HEX string. Not to mess with\n // the createHmac function, we should convert this HEX string to ArrayBuffer. Otherwise,\n // incorrect behavior will be met.\n ? hexToArrayBuffer(key)\n : E.right(key)\n // Otherwise we are hashing the token, but we want it to be a monad.\n : fn.pipe(\n E.right(hashToken(key, createHmac)),\n E.match(() => null as never, v => {\n return v instanceof Promise\n ? TE.tryCatch(() => v, err => err as never)\n : E.right(v);\n }),\n );\n\n if (async || typeof keyHmac === 'function') {\n return fn.pipe(\n typeof keyHmac === 'function' ? keyHmac : TE.fromEither(keyHmac),\n TE.chainW(v => TE.tryCatch(\n () => Promise.resolve(createHmac(data, v)).then(arrayBufferToHex),\n err => err as never,\n )),\n );\n }\n return fn.pipe(\n keyHmac,\n // In this branch createHmac can't be asynchronous. If it is, keyHmac would be Promise and the\n // result would be returned in the previous \"if\" statement.\n E.chain(v => E.right(\n arrayBufferToHex((createHmac as CreateHmacFn<false>)(data, v)),\n )),\n );\n}\n","import { type InitDataLike, serializeInitDataQuery } from '@tma.js/transformers';\nimport { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport type { Text } from './types.js';\n\nexport type SignableData =\n & Omit<InitDataLike, 'auth_date' | 'hash' | 'signature'>\n & { signature?: string };\n\nexport interface SignOptions {\n /**\n * True, if token is already hashed and doesn't require hashing using HMAC-SHA-256.\n */\n tokenHashed?: boolean;\n}\n\ninterface SignDataFpArg<Async extends boolean, Left> {\n (data: Text, key: Text, options?: SignOptions): Async extends true\n ? TE.TaskEither<Left, string>\n : E.Either<Left, string>;\n}\n\n/**\n * Signs specified init data.\n * @param data - init data to sign.\n * @param authDate - date, when this init data should be signed.\n * @param key - private key.\n * @param signData - function signing data.\n * @param options - additional options.\n * @returns Signed init data presented as query parameters.\n */\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<false, Left>,\n options?: SignOptions,\n): E.Either<Left, string>;\n\n/**\n * Signs specified init data.\n * @param data - init data to sign.\n * @param authDate - date, when this init data should be signed.\n * @param key - private key.\n * @param signData - function signing data.\n * @param options - additional options.\n * @returns Signed init data presented as query parameters.\n */\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<true, Left>,\n options?: SignOptions,\n): TE.TaskEither<Left, string>;\n\nexport function signFp<Left>(\n data: SignableData,\n key: Text,\n authDate: Date,\n signData: SignDataFpArg<boolean, Left>,\n options?: SignOptions,\n): E.Either<Left, string> | TE.TaskEither<Left, string> {\n const query = new URLSearchParams(serializeInitDataQuery({\n ...data,\n auth_date: authDate,\n signature: data.signature || '',\n }));\n\n // Convert search params to pairs and sort the final array.\n const pairs = [...query.entries()]\n .map(([name, value]) => `${name}=${value}`)\n .sort();\n\n // Compute sign, append it to the params and return.\n const queryWithHash = (signature: string): string => {\n query.append('hash', signature);\n return query.toString();\n };\n\n const eitherHash = signData(pairs.join('\\n'), key, options);\n return typeof eitherHash === 'function'\n ? fn.pipe(eitherHash, TE.chain(hash => TE.right(queryWithHash(hash))))\n : fn.pipe(eitherHash, E.chain(hash => E.right(queryWithHash(hash))));\n}\n","import {\n BetterPromise,\n type BetterPromiseOptions,\n type BetterPromiseRejectReason,\n} from 'better-promises';\nimport { either as E, taskEither as TE, function as fn } from 'fp-ts';\n\nimport {\n AuthDateInvalidError,\n ExpiredError,\n SignatureInvalidError,\n SignatureMissingError,\n} from './errors.js';\nimport { Text } from './types.js';\n\ntype OmittedPromiseOptions = Omit<BetterPromiseOptions, 'abortOnResolve' | 'abortOnReject'>;\n\nexport type ValidateValue = string | URLSearchParams;\nexport type Validate3rdValue = string | URLSearchParams;\n\nexport type ValidateError =\n | SignatureMissingError\n | SignatureInvalidError\n | AuthDateInvalidError\n | ExpiredError;\nexport type ValidateAsyncError = ValidateError | BetterPromiseRejectReason;\nexport type Validate3rdError =\n | SignatureMissingError\n | SignatureInvalidError\n | AuthDateInvalidError\n | ExpiredError\n | BetterPromiseRejectReason;\n\ninterface ValidateSignDataFpArg<Async extends boolean, Left> {\n (data: Text, key: Text, options?: ValidateOptions): Async extends true\n ? TE.TaskEither<Left, string>\n : E.Either<Left, string>;\n}\n\ninterface SharedValidateOptions {\n /**\n * Time in seconds which states, how long from creation time init data is considered valid.\n *\n * In other words, in case when authDate + expiresIn is before current time, init data is\n * recognized as expired.\n *\n * In case this value is equal to 0, the function does not check init data expiration.\n * @default 86400 (1 day)\n */\n expiresIn?: number;\n}\n\nexport interface ValidateOptions extends SharedValidateOptions {\n /**\n * True, if token is already hashed.\n * @default false\n */\n tokenHashed?: boolean;\n}\n\nexport interface ValidateAsyncOptions extends ValidateOptions, OmittedPromiseOptions {\n}\n\nexport interface Validate3rdOptions extends SharedValidateOptions, OmittedPromiseOptions {\n /**\n * When true, uses the test environment public key to validate init data.\n * @default false\n */\n test?: boolean;\n}\n\n/**\n * Validates passed init data using a publicly known Ee25519 key.\n * @param value - value to check.\n * @param botId - bot identifier\n * @param options - additional validation options.\n */\nexport function validate3rdFp(\n value: Validate3rdValue,\n botId: number,\n options: Validate3rdOptions = {},\n): TE.TaskEither<Validate3rdError, void> {\n // Init data required params.\n let authDate: Date | undefined;\n let authDateString: string | undefined;\n let signature: string | undefined;\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n (typeof value === 'string' ? new URLSearchParams(value) : value).forEach((value, key) => {\n if (key === 'hash') {\n return;\n }\n if (key === 'signature') {\n signature = value;\n return;\n }\n if (key === 'auth_date') {\n authDateString = value;\n const authDateNum = parseInt(value, 10);\n if (!Number.isNaN(authDateNum)) {\n authDate = new Date(authDateNum * 1000);\n }\n }\n\n pairs.push(`${key}=${value}`);\n });\n\n // Signature and auth date always required.\n if (!signature) {\n return TE.left(new SignatureMissingError(true));\n }\n\n if (!authDate) {\n return TE.left(new AuthDateInvalidError(authDateString));\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n if (expiresIn > 0) {\n // Check if init data expired.\n const expiresAtTs = authDate.getTime() + (expiresIn * 1000);\n const nowTs = Date.now();\n if (expiresAtTs < nowTs) {\n return TE.left(new ExpiredError(authDate, new Date(expiresAtTs), new Date(nowTs)));\n }\n }\n\n return fn.pipe(\n TE.tryCatch(\n () => {\n return BetterPromise.fn(async () => {\n return crypto.subtle.verify(\n 'Ed25519',\n await crypto.subtle.importKey(\n 'raw',\n Buffer.from(\n options.test\n ? '40055058a4ee38156a06562e52eece92a771bcd8346a8c4615cb7376eddf72ec'\n : 'e7bf03a2fa4602af4580703d88dda5bb59f32ed8b02a56c187fe7d34caed242d',\n 'hex',\n ),\n 'Ed25519',\n false,\n ['verify'],\n ),\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n Buffer.from(signature as string, 'base64'),\n Buffer.from(`${botId}:WebAppData\\n${pairs.sort().join('\\n')}`),\n );\n }, options);\n },\n (e: unknown) => e,\n ),\n TE.chainW(isVerified => {\n return isVerified\n ? TE.right(undefined)\n : TE.left(new SignatureInvalidError());\n }),\n );\n}\n\n/**\n * @see validate3rdFp\n */\nexport function validate3rd(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): BetterPromise<void> {\n return BetterPromise.fn(async () => {\n await fn.pipe(\n validate3rdFp(value, botId, options),\n TE.mapLeft(error => {\n throw error;\n }),\n )();\n });\n}\n\n/**\n * @param value - value to check.\n * @param botId - bot identifier\n * @param options - additional validation options.\n * @returns True is specified init data is signed by Telegram.\n */\nexport function isValid3rdFp(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): TE.TaskEither<void, boolean> {\n return fn.pipe(validate3rdFp(value, botId, options), TE.match(\n () => E.right(false),\n () => E.right(true),\n ));\n}\n\n/**\n * @see isValid3rdFp\n */\nexport function isValid3rd(\n value: Validate3rdValue,\n botId: number,\n options?: Validate3rdOptions,\n): BetterPromise<boolean> {\n return BetterPromise.fn(() => fn.pipe(\n isValid3rdFp(value, botId, options),\n TE.match(() => false, v => v),\n )());\n}\n\nexport function validateFp<Left>(\n async: false,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<false, Left>,\n options?: ValidateOptions,\n): E.Either<Left | ValidateError, void>;\n\nexport function validateFp<Left>(\n async: true,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<true, Left>,\n options?: ValidateAsyncOptions,\n): TE.TaskEither<Left | ValidateAsyncError, void>;\n\nexport function validateFp<Left>(\n async: boolean,\n value: ValidateValue,\n token: Text,\n signData: ValidateSignDataFpArg<boolean, Left>,\n options: ValidateOptions | ValidateAsyncOptions = {},\n):\n | E.Either<Left | ValidateError, void>\n | TE.TaskEither<Left | ValidateAsyncError, void> {\n // Init data required params.\n let authDate: Date | undefined;\n let authDateString: string | undefined;\n let hash: string | undefined;\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n (typeof value === 'string' ? new URLSearchParams(value) : value).forEach((value, key) => {\n if (key === 'hash') {\n hash = value;\n return;\n }\n\n if (key === 'auth_date') {\n authDateString = value;\n const authDateNum = parseInt(value, 10);\n if (!Number.isNaN(authDateNum)) {\n authDate = new Date(authDateNum * 1000);\n }\n }\n\n pairs.push(`${key}=${value}`);\n });\n\n // Hash and auth date always required.\n if (!hash) {\n return (async ? TE.left : E.left)(new SignatureMissingError(false));\n }\n\n if (!authDate) {\n return (async ? TE.left : E.left)(new AuthDateInvalidError(authDateString));\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n if (expiresIn > 0) {\n // Check if init data expired.\n const expiresAtTs = authDate.getTime() + (expiresIn * 1000);\n const nowTs = Date.now();\n if (expiresAtTs < nowTs) {\n return (async ? TE.left : E.left)(\n new ExpiredError(authDate, new Date(expiresAtTs), new Date(nowTs)),\n );\n }\n }\n\n // According to docs, we sort all the pairs in alphabetical order.\n pairs.sort();\n\n const eitherSignature = signData(pairs.join('\\n'), token, options);\n const onLeft = (error: Left) => E.left(error);\n const onRight = (signature: string) => (\n signature === hash ? E.right(undefined) : E.left(new SignatureInvalidError())\n );\n\n return typeof eitherSignature === 'function'\n ? fn.pipe(eitherSignature, TE.matchW(onLeft, onRight))\n : fn.pipe(eitherSignature, E.matchW(onLeft, onRight));\n}\n","import {\n parseInitDataQuery,\n parseInitDataQueryFp,\n type ParseInitDataQueryError,\n} from '@tma.js/transformers';\n\n/**\n * Parses an incoming value as init data.\n */\nexport const parse = parseInitDataQuery;\n\n/**\n * Parses an incoming value as init data.\n */\nexport const parseFp = parseInitDataQueryFp;\n\nexport { ParseInitDataQueryError as ParseError };\n"],"names":["E","fn","TE","value"],"mappings":"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"}
|