satuchain-api 1.0.1

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SATU TEAM
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,215 @@
1
+ # satuchain-api
2
+
3
+ Official JavaScript/TypeScript SDK for the **SATUCHAIN Developer API** — live forex rates, crypto prices, and commodity data.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/satuchain-api.svg)](https://www.npmjs.com/package/satuchain-api)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+
8
+ ## Requirements
9
+
10
+ - **≥ 10,000 STU** tokens on BNB Chain to generate an API key
11
+ - Get your key at [dev.satuchain.com](https://dev.satuchain.com)
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install satuchain-api
17
+ # or
18
+ yarn add satuchain-api
19
+ # or
20
+ pnpm add satuchain-api
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```typescript
26
+ import { SatuChainAPI } from "satuchain-api";
27
+
28
+ const api = new SatuChainAPI("sk_live_YOUR_KEY");
29
+
30
+ const data = await api.getCommodities();
31
+
32
+ // Forex — units per 1 USD
33
+ console.log(data.forex.IDR.value); // e.g. 16250
34
+ console.log(data.forex.MYR.value); // e.g. 4.71
35
+ console.log(data.forex.EUR.value); // e.g. 0.9251
36
+
37
+ // Crypto — price in USD
38
+ console.log(data.crypto.BTC.value); // e.g. 67420.50
39
+ console.log(data.crypto.BNB.value); // e.g. 580.10
40
+ console.log(data.crypto.STU.value); // e.g. 0.00182
41
+
42
+ // Commodities
43
+ console.log(data.commodities.XAU.value); // Gold e.g. 2680.50 (USD/troy oz)
44
+ console.log(data.commodities.XAU.changePercent); // e.g. -0.42 (% from prev close)
45
+ console.log(data.commodities.XAG.value); // Silver e.g. 31.40 (USD/troy oz)
46
+ console.log(data.commodities.COPPER.value); // Copper e.g. 4.20 (USD/lb)
47
+ ```
48
+
49
+ ## Constructor
50
+
51
+ ```typescript
52
+ // Simple — just pass the key
53
+ const api = new SatuChainAPI("sk_live_...");
54
+
55
+ // Full options
56
+ const api = new SatuChainAPI({
57
+ apiKey: "sk_live_...",
58
+ baseUrl: "https://dev.satuchain.com", // optional, default
59
+ timeout: 10000, // optional, ms
60
+ });
61
+ ```
62
+
63
+ ## Methods
64
+
65
+ ### `getCommodities(opts?)`
66
+
67
+ Fetches all available data in a single request.
68
+
69
+ ```typescript
70
+ const data = await api.getCommodities();
71
+ // data.crypto — BTC, BNB, STU
72
+ // data.forex — CNY, EUR, IDR, JPY, MYR, NGN, SGD, VND
73
+ // data.commodities — XAU, XAG, COPPER
74
+ ```
75
+
76
+ ### `getForex(opts?)`
77
+
78
+ Returns only forex rates.
79
+
80
+ ```typescript
81
+ const forex = await api.getForex();
82
+ console.log(forex.IDR.value); // IDR per 1 USD
83
+ ```
84
+
85
+ ### `getCrypto(opts?)`
86
+
87
+ Returns only crypto prices.
88
+
89
+ ```typescript
90
+ const crypto = await api.getCrypto();
91
+ console.log(crypto.BTC.value); // USD
92
+ ```
93
+
94
+ ### `getMetals(opts?)`
95
+
96
+ Returns only commodity prices.
97
+
98
+ ```typescript
99
+ const metals = await api.getMetals();
100
+ console.log(metals.XAU.value); // USD/troy oz
101
+ console.log(metals.XAU.changePercent); // % change from prev close
102
+ ```
103
+
104
+ ## Rate Limits
105
+
106
+ Each API key is limited to **60 requests per minute**. Rate limit info is available after any request:
107
+
108
+ ```typescript
109
+ const data = await api.getCommodities();
110
+
111
+ console.log(api.rateLimit);
112
+ // { limit: 60, remaining: 59, resetAt: 1712345678 }
113
+ ```
114
+
115
+ On rate limit exceeded, a `SatuChainRateLimitError` is thrown with a `retryAfter` field (seconds):
116
+
117
+ ```typescript
118
+ import { SatuChainRateLimitError } from "satuchain-api";
119
+
120
+ try {
121
+ const data = await api.getCommodities();
122
+ } catch (err) {
123
+ if (err instanceof SatuChainRateLimitError) {
124
+ console.log(`Retry after ${err.retryAfter}s`);
125
+ }
126
+ }
127
+ ```
128
+
129
+ ## Error Handling
130
+
131
+ ```typescript
132
+ import {
133
+ SatuChainAuthError,
134
+ SatuChainRateLimitError,
135
+ SatuChainUpstreamError,
136
+ SatuChainError,
137
+ } from "satuchain-api";
138
+
139
+ try {
140
+ const data = await api.getCommodities();
141
+ } catch (err) {
142
+ if (err instanceof SatuChainAuthError) {
143
+ // 401 — invalid or revoked API key
144
+ } else if (err instanceof SatuChainRateLimitError) {
145
+ // 429 — slow down, check err.retryAfter
146
+ } else if (err instanceof SatuChainUpstreamError) {
147
+ // 502 — upstream data source unavailable
148
+ } else if (err instanceof SatuChainError) {
149
+ // network timeout or other SDK error
150
+ }
151
+ }
152
+ ```
153
+
154
+ ## Request Cancellation
155
+
156
+ ```typescript
157
+ const controller = new AbortController();
158
+
159
+ setTimeout(() => controller.abort(), 3000);
160
+
161
+ const data = await api.getCommodities({ signal: controller.signal });
162
+ ```
163
+
164
+ ## CommonJS
165
+
166
+ ```javascript
167
+ const { SatuChainAPI } = require("satuchain-api");
168
+
169
+ const api = new SatuChainAPI("sk_live_YOUR_KEY");
170
+ api.getCommodities().then((data) => {
171
+ console.log(data.forex.IDR.value);
172
+ });
173
+ ```
174
+
175
+ ## Response Shape
176
+
177
+ ```typescript
178
+ {
179
+ ok: true,
180
+ base: "USD",
181
+ updatedAtUnix: 1712345600, // forex update time
182
+ nextUpdateUnix: 1712349200,
183
+ crypto: {
184
+ BTC: { name: "Bitcoin", value: 67420.50 },
185
+ BNB: { name: "BNB", value: 580.10 },
186
+ STU: { name: "SATU Token", value: 0.00182 }
187
+ },
188
+ forex: {
189
+ CNY: { name: "Chinese Yuan", value: 7.2412 },
190
+ EUR: { name: "Euro", value: 0.9251 },
191
+ IDR: { name: "Indonesian Rupiah", value: 16250 },
192
+ JPY: { name: "Japanese Yen", value: 151.82 },
193
+ MYR: { name: "Malaysian Ringgit", value: 4.7120 },
194
+ NGN: { name: "Nigerian Naira", value: 1580 },
195
+ SGD: { name: "Singapore Dollar", value: 1.3510 },
196
+ VND: { name: "Vietnamese Dong", value: 25100 }
197
+ },
198
+ commodities: {
199
+ XAU: { name: "Gold", value: 2680.50, changePercent: -0.42, unit: "USD/troy oz" },
200
+ XAG: { name: "Silver", value: 31.40, changePercent: 0.81, unit: "USD/troy oz" },
201
+ COPPER: { name: "Copper", value: 4.20, changePercent: -0.15, unit: "USD/lb" }
202
+ }
203
+ }
204
+ ```
205
+
206
+ ## Links
207
+
208
+ - **API Portal**: [dev.satuchain.com](https://dev.satuchain.com)
209
+ - **SATUCHAIN**: [satuchain.com](https://satuchain.com)
210
+ - **X (Twitter)**: [@SatuChain](https://x.com/SatuChain)
211
+ - **Telegram**: [t.me/satuchain](https://t.me/satuchain)
212
+
213
+ ## License
214
+
215
+ MIT — see [LICENSE](LICENSE)
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SatuChainAPI = void 0;
4
+ const errors_js_1 = require("./errors.js");
5
+ const DEFAULT_BASE_URL = "https://dev.satuchain.com";
6
+ const DEFAULT_TIMEOUT = 10000;
7
+ class SatuChainAPI {
8
+ constructor(options) {
9
+ /** Last rate-limit info from the most recent response */
10
+ this.rateLimit = null;
11
+ if (typeof options === "string") {
12
+ this.apiKey = options;
13
+ this.baseUrl = DEFAULT_BASE_URL;
14
+ this.timeout = DEFAULT_TIMEOUT;
15
+ }
16
+ else {
17
+ this.apiKey = options.apiKey;
18
+ this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
19
+ this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
20
+ }
21
+ if (!this.apiKey.startsWith("sk_live_")) {
22
+ throw new errors_js_1.SatuChainError("API key must start with sk_live_");
23
+ }
24
+ }
25
+ async request(path, opts) {
26
+ const controller = new AbortController();
27
+ const timer = setTimeout(() => controller.abort(), this.timeout);
28
+ const signal = opts?.signal
29
+ ? AbortSignal.any
30
+ ? AbortSignal.any([opts.signal, controller.signal])
31
+ : controller.signal
32
+ : controller.signal;
33
+ let res;
34
+ try {
35
+ res = await fetch(`${this.baseUrl}${path}`, {
36
+ method: "GET",
37
+ headers: {
38
+ "X-API-Key": this.apiKey,
39
+ "Accept": "application/json",
40
+ "User-Agent": "satuchain-sdk/1.0.1",
41
+ },
42
+ signal,
43
+ });
44
+ }
45
+ catch (err) {
46
+ clearTimeout(timer);
47
+ if (err?.name === "AbortError") {
48
+ throw new errors_js_1.SatuChainError(`Request timed out after ${this.timeout}ms`);
49
+ }
50
+ throw new errors_js_1.SatuChainError(`Network error: ${err?.message ?? err}`);
51
+ }
52
+ clearTimeout(timer);
53
+ // Parse rate-limit headers
54
+ const rlLimit = parseInt(res.headers.get("x-ratelimit-limit") ?? "");
55
+ const rlRemaining = parseInt(res.headers.get("x-ratelimit-remaining") ?? "");
56
+ const rlReset = parseInt(res.headers.get("x-ratelimit-reset") ?? "");
57
+ if (!isNaN(rlLimit)) {
58
+ this.rateLimit = { limit: rlLimit, remaining: rlRemaining, resetAt: rlReset };
59
+ }
60
+ if (res.status === 401) {
61
+ const body = await res.json().catch(() => ({}));
62
+ throw new errors_js_1.SatuChainAuthError(body?.error);
63
+ }
64
+ if (res.status === 429) {
65
+ const retryAfter = parseInt(res.headers.get("retry-after") ?? "60");
66
+ const body = await res.json().catch(() => ({}));
67
+ throw new errors_js_1.SatuChainRateLimitError(retryAfter, body?.error);
68
+ }
69
+ if (!res.ok) {
70
+ throw new errors_js_1.SatuChainUpstreamError(res.status);
71
+ }
72
+ const json = await res.json();
73
+ if (!json.ok) {
74
+ throw new errors_js_1.SatuChainError(json.error ?? "API error");
75
+ }
76
+ return json;
77
+ }
78
+ /**
79
+ * Fetch live commodity, forex, and crypto price data.
80
+ *
81
+ * @example
82
+ * const data = await api.getCommodities();
83
+ * console.log(data.forex.IDR.value); // IDR per 1 USD
84
+ * console.log(data.crypto.BTC.value); // BTC price in USD
85
+ * console.log(data.commodities.XAU.value); // Gold price in USD/troy oz
86
+ */
87
+ async getCommodities(opts) {
88
+ return this.request("/api/commodities", opts);
89
+ }
90
+ /**
91
+ * Get just the forex rates (subset of getCommodities).
92
+ */
93
+ async getForex(opts) {
94
+ const data = await this.getCommodities(opts);
95
+ return data.forex;
96
+ }
97
+ /**
98
+ * Get just the crypto prices (subset of getCommodities).
99
+ */
100
+ async getCrypto(opts) {
101
+ const data = await this.getCommodities(opts);
102
+ return data.crypto;
103
+ }
104
+ /**
105
+ * Get just the commodity prices (subset of getCommodities).
106
+ */
107
+ async getMetals(opts) {
108
+ const data = await this.getCommodities(opts);
109
+ return data.commodities;
110
+ }
111
+ }
112
+ exports.SatuChainAPI = SatuChainAPI;
113
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SatuChainUpstreamError = exports.SatuChainRateLimitError = exports.SatuChainAuthError = exports.SatuChainError = void 0;
4
+ class SatuChainError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "SatuChainError";
8
+ }
9
+ }
10
+ exports.SatuChainError = SatuChainError;
11
+ class SatuChainAuthError extends SatuChainError {
12
+ constructor(message = "Invalid or missing API key") {
13
+ super(message);
14
+ this.status = 401;
15
+ this.name = "SatuChainAuthError";
16
+ }
17
+ }
18
+ exports.SatuChainAuthError = SatuChainAuthError;
19
+ class SatuChainRateLimitError extends SatuChainError {
20
+ constructor(retryAfter, message) {
21
+ super(message ?? `Rate limit exceeded. Retry after ${retryAfter}s`);
22
+ this.status = 429;
23
+ this.name = "SatuChainRateLimitError";
24
+ this.retryAfter = retryAfter;
25
+ }
26
+ }
27
+ exports.SatuChainRateLimitError = SatuChainRateLimitError;
28
+ class SatuChainUpstreamError extends SatuChainError {
29
+ constructor(status, message) {
30
+ super(message ?? `Upstream error: ${status}`);
31
+ this.name = "SatuChainUpstreamError";
32
+ this.status = status;
33
+ }
34
+ }
35
+ exports.SatuChainUpstreamError = SatuChainUpstreamError;
36
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":";;;AAAA,MAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AALD,wCAKC;AAED,MAAa,kBAAmB,SAAQ,cAAc;IAEpD,YAAY,OAAO,GAAG,4BAA4B;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QAFR,WAAM,GAAG,GAAG,CAAC;QAGpB,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAND,gDAMC;AAED,MAAa,uBAAwB,SAAQ,cAAc;IAGzD,YAAY,UAAkB,EAAE,OAAgB;QAC9C,KAAK,CAAC,OAAO,IAAI,oCAAoC,UAAU,GAAG,CAAC,CAAC;QAH7D,WAAM,GAAG,GAAG,CAAC;QAIpB,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AARD,0DAQC;AAED,MAAa,sBAAuB,SAAQ,cAAc;IAExD,YAAY,MAAc,EAAE,OAAgB;QAC1C,KAAK,CAAC,OAAO,IAAI,mBAAmB,MAAM,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAPD,wDAOC"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SatuChainUpstreamError = exports.SatuChainRateLimitError = exports.SatuChainAuthError = exports.SatuChainError = exports.SatuChainAPI = void 0;
4
+ var client_js_1 = require("./client.js");
5
+ Object.defineProperty(exports, "SatuChainAPI", { enumerable: true, get: function () { return client_js_1.SatuChainAPI; } });
6
+ var errors_js_1 = require("./errors.js");
7
+ Object.defineProperty(exports, "SatuChainError", { enumerable: true, get: function () { return errors_js_1.SatuChainError; } });
8
+ Object.defineProperty(exports, "SatuChainAuthError", { enumerable: true, get: function () { return errors_js_1.SatuChainAuthError; } });
9
+ Object.defineProperty(exports, "SatuChainRateLimitError", { enumerable: true, get: function () { return errors_js_1.SatuChainRateLimitError; } });
10
+ Object.defineProperty(exports, "SatuChainUpstreamError", { enumerable: true, get: function () { return errors_js_1.SatuChainUpstreamError; } });
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAA2C;AAAlC,yGAAA,YAAY,OAAA;AACrB,yCAKqB;AAJnB,2GAAA,cAAc,OAAA;AACd,+GAAA,kBAAkB,OAAA;AAClB,oHAAA,uBAAuB,OAAA;AACvB,mHAAA,sBAAsB,OAAA"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // ─── Response Types ──────────────────────────────────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";AAAA,gFAAgF"}
@@ -0,0 +1,33 @@
1
+ import type { SatuChainAPIOptions, RequestOptions, CommoditiesResponse, RateLimitInfo } from "./types.js";
2
+ export declare class SatuChainAPI {
3
+ private readonly apiKey;
4
+ private readonly baseUrl;
5
+ private readonly timeout;
6
+ /** Last rate-limit info from the most recent response */
7
+ rateLimit: RateLimitInfo | null;
8
+ constructor(options: SatuChainAPIOptions | string);
9
+ private request;
10
+ /**
11
+ * Fetch live commodity, forex, and crypto price data.
12
+ *
13
+ * @example
14
+ * const data = await api.getCommodities();
15
+ * console.log(data.forex.IDR.value); // IDR per 1 USD
16
+ * console.log(data.crypto.BTC.value); // BTC price in USD
17
+ * console.log(data.commodities.XAU.value); // Gold price in USD/troy oz
18
+ */
19
+ getCommodities(opts?: RequestOptions): Promise<CommoditiesResponse>;
20
+ /**
21
+ * Get just the forex rates (subset of getCommodities).
22
+ */
23
+ getForex(opts?: RequestOptions): Promise<CommoditiesResponse["forex"]>;
24
+ /**
25
+ * Get just the crypto prices (subset of getCommodities).
26
+ */
27
+ getCrypto(opts?: RequestOptions): Promise<CommoditiesResponse["crypto"]>;
28
+ /**
29
+ * Get just the commodity prices (subset of getCommodities).
30
+ */
31
+ getMetals(opts?: RequestOptions): Promise<CommoditiesResponse["commodities"]>;
32
+ }
33
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,aAAa,EACd,MAAM,YAAY,CAAC;AAWpB,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,yDAAyD;IAClD,SAAS,EAAE,aAAa,GAAG,IAAI,CAAQ;gBAElC,OAAO,EAAE,mBAAmB,GAAG,MAAM;YAgBnC,OAAO;IAiErB;;;;;;;;OAQG;IACG,cAAc,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAIzE;;OAEG;IACG,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAK5E;;OAEG;IACG,SAAS,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAK9E;;OAEG;IACG,SAAS,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC;CAIpF"}
@@ -0,0 +1,109 @@
1
+ import { SatuChainAuthError, SatuChainRateLimitError, SatuChainUpstreamError, SatuChainError, } from "./errors.js";
2
+ const DEFAULT_BASE_URL = "https://dev.satuchain.com";
3
+ const DEFAULT_TIMEOUT = 10000;
4
+ export class SatuChainAPI {
5
+ constructor(options) {
6
+ /** Last rate-limit info from the most recent response */
7
+ this.rateLimit = null;
8
+ if (typeof options === "string") {
9
+ this.apiKey = options;
10
+ this.baseUrl = DEFAULT_BASE_URL;
11
+ this.timeout = DEFAULT_TIMEOUT;
12
+ }
13
+ else {
14
+ this.apiKey = options.apiKey;
15
+ this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
16
+ this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
17
+ }
18
+ if (!this.apiKey.startsWith("sk_live_")) {
19
+ throw new SatuChainError("API key must start with sk_live_");
20
+ }
21
+ }
22
+ async request(path, opts) {
23
+ const controller = new AbortController();
24
+ const timer = setTimeout(() => controller.abort(), this.timeout);
25
+ const signal = opts?.signal
26
+ ? AbortSignal.any
27
+ ? AbortSignal.any([opts.signal, controller.signal])
28
+ : controller.signal
29
+ : controller.signal;
30
+ let res;
31
+ try {
32
+ res = await fetch(`${this.baseUrl}${path}`, {
33
+ method: "GET",
34
+ headers: {
35
+ "X-API-Key": this.apiKey,
36
+ "Accept": "application/json",
37
+ "User-Agent": "satuchain-sdk/1.0.1",
38
+ },
39
+ signal,
40
+ });
41
+ }
42
+ catch (err) {
43
+ clearTimeout(timer);
44
+ if (err?.name === "AbortError") {
45
+ throw new SatuChainError(`Request timed out after ${this.timeout}ms`);
46
+ }
47
+ throw new SatuChainError(`Network error: ${err?.message ?? err}`);
48
+ }
49
+ clearTimeout(timer);
50
+ // Parse rate-limit headers
51
+ const rlLimit = parseInt(res.headers.get("x-ratelimit-limit") ?? "");
52
+ const rlRemaining = parseInt(res.headers.get("x-ratelimit-remaining") ?? "");
53
+ const rlReset = parseInt(res.headers.get("x-ratelimit-reset") ?? "");
54
+ if (!isNaN(rlLimit)) {
55
+ this.rateLimit = { limit: rlLimit, remaining: rlRemaining, resetAt: rlReset };
56
+ }
57
+ if (res.status === 401) {
58
+ const body = await res.json().catch(() => ({}));
59
+ throw new SatuChainAuthError(body?.error);
60
+ }
61
+ if (res.status === 429) {
62
+ const retryAfter = parseInt(res.headers.get("retry-after") ?? "60");
63
+ const body = await res.json().catch(() => ({}));
64
+ throw new SatuChainRateLimitError(retryAfter, body?.error);
65
+ }
66
+ if (!res.ok) {
67
+ throw new SatuChainUpstreamError(res.status);
68
+ }
69
+ const json = await res.json();
70
+ if (!json.ok) {
71
+ throw new SatuChainError(json.error ?? "API error");
72
+ }
73
+ return json;
74
+ }
75
+ /**
76
+ * Fetch live commodity, forex, and crypto price data.
77
+ *
78
+ * @example
79
+ * const data = await api.getCommodities();
80
+ * console.log(data.forex.IDR.value); // IDR per 1 USD
81
+ * console.log(data.crypto.BTC.value); // BTC price in USD
82
+ * console.log(data.commodities.XAU.value); // Gold price in USD/troy oz
83
+ */
84
+ async getCommodities(opts) {
85
+ return this.request("/api/commodities", opts);
86
+ }
87
+ /**
88
+ * Get just the forex rates (subset of getCommodities).
89
+ */
90
+ async getForex(opts) {
91
+ const data = await this.getCommodities(opts);
92
+ return data.forex;
93
+ }
94
+ /**
95
+ * Get just the crypto prices (subset of getCommodities).
96
+ */
97
+ async getCrypto(opts) {
98
+ const data = await this.getCommodities(opts);
99
+ return data.crypto;
100
+ }
101
+ /**
102
+ * Get just the commodity prices (subset of getCommodities).
103
+ */
104
+ async getMetals(opts) {
105
+ const data = await this.getCommodities(opts);
106
+ return data.commodities;
107
+ }
108
+ }
109
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,EACtB,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;AACrD,MAAM,eAAe,GAAG,KAAM,CAAC;AAE/B,MAAM,OAAO,YAAY;IAQvB,YAAY,OAAqC;QAHjD,yDAAyD;QAClD,cAAS,GAAyB,IAAI,CAAC;QAG5C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC;YACtB,IAAI,CAAC,OAAO,GAAG,gBAAgB,CAAC;YAChC,IAAI,CAAC,OAAO,GAAG,eAAe,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAC7B,IAAI,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACxE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,eAAe,CAAC;QACpD,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,cAAc,CAAC,kCAAkC,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,OAAO,CACnB,IAAY,EACZ,IAAqB;QAErB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAEjE,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM;YACzB,CAAC,CAAC,WAAW,CAAC,GAAG;gBACf,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;gBACnD,CAAC,CAAC,UAAU,CAAC,MAAM;YACrB,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC;QAEtB,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;gBAC1C,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,WAAW,EAAE,IAAI,CAAC,MAAM;oBACxB,QAAQ,EAAE,kBAAkB;oBAC5B,YAAY,EAAE,qBAAqB;iBACpC;gBACD,MAAM;aACP,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,GAAG,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC/B,MAAM,IAAI,cAAc,CAAC,2BAA2B,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;YACxE,CAAC;YACD,MAAM,IAAI,cAAc,CAAC,kBAAkB,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,YAAY,CAAC,KAAK,CAAC,CAAC;QAEpB,2BAA2B;QAC3B,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7E,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QAChF,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAQ,CAAC;YACvD,MAAM,IAAI,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,CAAC;YACpE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAQ,CAAC;YACvD,MAAM,IAAI,uBAAuB,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,sBAAsB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAS,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,IAAI,WAAW,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,IAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,cAAc,CAAC,IAAqB;QACxC,OAAO,IAAI,CAAC,OAAO,CAAsB,kBAAkB,EAAE,IAAI,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,IAAqB;QAClC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,IAAqB;QACnC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,IAAqB;QACnC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,17 @@
1
+ export declare class SatuChainError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare class SatuChainAuthError extends SatuChainError {
5
+ readonly status = 401;
6
+ constructor(message?: string);
7
+ }
8
+ export declare class SatuChainRateLimitError extends SatuChainError {
9
+ readonly status = 429;
10
+ readonly retryAfter: number;
11
+ constructor(retryAfter: number, message?: string);
12
+ }
13
+ export declare class SatuChainUpstreamError extends SatuChainError {
14
+ readonly status: number;
15
+ constructor(status: number, message?: string);
16
+ }
17
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,cAAc;IACpD,QAAQ,CAAC,MAAM,OAAO;gBACV,OAAO,SAA+B;CAInD;AAED,qBAAa,uBAAwB,SAAQ,cAAc;IACzD,QAAQ,CAAC,MAAM,OAAO;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAChB,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAKjD;AAED,qBAAa,sBAAuB,SAAQ,cAAc;IACxD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAK7C"}
@@ -0,0 +1,29 @@
1
+ export class SatuChainError extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = "SatuChainError";
5
+ }
6
+ }
7
+ export class SatuChainAuthError extends SatuChainError {
8
+ constructor(message = "Invalid or missing API key") {
9
+ super(message);
10
+ this.status = 401;
11
+ this.name = "SatuChainAuthError";
12
+ }
13
+ }
14
+ export class SatuChainRateLimitError extends SatuChainError {
15
+ constructor(retryAfter, message) {
16
+ super(message ?? `Rate limit exceeded. Retry after ${retryAfter}s`);
17
+ this.status = 429;
18
+ this.name = "SatuChainRateLimitError";
19
+ this.retryAfter = retryAfter;
20
+ }
21
+ }
22
+ export class SatuChainUpstreamError extends SatuChainError {
23
+ constructor(status, message) {
24
+ super(message ?? `Upstream error: ${status}`);
25
+ this.name = "SatuChainUpstreamError";
26
+ this.status = status;
27
+ }
28
+ }
29
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,cAAc;IAEpD,YAAY,OAAO,GAAG,4BAA4B;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QAFR,WAAM,GAAG,GAAG,CAAC;QAGpB,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,cAAc;IAGzD,YAAY,UAAkB,EAAE,OAAgB;QAC9C,KAAK,CAAC,OAAO,IAAI,oCAAoC,UAAU,GAAG,CAAC,CAAC;QAH7D,WAAM,GAAG,GAAG,CAAC;QAIpB,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,cAAc;IAExD,YAAY,MAAc,EAAE,OAAgB;QAC1C,KAAK,CAAC,OAAO,IAAI,mBAAmB,MAAM,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export { SatuChainAPI } from "./client.js";
2
+ export { SatuChainError, SatuChainAuthError, SatuChainRateLimitError, SatuChainUpstreamError, } from "./errors.js";
3
+ export type { SatuChainAPIOptions, RequestOptions, CommoditiesResponse, ForexEntry, CryptoEntry, CommodityEntry, RateLimitInfo, } from "./types.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { SatuChainAPI } from "./client.js";
2
+ export { SatuChainError, SatuChainAuthError, SatuChainRateLimitError, SatuChainUpstreamError, } from "./errors.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,65 @@
1
+ export interface ForexEntry {
2
+ name: string;
3
+ /** Units of this currency per 1 USD */
4
+ value: number | null;
5
+ }
6
+ export interface CryptoEntry {
7
+ name: string;
8
+ /** Price in USD */
9
+ value: number | null;
10
+ }
11
+ export interface CommodityEntry {
12
+ name: string;
13
+ /** Price in USD per unit (troy oz for XAU/XAG, lb for COPPER) */
14
+ value: number | null;
15
+ /** Percentage change from previous close (positive = up, negative = down) */
16
+ changePercent?: number | null;
17
+ /** Unit description e.g. "USD/troy oz" */
18
+ unit?: string;
19
+ note?: string;
20
+ }
21
+ export interface RateLimitInfo {
22
+ limit: number;
23
+ remaining: number;
24
+ resetAt: number;
25
+ }
26
+ export interface CommoditiesResponse {
27
+ ok: true;
28
+ base: "USD";
29
+ updatedAtUnix: number | null;
30
+ nextUpdateUnix: number | null;
31
+ crypto: {
32
+ BTC: CryptoEntry;
33
+ BNB: CryptoEntry;
34
+ STU: CryptoEntry;
35
+ };
36
+ forex: {
37
+ CNY: ForexEntry;
38
+ EUR: ForexEntry;
39
+ IDR: ForexEntry;
40
+ JPY: ForexEntry;
41
+ MYR: ForexEntry;
42
+ NGN: ForexEntry;
43
+ SGD: ForexEntry;
44
+ VND: ForexEntry;
45
+ [key: string]: ForexEntry;
46
+ };
47
+ commodities: {
48
+ XAU: CommodityEntry;
49
+ XAG: CommodityEntry;
50
+ COPPER: CommodityEntry;
51
+ };
52
+ }
53
+ export interface SatuChainAPIOptions {
54
+ /** Your API key — starts with sk_live_ */
55
+ apiKey: string;
56
+ /** Base URL (default: https://dev.satuchain.com) */
57
+ baseUrl?: string;
58
+ /** Request timeout in milliseconds (default: 10000) */
59
+ timeout?: number;
60
+ }
61
+ export interface RequestOptions {
62
+ /** AbortSignal for cancellation */
63
+ signal?: AbortSignal;
64
+ }
65
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,KAAK,CAAC;IACZ,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE;QACN,GAAG,EAAE,WAAW,CAAC;QACjB,GAAG,EAAE,WAAW,CAAC;QACjB,GAAG,EAAE,WAAW,CAAC;KAClB,CAAC;IACF,KAAK,EAAE;QACL,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC;KAC3B,CAAC;IACF,WAAW,EAAE;QACX,GAAG,EAAE,cAAc,CAAC;QACpB,GAAG,EAAE,cAAc,CAAC;QACpB,MAAM,EAAE,cAAc,CAAC;KACxB,CAAC;CACH;AAID,MAAM,WAAW,mBAAmB;IAClC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB"}
@@ -0,0 +1,3 @@
1
+ // ─── Response Types ──────────────────────────────────────────────────────────
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,gFAAgF"}
@@ -0,0 +1,33 @@
1
+ import type { SatuChainAPIOptions, RequestOptions, CommoditiesResponse, RateLimitInfo } from "./types.js";
2
+ export declare class SatuChainAPI {
3
+ private readonly apiKey;
4
+ private readonly baseUrl;
5
+ private readonly timeout;
6
+ /** Last rate-limit info from the most recent response */
7
+ rateLimit: RateLimitInfo | null;
8
+ constructor(options: SatuChainAPIOptions | string);
9
+ private request;
10
+ /**
11
+ * Fetch live commodity, forex, and crypto price data.
12
+ *
13
+ * @example
14
+ * const data = await api.getCommodities();
15
+ * console.log(data.forex.IDR.value); // IDR per 1 USD
16
+ * console.log(data.crypto.BTC.value); // BTC price in USD
17
+ * console.log(data.commodities.XAU.value); // Gold price in USD/troy oz
18
+ */
19
+ getCommodities(opts?: RequestOptions): Promise<CommoditiesResponse>;
20
+ /**
21
+ * Get just the forex rates (subset of getCommodities).
22
+ */
23
+ getForex(opts?: RequestOptions): Promise<CommoditiesResponse["forex"]>;
24
+ /**
25
+ * Get just the crypto prices (subset of getCommodities).
26
+ */
27
+ getCrypto(opts?: RequestOptions): Promise<CommoditiesResponse["crypto"]>;
28
+ /**
29
+ * Get just the commodity prices (subset of getCommodities).
30
+ */
31
+ getMetals(opts?: RequestOptions): Promise<CommoditiesResponse["commodities"]>;
32
+ }
33
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,aAAa,EACd,MAAM,YAAY,CAAC;AAWpB,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,yDAAyD;IAClD,SAAS,EAAE,aAAa,GAAG,IAAI,CAAQ;gBAElC,OAAO,EAAE,mBAAmB,GAAG,MAAM;YAgBnC,OAAO;IAiErB;;;;;;;;OAQG;IACG,cAAc,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAIzE;;OAEG;IACG,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAK5E;;OAEG;IACG,SAAS,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAK9E;;OAEG;IACG,SAAS,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC;CAIpF"}
@@ -0,0 +1,17 @@
1
+ export declare class SatuChainError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare class SatuChainAuthError extends SatuChainError {
5
+ readonly status = 401;
6
+ constructor(message?: string);
7
+ }
8
+ export declare class SatuChainRateLimitError extends SatuChainError {
9
+ readonly status = 429;
10
+ readonly retryAfter: number;
11
+ constructor(retryAfter: number, message?: string);
12
+ }
13
+ export declare class SatuChainUpstreamError extends SatuChainError {
14
+ readonly status: number;
15
+ constructor(status: number, message?: string);
16
+ }
17
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,cAAc;IACpD,QAAQ,CAAC,MAAM,OAAO;gBACV,OAAO,SAA+B;CAInD;AAED,qBAAa,uBAAwB,SAAQ,cAAc;IACzD,QAAQ,CAAC,MAAM,OAAO;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAChB,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAKjD;AAED,qBAAa,sBAAuB,SAAQ,cAAc;IACxD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAK7C"}
@@ -0,0 +1,4 @@
1
+ export { SatuChainAPI } from "./client.js";
2
+ export { SatuChainError, SatuChainAuthError, SatuChainRateLimitError, SatuChainUpstreamError, } from "./errors.js";
3
+ export type { SatuChainAPIOptions, RequestOptions, CommoditiesResponse, ForexEntry, CryptoEntry, CommodityEntry, RateLimitInfo, } from "./types.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC"}
@@ -0,0 +1,65 @@
1
+ export interface ForexEntry {
2
+ name: string;
3
+ /** Units of this currency per 1 USD */
4
+ value: number | null;
5
+ }
6
+ export interface CryptoEntry {
7
+ name: string;
8
+ /** Price in USD */
9
+ value: number | null;
10
+ }
11
+ export interface CommodityEntry {
12
+ name: string;
13
+ /** Price in USD per unit (troy oz for XAU/XAG, lb for COPPER) */
14
+ value: number | null;
15
+ /** Percentage change from previous close (positive = up, negative = down) */
16
+ changePercent?: number | null;
17
+ /** Unit description e.g. "USD/troy oz" */
18
+ unit?: string;
19
+ note?: string;
20
+ }
21
+ export interface RateLimitInfo {
22
+ limit: number;
23
+ remaining: number;
24
+ resetAt: number;
25
+ }
26
+ export interface CommoditiesResponse {
27
+ ok: true;
28
+ base: "USD";
29
+ updatedAtUnix: number | null;
30
+ nextUpdateUnix: number | null;
31
+ crypto: {
32
+ BTC: CryptoEntry;
33
+ BNB: CryptoEntry;
34
+ STU: CryptoEntry;
35
+ };
36
+ forex: {
37
+ CNY: ForexEntry;
38
+ EUR: ForexEntry;
39
+ IDR: ForexEntry;
40
+ JPY: ForexEntry;
41
+ MYR: ForexEntry;
42
+ NGN: ForexEntry;
43
+ SGD: ForexEntry;
44
+ VND: ForexEntry;
45
+ [key: string]: ForexEntry;
46
+ };
47
+ commodities: {
48
+ XAU: CommodityEntry;
49
+ XAG: CommodityEntry;
50
+ COPPER: CommodityEntry;
51
+ };
52
+ }
53
+ export interface SatuChainAPIOptions {
54
+ /** Your API key — starts with sk_live_ */
55
+ apiKey: string;
56
+ /** Base URL (default: https://dev.satuchain.com) */
57
+ baseUrl?: string;
58
+ /** Request timeout in milliseconds (default: 10000) */
59
+ timeout?: number;
60
+ }
61
+ export interface RequestOptions {
62
+ /** AbortSignal for cancellation */
63
+ signal?: AbortSignal;
64
+ }
65
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,KAAK,CAAC;IACZ,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE;QACN,GAAG,EAAE,WAAW,CAAC;QACjB,GAAG,EAAE,WAAW,CAAC;QACjB,GAAG,EAAE,WAAW,CAAC;KAClB,CAAC;IACF,KAAK,EAAE;QACL,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,GAAG,EAAE,UAAU,CAAC;QAChB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC;KAC3B,CAAC;IACF,WAAW,EAAE;QACX,GAAG,EAAE,cAAc,CAAC;QACpB,GAAG,EAAE,cAAc,CAAC;QACpB,MAAM,EAAE,cAAc,CAAC;KACxB,CAAC;CACH;AAID,MAAM,WAAW,mBAAmB;IAClC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "satuchain-api",
3
+ "version": "1.0.1",
4
+ "description": "Official JavaScript/TypeScript SDK for the SATUCHAIN Developer API",
5
+ "keywords": ["satuchain", "crypto", "forex", "commodities", "gold", "api", "sdk"],
6
+ "author": "SATU TEAM <dev@satuchain.com>",
7
+ "license": "MIT",
8
+ "homepage": "https://dev.satuchain.com",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/satuchain/dev-api.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/satuchain/dev-api/issues"
15
+ },
16
+ "type": "module",
17
+ "main": "./dist/cjs/index.cjs",
18
+ "module": "./dist/esm/index.js",
19
+ "types": "./dist/types/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "import": "./dist/esm/index.js",
23
+ "require": "./dist/cjs/index.cjs",
24
+ "types": "./dist/types/index.d.ts"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "README.md",
30
+ "LICENSE"
31
+ ],
32
+ "scripts": {
33
+ "build": "npm run build:esm && npm run build:cjs && npm run build:types",
34
+ "build:esm": "tsc -p tsconfig.esm.json",
35
+ "build:cjs": "tsc -p tsconfig.cjs.json && node scripts/rename-cjs.mjs",
36
+ "build:types": "tsc -p tsconfig.types.json",
37
+ "clean": "rm -rf dist"
38
+ },
39
+ "devDependencies": {
40
+ "typescript": "^5.4.0"
41
+ },
42
+ "engines": {
43
+ "node": ">=18.0.0"
44
+ }
45
+ }