@v3finance/monitoring-sdk 0.1.0 → 0.2.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/CHANGELOG.md +21 -11
- package/README.md +223 -148
- package/dist/cjs/client.d.ts +23 -42
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +44 -53
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/core/errors.d.ts +18 -18
- package/dist/cjs/core/errors.d.ts.map +1 -1
- package/dist/cjs/core/errors.js +17 -17
- package/dist/cjs/core/errors.js.map +1 -1
- package/dist/cjs/core/http.d.ts +22 -26
- package/dist/cjs/core/http.d.ts.map +1 -1
- package/dist/cjs/core/http.js +28 -36
- package/dist/cjs/core/http.js.map +1 -1
- package/dist/cjs/core/pagination.d.ts +6 -7
- package/dist/cjs/core/pagination.d.ts.map +1 -1
- package/dist/cjs/core/pagination.js +1 -1
- package/dist/cjs/core/pagination.js.map +1 -1
- package/dist/cjs/core/scope.d.ts +8 -0
- package/dist/cjs/core/scope.d.ts.map +1 -0
- package/dist/cjs/core/scope.js +3 -0
- package/dist/cjs/core/scope.js.map +1 -0
- package/dist/cjs/generated/types.d.ts +129 -117
- package/dist/cjs/generated/types.d.ts.map +1 -1
- package/dist/cjs/generated/types.js +1 -1
- package/dist/cjs/generated/types.js.map +1 -1
- package/dist/cjs/index.d.ts +6 -6
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +13 -16
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/resources/account.d.ts +12 -51
- package/dist/cjs/resources/account.d.ts.map +1 -1
- package/dist/cjs/resources/account.js +17 -61
- package/dist/cjs/resources/account.js.map +1 -1
- package/dist/cjs/resources/addresses.d.ts +49 -65
- package/dist/cjs/resources/addresses.d.ts.map +1 -1
- package/dist/cjs/resources/addresses.js +60 -69
- package/dist/cjs/resources/addresses.js.map +1 -1
- package/dist/cjs/resources/catalog.d.ts +17 -10
- package/dist/cjs/resources/catalog.d.ts.map +1 -1
- package/dist/cjs/resources/catalog.js +23 -17
- package/dist/cjs/resources/catalog.js.map +1 -1
- package/dist/cjs/resources/deliveries.d.ts +34 -23
- package/dist/cjs/resources/deliveries.d.ts.map +1 -1
- package/dist/cjs/resources/deliveries.js +27 -17
- package/dist/cjs/resources/deliveries.js.map +1 -1
- package/dist/cjs/resources/transactions.d.ts +14 -14
- package/dist/cjs/resources/transactions.d.ts.map +1 -1
- package/dist/cjs/resources/transactions.js +15 -16
- package/dist/cjs/resources/transactions.js.map +1 -1
- package/dist/cjs/resources/webhooks.d.ts +22 -0
- package/dist/cjs/resources/webhooks.d.ts.map +1 -0
- package/dist/cjs/resources/webhooks.js +35 -0
- package/dist/cjs/resources/webhooks.js.map +1 -0
- package/dist/cjs/units.d.ts +11 -11
- package/dist/cjs/units.js +14 -14
- package/dist/cjs/units.js.map +1 -1
- package/dist/cjs/version.d.ts +3 -3
- package/dist/cjs/version.d.ts.map +1 -1
- package/dist/cjs/version.js +3 -3
- package/dist/cjs/version.js.map +1 -1
- package/dist/cjs/webhooks.d.ts +33 -28
- package/dist/cjs/webhooks.d.ts.map +1 -1
- package/dist/cjs/webhooks.js +33 -28
- package/dist/cjs/webhooks.js.map +1 -1
- package/dist/esm/client.d.ts +23 -42
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +46 -55
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/core/errors.d.ts +18 -18
- package/dist/esm/core/errors.d.ts.map +1 -1
- package/dist/esm/core/errors.js +17 -17
- package/dist/esm/core/errors.js.map +1 -1
- package/dist/esm/core/http.d.ts +22 -26
- package/dist/esm/core/http.d.ts.map +1 -1
- package/dist/esm/core/http.js +28 -36
- package/dist/esm/core/http.js.map +1 -1
- package/dist/esm/core/pagination.d.ts +6 -7
- package/dist/esm/core/pagination.d.ts.map +1 -1
- package/dist/esm/core/pagination.js +1 -1
- package/dist/esm/core/pagination.js.map +1 -1
- package/dist/esm/core/scope.d.ts +8 -0
- package/dist/esm/core/scope.d.ts.map +1 -0
- package/dist/esm/core/scope.js +2 -0
- package/dist/esm/core/scope.js.map +1 -0
- package/dist/esm/generated/types.d.ts +129 -117
- package/dist/esm/generated/types.d.ts.map +1 -1
- package/dist/esm/generated/types.js +1 -1
- package/dist/esm/generated/types.js.map +1 -1
- package/dist/esm/index.d.ts +6 -6
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +6 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/resources/account.d.ts +12 -51
- package/dist/esm/resources/account.d.ts.map +1 -1
- package/dist/esm/resources/account.js +15 -57
- package/dist/esm/resources/account.js.map +1 -1
- package/dist/esm/resources/addresses.d.ts +49 -65
- package/dist/esm/resources/addresses.d.ts.map +1 -1
- package/dist/esm/resources/addresses.js +60 -69
- package/dist/esm/resources/addresses.js.map +1 -1
- package/dist/esm/resources/catalog.d.ts +17 -10
- package/dist/esm/resources/catalog.d.ts.map +1 -1
- package/dist/esm/resources/catalog.js +23 -17
- package/dist/esm/resources/catalog.js.map +1 -1
- package/dist/esm/resources/deliveries.d.ts +34 -23
- package/dist/esm/resources/deliveries.d.ts.map +1 -1
- package/dist/esm/resources/deliveries.js +27 -17
- package/dist/esm/resources/deliveries.js.map +1 -1
- package/dist/esm/resources/transactions.d.ts +14 -14
- package/dist/esm/resources/transactions.d.ts.map +1 -1
- package/dist/esm/resources/transactions.js +15 -16
- package/dist/esm/resources/transactions.js.map +1 -1
- package/dist/esm/resources/webhooks.d.ts +22 -0
- package/dist/esm/resources/webhooks.d.ts.map +1 -0
- package/dist/esm/resources/webhooks.js +31 -0
- package/dist/esm/resources/webhooks.js.map +1 -0
- package/dist/esm/units.d.ts +11 -11
- package/dist/esm/units.js +14 -14
- package/dist/esm/units.js.map +1 -1
- package/dist/esm/version.d.ts +3 -3
- package/dist/esm/version.d.ts.map +1 -1
- package/dist/esm/version.js +3 -3
- package/dist/esm/version.js.map +1 -1
- package/dist/esm/webhooks.d.ts +33 -28
- package/dist/esm/webhooks.d.ts.map +1 -1
- package/dist/esm/webhooks.js +33 -28
- package/dist/esm/webhooks.js.map +1 -1
- package/package.json +8 -5
- package/src/client.ts +50 -61
- package/src/core/errors.ts +18 -18
- package/src/core/http.ts +45 -55
- package/src/core/pagination.ts +7 -8
- package/src/core/scope.ts +8 -0
- package/src/generated/types.ts +139 -125
- package/src/index.ts +7 -24
- package/src/resources/account.ts +18 -72
- package/src/resources/addresses.ts +84 -109
- package/src/resources/catalog.ts +28 -19
- package/src/resources/deliveries.ts +43 -30
- package/src/resources/transactions.ts +18 -17
- package/src/resources/webhooks.ts +36 -0
- package/src/units.ts +14 -14
- package/src/version.ts +3 -3
- package/src/webhooks.ts +37 -32
- package/dist/cjs/resources/clients.d.ts +0 -84
- package/dist/cjs/resources/clients.d.ts.map +0 -1
- package/dist/cjs/resources/clients.js +0 -102
- package/dist/cjs/resources/clients.js.map +0 -1
- package/dist/esm/resources/clients.d.ts +0 -84
- package/dist/esm/resources/clients.d.ts.map +0 -1
- package/dist/esm/resources/clients.js +0 -97
- package/dist/esm/resources/clients.js.map +0 -1
- package/src/resources/clients.ts +0 -135
package/CHANGELOG.md
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
All notable changes to this package. The format
|
|
4
|
-
[
|
|
3
|
+
All notable changes to this package are documented in this file. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
|
|
5
5
|
|
|
6
|
-
## 0.
|
|
6
|
+
## 0.2.0 — 2026-10-28
|
|
7
|
+
|
|
8
|
+
### Breaking changes
|
|
9
|
+
|
|
10
|
+
- `MonitoringClient` authenticates with an API key only. Your client ID is resolved from the key, so methods no
|
|
11
|
+
longer take it as a parameter.
|
|
12
|
+
- Removed account management APIs: `MonitoringClient.signIn`, `auth`, `account.keys` and `clients`.
|
|
13
|
+
- `clients.sendTestWebhook()` is now `webhooks.sendTest()`.
|
|
14
|
+
- `AddressDefaults` is renamed to `SubscriptionDefaults`, and `AddressSubscriptionUpdate` to `AddressUpdate`.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
7
17
|
|
|
8
|
-
|
|
18
|
+
- `account.get()` and `account.id()`.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Documentation and type descriptions are now in English.
|
|
23
|
+
|
|
24
|
+
## 0.1.0 — 2026-10-28
|
|
9
25
|
|
|
10
|
-
-
|
|
11
|
-
secret, client keys, members, test webhook), addresses and subscriptions with automatic batching, webhook history,
|
|
12
|
-
transaction lookup with confirmations and finality.
|
|
13
|
-
- Webhooks: `parseWebhook`, `verifyWebhookSignature`, `signWebhookBody`, `isTestWebhook`, `webhookIdempotencyKey`.
|
|
14
|
-
- Amounts: `formatUnits`, `parseUnits`.
|
|
15
|
-
- Timeouts, cancellation, retries on 429 and 503, typed errors with per-item details.
|
|
16
|
-
- Types generated from the OpenAPI spec of the API.
|
|
26
|
+
- Initial release.
|
package/README.md
CHANGED
|
@@ -1,145 +1,249 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
# V3 Finance Monitoring SDK
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@v3finance/monitoring-sdk)
|
|
4
|
+
[](https://www.npmjs.com/package/@v3finance/monitoring-sdk)
|
|
5
|
+
[](https://www.npmjs.com/package/@v3finance/monitoring-sdk)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
The official TypeScript SDK for the [V3 Finance Monitoring API](https://monitoring.v3.finance/docs).
|
|
9
|
+
Monitor addresses on TRON and EVM networks and receive a signed webhook for every incoming and outgoing transfer.
|
|
10
|
+
|
|
11
|
+
- **Address monitoring** with per-address subscriptions: choose the assets and the direction you are notified about.
|
|
12
|
+
- **Webhooks** with signature verification and fully typed payloads.
|
|
13
|
+
- **Transaction lookup** with confirmations and finality, for any transaction on a supported network.
|
|
14
|
+
- **Delivery history** of every webhook sent to you.
|
|
15
|
+
- **Production-ready**: automatic retries, timeouts, cancellation, pagination and batching.
|
|
16
|
+
- **Fully typed**, zero dependencies, ESM and CommonJS. Runs on Node.js, Bun, Deno and Cloudflare Workers.
|
|
17
|
+
|
|
18
|
+
## Contents
|
|
19
|
+
|
|
20
|
+
- [Installation](#installation)
|
|
21
|
+
- [Quick start](#quick-start)
|
|
22
|
+
- [Configuration](#configuration)
|
|
23
|
+
- [Addresses](#addresses)
|
|
24
|
+
- [Receiving webhooks](#receiving-webhooks)
|
|
25
|
+
- [Transactions and finality](#transactions-and-finality)
|
|
26
|
+
- [Delivery history](#delivery-history)
|
|
27
|
+
- [Networks and assets](#networks-and-assets)
|
|
28
|
+
- [Amounts](#amounts)
|
|
29
|
+
- [Error handling](#error-handling)
|
|
30
|
+
- [Retries, timeouts and cancellation](#retries-timeouts-and-cancellation)
|
|
31
|
+
- [TypeScript](#typescript)
|
|
32
|
+
- [Requirements](#requirements)
|
|
33
|
+
- [Security](#security)
|
|
34
|
+
- [Versioning](#versioning)
|
|
35
|
+
- [Support](#support)
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
15
38
|
|
|
16
39
|
```bash
|
|
17
40
|
npm install @v3finance/monitoring-sdk
|
|
18
41
|
```
|
|
19
42
|
|
|
20
|
-
|
|
43
|
+
```bash
|
|
44
|
+
pnpm add @v3finance/monitoring-sdk
|
|
45
|
+
yarn add @v3finance/monitoring-sdk
|
|
46
|
+
bun add @v3finance/monitoring-sdk
|
|
47
|
+
```
|
|
21
48
|
|
|
22
49
|
## Quick start
|
|
23
50
|
|
|
24
51
|
```ts
|
|
25
52
|
import { MonitoringClient } from '@v3finance/monitoring-sdk'
|
|
26
53
|
|
|
27
|
-
const monitoring = new MonitoringClient({ apiKey: process.env.MONITORING_API_KEY })
|
|
54
|
+
const monitoring = new MonitoringClient({ apiKey: process.env.MONITORING_API_KEY! })
|
|
55
|
+
|
|
56
|
+
// Notify about incoming USDT on a deposit address
|
|
57
|
+
await monitoring.addresses.add(
|
|
58
|
+
[{ network: 'tron', address: 'TA8HgQbFjuMLWCaJeGyfrv8FErWSHz82vr', label: 'user-42' }],
|
|
59
|
+
{ assets: ['USDT'], direction: 'in' },
|
|
60
|
+
)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Every transfer on the address now triggers a signed webhook to your endpoint — see
|
|
64
|
+
[Receiving webhooks](#receiving-webhooks).
|
|
28
65
|
|
|
29
|
-
|
|
30
|
-
const { actor } = await monitoring.account.me()
|
|
31
|
-
const clientId = actor.clientId!
|
|
66
|
+
## Configuration
|
|
32
67
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
68
|
+
```ts
|
|
69
|
+
const monitoring = new MonitoringClient({
|
|
70
|
+
apiKey: process.env.MONITORING_API_KEY!,
|
|
71
|
+
timeoutMs: 10_000,
|
|
72
|
+
maxRetries: 3,
|
|
37
73
|
})
|
|
38
74
|
```
|
|
39
75
|
|
|
40
|
-
|
|
76
|
+
| Option | Type | Default | Description |
|
|
77
|
+
|---|---|---|---|
|
|
78
|
+
| `apiKey` | `string` | — | Your API key. **Required.** |
|
|
79
|
+
| `clientId` | `string` | resolved from the API key | Your client ID. |
|
|
80
|
+
| `baseUrl` | `string` | `https://monitoring.v3.finance` | API base URL. |
|
|
81
|
+
| `timeoutMs` | `number` | `30000` | Request timeout in milliseconds. |
|
|
82
|
+
| `maxRetries` | `number` | `2` | Retries for rate limits and transient errors. |
|
|
83
|
+
| `fetch` | `typeof fetch` | global `fetch` | Custom `fetch` implementation. |
|
|
84
|
+
| `headers` | `Record<string, string>` | — | Additional headers sent with every request. |
|
|
85
|
+
|
|
86
|
+
## Addresses
|
|
41
87
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
| Personal key `ce_user_…` | panel → Account, or `account.keys.create()` after signing in | everything you can do in the panel, with your role |
|
|
46
|
-
| Session | `MonitoringClient.signIn({ email, password })` | same as a personal key |
|
|
88
|
+
An address is monitored on a single network; to watch an EVM address on several networks, add it once per network.
|
|
89
|
+
Each address has a **subscription** — which assets (`assets`) and which direction (`direction`: `in`, `out` or
|
|
90
|
+
`both`) you are notified about. By default it covers all assets of the network in both directions.
|
|
47
91
|
|
|
48
92
|
```ts
|
|
49
|
-
|
|
50
|
-
|
|
93
|
+
// Add — lists larger than 1,000 addresses are sent in batches automatically
|
|
94
|
+
await monitoring.addresses.add(
|
|
95
|
+
[
|
|
96
|
+
{ network: 'tron', address: 'TA8HgQbFjuMLWCaJeGyfrv8FErWSHz82vr', label: 'user-42' },
|
|
97
|
+
{ network: 'ethereum', address: '0x533bcdd534fc3f9651471d7b4469a0d01ca45a2a', assets: ['USDT', 'USDC'] },
|
|
98
|
+
],
|
|
99
|
+
{ direction: 'in' },
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
// Change the subscription
|
|
103
|
+
await monitoring.addresses.update([{ network: 'tron', address: 'TA8HgQbFjuMLWCaJeGyfrv8FErWSHz82vr' }], { direction: 'both' })
|
|
104
|
+
|
|
105
|
+
// Iterate over all monitored addresses
|
|
106
|
+
for await (const address of monitoring.addresses.iterate({ network: 'tron' })) {
|
|
107
|
+
console.log(address.address, address.assets ?? 'all assets', address.direction)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Stop monitoring
|
|
111
|
+
await monitoring.addresses.remove([{ network: 'tron', address: 'TA8HgQbFjuMLWCaJeGyfrv8FErWSHz82vr' }])
|
|
51
112
|
```
|
|
52
113
|
|
|
114
|
+
Requests are validated as a whole: if any address is invalid for its network, nothing is changed and
|
|
115
|
+
`error.details` lists the problems by index.
|
|
116
|
+
|
|
53
117
|
## Receiving webhooks
|
|
54
118
|
|
|
55
|
-
Every webhook is a `POST` with JSON
|
|
56
|
-
|
|
57
|
-
|
|
119
|
+
Every webhook is a `POST` request with a JSON body and an `x-signature` header — an HMAC-SHA256 of the raw body keyed
|
|
120
|
+
with your webhook secret. `parseWebhook` verifies the signature and returns a typed payload.
|
|
121
|
+
|
|
122
|
+
**Express**
|
|
58
123
|
|
|
59
124
|
```ts
|
|
60
125
|
import express from 'express'
|
|
61
126
|
import { isTestWebhook, parseWebhook, webhookIdempotencyKey, WebhookSignatureError } from '@v3finance/monitoring-sdk'
|
|
62
127
|
|
|
128
|
+
const app = express()
|
|
129
|
+
|
|
63
130
|
app.post('/webhooks/monitoring', express.raw({ type: 'application/json' }), async (req, res) => {
|
|
64
131
|
try {
|
|
65
132
|
const event = await parseWebhook(req.body, req.headers, process.env.MONITORING_WEBHOOK_SECRET!)
|
|
66
|
-
if (!isTestWebhook(event))
|
|
133
|
+
if (!isTestWebhook(event)) {
|
|
134
|
+
await creditOnce(webhookIdempotencyKey(event), event.tx)
|
|
135
|
+
}
|
|
67
136
|
res.sendStatus(200)
|
|
68
|
-
} catch (
|
|
69
|
-
if (
|
|
70
|
-
throw
|
|
137
|
+
} catch (error) {
|
|
138
|
+
if (error instanceof WebhookSignatureError) return res.sendStatus(401)
|
|
139
|
+
throw error
|
|
71
140
|
}
|
|
72
141
|
})
|
|
73
142
|
```
|
|
74
143
|
|
|
75
|
-
|
|
144
|
+
**Next.js (App Router)** — and any runtime built on the Fetch API: Cloudflare Workers, Bun, Deno
|
|
76
145
|
|
|
77
146
|
```ts
|
|
78
|
-
|
|
147
|
+
export async function POST(request: Request) {
|
|
148
|
+
const event = await parseWebhook(await request.text(), request.headers, process.env.MONITORING_WEBHOOK_SECRET!)
|
|
149
|
+
// …
|
|
150
|
+
return new Response(null, { status: 200 })
|
|
151
|
+
}
|
|
79
152
|
```
|
|
80
153
|
|
|
81
|
-
|
|
154
|
+
**Hono**
|
|
82
155
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
156
|
+
```ts
|
|
157
|
+
app.post('/webhooks/monitoring', async (c) => {
|
|
158
|
+
const event = await parseWebhook(await c.req.text(), c.req.raw.headers, c.env.MONITORING_WEBHOOK_SECRET)
|
|
159
|
+
// …
|
|
160
|
+
return c.body(null, 200)
|
|
161
|
+
})
|
|
162
|
+
```
|
|
89
163
|
|
|
90
|
-
|
|
164
|
+
The payload:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"tx": {
|
|
169
|
+
"network": "TRON",
|
|
170
|
+
"asset": "USDT",
|
|
171
|
+
"contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
172
|
+
"type": "TOPUP",
|
|
173
|
+
"id": "1249cb7b7edd42072684b1db37ad495d4a5b7eefd1aff83e595e9bdb63a5fc45",
|
|
174
|
+
"block": 87445412,
|
|
175
|
+
"timestamp": 1793009472000,
|
|
176
|
+
"from": "TW9goADYcUxskhQQRifvwoRBUMHnmTh9MA",
|
|
177
|
+
"to": "TA8HgQbFjuMLWCaJeGyfrv8FErWSHz82vr",
|
|
178
|
+
"value": "100000000"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Best practices:
|
|
91
184
|
|
|
92
|
-
|
|
185
|
+
- **Verify against the raw body.** Parsing and re-serializing the JSON changes the bytes and breaks the signature.
|
|
186
|
+
- **Respond quickly.** Return a 2xx status within 15 seconds; otherwise the webhook is retried after 10 seconds,
|
|
187
|
+
1 minute and 5 minutes.
|
|
188
|
+
- **Process idempotently.** A webhook may be delivered more than once — deduplicate with `webhookIdempotencyKey(event)`.
|
|
189
|
+
- **Check the direction.** `type` is `TOPUP` for both directions; compare `from` and `to` with your addresses.
|
|
190
|
+
- **Wait for finality on large amounts.** Webhooks are sent as soon as a transfer is included in a block — see
|
|
191
|
+
[Transactions and finality](#transactions-and-finality).
|
|
192
|
+
- **Ignore test webhooks** — `isTestWebhook(event)` is `true` for them.
|
|
193
|
+
|
|
194
|
+
Send a test webhook to check your endpoint:
|
|
93
195
|
|
|
94
196
|
```ts
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
tx.confirmations // from the current head of the network
|
|
98
|
-
tx.final // cannot be reverted: TRON — solidified (~1 min), Ethereum — finalized (~13 min)
|
|
99
|
-
tx.transfers // every transfer inside: native, tokens, TRON internal TRX transfers
|
|
100
|
-
tx.watched // your watched addresses in this transaction
|
|
101
|
-
tx.webhooks // webhooks we sent you for it
|
|
197
|
+
const { delivery, signature, body } = await monitoring.webhooks.sendTest({ asset: 'USDT' })
|
|
198
|
+
console.log(delivery.ok ? 'Delivered' : `Endpoint responded with ${delivery.status ?? delivery.error}`)
|
|
102
199
|
```
|
|
103
200
|
|
|
104
|
-
##
|
|
201
|
+
## Transactions and finality
|
|
202
|
+
|
|
203
|
+
Look up any transaction on a supported network — not only the ones you were notified about.
|
|
105
204
|
|
|
106
205
|
```ts
|
|
107
|
-
await monitoring.
|
|
108
|
-
await monitoring.addresses.update(clientId, [{ network: 'tron', address: 'T…' }], { direction: 'both' })
|
|
109
|
-
await monitoring.addresses.remove(clientId, [{ network: 'tron', address: 'T…' }])
|
|
206
|
+
const tx = await monitoring.transactions.get('tron', event.tx.id)
|
|
110
207
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
208
|
+
tx.status // 'success' | 'failed' | 'pending'
|
|
209
|
+
tx.confirmations // blocks since inclusion
|
|
210
|
+
tx.final // the transaction can no longer be reverted
|
|
211
|
+
tx.fee // { asset: 'TRX', value: '6773500' }
|
|
212
|
+
tx.transfers // every transfer inside the transaction
|
|
213
|
+
tx.watched // your monitored addresses involved
|
|
214
|
+
tx.webhooks // webhooks sent to you for this transaction
|
|
114
215
|
```
|
|
115
216
|
|
|
116
|
-
A
|
|
117
|
-
|
|
118
|
-
one address on several networks with several items.
|
|
217
|
+
A transaction is final once its block is solidified on TRON (about 1 minute) or finalized on EVM networks (about
|
|
218
|
+
13 minutes on Ethereum). Credit large amounts once `final` is `true`.
|
|
119
219
|
|
|
120
|
-
##
|
|
220
|
+
## Delivery history
|
|
221
|
+
|
|
222
|
+
Every webhook sent to you is recorded with its status, attempts and your endpoint's response, and kept for 90 days.
|
|
121
223
|
|
|
122
224
|
```ts
|
|
123
|
-
for await (const
|
|
124
|
-
console.log(
|
|
225
|
+
for await (const delivery of monitoring.deliveries.iterate({ status: 'failed', since: new Date(Date.now() - 86_400_000) })) {
|
|
226
|
+
console.log(delivery.txId, delivery.attempts, delivery.lastHttpStatus ?? delivery.lastError)
|
|
125
227
|
}
|
|
126
|
-
|
|
228
|
+
|
|
229
|
+
const detail = await monitoring.deliveries.get(deliveryId) // includes the exact request body
|
|
127
230
|
```
|
|
128
231
|
|
|
129
|
-
|
|
232
|
+
Filter by `status` (`delivered`, `retrying`, `failed`), `network`, `asset`, `tx`, `address`, `since` and `until`.
|
|
130
233
|
|
|
131
|
-
|
|
234
|
+
## Networks and assets
|
|
132
235
|
|
|
133
236
|
```ts
|
|
134
|
-
await monitoring.
|
|
135
|
-
const
|
|
136
|
-
const { key } = await monitoring.clients.keys.create(clientId, { name: 'backend', expiresInDays: 365 })
|
|
137
|
-
const result = await monitoring.clients.sendTestWebhook(clientId, { asset: 'USDT' }) // result.delivery.ok
|
|
237
|
+
const networks = await monitoring.networks.list()
|
|
238
|
+
const assets = await monitoring.assets.list({ network: 'tron' })
|
|
138
239
|
```
|
|
139
240
|
|
|
241
|
+
You are notified about transfers of enabled assets of at least the asset's `minAmount`.
|
|
242
|
+
|
|
140
243
|
## Amounts
|
|
141
244
|
|
|
142
|
-
Amounts are strings in
|
|
245
|
+
Amounts are strings in the asset's smallest unit (sun, wei; USDT has 6 decimals). Convert them without losing
|
|
246
|
+
precision:
|
|
143
247
|
|
|
144
248
|
```ts
|
|
145
249
|
import { formatUnits, parseUnits } from '@v3finance/monitoring-sdk'
|
|
@@ -148,101 +252,72 @@ formatUnits('100000000', 6) // '100'
|
|
|
148
252
|
parseUnits('1.5', 6) // '1500000'
|
|
149
253
|
```
|
|
150
254
|
|
|
151
|
-
|
|
255
|
+
## Error handling
|
|
152
256
|
|
|
153
|
-
|
|
257
|
+
All errors extend `MonitoringError`.
|
|
258
|
+
|
|
259
|
+
| Error | When |
|
|
260
|
+
|---|---|
|
|
261
|
+
| `MonitoringApiError` | The API responded with an error. Has `status`, `code`, `details` and `requestId`. |
|
|
262
|
+
| `MonitoringConnectionError` | The request failed to reach the API. |
|
|
263
|
+
| `MonitoringTimeoutError` | The request exceeded `timeoutMs`. |
|
|
264
|
+
| `WebhookSignatureError` | A webhook signature does not match. |
|
|
154
265
|
|
|
155
266
|
```ts
|
|
156
|
-
import { MonitoringApiError
|
|
267
|
+
import { MonitoringApiError } from '@v3finance/monitoring-sdk'
|
|
157
268
|
|
|
158
269
|
try {
|
|
159
|
-
await monitoring.addresses.add(
|
|
160
|
-
} catch (
|
|
161
|
-
if (
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
e.requestId // send it to support
|
|
270
|
+
await monitoring.addresses.add(items)
|
|
271
|
+
} catch (error) {
|
|
272
|
+
if (error instanceof MonitoringApiError && error.status === 400) {
|
|
273
|
+
for (const { index, message } of error.details) console.error(`Item ${index}: ${message}`)
|
|
274
|
+
} else {
|
|
275
|
+
throw error
|
|
166
276
|
}
|
|
167
277
|
}
|
|
168
278
|
```
|
|
169
279
|
|
|
170
|
-
|
|
171
|
-
Network errors are retried only for requests that are safe to repeat.
|
|
172
|
-
- Every request has a timeout (`timeoutMs`, default 30 s) and accepts an `AbortSignal`:
|
|
173
|
-
`monitoring.addresses.list(clientId, {}, { signal })`.
|
|
174
|
-
- All errors extend `MonitoringError`.
|
|
175
|
-
|
|
176
|
-
## API reference
|
|
177
|
-
|
|
178
|
-
- Interactive reference: https://monitoring.v3.finance/docs
|
|
179
|
-
- OpenAPI 3.1: https://monitoring.v3.finance/openapi.json
|
|
180
|
-
- All request and response types are exported: `import type { Transaction, WebhookPayload } from '@v3finance/monitoring-sdk'`.
|
|
181
|
-
|
|
182
|
-
## Versioning
|
|
183
|
-
|
|
184
|
-
[SemVer](https://semver.org). While the version is `0.x`, minor releases may contain breaking changes; they are listed in
|
|
185
|
-
[CHANGELOG.md](./CHANGELOG.md).
|
|
186
|
-
|
|
187
|
-
---
|
|
280
|
+
## Retries, timeouts and cancellation
|
|
188
281
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
история доставок, транзакции с подтверждениями и финальностью. Подсказки в редакторе — по-русски.
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
npm install @v3finance/monitoring-sdk
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
**Только для сервера** — ключ в браузере увидит любой. Node.js 20+, Bun, Deno, Cloudflare Workers; ESM и CommonJS.
|
|
282
|
+
Rate-limited (`429`) and temporarily unavailable (`503`) requests are retried automatically with exponential backoff,
|
|
283
|
+
honoring `Retry-After`. Network errors are retried only for requests that are safe to repeat. Configure this with
|
|
284
|
+
`maxRetries` and `timeoutMs`, globally or per request:
|
|
199
285
|
|
|
200
286
|
```ts
|
|
201
|
-
|
|
287
|
+
const controller = new AbortController()
|
|
202
288
|
|
|
203
|
-
|
|
204
|
-
|
|
289
|
+
await monitoring.addresses.list({ network: 'tron' }, { timeoutMs: 5_000, maxRetries: 0, signal: controller.signal })
|
|
290
|
+
```
|
|
205
291
|
|
|
206
|
-
|
|
207
|
-
await monitoring.addresses.add(clientId, [{ network: 'tron', address: 'T…', label: 'user-42' }], { assets: ['USDT'], direction: 'in' })
|
|
292
|
+
## TypeScript
|
|
208
293
|
|
|
209
|
-
|
|
210
|
-
const event = await parseWebhook(rawBody, headers, process.env.MONITORING_WEBHOOK_SECRET!)
|
|
211
|
-
if (!isTestWebhook(event)) await creditOnce(webhookIdempotencyKey(event), event.tx)
|
|
294
|
+
The SDK is written in TypeScript and ships its own type declarations. All request and response types are exported:
|
|
212
295
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (tx.status === 'success' && tx.final) { /* зачислить */ }
|
|
296
|
+
```ts
|
|
297
|
+
import type { Address, Delivery, Transaction, WebhookPayload } from '@v3finance/monitoring-sdk'
|
|
216
298
|
```
|
|
217
299
|
|
|
218
|
-
|
|
300
|
+
## Requirements
|
|
301
|
+
|
|
302
|
+
- Node.js 20 or later, Bun, Deno or Cloudflare Workers.
|
|
303
|
+
- ESM (`import`) and CommonJS (`require`) are both supported.
|
|
219
304
|
|
|
220
|
-
|
|
221
|
-
- один вебхук может прийти повторно — обрабатывайте идемпотентно по `webhookIdempotencyKey(event)`;
|
|
222
|
-
- `type` всегда `TOPUP` — направление определяйте по `from` и `to`;
|
|
223
|
-
- вебхук уходит сразу, как перевод попал в блок, до финальности: крупные суммы зачисляйте после `final`;
|
|
224
|
-
- тестовые вебхуки (`isTestWebhook`, заголовок `x-webhook-test: 1`) не зачислять.
|
|
305
|
+
## Security
|
|
225
306
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
Суммы — строки в минимальных единицах: `formatUnits('100000000', 6) === '100'`.
|
|
307
|
+
- Use the SDK on your servers only. Never expose your API key or webhook secret to browsers or mobile apps.
|
|
308
|
+
- Keep credentials in environment variables or a secrets manager, not in source code.
|
|
309
|
+
- Always verify webhook signatures before processing a webhook.
|
|
230
310
|
|
|
231
|
-
|
|
311
|
+
## Versioning
|
|
232
312
|
|
|
233
|
-
|
|
313
|
+
This package follows [Semantic Versioning](https://semver.org). Changes are listed in [CHANGELOG.md](./CHANGELOG.md).
|
|
234
314
|
|
|
235
|
-
|
|
236
|
-
npm install
|
|
237
|
-
npm run spec:update # snapshot of https://monitoring.v3.finance/openapi.json → openapi/openapi.json
|
|
238
|
-
npm run generate # → src/generated/types.ts
|
|
239
|
-
npm run typecheck && npm test && npm run build
|
|
240
|
-
npm run build && MONITORING_API_KEY=ce_… node scripts/smoke.ts # against the real API, with a client key
|
|
241
|
-
```
|
|
315
|
+
## Support
|
|
242
316
|
|
|
243
|
-
|
|
244
|
-
|
|
317
|
+
- API reference: [monitoring.v3.finance/docs](https://monitoring.v3.finance/docs)
|
|
318
|
+
- OpenAPI specification: [monitoring.v3.finance/openapi.json](https://monitoring.v3.finance/openapi.json)
|
|
319
|
+
- For access and support, contact your V3 Finance account manager.
|
|
245
320
|
|
|
246
321
|
## License
|
|
247
322
|
|
|
248
|
-
[MIT](./LICENSE)
|
|
323
|
+
[MIT](./LICENSE) © V3 Finance
|
package/dist/cjs/client.d.ts
CHANGED
|
@@ -1,65 +1,46 @@
|
|
|
1
|
-
import { type ClientOptions
|
|
2
|
-
import { AccountResource
|
|
1
|
+
import { type ClientOptions } from './core/http.js';
|
|
2
|
+
import { AccountResource } from './resources/account.js';
|
|
3
3
|
import { AddressesResource } from './resources/addresses.js';
|
|
4
4
|
import { AssetsResource, NetworksResource } from './resources/catalog.js';
|
|
5
|
-
import { ClientsResource } from './resources/clients.js';
|
|
6
5
|
import { DeliveriesResource } from './resources/deliveries.js';
|
|
7
6
|
import { TransactionsResource } from './resources/transactions.js';
|
|
7
|
+
import { WebhooksResource } from './resources/webhooks.js';
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
* Только для сервера: ключ в браузере увидит любой.
|
|
9
|
+
* Client for the V3 Finance Monitoring API.
|
|
11
10
|
*
|
|
12
|
-
*
|
|
11
|
+
* Use it on the server only: an API key in a browser is visible to anyone.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
13
14
|
* ```ts
|
|
14
15
|
* import { MonitoringClient } from '@v3finance/monitoring-sdk'
|
|
15
16
|
*
|
|
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
|
-
* ```
|
|
17
|
+
* const monitoring = new MonitoringClient({ apiKey: process.env.MONITORING_API_KEY! })
|
|
19
18
|
*
|
|
20
|
-
*
|
|
21
|
-
* ```ts
|
|
22
|
-
* const { client } = await MonitoringClient.signIn({ email, password })
|
|
23
|
-
* const { key } = await client.account.keys.create({ name: 'ci' })
|
|
19
|
+
* await monitoring.addresses.add([{ network: 'tron', address: 'TA8Hg…' }], { assets: ['USDT'], direction: 'in' })
|
|
24
20
|
* ```
|
|
25
21
|
*/
|
|
26
22
|
export declare class MonitoringClient {
|
|
27
23
|
#private;
|
|
28
|
-
/**
|
|
24
|
+
/** Your client: the account your API key belongs to. */
|
|
29
25
|
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
|
-
/** Адреса на мониторинге и подписка */
|
|
26
|
+
/** Addresses you monitor and their subscriptions. */
|
|
39
27
|
readonly addresses: AddressesResource;
|
|
40
|
-
/**
|
|
28
|
+
/** Test your webhook endpoint. */
|
|
29
|
+
readonly webhooks: WebhooksResource;
|
|
30
|
+
/** History of webhooks sent to you. */
|
|
41
31
|
readonly deliveries: DeliveriesResource;
|
|
42
|
-
/**
|
|
32
|
+
/** Any transaction by hash, with confirmations and finality. */
|
|
43
33
|
readonly transactions: TransactionsResource;
|
|
34
|
+
/** Supported networks. */
|
|
35
|
+
readonly networks: NetworksResource;
|
|
36
|
+
/** Supported native coins and tokens. */
|
|
37
|
+
readonly assets: AssetsResource;
|
|
44
38
|
/**
|
|
45
|
-
* @param options -
|
|
46
|
-
* @throws {@link MonitoringError}
|
|
39
|
+
* @param options - API key and optional settings.
|
|
40
|
+
* @throws {@link MonitoringError} when `apiKey` is missing or `fetch` is not available.
|
|
47
41
|
*/
|
|
48
|
-
constructor(options
|
|
49
|
-
/**
|
|
42
|
+
constructor(options: ClientOptions);
|
|
43
|
+
/** API base URL this client sends requests to. */
|
|
50
44
|
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
45
|
}
|
|
65
46
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/cjs/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAGpE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAG1D;;;;;;;;;;;;;GAaG;AACH,qBAAa,gBAAgB;;IAC3B,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;IACjC,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAA;IACrC,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAA;IACnC,uCAAuC;IACvC,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAA;IACvC,gEAAgE;IAChE,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAA;IAC3C,0BAA0B;IAC1B,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAA;IACnC,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAK/B;;;OAGG;IACH,YAAY,OAAO,EAAE,aAAa,EAWjC;IAED,kDAAkD;IAClD,IAAI,OAAO,IAAI,MAAM,CAEpB;CAiBF"}
|