
Security News
OWASP 2025 Top 10 Adds Software Supply Chain Failures, Ranked Top Community Concern
OWASP’s 2025 Top 10 introduces Software Supply Chain Failures as a new category, reflecting rising concern over dependency and build system risks.
@0xmonaco/core
Advanced tools
⚠️ EARLY DEVELOPMENT WARNING ⚠️
This package is currently in early development.
Breaking changes are expected and may occur without notice. This version is intended for:
Core SDK implementation for interacting with Monaco Protocol. This SDK provides a comprehensive implementation with Authentication, Vault, Trading, Market, and Profile APIs, featuring JWT authentication and secure API Gateway integration.
npm install @0xmonaco/core
Before running tests, ensure you have:
A running hardhat node with the Monaco Protocol contracts deployed:
# In the contracts package
cd ../contracts
pnpm hardhat node # Start a local hardhat node
pnpm hardhat deploy --network localhost # Deploy contracts
Create a .env.test file in the tests directory:
# Create the file
cd packages/core/src/tests
touch .env.test
# Add the following content to .env.test:
echo 'TEST_PRIVATE_KEY=0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' > .env.test
Replace the example private key in .env.test with your actual test account private key:
Verify your setup:
# Make sure you're in the core package directory
cd packages/core
# Check if .env.test exists and has the correct format
cat src/tests/.env.test
# Should show: TEST_PRIVATE_KEY=0x...
# Run the tests
pnpm test
If you see an error about TEST_PRIVATE_KEY not being set:
.env.test exists in packages/core/src/tests directoryTEST_PRIVATE_KEY=0x1234... pnpm test
The SDK supports both Sei mainnet (pacific-1) and testnet (atlantic-2) networks. Network configurations are automatically handled through the NETWORK_ENDPOINTS constant:
import { NETWORK_ENDPOINTS } from "@0xmonaco/core";
// Access network configurations by network name
const mainnetConfig = NETWORK_ENDPOINTS.mainnet; // Pacific-1 mainnet
const testnetConfig = NETWORK_ENDPOINTS.testnet; // Atlantic-2 testnet
// Each network config includes:
// - rpcUrl: RPC endpoint for the network
// - apiUrl: API gateway endpoint for the network
import { MonacoSDK } from "@0xmonaco/core";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
// Initialize the SDK with wallet client
const account = privateKeyToAccount("0x...");
const walletClient = createWalletClient({
account,
transport: http()
});
const monaco = new MonacoSDK({
walletClient,
network: "mainnet", // or "testnet"
});
// Authentication
async function authExample() {
// Login with client ID and auto-connect authenticated WebSocket channels (Orders)
const authState = await monaco.login("your-client-id", { connectWebSocket: true });
console.log("Authenticated:", authState.user);
console.log("Tokens:", {
accessToken: authState.accessToken,
refreshToken: authState.refreshToken, // Use this for revokeToken()
});
// Authenticated WebSocket channels are now connected - start receiving real-time updates
// Currently this includes: Orders (personal order updates)
monaco.websocket.orders.subscribeToOrderEvents("BTC/USDC", "SPOT", (event) => {
console.log("Order event:", event.eventType);
});
// Check authentication status
console.log("Is authenticated:", monaco.isAuthenticated());
// Logout (revokes the refresh token and disconnects authenticated WebSockets)
await monaco.logout();
// Or manually revoke the token
// ✅ CORRECT: Use authState.refreshToken
await monaco.auth.revokeToken(authState.refreshToken);
}
// Market Data
async function marketExample() {
// Get all trading pairs
const pairs = await monaco.market.getTradingPairs();
console.log("Available pairs:", pairs.length);
// Get specific trading pair
const btcPair = await monaco.market.getTradingPairBySymbol("BTC/USDC");
console.log("BTC pair:", btcPair?.symbol, btcPair?.maker_fee_bps);
}
// Vault Operations
async function vaultExample() {
// Check vault balance
const balance = await monaco.vault.getBalance("0x..."); // token address
console.log("Vault balance:", balance.formatted, balance.symbol);
// Approve vault to spend tokens
const approval = await monaco.vault.approve("0x...", parseEther("1000"));
console.log("Approval transaction:", approval.hash);
// Deposit tokens
const result = await monaco.vault.deposit("0x...", parseEther("100"));
console.log("Deposit transaction:", result.hash);
// Withdraw tokens
const withdrawal = await monaco.vault.withdraw("0x...", parseEther("50"));
console.log("Withdrawal transaction:", withdrawal.hash);
}
// Trading Operations
async function tradingExample() {
// Place a limit order
const order = await monaco.trading.placeLimitOrder(
"BTC/USDC", // market
"BUY", // side
"0.001", // quantity
"50000" // price
);
console.log("Order placed:", order.order_id);
// Place a limit order with IOC (Immediate or Cancel)
const iocOrder = await monaco.trading.placeLimitOrder(
"BTC/USDC",
"BUY",
"0.001",
"50000",
{ timeInForce: "IOC" } // Execute immediately or cancel
);
console.log("IOC order placed:", iocOrder.order_id);
// Place a market order
const marketOrder = await monaco.trading.placeMarketOrder(
"BTC/USDC",
"SELL",
"0.001"
);
console.log("Market order placed:", marketOrder.order_id);
// Place a market order with FOK (Fill or Kill)
const fokOrder = await monaco.trading.placeMarketOrder(
"BTC/USDC",
"BUY",
"0.001",
{ timeInForce: "FOK" } // Must fill completely or cancel
);
console.log("FOK order placed:", fokOrder.order_id);
// Get paginated orders
const orders = await monaco.trading.getPaginatedOrders({
status: "PENDING",
trading_pair: "BTC/USDC",
page: 1,
page_size: 10
});
console.log("Orders:", orders.data.length);
// Replace an order
const replaceResult = await monaco.trading.replaceOrder("order-id", {
quantity: "0.002",
price: "51000"
});
console.log("Order replaced:", replaceResult.order_id);
// Cancel an order
const cancelResult = await monaco.trading.cancelOrder("order-id");
console.log("Order cancelled:", cancelResult.status);
// Get specific order
const orderDetails = await monaco.trading.getOrder("order-id");
console.log("Order details:", orderDetails.order);
}
The main SDK class that provides access to all protocol features.
class MonacoSDK {
readonly applications: ApplicationsAPI;
readonly auth: AuthAPI;
readonly vault: VaultAPI;
readonly trading: TradingAPI;
readonly market: MarketAPI;
readonly profile: ProfileAPI;
readonly websocket: {
orders: OrdersWebSocketClient;
ohlcv: OHLCVWebSocketClient;
orderbook: OrderbookWebSocketClient;
};
readonly walletClient: WalletClient;
readonly publicClient: PublicClient;
constructor(config: SDKConfig);
// Authentication
login(clientId: string, options?: { connectWebSocket?: boolean }): Promise<AuthState>;
logout(): Promise<void>;
refreshAuth(): Promise<AuthState>;
getAuthState(): AuthState | undefined;
isAuthenticated(): boolean;
// Network utilities
isConnected(): boolean;
getAccountAddress(): string;
getNetwork(): Network;
getChainId(): number;
waitForTransaction(hash: string, confirmations?: number, timeout?: number): Promise<TransactionReceipt>;
}
interface SDKConfig {
/** Wallet client for signing operations */
walletClient: WalletClient;
/** Optional network override (defaults to 'mainnet') */
network?: Network;
/** Optional transport for the public client */
transport?: Transport;
}
The SDK uses JWT tokens for authentication. Understanding the token structure is important:
// After login, you receive an AuthState object
const authState = await sdk.login(clientId);
// AuthState structure:
interface AuthState {
accessToken: string; // For making authenticated API requests
refreshToken: string; // For refreshing tokens AND revoking (logout)
expiresAt: number; // When the access token expires
user: User; // User information
}
⚠️ Important: The authentication response contains refreshToken, NOT revokeToken.
// ✅ CORRECT: Revoke using refreshToken
await sdk.auth.revokeToken(authState.refreshToken);
// 💡 TIP: Use the built-in logout method
await sdk.logout(); // Automatically calls revokeToken internally
Token Management Methods:
login(clientId, options?) - Authenticate and get tokens
clientId: Your application's client IDoptions.connectWebSocket: (optional) Auto-connect all authenticated WebSocket channels after login (default: false)logout() - Revoke token and clear staterefreshAuth() - Refresh the access token using the stored refresh tokenisAuthenticated() - Check if user is authenticatedgetAuthState() - Get current auth state with tokensThe vault API provides secure token management operations:
interface VaultAPI extends BaseAPI {
// Vault address management
setVaultAddress(vaultAddress: Address): void;
getVaultAddress(): Address | undefined;
// Token operations
approve(token: string, amount: bigint, autoWait?: boolean): Promise<TransactionResult>;
deposit(token: string, amount: bigint, autoWait?: boolean): Promise<TransactionResult>;
withdraw(token: string, amount: bigint, autoWait?: boolean): Promise<TransactionResult>;
// Balance queries
getBalance(token: string): Promise<Balance>;
}
The trading API provides comprehensive order management:
interface TradingAPI extends BaseAPI {
// Order placement
placeLimitOrder(
market: string,
side: OrderSide,
quantity: string,
price: string,
options?: {
tradingMode?: string;
useMasterBalance?: boolean;
expirationDate?: string;
timeInForce?: string; // "GTC", "IOC", or "FOK"
}
): Promise<CreateOrderResponse>;
placeMarketOrder(
market: string,
side: OrderSide,
quantity: string,
options?: {
tradingMode?: string;
slippageTolerance?: number;
timeInForce?: string; // "GTC", "IOC", or "FOK"
}
): Promise<CreateOrderResponse>;
// Order management
cancelOrder(orderId: string): Promise<CancelOrderResponse>;
replaceOrder(
orderId: string,
newOrder: {
price?: string;
quantity: string;
useMasterBalance?: boolean;
}
): Promise<ReplaceOrderResponse>;
// Order queries
getPaginatedOrders(params?: GetPaginatedOrdersParams): Promise<GetPaginatedOrdersResponse>;
getOrder(orderId: string): Promise<GetOrderResponse>;
}
The market API provides access to trading pair metadata:
interface MarketAPI extends BaseAPI {
// Market data
getTradingPairs(): Promise<TradingPair[]>;
getTradingPairBySymbol(symbol: string): Promise<TradingPair | undefined>;
}
The SDK provides three WebSocket clients with different authentication requirements:
No authentication required. Provide public market data. You always connect manually:
// Step 1: Establish WebSocket connection (no authentication needed)
await monaco.websocket.ohlcv.connect();
await monaco.websocket.orderbook.connect();
// Step 2: Subscribe to public market data
monaco.websocket.ohlcv.subscribeToOHLCV("BTC/USDC", "SPOT", "1m", (event) => {
console.log("OHLCV data:", event.candlestick);
});
monaco.websocket.orderbook.subscribeToOrderbookEvents("BTC/USDC", "SPOT", (event) => {
console.log("Orderbook update:", event.bids.length, "bids");
});
Requires JWT authentication for personal order updates. You can either auto-connect during login or connect manually:
Option 1: Auto-connect (recommended for authenticated channels)
// Login and auto-connect all authenticated WebSocket channels
// Currently includes: Orders (personal order updates)
await monaco.login(clientId, { connectWebSocket: true });
// Subscribe to personal order events (already connected)
monaco.websocket.orders.subscribeToOrderEvents("BTC/USDC", "SPOT", (event) => {
console.log("Personal order event:", event.eventType);
});
Option 2: Manual connection (required for public channels, optional for authenticated)
// Public channels like OHLCV always require manual connection (no auth needed)
await monaco.websocket.ohlcv.connect();
monaco.websocket.ohlcv.subscribeToOHLCV("BTC/USDC", "SPOT", "1m", (event) => {
console.log("OHLCV data:", event.candlestick);
});
// For authenticated channels, you can also connect manually for more control
await monaco.login(clientId);
await monaco.websocket.orders.connect();
monaco.websocket.orders.subscribeToOrderEvents("BTC/USDC", "SPOT", (event) => {
console.log("Personal order event:", event.eventType);
});
Note:
connectWebSocket: true option automatically connects all authenticated WebSocket channels (currently Orders).connect() explicitly as they don't require authentication.The SDK uses structured error classes for comprehensive error handling:
import { APIError, ContractError, TransactionError, OrderError } from "@0xmonaco/core";
try {
await sdk.vault.deposit(token, amount);
} catch (error) {
if (error instanceof ContractError) {
console.error("Contract error:", error.message);
console.error("Error code:", error.code);
} else if (error instanceof APIError) {
console.error("API error:", error.message);
console.error("Status:", error.status);
} else if (error instanceof TransactionError) {
console.error("Transaction error:", error.message);
} else if (error instanceof OrderError) {
console.error("Order error:", error.message);
console.error("Market:", error.market);
}
}
Error Types:
MonacoCoreError: Base error class for all SDK errorsAPIError: API request failures and communication errorsContractError: Smart contract operation errorsTransactionError: Blockchain transaction errorsOrderError: Trading order specific errorsInvalidConfigError: Configuration validation errorsInvalidStateError: Invalid state or operation errorspackages/core/
├── src/ # Source code
│ ├── api/ # API implementations
│ │ ├── applications/ # Applications API
│ │ ├── auth/ # Authentication API
│ │ ├── base.ts # Base API class
│ │ ├── market/ # Market data API
│ │ ├── profile/ # Profile management API
│ │ ├── trading/ # Trading operations API
│ │ ├── vault/ # Vault operations API
│ │ ├── websocket/ # WebSocket client
│ │ └── index.ts # API exports
│ ├── constants/ # Constants and configurations
│ ├── errors.ts # Error classes and codes
│ ├── networks.ts # Network endpoint configurations
│ ├── sdk.ts # Main SDK implementation
│ └── index.ts # Public API exports
├── tests/ # Test suite
├── dist/ # Compiled output
├── package.json # Package configuration
└── tsconfig.json # TypeScript configuration
git clone https://github.com/monaco-protocol/monaco-monorepo.git
cd monaco-monorepo
pnpm install
pnpm build --filter @0xmonaco/core
Run the test suite:
pnpm test --filter @0xmonaco/core
The project uses ESLint and Prettier for code formatting. Run the linter:
pnpm lint --filter @0xmonaco/core
We welcome contributions! Please see our Contributing Guide for details.
This project is licensed under the MIT License - see the LICENSE file for details.
For support, please:
FAQs
⚠️ **EARLY DEVELOPMENT WARNING** ⚠️
We found that @0xmonaco/core demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OWASP’s 2025 Top 10 introduces Software Supply Chain Failures as a new category, reflecting rising concern over dependency and build system risks.

Research
/Security News
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.