clanker-sdk 1.1.0 → 1.4.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/README.md CHANGED
@@ -21,7 +21,11 @@ We'll evaluate each request individually as we carefully scale our platform acce
21
21
  Create a `.env` file in your project root:
22
22
 
23
23
  ```bash
24
+ # Clanker API Key (required for token operations)
24
25
  CLANKER_API_KEY=your_api_key_here
26
+
27
+ # Dune Analytics API Key (required for market data)
28
+ DUNE_API_KEY=your_dune_api_key_here
25
29
  ```
26
30
 
27
31
  Copy the `.env.example` file to get started:
@@ -30,47 +34,45 @@ Copy the `.env.example` file to get started:
30
34
  cp .env.example .env
31
35
  ```
32
36
 
33
- Make sure to add your API key to the `.env` file and never commit it to version control.
37
+ Make sure to add your API keys to the `.env` file and never commit it to version control.
38
+
39
+ ### 3. Getting Your Dune API Key
40
+
41
+ To access market data features, you'll need a Dune Analytics API key:
42
+
43
+ 1. Visit [dune.xyz](https://dune.xyz) and sign up for an account
44
+ 2. Go to your [API Keys page](https://dune.com/settings/api)
45
+ 3. Create a new API key
46
+ 4. Add the key to your `.env` file as `DUNE_API_KEY`
47
+
48
+ Note: Dune API access requires a paid subscription. Check their [pricing page](https://dune.com/pricing) for more details.
34
49
 
35
- ### 3. Basic Usage
50
+ ### 4. Basic Usage
36
51
 
37
52
  ```typescript
38
53
  import * as dotenv from 'dotenv';
39
- import { ClankerSDK } from 'clanker-sdk';
40
- import { randomBytes } from 'crypto'; // Node.js built-in crypto module
54
+ import { ClankerSDK, MarketDataClient } from 'clanker-sdk';
41
55
 
42
56
  // Load environment variables
43
57
  dotenv.config();
44
58
 
45
- // Validate API key
46
- const API_KEY = process.env.CLANKER_API_KEY;
47
- if (!API_KEY) {
48
- throw new Error('Missing CLANKER_API_KEY in environment variables');
49
- }
59
+ // Initialize SDK for token operations
60
+ const clanker = new ClankerSDK(process.env.CLANKER_API_KEY);
50
61
 
51
- // Generate a unique 32-character request key for idempotency
52
- function generateRequestKey(): string {
53
- return randomBytes(16).toString('hex'); // Generates a 32-character hex string
54
- }
62
+ // Initialize market data client for analytics
63
+ const marketData = new MarketDataClient(process.env.DUNE_API_KEY);
55
64
 
