UNPKG

pmarket-cli

Version:
178 lines 7.21 kB
import { ClobClient, Chain, OrderType } from "@polymarket/clob-client"; import { ethers } from "ethers"; import axios from "axios"; const CLOB_API_ENDPOINT = "https://clob.polymarket.com/"; const DATA_API_ENDPOINT = "https://data-api.polymarket.com"; export class PolymarketService { clobClient; signer; configService; initialized = false; constructor(configService) { this.configService = configService; this.initializeWallet(); } initializeWallet() { const privateKey = this.configService.getPrivateKey(); if (!privateKey) { console.log("Please provide a valid private key in ~/.pmarket-cli/config.json"); return; } const provider = new ethers.JsonRpcProvider(this.configService.getRpcProvider()); try { this.signer = new ethers.Wallet(privateKey, provider); } catch { console.log("Please provide a valid private key in ~/.pmarket-cli/config.json"); return; } } async ensureInitialized(requireCreds = false) { if (this.initialized && this.clobClient) { // If we need creds but don't have them, re-initialize with creds if (requireCreds && !this.configService.hasCredentials()) { this.initialized = false; } else { return; } } if (!this.signer) { throw new Error("Wallet not initialized. Please check your private key."); } const funderAddress = this.configService.getFunderAddress(); let creds = this.configService.getCreds(); // Auto-derive credentials if needed and not available if (requireCreds && !creds) { console.log("API credentials required. Deriving credentials..."); // Create a temporary client to derive credentials const tempClient = new ClobClient(CLOB_API_ENDPOINT, Chain.POLYGON, this.signer, undefined, 0, // SignatureType.EOA for regular wallets funderAddress); try { const derivedCreds = await tempClient.deriveApiKey(); if (!derivedCreds.error && derivedCreds.key && derivedCreds.secret && derivedCreds.passphrase) { this.configService.saveCredentials(derivedCreds.key, derivedCreds.secret, derivedCreds.passphrase); creds = { key: derivedCreds.key, secret: derivedCreds.secret, passphrase: derivedCreds.passphrase }; } else { throw new Error("Derive failed, creating new key"); } } catch { console.log("Creating new API key..."); const newCreds = await tempClient.createApiKey(); // The response should have key, secret, passphrase fields if (!newCreds.key || !newCreds.secret || !newCreds.passphrase) { console.error("Failed to get valid API credentials"); throw new Error("Failed to create API credentials - missing required fields"); } this.configService.saveCredentials(newCreds.key, newCreds.secret, newCreds.passphrase); creds = { key: newCreds.key, secret: newCreds.secret, passphrase: newCreds.passphrase }; } } if (creds) { this.clobClient = new ClobClient(CLOB_API_ENDPOINT, Chain.POLYGON, this.signer, creds, 0, // SignatureType.EOA for regular wallets funderAddress); } else { this.clobClient = new ClobClient(CLOB_API_ENDPOINT, Chain.POLYGON, this.signer, undefined, 0, // SignatureType.EOA for regular wallets funderAddress); } this.initialized = true; } async fetchAllMarkets() { await this.ensureInitialized(); if (!this.clobClient) { throw new Error("CLOB client not initialized"); } const allMarkets = []; let nextCursor = ""; while (true) { const response = await this.clobClient.getMarkets(nextCursor); allMarkets.push(...response.data); if (response.next_cursor === "LTE=" || !response.next_cursor) { break; } nextCursor = response.next_cursor; } return allMarkets; } async getMarketsAcceptingOrders() { const markets = await this.fetchAllMarkets(); return markets .filter((market) => !market.closed && market.active) .map((market) => { return { yes: market.tokens[0], no: market.tokens[1], question: market.question, }; }); } async marketOrder(tokenID, side, size, price) { await this.ensureInitialized(true); // Requires credentials if (!this.clobClient) { throw new Error("CLOB client not initialized"); } const orderBook = await this.clobClient.getOrderBook(tokenID); const isNegRisk = orderBook.neg_risk === true; console.log(`Creating ${side} order: ${size} shares at $${price}${isNegRisk ? ' (neg_risk market)' : ''}`); const marketOrder = await this.clobClient.createOrder({ tokenID: tokenID, price: price, side: side, size: size, feeRateBps: 0, nonce: 0, expiration: 0, }, { negRisk: isNegRisk }); const resp = await this.clobClient.postOrder(marketOrder, OrderType.GTC); return resp; } async getOrderBook(tokenId) { await this.ensureInitialized(); if (!this.clobClient) { throw new Error("CLOB client not initialized"); } return this.clobClient.getOrderBook(tokenId); } async cancelAll() { await this.ensureInitialized(true); // Requires credentials if (!this.clobClient) { throw new Error("CLOB client not initialized"); } return this.clobClient.cancelAll(); } async getApiKeys() { // This will auto-derive credentials if needed await this.ensureInitialized(true); if (!this.clobClient) { throw new Error("CLOB client not initialized"); } const creds = this.configService.getCreds(); if (creds) { console.log("API credentials ready."); return creds; } throw new Error("Failed to derive API credentials"); } async getPositions() { if (!this.signer) { throw new Error("Wallet not initialized. Please check your private key."); } const address = await this.signer.getAddress(); const response = await axios.get(`${DATA_API_ENDPOINT}/positions`, { params: { user: address, sizeThreshold: 0.01, sortBy: "CURRENT", sortDirection: "DESC", }, }); return response.data; } getWalletAddress() { return this.signer?.address; } } //# sourceMappingURL=polymarket.service.js.map