@cyberdrk/onchain 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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +135 -0
  3. package/dist/cli/program.d.ts +4 -0
  4. package/dist/cli/program.d.ts.map +1 -0
  5. package/dist/cli/program.js +43 -0
  6. package/dist/cli/program.js.map +1 -0
  7. package/dist/cli/setup-wizard.d.ts +7 -0
  8. package/dist/cli/setup-wizard.d.ts.map +1 -0
  9. package/dist/cli/setup-wizard.js +96 -0
  10. package/dist/cli/setup-wizard.js.map +1 -0
  11. package/dist/cli/shared.d.ts +35 -0
  12. package/dist/cli/shared.d.ts.map +1 -0
  13. package/dist/cli/shared.js +120 -0
  14. package/dist/cli/shared.js.map +1 -0
  15. package/dist/cli.d.ts +3 -0
  16. package/dist/cli.d.ts.map +1 -0
  17. package/dist/cli.js +10 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/commands/balance.d.ts +4 -0
  20. package/dist/commands/balance.d.ts.map +1 -0
  21. package/dist/commands/balance.js +141 -0
  22. package/dist/commands/balance.js.map +1 -0
  23. package/dist/commands/binance.d.ts +4 -0
  24. package/dist/commands/binance.d.ts.map +1 -0
  25. package/dist/commands/binance.js +129 -0
  26. package/dist/commands/binance.js.map +1 -0
  27. package/dist/commands/coinbase.d.ts +4 -0
  28. package/dist/commands/coinbase.d.ts.map +1 -0
  29. package/dist/commands/coinbase.js +122 -0
  30. package/dist/commands/coinbase.js.map +1 -0
  31. package/dist/commands/config.d.ts +4 -0
  32. package/dist/commands/config.d.ts.map +1 -0
  33. package/dist/commands/config.js +90 -0
  34. package/dist/commands/config.js.map +1 -0
  35. package/dist/commands/history.d.ts +4 -0
  36. package/dist/commands/history.d.ts.map +1 -0
  37. package/dist/commands/history.js +124 -0
  38. package/dist/commands/history.js.map +1 -0
  39. package/dist/commands/markets.d.ts +4 -0
  40. package/dist/commands/markets.d.ts.map +1 -0
  41. package/dist/commands/markets.js +59 -0
  42. package/dist/commands/markets.js.map +1 -0
  43. package/dist/commands/polymarket.d.ts +4 -0
  44. package/dist/commands/polymarket.d.ts.map +1 -0
  45. package/dist/commands/polymarket.js +180 -0
  46. package/dist/commands/polymarket.js.map +1 -0
  47. package/dist/commands/portfolio.d.ts +4 -0
  48. package/dist/commands/portfolio.d.ts.map +1 -0
  49. package/dist/commands/portfolio.js +162 -0
  50. package/dist/commands/portfolio.js.map +1 -0
  51. package/dist/commands/price.d.ts +4 -0
  52. package/dist/commands/price.d.ts.map +1 -0
  53. package/dist/commands/price.js +95 -0
  54. package/dist/commands/price.js.map +1 -0
  55. package/dist/commands/setup.d.ts +4 -0
  56. package/dist/commands/setup.d.ts.map +1 -0
  57. package/dist/commands/setup.js +47 -0
  58. package/dist/commands/setup.js.map +1 -0
  59. package/dist/commands/test.d.ts +4 -0
  60. package/dist/commands/test.d.ts.map +1 -0
  61. package/dist/commands/test.js +198 -0
  62. package/dist/commands/test.js.map +1 -0
  63. package/dist/index.d.ts +5 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +6 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/lib/browser-scraper.d.ts +39 -0
  68. package/dist/lib/browser-scraper.d.ts.map +1 -0
  69. package/dist/lib/browser-scraper.js +214 -0
  70. package/dist/lib/browser-scraper.js.map +1 -0
  71. package/dist/lib/config.d.ts +19 -0
  72. package/dist/lib/config.d.ts.map +1 -0
  73. package/dist/lib/config.js +52 -0
  74. package/dist/lib/config.js.map +1 -0
  75. package/dist/lib/credentials.d.ts +23 -0
  76. package/dist/lib/credentials.d.ts.map +1 -0
  77. package/dist/lib/credentials.js +49 -0
  78. package/dist/lib/credentials.js.map +1 -0
  79. package/dist/lib/mixins/binance.d.ts +12 -0
  80. package/dist/lib/mixins/binance.d.ts.map +1 -0
  81. package/dist/lib/mixins/binance.js +167 -0
  82. package/dist/lib/mixins/binance.js.map +1 -0
  83. package/dist/lib/mixins/coinbase.d.ts +11 -0
  84. package/dist/lib/mixins/coinbase.d.ts.map +1 -0
  85. package/dist/lib/mixins/coinbase.js +266 -0
  86. package/dist/lib/mixins/coinbase.js.map +1 -0
  87. package/dist/lib/mixins/coingecko.d.ts +10 -0
  88. package/dist/lib/mixins/coingecko.d.ts.map +1 -0
  89. package/dist/lib/mixins/coingecko.js +217 -0
  90. package/dist/lib/mixins/coingecko.js.map +1 -0
  91. package/dist/lib/mixins/coinmarketcap.d.ts +9 -0
  92. package/dist/lib/mixins/coinmarketcap.d.ts.map +1 -0
  93. package/dist/lib/mixins/coinmarketcap.js +142 -0
  94. package/dist/lib/mixins/coinmarketcap.js.map +1 -0
  95. package/dist/lib/mixins/debank.d.ts +21 -0
  96. package/dist/lib/mixins/debank.d.ts.map +1 -0
  97. package/dist/lib/mixins/debank.js +280 -0
  98. package/dist/lib/mixins/debank.js.map +1 -0
  99. package/dist/lib/mixins/helius.d.ts +12 -0
  100. package/dist/lib/mixins/helius.d.ts.map +1 -0
  101. package/dist/lib/mixins/helius.js +281 -0
  102. package/dist/lib/mixins/helius.js.map +1 -0
  103. package/dist/lib/mixins/polymarket.d.ts +13 -0
  104. package/dist/lib/mixins/polymarket.d.ts.map +1 -0
  105. package/dist/lib/mixins/polymarket.js +186 -0
  106. package/dist/lib/mixins/polymarket.js.map +1 -0
  107. package/dist/lib/onchain-client-base.d.ts +20 -0
  108. package/dist/lib/onchain-client-base.d.ts.map +1 -0
  109. package/dist/lib/onchain-client-base.js +45 -0
  110. package/dist/lib/onchain-client-base.js.map +1 -0
  111. package/dist/lib/onchain-client-types.d.ts +228 -0
  112. package/dist/lib/onchain-client-types.d.ts.map +1 -0
  113. package/dist/lib/onchain-client-types.js +2 -0
  114. package/dist/lib/onchain-client-types.js.map +1 -0
  115. package/dist/lib/onchain-client.d.ts +15 -0
  116. package/dist/lib/onchain-client.d.ts.map +1 -0
  117. package/dist/lib/onchain-client.js +13 -0
  118. package/dist/lib/onchain-client.js.map +1 -0
  119. package/dist/lib/output.d.ts +28 -0
  120. package/dist/lib/output.d.ts.map +1 -0
  121. package/dist/lib/output.js +94 -0
  122. package/dist/lib/output.js.map +1 -0
  123. package/dist/lib/utils/address.d.ts +26 -0
  124. package/dist/lib/utils/address.d.ts.map +1 -0
  125. package/dist/lib/utils/address.js +61 -0
  126. package/dist/lib/utils/address.js.map +1 -0
  127. package/dist/lib/utils/formatters.d.ts +42 -0
  128. package/dist/lib/utils/formatters.d.ts.map +1 -0
  129. package/dist/lib/utils/formatters.js +173 -0
  130. package/dist/lib/utils/formatters.js.map +1 -0
  131. package/package.json +77 -0