56
- // Initialize SDK
57
- const clanker = new ClankerSDK(API_KEY);
58
-
59
- // Deploy a token with custom splits (requires requestKey)
60
- const token = await clanker.deployTokenWithSplits({
65
+ // Deploy a token
66
+ const token = await clanker.deployToken({
61
67
  name: "Community Token",
62
68
  symbol: "CMTY",
63
69
  image: "https://example.com/token.png",
64
70
  requestorAddress: "0x1234567890123456789012345678901234567890", // Address receiving 40% creator rewards
65
- requestKey: generateRequestKey(), // Required for preventing duplicate deployments
66
- splitAddress: "0x935Ce0B6bBE179B45061BD5477A4BBA304fc3FFe"
67
71
  });
68
- ```
69
72
 
70
- ## Important Notes
71
-
72
- - **requestKey**: A unique 32-character string required for custom deployments (like splits) to prevent duplicate tokens (idempotency check)
73
- - **requestorAddress**: The address where 40% of creator rewards will be sent
73
+ // Get market data for your tokens
74
+ const marketStats = await marketData.getClankerDictionary();
75
+ ```
74
76
 
75
77
  ## Features
76
78
 
@@ -79,6 +81,45 @@ const token = await clanker.deployTokenWithSplits({
79
81
  - 📊 Rewards Tracking
80
82
  - 🔒 Type-safe API
81
83
  - 📝 Full TypeScript Support
84
+ - 📈 Market Data Analytics
85
+
86
+ ## Market Data Features
87
+
88
+ The SDK provides access to comprehensive market data through Dune Analytics integration:
89
+
90
+ ### Clanker Dictionary
91
+ Get detailed information about all Clanker tokens:
92
+ ```typescript
93
+ const dictionary = await marketData.getClankerDictionary();
94
+ // Returns: Array of tokens with market cap, volume, and liquidity data
95
+ ```
96
+
97
+ ### DEX Pair Statistics
98
+ Get detailed DEX pair statistics for any token:
99
+ ```typescript
100
+ const dexStats = await marketData.getDexPairStats(
101
+ 'ethereum', // Chain name (ethereum, arbitrum, etc.)
102
+ '0x1234...' // Optional: Token address to filter by
103
+ );
104
+ // Returns: Detailed DEX pair statistics including:
105
+ // - Trading volumes (24h, 7d, 30d)
106
+ // - Liquidity
107
+ // - Volume/Liquidity ratios
108
+ ```
109
+
110
+ Supported chains for DEX stats:
111
+ - ethereum
112
+ - arbitrum
113
+ - base
114
+ - bnb
115
+ - celo
116
+ - fantom
117
+ - gnosis
118
+ - optimism
119
+ - polygon
120
+ - scroll
121
+ - zk_sync
122
+ - solana
82
123
 
83
124
  ## Examples
84
125
 
@@ -86,12 +127,14 @@ Check out the `examples/` directory for more usage examples:
86
127
 
87
128
  - Token Deployment (`examples/token-deployment.ts`)
88
129
  - Rewards and Fees (`examples/rewards-and-fees.ts`)
130
+ - Market Data (`examples/market-data.ts`)
89
131
 
90
132
  Run examples using:
91
133
 
92
134
  ```bash
93
135
  npm run example:deploy # Run token deployment example
94
136
  npm run example:rewards # Run rewards tracking example
137
+ npm run example:market # Run market data example
95
138
  npm run example # Run all examples
96
139
  ```
97
140
 
package/dist/index.d.mts CHANGED
@@ -67,4 +67,37 @@ declare class ClankerSDK {
67
67
  private validateDeployOptions;
68
68
  }
69
69
 
70
- export { ClankerError, ClankerSDK, type DeployTokenOptions, type DeployTokenWithSplitsOptions, type DeployedToken, type DeployedTokensResponse, type EstimatedRewardsResponse, type Token, type UncollectedFeesResponse, ClankerSDK as default };
70
+ interface ClankerMarketData {
71
+ name: string;
72
+ symbol: string;
73
+ marketCap?: number;
74
+ volume24h?: number;
75
+ volume7d?: number;
76
+ liquidity?: number;
77
+ }
78
+ declare class MarketDataClient {
79
+ private readonly dune;
80
+ private readonly apiKey;
81
+ private readonly DICTIONARY_QUERY_ID;
82
+ constructor(duneApiKey: string);
83
+ /**
84
+ * Get market data from the materialized view
85
+ */
86
+ getClankerDictionary(): Promise<ClankerMarketData[]>;
87
+ /**
88
+ * Get DEX pair stats for a specific chain
89
+ * @param chain - The blockchain to query (e.g., 'ethereum', 'arbitrum', etc.)
90
+ * @param tokenAddress - Optional token address to filter by
91
+ */
92
+ getDexPairStats(chain: string, tokenAddress?: string): Promise<any>;
93
+ /**
94
+ * Transform raw dictionary data into a standardized format
95
+ */
96
+ private transformDictionaryData;
97
+ /**
98
+ * Filter DEX pairs by token address
99
+ */
100
+ private filterPairsByToken;
101
+ }
102
+
103
+ export { ClankerError, type ClankerMarketData, ClankerSDK, type DeployTokenOptions, type DeployTokenWithSplitsOptions, type DeployedToken, type DeployedTokensResponse, type EstimatedRewardsResponse, MarketDataClient, type Token, type UncollectedFeesResponse, ClankerSDK as default };
package/dist/index.d.ts CHANGED
@@ -67,4 +67,37 @@ declare class ClankerSDK {
67
67
  private validateDeployOptions;
68
68
  }
69
69
 
70
- export { ClankerError, ClankerSDK, type DeployTokenOptions, type DeployTokenWithSplitsOptions, type DeployedToken, type DeployedTokensResponse, type EstimatedRewardsResponse, type Token, type UncollectedFeesResponse, ClankerSDK as default };
70
+ interface ClankerMarketData {
71
+ name: string;
72
+ symbol: string;
73
+ marketCap?: number;
74
+ volume24h?: number;
75
+ volume7d?: number;
76
+ liquidity?: number;
77
+ }
78
+ declare class MarketDataClient {
79
+ private readonly dune;
80
+ private readonly apiKey;
81
+ private readonly DICTIONARY_QUERY_ID;
82
+ constructor(duneApiKey: string);
83
+ /**
84
+ * Get market data from the materialized view
85
+ */
86
+ getClankerDictionary(): Promise<ClankerMarketData[]>;
87
+ /**
88
+ * Get DEX pair stats for a specific chain
89
+ * @param chain - The blockchain to query (e.g., 'ethereum', 'arbitrum', etc.)
90
+ * @param tokenAddress - Optional token address to filter by
91
+ */
92
+ getDexPairStats(chain: string, tokenAddress?: string): Promise<any>;
93
+ /**
94
+ * Transform raw dictionary data into a standardized format
95
+ */
96
+ private transformDictionaryData;
97
+ /**
98
+ * Filter DEX pairs by token address
99
+ */
100
+ private filterPairsByToken;
101
+ }
102
+
103
+ export { ClankerError, type ClankerMarketData, ClankerSDK, type DeployTokenOptions, type DeployTokenWithSplitsOptions, type DeployedToken, type DeployedTokensResponse, type EstimatedRewardsResponse, MarketDataClient, type Token, type UncollectedFeesResponse, ClankerSDK as default };
package/dist/index.js CHANGED
@@ -32,6 +32,7 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  ClankerError: () => ClankerError,
34
34
  ClankerSDK: () => ClankerSDK,
35
+ MarketDataClient: () => MarketDataClient,
35
36
  default: () => ClankerSDK
36
37
  });
37
38
  module.exports = __toCommonJS(index_exports);
@@ -164,8 +165,92 @@ var ClankerSDK = class {
164
165
  }
165
166
  }
166
167
  };
