@hbar-kit/mirror 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.
- package/LICENSE +21 -0
- package/README.md +20 -0
- package/dist/index.cjs +254 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +202 -0
- package/dist/index.d.ts +202 -0
- package/dist/index.js +246 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -0
- package/src/client.ts +38 -0
- package/src/index.ts +13 -0
- package/src/json.ts +17 -0
- package/src/normalize.ts +81 -0
- package/src/paginate.ts +23 -0
- package/src/resources/accounts.ts +28 -0
- package/src/resources/balances.ts +19 -0
- package/src/resources/tokens.ts +17 -0
- package/src/resources/transactions.ts +52 -0
- package/src/transport.ts +84 -0
- package/src/types.ts +120 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Oleksandr Ostrovskyi
|
|
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
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @hbar-kit/mirror
|
|
2
|
+
|
|
3
|
+
Typed client for the Hedera Mirror Node REST API. Native `fetch`, retry-aware transport,
|
|
4
|
+
lossless `bigint` amount parsing, `links.next` pagination, and normalized responses.
|
|
5
|
+
|
|
6
|
+
```ts
|
|
7
|
+
import { createMirrorClient } from "@hbar-kit/mirror"
|
|
8
|
+
|
|
9
|
+
const mirror = createMirrorClient({ network: "testnet" })
|
|
10
|
+
const page = await mirror.transactions.find({
|
|
11
|
+
accountId: "0.0.8093816",
|
|
12
|
+
transactionType: "cryptotransfer",
|
|
13
|
+
result: "success",
|
|
14
|
+
limit: 25,
|
|
15
|
+
})
|
|
16
|
+
for (const tx of page.items) console.log(tx.transactionId, tx.memo, tx.transfers)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`network` (or `baseUrl`) is required — there is no default, which prevents testnet/mainnet
|
|
20
|
+
mix-ups. See the [docs](https://github.com/devwhodevs/hbar-kit).
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@hbar-kit/core');
|
|
4
|
+
|
|
5
|
+
// src/client.ts
|
|
6
|
+
|
|
7
|
+
// src/json.ts
|
|
8
|
+
var BIGINT_KEYS = ["amount", "balance", "charged_tx_fee", "serial_number"];
|
|
9
|
+
function parseJsonWithBigInt(text) {
|
|
10
|
+
const keyAlternation = BIGINT_KEYS.join("|");
|
|
11
|
+
const re = new RegExp(`("(?:${keyAlternation})"\\s*:\\s*)(-?\\d+)`, "g");
|
|
12
|
+
const marked = text.replace(re, (_m, prefix, num) => `${prefix}" bi:${num}"`);
|
|
13
|
+
return JSON.parse(marked, (_k, value) => {
|
|
14
|
+
if (typeof value === "string" && value.startsWith(" bi:")) return BigInt(value.slice(4));
|
|
15
|
+
return value;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/transport.ts
|
|
20
|
+
var RETRYABLE = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
21
|
+
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
22
|
+
var jitter = (ms) => ms * (0.5 + Math.random());
|
|
23
|
+
function http(baseUrl, options = {}) {
|
|
24
|
+
const doFetch = options.fetch ?? globalThis.fetch;
|
|
25
|
+
const retryCount = options.retryCount ?? 3;
|
|
26
|
+
const retryDelay = options.retryDelay ?? 150;
|
|
27
|
+
const timeout = options.timeout ?? 1e4;
|
|
28
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
29
|
+
async function get(path) {
|
|
30
|
+
const url = path.startsWith("http") ? path : base + path;
|
|
31
|
+
let attempt = 0;
|
|
32
|
+
let lastErr;
|
|
33
|
+
while (attempt <= retryCount) {
|
|
34
|
+
const controller = new AbortController();
|
|
35
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
36
|
+
try {
|
|
37
|
+
const response = await doFetch(url, {
|
|
38
|
+
signal: controller.signal,
|
|
39
|
+
headers: { accept: "application/json", ...options.headers }
|
|
40
|
+
});
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
if (response.ok) {
|
|
43
|
+
const text = await response.text();
|
|
44
|
+
return text ? parseJsonWithBigInt(text) : null;
|
|
45
|
+
}
|
|
46
|
+
if (RETRYABLE.has(response.status) && attempt < retryCount) {
|
|
47
|
+
const retryAfter = Number(response.headers.get("retry-after"));
|
|
48
|
+
const wait = Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter * 1e3 : jitter(retryDelay * 2 ** attempt);
|
|
49
|
+
await sleep(wait);
|
|
50
|
+
attempt++;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const body = await response.text().catch(() => "");
|
|
54
|
+
if (response.status === 429) {
|
|
55
|
+
const ra = Number(response.headers.get("retry-after"));
|
|
56
|
+
throw new core.RateLimitError(
|
|
57
|
+
`Mirror Node rate limited (429)`,
|
|
58
|
+
Number.isFinite(ra) ? { details: body, retryAfter: ra } : { details: body }
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
throw new core.MirrorHttpError(`Mirror Node HTTP ${response.status}`, response.status, {
|
|
62
|
+
details: body
|
|
63
|
+
});
|
|
64
|
+
} catch (err) {
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
if (err instanceof core.MirrorHttpError) throw err;
|
|
67
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
68
|
+
throw new core.TimeoutError(`Mirror Node request timed out after ${timeout}ms`, { cause: err });
|
|
69
|
+
}
|
|
70
|
+
lastErr = err;
|
|
71
|
+
if (attempt < retryCount) {
|
|
72
|
+
await sleep(jitter(retryDelay * 2 ** attempt));
|
|
73
|
+
attempt++;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
throw new core.NetworkError(`Mirror Node request failed: ${String(err)}`, { cause: err });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
throw new core.NetworkError(`Mirror Node request failed`, { cause: lastErr });
|
|
80
|
+
}
|
|
81
|
+
return { get, baseUrl: base };
|
|
82
|
+
}
|
|
83
|
+
var decodeMemo = (b64) => b64 ? Buffer.from(b64, "base64").toString("utf8") : "";
|
|
84
|
+
function normalizeTransaction(raw) {
|
|
85
|
+
return {
|
|
86
|
+
transactionId: raw.transaction_id,
|
|
87
|
+
consensusTimestamp: core.parseTimestamp(raw.consensus_timestamp),
|
|
88
|
+
validStartTimestamp: raw.valid_start_timestamp ? core.parseTimestamp(raw.valid_start_timestamp) : void 0,
|
|
89
|
+
result: raw.result,
|
|
90
|
+
name: raw.name,
|
|
91
|
+
chargedTxFee: raw.charged_tx_fee,
|
|
92
|
+
memo: decodeMemo(raw.memo_base64),
|
|
93
|
+
nonce: raw.nonce,
|
|
94
|
+
scheduled: raw.scheduled,
|
|
95
|
+
parentConsensusTimestamp: raw.parent_consensus_timestamp,
|
|
96
|
+
transfers: (raw.transfers ?? []).map((t) => ({
|
|
97
|
+
account: t.account,
|
|
98
|
+
amount: t.amount,
|
|
99
|
+
isApproval: t.is_approval ?? false
|
|
100
|
+
})),
|
|
101
|
+
tokenTransfers: (raw.token_transfers ?? []).map((t) => ({
|
|
102
|
+
tokenId: t.token_id,
|
|
103
|
+
account: t.account,
|
|
104
|
+
amount: t.amount,
|
|
105
|
+
isApproval: t.is_approval ?? false
|
|
106
|
+
})),
|
|
107
|
+
nftTransfers: (raw.nft_transfers ?? []).map((t) => ({
|
|
108
|
+
tokenId: t.token_id,
|
|
109
|
+
sender: t.sender_account_id,
|
|
110
|
+
receiver: t.receiver_account_id,
|
|
111
|
+
serial: t.serial_number,
|
|
112
|
+
isApproval: t.is_approval ?? false
|
|
113
|
+
})),
|
|
114
|
+
raw
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function normalizeToken(raw) {
|
|
118
|
+
return {
|
|
119
|
+
tokenId: raw.token_id,
|
|
120
|
+
decimals: Number(raw.decimals),
|
|
121
|
+
symbol: raw.symbol,
|
|
122
|
+
name: raw.name,
|
|
123
|
+
type: raw.type,
|
|
124
|
+
totalSupply: raw.total_supply != null ? BigInt(raw.total_supply) : void 0,
|
|
125
|
+
maxSupply: raw.max_supply != null ? BigInt(raw.max_supply) : void 0,
|
|
126
|
+
treasuryAccountId: raw.treasury_account_id,
|
|
127
|
+
raw
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function normalizeAccountBalance(raw) {
|
|
131
|
+
return {
|
|
132
|
+
accountId: raw.account,
|
|
133
|
+
balance: raw.balance.balance,
|
|
134
|
+
tokens: (raw.balance.tokens ?? []).map((t) => ({ tokenId: t.token_id, balance: t.balance })),
|
|
135
|
+
raw
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function isNotFound(body) {
|
|
139
|
+
if (!body || typeof body !== "object") return false;
|
|
140
|
+
const status = body._status;
|
|
141
|
+
if (status?.messages?.some((m) => /not found/i.test(m.message))) return true;
|
|
142
|
+
const txs = body.transactions;
|
|
143
|
+
if (Array.isArray(txs) && txs.length === 0) return true;
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/resources/transactions.ts
|
|
148
|
+
function buildQuery(params) {
|
|
149
|
+
const q = new URLSearchParams();
|
|
150
|
+
if (params.accountId) q.set("account.id", params.accountId);
|
|
151
|
+
if (params.transactionType) q.set("transactiontype", params.transactionType);
|
|
152
|
+
if (params.result) q.set("result", params.result);
|
|
153
|
+
if (params.order) q.set("order", params.order);
|
|
154
|
+
q.set("limit", String(Math.min(params.limit ?? 25, 100)));
|
|
155
|
+
if (params.after) q.append("timestamp", core.tsFilter("gte", params.after));
|
|
156
|
+
if (params.before) q.append("timestamp", core.tsFilter("lt", params.before));
|
|
157
|
+
return q.toString();
|
|
158
|
+
}
|
|
159
|
+
function createTransactionsResource(transport) {
|
|
160
|
+
return {
|
|
161
|
+
async find(params = {}) {
|
|
162
|
+
const body = await transport.get(
|
|
163
|
+
`/api/v1/transactions?${buildQuery(params)}`
|
|
164
|
+
);
|
|
165
|
+
return {
|
|
166
|
+
items: (body.transactions ?? []).map(normalizeTransaction),
|
|
167
|
+
next: body.links?.next ?? null
|
|
168
|
+
};
|
|
169
|
+
},
|
|
170
|
+
async get(transactionId) {
|
|
171
|
+
const id = core.txIdToMirror(transactionId);
|
|
172
|
+
const body = await transport.get(`/api/v1/transactions/${id}`);
|
|
173
|
+
return (body.transactions ?? []).map(normalizeTransaction);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function createAccountsResource(transport) {
|
|
178
|
+
return {
|
|
179
|
+
async getBalance(accountId) {
|
|
180
|
+
core.assertEntityId(accountId);
|
|
181
|
+
return normalizeAccountBalance(
|
|
182
|
+
await transport.get(`/api/v1/accounts/${accountId}`)
|
|
183
|
+
);
|
|
184
|
+
},
|
|
185
|
+
async isAssociated(accountId, tokenId) {
|
|
186
|
+
core.assertEntityId(accountId);
|
|
187
|
+
core.assertEntityId(tokenId);
|
|
188
|
+
const body = await transport.get(
|
|
189
|
+
`/api/v1/accounts/${accountId}/tokens?token.id=${tokenId}`
|
|
190
|
+
);
|
|
191
|
+
return Array.isArray(body.tokens) && body.tokens.length > 0;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function createTokensResource(transport) {
|
|
196
|
+
return {
|
|
197
|
+
async get(tokenId) {
|
|
198
|
+
core.assertEntityId(tokenId);
|
|
199
|
+
return normalizeToken(await transport.get(`/api/v1/tokens/${tokenId}`));
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function createBalancesResource(transport) {
|
|
204
|
+
return {
|
|
205
|
+
async get(accountId) {
|
|
206
|
+
core.assertEntityId(accountId);
|
|
207
|
+
const body = await transport.get(`/api/v1/balances?account.id=${accountId}&limit=1`);
|
|
208
|
+
return { accountId, balance: body.balances?.[0]?.balance ?? 0n, timestamp: body.timestamp };
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/client.ts
|
|
214
|
+
function createMirrorClient(config) {
|
|
215
|
+
const { baseUrl } = core.resolveNetwork(config);
|
|
216
|
+
const transportOptions = {};
|
|
217
|
+
if (config.fetch !== void 0) transportOptions.fetch = config.fetch;
|
|
218
|
+
if (config.retryCount !== void 0) transportOptions.retryCount = config.retryCount;
|
|
219
|
+
if (config.retryDelay !== void 0) transportOptions.retryDelay = config.retryDelay;
|
|
220
|
+
if (config.timeout !== void 0) transportOptions.timeout = config.timeout;
|
|
221
|
+
if (config.headers !== void 0) transportOptions.headers = config.headers;
|
|
222
|
+
const transport = config.transport ?? http(baseUrl, transportOptions);
|
|
223
|
+
return {
|
|
224
|
+
baseUrl: transport.baseUrl,
|
|
225
|
+
transport,
|
|
226
|
+
transactions: createTransactionsResource(transport),
|
|
227
|
+
accounts: createAccountsResource(transport),
|
|
228
|
+
tokens: createTokensResource(transport),
|
|
229
|
+
balances: createBalancesResource(transport)
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// src/paginate.ts
|
|
234
|
+
async function* paginate(transport, firstPath, select, options = {}) {
|
|
235
|
+
const maxPages = options.maxPages ?? 1e3;
|
|
236
|
+
let path = firstPath;
|
|
237
|
+
let pages = 0;
|
|
238
|
+
while (path && pages < maxPages) {
|
|
239
|
+
const page = await transport.get(path);
|
|
240
|
+
for (const item of select(page)) yield item;
|
|
241
|
+
path = page.links?.next ?? null;
|
|
242
|
+
pages++;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
exports.createMirrorClient = createMirrorClient;
|
|
247
|
+
exports.http = http;
|
|
248
|
+
exports.isNotFound = isNotFound;
|
|
249
|
+
exports.normalizeAccountBalance = normalizeAccountBalance;
|
|
250
|
+
exports.normalizeToken = normalizeToken;
|
|
251
|
+
exports.normalizeTransaction = normalizeTransaction;
|
|
252
|
+
exports.paginate = paginate;
|
|
253
|
+
//# sourceMappingURL=index.cjs.map
|
|
254
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/json.ts","../src/transport.ts","../src/normalize.ts","../src/resources/transactions.ts","../src/resources/accounts.ts","../src/resources/tokens.ts","../src/resources/balances.ts","../src/client.ts","../src/paginate.ts"],"names":["RateLimitError","MirrorHttpError","TimeoutError","NetworkError","parseTimestamp","tsFilter","txIdToMirror","assertEntityId","resolveNetwork"],"mappings":"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","file":"index.cjs","sourcesContent":["// Fields whose integer values may exceed Number.MAX_SAFE_INTEGER and must be bigint.\nconst BIGINT_KEYS = [\"amount\", \"balance\", \"charged_tx_fee\", \"serial_number\"]\n\n/**\n * Parse Mirror Node JSON, coercing known integer money fields to bigint losslessly.\n * Wraps `\"key\": <integer>` in a sentinel string BEFORE JSON.parse so large integers\n * never pass through a lossy JS number, then revives them as bigint.\n */\nexport function parseJsonWithBigInt(text: string): unknown {\n const keyAlternation = BIGINT_KEYS.join(\"|\")\n const re = new RegExp(`(\"(?:${keyAlternation})\"\\\\s*:\\\\s*)(-?\\\\d+)`, \"g\")\n const marked = text.replace(re, (_m, prefix: string, num: string) => `${prefix}\" bi:${num}\"`)\n return JSON.parse(marked, (_k, value) => {\n if (typeof value === \"string\" && value.startsWith(\" bi:\")) return BigInt(value.slice(4))\n return value\n })\n}\n","import { MirrorHttpError, RateLimitError, TimeoutError, NetworkError } from \"@hbar-kit/core\"\nimport { parseJsonWithBigInt } from \"./json.js\"\n\nexport interface TransportOptions {\n fetch?: typeof fetch\n retryCount?: number\n retryDelay?: number\n timeout?: number\n headers?: Record<string, string>\n}\nexport interface Transport {\n get(path: string): Promise<unknown>\n baseUrl: string\n}\n\nconst RETRYABLE = new Set([408, 425, 429, 500, 502, 503, 504])\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\nconst jitter = (ms: number) => ms * (0.5 + Math.random())\n\nexport function http(baseUrl: string, options: TransportOptions = {}): Transport {\n const doFetch = options.fetch ?? globalThis.fetch\n const retryCount = options.retryCount ?? 3\n const retryDelay = options.retryDelay ?? 150\n const timeout = options.timeout ?? 10_000\n const base = baseUrl.replace(/\\/+$/, \"\")\n\n async function get(path: string): Promise<unknown> {\n const url = path.startsWith(\"http\") ? path : base + path\n let attempt = 0\n let lastErr: unknown\n while (attempt <= retryCount) {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeout)\n try {\n const response = await doFetch(url, {\n signal: controller.signal,\n headers: { accept: \"application/json\", ...options.headers },\n })\n clearTimeout(timer)\n if (response.ok) {\n const text = await response.text()\n return text ? parseJsonWithBigInt(text) : null\n }\n if (RETRYABLE.has(response.status) && attempt < retryCount) {\n const retryAfter = Number(response.headers.get(\"retry-after\"))\n const wait =\n Number.isFinite(retryAfter) && retryAfter > 0\n ? retryAfter * 1000\n : jitter(retryDelay * 2 ** attempt)\n await sleep(wait)\n attempt++\n continue\n }\n const body = await response.text().catch(() => \"\")\n if (response.status === 429) {\n const ra = Number(response.headers.get(\"retry-after\"))\n throw new RateLimitError(\n `Mirror Node rate limited (429)`,\n Number.isFinite(ra) ? { details: body, retryAfter: ra } : { details: body },\n )\n }\n throw new MirrorHttpError(`Mirror Node HTTP ${response.status}`, response.status, {\n details: body,\n })\n } catch (err) {\n clearTimeout(timer)\n if (err instanceof MirrorHttpError) throw err\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new TimeoutError(`Mirror Node request timed out after ${timeout}ms`, { cause: err })\n }\n lastErr = err\n if (attempt < retryCount) {\n await sleep(jitter(retryDelay * 2 ** attempt))\n attempt++\n continue\n }\n throw new NetworkError(`Mirror Node request failed: ${String(err)}`, { cause: err })\n }\n }\n throw new NetworkError(`Mirror Node request failed`, { cause: lastErr })\n }\n\n return { get, baseUrl: base }\n}\n","import { parseTimestamp } from \"@hbar-kit/core\"\nimport type {\n RawTransaction,\n Transaction,\n RawToken,\n Token,\n RawAccount,\n AccountBalance,\n RawStatus,\n} from \"./types.js\"\n\nconst decodeMemo = (b64: string): string => (b64 ? Buffer.from(b64, \"base64\").toString(\"utf8\") : \"\")\n\nexport function normalizeTransaction(raw: RawTransaction): Transaction {\n return {\n transactionId: raw.transaction_id,\n consensusTimestamp: parseTimestamp(raw.consensus_timestamp),\n validStartTimestamp: raw.valid_start_timestamp\n ? parseTimestamp(raw.valid_start_timestamp)\n : undefined,\n result: raw.result,\n name: raw.name,\n chargedTxFee: raw.charged_tx_fee,\n memo: decodeMemo(raw.memo_base64),\n nonce: raw.nonce,\n scheduled: raw.scheduled,\n parentConsensusTimestamp: raw.parent_consensus_timestamp,\n transfers: (raw.transfers ?? []).map((t) => ({\n account: t.account,\n amount: t.amount,\n isApproval: t.is_approval ?? false,\n })),\n tokenTransfers: (raw.token_transfers ?? []).map((t) => ({\n tokenId: t.token_id,\n account: t.account,\n amount: t.amount,\n isApproval: t.is_approval ?? false,\n })),\n nftTransfers: (raw.nft_transfers ?? []).map((t) => ({\n tokenId: t.token_id,\n sender: t.sender_account_id,\n receiver: t.receiver_account_id,\n serial: t.serial_number,\n isApproval: t.is_approval ?? false,\n })),\n raw,\n }\n}\n\nexport function normalizeToken(raw: RawToken): Token {\n return {\n tokenId: raw.token_id,\n decimals: Number(raw.decimals),\n symbol: raw.symbol,\n name: raw.name,\n type: raw.type,\n totalSupply: raw.total_supply != null ? BigInt(raw.total_supply) : undefined,\n maxSupply: raw.max_supply != null ? BigInt(raw.max_supply) : undefined,\n treasuryAccountId: raw.treasury_account_id,\n raw,\n }\n}\n\nexport function normalizeAccountBalance(raw: RawAccount): AccountBalance {\n return {\n accountId: raw.account,\n balance: raw.balance.balance,\n tokens: (raw.balance.tokens ?? []).map((t) => ({ tokenId: t.token_id, balance: t.balance })),\n raw,\n }\n}\n\n/** Detect Mirror Node not-found: the _status envelope, or an empty transactions array. */\nexport function isNotFound(body: unknown): boolean {\n if (!body || typeof body !== \"object\") return false\n const status = (body as RawStatus)._status\n if (status?.messages?.some((m) => /not found/i.test(m.message))) return true\n const txs = (body as { transactions?: unknown[] }).transactions\n if (Array.isArray(txs) && txs.length === 0) return true\n return false\n}\n","import { tsFilter, txIdToMirror } from \"@hbar-kit/core\"\nimport type { Transport } from \"../transport.js\"\nimport { normalizeTransaction } from \"../normalize.js\"\nimport type { Page, RawTransaction, RawTransactionList, Transaction } from \"../types.js\"\n\nexport interface FindTransactionsParams {\n accountId?: string\n transactionType?: string\n result?: \"success\" | \"fail\"\n order?: \"asc\" | \"desc\"\n limit?: number\n after?: Date | string\n before?: Date | string\n}\n\nexport interface TransactionsResource {\n find(params?: FindTransactionsParams): Promise<Page<Transaction>>\n get(transactionId: string): Promise<Transaction[]>\n}\n\nfunction buildQuery(params: FindTransactionsParams): string {\n const q = new URLSearchParams()\n if (params.accountId) q.set(\"account.id\", params.accountId)\n if (params.transactionType) q.set(\"transactiontype\", params.transactionType)\n if (params.result) q.set(\"result\", params.result)\n if (params.order) q.set(\"order\", params.order)\n q.set(\"limit\", String(Math.min(params.limit ?? 25, 100)))\n if (params.after) q.append(\"timestamp\", tsFilter(\"gte\", params.after))\n if (params.before) q.append(\"timestamp\", tsFilter(\"lt\", params.before))\n return q.toString()\n}\n\nexport function createTransactionsResource(transport: Transport): TransactionsResource {\n return {\n async find(params = {}) {\n const body = (await transport.get(\n `/api/v1/transactions?${buildQuery(params)}`,\n )) as RawTransactionList\n return {\n items: (body.transactions ?? []).map(normalizeTransaction),\n next: body.links?.next ?? null,\n }\n },\n async get(transactionId) {\n const id = txIdToMirror(transactionId)\n const body = (await transport.get(`/api/v1/transactions/${id}`)) as {\n transactions?: RawTransaction[]\n }\n return (body.transactions ?? []).map(normalizeTransaction)\n },\n }\n}\n","import { assertEntityId } from \"@hbar-kit/core\"\nimport type { Transport } from \"../transport.js\"\nimport { normalizeAccountBalance } from \"../normalize.js\"\nimport type { AccountBalance, RawAccount } from \"../types.js\"\n\nexport interface AccountsResource {\n getBalance(accountId: string): Promise<AccountBalance>\n isAssociated(accountId: string, tokenId: string): Promise<boolean>\n}\n\nexport function createAccountsResource(transport: Transport): AccountsResource {\n return {\n async getBalance(accountId) {\n assertEntityId(accountId)\n return normalizeAccountBalance(\n (await transport.get(`/api/v1/accounts/${accountId}`)) as RawAccount,\n )\n },\n async isAssociated(accountId, tokenId) {\n assertEntityId(accountId)\n assertEntityId(tokenId)\n const body = (await transport.get(\n `/api/v1/accounts/${accountId}/tokens?token.id=${tokenId}`,\n )) as { tokens?: unknown[] }\n return Array.isArray(body.tokens) && body.tokens.length > 0\n },\n }\n}\n","import { assertEntityId } from \"@hbar-kit/core\"\nimport type { Transport } from \"../transport.js\"\nimport { normalizeToken } from \"../normalize.js\"\nimport type { RawToken, Token } from \"../types.js\"\n\nexport interface TokensResource {\n get(tokenId: string): Promise<Token>\n}\n\nexport function createTokensResource(transport: Transport): TokensResource {\n return {\n async get(tokenId) {\n assertEntityId(tokenId)\n return normalizeToken((await transport.get(`/api/v1/tokens/${tokenId}`)) as RawToken)\n },\n }\n}\n","import { assertEntityId } from \"@hbar-kit/core\"\nimport type { Transport } from \"../transport.js\"\n\nexport interface BalancesResource {\n get(accountId: string): Promise<{ accountId: string; balance: bigint; timestamp: string }>\n}\n\nexport function createBalancesResource(transport: Transport): BalancesResource {\n return {\n async get(accountId) {\n assertEntityId(accountId)\n const body = (await transport.get(`/api/v1/balances?account.id=${accountId}&limit=1`)) as {\n timestamp: string\n balances: { account: string; balance: bigint }[]\n }\n return { accountId, balance: body.balances?.[0]?.balance ?? 0n, timestamp: body.timestamp }\n },\n }\n}\n","import { resolveNetwork, type NetworkInput } from \"@hbar-kit/core\"\nimport { http, type TransportOptions, type Transport } from \"./transport.js\"\nimport { createTransactionsResource, type TransactionsResource } from \"./resources/transactions.js\"\nimport { createAccountsResource, type AccountsResource } from \"./resources/accounts.js\"\nimport { createTokensResource, type TokensResource } from \"./resources/tokens.js\"\nimport { createBalancesResource, type BalancesResource } from \"./resources/balances.js\"\n\nexport interface MirrorClientConfig extends NetworkInput, TransportOptions {\n transport?: Transport\n}\n\nexport interface MirrorClient {\n baseUrl: string\n transport: Transport\n transactions: TransactionsResource\n accounts: AccountsResource\n tokens: TokensResource\n balances: BalancesResource\n}\n\nexport function createMirrorClient(config: MirrorClientConfig): MirrorClient {\n const { baseUrl } = resolveNetwork(config)\n const transportOptions: TransportOptions = {}\n if (config.fetch !== undefined) transportOptions.fetch = config.fetch\n if (config.retryCount !== undefined) transportOptions.retryCount = config.retryCount\n if (config.retryDelay !== undefined) transportOptions.retryDelay = config.retryDelay\n if (config.timeout !== undefined) transportOptions.timeout = config.timeout\n if (config.headers !== undefined) transportOptions.headers = config.headers\n const transport = config.transport ?? http(baseUrl, transportOptions)\n return {\n baseUrl: transport.baseUrl,\n transport,\n transactions: createTransactionsResource(transport),\n accounts: createAccountsResource(transport),\n tokens: createTokensResource(transport),\n balances: createBalancesResource(transport),\n }\n}\n","import type { Transport } from \"./transport.js\"\n\nexport interface PaginateOptions {\n maxPages?: number\n}\n\n/** Async-iterate a list endpoint by following links.next verbatim until null. */\nexport async function* paginate<T>(\n transport: Transport,\n firstPath: string,\n select: (page: unknown) => T[],\n options: PaginateOptions = {},\n): AsyncGenerator<T, void, unknown> {\n const maxPages = options.maxPages ?? 1000\n let path: string | null = firstPath\n let pages = 0\n while (path && pages < maxPages) {\n const page: unknown = await transport.get(path)\n for (const item of select(page)) yield item\n path = (page as { links?: { next: string | null } }).links?.next ?? null\n pages++\n }\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { HederaTimestamp, NetworkInput } from '@hbar-kit/core';
|
|
2
|
+
|
|
3
|
+
interface TransportOptions {
|
|
4
|
+
fetch?: typeof fetch;
|
|
5
|
+
retryCount?: number;
|
|
6
|
+
retryDelay?: number;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
interface Transport {
|
|
11
|
+
get(path: string): Promise<unknown>;
|
|
12
|
+
baseUrl: string;
|
|
13
|
+
}
|
|
14
|
+
declare function http(baseUrl: string, options?: TransportOptions): Transport;
|
|
15
|
+
|
|
16
|
+
interface RawTransfer {
|
|
17
|
+
account: string;
|
|
18
|
+
amount: bigint;
|
|
19
|
+
is_approval?: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface RawTokenTransfer {
|
|
22
|
+
token_id: string;
|
|
23
|
+
account: string;
|
|
24
|
+
amount: bigint;
|
|
25
|
+
is_approval?: boolean;
|
|
26
|
+
}
|
|
27
|
+
interface RawNftTransfer {
|
|
28
|
+
token_id: string;
|
|
29
|
+
sender_account_id: string | null;
|
|
30
|
+
receiver_account_id: string | null;
|
|
31
|
+
serial_number: bigint;
|
|
32
|
+
is_approval?: boolean;
|
|
33
|
+
}
|
|
34
|
+
interface RawTransaction {
|
|
35
|
+
transaction_id: string;
|
|
36
|
+
consensus_timestamp: string;
|
|
37
|
+
valid_start_timestamp?: string;
|
|
38
|
+
result: string;
|
|
39
|
+
name: string;
|
|
40
|
+
charged_tx_fee: bigint;
|
|
41
|
+
memo_base64: string;
|
|
42
|
+
node?: string;
|
|
43
|
+
nonce: number;
|
|
44
|
+
scheduled: boolean;
|
|
45
|
+
parent_consensus_timestamp: string | null;
|
|
46
|
+
transfers: RawTransfer[];
|
|
47
|
+
token_transfers: RawTokenTransfer[];
|
|
48
|
+
nft_transfers: RawNftTransfer[];
|
|
49
|
+
}
|
|
50
|
+
interface RawListLinks {
|
|
51
|
+
next: string | null;
|
|
52
|
+
}
|
|
53
|
+
interface RawTransactionList {
|
|
54
|
+
transactions: RawTransaction[];
|
|
55
|
+
links: RawListLinks;
|
|
56
|
+
}
|
|
57
|
+
interface RawToken {
|
|
58
|
+
token_id: string;
|
|
59
|
+
decimals: string | number;
|
|
60
|
+
symbol: string;
|
|
61
|
+
name: string;
|
|
62
|
+
type: string;
|
|
63
|
+
total_supply?: string;
|
|
64
|
+
max_supply?: string;
|
|
65
|
+
treasury_account_id?: string;
|
|
66
|
+
}
|
|
67
|
+
interface RawAccount {
|
|
68
|
+
account: string;
|
|
69
|
+
evm_address?: string;
|
|
70
|
+
deleted?: boolean;
|
|
71
|
+
balance: {
|
|
72
|
+
balance: bigint;
|
|
73
|
+
timestamp: string;
|
|
74
|
+
tokens: {
|
|
75
|
+
token_id: string;
|
|
76
|
+
balance: bigint;
|
|
77
|
+
}[];
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
interface RawStatus {
|
|
81
|
+
_status?: {
|
|
82
|
+
messages?: {
|
|
83
|
+
message: string;
|
|
84
|
+
}[];
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
interface Transfer {
|
|
88
|
+
account: string;
|
|
89
|
+
amount: bigint;
|
|
90
|
+
isApproval: boolean;
|
|
91
|
+
}
|
|
92
|
+
interface TokenTransfer {
|
|
93
|
+
tokenId: string;
|
|
94
|
+
account: string;
|
|
95
|
+
amount: bigint;
|
|
96
|
+
isApproval: boolean;
|
|
97
|
+
}
|
|
98
|
+
interface NftTransfer {
|
|
99
|
+
tokenId: string;
|
|
100
|
+
sender: string | null;
|
|
101
|
+
receiver: string | null;
|
|
102
|
+
serial: bigint;
|
|
103
|
+
isApproval: boolean;
|
|
104
|
+
}
|
|
105
|
+
interface Transaction {
|
|
106
|
+
transactionId: string;
|
|
107
|
+
consensusTimestamp: HederaTimestamp;
|
|
108
|
+
validStartTimestamp?: HederaTimestamp | undefined;
|
|
109
|
+
result: string;
|
|
110
|
+
name: string;
|
|
111
|
+
chargedTxFee: bigint;
|
|
112
|
+
memo: string;
|
|
113
|
+
nonce: number;
|
|
114
|
+
scheduled: boolean;
|
|
115
|
+
parentConsensusTimestamp: string | null;
|
|
116
|
+
transfers: Transfer[];
|
|
117
|
+
tokenTransfers: TokenTransfer[];
|
|
118
|
+
nftTransfers: NftTransfer[];
|
|
119
|
+
raw: RawTransaction;
|
|
120
|
+
}
|
|
121
|
+
interface Token {
|
|
122
|
+
tokenId: string;
|
|
123
|
+
decimals: number;
|
|
124
|
+
symbol: string;
|
|
125
|
+
name: string;
|
|
126
|
+
type: string;
|
|
127
|
+
totalSupply?: bigint | undefined;
|
|
128
|
+
maxSupply?: bigint | undefined;
|
|
129
|
+
treasuryAccountId?: string | undefined;
|
|
130
|
+
raw: RawToken;
|
|
131
|
+
}
|
|
132
|
+
interface AccountBalance {
|
|
133
|
+
accountId: string;
|
|
134
|
+
balance: bigint;
|
|
135
|
+
tokens: {
|
|
136
|
+
tokenId: string;
|
|
137
|
+
balance: bigint;
|
|
138
|
+
}[];
|
|
139
|
+
raw: RawAccount;
|
|
140
|
+
}
|
|
141
|
+
interface Page<T> {
|
|
142
|
+
items: T[];
|
|
143
|
+
next: string | null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
interface FindTransactionsParams {
|
|
147
|
+
accountId?: string;
|
|
148
|
+
transactionType?: string;
|
|
149
|
+
result?: "success" | "fail";
|
|
150
|
+
order?: "asc" | "desc";
|
|
151
|
+
limit?: number;
|
|
152
|
+
after?: Date | string;
|
|
153
|
+
before?: Date | string;
|
|
154
|
+
}
|
|
155
|
+
interface TransactionsResource {
|
|
156
|
+
find(params?: FindTransactionsParams): Promise<Page<Transaction>>;
|
|
157
|
+
get(transactionId: string): Promise<Transaction[]>;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
interface AccountsResource {
|
|
161
|
+
getBalance(accountId: string): Promise<AccountBalance>;
|
|
162
|
+
isAssociated(accountId: string, tokenId: string): Promise<boolean>;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
interface TokensResource {
|
|
166
|
+
get(tokenId: string): Promise<Token>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
interface BalancesResource {
|
|
170
|
+
get(accountId: string): Promise<{
|
|
171
|
+
accountId: string;
|
|
172
|
+
balance: bigint;
|
|
173
|
+
timestamp: string;
|
|
174
|
+
}>;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
interface MirrorClientConfig extends NetworkInput, TransportOptions {
|
|
178
|
+
transport?: Transport;
|
|
179
|
+
}
|
|
180
|
+
interface MirrorClient {
|
|
181
|
+
baseUrl: string;
|
|
182
|
+
transport: Transport;
|
|
183
|
+
transactions: TransactionsResource;
|
|
184
|
+
accounts: AccountsResource;
|
|
185
|
+
tokens: TokensResource;
|
|
186
|
+
balances: BalancesResource;
|
|
187
|
+
}
|
|
188
|
+
declare function createMirrorClient(config: MirrorClientConfig): MirrorClient;
|
|
189
|
+
|
|
190
|
+
interface PaginateOptions {
|
|
191
|
+
maxPages?: number;
|
|
192
|
+
}
|
|
193
|
+
/** Async-iterate a list endpoint by following links.next verbatim until null. */
|
|
194
|
+
declare function paginate<T>(transport: Transport, firstPath: string, select: (page: unknown) => T[], options?: PaginateOptions): AsyncGenerator<T, void, unknown>;
|
|
195
|
+
|
|
196
|
+
declare function normalizeTransaction(raw: RawTransaction): Transaction;
|
|
197
|
+
declare function normalizeToken(raw: RawToken): Token;
|
|
198
|
+
declare function normalizeAccountBalance(raw: RawAccount): AccountBalance;
|
|
199
|
+
/** Detect Mirror Node not-found: the _status envelope, or an empty transactions array. */
|
|
200
|
+
declare function isNotFound(body: unknown): boolean;
|
|
201
|
+
|
|
202
|
+
export { type AccountBalance, type FindTransactionsParams, type MirrorClient, type MirrorClientConfig, type NftTransfer, type Page, type RawAccount, type RawListLinks, type RawNftTransfer, type RawStatus, type RawToken, type RawTokenTransfer, type RawTransaction, type RawTransactionList, type RawTransfer, type Token, type TokenTransfer, type Transaction, type Transfer, type Transport, type TransportOptions, createMirrorClient, http, isNotFound, normalizeAccountBalance, normalizeToken, normalizeTransaction, paginate };
|