@@ -0,0 +1,214 @@
1
+ import { execSync, spawnSync } from 'node:child_process';
2
+ import { randomBytes } from 'node:crypto';
3
+ /**
4
+ * Generate a unique session name to avoid conflicts with corrupted default sessions.
5
+ */
6
+ function generateSessionName() {
7
+ return `onchain-${randomBytes(4).toString('hex')}`;
8
+ }
9
+ /**
10
+ * Execute an agent-browser command with a specific session and return the output.
11
+ */
12
+ function runAgentBrowser(session, args, timeoutMs = 30000) {
13
+ const result = spawnSync('agent-browser', ['--session', session, ...args], {
14
+ encoding: 'utf8',
15
+ timeout: timeoutMs,
16
+ stdio: ['pipe', 'pipe', 'pipe'],
17
+ });
18
+ if (result.error) {
19
+ throw result.error;
20
+ }
21
+ if (result.status !== 0) {
22
+ throw new Error(result.stderr || `agent-browser exited with code ${result.status}`);
23
+ }
24
+ return result.stdout;
25
+ }
26
+ /**
27
+ * Close browser session, ignoring errors.
28
+ */
29
+ function closeBrowser(session) {
30
+ try {
31
+ runAgentBrowser(session, ['close'], 5000);
32
+ }
33
+ catch {
34
+ // Ignore close errors
35
+ }
36
+ }
37
+ /**
38
+ * Check if agent-browser CLI is available.
39
+ */
40
+ export function isAgentBrowserAvailable() {
41
+ try {
42
+ execSync('which agent-browser', { encoding: 'utf8', stdio: 'pipe' });
43
+ return true;
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
49
+ // JavaScript to extract balance data from DeBank page
50
+ // Returns a plain object (agent-browser will JSON-stringify the result)
51
+ const DEBANK_EXTRACT_SCRIPT = `
52
+ (function() {
53
+ const text = document.body.innerText;
54
+ const totalMatch = text.match(/\\$[\\d,]+(?:\\.\\d+)?/);
55
+ const totalValueUsd = totalMatch ? parseFloat(totalMatch[0].replace(/[$,]/g, "")) : 0;
56
+
57
+ const tableStart = text.indexOf("Token\\nPrice\\nAmount\\nUSD Value");
58
+ const balances = [];
59
+ if (tableStart > -1) {
60
+ const tableText = text.substring(tableStart + "Token\\nPrice\\nAmount\\nUSD Value".length);
61
+ const lines = tableText.split("\\n").filter(l => l.trim());
62
+ let i = 0;
63
+ while (i < lines.length && balances.length < 100) {
64
+ const symbol = lines[i];
65
+ if (symbol.includes("Protocol") || symbol.includes("Show all") || symbol.includes("Unfold")) break;
66
+ if (i + 3 < lines.length) {
67
+ const priceStr = lines[i + 1];
68
+ const valueStr = lines[i + 3];
69
+ if (priceStr.startsWith("$") && valueStr.startsWith("$")) {
70
+ const amount = parseFloat(lines[i + 2].replace(/,/g, "")) || 0;
71
+ const valueUsd = parseFloat(valueStr.replace(/[$,]/g, "")) || 0;
72
+ balances.push({
73
+ symbol: symbol.replace(/\\s*\\([^)]*\\)/g, "").trim(),
74
+ amount,
75
+ valueUsd
76
+ });
77
+ i += 4;
78
+ } else i++;
79
+ } else break;
80
+ }
81
+ }
82
+ return {totalValueUsd, balances};
83
+ })()
84
+ `.trim();
85
+ // JavaScript to extract balance data from Solscan page
86
+ // Returns a plain object (agent-browser will JSON-stringify the result)
87
+ const SOLSCAN_EXTRACT_SCRIPT = `
88
+ (function() {
89
+ const text = document.body.innerText;
90
+
91
+ // Extract SOL balance
92
+ const solMatch = text.match(/(\\d+\\.?\\d*)\\s*SOL/);
93
+ const solBalance = solMatch ? parseFloat(solMatch[1]) : 0;
94
+
95
+ // Try to extract total value
96
+ const totalMatch = text.match(/\\$[\\d,]+(?:\\.\\d+)?/);
97
+ const totalValueUsd = totalMatch ? parseFloat(totalMatch[0].replace(/[$,]/g, "")) : 0;
98
+
99
+ const balances = [];
100
+
101
+ // Add SOL balance
102
+ if (solBalance > 0) {
103
+ balances.push({symbol: "SOL", amount: solBalance, valueUsd: null});
104
+ }
105
+
106
+ // Look for token table (Portfolio section)
107
+ const portfolioStart = text.indexOf("Token");
108
+ if (portfolioStart > -1) {
109
+ const portfolioText = text.substring(portfolioStart);
110
+ const lines = portfolioText.split("\\n").filter(l => l.trim());
111
+ let i = 0;
112
+ while (i < lines.length && balances.length < 100) {
113
+ const line = lines[i];
114
+ // Look for token symbols (uppercase letters)
115
+ if (/^[A-Z][A-Z0-9]{1,9}$/.test(line) && line !== "SOL") {
116
+ const symbol = line;
117
+ // Try to find amount and value in next lines
118
+ let amount = 0;
119
+ let valueUsd = null;
120
+ for (let j = 1; j <= 3 && i + j < lines.length; j++) {
121
+ const nextLine = lines[i + j];
122
+ if (/^[\\d,]+\\.?\\d*$/.test(nextLine.replace(/,/g, ""))) {
123
+ amount = parseFloat(nextLine.replace(/,/g, "")) || 0;
124
+ }
125
+ if (nextLine.startsWith("$")) {
126
+ valueUsd = parseFloat(nextLine.replace(/[$,]/g, "")) || null;
127
+ }
128
+ }
129
+ if (amount > 0 && !balances.some(b => b.symbol === symbol)) {
130
+ balances.push({symbol, amount, valueUsd});
131
+ }
132
+ }
133
+ i++;
134
+ }
135
+ }
136
+
137
+ return {totalValueUsd, balances};
138
+ })()
139
+ `.trim();
140
+ /**
141
+ * Scrape DeBank profile page for EVM wallet balances.
142
+ * Uses agent-browser CLI to navigate and extract data via JavaScript.
143
+ */
144
+ export async function scrapeDebankProfile(address, timeoutMs = 60000) {
145
+ const session = generateSessionName();
146
+ try {
147
+ const url = `https://debank.com/profile/${address}`;
148
+ // Open the page (this launches the browser)
149
+ runAgentBrowser(session, ['open', url], timeoutMs);
150
+ // Wait for JS to render (DeBank is heavy)
151
+ await new Promise((resolve) => setTimeout(resolve, 5000));
152
+ // Extract data using JavaScript evaluation
153
+ const output = runAgentBrowser(session, ['eval', DEBANK_EXTRACT_SCRIPT], timeoutMs);
154
+ // Parse the JSON output - agent-browser returns clean JSON when returning objects
155
+ const data = JSON.parse(output.trim());
156
+ // Close the browser
157
+ closeBrowser(session);
158
+ // Convert to our format
159
+ const balances = data.balances.map((b) => ({
160
+ symbol: b.symbol,
161
+ name: b.symbol,
162
+ amount: b.amount,
163
+ valueUsd: b.valueUsd,
164
+ chain: 'evm',
165
+ }));
166
+ return { success: true, balances, totalValueUsd: data.totalValueUsd };
167
+ }
168
+ catch (error) {
169
+ closeBrowser(session);
170
+ return {
171
+ success: false,
172
+ error: `Browser scraping failed: ${error instanceof Error ? error.message : String(error)}`,
173
+ };
174
+ }
175
+ }
176
+ /**
177
+ * Scrape Solscan profile page for Solana wallet balances.
178
+ * Uses agent-browser CLI to navigate and extract data via JavaScript.
179
+ */
180
+ export async function scrapeSolscanProfile(address, timeoutMs = 60000) {
181
+ const session = generateSessionName();
182
+ try {
183
+ const url = `https://solscan.io/account/${address}`;
184
+ // Open the page
185
+ runAgentBrowser(session, ['open', url], timeoutMs);
186
+ // Wait for JS to render
187
+ await new Promise((resolve) => setTimeout(resolve, 5000));
188
+ // Extract data using JavaScript evaluation
189
+ const output = runAgentBrowser(session, ['eval', SOLSCAN_EXTRACT_SCRIPT], timeoutMs);
190
+ // Parse the JSON output - agent-browser returns clean JSON when returning objects
191
+ const data = JSON.parse(output.trim());
192
+ // Close the browser
193
+ closeBrowser(session);
194
+ // Convert to our format
195
+ const balances = data.balances.map((b) => ({
196
+ symbol: b.symbol,
197
+ name: b.symbol,
198
+ amount: b.amount,
199
+ valueUsd: b.valueUsd,
200
+ chain: 'solana',
201
+ }));
202
+ // Calculate total from individual values if not set
203
+ const totalValueUsd = data.totalValueUsd || balances.reduce((sum, b) => sum + (b.valueUsd ?? 0), 0);
204
+ return { success: true, balances, totalValueUsd };
205
+ }
206
+ catch (error) {
207
+ closeBrowser(session);
208
+ return {
209
+ success: false,
210
+ error: `Browser scraping failed: ${error instanceof Error ? error.message : String(error)}`,
211
+ };
212
+ }
213
+ }
214
+ //# sourceMappingURL=browser-scraper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-scraper.js","sourceRoot":"","sources":["../../src/lib/browser-scraper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface OnchainConfig {
2
+ debankApiKey?: string;
3
+ heliusApiKey?: string;
4
+ coinbaseApiKeyId?: string;
5
+ coinbaseApiKeySecret?: string;
6
+ binanceApiKey?: string;
7
+ binanceApiSecret?: string;
8
+ coingeckoApiKey?: string;
9
+ coinmarketcapApiKey?: string;
10
+ timeoutMs?: number;
11
+ }
12
+ export declare function loadConfig(warn: (message: string) => void): OnchainConfig;
13
+ export declare function saveConfig(config: Partial<OnchainConfig>, options?: {
14
+ global?: boolean;
15
+ }): void;
16
+ export declare function getConfigPath(options?: {
17
+ global?: boolean;
18
+ }): string;
19
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4BD,wBAAgB,UAAU,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,aAAa,CASzE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAc/F;AAED,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAEpE"}
@@ -0,0 +1,52 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { dirname, join } from 'node:path';
4
+ import JSON5 from 'json5';
5
+ const DEFAULT_CONFIG = {
6
+ timeoutMs: 30000,
7
+ };
8
+ function getGlobalConfigPath() {
9
+ return join(homedir(), '.config', 'onchain', 'config.json5');
10
+ }
11
+ function getLocalConfigPath() {
12
+ return join(process.cwd(), '.onchainrc.json5');
13
+ }
14
+ function readConfigFile(path, warn) {
15
+ if (!existsSync(path)) {
16
+ return {};
17
+ }
18
+ try {
19
+ const raw = readFileSync(path, 'utf8');
20
+ const parsed = JSON5.parse(raw);
21
+ return parsed ?? {};
22
+ }
23
+ catch (error) {
24
+ warn(`Failed to parse config at ${path}: ${error instanceof Error ? error.message : String(error)}`);
25
+ return {};
26
+ }
27
+ }
28
+ export function loadConfig(warn) {
29
+ const globalPath = getGlobalConfigPath();
30
+ const localPath = getLocalConfigPath();
31
+ return {
32
+ ...DEFAULT_CONFIG,
33
+ ...readConfigFile(globalPath, warn),
34
+ ...readConfigFile(localPath, warn),
35
+ };
36
+ }
37
+ export function saveConfig(config, options) {
38
+ const path = options?.global ? getGlobalConfigPath() : getLocalConfigPath();
39
+ const dir = dirname(path);
40
+ if (!existsSync(dir)) {
41
+ mkdirSync(dir, { recursive: true });
42
+ }
43
+ // Load existing config and merge
44
+ const existing = existsSync(path) ? readConfigFile(path, () => { }) : {};
45
+ const merged = { ...existing, ...config };
46
+ const content = JSON5.stringify(merged, null, 2);
47
+ writeFileSync(path, content, 'utf8');
48
+ }
49
+ export function getConfigPath(options) {
50
+ return options?.global ? getGlobalConfigPath() : getLocalConfigPath();
51
+ }
52
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;AAe1B,MAAM,cAAc,GAAkB;IACpC,SAAS,EAAE,KAAK;CACjB,CAAC;AAEF,SAAS,mBAAmB;IAC1B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,IAA+B;IACnE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAA2B,CAAC;QAC1D,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,6BAA6B,IAAI,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrG,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAA+B;IACxD,MAAM,UAAU,GAAG,mBAAmB,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,kBAAkB,EAAE,CAAC;IAEvC,OAAO;QACL,GAAG,cAAc;QACjB,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC;QACnC,GAAG,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC;KACnC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAA8B,EAAE,OAA8B;IACvF,MAAM,IAAI,GAAG,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC;IAC5E,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,iCAAiC;IACjC,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;IAE1C,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACjD,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAA8B;IAC1D,OAAO,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC;AACxE,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { OnchainConfig } from './config.js';
2
+ export interface ResolvedCredentials {
3
+ debankApiKey?: string;
4
+ heliusApiKey?: string;
5
+ coinbaseApiKeyId?: string;
6
+ coinbaseApiKeySecret?: string;
7
+ binanceApiKey?: string;
8
+ binanceApiSecret?: string;
9
+ coingeckoApiKey?: string;
10
+ coinmarketcapApiKey?: string;
11
+ warnings: string[];
12
+ }
13
+ export declare function resolveCredentials(config: OnchainConfig, env?: NodeJS.ProcessEnv): ResolvedCredentials;
14
+ export declare function validateCredentials(creds: ResolvedCredentials): {
15
+ hasDebank: boolean;
16
+ hasHelius: boolean;
17
+ hasCoinbase: boolean;
18
+ hasBinance: boolean;
19
+ hasCoinGecko: boolean;
20
+ hasCoinMarketCap: boolean;
21
+ };
22
+ export declare function getMissingCredentialsMessage(feature: string, requiredCreds: string[]): string;
23
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,mBAAmB,CAyBnH;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,GAAG;IAC/D,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CASA;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,CAc7F"}
@@ -0,0 +1,49 @@
1
+ export function resolveCredentials(config, env = process.env) {
2
+ const warnings = [];
3
+ // Resolve each credential from env first, then config
4
+ const debankApiKey = env.DEBANK_API_KEY ?? config.debankApiKey;
5
+ const heliusApiKey = env.HELIUS_API_KEY ?? config.heliusApiKey;
6
+ // Coinbase CDP API credentials
7
+ const coinbaseApiKeyId = env.COINBASE_API_KEY_ID ?? config.coinbaseApiKeyId;
8
+ const coinbaseApiKeySecret = env.COINBASE_API_KEY_SECRET ?? config.coinbaseApiKeySecret;
9
+ const binanceApiKey = env.BINANCE_API_KEY ?? config.binanceApiKey;
10
+ const binanceApiSecret = env.BINANCE_API_SECRET ?? config.binanceApiSecret;
11
+ const coingeckoApiKey = env.COINGECKO_API_KEY ?? config.coingeckoApiKey;
12
+ const coinmarketcapApiKey = env.COINMARKETCAP_API_KEY ?? config.coinmarketcapApiKey;
13
+ return {
14
+ debankApiKey,
15
+ heliusApiKey,
16
+ coinbaseApiKeyId,
17
+ coinbaseApiKeySecret,
18
+ binanceApiKey,
19
+ binanceApiSecret,
20
+ coingeckoApiKey,
21
+ coinmarketcapApiKey,
22
+ warnings,
23
+ };
24
+ }
25
+ export function validateCredentials(creds) {
26
+ return {
27
+ hasDebank: Boolean(creds.debankApiKey),
28
+ hasHelius: Boolean(creds.heliusApiKey),
29
+ hasCoinbase: Boolean(creds.coinbaseApiKeyId && creds.coinbaseApiKeySecret),
30
+ hasBinance: Boolean(creds.binanceApiKey && creds.binanceApiSecret),
31
+ hasCoinGecko: Boolean(creds.coingeckoApiKey), // Optional, free tier exists
32
+ hasCoinMarketCap: Boolean(creds.coinmarketcapApiKey),
33
+ };
34
+ }
35
+ export function getMissingCredentialsMessage(feature, requiredCreds) {
36
+ const envVars = requiredCreds.map((c) => {
37
+ const envMap = {
38
+ debank: 'DEBANK_API_KEY',
39
+ helius: 'HELIUS_API_KEY',
40
+ coinbase: 'COINBASE_API_KEY_ID and COINBASE_API_KEY_SECRET',
41
+ binance: 'BINANCE_API_KEY and BINANCE_API_SECRET',
42
+ coingecko: 'COINGECKO_API_KEY',
43
+ coinmarketcap: 'COINMARKETCAP_API_KEY',
44
+ };
45
+ return envMap[c] ?? c;
46
+ });
47
+ return `${feature} requires: ${envVars.join(', ')}. Run \`onchain setup\` or set environment variables.`;
48
+ }
49
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"AAeA,MAAM,UAAU,kBAAkB,CAAC,MAAqB,EAAE,MAAyB,OAAO,CAAC,GAAG;IAC5F,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,sDAAsD;IACtD,MAAM,YAAY,GAAG,GAAG,CAAC,cAAc,IAAI,MAAM,CAAC,YAAY,CAAC;IAC/D,MAAM,YAAY,GAAG,GAAG,CAAC,cAAc,IAAI,MAAM,CAAC,YAAY,CAAC;IAC/D,+BAA+B;IAC/B,MAAM,gBAAgB,GAAG,GAAG,CAAC,mBAAmB,IAAI,MAAM,CAAC,gBAAgB,CAAC;IAC5E,MAAM,oBAAoB,GAAG,GAAG,CAAC,uBAAuB,IAAI,MAAM,CAAC,oBAAoB,CAAC;IACxF,MAAM,aAAa,GAAG,GAAG,CAAC,eAAe,IAAI,MAAM,CAAC,aAAa,CAAC;IAClE,MAAM,gBAAgB,GAAG,GAAG,CAAC,kBAAkB,IAAI,MAAM,CAAC,gBAAgB,CAAC;IAC3E,MAAM,eAAe,GAAG,GAAG,CAAC,iBAAiB,IAAI,MAAM,CAAC,eAAe,CAAC;IACxE,MAAM,mBAAmB,GAAG,GAAG,CAAC,qBAAqB,IAAI,MAAM,CAAC,mBAAmB,CAAC;IAEpF,OAAO;QACL,YAAY;QACZ,YAAY;QACZ,gBAAgB;QAChB,oBAAoB;QACpB,aAAa;QACb,gBAAgB;QAChB,eAAe;QACf,mBAAmB;QACnB,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAA0B;IAQ5D,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;QACtC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;QACtC,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,oBAAoB,CAAC;QAC1E,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,gBAAgB,CAAC;QAClE,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,6BAA6B;QAC3E,gBAAgB,EAAE,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC;KACrD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAAe,EAAE,aAAuB;IACnF,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACtC,MAAM,MAAM,GAA2B;YACrC,MAAM,EAAE,gBAAgB;YACxB,MAAM,EAAE,gBAAgB;YACxB,QAAQ,EAAE,iDAAiD;YAC3D,OAAO,EAAE,wCAAwC;YACjD,SAAS,EAAE,mBAAmB;YAC9B,aAAa,EAAE,uBAAuB;SACvC,CAAC;QACF,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,OAAO,cAAc,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,uDAAuD,CAAC;AAC3G,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { AbstractConstructor, Mixin, OnchainClientBase } from '../onchain-client-base.js';
2
+ import type { CexBalanceResult, CexHistoryResult } from '../onchain-client-types.js';
3
+ export interface BinanceMethods {
4
+ getBinanceBalances(): Promise<CexBalanceResult>;
5
+ getBinanceHistory(options?: {
6
+ symbol?: string;
7
+ limit?: number;
8
+ cursor?: string;
9
+ }): Promise<CexHistoryResult>;
10
+ }
11
+ export declare function withBinance<TBase extends AbstractConstructor<OnchainClientBase>>(Base: TBase): Mixin<TBase, BinanceMethods>;
12
+ //# sourceMappingURL=binance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binance.d.ts","sourceRoot":"","sources":["../../../src/lib/mixins/binance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC/F,OAAO,KAAK,EAAc,gBAAgB,EAAE,gBAAgB,EAAY,MAAM,4BAA4B,CAAC;AAI3G,MAAM,WAAW,cAAc;IAC7B,kBAAkB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAChD,iBAAiB,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC9G;AAiCD,wBAAgB,WAAW,CAAC,KAAK,SAAS,mBAAmB,CAAC,iBAAiB,CAAC,EAC9E,IAAI,EAAE,KAAK,GACV,KAAK,CAAC,KAAK,EAAE,cAAc,CAAC,CAsM9B"}
@@ -0,0 +1,167 @@
1
+ import { createHmac } from 'node:crypto';
2
+ const BINANCE_API_BASE = 'https://api.binance.com';
3
+ export function withBinance(Base) {
4
+ class BinanceMixin extends Base {
5
+ generateBinanceSignature(queryString) {
6
+ if (!this.binanceApiSecret) {
7
+ throw new Error('Binance API secret required');
8
+ }
9
+ const hmac = createHmac('sha256', this.binanceApiSecret);
10
+ hmac.update(queryString);
11
+ return hmac.digest('hex');
12
+ }
13
+ getBinanceHeaders() {
14
+ if (!this.binanceApiKey) {
15
+ throw new Error('Binance API key required');
16
+ }
17
+ return {
18
+ 'X-MBX-APIKEY': this.binanceApiKey,
19
+ 'Content-Type': 'application/json',
20
+ };
21
+ }
22
+ async getBinancePrices() {
23
+ try {
24
+ const response = await this.fetchWithTimeout(`${BINANCE_API_BASE}/api/v3/ticker/price`);
25
+ if (!response.ok) {
26
+ return new Map();
27
+ }
28
+ const data = (await response.json());
29
+ const prices = new Map();
30
+ for (const item of data) {
31
+ // Extract base asset from trading pair (e.g., BTCUSDT -> BTC)
32
+ if (item.symbol.endsWith('USDT')) {
33
+ const asset = item.symbol.replace('USDT', '');
34
+ prices.set(asset, Number.parseFloat(item.price));
35
+ }
36
+ }
37
+ // Add stablecoin prices
38
+ prices.set('USDT', 1);
39
+ prices.set('USDC', 1);
40
+ prices.set('BUSD', 1);
41
+ prices.set('DAI', 1);
42
+ return prices;
43
+ }
44
+ catch {
45
+ return new Map();
46
+ }
47
+ }
48
+ async getBinanceBalances() {
49
+ if (!this.binanceApiKey || !this.binanceApiSecret) {
50
+ return { success: false, error: 'Binance API credentials not configured' };
51
+ }
52
+ try {
53
+ const timestamp = Date.now();
54
+ const queryString = `timestamp=${timestamp}`;
55
+ const signature = this.generateBinanceSignature(queryString);
56
+ const url = `${BINANCE_API_BASE}/api/v3/account?${queryString}&signature=${signature}`;
57
+ const response = await this.fetchWithTimeout(url, {
58
+ headers: this.getBinanceHeaders(),
59
+ });
60
+ if (!response.ok) {
61
+ const errorText = await response.text();
62
+ return { success: false, error: `Binance API error: ${response.status} - ${errorText}` };
63
+ }
64
+ const data = (await response.json());
65
+ // Get prices for valuation
66
+ const prices = await this.getBinancePrices();
67
+ let totalValueUsd = 0;
68
+ const balances = [];
69
+ for (const balance of data.balances) {
70
+ const free = Number.parseFloat(balance.free);
71
+ const locked = Number.parseFloat(balance.locked);
72
+ const total = free + locked;
73
+ if (total <= 0) {
74
+ continue;
75
+ }
76
+ const price = prices.get(balance.asset);
77
+ const valueUsd = price ? total * price : undefined;
78
+ if (valueUsd) {
79
+ totalValueUsd += valueUsd;
80
+ }
81
+ balances.push({
82
+ exchange: 'binance',
83
+ asset: balance.asset,
84
+ free,
85
+ locked,
86
+ total,
87
+ valueUsd,
88
+ });
89
+ }
90
+ // Sort by value descending
91
+ balances.sort((a, b) => (b.valueUsd ?? 0) - (a.valueUsd ?? 0));
92
+ return { success: true, balances, totalValueUsd };
93
+ }
94
+ catch (error) {
95
+ return {
96
+ success: false,
97
+ error: `Failed to fetch Binance balances: ${error instanceof Error ? error.message : String(error)}`,
98
+ };
99
+ }
100
+ }
101
+ async getBinanceHistory(options) {
102
+ if (!this.binanceApiKey || !this.binanceApiSecret) {
103
+ return { success: false, error: 'Binance API credentials not configured' };
104
+ }
105
+ try {
106
+ const limit = options?.limit ?? 50;
107
+ const timestamp = Date.now();
108
+ // If no symbol specified, get trades from common pairs
109
+ const symbols = options?.symbol ? [options.symbol] : ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT'];
110
+ const allTrades = [];
111
+ for (const symbol of symbols) {
112
+ let queryString = `symbol=${symbol}&limit=${limit}&timestamp=${timestamp}`;
113
+ if (options?.cursor) {
114
+ queryString += `&fromId=${options.cursor}`;
115
+ }
116
+ const signature = this.generateBinanceSignature(queryString);
117
+ const url = `${BINANCE_API_BASE}/api/v3/myTrades?${queryString}&signature=${signature}`;
118
+ try {
119
+ const response = await this.fetchWithTimeout(url, {
120
+ headers: this.getBinanceHeaders(),
121
+ });
122
+ if (!response.ok) {
123
+ continue;
124
+ }
125
+ const data = (await response.json());
126
+ for (const trade of data) {
127
+ const price = Number.parseFloat(trade.price);
128
+ const quantity = Number.parseFloat(trade.qty);
129
+ const total = Number.parseFloat(trade.quoteQty);
130
+ const fee = Number.parseFloat(trade.commission);
131
+ allTrades.push({
132
+ exchange: 'binance',
133
+ id: String(trade.id),
134
+ symbol: trade.symbol,
135
+ side: trade.isBuyer ? 'buy' : 'sell',
136
+ price,
137
+ quantity,
138
+ total,
139
+ fee,
140
+ feeAsset: trade.commissionAsset,
141
+ timestamp: trade.time / 1000,
142
+ orderId: String(trade.orderId),
143
+ });
144
+ }
145
+ }
146
+ catch {
147
+ // Continue to next symbol on error
148
+ }
149
+ }
150
+ // Sort by timestamp descending
151
+ allTrades.sort((a, b) => b.timestamp - a.timestamp);
152
+ // Limit results
153
+ const limitedTrades = allTrades.slice(0, limit);
154
+ const nextCursor = limitedTrades.length === limit ? limitedTrades[limitedTrades.length - 1]?.id : undefined;
155
+ return { success: true, trades: limitedTrades, nextCursor };
156
+ }
157
+ catch (error) {
158
+ return {
159
+ success: false,
160
+ error: `Failed to fetch Binance history: ${error instanceof Error ? error.message : String(error)}`,
161
+ };
162
+ }
163
+ }
164
+ }
165
+ return BinanceMixin;
166
+ }
167
+ //# sourceMappingURL=binance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binance.js","sourceRoot":"","sources":["../../../src/lib/mixins/binance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { AbstractConstructor, Mixin, OnchainClientBase } from '../onchain-client-base.js';
2
+ import type { CexBalanceResult, CexHistoryResult } from '../onchain-client-types.js';
3
+ export interface CoinbaseMethods {
4
+ getCoinbaseBalances(): Promise<CexBalanceResult>;
5
+ getCoinbaseHistory(options?: {
6
+ limit?: number;
7
+ cursor?: string;
8
+ }): Promise<CexHistoryResult>;
9
+ }
10
+ export declare function withCoinbase<TBase extends AbstractConstructor<OnchainClientBase>>(Base: TBase): Mixin<TBase, CoinbaseMethods>;
11
+ //# sourceMappingURL=coinbase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coinbase.d.ts","sourceRoot":"","sources":["../../../src/lib/mixins/coinbase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC/F,OAAO,KAAK,EAAc,gBAAgB,EAAE,gBAAgB,EAAY,MAAM,4BAA4B,CAAC;AAI3G,MAAM,WAAW,eAAe;IAC9B,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjD,kBAAkB,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC9F;AAsLD,wBAAgB,YAAY,CAAC,KAAK,SAAS,mBAAmB,CAAC,iBAAiB,CAAC,EAC/E,IAAI,EAAE,KAAK,GACV,KAAK,CAAC,KAAK,EAAE,eAAe,CAAC,CAgP/B"}