168
+
169
+ // src/MarketData.ts
170
+ var import_client_sdk = require("@duneanalytics/client-sdk");
171
+ var MarketDataClient = class {
172
+ // Your materialized view query ID
173
+ constructor(duneApiKey) {
174
+ this.DICTIONARY_QUERY_ID = 4405741;
175
+ if (!duneApiKey) {
176
+ throw new ClankerError("Dune API key is required for market data");
177
+ }
178
+ this.apiKey = duneApiKey;
179
+ this.dune = new import_client_sdk.DuneClient(duneApiKey);
180
+ }
181
+ /**
182
+ * Get market data from the materialized view
183
+ */
184
+ async getClankerDictionary() {
185
+ try {
186
+ const result = await this.dune.getLatestResult({ queryId: this.DICTIONARY_QUERY_ID });
187
+ if (!result?.result?.rows) {
188
+ throw new ClankerError("No data returned from Dune");
189
+ }
190
+ return this.transformDictionaryData(result.result.rows);
191
+ } catch (error) {
192
+ if (error instanceof Error) {
193
+ throw new ClankerError(`Failed to fetch Clanker dictionary: ${error.message}`);
194
+ }
195
+ throw new ClankerError("Failed to fetch Clanker dictionary");
196
+ }
197
+ }
198
+ /**
199
+ * Get DEX pair stats for a specific chain
200
+ * @param chain - The blockchain to query (e.g., 'ethereum', 'arbitrum', etc.)
201
+ * @param tokenAddress - Optional token address to filter by
202
+ */
203
+ async getDexPairStats(chain, tokenAddress) {
204
+ const url = `https://api.dune.com/api/v1/dex/pairs/${chain}`;
205
+ const options = {
206
+ method: "GET",
207
+ headers: {
208
+ "X-Dune-Api-Key": this.apiKey
209
+ }
210
+ };
211
+ try {
212
+ const response = await fetch(url, options);
213
+ if (!response.ok) {
214
+ throw new Error(`HTTP error! status: ${response.status}`);
215
+ }
216
+ const data = await response.json();
217
+ if (tokenAddress) {
218
+ return this.filterPairsByToken(data, tokenAddress);
219
+ }
220
+ return data;
221
+ } catch (error) {
222
+ if (error instanceof Error) {
223
+ throw new ClankerError(`Failed to fetch DEX pair stats: ${error.message}`);
224
+ }
225
+ throw new ClankerError("Failed to fetch DEX pair stats");
226
+ }
227
+ }
228
+ /**
229
+ * Transform raw dictionary data into a standardized format
230
+ */
231
+ transformDictionaryData(rows) {
232
+ return rows.map((row) => ({
233
+ name: row.name || "",
234
+ symbol: row.symbol || "",
235
+ marketCap: row.market_cap || void 0,
236
+ volume24h: row.volume_24h || void 0,
237
+ volume7d: row.volume_7d || void 0,
238
+ liquidity: row.liquidity || void 0
239
+ }));
240
+ }
241
+ /**
242
+ * Filter DEX pairs by token address
243
+ */
244
+ filterPairsByToken(data, tokenAddress) {
245
+ const rows = data?.result?.rows || [];
246
+ return rows.filter(
247
+ (pair) => pair.token_a_address?.toLowerCase() === tokenAddress.toLowerCase() || pair.token_b_address?.toLowerCase() === tokenAddress.toLowerCase()
248
+ );
249
+ }
250
+ };
167
251
  // Annotate the CommonJS export names for ESM import in node:
168
252
  0 && (module.exports = {
169
253
  ClankerError,
170
- ClankerSDK
254
+ ClankerSDK,
255
+ MarketDataClient
171
256
  });
