glassnode-api 0.1.0 → 0.1.4
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/README.md +16 -10
- package/dist/examples/metadata.validation.d.ts +1 -0
- package/dist/examples/metadata.validation.js +126 -0
- package/dist/examples/metric.dump.d.ts +1 -0
- package/dist/examples/metric.dump.js +28 -0
- package/dist/{glassnode-api.js → src/glassnode-api.js} +2 -1
- package/dist/{types → src/types}/metadata.d.ts +6 -6
- package/dist/{types → src/types}/metadata.js +4 -1
- package/package.json +6 -2
- package/dist/types/response.d.ts +0 -39
- package/dist/types/response.js +0 -14
- /package/dist/{glassnode-api.d.ts → src/glassnode-api.d.ts} +0 -0
- /package/dist/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/{index.js → src/index.js} +0 -0
- /package/dist/{types → src/types}/config.d.ts +0 -0
- /package/dist/{types → src/types}/config.js +0 -0
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ A Node.js client for the [Glassnode API](https://docs.glassnode.com/).
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
npm install glassnode-api
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
@@ -43,30 +43,36 @@ async function getMetrics() {
|
|
|
43
43
|
|
|
44
44
|
## Examples
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
Explore our [detailed examples](./examples/README.md) to learn how to use the Glassnode API client effectively. The examples demonstrate:
|
|
47
|
+
|
|
48
|
+
- Fetching and validating asset metadata
|
|
49
|
+
- Working with metric lists and metadata
|
|
50
|
+
- Calling metrics with parameters
|
|
51
|
+
|
|
52
|
+
To run the examples:
|
|
47
53
|
|
|
48
54
|
1. Navigate to the examples directory
|
|
49
|
-
2. Create a `.env` file
|
|
50
|
-
3. Install dependencies with `
|
|
51
|
-
4. Run an example with `
|
|
55
|
+
2. Create a `.env` file with your API key: `GLASSNODE_API_KEY=your_key_here`
|
|
56
|
+
3. Install dependencies with `npm install`
|
|
57
|
+
4. Run an example with `npx ts-node metadata.validation.ts`
|
|
52
58
|
|
|
53
59
|
## Development
|
|
54
60
|
|
|
55
61
|
```bash
|
|
56
62
|
# Install dependencies
|
|
57
|
-
|
|
63
|
+
npm install
|
|
58
64
|
|
|
59
65
|
# Build the project
|
|
60
|
-
|
|
66
|
+
npm run build
|
|
61
67
|
|
|
62
68
|
# Run tests
|
|
63
|
-
|
|
69
|
+
npm test
|
|
64
70
|
|
|
65
71
|
# Lint code
|
|
66
|
-
|
|
72
|
+
npm run lint
|
|
67
73
|
|
|
68
74
|
# Format code
|
|
69
|
-
|
|
75
|
+
npm run format
|
|
70
76
|
```
|
|
71
77
|
|
|
72
78
|
## License
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const src_1 = require("../src");
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
require("dotenv/config");
|
|
6
|
+
// Create an instance of the API client
|
|
7
|
+
const api = new src_1.GlassnodeAPI({
|
|
8
|
+
apiKey: process.env.GLASSNODE_API_KEY || '', // Get API key from .env file
|
|
9
|
+
});
|
|
10
|
+
async function fetchAssetMetadata() {
|
|
11
|
+
try {
|
|
12
|
+
// Get asset metadata
|
|
13
|
+
console.log('Fetching asset metadata...');
|
|
14
|
+
const assetMetadata = await api.getAssetMetadata();
|
|
15
|
+
// Show total number of assets
|
|
16
|
+
console.log(`Found ${assetMetadata.length} assets in total`);
|
|
17
|
+
// Custom validation: Check if USDC is present in the response
|
|
18
|
+
const USDCSchema = zod_1.z.object({
|
|
19
|
+
symbol: zod_1.z.literal('USDC'),
|
|
20
|
+
name: zod_1.z.literal('USDC'),
|
|
21
|
+
asset_type: zod_1.z.literal('TOKEN'),
|
|
22
|
+
});
|
|
23
|
+
// Create a refine function that looks for USDC
|
|
24
|
+
const usdc = assetMetadata.find((asset) => asset.symbol === 'USDC');
|
|
25
|
+
if (usdc) {
|
|
26
|
+
try {
|
|
27
|
+
USDCSchema.parse(usdc);
|
|
28
|
+
console.log('✅ USDC validation successful');
|
|
29
|
+
// Print 3 first blockchains for USDC
|
|
30
|
+
console.log('First 3 blockchains for USDC:');
|
|
31
|
+
usdc.blockchains.slice(0, 3).forEach((blockchain) => {
|
|
32
|
+
console.log(` - ${blockchain.blockchain} - ${blockchain.address}`);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (error instanceof zod_1.z.ZodError) {
|
|
37
|
+
console.error('❌ Schema validation failed:', error.errors);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.log('❌ USDC not found in response');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error('Error fetching asset metadata:', error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function fetchMetricList() {
|
|
53
|
+
try {
|
|
54
|
+
console.log('\nFetching metric list...');
|
|
55
|
+
const metricList = await api.getMetricList();
|
|
56
|
+
// Display basic metrics information
|
|
57
|
+
console.log(`Found ${metricList.length} metrics in total`);
|
|
58
|
+
// Check for market metrics
|
|
59
|
+
const marketMetrics = metricList.filter((metric) => metric.startsWith('/market/'));
|
|
60
|
+
if (marketMetrics.length > 0) {
|
|
61
|
+
console.log(`✅ Found ${marketMetrics.length} market metrics`);
|
|
62
|
+
console.log(`First 3 market metrics:`);
|
|
63
|
+
marketMetrics.slice(0, 3).forEach((metric) => console.log(` - ${metric}`));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log('❌ No market metrics found');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error('Error fetching metric list:', error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function fetchExchangeBalanceMetadata() {
|
|
74
|
+
try {
|
|
75
|
+
console.log('\nFetching exchange balance metadata...');
|
|
76
|
+
const metricPath = '/distribution/balance_exchanges';
|
|
77
|
+
const metadata = await api.getMetricMetadata(metricPath);
|
|
78
|
+
console.log('✅ Exchange balance metadata:');
|
|
79
|
+
console.log(` Path: ${metadata.path}`);
|
|
80
|
+
console.log(` Tier: ${metadata.tier}`);
|
|
81
|
+
console.log(` Modified: ${metadata.modified?.toISOString()}`);
|
|
82
|
+
// Display available parameters
|
|
83
|
+
console.log('\nAvailable parameters:');
|
|
84
|
+
// Only print the firt 3 values per parameter
|
|
85
|
+
Object.entries(metadata.parameters).forEach(([key, values]) => {
|
|
86
|
+
console.log(` ${key}: ${values.slice(0, 3).join(', ')}`);
|
|
87
|
+
});
|
|
88
|
+
// Display documentation links
|
|
89
|
+
if (metadata.refs.docs) {
|
|
90
|
+
console.log(`\nDocumentation: ${metadata.refs.docs}`);
|
|
91
|
+
}
|
|
92
|
+
if (metadata.refs.studio) {
|
|
93
|
+
console.log(`Studio: ${metadata.refs.studio}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error('Error fetching exchange balance metadata:', error);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function fetchExchangeBalanceWithParams() {
|
|
101
|
+
try {
|
|
102
|
+
console.log('\nFetching exchange balance metadata with specific parameters...');
|
|
103
|
+
const metricPath = '/distribution/balance_exchanges';
|
|
104
|
+
const params = { a: 'BTC' };
|
|
105
|
+
const metadata = await api.getMetricMetadata(metricPath, params);
|
|
106
|
+
console.log('✅ Exchange balance metadata for BTC:');
|
|
107
|
+
console.log(` Path: ${metadata.path}`);
|
|
108
|
+
console.log(` Tier: ${metadata.tier}`);
|
|
109
|
+
// Display queried parameters
|
|
110
|
+
console.log('\nQueried parameters:');
|
|
111
|
+
Object.entries(metadata.queried).forEach(([key, value]) => {
|
|
112
|
+
console.log(` ${key}: ${value}`);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error('Error fetching exchange balance metadata with parameters:', error);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Execute the examples
|
|
120
|
+
async function runExamples() {
|
|
121
|
+
await fetchAssetMetadata();
|
|
122
|
+
await fetchMetricList();
|
|
123
|
+
await fetchExchangeBalanceMetadata();
|
|
124
|
+
await fetchExchangeBalanceWithParams();
|
|
125
|
+
}
|
|
126
|
+
runExamples();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const src_1 = require("../src");
|
|
4
|
+
require("dotenv/config");
|
|
5
|
+
// Create an instance of the API client
|
|
6
|
+
const api = new src_1.GlassnodeAPI({
|
|
7
|
+
apiKey: process.env.GLASSNODE_API_KEY || '', // Get API key from .env file
|
|
8
|
+
});
|
|
9
|
+
// Execute the examples
|
|
10
|
+
async function runExamples() {
|
|
11
|
+
//const assetMetadata = await api.getAssetMetadata();
|
|
12
|
+
const metricList = await api.getMetricList();
|
|
13
|
+
for (const metric of metricList.slice(0, 10)) {
|
|
14
|
+
const metricMetadata = await api.getMetricMetadata(metric);
|
|
15
|
+
const params = metricMetadata.parameters;
|
|
16
|
+
// create params object from params array
|
|
17
|
+
const paramsObject = {};
|
|
18
|
+
for (const param of Object.keys(params)) {
|
|
19
|
+
// Fix: params[param] is an array of strings, not an object with values property
|
|
20
|
+
if (Array.isArray(params[param]) && params[param].length > 0) {
|
|
21
|
+
paramsObject[param] = params[param][0];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const result = (await api.callMetric(metric, paramsObject));
|
|
25
|
+
console.log(result[0]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
runExamples();
|
|
@@ -32,6 +32,7 @@ class GlassnodeAPI {
|
|
|
32
32
|
api_key: this.apiKey,
|
|
33
33
|
});
|
|
34
34
|
const url = `${this.apiUrl}${endpoint}?${queryParams}`;
|
|
35
|
+
console.log(' API call:', url);
|
|
35
36
|
try {
|
|
36
37
|
const response = await fetch(url);
|
|
37
38
|
if (!response.ok) {
|
|
@@ -85,7 +86,7 @@ class GlassnodeAPI {
|
|
|
85
86
|
* @returns Promise resolving to the response data
|
|
86
87
|
*/
|
|
87
88
|
async callMetric(metricPath, params = {}) {
|
|
88
|
-
const response = await this.request('
|
|
89
|
+
const response = await this.request('/v1/metrics' + metricPath, { ...params, f: 'json' });
|
|
89
90
|
return response;
|
|
90
91
|
}
|
|
91
92
|
}
|
|
@@ -252,7 +252,7 @@ export declare const MetricMetadataSchema: z.ZodObject<{
|
|
|
252
252
|
/**
|
|
253
253
|
* The last date that the metadata was updated
|
|
254
254
|
*/
|
|
255
|
-
modified: z.ZodEffects<z.ZodNumber
|
|
255
|
+
modified: z.ZodEffects<z.ZodOptional<z.ZodNumber>, Date | undefined, number | undefined>;
|
|
256
256
|
/**
|
|
257
257
|
* Next parameter for the metric
|
|
258
258
|
*/
|
|
@@ -281,24 +281,24 @@ export declare const MetricMetadataSchema: z.ZodObject<{
|
|
|
281
281
|
}, "strip", z.ZodTypeAny, {
|
|
282
282
|
path: string;
|
|
283
283
|
tier: number;
|
|
284
|
-
modified: Date;
|
|
285
284
|
refs: {
|
|
286
285
|
docs?: string | undefined;
|
|
287
286
|
studio?: string | undefined;
|
|
288
287
|
};
|
|
289
288
|
queried: Record<string, any>;
|
|
290
289
|
parameters: Record<string, string[]>;
|
|
290
|
+
modified?: Date | undefined;
|
|
291
291
|
next_param?: string | undefined;
|
|
292
292
|
}, {
|
|
293
293
|
path: string;
|
|
294
294
|
tier: number;
|
|
295
|
-
modified: number;
|
|
296
295
|
refs: {
|
|
297
296
|
docs?: string | undefined;
|
|
298
297
|
studio?: string | undefined;
|
|
299
298
|
};
|
|
300
299
|
queried: Record<string, any>;
|
|
301
300
|
parameters: Record<string, string[]>;
|
|
301
|
+
modified?: number | undefined;
|
|
302
302
|
next_param?: string | undefined;
|
|
303
303
|
}>;
|
|
304
304
|
/**
|
|
@@ -320,7 +320,7 @@ export declare const MetricMetadataResponseSchema: z.ZodObject<{
|
|
|
320
320
|
/**
|
|
321
321
|
* The last date that the metadata was updated
|
|
322
322
|
*/
|
|
323
|
-
modified: z.ZodEffects<z.ZodNumber
|
|
323
|
+
modified: z.ZodEffects<z.ZodOptional<z.ZodNumber>, Date | undefined, number | undefined>;
|
|
324
324
|
/**
|
|
325
325
|
* Next parameter for the metric
|
|
326
326
|
*/
|
|
@@ -349,24 +349,24 @@ export declare const MetricMetadataResponseSchema: z.ZodObject<{
|
|
|
349
349
|
}, "strip", z.ZodTypeAny, {
|
|
350
350
|
path: string;
|
|
351
351
|
tier: number;
|
|
352
|
-
modified: Date;
|
|
353
352
|
refs: {
|
|
354
353
|
docs?: string | undefined;
|
|
355
354
|
studio?: string | undefined;
|
|
356
355
|
};
|
|
357
356
|
queried: Record<string, any>;
|
|
358
357
|
parameters: Record<string, string[]>;
|
|
358
|
+
modified?: Date | undefined;
|
|
359
359
|
next_param?: string | undefined;
|
|
360
360
|
}, {
|
|
361
361
|
path: string;
|
|
362
362
|
tier: number;
|
|
363
|
-
modified: number;
|
|
364
363
|
refs: {
|
|
365
364
|
docs?: string | undefined;
|
|
366
365
|
studio?: string | undefined;
|
|
367
366
|
};
|
|
368
367
|
queried: Record<string, any>;
|
|
369
368
|
parameters: Record<string, string[]>;
|
|
369
|
+
modified?: number | undefined;
|
|
370
370
|
next_param?: string | undefined;
|
|
371
371
|
}>;
|
|
372
372
|
/**
|
|
@@ -90,7 +90,10 @@ exports.MetricMetadataSchema = zod_1.z.object({
|
|
|
90
90
|
/**
|
|
91
91
|
* The last date that the metadata was updated
|
|
92
92
|
*/
|
|
93
|
-
modified: zod_1.z
|
|
93
|
+
modified: zod_1.z
|
|
94
|
+
.number()
|
|
95
|
+
.optional()
|
|
96
|
+
.transform((val) => (val ? new Date(val * 1000) : undefined)),
|
|
94
97
|
/**
|
|
95
98
|
* Next parameter for the metric
|
|
96
99
|
*/
|
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glassnode-api",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Node.js client for the Glassnode API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist"
|
|
9
9
|
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/planadecu/glassnode-api-node.git"
|
|
13
|
+
},
|
|
10
14
|
"scripts": {
|
|
11
15
|
"build": "tsc",
|
|
12
16
|
"test": "jest",
|
|
@@ -34,7 +38,7 @@
|
|
|
34
38
|
"prettier": "^3.5.3",
|
|
35
39
|
"ts-jest": "^29.3.2",
|
|
36
40
|
"typescript": "^5.8.3",
|
|
37
|
-
"typescript-eslint": "^8.32.
|
|
41
|
+
"typescript-eslint": "^8.32.1"
|
|
38
42
|
},
|
|
39
43
|
"lint-staged": {
|
|
40
44
|
"*.{js,ts,mjs}": [
|
package/dist/types/response.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
/**
|
|
3
|
-
* Generic API response schema
|
|
4
|
-
*/
|
|
5
|
-
export declare const ResponseSchema: <T extends z.ZodTypeAny>(dataSchema: T) => z.ZodObject<{
|
|
6
|
-
/**
|
|
7
|
-
* Response data
|
|
8
|
-
*/
|
|
9
|
-
data: T;
|
|
10
|
-
}, "strip", z.ZodTypeAny, z.objectUtil.addQuestionMarks<z.baseObjectOutputType<{
|
|
11
|
-
/**
|
|
12
|
-
* Response data
|
|
13
|
-
*/
|
|
14
|
-
data: T;
|
|
15
|
-
}>, any> extends infer T_1 ? { [k in keyof T_1]: z.objectUtil.addQuestionMarks<z.baseObjectOutputType<{
|
|
16
|
-
/**
|
|
17
|
-
* Response data
|
|
18
|
-
*/
|
|
19
|
-
data: T;
|
|
20
|
-
}>, any>[k]; } : never, z.baseObjectInputType<{
|
|
21
|
-
/**
|
|
22
|
-
* Response data
|
|
23
|
-
*/
|
|
24
|
-
data: T;
|
|
25
|
-
}> extends infer T_2 ? { [k_1 in keyof T_2]: z.baseObjectInputType<{
|
|
26
|
-
/**
|
|
27
|
-
* Response data
|
|
28
|
-
*/
|
|
29
|
-
data: T;
|
|
30
|
-
}>[k_1]; } : never>;
|
|
31
|
-
/**
|
|
32
|
-
* Generic API response type
|
|
33
|
-
*/
|
|
34
|
-
export type Response<T> = {
|
|
35
|
-
/**
|
|
36
|
-
* Response data
|
|
37
|
-
*/
|
|
38
|
-
data: T;
|
|
39
|
-
};
|
package/dist/types/response.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ResponseSchema = void 0;
|
|
4
|
-
const zod_1 = require("zod");
|
|
5
|
-
/**
|
|
6
|
-
* Generic API response schema
|
|
7
|
-
*/
|
|
8
|
-
const ResponseSchema = (dataSchema) => zod_1.z.object({
|
|
9
|
-
/**
|
|
10
|
-
* Response data
|
|
11
|
-
*/
|
|
12
|
-
data: dataSchema
|
|
13
|
-
});
|
|
14
|
-
exports.ResponseSchema = ResponseSchema;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|