@tma.js/init-data 0.2.22 → 4.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +112 -16
- package/dist/dts/errors.d.ts +41 -0
- package/dist/dts/index.d.ts +7 -6
- package/dist/dts/parsing.d.ts +25 -0
- package/dist/dts/result.d.ts +45 -0
- package/dist/dts/signing.d.ts +54 -0
- package/dist/dts/types.d.ts +65 -57
- package/dist/dts/validation.d.ts +110 -0
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.iife.js +3 -1
- package/dist/index.iife.js.map +1 -1
- package/dist/index.js +246 -0
- package/dist/index.js.map +1 -0
- package/package.json +20 -21
- package/dist/dts/chat.d.ts +0 -10
- package/dist/dts/initData.d.ts +0 -5
- package/dist/dts/parse.d.ts +0 -6
- package/dist/dts/serialize.d.ts +0 -6
- package/dist/dts/user.d.ts +0 -5
- package/dist/index.mjs +0 -141
- package/dist/index.mjs.map +0 -1
- package/src/chat.ts +0 -17
- package/src/index.ts +0 -6
- package/src/initData.ts +0 -41
- package/src/parse.ts +0 -10
- package/src/serialize.ts +0 -77
- package/src/types.ts +0 -164
- package/src/user.ts +0 -45
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,28 +1,124 @@
|
|
|
1
1
|
# @tma.js/init-data
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Parse, validate and sign Telegram Mini Apps
|
|
4
|
+
[init data](https://docs.telegram-mini-apps.com/platform/init-data) on the server. Built on
|
|
5
|
+
Web Crypto, so it works in Node.js 20+, Bun, Deno, Cloudflare Workers and other modern runtimes.
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
```bash
|
|
8
|
+
pnpm i @tma.js/init-data
|
|
9
|
+
```
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
## Validating
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
`validate` checks the init data signature and expiration, and returns the parsed init data:
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
```ts
|
|
16
|
+
import { validate } from '@tma.js/init-data';
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
// Raw init data sent by the client, e.g. in the Authorization header.
|
|
19
|
+
const initData = await validate(rawInitData, botToken);
|
|
20
|
+
console.log(initData.user?.id, initData.auth_date);
|
|
21
|
+
```
|
|
14
22
|
|
|
15
|
-
|
|
23
|
+
It throws `SignatureMissingError`, `AuthDateInvalidError`, `ExpiredError`,
|
|
24
|
+
`SignatureInvalidError` or `InvalidInitDataError` if init data is invalid. Use `isValid` to get
|
|
25
|
+
a boolean instead.
|
|
16
26
|
|
|
27
|
+
### Handling errors
|
|
17
28
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
[![docs-badge]][docs-link]
|
|
21
|
-
[![code-badge]][code-link]
|
|
29
|
+
Each throwing function has a `safe` counterpart returning the error instead of throwing it.
|
|
30
|
+
The error type is a union of all possible errors, so the compiler knows what to handle:
|
|
22
31
|
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
```ts
|
|
33
|
+
import { matchError, safeValidate } from '@tma.js/init-data';
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
const result = await safeValidate(rawInitData, botToken);
|
|
36
|
+
if (!result.ok) {
|
|
37
|
+
// Compilation fails if any error is left unhandled.
|
|
38
|
+
return matchError(result.error, {
|
|
39
|
+
SignatureMissingError: () => reply(401, 'Init data is not signed'),
|
|
40
|
+
AuthDateInvalidError: () => reply(401, 'Init data has no valid auth date'),
|
|
41
|
+
ExpiredError: () => reply(401, 'Init data has expired'),
|
|
42
|
+
SignatureInvalidError: () => reply(403, 'Init data signature is invalid'),
|
|
43
|
+
InvalidInitDataError: () => reply(400, 'Init data has an unexpected structure'),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const initData = result.data;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Each error class also has the `is` method to check a single error: `ExpiredError.is(result.error)`.
|
|
50
|
+
The `ValidateError` type is the union of all validation errors.
|
|
51
|
+
|
|
52
|
+
Safe functions return only expected errors. Unexpected ones, like a broken Web Crypto
|
|
53
|
+
implementation, are still thrown.
|
|
54
|
+
|
|
55
|
+
Init data expires in 1 day by default. Change it with the `expiresIn` option (in seconds), or
|
|
56
|
+
pass `0` to skip the check:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
await validate(rawInitData, botToken, { expiresIn: 3600 });
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Secret key
|
|
63
|
+
|
|
64
|
+
Each call derives a key from the bot token. To do it once, create a secret key and pass it
|
|
65
|
+
instead of the token:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { createSecretKey, validate } from '@tma.js/init-data';
|
|
69
|
+
|
|
70
|
+
const secretKey = await createSecretKey(botToken);
|
|
71
|
+
await validate(rawInitData, secretKey);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If the server only validates init data, it doesn't need the bot token at all. Store its hash
|
|
75
|
+
created with `hashToken` instead:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { createSecretKey, hashToken } from '@tma.js/init-data';
|
|
79
|
+
|
|
80
|
+
await hashToken(botToken); // Run once, store the result.
|
|
81
|
+
const secretKey = await createSecretKey(process.env.BOT_TOKEN_HASH!, { hashed: true });
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Third-party validation
|
|
85
|
+
|
|
86
|
+
Init data of another bot can be validated without its token, using the Telegram public key:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { validate3rd } from '@tma.js/init-data';
|
|
90
|
+
|
|
91
|
+
const initData = await validate3rd(rawInitData, botId);
|
|
92
|
+
// Or safeValidate3rd to get the error instead of throwing it.
|
|
93
|
+
// Init data from the Telegram test environment.
|
|
94
|
+
await validate3rd(rawInitData, botId, { test: true });
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Parsing
|
|
98
|
+
|
|
99
|
+
`parse` reads init data without checking its signature. It throws `InvalidInitDataError` if the
|
|
100
|
+
value has an unexpected structure. `safeParse` returns this error instead.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import { parse, serialize } from '@tma.js/init-data';
|
|
104
|
+
|
|
105
|
+
const initData = parse(rawInitData);
|
|
106
|
+
serialize(initData); // Back to the query format.
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Signing
|
|
110
|
+
|
|
111
|
+
`sign` creates init data signed with the bot token. It is useful to test the server or to mock
|
|
112
|
+
the Telegram environment:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import { sign } from '@tma.js/init-data';
|
|
116
|
+
|
|
117
|
+
const rawInitData = await sign({
|
|
118
|
+
user: { id: 1, first_name: 'Pavel' },
|
|
119
|
+
// Defaults to the current date.
|
|
120
|
+
auth_date: new Date(),
|
|
121
|
+
}, botToken);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Use `signData` to sign an arbitrary data-check-string.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
declare const InvalidInitDataError_base: import('error-kid').ErrorClassWithData<[_value: string, cause?: unknown], {
|
|
2
|
+
value: string;
|
|
3
|
+
}, "InvalidInitDataError">;
|
|
4
|
+
/**
|
|
5
|
+
* Thrown when a value doesn't represent valid init data.
|
|
6
|
+
*/
|
|
7
|
+
export declare class InvalidInitDataError extends /* @__PURE__ */ InvalidInitDataError_base {
|
|
8
|
+
}
|
|
9
|
+
declare const SignatureMissingError_base: import('error-kid').ErrorClassWithData<[param: "hash" | "signature"], {
|
|
10
|
+
param: "hash" | "signature";
|
|
11
|
+
}, "SignatureMissingError">;
|
|
12
|
+
/**
|
|
13
|
+
* Thrown when init data has no parameter containing its signature.
|
|
14
|
+
*/
|
|
15
|
+
export declare class SignatureMissingError extends /* @__PURE__ */ SignatureMissingError_base {
|
|
16
|
+
}
|
|
17
|
+
declare const SignatureInvalidError_base: import('error-kid').ErrorClass<[], "SignatureInvalidError">;
|
|
18
|
+
/**
|
|
19
|
+
* Thrown when init data signature doesn't match its content.
|
|
20
|
+
*/
|
|
21
|
+
export declare class SignatureInvalidError extends /* @__PURE__ */ SignatureInvalidError_base {
|
|
22
|
+
}
|
|
23
|
+
declare const AuthDateInvalidError_base: import('error-kid').ErrorClassWithData<[value?: string | undefined], {
|
|
24
|
+
value: string | undefined;
|
|
25
|
+
}, "AuthDateInvalidError">;
|
|
26
|
+
/**
|
|
27
|
+
* Thrown when the `auth_date` init data parameter is missing or isn't a Unix time.
|
|
28
|
+
*/
|
|
29
|
+
export declare class AuthDateInvalidError extends /* @__PURE__ */ AuthDateInvalidError_base {
|
|
30
|
+
}
|
|
31
|
+
declare const ExpiredError_base: import('error-kid').ErrorClassWithData<[issuedAt: Date, expiresAt: Date, now: Date], {
|
|
32
|
+
issuedAt: Date;
|
|
33
|
+
expiresAt: Date;
|
|
34
|
+
now: Date;
|
|
35
|
+
}, "ExpiredError">;
|
|
36
|
+
/**
|
|
37
|
+
* Thrown when init data has expired.
|
|
38
|
+
*/
|
|
39
|
+
export declare class ExpiredError extends /* @__PURE__ */ ExpiredError_base {
|
|
40
|
+
}
|
|
41
|
+
export {};
|
package/dist/dts/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
1
|
+
export { matchError } from 'error-kid';
|
|
2
|
+
export { AuthDateInvalidError, ExpiredError, InvalidInitDataError, SignatureInvalidError, SignatureMissingError, } from './errors.js';
|
|
3
|
+
export { parse, safeParse, serialize } from './parsing.js';
|
|
4
|
+
export type { Result } from './result.js';
|
|
5
|
+
export { createSecretKey, hashToken, sign, signData, type Secret, type SignableInitData, } from './signing.js';
|
|
6
|
+
export { isValid, isValid3rd, safeValidate, safeValidate3rd, validate, validate3rd, type Validate3rdOptions, type ValidateError, type ValidateOptions, } from './validation.js';
|
|
7
|
+
export type * from './types.js';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { InvalidInitDataError } from './errors.js';
|
|
2
|
+
import { Result } from './result.js';
|
|
3
|
+
import { InitData } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Parses init data from its query representation. The function doesn't check the init data
|
|
6
|
+
* signature, use `safeValidate` for that.
|
|
7
|
+
* @param value - init data query.
|
|
8
|
+
* @returns Parsed init data, or `InvalidInitDataError` if the value doesn't represent valid
|
|
9
|
+
* init data.
|
|
10
|
+
*/
|
|
11
|
+
export declare function safeParse(value: string | URLSearchParams): Result<InvalidInitDataError, InitData>;
|
|
12
|
+
/**
|
|
13
|
+
* Parses init data from its query representation. The function doesn't check the init data
|
|
14
|
+
* signature, use `validate` for that.
|
|
15
|
+
*
|
|
16
|
+
* Throwing version of `safeParse`.
|
|
17
|
+
* @param value - init data query.
|
|
18
|
+
* @throws {InvalidInitDataError} The value doesn't represent valid init data.
|
|
19
|
+
*/
|
|
20
|
+
export declare const parse: (value: string | URLSearchParams) => InitData;
|
|
21
|
+
/**
|
|
22
|
+
* Converts init data to its query representation.
|
|
23
|
+
* @param value - init data.
|
|
24
|
+
*/
|
|
25
|
+
export declare function serialize(value: Partial<InitData>): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of an operation which can fail with one of the known errors. Unlike a thrown error,
|
|
3
|
+
* the error type here is checked by the compiler.
|
|
4
|
+
*/
|
|
5
|
+
export type Result<E, T> = {
|
|
6
|
+
ok: false;
|
|
7
|
+
error: E;
|
|
8
|
+
} | {
|
|
9
|
+
ok: true;
|
|
10
|
+
data: T;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* @returns A successful result.
|
|
14
|
+
* @param data - result data.
|
|
15
|
+
*/
|
|
16
|
+
export declare function ok<T>(data: T): {
|
|
17
|
+
ok: true;
|
|
18
|
+
data: T;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* @returns A failed result.
|
|
22
|
+
* @param error - result error.
|
|
23
|
+
*/
|
|
24
|
+
export declare function err<E>(error: E): {
|
|
25
|
+
ok: false;
|
|
26
|
+
error: E;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* @returns Result data.
|
|
30
|
+
* @param result - result to unwrap.
|
|
31
|
+
* @throws The result error, if the result is failed.
|
|
32
|
+
*/
|
|
33
|
+
export declare function unwrap<E extends Error, T>(result: Result<E, T>): T;
|
|
34
|
+
/**
|
|
35
|
+
* Creates a throwing version of a function returning a result. The created function accepts
|
|
36
|
+
* the same arguments and returns the result data, or throws the result error.
|
|
37
|
+
*
|
|
38
|
+
* Generic functions lose their type parameters when wrapped, so write their throwing versions
|
|
39
|
+
* manually using `unwrap`.
|
|
40
|
+
* @param fn - function returning a result, or a promise of it.
|
|
41
|
+
* @example
|
|
42
|
+
* export const createStartParam = throwing(safeCreateStartParam);
|
|
43
|
+
*/
|
|
44
|
+
export declare function throwing<A extends unknown[], E extends Error, T>(fn: (...args: A) => Promise<Result<E, T>>): (...args: A) => Promise<T>;
|
|
45
|
+
export declare function throwing<A extends unknown[], E extends Error, T>(fn: (...args: A) => Result<E, T>): (...args: A) => T;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { InitData } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Bot token, or a secret key created with `createSecretKey`.
|
|
4
|
+
*/
|
|
5
|
+
export type Secret = string | CryptoKey;
|
|
6
|
+
/**
|
|
7
|
+
* Init data to sign. If `auth_date` is omitted, the current date is used.
|
|
8
|
+
*/
|
|
9
|
+
export type SignableInitData = Omit<InitData, 'auth_date' | 'hash'> & {
|
|
10
|
+
auth_date?: Date;
|
|
11
|
+
};
|
|
12
|
+
export declare function bytesToHex(bytes: ArrayBuffer): string;
|
|
13
|
+
export declare function hexToBytes(hex: string): Uint8Array<ArrayBuffer>;
|
|
14
|
+
/**
|
|
15
|
+
* @returns Data-check-string of the init data parameters: `key=value` pairs sorted
|
|
16
|
+
* alphabetically and separated by line feeds.
|
|
17
|
+
* @param pairs - init data parameters.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createDataCheckString(pairs: [key: string, value: string][]): string;
|
|
20
|
+
/**
|
|
21
|
+
* Hashes the bot token the way Telegram does to sign init data. Store the result instead of
|
|
22
|
+
* the bot token if the server only needs to validate init data, and pass it to
|
|
23
|
+
* `createSecretKey` with the `hashed` option.
|
|
24
|
+
* @param token - bot token.
|
|
25
|
+
* @returns HMAC-SHA-256 of the bot token keyed with `WebAppData`, in the hex format.
|
|
26
|
+
*/
|
|
27
|
+
export declare function hashToken(token: string): Promise<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Creates a key used to sign and validate init data. Create it once and reuse to avoid
|
|
30
|
+
* hashing the bot token on each call.
|
|
31
|
+
* @param token - bot token, or its hash created with `hashToken` if `hashed` is true.
|
|
32
|
+
* @param options - additional options.
|
|
33
|
+
* @throws {TypeError} The token is marked as hashed but isn't a SHA-256 hash in the hex format.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createSecretKey(token: string, options?: {
|
|
36
|
+
hashed?: boolean;
|
|
37
|
+
}): Promise<CryptoKey>;
|
|
38
|
+
export declare function toSecretKey(secret: Secret): Promise<CryptoKey>;
|
|
39
|
+
/**
|
|
40
|
+
* Signs data the way Telegram signs init data.
|
|
41
|
+
* @param data - data to sign, usually a data-check-string.
|
|
42
|
+
* @param secret - bot token or a secret key.
|
|
43
|
+
* @returns Signature in the hex format.
|
|
44
|
+
*/
|
|
45
|
+
export declare function signData(data: string, secret: Secret): Promise<string>;
|
|
46
|
+
/**
|
|
47
|
+
* Signs init data. Useful to test the server or to mock the Telegram environment.
|
|
48
|
+
* @param data - init data to sign.
|
|
49
|
+
* @param secret - bot token or a secret key.
|
|
50
|
+
* @returns Signed init data in the query format.
|
|
51
|
+
* @example
|
|
52
|
+
* const initData = await sign({ user: { id: 1, first_name: 'Pavel' } }, botToken);
|
|
53
|
+
*/
|
|
54
|
+
export declare function sign(data: SignableInitData, secret: Secret): Promise<string>;
|
package/dist/dts/types.d.ts
CHANGED
|
@@ -1,133 +1,141 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Type of the chat from which the mini app was opened.
|
|
3
3
|
*/
|
|
4
4
|
export type ChatType = 'sender' | 'private' | 'group' | 'supergroup' | 'channel' | string;
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* @see https://core.telegram.org/bots/webapps#webappuser
|
|
7
7
|
*/
|
|
8
8
|
export interface User {
|
|
9
9
|
/**
|
|
10
|
-
* True
|
|
10
|
+
* True if the user added the bot to the attachment menu.
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
added_to_attachment_menu?: boolean;
|
|
13
13
|
/**
|
|
14
|
-
* True
|
|
14
|
+
* True if the user allowed the bot to message them.
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
allows_write_to_pm?: boolean;
|
|
17
17
|
/**
|
|
18
18
|
* First name of the user or bot.
|
|
19
19
|
*/
|
|
20
|
-
|
|
20
|
+
first_name: string;
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* Unique identifier of the user or bot.
|
|
23
23
|
*/
|
|
24
24
|
id: number;
|
|
25
25
|
/**
|
|
26
|
-
* True
|
|
27
|
-
* @see InitData.receiver
|
|
26
|
+
* True if the user is a bot. Returned in the `receiver` field only.
|
|
28
27
|
*/
|
|
29
|
-
|
|
28
|
+
is_bot?: boolean;
|
|
30
29
|
/**
|
|
31
|
-
* True
|
|
30
|
+
* True if the user has Telegram Premium.
|
|
32
31
|
*/
|
|
33
|
-
|
|
32
|
+
is_premium?: boolean;
|
|
34
33
|
/**
|
|
35
|
-
*
|
|
34
|
+
* [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag) of the user's
|
|
35
|
+
* language. Returned in the `user` field only.
|
|
36
36
|
*/
|
|
37
|
-
|
|
37
|
+
language_code?: string;
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
40
|
-
* Returns in user field only.
|
|
39
|
+
* Last name of the user or bot.
|
|
41
40
|
*/
|
|
42
|
-
|
|
41
|
+
last_name?: string;
|
|
43
42
|
/**
|
|
44
|
-
* URL of the user
|
|
45
|
-
* formats. Only returned for Mini Apps launched from the attachment menu.
|
|
43
|
+
* URL of the user's profile photo in the .jpeg or .svg format.
|
|
46
44
|
*/
|
|
47
|
-
|
|
45
|
+
photo_url?: string;
|
|
48
46
|
/**
|
|
49
47
|
* Username of the user or bot.
|
|
50
48
|
*/
|
|
51
49
|
username?: string;
|
|
52
50
|
}
|
|
53
51
|
/**
|
|
54
|
-
*
|
|
52
|
+
* @see https://core.telegram.org/bots/webapps#webappchat
|
|
55
53
|
*/
|
|
56
54
|
export interface Chat {
|
|
57
55
|
/**
|
|
58
|
-
* Unique identifier
|
|
56
|
+
* Unique identifier of the chat.
|
|
59
57
|
*/
|
|
60
58
|
id: number;
|
|
61
59
|
/**
|
|
62
|
-
* URL of the chat
|
|
63
|
-
*
|
|
64
|
-
*/
|
|
65
|
-
photoUrl?: string;
|
|
66
|
-
/**
|
|
67
|
-
* Type of chat.
|
|
60
|
+
* URL of the chat's photo in the .jpeg or .svg format. Returned only for mini apps launched
|
|
61
|
+
* from the attachment menu.
|
|
68
62
|
*/
|
|
69
|
-
|
|
63
|
+
photo_url?: string;
|
|
70
64
|
/**
|
|
71
65
|
* Title of the chat.
|
|
72
66
|
*/
|
|
73
67
|
title: string;
|
|
68
|
+
/**
|
|
69
|
+
* Type of the chat.
|
|
70
|
+
*/
|
|
71
|
+
type: 'group' | 'supergroup' | 'channel' | string;
|
|
74
72
|
/**
|
|
75
73
|
* Username of the chat.
|
|
76
74
|
*/
|
|
77
75
|
username?: string;
|
|
78
76
|
}
|
|
79
77
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
78
|
+
* Init data passed by the Telegram client to the mini app.
|
|
79
|
+
* @see https://core.telegram.org/bots/webapps#webappinitdata
|
|
80
|
+
* @see https://docs.telegram-mini-apps.com/platform/init-data
|
|
82
81
|
*/
|
|
83
82
|
export interface InitData {
|
|
84
83
|
/**
|
|
85
|
-
*
|
|
84
|
+
* Date when the init data was created.
|
|
86
85
|
*/
|
|
87
|
-
|
|
86
|
+
auth_date: Date;
|
|
88
87
|
/**
|
|
89
|
-
*
|
|
88
|
+
* Number of seconds after which a message can be sent via the
|
|
89
|
+
* [answerWebAppQuery](https://core.telegram.org/bots/api#answerwebappquery) method.
|
|
90
90
|
*/
|
|
91
|
-
|
|
91
|
+
can_send_after?: number;
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* chats – only for Mini Apps launched via the attachment menu.
|
|
93
|
+
* Chat where the bot was launched via the attachment menu, or the chat of the processed join
|
|
94
|
+
* request. Returned for supergroups, channels and group chats.
|
|
96
95
|
*/
|
|
97
96
|
chat?: Chat;
|
|
98
97
|
/**
|
|
99
|
-
*
|
|
98
|
+
* Global identifier of the chat from which the mini app was opened. Returned only for mini
|
|
99
|
+
* apps opened by a direct link.
|
|
100
|
+
*/
|
|
101
|
+
chat_instance?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Unique identifier for processing a chat join request via the
|
|
104
|
+
* [answerChatJoinRequestQuery](https://core.telegram.org/bots/api#answerchatjoinrequestquery)
|
|
105
|
+
* method.
|
|
100
106
|
*/
|
|
101
|
-
|
|
107
|
+
chat_join_request_query_id?: string;
|
|
102
108
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
109
|
+
* Type of the chat from which the mini app was opened. Returned only for mini apps opened by
|
|
110
|
+
* a direct link.
|
|
105
111
|
*/
|
|
106
|
-
|
|
112
|
+
chat_type?: ChatType;
|
|
107
113
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
114
|
+
* Init data hash used to validate it with the bot token.
|
|
115
|
+
* @see https://core.telegram.org/bots/webapps#validating-data-received-via-the-mini-app
|
|
110
116
|
*/
|
|
111
117
|
hash: string;
|
|
112
118
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
119
|
+
* Unique identifier of the mini app session, required for sending messages via the
|
|
120
|
+
* [answerWebAppQuery](https://core.telegram.org/bots/api#answerwebappquery) method.
|
|
115
121
|
*/
|
|
116
|
-
|
|
122
|
+
query_id?: string;
|
|
117
123
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* Returned only for private chats and only for Mini Apps launched
|
|
121
|
-
* via the attachment menu.
|
|
124
|
+
* Chat partner of the current user in the chat where the bot was launched via the attachment
|
|
125
|
+
* menu. Returned only for private chats.
|
|
122
126
|
*/
|
|
123
127
|
receiver?: User;
|
|
124
128
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
129
|
+
* Init data signature used to validate it without the bot token.
|
|
130
|
+
* @see https://core.telegram.org/bots/webapps#validating-data-for-third-party-use
|
|
131
|
+
*/
|
|
132
|
+
signature?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Value of the `startattach` or `startapp` parameter passed in the link.
|
|
127
135
|
*/
|
|
128
|
-
|
|
136
|
+
start_param?: string;
|
|
129
137
|
/**
|
|
130
|
-
*
|
|
138
|
+
* Current user.
|
|
131
139
|
*/
|
|
132
140
|
user?: User;
|
|
133
141
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { AuthDateInvalidError, ExpiredError, SignatureInvalidError, InvalidInitDataError, SignatureMissingError } from './errors.js';
|
|
2
|
+
import { Result } from './result.js';
|
|
3
|
+
import { Secret } from './signing.js';
|
|
4
|
+
import { InitData } from './types.js';
|
|
5
|
+
export interface ValidateOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Time in seconds during which init data is considered valid after it was created. Pass `0`
|
|
8
|
+
* to skip the expiration check.
|
|
9
|
+
* @default 86400 (1 day)
|
|
10
|
+
*/
|
|
11
|
+
expiresIn?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface Validate3rdOptions extends ValidateOptions {
|
|
14
|
+
/**
|
|
15
|
+
* True if init data was created in the Telegram test environment.
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
test?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Error returned when init data is invalid.
|
|
22
|
+
*/
|
|
23
|
+
export type ValidateError = SignatureMissingError | AuthDateInvalidError | ExpiredError | SignatureInvalidError | InvalidInitDataError;
|
|
24
|
+
/**
|
|
25
|
+
* Validates init data using the bot token and parses it.
|
|
26
|
+
* @param value - init data query.
|
|
27
|
+
* @param secret - bot token or a secret key created with `createSecretKey`.
|
|
28
|
+
* @param options - additional options.
|
|
29
|
+
* @returns Parsed init data, or one of the errors:
|
|
30
|
+
* - `SignatureMissingError`: the `hash` parameter is missing;
|
|
31
|
+
* - `AuthDateInvalidError`: the `auth_date` parameter is missing or invalid;
|
|
32
|
+
* - `ExpiredError`: init data has expired;
|
|
33
|
+
* - `SignatureInvalidError`: init data wasn't signed with the specified bot token;
|
|
34
|
+
* - `InvalidInitDataError`: init data is signed, but has an unexpected structure.
|
|
35
|
+
* @see https://core.telegram.org/bots/webapps#validating-data-received-via-the-mini-app
|
|
36
|
+
* @example
|
|
37
|
+
* const result = await safeValidate(rawInitData, botToken);
|
|
38
|
+
* if (!result.ok) {
|
|
39
|
+
* return matchError(result.error, {
|
|
40
|
+
* ExpiredError: () => reply(401, 'Init data has expired'),
|
|
41
|
+
* ...
|
|
42
|
+
* });
|
|
43
|
+
* }
|
|
44
|
+
* const initData = result.data;
|
|
45
|
+
*/
|
|
46
|
+
export declare function safeValidate(value: string | URLSearchParams, secret: Secret, options?: ValidateOptions): Promise<Result<ValidateError, InitData>>;
|
|
47
|
+
/**
|
|
48
|
+
* Validates init data using the bot token and parses it.
|
|
49
|
+
*
|
|
50
|
+
* Throwing version of `safeValidate`.
|
|
51
|
+
* @param value - init data query.
|
|
52
|
+
* @param secret - bot token or a secret key created with `createSecretKey`.
|
|
53
|
+
* @param options - additional options.
|
|
54
|
+
* @returns Parsed init data.
|
|
55
|
+
* @throws {SignatureMissingError} The `hash` parameter is missing.
|
|
56
|
+
* @throws {AuthDateInvalidError} The `auth_date` parameter is missing or invalid.
|
|
57
|
+
* @throws {ExpiredError} Init data has expired.
|
|
58
|
+
* @throws {SignatureInvalidError} Init data wasn't signed with the specified bot token.
|
|
59
|
+
* @throws {InvalidInitDataError} Init data is signed, but has an unexpected structure.
|
|
60
|
+
* @see https://core.telegram.org/bots/webapps#validating-data-received-via-the-mini-app
|
|
61
|
+
* @example
|
|
62
|
+
* const initData = await validate(rawInitData, botToken);
|
|
63
|
+
*/
|
|
64
|
+
export declare const validate: (value: string | URLSearchParams, secret: Secret, options?: ValidateOptions | undefined) => Promise<InitData>;
|
|
65
|
+
/**
|
|
66
|
+
* @returns True if init data is signed with the bot token and hasn't expired.
|
|
67
|
+
* @param value - init data query.
|
|
68
|
+
* @param secret - bot token or a secret key created with `createSecretKey`.
|
|
69
|
+
* @param options - additional options.
|
|
70
|
+
*/
|
|
71
|
+
export declare function isValid(value: string | URLSearchParams, secret: Secret, options?: ValidateOptions): Promise<boolean>;
|
|
72
|
+
/**
|
|
73
|
+
* Validates init data without the bot token, using the Telegram public key, and parses it.
|
|
74
|
+
* Useful for third parties receiving init data of another bot.
|
|
75
|
+
* @param value - init data query.
|
|
76
|
+
* @param botId - identifier of the bot the init data was issued for.
|
|
77
|
+
* @param options - additional options.
|
|
78
|
+
* @returns Parsed init data, or one of the errors:
|
|
79
|
+
* - `SignatureMissingError`: the `signature` parameter is missing;
|
|
80
|
+
* - `AuthDateInvalidError`: the `auth_date` parameter is missing or invalid;
|
|
81
|
+
* - `ExpiredError`: init data has expired;
|
|
82
|
+
* - `SignatureInvalidError`: init data wasn't signed by Telegram for the specified bot;
|
|
83
|
+
* - `InvalidInitDataError`: init data is signed, but has an unexpected structure.
|
|
84
|
+
* @see https://core.telegram.org/bots/webapps#validating-data-for-third-party-use
|
|
85
|
+
*/
|
|
86
|
+
export declare function safeValidate3rd(value: string | URLSearchParams, botId: number, options?: Validate3rdOptions): Promise<Result<ValidateError, InitData>>;
|
|
87
|
+
/**
|
|
88
|
+
* Validates init data without the bot token, using the Telegram public key, and parses it.
|
|
89
|
+
* Useful for third parties receiving init data of another bot.
|
|
90
|
+
*
|
|
91
|
+
* Throwing version of `safeValidate3rd`.
|
|
92
|
+
* @param value - init data query.
|
|
93
|
+
* @param botId - identifier of the bot the init data was issued for.
|
|
94
|
+
* @param options - additional options.
|
|
95
|
+
* @returns Parsed init data.
|
|
96
|
+
* @throws {SignatureMissingError} The `signature` parameter is missing.
|
|
97
|
+
* @throws {AuthDateInvalidError} The `auth_date` parameter is missing or invalid.
|
|
98
|
+
* @throws {ExpiredError} Init data has expired.
|
|
99
|
+
* @throws {SignatureInvalidError} Init data wasn't signed by Telegram for the specified bot.
|
|
100
|
+
* @throws {InvalidInitDataError} Init data is signed, but has an unexpected structure.
|
|
101
|
+
* @see https://core.telegram.org/bots/webapps#validating-data-for-third-party-use
|
|
102
|
+
*/
|
|
103
|
+
export declare const validate3rd: (value: string | URLSearchParams, botId: number, options?: Validate3rdOptions | undefined) => Promise<InitData>;
|
|
104
|
+
/**
|
|
105
|
+
* @returns True if init data is signed by Telegram for the specified bot and hasn't expired.
|
|
106
|
+
* @param value - init data query.
|
|
107
|
+
* @param botId - identifier of the bot the init data was issued for.
|
|
108
|
+
* @param options - additional options.
|
|
109
|
+
*/
|
|
110
|
+
export declare function isValid3rd(value: string | URLSearchParams, botId: number, options?: Validate3rdOptions): Promise<boolean>;
|