package/dist/index.mjs CHANGED
@@ -126,8 +126,92 @@ var ClankerSDK = class {
126
126
  }
127
127
  }
128
128
  };
129
+
130
+ // src/MarketData.ts
131
+ import { DuneClient } from "@duneanalytics/client-sdk";
132
+ var MarketDataClient = class {
133
+ // Your materialized view query ID
134
+ constructor(duneApiKey) {
135
+ this.DICTIONARY_QUERY_ID = 4405741;
136
+ if (!duneApiKey) {
137
+ throw new ClankerError("Dune API key is required for market data");
138
+ }
139
+ this.apiKey = duneApiKey;
140
+ this.dune = new DuneClient(duneApiKey);
141
+ }
142
+ /**
143
+ * Get market data from the materialized view
144
+ */
145
+ async getClankerDictionary() {
146
+ try {
147
+ const result = await this.dune.getLatestResult({ queryId: this.DICTIONARY_QUERY_ID });
148
+ if (!result?.result?.rows) {
149
+ throw new ClankerError("No data returned from Dune");
150
+ }
151
+ return this.transformDictionaryData(result.result.rows);
152
+ } catch (error) {
153
+ if (error instanceof Error) {
154
+ throw new ClankerError(`Failed to fetch Clanker dictionary: ${error.message}`);
155
+ }
156
+ throw new ClankerError("Failed to fetch Clanker dictionary");
157
+ }
158
+ }
159
+ /**
160
+ * Get DEX pair stats for a specific chain
161
+ * @param chain - The blockchain to query (e.g., 'ethereum', 'arbitrum', etc.)
162
+ * @param tokenAddress - Optional token address to filter by
163
+ */
164
+ async getDexPairStats(chain, tokenAddress) {
165
+ const url = `https://api.dune.com/api/v1/dex/pairs/${chain}`;
166
+ const options = {
167
+ method: "GET",
168
+ headers: {
169
+ "X-Dune-Api-Key": this.apiKey
170
+ }
171
+ };
172
+ try {
173
+ const response = await fetch(url, options);
174
+ if (!response.ok) {
175
+ throw new Error(`HTTP error! status: ${response.status}`);
176
+ }
177
+ const data = await response.json();
178
+ if (tokenAddress) {
179
+ return this.filterPairsByToken(data, tokenAddress);
180
+ }
181
+ return data;
182
+ } catch (error) {
183
+ if (error instanceof Error) {
184
+ throw new ClankerError(`Failed to fetch DEX pair stats: ${error.message}`);
185
+ }
186
+ throw new ClankerError("Failed to fetch DEX pair stats");
187
+ }
188
+ }
189
+ /**
190
+ * Transform raw dictionary data into a standardized format
191
+ */
192
+ transformDictionaryData(rows) {
193
+ return rows.map((row) => ({
194
+ name: row.name || "",
195
+ symbol: row.symbol || "",
196
+ marketCap: row.market_cap || void 0,
197
+ volume24h: row.volume_24h || void 0,
198
+ volume7d: row.volume_7d || void 0,
199
+ liquidity: row.liquidity || void 0
200
+ }));
201
+ }
202
+ /**
203
+ * Filter DEX pairs by token address
204
+ */
205
+ filterPairsByToken(data, tokenAddress) {
206
+ const rows = data?.result?.rows || [];
207
+ return rows.filter(
208
+ (pair) => pair.token_a_address?.toLowerCase() === tokenAddress.toLowerCase() || pair.token_b_address?.toLowerCase() === tokenAddress.toLowerCase()
209
+ );
210
+ }
211
+ };
129
212
  export {
130
213
  ClankerError,
131
214
  ClankerSDK,
215
+ MarketDataClient,
132
216
  ClankerSDK as default
133
217
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clanker-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.4.0",
4
4
  "description": "A lightweight TypeScript SDK for interacting with the Clanker API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -17,7 +17,8 @@
17
17
  "prepare": "npm run build",
18
18
  "example:deploy": "ts-node examples/token-deployment.ts",
19
19
  "example:rewards": "ts-node examples/rewards-and-fees.ts",
20
- "example": "npm run example:deploy && npm run example:rewards"
20
+ "example:market": "ts-node examples/market-data.ts",
21
+ "example": "npm run example:deploy && npm run example:rewards && npm run example:market"
21
22
  },
22
23
  "publishConfig": {
23
24
  "access": "public",
@@ -43,6 +44,7 @@
43
44
  "author": "Clanker Team",
44
45
  "license": "ISC",
45
46
  "dependencies": {
47
+ "@duneanalytics/client-sdk": "^0.2.5",
46
48
  "axios": "^1.6.7"
47
49
  },
48
50
  "devDependencies": {