@v3finance/monitoring-sdk 0.0.0-stage → 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 +26 -0
- package/LICENSE +21 -0
- package/README.md +322 -2
- package/dist/cjs/client.d.ts +46 -0
- package/dist/cjs/client.d.ts.map +1 -0
- package/dist/cjs/client.js +80 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/core/errors.d.ts +64 -0
- package/dist/cjs/core/errors.d.ts.map +1 -0
- package/dist/cjs/core/errors.js +95 -0
- package/dist/cjs/core/errors.js.map +1 -0
- package/dist/cjs/core/http.d.ts +58 -0
- package/dist/cjs/core/http.d.ts.map +1 -0
- package/dist/cjs/core/http.js +143 -0
- package/dist/cjs/core/http.js.map +1 -0
- package/dist/cjs/core/pagination.d.ts +12 -0
- package/dist/cjs/core/pagination.d.ts.map +1 -0
- package/dist/cjs/core/pagination.js +15 -0
- package/dist/cjs/core/pagination.js.map +1 -0
- 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 +336 -0
- package/dist/cjs/generated/types.d.ts.map +1 -0
- package/dist/cjs/generated/types.js +5 -0
- package/dist/cjs/generated/types.js.map +1 -0
- package/dist/cjs/index.d.ts +23 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +47 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/resources/account.d.ts +22 -0
- package/dist/cjs/resources/account.d.ts.map +1 -0
- package/dist/cjs/resources/account.js +31 -0
- package/dist/cjs/resources/account.js.map +1 -0
- package/dist/cjs/resources/addresses.d.ts +93 -0
- package/dist/cjs/resources/addresses.d.ts.map +1 -0
- package/dist/cjs/resources/addresses.js +128 -0
- package/dist/cjs/resources/addresses.js.map +1 -0
- package/dist/cjs/resources/catalog.d.ts +37 -0
- package/dist/cjs/resources/catalog.d.ts.map +1 -0
- package/dist/cjs/resources/catalog.js +52 -0
- package/dist/cjs/resources/catalog.js.map +1 -0
- package/dist/cjs/resources/deliveries.d.ts +61 -0
- package/dist/cjs/resources/deliveries.d.ts.map +1 -0
- package/dist/cjs/resources/deliveries.js +53 -0
- package/dist/cjs/resources/deliveries.js.map +1 -0
- package/dist/cjs/resources/transactions.d.ts +28 -0
- package/dist/cjs/resources/transactions.d.ts.map +1 -0
- package/dist/cjs/resources/transactions.js +34 -0
- package/dist/cjs/resources/transactions.js.map +1 -0
- 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 +29 -0
- package/dist/cjs/units.d.ts.map +1 -0
- package/dist/cjs/units.js +62 -0
- package/dist/cjs/units.js.map +1 -0
- package/dist/cjs/version.d.ts +5 -0
- package/dist/cjs/version.d.ts.map +1 -0
- package/dist/cjs/version.js +8 -0
- package/dist/cjs/version.js.map +1 -0
- package/dist/cjs/webhooks.d.ts +82 -0
- package/dist/cjs/webhooks.d.ts.map +1 -0
- package/dist/cjs/webhooks.js +133 -0
- package/dist/cjs/webhooks.js.map +1 -0
- package/dist/esm/client.d.ts +46 -0
- package/dist/esm/client.d.ts.map +1 -0
- package/dist/esm/client.js +76 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/core/errors.d.ts +64 -0
- package/dist/esm/core/errors.d.ts.map +1 -0
- package/dist/esm/core/errors.js +86 -0
- package/dist/esm/core/errors.js.map +1 -0
- package/dist/esm/core/http.d.ts +58 -0
- package/dist/esm/core/http.d.ts.map +1 -0
- package/dist/esm/core/http.js +138 -0
- package/dist/esm/core/http.js.map +1 -0
- package/dist/esm/core/pagination.d.ts +12 -0
- package/dist/esm/core/pagination.d.ts.map +1 -0
- package/dist/esm/core/pagination.js +12 -0
- package/dist/esm/core/pagination.js.map +1 -0
- 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 +336 -0
- package/dist/esm/generated/types.d.ts.map +1 -0
- package/dist/esm/generated/types.js +4 -0
- package/dist/esm/generated/types.js.map +1 -0
- package/dist/esm/index.d.ts +23 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +20 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/resources/account.d.ts +22 -0
- package/dist/esm/resources/account.d.ts.map +1 -0
- package/dist/esm/resources/account.js +27 -0
- package/dist/esm/resources/account.js.map +1 -0
- package/dist/esm/resources/addresses.d.ts +93 -0
- package/dist/esm/resources/addresses.d.ts.map +1 -0
- package/dist/esm/resources/addresses.js +124 -0
- package/dist/esm/resources/addresses.js.map +1 -0
- package/dist/esm/resources/catalog.d.ts +37 -0
- package/dist/esm/resources/catalog.d.ts.map +1 -0
- package/dist/esm/resources/catalog.js +47 -0
- package/dist/esm/resources/catalog.js.map +1 -0
- package/dist/esm/resources/deliveries.d.ts +61 -0
- package/dist/esm/resources/deliveries.d.ts.map +1 -0
- package/dist/esm/resources/deliveries.js +49 -0
- package/dist/esm/resources/deliveries.js.map +1 -0
- package/dist/esm/resources/transactions.d.ts +28 -0
- package/dist/esm/resources/transactions.d.ts.map +1 -0
- package/dist/esm/resources/transactions.js +30 -0
- package/dist/esm/resources/transactions.js.map +1 -0
- 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 +29 -0
- package/dist/esm/units.d.ts.map +1 -0
- package/dist/esm/units.js +58 -0
- package/dist/esm/units.js.map +1 -0
- package/dist/esm/version.d.ts +5 -0
- package/dist/esm/version.d.ts.map +1 -0
- package/dist/esm/version.js +5 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/esm/webhooks.d.ts +82 -0
- package/dist/esm/webhooks.d.ts.map +1 -0
- package/dist/esm/webhooks.js +125 -0
- package/dist/esm/webhooks.js.map +1 -0
- package/package.json +69 -4
- package/src/client.ts +83 -0
- package/src/core/errors.ts +99 -0
- package/src/core/http.ts +183 -0
- package/src/core/pagination.ts +20 -0
- package/src/core/scope.ts +8 -0
- package/src/generated/types.ts +369 -0
- package/src/index.ts +43 -0
- package/src/resources/account.ts +33 -0
- package/src/resources/addresses.ts +165 -0
- package/src/resources/catalog.ts +56 -0
- package/src/resources/deliveries.ts +82 -0
- package/src/resources/transactions.ts +34 -0
- package/src/resources/webhooks.ts +36 -0
- package/src/units.ts +56 -0
- package/src/version.ts +5 -0
- package/src/webhooks.ts +138 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
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
|
+
|
|
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
|
|
17
|
+
|
|
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
|
|
25
|
+
|
|
26
|
+
- Initial release.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 V3 Finance
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,323 @@
|
|
|
1
|
-
#
|
|
1
|
+
# V3 Finance Monitoring SDK
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install @v3finance/monitoring-sdk
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pnpm add @v3finance/monitoring-sdk
|
|
45
|
+
yarn add @v3finance/monitoring-sdk
|
|
46
|
+
bun add @v3finance/monitoring-sdk
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Quick start
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { MonitoringClient } from '@v3finance/monitoring-sdk'
|
|
53
|
+
|
|
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).
|
|
65
|
+
|
|
66
|
+
## Configuration
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
const monitoring = new MonitoringClient({
|
|
70
|
+
apiKey: process.env.MONITORING_API_KEY!,
|
|
71
|
+
timeoutMs: 10_000,
|
|
72
|
+
maxRetries: 3,
|
|
73
|
+
})
|
|
74
|
+
```
|
|
75
|
+
|
|
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
|
|
87
|
+
|
|
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.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
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' }])
|
|
112
|
+
```
|
|
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
|
+
|
|
117
|
+
## Receiving webhooks
|
|
118
|
+
|
|
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**
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import express from 'express'
|
|
126
|
+
import { isTestWebhook, parseWebhook, webhookIdempotencyKey, WebhookSignatureError } from '@v3finance/monitoring-sdk'
|
|
127
|
+
|
|
128
|
+
const app = express()
|
|
129
|
+
|
|
130
|
+
app.post('/webhooks/monitoring', express.raw({ type: 'application/json' }), async (req, res) => {
|
|
131
|
+
try {
|
|
132
|
+
const event = await parseWebhook(req.body, req.headers, process.env.MONITORING_WEBHOOK_SECRET!)
|
|
133
|
+
if (!isTestWebhook(event)) {
|
|
134
|
+
await creditOnce(webhookIdempotencyKey(event), event.tx)
|
|
135
|
+
}
|
|
136
|
+
res.sendStatus(200)
|
|
137
|
+
} catch (error) {
|
|
138
|
+
if (error instanceof WebhookSignatureError) return res.sendStatus(401)
|
|
139
|
+
throw error
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Next.js (App Router)** — and any runtime built on the Fetch API: Cloudflare Workers, Bun, Deno
|
|
145
|
+
|
|
146
|
+
```ts
|
|
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
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Hono**
|
|
155
|
+
|
|
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
|
+
```
|
|
163
|
+
|
|
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:
|
|
184
|
+
|
|
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:
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
const { delivery, signature, body } = await monitoring.webhooks.sendTest({ asset: 'USDT' })
|
|
198
|
+
console.log(delivery.ok ? 'Delivered' : `Endpoint responded with ${delivery.status ?? delivery.error}`)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Transactions and finality
|
|
202
|
+
|
|
203
|
+
Look up any transaction on a supported network — not only the ones you were notified about.
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
const tx = await monitoring.transactions.get('tron', event.tx.id)
|
|
207
|
+
|
|
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
|
|
215
|
+
```
|
|
216
|
+
|
|
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`.
|
|
219
|
+
|
|
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.
|
|
223
|
+
|
|
224
|
+
```ts
|
|
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)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const detail = await monitoring.deliveries.get(deliveryId) // includes the exact request body
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Filter by `status` (`delivered`, `retrying`, `failed`), `network`, `asset`, `tx`, `address`, `since` and `until`.
|
|
233
|
+
|
|
234
|
+
## Networks and assets
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
const networks = await monitoring.networks.list()
|
|
238
|
+
const assets = await monitoring.assets.list({ network: 'tron' })
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
You are notified about transfers of enabled assets of at least the asset's `minAmount`.
|
|
242
|
+
|
|
243
|
+
## Amounts
|
|
244
|
+
|
|
245
|
+
Amounts are strings in the asset's smallest unit (sun, wei; USDT has 6 decimals). Convert them without losing
|
|
246
|
+
precision:
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
import { formatUnits, parseUnits } from '@v3finance/monitoring-sdk'
|
|
250
|
+
|
|
251
|
+
formatUnits('100000000', 6) // '100'
|
|
252
|
+
parseUnits('1.5', 6) // '1500000'
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Error handling
|
|
256
|
+
|
|
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. |
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
import { MonitoringApiError } from '@v3finance/monitoring-sdk'
|
|
268
|
+
|
|
269
|
+
try {
|
|
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
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Retries, timeouts and cancellation
|
|
281
|
+
|
|
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:
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
const controller = new AbortController()
|
|
288
|
+
|
|
289
|
+
await monitoring.addresses.list({ network: 'tron' }, { timeoutMs: 5_000, maxRetries: 0, signal: controller.signal })
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## TypeScript
|
|
293
|
+
|
|
294
|
+
The SDK is written in TypeScript and ships its own type declarations. All request and response types are exported:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
import type { Address, Delivery, Transaction, WebhookPayload } from '@v3finance/monitoring-sdk'
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Requirements
|
|
301
|
+
|
|
302
|
+
- Node.js 20 or later, Bun, Deno or Cloudflare Workers.
|
|
303
|
+
- ESM (`import`) and CommonJS (`require`) are both supported.
|
|
304
|
+
|
|
305
|
+
## Security
|
|
306
|
+
|
|
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.
|
|
310
|
+
|
|
311
|
+
## Versioning
|
|
312
|
+
|
|
313
|
+
This package follows [Semantic Versioning](https://semver.org). Changes are listed in [CHANGELOG.md](./CHANGELOG.md).
|
|
314
|
+
|
|
315
|
+
## Support
|
|
316
|
+
|
|
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.
|
|
320
|
+
|
|
321
|
+
## License
|
|
322
|
+
|
|
323
|
+
[MIT](./LICENSE) © V3 Finance
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type ClientOptions } from './core/http.js';
|
|
2
|
+
import { AccountResource } from './resources/account.js';
|
|
3
|
+
import { AddressesResource } from './resources/addresses.js';
|
|
4
|
+
import { AssetsResource, NetworksResource } from './resources/catalog.js';
|
|
5
|
+
import { DeliveriesResource } from './resources/deliveries.js';
|
|
6
|
+
import { TransactionsResource } from './resources/transactions.js';
|
|
7
|
+
import { WebhooksResource } from './resources/webhooks.js';
|
|
8
|
+
/**
|
|
9
|
+
* Client for the V3 Finance Monitoring API.
|
|
10
|
+
*
|
|
11
|
+
* Use it on the server only: an API key in a browser is visible to anyone.
|
|
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
|
+
*
|
|
19
|
+
* await monitoring.addresses.add([{ network: 'tron', address: 'TA8Hg…' }], { assets: ['USDT'], direction: 'in' })
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare class MonitoringClient {
|
|
23
|
+
#private;
|
|
24
|
+
/** Your client: the account your API key belongs to. */
|
|
25
|
+
readonly account: AccountResource;
|
|
26
|
+
/** Addresses you monitor and their subscriptions. */
|
|
27
|
+
readonly addresses: AddressesResource;
|
|
28
|
+
/** Test your webhook endpoint. */
|
|
29
|
+
readonly webhooks: WebhooksResource;
|
|
30
|
+
/** History of webhooks sent to you. */
|
|
31
|
+
readonly deliveries: DeliveriesResource;
|
|
32
|
+
/** Any transaction by hash, with confirmations and finality. */
|
|
33
|
+
readonly transactions: TransactionsResource;
|
|
34
|
+
/** Supported networks. */
|
|
35
|
+
readonly networks: NetworksResource;
|
|
36
|
+
/** Supported native coins and tokens. */
|
|
37
|
+
readonly assets: AssetsResource;
|
|
38
|
+
/**
|
|
39
|
+
* @param options - API key and optional settings.
|
|
40
|
+
* @throws {@link MonitoringError} when `apiKey` is missing or `fetch` is not available.
|
|
41
|
+
*/
|
|
42
|
+
constructor(options: ClientOptions);
|
|
43
|
+
/** API base URL this client sends requests to. */
|
|
44
|
+
get baseUrl(): string;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MonitoringClient = void 0;
|
|
4
|
+
const errors_js_1 = require("./core/errors.js");
|
|
5
|
+
const http_js_1 = require("./core/http.js");
|
|
6
|
+
const account_js_1 = require("./resources/account.js");
|
|
7
|
+
const addresses_js_1 = require("./resources/addresses.js");
|
|
8
|
+
const catalog_js_1 = require("./resources/catalog.js");
|
|
9
|
+
const deliveries_js_1 = require("./resources/deliveries.js");
|
|
10
|
+
const transactions_js_1 = require("./resources/transactions.js");
|
|
11
|
+
const webhooks_js_1 = require("./resources/webhooks.js");
|
|
12
|
+
const version_js_1 = require("./version.js");
|
|
13
|
+
/**
|
|
14
|
+
* Client for the V3 Finance Monitoring API.
|
|
15
|
+
*
|
|
16
|
+
* Use it on the server only: an API key in a browser is visible to anyone.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { MonitoringClient } from '@v3finance/monitoring-sdk'
|
|
21
|
+
*
|
|
22
|
+
* const monitoring = new MonitoringClient({ apiKey: process.env.MONITORING_API_KEY! })
|
|
23
|
+
*
|
|
24
|
+
* await monitoring.addresses.add([{ network: 'tron', address: 'TA8Hg…' }], { assets: ['USDT'], direction: 'in' })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
class MonitoringClient {
|
|
28
|
+
/** Your client: the account your API key belongs to. */
|
|
29
|
+
account;
|
|
30
|
+
/** Addresses you monitor and their subscriptions. */
|
|
31
|
+
addresses;
|
|
32
|
+
/** Test your webhook endpoint. */
|
|
33
|
+
webhooks;
|
|
34
|
+
/** History of webhooks sent to you. */
|
|
35
|
+
deliveries;
|
|
36
|
+
/** Any transaction by hash, with confirmations and finality. */
|
|
37
|
+
transactions;
|
|
38
|
+
/** Supported networks. */
|
|
39
|
+
networks;
|
|
40
|
+
/** Supported native coins and tokens. */
|
|
41
|
+
assets;
|
|
42
|
+
#http;
|
|
43
|
+
#clientId;
|
|
44
|
+
/**
|
|
45
|
+
* @param options - API key and optional settings.
|
|
46
|
+
* @throws {@link MonitoringError} when `apiKey` is missing or `fetch` is not available.
|
|
47
|
+
*/
|
|
48
|
+
constructor(options) {
|
|
49
|
+
this.#http = new http_js_1.HttpClient(options, version_js_1.DEFAULT_BASE_URL);
|
|
50
|
+
if (options.clientId)
|
|
51
|
+
this.#clientId = Promise.resolve(options.clientId);
|
|
52
|
+
const scope = { http: this.#http, clientPath: async () => `/v1/clients/${(0, http_js_1.seg)(await this.#resolveClientId())}` };
|
|
53
|
+
this.account = new account_js_1.AccountResource(scope, () => this.#resolveClientId());
|
|
54
|
+
this.addresses = new addresses_js_1.AddressesResource(scope);
|
|
55
|
+
this.webhooks = new webhooks_js_1.WebhooksResource(scope);
|
|
56
|
+
this.deliveries = new deliveries_js_1.DeliveriesResource(scope);
|
|
57
|
+
this.transactions = new transactions_js_1.TransactionsResource(scope);
|
|
58
|
+
this.networks = new catalog_js_1.NetworksResource(scope);
|
|
59
|
+
this.assets = new catalog_js_1.AssetsResource(scope);
|
|
60
|
+
}
|
|
61
|
+
/** API base URL this client sends requests to. */
|
|
62
|
+
get baseUrl() {
|
|
63
|
+
return this.#http.baseUrl;
|
|
64
|
+
}
|
|
65
|
+
/** Client ID of the API key: from the options, or resolved once from the API and cached. */
|
|
66
|
+
#resolveClientId() {
|
|
67
|
+
this.#clientId ??= this.#http.request({ method: 'GET', path: '/v1/me', idempotent: true }).then((identity) => {
|
|
68
|
+
if (!identity.actor.clientId)
|
|
69
|
+
throw new errors_js_1.MonitoringError('this API key is not bound to a client: pass clientId in the options');
|
|
70
|
+
return identity.actor.clientId;
|
|
71
|
+
}, (error) => {
|
|
72
|
+
// a failed lookup is not cached: the next call tries again
|
|
73
|
+
this.#clientId = undefined;
|
|
74
|
+
throw error;
|
|
75
|
+
});
|
|
76
|
+
return this.#clientId;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.MonitoringClient = MonitoringClient;
|
|
80
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":";;;AAAA,gDAAkD;AAClD,4CAAoE;AAGpE,uDAAwD;AACxD,2DAA4D;AAC5D,uDAAyE;AACzE,6DAA8D;AAC9D,iEAAkE;AAClE,yDAA0D;AAC1D,6CAA+C;AAE/C;;;;;;;;;;;;;GAaG;AACH;IACE,wDAAwD;IAC/C,OAAO,CAAiB;IACjC,qDAAqD;IAC5C,SAAS,CAAmB;IACrC,kCAAkC;IACzB,QAAQ,CAAkB;IACnC,uCAAuC;IAC9B,UAAU,CAAoB;IACvC,gEAAgE;IACvD,YAAY,CAAsB;IAC3C,0BAA0B;IACjB,QAAQ,CAAkB;IACnC,yCAAyC;IAChC,MAAM,CAAgB;IAEtB,KAAK,CAAY;IAC1B,SAAS,CAA6B;IAEtC;;;OAGG;IACH,YAAY,OAAsB;QAChC,IAAI,CAAC,KAAK,GAAG,IAAI,oBAAU,CAAC,OAAO,EAAE,6BAAgB,CAAC,CAAA;QACtD,IAAI,OAAO,CAAC,QAAQ;YAAE,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACxE,MAAM,KAAK,GAAU,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,eAAe,IAAA,aAAG,EAAC,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC,EAAE,EAAE,CAAA;QACtH,IAAI,CAAC,OAAO,GAAG,IAAI,4BAAe,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAA;QACxE,IAAI,CAAC,SAAS,GAAG,IAAI,gCAAiB,CAAC,KAAK,CAAC,CAAA;QAC7C,IAAI,CAAC,QAAQ,GAAG,IAAI,8BAAgB,CAAC,KAAK,CAAC,CAAA;QAC3C,IAAI,CAAC,UAAU,GAAG,IAAI,kCAAkB,CAAC,KAAK,CAAC,CAAA;QAC/C,IAAI,CAAC,YAAY,GAAG,IAAI,sCAAoB,CAAC,KAAK,CAAC,CAAA;QACnD,IAAI,CAAC,QAAQ,GAAG,IAAI,6BAAgB,CAAC,KAAK,CAAC,CAAA;QAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,2BAAc,CAAC,KAAK,CAAC,CAAA;IACzC,CAAC;IAED,kDAAkD;IAClD,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAA;IAC3B,CAAC;IAED,4FAA4F;IAC5F,gBAAgB;QACd,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAW,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CACvG,CAAC,QAAQ,EAAE,EAAE;YACX,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ;gBAAE,MAAM,IAAI,2BAAe,CAAC,qEAAqE,CAAC,CAAA;YAC9H,OAAO,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAA;QAChC,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;YACjB,2DAA2D;YAC3D,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;YAC1B,MAAM,KAAK,CAAA;QACb,CAAC,CACF,CAAA;QACD,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ApiErrorBody } from '../generated/types.js';
|
|
2
|
+
/** A per-item problem of a batch request: the item's index in your request and the reason. */
|
|
3
|
+
export type ErrorDetail = NonNullable<ApiErrorBody['error']['details']>[number];
|
|
4
|
+
/**
|
|
5
|
+
* Base class of every error thrown by the SDK.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* try {
|
|
10
|
+
* await monitoring.addresses.add(items)
|
|
11
|
+
* } catch (error) {
|
|
12
|
+
* if (error instanceof MonitoringApiError && error.status === 400) console.log(error.details)
|
|
13
|
+
* else throw error
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare class MonitoringError extends Error {
|
|
18
|
+
constructor(message: string, options?: {
|
|
19
|
+
cause?: unknown;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/** The API responded with an error status (4xx or 5xx). */
|
|
23
|
+
export declare class MonitoringApiError extends MonitoringError {
|
|
24
|
+
/** HTTP status code. */
|
|
25
|
+
readonly status: number;
|
|
26
|
+
/**
|
|
27
|
+
* Machine-readable error code, e.g. `invalid_request`, `unauthorized`, `forbidden`, `not_found`,
|
|
28
|
+
* `rate_limited`, `upstream_error`, `upstream_rate_limited`.
|
|
29
|
+
*/
|
|
30
|
+
readonly code: string;
|
|
31
|
+
/** Per-item problems of a batch request, such as invalid addresses. Empty when there are none. */
|
|
32
|
+
readonly details: ErrorDetail[];
|
|
33
|
+
/** Request ID. Include it when contacting support. */
|
|
34
|
+
readonly requestId: string | undefined;
|
|
35
|
+
/** Raw response body. */
|
|
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
|
+
/** `true` for transient errors — rate limits and unavailable upstream providers — that can be retried later. */
|
|
46
|
+
get retryable(): boolean;
|
|
47
|
+
}
|
|
48
|
+
/** The request did not get a response because of a network or connection failure. */
|
|
49
|
+
export declare class MonitoringConnectionError extends MonitoringError {
|
|
50
|
+
constructor(message: string, options?: {
|
|
51
|
+
cause?: unknown;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** The request did not complete within `timeoutMs`. */
|
|
55
|
+
export declare class MonitoringTimeoutError extends MonitoringConnectionError {
|
|
56
|
+
constructor(timeoutMs: number);
|
|
57
|
+
}
|
|
58
|
+
/** The webhook signature does not match: the body was altered or is verified with the wrong secret. */
|
|
59
|
+
export declare class WebhookSignatureError extends MonitoringError {
|
|
60
|
+
constructor(message?: string);
|
|
61
|
+
}
|
|
62
|
+
/** Builds an error from any error body the API returns. */
|
|
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,8FAA8F;AAC9F,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,2DAA2D;AAC3D,qBAAa,kBAAmB,SAAQ,eAAe;IACrD,wBAAwB;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,kGAAkG;IAClG,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,CAAA;IAC/B,sDAAsD;IACtD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,yBAAyB;IACzB,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,gHAAgH;IAChH,IAAI,SAAS,IAAI,OAAO,CAEvB;CACF;AAED,qFAAqF;AACrF,qBAAa,yBAA0B,SAAQ,eAAe;IAC5D,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAGzD;CACF;AAED,uDAAuD;AACvD,qBAAa,sBAAuB,SAAQ,yBAAyB;IACnE,YAAY,SAAS,EAAE,MAAM,EAG5B;CACF;AAED,uGAAuG;AACvG,qBAAa,qBAAsB,SAAQ,eAAe;IACxD,YAAY,OAAO,SAA+B,EAGjD;CACF;AAED,2DAA2D;AAC3D,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,CAW7G"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebhookSignatureError = exports.MonitoringTimeoutError = exports.MonitoringConnectionError = exports.MonitoringApiError = exports.MonitoringError = void 0;
|
|
4
|
+
exports.apiErrorFrom = apiErrorFrom;
|
|
5
|
+
/**
|
|
6
|
+
* Base class of every error thrown by the SDK.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* try {
|
|
11
|
+
* await monitoring.addresses.add(items)
|
|
12
|
+
* } catch (error) {
|
|
13
|
+
* if (error instanceof MonitoringApiError && error.status === 400) console.log(error.details)
|
|
14
|
+
* else throw error
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
class MonitoringError extends Error {
|
|
19
|
+
constructor(message, options) {
|
|
20
|
+
super(message, options);
|
|
21
|
+
this.name = 'MonitoringError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.MonitoringError = MonitoringError;
|
|
25
|
+
/** The API responded with an error status (4xx or 5xx). */
|
|
26
|
+
class MonitoringApiError extends MonitoringError {
|
|
27
|
+
/** HTTP status code. */
|
|
28
|
+
status;
|
|
29
|
+
/**
|
|
30
|
+
* Machine-readable error code, e.g. `invalid_request`, `unauthorized`, `forbidden`, `not_found`,
|
|
31
|
+
* `rate_limited`, `upstream_error`, `upstream_rate_limited`.
|
|
32
|
+
*/
|
|
33
|
+
code;
|
|
34
|
+
/** Per-item problems of a batch request, such as invalid addresses. Empty when there are none. */
|
|
35
|
+
details;
|
|
36
|
+
/** Request ID. Include it when contacting support. */
|
|
37
|
+
requestId;
|
|
38
|
+
/** Raw response body. */
|
|
39
|
+
body;
|
|
40
|
+
constructor(init) {
|
|
41
|
+
super(`${init.message} (HTTP ${init.status}, ${init.code})`);
|
|
42
|
+
this.name = 'MonitoringApiError';
|
|
43
|
+
this.status = init.status;
|
|
44
|
+
this.code = init.code;
|
|
45
|
+
this.details = init.details ?? [];
|
|
46
|
+
this.requestId = init.requestId;
|
|
47
|
+
this.body = init.body;
|
|
48
|
+
}
|
|
49
|
+
/** `true` for transient errors — rate limits and unavailable upstream providers — that can be retried later. */
|
|
50
|
+
get retryable() {
|
|
51
|
+
return this.status === 429 || this.status === 503;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.MonitoringApiError = MonitoringApiError;
|
|
55
|
+
/** The request did not get a response because of a network or connection failure. */
|
|
56
|
+
class MonitoringConnectionError extends MonitoringError {
|
|
57
|
+
constructor(message, options) {
|
|
58
|
+
super(message, options);
|
|
59
|
+
this.name = 'MonitoringConnectionError';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.MonitoringConnectionError = MonitoringConnectionError;
|
|
63
|
+
/** The request did not complete within `timeoutMs`. */
|
|
64
|
+
class MonitoringTimeoutError extends MonitoringConnectionError {
|
|
65
|
+
constructor(timeoutMs) {
|
|
66
|
+
super(`request timed out after ${timeoutMs} ms`);
|
|
67
|
+
this.name = 'MonitoringTimeoutError';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.MonitoringTimeoutError = MonitoringTimeoutError;
|
|
71
|
+
/** The webhook signature does not match: the body was altered or is verified with the wrong secret. */
|
|
72
|
+
class WebhookSignatureError extends MonitoringError {
|
|
73
|
+
constructor(message = 'webhook signature mismatch') {
|
|
74
|
+
super(message);
|
|
75
|
+
this.name = 'WebhookSignatureError';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.WebhookSignatureError = WebhookSignatureError;
|
|
79
|
+
/** Builds an error from any error body the API returns. */
|
|
80
|
+
function apiErrorFrom(status, body, requestId) {
|
|
81
|
+
const b = (body ?? {});
|
|
82
|
+
const v1 = typeof b.error === 'object' && b.error !== null ? b.error : undefined;
|
|
83
|
+
const message = (typeof v1?.message === 'string' && v1.message) ||
|
|
84
|
+
(typeof b.error === 'string' && b.error) ||
|
|
85
|
+
(typeof b.message === 'string' && b.message) ||
|
|
86
|
+
`HTTP ${status}`;
|
|
87
|
+
const code = (typeof v1?.code === 'string' && v1.code) || (typeof b.code === 'string' && b.code.toLowerCase()) || defaultCode(status);
|
|
88
|
+
const details = (Array.isArray(v1?.details) ? v1.details : Array.isArray(b.details) ? b.details : []);
|
|
89
|
+
return new MonitoringApiError({ status, code, message, details, requestId, body });
|
|
90
|
+
}
|
|
91
|
+
function defaultCode(status) {
|
|
92
|
+
const codes = { 400: 'invalid_request', 401: 'unauthorized', 403: 'forbidden', 404: 'not_found', 409: 'conflict', 429: 'rate_limited' };
|
|
93
|
+
return codes[status] ?? (status >= 500 ? 'server_error' : 'http_error');
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=errors.js.map
|