@0xmonaco/core 0.8.7 → 0.8.10
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/dist/api/applications/api.d.ts +61 -8
- package/dist/api/applications/api.js +71 -7
- package/dist/api/auth/api.d.ts +44 -76
- package/dist/api/auth/api.js +61 -104
- package/dist/api/base.d.ts +48 -7
- package/dist/api/base.js +95 -12
- package/dist/api/delegated-agents/api.d.ts +2 -1
- package/dist/api/delegated-agents/api.js +4 -0
- package/dist/api/faucet/api.d.ts +25 -0
- package/dist/api/faucet/api.js +29 -0
- package/dist/api/faucet/index.d.ts +1 -0
- package/dist/api/faucet/index.js +1 -0
- package/dist/api/index.d.ts +4 -0
- package/dist/api/index.js +4 -0
- package/dist/api/margin-accounts/api.d.ts +3 -4
- package/dist/api/margin-accounts/api.js +8 -15
- package/dist/api/market/api.d.ts +3 -1
- package/dist/api/market/api.js +8 -0
- package/dist/api/orderbook/api.js +2 -1
- package/dist/api/perp/routes.d.ts +62 -4
- package/dist/api/perp/routes.js +27 -4
- package/dist/api/profile/api.d.ts +18 -1
- package/dist/api/profile/api.js +41 -1
- package/dist/api/sub-accounts/api.d.ts +62 -0
- package/dist/api/sub-accounts/api.js +80 -0
- package/dist/api/sub-accounts/index.d.ts +1 -0
- package/dist/api/sub-accounts/index.js +1 -0
- package/dist/api/trades/api.d.ts +12 -1
- package/dist/api/trades/api.js +13 -1
- package/dist/api/trading/api.d.ts +5 -2
- package/dist/api/trading/api.js +13 -27
- package/dist/api/websocket/types.d.ts +5 -5
- package/dist/api/websocket/websocket.js +43 -22
- package/dist/api/whitelist/api.d.ts +27 -0
- package/dist/api/whitelist/api.js +32 -0
- package/dist/api/whitelist/index.d.ts +1 -0
- package/dist/api/whitelist/index.js +1 -0
- package/dist/api/withdrawals/api.d.ts +15 -0
- package/dist/api/withdrawals/api.js +27 -0
- package/dist/api/withdrawals/index.d.ts +1 -0
- package/dist/api/withdrawals/index.js +1 -0
- package/dist/coverage.d.ts +85 -0
- package/dist/coverage.js +85 -0
- package/dist/crypto/session.d.ts +40 -0
- package/dist/crypto/session.js +60 -0
- package/dist/sdk.d.ts +56 -18
- package/dist/sdk.js +156 -53
- package/package.json +5 -3
package/dist/sdk.js
CHANGED
|
@@ -4,25 +4,44 @@ import { sei, seiTestnet } from "viem/chains";
|
|
|
4
4
|
import { ApplicationsAPIImpl, createMonacoWebSocket, OrderbookAPIImpl, TradesAPIImpl } from "./api";
|
|
5
5
|
import { AuthAPIImpl } from "./api/auth";
|
|
6
6
|
import { DelegatedAgentsAPIImpl } from "./api/delegated-agents";
|
|
7
|
+
import { FaucetAPIImpl } from "./api/faucet";
|
|
7
8
|
import { FeesAPIImpl } from "./api/fees";
|
|
8
9
|
import { MarginAccountsAPIImpl } from "./api/margin-accounts";
|
|
9
10
|
import { MarketAPIImpl } from "./api/market";
|
|
10
11
|
import { PositionsAPIImpl } from "./api/positions";
|
|
11
12
|
import { ProfileAPIImpl } from "./api/profile";
|
|
13
|
+
import { SubAccountsAPIImpl } from "./api/sub-accounts";
|
|
12
14
|
import { TradingAPIImpl } from "./api/trading";
|
|
13
15
|
import { VaultAPIImpl } from "./api/vault";
|
|
16
|
+
import { WhitelistAPIImpl } from "./api/whitelist";
|
|
17
|
+
import { WithdrawalsAPIImpl } from "./api/withdrawals";
|
|
18
|
+
import { generateSessionKeypair, privateKeyHex, publicKeyHex } from "./crypto/session";
|
|
14
19
|
import { APIError, InvalidConfigError, InvalidStateError } from "./errors";
|
|
15
20
|
import { resolveApiUrl, resolveWsUrl } from "./networks";
|
|
21
|
+
/** Validate a user-supplied URL override, returning it unchanged when valid. */
|
|
22
|
+
function validateUrl(value, field) {
|
|
23
|
+
try {
|
|
24
|
+
new URL(value);
|
|
25
|
+
}
|
|
26
|
+
catch (_e) {
|
|
27
|
+
throw new InvalidConfigError(`${field} must be a valid URL, got: ${value}`, field);
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
16
31
|
export class MonacoSDKImpl {
|
|
17
32
|
auth;
|
|
18
33
|
delegatedAgents;
|
|
19
34
|
applications;
|
|
20
35
|
fees;
|
|
21
36
|
vault;
|
|
37
|
+
withdrawals;
|
|
22
38
|
trading;
|
|
23
39
|
market;
|
|
24
40
|
marginAccounts;
|
|
25
41
|
positions;
|
|
42
|
+
subAccounts;
|
|
43
|
+
faucet;
|
|
44
|
+
whitelist;
|
|
26
45
|
profile;
|
|
27
46
|
orderbook;
|
|
28
47
|
trades;
|
|
@@ -33,22 +52,69 @@ export class MonacoSDKImpl {
|
|
|
33
52
|
network;
|
|
34
53
|
chain;
|
|
35
54
|
/**
|
|
36
|
-
* Propagate the
|
|
55
|
+
* Propagate the session keypair (or `undefined` to clear) to all APIs and
|
|
56
|
+
* the WebSocket client.
|
|
57
|
+
*/
|
|
58
|
+
propagateSession(credentials) {
|
|
59
|
+
this.auth.setSessionKeypair(credentials);
|
|
60
|
+
this.delegatedAgents.setSessionKeypair(credentials);
|
|
61
|
+
this.applications.setSessionKeypair(credentials);
|
|
62
|
+
this.fees.setSessionKeypair(credentials);
|
|
63
|
+
this.vault.setSessionKeypair(credentials);
|
|
64
|
+
this.withdrawals.setSessionKeypair(credentials);
|
|
65
|
+
this.trading.setSessionKeypair(credentials);
|
|
66
|
+
this.market.setSessionKeypair(credentials);
|
|
67
|
+
this.marginAccounts.setSessionKeypair(credentials);
|
|
68
|
+
this.positions.setSessionKeypair(credentials);
|
|
69
|
+
this.subAccounts.setSessionKeypair(credentials);
|
|
70
|
+
this.faucet.setSessionKeypair(credentials);
|
|
71
|
+
this.whitelist.setSessionKeypair(credentials);
|
|
72
|
+
this.profile.setSessionKeypair(credentials);
|
|
73
|
+
this.orderbook.setSessionKeypair(credentials);
|
|
74
|
+
this.trades.setSessionKeypair(credentials);
|
|
75
|
+
this.ws.setSessionKeypair(credentials);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Set (or clear) the application secret key used for backend-authenticated
|
|
79
|
+
* requests (those annotated `#[require_backend]` on the gateway, e.g. the
|
|
80
|
+
* `applications` reporting endpoints).
|
|
81
|
+
*
|
|
82
|
+
* The raw `sk_...` key is sent in the `x-server-key` header on each such
|
|
83
|
+
* request. This is independent of {@link login}/session auth — a client may
|
|
84
|
+
* hold both a session and a server key at once.
|
|
85
|
+
*
|
|
86
|
+
* @param serverKey - The application secret key (`sk_...`), or `undefined` to clear.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* sdk.setServerKey("sk_live_...");
|
|
91
|
+
* const orders = await sdk.applications.listApplicationOrders({ status: "FILLED" });
|
|
92
|
+
* ```
|
|
37
93
|
*/
|
|
38
|
-
|
|
39
|
-
this.auth.
|
|
40
|
-
this.delegatedAgents.
|
|
41
|
-
this.applications.
|
|
42
|
-
this.fees.
|
|
43
|
-
this.vault.
|
|
44
|
-
this.
|
|
45
|
-
this.
|
|
46
|
-
this.
|
|
47
|
-
this.
|
|
48
|
-
this.
|
|
49
|
-
this.
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
94
|
+
setServerKey(serverKey) {
|
|
95
|
+
this.auth.setServerKey(serverKey);
|
|
96
|
+
this.delegatedAgents.setServerKey(serverKey);
|
|
97
|
+
this.applications.setServerKey(serverKey);
|
|
98
|
+
this.fees.setServerKey(serverKey);
|
|
99
|
+
this.vault.setServerKey(serverKey);
|
|
100
|
+
this.withdrawals.setServerKey(serverKey);
|
|
101
|
+
this.trading.setServerKey(serverKey);
|
|
102
|
+
this.market.setServerKey(serverKey);
|
|
103
|
+
this.marginAccounts.setServerKey(serverKey);
|
|
104
|
+
this.positions.setServerKey(serverKey);
|
|
105
|
+
this.subAccounts.setServerKey(serverKey);
|
|
106
|
+
this.faucet.setServerKey(serverKey);
|
|
107
|
+
this.whitelist.setServerKey(serverKey);
|
|
108
|
+
this.profile.setServerKey(serverKey);
|
|
109
|
+
this.orderbook.setServerKey(serverKey);
|
|
110
|
+
this.trades.setServerKey(serverKey);
|
|
111
|
+
}
|
|
112
|
+
/** Extract the session keypair from an auth state. */
|
|
113
|
+
sessionFromAuthState(authState) {
|
|
114
|
+
return {
|
|
115
|
+
publicKey: authState.sessionPublicKey,
|
|
116
|
+
privateKey: authState.sessionPrivateKey,
|
|
117
|
+
};
|
|
52
118
|
}
|
|
53
119
|
constructor(cfg) {
|
|
54
120
|
// Validate network - must be a preset
|
|
@@ -67,8 +133,8 @@ export class MonacoSDKImpl {
|
|
|
67
133
|
catch (_e) {
|
|
68
134
|
throw new InvalidConfigError(`seiRpcUrl must be a valid URL, got: ${cfg.seiRpcUrl}`, "seiRpcUrl");
|
|
69
135
|
}
|
|
70
|
-
//
|
|
71
|
-
const wsUrl = resolveWsUrl(this.network);
|
|
136
|
+
// Resolve the WebSocket URL: explicit override (validated) or network preset.
|
|
137
|
+
const wsUrl = cfg.wsUrl ? validateUrl(cfg.wsUrl, "wsUrl") : resolveWsUrl(this.network);
|
|
72
138
|
// Use Sei mainnet chain only for "mainnet" network, testnet for everything else
|
|
73
139
|
const chain = this.network === "mainnet" ? sei : seiTestnet;
|
|
74
140
|
this.chain = chain;
|
|
@@ -78,8 +144,8 @@ export class MonacoSDKImpl {
|
|
|
78
144
|
chain,
|
|
79
145
|
transport,
|
|
80
146
|
});
|
|
81
|
-
// Resolve the API URL (
|
|
82
|
-
const apiUrl = resolveApiUrl(this.network);
|
|
147
|
+
// Resolve the API URL: explicit override (validated) or network preset.
|
|
148
|
+
const apiUrl = cfg.apiUrl ? validateUrl(cfg.apiUrl, "apiUrl") : resolveApiUrl(this.network);
|
|
83
149
|
// Validate wallet client chain if provided
|
|
84
150
|
if (cfg.walletClient) {
|
|
85
151
|
if (cfg.walletClient.chain?.id !== chain.id) {
|
|
@@ -92,11 +158,15 @@ export class MonacoSDKImpl {
|
|
|
92
158
|
this.market = new MarketAPIImpl(apiUrl);
|
|
93
159
|
this.marginAccounts = new MarginAccountsAPIImpl(apiUrl);
|
|
94
160
|
this.positions = new PositionsAPIImpl(apiUrl);
|
|
161
|
+
this.subAccounts = new SubAccountsAPIImpl(apiUrl);
|
|
162
|
+
this.faucet = new FaucetAPIImpl(apiUrl);
|
|
163
|
+
this.whitelist = new WhitelistAPIImpl(apiUrl);
|
|
95
164
|
this.auth = new AuthAPIImpl(this.walletClient, this.chain, apiUrl);
|
|
96
165
|
this.delegatedAgents = new DelegatedAgentsAPIImpl(apiUrl);
|
|
97
166
|
this.fees = new FeesAPIImpl(apiUrl);
|
|
98
167
|
this.profile = new ProfileAPIImpl(apiUrl);
|
|
99
168
|
this.vault = new VaultAPIImpl(this.publicClient, this.walletClient, this.chain, this.applications, this.profile, apiUrl);
|
|
169
|
+
this.withdrawals = new WithdrawalsAPIImpl(apiUrl);
|
|
100
170
|
this.trading = new TradingAPIImpl(apiUrl);
|
|
101
171
|
this.orderbook = new OrderbookAPIImpl(apiUrl);
|
|
102
172
|
this.trades = new TradesAPIImpl(apiUrl);
|
|
@@ -107,14 +177,16 @@ export class MonacoSDKImpl {
|
|
|
107
177
|
/**
|
|
108
178
|
* Authenticate the user
|
|
109
179
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* - `
|
|
113
|
-
*
|
|
180
|
+
* Generates a session keypair, has the wallet authorize it, and returns an
|
|
181
|
+
* AuthState object containing:
|
|
182
|
+
* - `sessionPublicKey` / `sessionPrivateKey`: the session keypair used to
|
|
183
|
+
* sign subsequent requests (the private key is the credential — persist it
|
|
184
|
+
* to survive reloads without re-prompting the wallet)
|
|
185
|
+
* - `expiresAt`: When the session expires
|
|
114
186
|
* - `user`: User information
|
|
115
187
|
*
|
|
116
|
-
* Note: Use `sdk.logout()` to revoke the
|
|
117
|
-
* `sdk.auth.
|
|
188
|
+
* Note: Use `sdk.logout()` to revoke the session and clean up, or call
|
|
189
|
+
* `sdk.auth.revokeSession()` directly to just revoke.
|
|
118
190
|
*
|
|
119
191
|
* @param clientId - The client ID for authentication
|
|
120
192
|
* @param options - Optional configuration
|
|
@@ -128,30 +200,57 @@ export class MonacoSDKImpl {
|
|
|
128
200
|
* // Login and auto-connect WebSocket
|
|
129
201
|
* const authState = await sdk.login(clientId, { connectWebSocket: true });
|
|
130
202
|
*
|
|
131
|
-
* // Manual WebSocket connection
|
|
132
|
-
* await sdk.ws.connect();
|
|
133
|
-
*
|
|
134
203
|
* // Later, to revoke:
|
|
135
|
-
* await sdk.auth.
|
|
204
|
+
* await sdk.auth.revokeSession(); // ✅
|
|
136
205
|
* // Or revoke and disconnect WebSocket:
|
|
137
|
-
* await sdk.logout(); // ✅ Calls
|
|
206
|
+
* await sdk.logout(); // ✅ Calls revokeSession internally and disconnects WebSocket
|
|
138
207
|
* ```
|
|
139
208
|
*/
|
|
140
209
|
async login(clientId, options) {
|
|
141
|
-
|
|
142
|
-
this.authState
|
|
143
|
-
accessToken: response.accessToken,
|
|
144
|
-
refreshToken: response.refreshToken,
|
|
145
|
-
expiresAt: response.expiresAt,
|
|
146
|
-
user: response.user,
|
|
147
|
-
};
|
|
148
|
-
this.propagateAccessToken(this.authState.accessToken);
|
|
210
|
+
this.authState = await this.auth.authenticate(clientId);
|
|
211
|
+
this.propagateSession(this.sessionFromAuthState(this.authState));
|
|
149
212
|
// Auto-connect WebSocket if requested
|
|
150
213
|
if (options?.connectWebSocket) {
|
|
151
214
|
await this.ws.connect();
|
|
152
215
|
}
|
|
153
216
|
return this.authState;
|
|
154
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Create and adopt an owner-scoped delegated session.
|
|
220
|
+
*
|
|
221
|
+
* This must be called while authenticated as the agent wallet. The delegated
|
|
222
|
+
* session uses a fresh ed25519 keypair generated locally; the current agent
|
|
223
|
+
* session signs the registration request, and subsequent SDK calls use the
|
|
224
|
+
* delegated session keypair.
|
|
225
|
+
*/
|
|
226
|
+
async loginAsDelegatedOwner(ownerUserId) {
|
|
227
|
+
if (!this.authState) {
|
|
228
|
+
throw new APIError("No active agent session to create delegated session", {
|
|
229
|
+
endpoint: "delegated-agents/sessions",
|
|
230
|
+
statusCode: StatusCodes.UNAUTHORIZED,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
const keypair = generateSessionKeypair();
|
|
234
|
+
const session = {
|
|
235
|
+
publicKey: publicKeyHex(keypair),
|
|
236
|
+
privateKey: privateKeyHex(keypair),
|
|
237
|
+
};
|
|
238
|
+
const delegatedSession = await this.delegatedAgents.createDelegatedSession({
|
|
239
|
+
ownerUserId,
|
|
240
|
+
sessionPublicKey: session.publicKey,
|
|
241
|
+
});
|
|
242
|
+
this.authState = {
|
|
243
|
+
sessionPublicKey: session.publicKey,
|
|
244
|
+
sessionPrivateKey: session.privateKey,
|
|
245
|
+
expiresAt: delegatedSession.expires_at,
|
|
246
|
+
user: {
|
|
247
|
+
id: delegatedSession.owner_user_id,
|
|
248
|
+
address: delegatedSession.agent_address,
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
this.propagateSession(this.sessionFromAuthState(this.authState));
|
|
252
|
+
return this.authState;
|
|
253
|
+
}
|
|
155
254
|
/**
|
|
156
255
|
* Get the current authentication state
|
|
157
256
|
*
|
|
@@ -168,59 +267,63 @@ export class MonacoSDKImpl {
|
|
|
168
267
|
*/
|
|
169
268
|
setAuthState(authState) {
|
|
170
269
|
this.authState = authState;
|
|
171
|
-
this.
|
|
270
|
+
this.propagateSession(this.sessionFromAuthState(authState));
|
|
172
271
|
}
|
|
173
272
|
/**
|
|
174
273
|
* Log the user out
|
|
175
274
|
*
|
|
176
|
-
* This method revokes the
|
|
275
|
+
* This method revokes the session (if authenticated), disconnects all authenticated
|
|
177
276
|
* WebSocket channels, and clears the local auth state.
|
|
178
|
-
* It internally calls `auth.
|
|
277
|
+
* It internally calls `auth.revokeSession()` to invalidate the session on the server.
|
|
179
278
|
*
|
|
180
279
|
* @example
|
|
181
280
|
* ```typescript
|
|
182
281
|
* await sdk.logout();
|
|
183
|
-
* //
|
|
282
|
+
* // Session is revoked, authenticated WebSockets disconnected, and local state cleared
|
|
184
283
|
* ```
|
|
185
284
|
*/
|
|
186
285
|
async logout() {
|
|
187
|
-
if (this.authState
|
|
286
|
+
if (this.authState) {
|
|
188
287
|
try {
|
|
189
|
-
await this.auth.
|
|
288
|
+
await this.auth.revokeSession();
|
|
190
289
|
}
|
|
191
290
|
catch (error) {
|
|
192
291
|
// Log but don't throw - we want to clear the local state regardless
|
|
193
|
-
console.warn("Failed to revoke
|
|
292
|
+
console.warn("Failed to revoke session on logout:", error);
|
|
194
293
|
}
|
|
195
294
|
}
|
|
196
295
|
this.authState = undefined;
|
|
197
|
-
this.
|
|
296
|
+
this.propagateSession(undefined);
|
|
198
297
|
this.ws.disconnect();
|
|
199
298
|
}
|
|
200
299
|
/**
|
|
201
|
-
* Refresh the
|
|
300
|
+
* Refresh the current session, extending its expiry.
|
|
301
|
+
*
|
|
302
|
+
* Signs a refresh request with the active session key and updates the local
|
|
303
|
+
* `expiresAt`. The session keypair is unchanged. If no session is active, or
|
|
304
|
+
* the session has expired/been revoked, this throws.
|
|
305
|
+
*
|
|
202
306
|
* @returns The updated authentication state
|
|
203
307
|
*/
|
|
204
308
|
async refreshAuth() {
|
|
205
|
-
if (!this.authState
|
|
206
|
-
throw new APIError("No
|
|
309
|
+
if (!this.authState) {
|
|
310
|
+
throw new APIError("No active session to refresh", {
|
|
207
311
|
endpoint: "auth/refresh",
|
|
208
312
|
statusCode: StatusCodes.UNAUTHORIZED,
|
|
209
313
|
});
|
|
210
314
|
}
|
|
211
315
|
try {
|
|
212
|
-
const response = await this.auth.
|
|
316
|
+
const response = await this.auth.refreshSession();
|
|
213
317
|
this.authState = {
|
|
214
318
|
...this.authState,
|
|
215
|
-
accessToken: response.accessToken,
|
|
216
319
|
expiresAt: response.expiresAt,
|
|
217
320
|
};
|
|
218
|
-
this.propagateAccessToken(this.authState.accessToken);
|
|
219
321
|
return this.authState;
|
|
220
322
|
}
|
|
221
323
|
catch (error) {
|
|
222
|
-
// If refresh fails,
|
|
324
|
+
// If refresh fails, the session is no longer usable.
|
|
223
325
|
this.authState = undefined;
|
|
326
|
+
this.propagateSession(undefined);
|
|
224
327
|
throw error;
|
|
225
328
|
}
|
|
226
329
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xmonaco/core",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -23,8 +23,10 @@
|
|
|
23
23
|
"viem": "^2.45.2"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@0xmonaco/contracts": "0.8.
|
|
27
|
-
"@0xmonaco/types": "0.8.
|
|
26
|
+
"@0xmonaco/contracts": "0.8.10",
|
|
27
|
+
"@0xmonaco/types": "0.8.10",
|
|
28
|
+
"@noble/curves": "^1.9.1",
|
|
29
|
+
"@noble/hashes": "^1.8.0",
|
|
28
30
|
"http-status-codes": "^2.3.0"
|
|
29
31
|
},
|
|
30
32
|
"devDependencies": {
|