@v3finance/monitoring-sdk 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +247 -2
  4. package/dist/cjs/client.d.ts +65 -0
  5. package/dist/cjs/client.d.ts.map +1 -0
  6. package/dist/cjs/client.js +89 -0
  7. package/dist/cjs/client.js.map +1 -0
  8. package/dist/cjs/core/errors.d.ts +64 -0
  9. package/dist/cjs/core/errors.d.ts.map +1 -0
  10. package/dist/cjs/core/errors.js +95 -0
  11. package/dist/cjs/core/errors.js.map +1 -0
  12. package/dist/cjs/core/http.d.ts +62 -0
  13. package/dist/cjs/core/http.d.ts.map +1 -0
  14. package/dist/cjs/core/http.js +151 -0
  15. package/dist/cjs/core/http.js.map +1 -0
  16. package/dist/cjs/core/pagination.d.ts +13 -0
  17. package/dist/cjs/core/pagination.d.ts.map +1 -0
  18. package/dist/cjs/core/pagination.js +15 -0
  19. package/dist/cjs/core/pagination.js.map +1 -0
  20. package/dist/cjs/generated/types.d.ts +324 -0
  21. package/dist/cjs/generated/types.d.ts.map +1 -0
  22. package/dist/cjs/generated/types.js +5 -0
  23. package/dist/cjs/generated/types.js.map +1 -0
  24. package/dist/cjs/index.d.ts +23 -0
  25. package/dist/cjs/index.d.ts.map +1 -0
  26. package/dist/cjs/index.js +50 -0
  27. package/dist/cjs/index.js.map +1 -0
  28. package/dist/cjs/package.json +1 -0
  29. package/dist/cjs/resources/account.d.ts +61 -0
  30. package/dist/cjs/resources/account.d.ts.map +1 -0
  31. package/dist/cjs/resources/account.js +75 -0
  32. package/dist/cjs/resources/account.js.map +1 -0
  33. package/dist/cjs/resources/addresses.d.ts +109 -0
  34. package/dist/cjs/resources/addresses.d.ts.map +1 -0
  35. package/dist/cjs/resources/addresses.js +137 -0
  36. package/dist/cjs/resources/addresses.js.map +1 -0
  37. package/dist/cjs/resources/catalog.d.ts +30 -0
  38. package/dist/cjs/resources/catalog.d.ts.map +1 -0
  39. package/dist/cjs/resources/catalog.js +46 -0
  40. package/dist/cjs/resources/catalog.js.map +1 -0
  41. package/dist/cjs/resources/clients.d.ts +84 -0
  42. package/dist/cjs/resources/clients.d.ts.map +1 -0
  43. package/dist/cjs/resources/clients.js +102 -0
  44. package/dist/cjs/resources/clients.js.map +1 -0
  45. package/dist/cjs/resources/deliveries.d.ts +50 -0
  46. package/dist/cjs/resources/deliveries.d.ts.map +1 -0
  47. package/dist/cjs/resources/deliveries.js +43 -0
  48. package/dist/cjs/resources/deliveries.js.map +1 -0
  49. package/dist/cjs/resources/transactions.d.ts +28 -0
  50. package/dist/cjs/resources/transactions.d.ts.map +1 -0
  51. package/dist/cjs/resources/transactions.js +35 -0
  52. package/dist/cjs/resources/transactions.js.map +1 -0
  53. package/dist/cjs/units.d.ts +29 -0
  54. package/dist/cjs/units.d.ts.map +1 -0
  55. package/dist/cjs/units.js +62 -0
  56. package/dist/cjs/units.js.map +1 -0
  57. package/dist/cjs/version.d.ts +5 -0
  58. package/dist/cjs/version.d.ts.map +1 -0
  59. package/dist/cjs/version.js +8 -0
  60. package/dist/cjs/version.js.map +1 -0
  61. package/dist/cjs/webhooks.d.ts +77 -0
  62. package/dist/cjs/webhooks.d.ts.map +1 -0
  63. package/dist/cjs/webhooks.js +128 -0
  64. package/dist/cjs/webhooks.js.map +1 -0
  65. package/dist/esm/client.d.ts +65 -0
  66. package/dist/esm/client.d.ts.map +1 -0
  67. package/dist/esm/client.js +85 -0
  68. package/dist/esm/client.js.map +1 -0
  69. package/dist/esm/core/errors.d.ts +64 -0
  70. package/dist/esm/core/errors.d.ts.map +1 -0
  71. package/dist/esm/core/errors.js +86 -0
  72. package/dist/esm/core/errors.js.map +1 -0
  73. package/dist/esm/core/http.d.ts +62 -0
  74. package/dist/esm/core/http.d.ts.map +1 -0
  75. package/dist/esm/core/http.js +146 -0
  76. package/dist/esm/core/http.js.map +1 -0
  77. package/dist/esm/core/pagination.d.ts +13 -0
  78. package/dist/esm/core/pagination.d.ts.map +1 -0
  79. package/dist/esm/core/pagination.js +12 -0
  80. package/dist/esm/core/pagination.js.map +1 -0
  81. package/dist/esm/generated/types.d.ts +324 -0
  82. package/dist/esm/generated/types.d.ts.map +1 -0
  83. package/dist/esm/generated/types.js +4 -0
  84. package/dist/esm/generated/types.js.map +1 -0
  85. package/dist/esm/index.d.ts +23 -0
  86. package/dist/esm/index.d.ts.map +1 -0
  87. package/dist/esm/index.js +20 -0
  88. package/dist/esm/index.js.map +1 -0
  89. package/dist/esm/resources/account.d.ts +61 -0
  90. package/dist/esm/resources/account.d.ts.map +1 -0
  91. package/dist/esm/resources/account.js +69 -0
  92. package/dist/esm/resources/account.js.map +1 -0
  93. package/dist/esm/resources/addresses.d.ts +109 -0
  94. package/dist/esm/resources/addresses.d.ts.map +1 -0
  95. package/dist/esm/resources/addresses.js +133 -0
  96. package/dist/esm/resources/addresses.js.map +1 -0
  97. package/dist/esm/resources/catalog.d.ts +30 -0
  98. package/dist/esm/resources/catalog.d.ts.map +1 -0
  99. package/dist/esm/resources/catalog.js +41 -0
  100. package/dist/esm/resources/catalog.js.map +1 -0
  101. package/dist/esm/resources/clients.d.ts +84 -0
  102. package/dist/esm/resources/clients.d.ts.map +1 -0
  103. package/dist/esm/resources/clients.js +97 -0
  104. package/dist/esm/resources/clients.js.map +1 -0
  105. package/dist/esm/resources/deliveries.d.ts +50 -0
  106. package/dist/esm/resources/deliveries.d.ts.map +1 -0
  107. package/dist/esm/resources/deliveries.js +39 -0
  108. package/dist/esm/resources/deliveries.js.map +1 -0
  109. package/dist/esm/resources/transactions.d.ts +28 -0
  110. package/dist/esm/resources/transactions.d.ts.map +1 -0
  111. package/dist/esm/resources/transactions.js +31 -0
  112. package/dist/esm/resources/transactions.js.map +1 -0
  113. package/dist/esm/units.d.ts +29 -0
  114. package/dist/esm/units.d.ts.map +1 -0
  115. package/dist/esm/units.js +58 -0
  116. package/dist/esm/units.js.map +1 -0
  117. package/dist/esm/version.d.ts +5 -0
  118. package/dist/esm/version.d.ts.map +1 -0
  119. package/dist/esm/version.js +5 -0
  120. package/dist/esm/version.js.map +1 -0
  121. package/dist/esm/webhooks.d.ts +77 -0
  122. package/dist/esm/webhooks.d.ts.map +1 -0
  123. package/dist/esm/webhooks.js +120 -0
  124. package/dist/esm/webhooks.js.map +1 -0
  125. package/package.json +66 -4
  126. package/src/client.ts +94 -0
  127. package/src/core/errors.ts +99 -0
  128. package/src/core/http.ts +193 -0
  129. package/src/core/pagination.ts +21 -0
  130. package/src/generated/types.ts +355 -0
  131. package/src/index.ts +60 -0
  132. package/src/resources/account.ts +87 -0
  133. package/src/resources/addresses.ts +190 -0
  134. package/src/resources/catalog.ts +47 -0
  135. package/src/resources/clients.ts +135 -0
  136. package/src/resources/deliveries.ts +69 -0
  137. package/src/resources/transactions.ts +33 -0
  138. package/src/units.ts +56 -0
  139. package/src/version.ts +5 -0
  140. package/src/webhooks.ts +133 -0
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ /**
3
+ * Приём вебхуков: проверка подписи и разбор тела. Работает без клиента API и без сети — нужен только секрет
4
+ * подписи клиента. Использует WebCrypto: Node.js 20+, Bun, Deno, Cloudflare Workers.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.WEBHOOK_HEADERS = void 0;
8
+ exports.signWebhookBody = signWebhookBody;
9
+ exports.verifyWebhookSignature = verifyWebhookSignature;
10
+ exports.parseWebhook = parseWebhook;
11
+ exports.isTestWebhook = isTestWebhook;
12
+ exports.webhookIdempotencyKey = webhookIdempotencyKey;
13
+ const errors_js_1 = require("./core/errors.js");
14
+ /** Заголовки вебхука */
15
+ exports.WEBHOOK_HEADERS = {
16
+ /** HMAC-SHA256 сырого тела секретом клиента, hex в нижнем регистре */
17
+ signature: 'x-signature',
18
+ /** id клиента */
19
+ clientId: 'x-client-id',
20
+ /** `1` у тестового вебхука — такой не зачислять */
21
+ test: 'x-webhook-test',
22
+ };
23
+ const encoder = new TextEncoder();
24
+ function bytesOf(body) {
25
+ if (typeof body === 'string')
26
+ return encoder.encode(body);
27
+ // копия: WebCrypto не принимает view над SharedArrayBuffer (Buffer в Node.js — тоже Uint8Array)
28
+ return body instanceof Uint8Array ? new Uint8Array(body) : new Uint8Array(body);
29
+ }
30
+ function signatureOf(source) {
31
+ if (source === null || source === undefined)
32
+ return undefined;
33
+ if (typeof source === 'string')
34
+ return source;
35
+ if (typeof source.get === 'function')
36
+ return source.get(exports.WEBHOOK_HEADERS.signature) ?? undefined;
37
+ const value = source[exports.WEBHOOK_HEADERS.signature];
38
+ return Array.isArray(value) ? value[0] : value;
39
+ }
40
+ /** Сравнение без утечки по времени: время не зависит от того, где строки расходятся */
41
+ function safeEqual(a, b) {
42
+ if (a.length !== b.length)
43
+ return false;
44
+ let diff = 0;
45
+ for (let i = 0; i < a.length; i++)
46
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
47
+ return diff === 0;
48
+ }
49
+ /**
50
+ * Подпись тела секретом клиента — как её считает сервис. Нужна в тестах вашего обработчика вебхуков.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * const body = JSON.stringify({ tx: { …, id: 'test' } })
55
+ * await fetch('http://localhost:3000/webhooks', { method: 'POST', body, headers: { 'x-signature': await signWebhookBody(body, secret) } })
56
+ * ```
57
+ */
58
+ async function signWebhookBody(body, secret) {
59
+ const key = await crypto.subtle.importKey('raw', encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
60
+ const mac = new Uint8Array(await crypto.subtle.sign('HMAC', key, bytesOf(body)));
61
+ return Array.from(mac, (b) => b.toString(16).padStart(2, '0')).join('');
62
+ }
63
+ /**
64
+ * Проверяет подпись вебхука: `true` — тело пришло от сервиса и не изменено.
65
+ *
66
+ * @param body - сырое тело запроса
67
+ * @param signature - заголовок `x-signature` или все заголовки запроса
68
+ * @param secret - секрет подписи клиента
69
+ */
70
+ async function verifyWebhookSignature(body, signature, secret) {
71
+ const given = signatureOf(signature)?.trim().toLowerCase();
72
+ if (!given)
73
+ return false;
74
+ return safeEqual(await signWebhookBody(body, secret), given);
75
+ }
76
+ /**
77
+ * Проверяет подпись и возвращает разобранный вебхук.
78
+ *
79
+ * Дальше — по правилам приёма: тестовый вебхук ({@link isTestWebhook}) не зачислять; один и тот же вебхук может
80
+ * прийти повторно — обрабатывайте идемпотентно по {@link webhookIdempotencyKey}; ответьте 2xx в течение 15 секунд.
81
+ * Вебхук уходит, как только перевод попал в блок, — для крупных сумм дождитесь финальности
82
+ * (`monitoring.transactions.get(...).final`).
83
+ *
84
+ * @throws {@link WebhookSignatureError} подпись не совпала — ответьте 401 и ничего не зачисляйте
85
+ *
86
+ * @example Express — нужен сырой body
87
+ * ```ts
88
+ * app.post('/webhooks/monitoring', express.raw({ type: 'application/json' }), async (req, res) => {
89
+ * const event = await parseWebhook(req.body, req.headers, process.env.MONITORING_WEBHOOK_SECRET!)
90
+ * if (!isTestWebhook(event)) await creditOnce(webhookIdempotencyKey(event), event.tx)
91
+ * res.sendStatus(200)
92
+ * })
93
+ * ```
94
+ *
95
+ * @example Hono, Next.js route handler, Cloudflare Workers
96
+ * ```ts
97
+ * const event = await parseWebhook(await request.text(), request.headers, env.MONITORING_WEBHOOK_SECRET)
98
+ * ```
99
+ */
100
+ async function parseWebhook(body, signature, secret) {
101
+ if (!(await verifyWebhookSignature(body, signature, secret)))
102
+ throw new errors_js_1.WebhookSignatureError();
103
+ let payload;
104
+ try {
105
+ payload = JSON.parse(typeof body === 'string' ? body : new TextDecoder().decode(bytesOf(body)));
106
+ }
107
+ catch (e) {
108
+ throw new errors_js_1.MonitoringError('webhook body is not valid JSON', { cause: e });
109
+ }
110
+ const tx = payload?.tx;
111
+ if (typeof tx !== 'object' || tx === null || typeof tx.id !== 'string')
112
+ throw new errors_js_1.MonitoringError('webhook body has no tx');
113
+ return payload;
114
+ }
115
+ /** Тестовый вебхук (из панели или `clients.sendTestWebhook`) — такой не зачислять */
116
+ function isTestWebhook(event) {
117
+ return event.test === true;
118
+ }
119
+ /**
120
+ * Ключ идемпотентности вебхука: сеть, транзакция и номер лога. Один перевод — один ключ, даже если вебхук пришёл
121
+ * несколько раз. В одной транзакции EVM может быть несколько переводов токенов — у них разный `logIndex`.
122
+ *
123
+ * @example `"TRON:1249cb…a5fc45:"`, `"ETHEREUM:0x3fbc…1d57:7"`
124
+ */
125
+ function webhookIdempotencyKey(event) {
126
+ return `${event.tx.network}:${event.tx.id}:${event.tx.logIndex ?? ''}`;
127
+ }
128
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/webhooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { type ClientOptions, type RequestOptions } from './core/http.js';
2
+ import { AccountResource, AuthResource, type SignInResult } from './resources/account.js';
3
+ import { AddressesResource } from './resources/addresses.js';
4
+ import { AssetsResource, NetworksResource } from './resources/catalog.js';
5
+ import { ClientsResource } from './resources/clients.js';
6
+ import { DeliveriesResource } from './resources/deliveries.js';
7
+ import { TransactionsResource } from './resources/transactions.js';
8
+ /**
9
+ * Клиент API мониторинга адресов V3 Finance: адреса и подписки, история вебхуков, транзакции, ваш клиент и ключи.
10
+ * Только для сервера: ключ в браузере увидит любой.
11
+ *
12
+ * @example С ключом клиента — для бэкенда
13
+ * ```ts
14
+ * import { MonitoringClient } from '@v3finance/monitoring-sdk'
15
+ *
16
+ * const monitoring = new MonitoringClient({ apiKey: process.env.MONITORING_API_KEY })
17
+ * await monitoring.addresses.add(clientId, [{ network: 'tron', address: 'T…' }], { assets: ['USDT'], direction: 'in' })
18
+ * ```
19
+ *
20
+ * @example По паролю — для скриптов, которым нужны права пользователя
21
+ * ```ts
22
+ * const { client } = await MonitoringClient.signIn({ email, password })
23
+ * const { key } = await client.account.keys.create({ name: 'ci' })
24
+ * ```
25
+ */
26
+ export declare class MonitoringClient {
27
+ #private;
28
+ /** Кто вы и ваши личные ключи */
29
+ readonly account: AccountResource;
30
+ /** Выход и смена пароля (для клиента, вошедшего по паролю) */
31
+ readonly auth: AuthResource;
32
+ /** Сети */
33
+ readonly networks: NetworksResource;
34
+ /** Нативные монеты и токены */
35
+ readonly assets: AssetsResource;
36
+ /** Ваш клиент: URL вебхука, секрет, ключи, участники, тестовый вебхук */
37
+ readonly clients: ClientsResource;
38
+ /** Адреса на мониторинге и подписка */
39
+ readonly addresses: AddressesResource;
40
+ /** История вебхуков */
41
+ readonly deliveries: DeliveriesResource;
42
+ /** Транзакция по хешу: статус, подтверждения, финальность */
43
+ readonly transactions: TransactionsResource;
44
+ /**
45
+ * @param options - ключ (`apiKey`) или токен сессии (`sessionToken`), адрес API, таймаут, повторы
46
+ * @throws {@link MonitoringError} переданы и ключ, и токен; нет `fetch`
47
+ */
48
+ constructor(options?: ClientOptions);
49
+ /** Адрес API, с которым работает клиент */
50
+ get baseUrl(): string;
51
+ /**
52
+ * Вход по email и паролю: возвращает клиента с токеном сессии. Регистрации нет — пользователей заводит
53
+ * администратор сервиса. Не больше 3 попыток за 10 секунд с одного IP.
54
+ *
55
+ * @param options - настройки клиента, кроме учётных данных
56
+ * @throws {@link MonitoringApiError} 401 — неверный email или пароль
57
+ */
58
+ static signIn(credentials: {
59
+ email: string;
60
+ password: string;
61
+ }, options?: Omit<ClientOptions, 'apiKey' | 'sessionToken'>, requestOptions?: RequestOptions): Promise<SignInResult & {
62
+ client: MonitoringClient;
63
+ }>;
64
+ }
65
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAGlE;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,gBAAgB;;IAC3B,iCAAiC;IACjC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;IACjC,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;IAC3B,WAAW;IACX,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAA;IACnC,+BAA+B;IAC/B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;IACjC,uCAAuC;IACvC,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAA;IACrC,uBAAuB;IACvB,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAA;IACvC,6DAA6D;IAC7D,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAA;IAI3C;;;OAGG;IACH,YAAY,OAAO,GAAE,aAAkB,EAUtC;IAED,2CAA2C;IAC3C,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;;;;OAMG;IACH,OAAa,MAAM,CACjB,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAChD,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,cAAc,CAAM,EAC5D,cAAc,CAAC,EAAE,cAAc,GAC9B,OAAO,CAAC,YAAY,GAAG;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAYtD;CACF"}
@@ -0,0 +1,85 @@
1
+ import { HttpClient } from './core/http.js';
2
+ import { AccountResource, AuthResource } from './resources/account.js';
3
+ import { AddressesResource } from './resources/addresses.js';
4
+ import { AssetsResource, NetworksResource } from './resources/catalog.js';
5
+ import { ClientsResource } from './resources/clients.js';
6
+ import { DeliveriesResource } from './resources/deliveries.js';
7
+ import { TransactionsResource } from './resources/transactions.js';
8
+ import { DEFAULT_BASE_URL } from './version.js';
9
+ /**
10
+ * Клиент API мониторинга адресов V3 Finance: адреса и подписки, история вебхуков, транзакции, ваш клиент и ключи.
11
+ * Только для сервера: ключ в браузере увидит любой.
12
+ *
13
+ * @example С ключом клиента — для бэкенда
14
+ * ```ts
15
+ * import { MonitoringClient } from '@v3finance/monitoring-sdk'
16
+ *
17
+ * const monitoring = new MonitoringClient({ apiKey: process.env.MONITORING_API_KEY })
18
+ * await monitoring.addresses.add(clientId, [{ network: 'tron', address: 'T…' }], { assets: ['USDT'], direction: 'in' })
19
+ * ```
20
+ *
21
+ * @example По паролю — для скриптов, которым нужны права пользователя
22
+ * ```ts
23
+ * const { client } = await MonitoringClient.signIn({ email, password })
24
+ * const { key } = await client.account.keys.create({ name: 'ci' })
25
+ * ```
26
+ */
27
+ export class MonitoringClient {
28
+ /** Кто вы и ваши личные ключи */
29
+ account;
30
+ /** Выход и смена пароля (для клиента, вошедшего по паролю) */
31
+ auth;
32
+ /** Сети */
33
+ networks;
34
+ /** Нативные монеты и токены */
35
+ assets;
36
+ /** Ваш клиент: URL вебхука, секрет, ключи, участники, тестовый вебхук */
37
+ clients;
38
+ /** Адреса на мониторинге и подписка */
39
+ addresses;
40
+ /** История вебхуков */
41
+ deliveries;
42
+ /** Транзакция по хешу: статус, подтверждения, финальность */
43
+ transactions;
44
+ #http;
45
+ /**
46
+ * @param options - ключ (`apiKey`) или токен сессии (`sessionToken`), адрес API, таймаут, повторы
47
+ * @throws {@link MonitoringError} переданы и ключ, и токен; нет `fetch`
48
+ */
49
+ constructor(options = {}) {
50
+ this.#http = new HttpClient(options, DEFAULT_BASE_URL);
51
+ this.account = new AccountResource(this.#http);
52
+ this.auth = new AuthResource(this.#http);
53
+ this.networks = new NetworksResource(this.#http);
54
+ this.assets = new AssetsResource(this.#http);
55
+ this.clients = new ClientsResource(this.#http);
56
+ this.addresses = new AddressesResource(this.#http);
57
+ this.deliveries = new DeliveriesResource(this.#http);
58
+ this.transactions = new TransactionsResource(this.#http);
59
+ }
60
+ /** Адрес API, с которым работает клиент */
61
+ get baseUrl() {
62
+ return this.#http.baseUrl;
63
+ }
64
+ /**
65
+ * Вход по email и паролю: возвращает клиента с токеном сессии. Регистрации нет — пользователей заводит
66
+ * администратор сервиса. Не больше 3 попыток за 10 секунд с одного IP.
67
+ *
68
+ * @param options - настройки клиента, кроме учётных данных
69
+ * @throws {@link MonitoringApiError} 401 — неверный email или пароль
70
+ */
71
+ static async signIn(credentials, options = {}, requestOptions) {
72
+ const http = new HttpClient(options, DEFAULT_BASE_URL);
73
+ const r = await http.request({
74
+ method: 'POST',
75
+ path: '/api/auth/sign-in/email',
76
+ body: credentials,
77
+ idempotent: false,
78
+ auth: false,
79
+ // повтор при отказе 429 только сожжёт попытки входа
80
+ options: { maxRetries: 0, ...requestOptions },
81
+ });
82
+ return { token: r.token, user: r.user, client: new MonitoringClient({ ...options, sessionToken: r.token }) };
83
+ }
84
+ }
85
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA2C,MAAM,gBAAgB,CAAA;AAEpF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAqB,MAAM,wBAAwB,CAAA;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,gBAAgB;IAC3B,iCAAiC;IACxB,OAAO,CAAiB;IACjC,8DAA8D;IACrD,IAAI,CAAc;IAC3B,WAAW;IACF,QAAQ,CAAkB;IACnC,+BAA+B;IACtB,MAAM,CAAgB;IAC/B,yEAAyE;IAChE,OAAO,CAAiB;IACjC,uCAAuC;IAC9B,SAAS,CAAmB;IACrC,uBAAuB;IACd,UAAU,CAAoB;IACvC,6DAA6D;IACpD,YAAY,CAAsB;IAElC,KAAK,CAAY;IAE1B;;;OAGG;IACH,YAAY,OAAO,GAAkB,EAAE;QACrC,IAAI,CAAC,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAA;QACtD,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC9C,IAAI,CAAC,IAAI,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACxC,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChD,IAAI,CAAC,MAAM,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC5C,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC9C,IAAI,CAAC,SAAS,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAClD,IAAI,CAAC,UAAU,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACpD,IAAI,CAAC,YAAY,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1D,CAAC;IAED,2CAA2C;IAC3C,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAA;IAC3B,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CACjB,WAAgD,EAChD,OAAO,GAAmD,EAAE,EAC5D,cAA+B;QAE/B,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAA;QACtD,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAgC;YAC1D,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,yBAAyB;YAC/B,IAAI,EAAE,WAAW;YACjB,UAAU,EAAE,KAAK;YACjB,IAAI,EAAE,KAAK;YACX,oDAAoD;YACpD,OAAO,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,GAAG,cAAc,EAAE;SAC9C,CAAC,CAAA;QACF,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,gBAAgB,CAAC,EAAE,GAAG,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAA;IAC9G,CAAC;CACF"}
@@ -0,0 +1,64 @@
1
+ import type { ApiErrorBody } from '../generated/types.js';
2
+ /** Ошибка по элементу запроса: номер элемента в переданном массиве и причина */
3
+ export type ErrorDetail = NonNullable<ApiErrorBody['error']['details']>[number];
4
+ /**
5
+ * Базовый класс всех ошибок SDK. Ловите его, чтобы перехватить любую ошибку SDK.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * try {
10
+ * await monitoring.addresses.add(clientId, items)
11
+ * } catch (e) {
12
+ * if (e instanceof MonitoringApiError && e.status === 400) console.log(e.details)
13
+ * else throw e
14
+ * }
15
+ * ```
16
+ */
17
+ export declare class MonitoringError extends Error {
18
+ constructor(message: string, options?: {
19
+ cause?: unknown;
20
+ });
21
+ }
22
+ /** API ответил ошибкой: HTTP 4xx или 5xx */
23
+ export declare class MonitoringApiError extends MonitoringError {
24
+ /** HTTP-статус ответа */
25
+ readonly status: number;
26
+ /**
27
+ * Машинный код ошибки: `invalid_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`,
28
+ * `rate_limited`, `upstream_error`, `upstream_rate_limited`, `unavailable`…
29
+ */
30
+ readonly code: string;
31
+ /** Ошибки по элементам запроса (например, какой адрес из переданных не подошёл); пустой массив, если их нет */
32
+ readonly details: ErrorDetail[];
33
+ /** Идентификатор запроса (`cf-ray`) — укажите его, если обращаетесь в поддержку */
34
+ readonly requestId: string | undefined;
35
+ /** Тело ответа как есть */
36
+ readonly body: unknown;
37
+ constructor(init: {
38
+ status: number;
39
+ code: string;
40
+ message: string;
41
+ details?: ErrorDetail[];
42
+ requestId?: string;
43
+ body?: unknown;
44
+ });
45
+ /** Временная ошибка — лимит частоты или недоступный провайдер: запрос можно повторить позже */
46
+ get retryable(): boolean;
47
+ }
48
+ /** Ответа нет: сбой сети или соединения */
49
+ export declare class MonitoringConnectionError extends MonitoringError {
50
+ constructor(message: string, options?: {
51
+ cause?: unknown;
52
+ });
53
+ }
54
+ /** Запрос не уложился в таймаут (`timeoutMs`) */
55
+ export declare class MonitoringTimeoutError extends MonitoringConnectionError {
56
+ constructor(timeoutMs: number);
57
+ }
58
+ /** Подпись вебхука не прошла проверку: тело подделано, изменено по дороге или проверяется не тем секретом */
59
+ export declare class WebhookSignatureError extends MonitoringError {
60
+ constructor(message?: string);
61
+ }
62
+ /** Тело ошибки в любом из форматов API: `/v1`, старые пути (`{ok: false}`), вход (`{code, message}`) */
63
+ export declare function apiErrorFrom(status: number, body: unknown, requestId: string | undefined): MonitoringApiError;
64
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEzD,gFAAgF;AAChF,MAAM,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/E;;;;;;;;;;;;GAYG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAGzD;CACF;AAED,4CAA4C;AAC5C,qBAAa,kBAAmB,SAAQ,eAAe;IACrD,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,+GAA+G;IAC/G,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,CAAA;IAC/B,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,2BAA2B;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IAEtB,YAAY,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,EAQ/H;IAED,+FAA+F;IAC/F,IAAI,SAAS,IAAI,OAAO,CAEvB;CACF;AAED,2CAA2C;AAC3C,qBAAa,yBAA0B,SAAQ,eAAe;IAC5D,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAGzD;CACF;AAED,iDAAiD;AACjD,qBAAa,sBAAuB,SAAQ,yBAAyB;IACnE,YAAY,SAAS,EAAE,MAAM,EAG5B;CACF;AAED,6GAA6G;AAC7G,qBAAa,qBAAsB,SAAQ,eAAe;IACxD,YAAY,OAAO,SAA+B,EAGjD;CACF;AAED,wGAAwG;AACxG,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,CAW7G"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Базовый класс всех ошибок SDK. Ловите его, чтобы перехватить любую ошибку SDK.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * try {
7
+ * await monitoring.addresses.add(clientId, items)
8
+ * } catch (e) {
9
+ * if (e instanceof MonitoringApiError && e.status === 400) console.log(e.details)
10
+ * else throw e
11
+ * }
12
+ * ```
13
+ */
14
+ export class MonitoringError extends Error {
15
+ constructor(message, options) {
16
+ super(message, options);
17
+ this.name = 'MonitoringError';
18
+ }
19
+ }
20
+ /** API ответил ошибкой: HTTP 4xx или 5xx */
21
+ export class MonitoringApiError extends MonitoringError {
22
+ /** HTTP-статус ответа */
23
+ status;
24
+ /**
25
+ * Машинный код ошибки: `invalid_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`,
26
+ * `rate_limited`, `upstream_error`, `upstream_rate_limited`, `unavailable`…
27
+ */
28
+ code;
29
+ /** Ошибки по элементам запроса (например, какой адрес из переданных не подошёл); пустой массив, если их нет */
30
+ details;
31
+ /** Идентификатор запроса (`cf-ray`) — укажите его, если обращаетесь в поддержку */
32
+ requestId;
33
+ /** Тело ответа как есть */
34
+ body;
35
+ constructor(init) {
36
+ super(`${init.message} (HTTP ${init.status}, ${init.code})`);
37
+ this.name = 'MonitoringApiError';
38
+ this.status = init.status;
39
+ this.code = init.code;
40
+ this.details = init.details ?? [];
41
+ this.requestId = init.requestId;
42
+ this.body = init.body;
43
+ }
44
+ /** Временная ошибка — лимит частоты или недоступный провайдер: запрос можно повторить позже */
45
+ get retryable() {
46
+ return this.status === 429 || this.status === 503;
47
+ }
48
+ }
49
+ /** Ответа нет: сбой сети или соединения */
50
+ export class MonitoringConnectionError extends MonitoringError {
51
+ constructor(message, options) {
52
+ super(message, options);
53
+ this.name = 'MonitoringConnectionError';
54
+ }
55
+ }
56
+ /** Запрос не уложился в таймаут (`timeoutMs`) */
57
+ export class MonitoringTimeoutError extends MonitoringConnectionError {
58
+ constructor(timeoutMs) {
59
+ super(`request timed out after ${timeoutMs} ms`);
60
+ this.name = 'MonitoringTimeoutError';
61
+ }
62
+ }
63
+ /** Подпись вебхука не прошла проверку: тело подделано, изменено по дороге или проверяется не тем секретом */
64
+ export class WebhookSignatureError extends MonitoringError {
65
+ constructor(message = 'webhook signature mismatch') {
66
+ super(message);
67
+ this.name = 'WebhookSignatureError';
68
+ }
69
+ }
70
+ /** Тело ошибки в любом из форматов API: `/v1`, старые пути (`{ok: false}`), вход (`{code, message}`) */
71
+ export function apiErrorFrom(status, body, requestId) {
72
+ const b = (body ?? {});
73
+ const v1 = typeof b.error === 'object' && b.error !== null ? b.error : undefined;
74
+ const message = (typeof v1?.message === 'string' && v1.message) ||
75
+ (typeof b.error === 'string' && b.error) ||
76
+ (typeof b.message === 'string' && b.message) ||
77
+ `HTTP ${status}`;
78
+ const code = (typeof v1?.code === 'string' && v1.code) || (typeof b.code === 'string' && b.code.toLowerCase()) || defaultCode(status);
79
+ const details = (Array.isArray(v1?.details) ? v1.details : Array.isArray(b.details) ? b.details : []);
80
+ return new MonitoringApiError({ status, code, message, details, requestId, body });
81
+ }
82
+ function defaultCode(status) {
83
+ const codes = { 400: 'invalid_request', 401: 'unauthorized', 403: 'forbidden', 404: 'not_found', 409: 'conflict', 429: 'rate_limited' };
84
+ return codes[status] ?? (status >= 500 ? 'server_error' : 'http_error');
85
+ }
86
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/core/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /** Настройки одного запроса — последний необязательный аргумент любого метода */
2
+ export interface RequestOptions {
3
+ /** Отмена запроса; повторы тоже прекращаются */
4
+ signal?: AbortSignal;
5
+ /** Таймаут этого запроса, мс — вместо {@link ClientOptions.timeoutMs} */
6
+ timeoutMs?: number;
7
+ /** Сколько раз повторить этот запрос — вместо {@link ClientOptions.maxRetries} */
8
+ maxRetries?: number;
9
+ }
10
+ /** Настройки клиента */
11
+ export interface ClientOptions {
12
+ /**
13
+ * API-ключ: ключ клиента `ce_…` (адреса, история и транзакции своего клиента) или личный ключ `ce_user_…`
14
+ * (всё, что вы можете в панели, с вашими правами). Уходит в заголовке `x-api-key`.
15
+ */
16
+ apiKey?: string;
17
+ /** Токен сессии из {@link MonitoringClient.signIn} — вместо `apiKey`. Уходит в `Authorization: Bearer` */
18
+ sessionToken?: string;
19
+ /** Адрес API. По умолчанию `https://monitoring.v3.finance` */
20
+ baseUrl?: string;
21
+ /** Таймаут запроса, мс. По умолчанию 30 000 */
22
+ timeoutMs?: number;
23
+ /**
24
+ * Сколько раз повторять запрос после временной ошибки. По умолчанию 2.
25
+ *
26
+ * Повторяются ответы 429 и 503 (запрос не был выполнен), а сбои сети и таймауты — только у запросов,
27
+ * которые безопасно выполнить дважды (чтение, снятие и добавление адресов, отзыв ключа). Пауза — из
28
+ * `Retry-After`, иначе экспоненциальная с разбросом.
29
+ */
30
+ maxRetries?: number;
31
+ /** Своя реализация `fetch` — для тестов, прокси, логирования. По умолчанию глобальный `fetch` */
32
+ fetch?: typeof fetch;
33
+ /** Дополнительные заголовки каждого запроса */
34
+ headers?: Record<string, string>;
35
+ }
36
+ type Query = Record<string, string | number | boolean | null | undefined>;
37
+ /** Описание одного запроса к API */
38
+ export interface Call {
39
+ method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
40
+ path: string;
41
+ query?: Query;
42
+ body?: unknown;
43
+ /** Можно ли повторить после сбоя сети: повтор не изменит результат */
44
+ idempotent: boolean;
45
+ /** Статусы, которые возвращаются как данные, а не ошибка (тестовый вебхук: 502 — «не доставлен») */
46
+ acceptStatuses?: number[];
47
+ /** false — запрос без учётных данных (вход) */
48
+ auth?: boolean;
49
+ options?: RequestOptions | undefined;
50
+ }
51
+ /** Транспорт SDK: адрес, авторизация, таймауты, повторы, разбор ошибок. Ресурсы ходят в API только через него */
52
+ export declare class HttpClient {
53
+ #private;
54
+ readonly baseUrl: string;
55
+ constructor(options: ClientOptions, defaultBaseUrl: string);
56
+ /** Выполняет запрос и возвращает разобранный JSON ответа */
57
+ request<T>(call: Call): Promise<T>;
58
+ }
59
+ /** Сегмент пути: id клиента, хеш и т. п. */
60
+ export declare const seg: (value: string | number) => string;
61
+ export {};
62
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/core/http.ts"],"names":[],"mappings":"AAGA,iFAAiF;AACjF,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAwB;AACxB,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0GAA0G;IAC1G,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iGAAiG;IACjG,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC;AAED,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;AAEzE,oCAAoC;AACpC,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,sEAAsE;IACtE,UAAU,EAAE,OAAO,CAAA;IACnB,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,CAAA;CACrC;AAKD,iHAAiH;AACjH,qBAAa,UAAU;;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IAQxB,YAAY,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,EAWzD;IAED,4DAA4D;IACtD,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CA4BvC;CAwCF;AAuCD,4CAA4C;AAC5C,eAAO,MAAM,GAAG,UAAW,MAAM,GAAG,MAAM,WAAsC,CAAA"}