@temple-digital-group/temple-canton-js 1.0.39-beta.5 → 2.0.0-beta.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/README.md +8 -83
- package/dist/api/index.d.ts +5 -25
- package/dist/api/index.js +11 -99
- package/dist/api/tokenStore.d.ts +7 -23
- package/dist/api/tokenStore.js +7 -47
- package/dist/api/types.d.ts +0 -23
- package/dist/api/types.js +1 -1
- package/package.json +1 -1
- package/src/api/index.ts +12 -115
- package/src/api/tokenStore.ts +8 -52
- package/src/api/types.ts +1 -30
- package/src/config/index.js +5 -1
package/README.md
CHANGED
|
@@ -12,73 +12,6 @@ npm install @temple-digital-group/temple-canton-js
|
|
|
12
12
|
|
|
13
13
|
Call `initialize()` before using any SDK functions. It sets up the config and optionally authenticates with the Temple REST API.
|
|
14
14
|
|
|
15
|
-
### Custom Validator
|
|
16
|
-
|
|
17
|
-
For apps connecting to your own validator (browser or server-side):
|
|
18
|
-
|
|
19
|
-
```javascript
|
|
20
|
-
import { initialize } from "@temple-digital-group/temple-canton-js";
|
|
21
|
-
|
|
22
|
-
await initialize({
|
|
23
|
-
NETWORK: "mainnet",
|
|
24
|
-
VALIDATOR_API_URL: "https://your-validator-url",
|
|
25
|
-
VALIDATOR_SCAN_API_URL: "https://your-scan-api-url",
|
|
26
|
-
VALIDATOR_USER_PARTY_ID: "your-user-party-id",
|
|
27
|
-
AUTH0_TOKEN_URL: "https://your-auth0-domain/oauth/token",
|
|
28
|
-
AUTH0_USER_ID: "your-auth0-user-id",
|
|
29
|
-
AUTH0_CLIENT_ID: "your-client-id",
|
|
30
|
-
AUTH0_CLIENT_SECRET: "your-client-secret",
|
|
31
|
-
AUTH0_AUDIENCE: "your-audience",
|
|
32
|
-
});
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Custom Validator + REST API
|
|
36
|
-
|
|
37
|
-
To also authenticate with the Temple REST API at init time, pass `API_EMAIL`/`API_PASSWORD`:
|
|
38
|
-
|
|
39
|
-
```javascript
|
|
40
|
-
import { initialize } from "@temple-digital-group/temple-canton-js";
|
|
41
|
-
|
|
42
|
-
await initialize({
|
|
43
|
-
NETWORK: "mainnet",
|
|
44
|
-
VALIDATOR_API_URL: "https://your-validator-url",
|
|
45
|
-
VALIDATOR_SCAN_API_URL: "https://your-scan-api-url",
|
|
46
|
-
VALIDATOR_USER_PARTY_ID: "your-user-party-id",
|
|
47
|
-
AUTH0_TOKEN_URL: "https://your-auth0-domain/oauth/token",
|
|
48
|
-
AUTH0_USER_ID: "your-auth0-user-id",
|
|
49
|
-
AUTH0_CLIENT_ID: "your-client-id",
|
|
50
|
-
AUTH0_CLIENT_SECRET: "your-client-secret",
|
|
51
|
-
AUTH0_AUDIENCE: "your-audience",
|
|
52
|
-
API_EMAIL: "user@example.com",
|
|
53
|
-
API_PASSWORD: "password",
|
|
54
|
-
});
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
| Key | Required | Description |
|
|
58
|
-
| ------------------------- | -------- | ---------------------------------------------------- |
|
|
59
|
-
| `NETWORK` | Yes | `mainnet`, `testnet`, or `localhost` |
|
|
60
|
-
| `VALIDATOR_API_URL` | No | Base URL of the Canton validator ledger API |
|
|
61
|
-
| `VALIDATOR_SCAN_API_URL` | No | Base URL of the Canton Scan API |
|
|
62
|
-
| `VALIDATOR_USER_PARTY_ID` | No | The user's party ID on the network |
|
|
63
|
-
| `JWT_TOKEN` | No\* | Pre-authenticated JWT token for ledger API calls |
|
|
64
|
-
| `AUTH0_TOKEN_URL` | No\* | Auth0 OAuth token endpoint |
|
|
65
|
-
| `AUTH0_CLIENT_ID` | No\* | Auth0 application client ID |
|
|
66
|
-
| `AUTH0_CLIENT_SECRET` | No\* | Auth0 application client secret |
|
|
67
|
-
| `AUTH0_AUDIENCE` | No\* | Auth0 API audience identifier |
|
|
68
|
-
| `AUTH0_USER_ID` | No\* | Auth0 user ID for the service account |
|
|
69
|
-
| `API_EMAIL` | No | Temple REST API email (triggers login at init) |
|
|
70
|
-
| `API_PASSWORD` | No | Temple REST API password (required with `API_EMAIL`) |
|
|
71
|
-
|
|
72
|
-
\* Provide either `JWT_TOKEN` (browser) or the `AUTH0_*` fields (server-side). The SDK fetches and caches JWT tokens automatically when Auth0 credentials are provided. Only needed when using a custom validator.
|
|
73
|
-
|
|
74
|
-
To update the JWT token later without re-initializing:
|
|
75
|
-
|
|
76
|
-
```javascript
|
|
77
|
-
import { setJWTToken } from "@temple-digital-group/temple-canton-js";
|
|
78
|
-
|
|
79
|
-
setJWTToken(newToken);
|
|
80
|
-
```
|
|
81
|
-
|
|
82
15
|
### Wallet Adapter
|
|
83
16
|
|
|
84
17
|
For apps using Loop Wallet. Pass the Loop SDK instance as `WALLET_ADAPTER` — the SDK auto-detects server vs client mode.
|
|
@@ -106,11 +39,8 @@ setWalletAdapter(loop);
|
|
|
106
39
|
| Key | Required | Description |
|
|
107
40
|
| ---------------- | -------- | --------------------------------------------------------------- |
|
|
108
41
|
| `NETWORK` | Yes | `mainnet`, `testnet`, or `localhost` |
|
|
109
|
-
| `WALLET_ADAPTER` |
|
|
110
|
-
|
|
111
|
-
> You can optionally pass `API_EMAIL`/`API_PASSWORD` to any `initialize()` call to also authenticate with the REST API at init time.
|
|
112
|
-
|
|
113
|
-
> **Legacy:** `initializeConfig()` is still available as a sync-only alternative (no REST API auth). `initialize()` is the recommended approach.
|
|
42
|
+
| `WALLET_ADAPTER` | Yes | Loop SDK instance — auto-detects server/client mode for signing |
|
|
43
|
+
| `API_KEY` | No | Temple REST API key for authenticated endpoints |
|
|
114
44
|
|
|
115
45
|
## Supported Instruments
|
|
116
46
|
|
|
@@ -189,9 +119,9 @@ const result = await depositFunds(depositOpts);
|
|
|
189
119
|
| `allocateBefore` | No | ISO timestamp; allocation deadline (default: +1h) |
|
|
190
120
|
| `settleBefore` | No | ISO timestamp; settlement deadline (default: +2h) |
|
|
191
121
|
| `disclosures` | No | Pre-fetched Amulet disclosures (for FE without API access) |
|
|
192
|
-
| `userId` | No |
|
|
122
|
+
| `userId` | No | User ID (falls back to wallet adapter / config) |
|
|
193
123
|
|
|
194
|
-
For Amulet deposits
|
|
124
|
+
For Amulet deposits, the SDK fetches disclosures automatically. You can also pass them manually via `opts.disclosures`.
|
|
195
125
|
|
|
196
126
|
### 3. Trading Balance
|
|
197
127
|
|
|
@@ -298,7 +228,7 @@ Each entry in the returned array contains:
|
|
|
298
228
|
```javascript
|
|
299
229
|
import { mergeAmuletHoldingsForParty, mergeUtilityHoldingsForParty, getAmuletDisclosures, getUtxoCount } from "@temple-digital-group/temple-canton-js";
|
|
300
230
|
|
|
301
|
-
//
|
|
231
|
+
// Merge all Amulet or utility holdings
|
|
302
232
|
await mergeAmuletHoldingsForParty(partyId);
|
|
303
233
|
await mergeUtilityHoldingsForParty(partyId, "USDCx");
|
|
304
234
|
|
|
@@ -324,7 +254,6 @@ const counts = await getUtxoCount(partyId, "USDCx", walletProvider);
|
|
|
324
254
|
| Function | Description |
|
|
325
255
|
| --------------------------- | ----------------------------------------------------------------------------- |
|
|
326
256
|
| `initialize(config)` | Initialize the SDK, set config, and optionally authenticate with the REST API |
|
|
327
|
-
| `setJWTToken(token)` | Update the JWT token without re-initializing the config |
|
|
328
257
|
| `setWalletAdapter(adapter)` | Set or update the Loop SDK instance for all wallet-aware functions |
|
|
329
258
|
|
|
330
259
|
### Instrument Catalog
|
|
@@ -367,21 +296,17 @@ const counts = await getUtxoCount(partyId, "USDCx", walletProvider);
|
|
|
367
296
|
| ------------------------------------------------------------------------------------------ | -------- | ------------------------------ |
|
|
368
297
|
| `mergeAmuletHoldingsForParty(party, returnCommand, provider, maxUtxos, amuletDisclosures)` | **W** | Merge Amulet holdings into one |
|
|
369
298
|
| `mergeUtilityHoldingsForParty(party, utilityAsset, returnCommand, provider, maxUtxos)` | **W** | Merge utility holdings into one |
|
|
370
|
-
| `splitAmuletHoldingForParty(party, outputQuantity)` | | Split an Amulet holding |
|
|
371
|
-
| `unlockLockedAmulets(party)` | | Unlock locked Amulet holdings |
|
|
372
299
|
|
|
373
300
|
### Temple REST API
|
|
374
301
|
|
|
375
|
-
> These functions call the Temple REST API. Pass `
|
|
302
|
+
> These functions call the Temple REST API. Pass `API_KEY` in `initialize()` or call `setApiKey()` to authenticate.
|
|
376
303
|
|
|
377
304
|
#### Auth
|
|
378
305
|
|
|
379
306
|
| Function | Description |
|
|
380
307
|
| ----------------------------------- | --------------------------------------------------- |
|
|
381
|
-
| `
|
|
382
|
-
| `
|
|
383
|
-
| `logout()` | Clear stored tokens |
|
|
384
|
-
| `getUserId()` | Get the stored user ID from login |
|
|
308
|
+
| `setApiKey(key)` | Set the API key for REST API authentication |
|
|
309
|
+
| `getUserId()` | Get the stored user ID |
|
|
385
310
|
|
|
386
311
|
#### Market Data
|
|
387
312
|
|
package/dist/api/index.d.ts
CHANGED
|
@@ -1,32 +1,13 @@
|
|
|
1
|
-
import type { ApiError,
|
|
2
|
-
export type { ApiError,
|
|
1
|
+
import type { ApiError, Ticker, OrderBook, OrderBookOptions, SymbolConfig, OpenInterest, Trade, RecentTradesOptions, ActiveOrder, ActiveOrdersOptions, CancelOrderResponse, CancelAllOrdersOptions, CancelAllOrdersResponse, CreateOrderRequestOpts, CreateOrderRequestResponse, DelegationResponse, WithdrawalResponse, WithdrawalStatusResponse, TradingBalanceResponse, AmuletDisclosure, DisclosuresResponse } from "./types.js";
|
|
2
|
+
export type { ApiError, Ticker, OrderBook, OrderBookOptions, SymbolConfig, OpenInterest, Trade, RecentTradesOptions, ActiveOrder, ActiveOrdersOptions, CancelOrderResponse, CancelAllOrdersOptions, CancelAllOrdersResponse, CreateOrderRequestResponse, DelegationResponse, WithdrawalResponse, WithdrawalStatusResponse, TradingBalanceResponse, AmuletDisclosure, DisclosuresResponse, };
|
|
3
3
|
export { setApiKey, getUserId } from "./tokenStore.js";
|
|
4
4
|
export { setWalletAdapter } from "../../src/config/index.js";
|
|
5
5
|
/**
|
|
6
|
-
* Initialize the Temple SDK — sets config and
|
|
7
|
-
* Pass `API_EMAIL`/`API_PASSWORD` or `API_KEY` to authenticate eagerly at init time.
|
|
6
|
+
* Initialize the Temple SDK — sets config and authenticates with the REST API via API key.
|
|
8
7
|
*
|
|
9
|
-
* @returns
|
|
10
|
-
* Returns `null` if no API credentials were provided (config-only init).
|
|
8
|
+
* @returns null (config-only init). Throws no errors.
|
|
11
9
|
*/
|
|
12
|
-
export declare function initialize(cfg: Record<string, unknown>): Promise<
|
|
13
|
-
/**
|
|
14
|
-
* Login to the Temple REST API with email and password.
|
|
15
|
-
* Stores tokens automatically for subsequent API calls.
|
|
16
|
-
* @param email - User email
|
|
17
|
-
* @param password - User password
|
|
18
|
-
*/
|
|
19
|
-
export declare function login(email: string, password: string): Promise<LoginResponse | ApiError>;
|
|
20
|
-
/**
|
|
21
|
-
* Refresh the access token using the stored or provided refresh token.
|
|
22
|
-
* Updates the token store automatically on success.
|
|
23
|
-
* @param refreshTokenOverride - Optional explicit refresh token (uses stored one if omitted)
|
|
24
|
-
*/
|
|
25
|
-
export declare function refreshAccessToken(refreshTokenOverride?: string): Promise<RefreshResponse | ApiError>;
|
|
26
|
-
/**
|
|
27
|
-
* Logout: clear all stored REST API tokens.
|
|
28
|
-
*/
|
|
29
|
-
export declare function logout(): void;
|
|
10
|
+
export declare function initialize(cfg: Record<string, unknown>): Promise<null>;
|
|
30
11
|
/**
|
|
31
12
|
* Get ticker data for one or all trading pairs.
|
|
32
13
|
* @param symbol - Optional symbol filter (e.g., "Amulet/USDCx")
|
|
@@ -77,7 +58,6 @@ export declare function cancelAllOrders(options?: CancelAllOrdersOptions): Promi
|
|
|
77
58
|
export declare function getDisclosures(partyId: string): Promise<DisclosuresResponse | ApiError>;
|
|
78
59
|
/**
|
|
79
60
|
* Get the user's trading delegation status.
|
|
80
|
-
* The user ID is extracted from the JWT token automatically.
|
|
81
61
|
*/
|
|
82
62
|
export declare function getDelegation(): Promise<DelegationResponse | ApiError>;
|
|
83
63
|
/**
|
package/dist/api/index.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import config, { initializeConfig, setWalletAdapter } from "../../src/config/index.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getApiKey, setApiKey as setApiKeyFromConfig, getAuthHeader, setUserId, } from "./tokenStore.js";
|
|
4
4
|
export { setApiKey, getUserId } from "./tokenStore.js";
|
|
5
5
|
export { setWalletAdapter } from "../../src/config/index.js";
|
|
6
6
|
// ── Initialization ──
|
|
7
7
|
/**
|
|
8
|
-
* Initialize the Temple SDK — sets config and
|
|
9
|
-
* Pass `API_EMAIL`/`API_PASSWORD` or `API_KEY` to authenticate eagerly at init time.
|
|
8
|
+
* Initialize the Temple SDK — sets config and authenticates with the REST API via API key.
|
|
10
9
|
*
|
|
11
|
-
* @returns
|
|
12
|
-
* Returns `null` if no API credentials were provided (config-only init).
|
|
10
|
+
* @returns null (config-only init). Throws no errors.
|
|
13
11
|
*/
|
|
14
12
|
export async function initialize(cfg) {
|
|
15
13
|
initializeConfig(cfg);
|
|
@@ -19,18 +17,14 @@ export async function initialize(cfg) {
|
|
|
19
17
|
const apiKey = cfg.API_KEY;
|
|
20
18
|
if (apiKey) {
|
|
21
19
|
setApiKeyFromConfig(apiKey);
|
|
22
|
-
return null;
|
|
23
20
|
}
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return login(email, password);
|
|
21
|
+
const userIdValue = cfg.USER_ID;
|
|
22
|
+
if (userIdValue) {
|
|
23
|
+
setUserId(userIdValue);
|
|
28
24
|
}
|
|
29
25
|
return null;
|
|
30
26
|
}
|
|
31
27
|
// ── Internal helpers ──
|
|
32
|
-
/** Pending auto-login promise for dedup. */
|
|
33
|
-
let autoLoginPromise = null;
|
|
34
28
|
function handleApiError(error, context) {
|
|
35
29
|
const err = error;
|
|
36
30
|
const status = err.response?.status ?? null;
|
|
@@ -42,49 +36,18 @@ function handleApiError(error, context) {
|
|
|
42
36
|
console.error(`[Temple API] ${context}: ${message}${status ? ` (HTTP ${status})` : ""}`);
|
|
43
37
|
return { error: true, status, code, message };
|
|
44
38
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
async function ensureAuthenticated() {
|
|
48
|
-
// API key takes priority — no login needed
|
|
39
|
+
function ensureAuthenticated() {
|
|
40
|
+
// API key from config if not already set
|
|
49
41
|
const configApiKey = config.API_KEY;
|
|
50
42
|
if (!getApiKey() && configApiKey) {
|
|
51
43
|
setApiKeyFromConfig(configApiKey);
|
|
52
44
|
}
|
|
53
45
|
if (getApiKey())
|
|
54
46
|
return null;
|
|
55
|
-
|
|
56
|
-
if (!getAccessToken()) {
|
|
57
|
-
const email = config.API_EMAIL;
|
|
58
|
-
const password = config.API_PASSWORD;
|
|
59
|
-
if (email && password) {
|
|
60
|
-
if (!autoLoginPromise) {
|
|
61
|
-
autoLoginPromise = login(email, password).finally(() => {
|
|
62
|
-
autoLoginPromise = null;
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
const result = await autoLoginPromise;
|
|
66
|
-
if ("error" in result && result.error)
|
|
67
|
-
return result;
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
return { error: true, status: 401, code: "NOT_AUTHENTICATED", message: "Not logged in. Call login() or provide API_EMAIL/API_PASSWORD in config." };
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// Auto-refresh if expired
|
|
74
|
-
if (isTokenExpired()) {
|
|
75
|
-
if (!refreshPromise) {
|
|
76
|
-
refreshPromise = refreshAccessToken().finally(() => {
|
|
77
|
-
refreshPromise = null;
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
const result = await refreshPromise;
|
|
81
|
-
if ("error" in result && result.error)
|
|
82
|
-
return result;
|
|
83
|
-
}
|
|
84
|
-
return null;
|
|
47
|
+
return { error: true, status: 401, code: "NOT_AUTHENTICATED", message: "API key required. Pass API_KEY in initialize() or call setApiKey()." };
|
|
85
48
|
}
|
|
86
49
|
async function authenticatedGet(path, params) {
|
|
87
|
-
const authError =
|
|
50
|
+
const authError = ensureAuthenticated();
|
|
88
51
|
if (authError)
|
|
89
52
|
return authError;
|
|
90
53
|
const headers = {
|
|
@@ -111,7 +74,7 @@ async function authenticatedGet(path, params) {
|
|
|
111
74
|
}
|
|
112
75
|
}
|
|
113
76
|
async function authenticatedPost(path, body) {
|
|
114
|
-
const authError =
|
|
77
|
+
const authError = ensureAuthenticated();
|
|
115
78
|
if (authError)
|
|
116
79
|
return authError;
|
|
117
80
|
const headers = {
|
|
@@ -126,56 +89,6 @@ async function authenticatedPost(path, body) {
|
|
|
126
89
|
return handleApiError(error, `POST ${path}`);
|
|
127
90
|
}
|
|
128
91
|
}
|
|
129
|
-
// ── Auth ──
|
|
130
|
-
/**
|
|
131
|
-
* Login to the Temple REST API with email and password.
|
|
132
|
-
* Stores tokens automatically for subsequent API calls.
|
|
133
|
-
* @param email - User email
|
|
134
|
-
* @param password - User password
|
|
135
|
-
*/
|
|
136
|
-
export async function login(email, password) {
|
|
137
|
-
if (!email || !password) {
|
|
138
|
-
return { error: true, status: null, code: "INVALID_PARAMS", message: "Email and password are required." };
|
|
139
|
-
}
|
|
140
|
-
try {
|
|
141
|
-
const response = await axios.post(`${config.API_BASE_URL}/auth/login`, {
|
|
142
|
-
email,
|
|
143
|
-
password,
|
|
144
|
-
});
|
|
145
|
-
setTokens(response.data);
|
|
146
|
-
return response.data;
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
return handleApiError(error, "login");
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Refresh the access token using the stored or provided refresh token.
|
|
154
|
-
* Updates the token store automatically on success.
|
|
155
|
-
* @param refreshTokenOverride - Optional explicit refresh token (uses stored one if omitted)
|
|
156
|
-
*/
|
|
157
|
-
export async function refreshAccessToken(refreshTokenOverride) {
|
|
158
|
-
const token = refreshTokenOverride ?? getRefreshToken();
|
|
159
|
-
if (!token) {
|
|
160
|
-
return { error: true, status: null, code: "NO_REFRESH_TOKEN", message: "No refresh token available. Call login() first." };
|
|
161
|
-
}
|
|
162
|
-
try {
|
|
163
|
-
const response = await axios.post(`${config.API_BASE_URL}/auth/refresh`, {
|
|
164
|
-
refresh_token: token,
|
|
165
|
-
});
|
|
166
|
-
setTokens(response.data);
|
|
167
|
-
return response.data;
|
|
168
|
-
}
|
|
169
|
-
catch (error) {
|
|
170
|
-
return handleApiError(error, "refreshAccessToken");
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Logout: clear all stored REST API tokens.
|
|
175
|
-
*/
|
|
176
|
-
export function logout() {
|
|
177
|
-
clearTokens();
|
|
178
|
-
}
|
|
179
92
|
// ── Helpers ──
|
|
180
93
|
/** Normalize CC → Amulet in symbol strings (e.g. "CC/SBC" → "Amulet/SBC", "CC" → "Amulet") */
|
|
181
94
|
function normalizeSymbol(symbol) {
|
|
@@ -281,7 +194,6 @@ export async function getDisclosures(partyId) {
|
|
|
281
194
|
// ── Delegation ──
|
|
282
195
|
/**
|
|
283
196
|
* Get the user's trading delegation status.
|
|
284
|
-
* The user ID is extracted from the JWT token automatically.
|
|
285
197
|
*/
|
|
286
198
|
export async function getDelegation() {
|
|
287
199
|
return authenticatedGet("/api/trading/delegation");
|
package/dist/api/tokenStore.d.ts
CHANGED
|
@@ -1,30 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AuthHeaders } from "./types.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*/
|
|
5
|
-
export declare function setTokens(data: TokenData): void;
|
|
6
|
-
/**
|
|
7
|
-
* Get the current access token, or null if not logged in.
|
|
8
|
-
*/
|
|
9
|
-
export declare function getAccessToken(): string | null;
|
|
10
|
-
/**
|
|
11
|
-
* Get the stored refresh token, or null if not logged in.
|
|
12
|
-
*/
|
|
13
|
-
export declare function getRefreshToken(): string | null;
|
|
14
|
-
/**
|
|
15
|
-
* Check if the current access token is expired (with 60-second buffer).
|
|
16
|
-
*/
|
|
17
|
-
export declare function isTokenExpired(): boolean;
|
|
18
|
-
/**
|
|
19
|
-
* Get the stored user ID from login, or null if not logged in.
|
|
3
|
+
* Get the stored user ID, or null if not set.
|
|
20
4
|
*/
|
|
21
5
|
export declare function getUserId(): string | null;
|
|
22
6
|
/**
|
|
23
|
-
*
|
|
7
|
+
* Set the user ID directly (e.g. from config at init time).
|
|
24
8
|
*/
|
|
25
|
-
export declare function
|
|
9
|
+
export declare function setUserId(id: string): void;
|
|
26
10
|
/**
|
|
27
|
-
* Set an API key for authentication
|
|
11
|
+
* Set an API key for authentication.
|
|
28
12
|
*/
|
|
29
13
|
export declare function setApiKey(key: string): void;
|
|
30
14
|
/**
|
|
@@ -32,7 +16,7 @@ export declare function setApiKey(key: string): void;
|
|
|
32
16
|
*/
|
|
33
17
|
export declare function getApiKey(): string | null;
|
|
34
18
|
/**
|
|
35
|
-
* Get the authorization header
|
|
36
|
-
* Returns null if
|
|
19
|
+
* Get the authorization header using the API key.
|
|
20
|
+
* Returns null if no API key is set.
|
|
37
21
|
*/
|
|
38
22
|
export declare function getAuthHeader(): AuthHeaders | null;
|
package/dist/api/tokenStore.js
CHANGED
|
@@ -1,56 +1,19 @@
|
|
|
1
|
-
let accessToken = null;
|
|
2
|
-
let refreshToken = null;
|
|
3
|
-
let tokenExpiryTime = null;
|
|
4
1
|
let apiKey = null;
|
|
5
2
|
let userId = null;
|
|
6
3
|
/**
|
|
7
|
-
*
|
|
8
|
-
*/
|
|
9
|
-
export function setTokens(data) {
|
|
10
|
-
accessToken = data.access_token;
|
|
11
|
-
refreshToken = data.refresh_token;
|
|
12
|
-
tokenExpiryTime = Date.now() + data.expires_in * 1000;
|
|
13
|
-
if (data.user?.user_id != null) {
|
|
14
|
-
userId = String(data.user.user_id);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Get the current access token, or null if not logged in.
|
|
19
|
-
*/
|
|
20
|
-
export function getAccessToken() {
|
|
21
|
-
return accessToken;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Get the stored refresh token, or null if not logged in.
|
|
25
|
-
*/
|
|
26
|
-
export function getRefreshToken() {
|
|
27
|
-
return refreshToken;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Check if the current access token is expired (with 60-second buffer).
|
|
31
|
-
*/
|
|
32
|
-
export function isTokenExpired() {
|
|
33
|
-
if (!tokenExpiryTime)
|
|
34
|
-
return true;
|
|
35
|
-
return Date.now() >= tokenExpiryTime - 60000;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Get the stored user ID from login, or null if not logged in.
|
|
4
|
+
* Get the stored user ID, or null if not set.
|
|
39
5
|
*/
|
|
40
6
|
export function getUserId() {
|
|
41
7
|
return userId;
|
|
42
8
|
}
|
|
43
9
|
/**
|
|
44
|
-
*
|
|
10
|
+
* Set the user ID directly (e.g. from config at init time).
|
|
45
11
|
*/
|
|
46
|
-
export function
|
|
47
|
-
|
|
48
|
-
refreshToken = null;
|
|
49
|
-
tokenExpiryTime = null;
|
|
50
|
-
userId = null;
|
|
12
|
+
export function setUserId(id) {
|
|
13
|
+
userId = id;
|
|
51
14
|
}
|
|
52
15
|
/**
|
|
53
|
-
* Set an API key for authentication
|
|
16
|
+
* Set an API key for authentication.
|
|
54
17
|
*/
|
|
55
18
|
export function setApiKey(key) {
|
|
56
19
|
apiKey = key;
|
|
@@ -62,15 +25,12 @@ export function getApiKey() {
|
|
|
62
25
|
return apiKey;
|
|
63
26
|
}
|
|
64
27
|
/**
|
|
65
|
-
* Get the authorization header
|
|
66
|
-
* Returns null if
|
|
28
|
+
* Get the authorization header using the API key.
|
|
29
|
+
* Returns null if no API key is set.
|
|
67
30
|
*/
|
|
68
31
|
export function getAuthHeader() {
|
|
69
32
|
if (apiKey) {
|
|
70
33
|
return { Authorization: `Bearer ${apiKey}` };
|
|
71
34
|
}
|
|
72
|
-
if (accessToken) {
|
|
73
|
-
return { Authorization: `Bearer ${accessToken}` };
|
|
74
|
-
}
|
|
75
35
|
return null;
|
|
76
36
|
}
|
package/dist/api/types.d.ts
CHANGED
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
export interface LoginUser {
|
|
2
|
-
user_id: number;
|
|
3
|
-
max_limit_orders: number;
|
|
4
|
-
max_market_orders: number;
|
|
5
|
-
}
|
|
6
|
-
export interface LoginResponse {
|
|
7
|
-
access_token: string;
|
|
8
|
-
refresh_token: string;
|
|
9
|
-
expires_in: number;
|
|
10
|
-
token_type: string;
|
|
11
|
-
user: LoginUser;
|
|
12
|
-
}
|
|
13
|
-
export interface RefreshResponse {
|
|
14
|
-
access_token: string;
|
|
15
|
-
refresh_token: string;
|
|
16
|
-
expires_in: number;
|
|
17
|
-
}
|
|
18
1
|
export interface Ticker {
|
|
19
2
|
symbol: string;
|
|
20
3
|
last_price: string;
|
|
@@ -161,12 +144,6 @@ export interface ApiError {
|
|
|
161
144
|
code: string | null;
|
|
162
145
|
message: string;
|
|
163
146
|
}
|
|
164
|
-
export interface TokenData {
|
|
165
|
-
access_token: string;
|
|
166
|
-
refresh_token: string;
|
|
167
|
-
expires_in: number;
|
|
168
|
-
user?: LoginUser;
|
|
169
|
-
}
|
|
170
147
|
export interface AuthHeaders {
|
|
171
148
|
Authorization: string;
|
|
172
149
|
}
|
package/dist/api/types.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// ──
|
|
1
|
+
// ── Market Data ──
|
|
2
2
|
export {};
|
package/package.json
CHANGED
package/src/api/index.ts
CHANGED
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
import axios, { type AxiosRequestConfig } from "axios";
|
|
2
2
|
import config, { initializeConfig, setWalletAdapter } from "../../src/config/index.js";
|
|
3
3
|
import {
|
|
4
|
-
setTokens,
|
|
5
|
-
getAccessToken,
|
|
6
|
-
getRefreshToken,
|
|
7
4
|
getApiKey,
|
|
8
5
|
setApiKey as setApiKeyFromConfig,
|
|
9
|
-
isTokenExpired,
|
|
10
|
-
clearTokens,
|
|
11
6
|
getAuthHeader,
|
|
7
|
+
setUserId,
|
|
12
8
|
} from "./tokenStore.js";
|
|
13
9
|
import type {
|
|
14
10
|
ApiError,
|
|
15
|
-
LoginUser,
|
|
16
|
-
LoginResponse,
|
|
17
|
-
RefreshResponse,
|
|
18
11
|
Ticker,
|
|
19
12
|
OrderBook,
|
|
20
13
|
OrderBookOptions,
|
|
@@ -40,9 +33,6 @@ import type {
|
|
|
40
33
|
// Re-export types and token utilities consumers may need
|
|
41
34
|
export type {
|
|
42
35
|
ApiError,
|
|
43
|
-
LoginUser,
|
|
44
|
-
LoginResponse,
|
|
45
|
-
RefreshResponse,
|
|
46
36
|
Ticker,
|
|
47
37
|
OrderBook,
|
|
48
38
|
OrderBookOptions,
|
|
@@ -69,13 +59,11 @@ export { setWalletAdapter } from "../../src/config/index.js";
|
|
|
69
59
|
// ── Initialization ──
|
|
70
60
|
|
|
71
61
|
/**
|
|
72
|
-
* Initialize the Temple SDK — sets config and
|
|
73
|
-
* Pass `API_EMAIL`/`API_PASSWORD` or `API_KEY` to authenticate eagerly at init time.
|
|
62
|
+
* Initialize the Temple SDK — sets config and authenticates with the REST API via API key.
|
|
74
63
|
*
|
|
75
|
-
* @returns
|
|
76
|
-
* Returns `null` if no API credentials were provided (config-only init).
|
|
64
|
+
* @returns null (config-only init). Throws no errors.
|
|
77
65
|
*/
|
|
78
|
-
export async function initialize(cfg: Record<string, unknown>): Promise<
|
|
66
|
+
export async function initialize(cfg: Record<string, unknown>): Promise<null> {
|
|
79
67
|
initializeConfig(cfg);
|
|
80
68
|
|
|
81
69
|
if (cfg.WALLET_ADAPTER) {
|
|
@@ -85,13 +73,11 @@ export async function initialize(cfg: Record<string, unknown>): Promise<LoginRes
|
|
|
85
73
|
const apiKey = cfg.API_KEY as string | undefined;
|
|
86
74
|
if (apiKey) {
|
|
87
75
|
setApiKeyFromConfig(apiKey);
|
|
88
|
-
return null;
|
|
89
76
|
}
|
|
90
77
|
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return login(email, password);
|
|
78
|
+
const userIdValue = cfg.USER_ID as string | undefined;
|
|
79
|
+
if (userIdValue) {
|
|
80
|
+
setUserId(userIdValue);
|
|
95
81
|
}
|
|
96
82
|
|
|
97
83
|
return null;
|
|
@@ -99,9 +85,6 @@ export async function initialize(cfg: Record<string, unknown>): Promise<LoginRes
|
|
|
99
85
|
|
|
100
86
|
// ── Internal helpers ──
|
|
101
87
|
|
|
102
|
-
/** Pending auto-login promise for dedup. */
|
|
103
|
-
let autoLoginPromise: Promise<LoginResponse | ApiError> | null = null;
|
|
104
|
-
|
|
105
88
|
function handleApiError(error: unknown, context: string): ApiError {
|
|
106
89
|
const err = error as { response?: { status?: number; data?: { message?: string; error?: string; code?: string } }; message?: string };
|
|
107
90
|
const status = err.response?.status ?? null;
|
|
@@ -117,50 +100,19 @@ function handleApiError(error: unknown, context: string): ApiError {
|
|
|
117
100
|
return { error: true, status, code, message };
|
|
118
101
|
}
|
|
119
102
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
async function ensureAuthenticated(): Promise<ApiError | null> {
|
|
124
|
-
// API key takes priority — no login needed
|
|
103
|
+
function ensureAuthenticated(): ApiError | null {
|
|
104
|
+
// API key from config if not already set
|
|
125
105
|
const configApiKey = (config as Record<string, unknown>).API_KEY as string | undefined;
|
|
126
106
|
if (!getApiKey() && configApiKey) {
|
|
127
107
|
setApiKeyFromConfig(configApiKey);
|
|
128
108
|
}
|
|
129
109
|
if (getApiKey()) return null;
|
|
130
110
|
|
|
131
|
-
|
|
132
|
-
if (!getAccessToken()) {
|
|
133
|
-
const email = (config as Record<string, unknown>).API_EMAIL as string | undefined;
|
|
134
|
-
const password = (config as Record<string, unknown>).API_PASSWORD as string | undefined;
|
|
135
|
-
if (email && password) {
|
|
136
|
-
if (!autoLoginPromise) {
|
|
137
|
-
autoLoginPromise = login(email, password).finally(() => {
|
|
138
|
-
autoLoginPromise = null;
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
const result = await autoLoginPromise;
|
|
142
|
-
if ("error" in result && result.error) return result as ApiError;
|
|
143
|
-
} else {
|
|
144
|
-
return { error: true, status: 401, code: "NOT_AUTHENTICATED", message: "Not logged in. Call login() or provide API_EMAIL/API_PASSWORD in config." };
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Auto-refresh if expired
|
|
149
|
-
if (isTokenExpired()) {
|
|
150
|
-
if (!refreshPromise) {
|
|
151
|
-
refreshPromise = refreshAccessToken().finally(() => {
|
|
152
|
-
refreshPromise = null;
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
const result = await refreshPromise;
|
|
156
|
-
if ("error" in result && result.error) return result as ApiError;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return null;
|
|
111
|
+
return { error: true, status: 401, code: "NOT_AUTHENTICATED", message: "API key required. Pass API_KEY in initialize() or call setApiKey()." };
|
|
160
112
|
}
|
|
161
113
|
|
|
162
114
|
async function authenticatedGet<T>(path: string, params?: Record<string, string | number | undefined>): Promise<T | ApiError> {
|
|
163
|
-
const authError =
|
|
115
|
+
const authError = ensureAuthenticated();
|
|
164
116
|
if (authError) return authError;
|
|
165
117
|
|
|
166
118
|
const headers = {
|
|
@@ -188,7 +140,7 @@ async function authenticatedGet<T>(path: string, params?: Record<string, string
|
|
|
188
140
|
}
|
|
189
141
|
|
|
190
142
|
async function authenticatedPost<T>(path: string, body?: Record<string, unknown>): Promise<T | ApiError> {
|
|
191
|
-
const authError =
|
|
143
|
+
const authError = ensureAuthenticated();
|
|
192
144
|
if (authError) return authError;
|
|
193
145
|
|
|
194
146
|
const headers = {
|
|
@@ -204,60 +156,6 @@ async function authenticatedPost<T>(path: string, body?: Record<string, unknown>
|
|
|
204
156
|
}
|
|
205
157
|
}
|
|
206
158
|
|
|
207
|
-
// ── Auth ──
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Login to the Temple REST API with email and password.
|
|
211
|
-
* Stores tokens automatically for subsequent API calls.
|
|
212
|
-
* @param email - User email
|
|
213
|
-
* @param password - User password
|
|
214
|
-
*/
|
|
215
|
-
export async function login(email: string, password: string): Promise<LoginResponse | ApiError> {
|
|
216
|
-
if (!email || !password) {
|
|
217
|
-
return { error: true, status: null, code: "INVALID_PARAMS", message: "Email and password are required." };
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
try {
|
|
221
|
-
const response = await axios.post<LoginResponse>(`${config.API_BASE_URL}/auth/login`, {
|
|
222
|
-
email,
|
|
223
|
-
password,
|
|
224
|
-
});
|
|
225
|
-
setTokens(response.data);
|
|
226
|
-
return response.data;
|
|
227
|
-
} catch (error) {
|
|
228
|
-
return handleApiError(error, "login");
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Refresh the access token using the stored or provided refresh token.
|
|
234
|
-
* Updates the token store automatically on success.
|
|
235
|
-
* @param refreshTokenOverride - Optional explicit refresh token (uses stored one if omitted)
|
|
236
|
-
*/
|
|
237
|
-
export async function refreshAccessToken(refreshTokenOverride?: string): Promise<RefreshResponse | ApiError> {
|
|
238
|
-
const token = refreshTokenOverride ?? getRefreshToken();
|
|
239
|
-
if (!token) {
|
|
240
|
-
return { error: true, status: null, code: "NO_REFRESH_TOKEN", message: "No refresh token available. Call login() first." };
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
try {
|
|
244
|
-
const response = await axios.post<RefreshResponse>(`${config.API_BASE_URL}/auth/refresh`, {
|
|
245
|
-
refresh_token: token,
|
|
246
|
-
});
|
|
247
|
-
setTokens(response.data);
|
|
248
|
-
return response.data;
|
|
249
|
-
} catch (error) {
|
|
250
|
-
return handleApiError(error, "refreshAccessToken");
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Logout: clear all stored REST API tokens.
|
|
256
|
-
*/
|
|
257
|
-
export function logout(): void {
|
|
258
|
-
clearTokens();
|
|
259
|
-
}
|
|
260
|
-
|
|
261
159
|
// ── Helpers ──
|
|
262
160
|
|
|
263
161
|
/** Normalize CC → Amulet in symbol strings (e.g. "CC/SBC" → "Amulet/SBC", "CC" → "Amulet") */
|
|
@@ -378,7 +276,6 @@ export async function getDisclosures(partyId: string): Promise<DisclosuresRespon
|
|
|
378
276
|
|
|
379
277
|
/**
|
|
380
278
|
* Get the user's trading delegation status.
|
|
381
|
-
* The user ID is extracted from the JWT token automatically.
|
|
382
279
|
*/
|
|
383
280
|
export async function getDelegation(): Promise<DelegationResponse | ApiError> {
|
|
384
281
|
return authenticatedGet("/api/trading/delegation");
|
package/src/api/tokenStore.ts
CHANGED
|
@@ -1,65 +1,24 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AuthHeaders } from "./types.js";
|
|
2
2
|
|
|
3
|
-
let accessToken: string | null = null;
|
|
4
|
-
let refreshToken: string | null = null;
|
|
5
|
-
let tokenExpiryTime: number | null = null;
|
|
6
3
|
let apiKey: string | null = null;
|
|
7
4
|
let userId: string | null = null;
|
|
8
5
|
|
|
9
6
|
/**
|
|
10
|
-
*
|
|
11
|
-
*/
|
|
12
|
-
export function setTokens(data: TokenData): void {
|
|
13
|
-
accessToken = data.access_token;
|
|
14
|
-
refreshToken = data.refresh_token;
|
|
15
|
-
tokenExpiryTime = Date.now() + data.expires_in * 1000;
|
|
16
|
-
if (data.user?.user_id != null) {
|
|
17
|
-
userId = String(data.user.user_id);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Get the current access token, or null if not logged in.
|
|
23
|
-
*/
|
|
24
|
-
export function getAccessToken(): string | null {
|
|
25
|
-
return accessToken;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Get the stored refresh token, or null if not logged in.
|
|
30
|
-
*/
|
|
31
|
-
export function getRefreshToken(): string | null {
|
|
32
|
-
return refreshToken;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Check if the current access token is expired (with 60-second buffer).
|
|
37
|
-
*/
|
|
38
|
-
export function isTokenExpired(): boolean {
|
|
39
|
-
if (!tokenExpiryTime) return true;
|
|
40
|
-
return Date.now() >= tokenExpiryTime - 60_000;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Get the stored user ID from login, or null if not logged in.
|
|
7
|
+
* Get the stored user ID, or null if not set.
|
|
45
8
|
*/
|
|
46
9
|
export function getUserId(): string | null {
|
|
47
10
|
return userId;
|
|
48
11
|
}
|
|
49
12
|
|
|
50
|
-
|
|
51
13
|
/**
|
|
52
|
-
*
|
|
14
|
+
* Set the user ID directly (e.g. from config at init time).
|
|
53
15
|
*/
|
|
54
|
-
export function
|
|
55
|
-
|
|
56
|
-
refreshToken = null;
|
|
57
|
-
tokenExpiryTime = null;
|
|
58
|
-
userId = null;
|
|
16
|
+
export function setUserId(id: string): void {
|
|
17
|
+
userId = id;
|
|
59
18
|
}
|
|
60
19
|
|
|
61
20
|
/**
|
|
62
|
-
* Set an API key for authentication
|
|
21
|
+
* Set an API key for authentication.
|
|
63
22
|
*/
|
|
64
23
|
export function setApiKey(key: string): void {
|
|
65
24
|
apiKey = key;
|
|
@@ -73,15 +32,12 @@ export function getApiKey(): string | null {
|
|
|
73
32
|
}
|
|
74
33
|
|
|
75
34
|
/**
|
|
76
|
-
* Get the authorization header
|
|
77
|
-
* Returns null if
|
|
35
|
+
* Get the authorization header using the API key.
|
|
36
|
+
* Returns null if no API key is set.
|
|
78
37
|
*/
|
|
79
38
|
export function getAuthHeader(): AuthHeaders | null {
|
|
80
39
|
if (apiKey) {
|
|
81
40
|
return { Authorization: `Bearer ${apiKey}` };
|
|
82
41
|
}
|
|
83
|
-
if (accessToken) {
|
|
84
|
-
return { Authorization: `Bearer ${accessToken}` };
|
|
85
|
-
}
|
|
86
42
|
return null;
|
|
87
43
|
}
|
package/src/api/types.ts
CHANGED
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
// ── Auth ──
|
|
2
|
-
|
|
3
|
-
export interface LoginUser {
|
|
4
|
-
user_id: number;
|
|
5
|
-
max_limit_orders: number;
|
|
6
|
-
max_market_orders: number;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface LoginResponse {
|
|
10
|
-
access_token: string;
|
|
11
|
-
refresh_token: string;
|
|
12
|
-
expires_in: number;
|
|
13
|
-
token_type: string;
|
|
14
|
-
user: LoginUser;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface RefreshResponse {
|
|
18
|
-
access_token: string;
|
|
19
|
-
refresh_token: string;
|
|
20
|
-
expires_in: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
1
|
// ── Market Data ──
|
|
24
2
|
|
|
25
3
|
export interface Ticker {
|
|
@@ -209,14 +187,7 @@ export interface ApiError {
|
|
|
209
187
|
message: string;
|
|
210
188
|
}
|
|
211
189
|
|
|
212
|
-
// ──
|
|
213
|
-
|
|
214
|
-
export interface TokenData {
|
|
215
|
-
access_token: string;
|
|
216
|
-
refresh_token: string;
|
|
217
|
-
expires_in: number;
|
|
218
|
-
user?: LoginUser;
|
|
219
|
-
}
|
|
190
|
+
// ── Auth ──
|
|
220
191
|
|
|
221
192
|
export interface AuthHeaders {
|
|
222
193
|
Authorization: string;
|
package/src/config/index.js
CHANGED
|
@@ -114,7 +114,11 @@ const config = {
|
|
|
114
114
|
get NETWORK() { return getConfigValue("NETWORK") || NETWORK_MAINNET; },
|
|
115
115
|
|
|
116
116
|
// Temple REST API
|
|
117
|
-
get API_BASE_URL() {
|
|
117
|
+
get API_BASE_URL() {
|
|
118
|
+
const network = getConfigValue("NETWORK") || NETWORK_MAINNET;
|
|
119
|
+
if (network === NETWORK_TESTNET) return "https://api-testnet.templedigitalgroup.com";
|
|
120
|
+
return "https://api.templedigitalgroup.com";
|
|
121
|
+
},
|
|
118
122
|
get API_EMAIL() { return getConfigValue("API_EMAIL"); },
|
|
119
123
|
get API_PASSWORD() { return getConfigValue("API_PASSWORD"); },
|
|
120
124
|
get API_KEY() { return getConfigValue("API_KEY"); },
|