From 00edad1c58a75789e739827dc813ba9d80db18c6 Mon Sep 17 00:00:00 2001 From: Ronan-Yann Lorin Date: Thu, 7 Nov 2024 18:13:27 +0100 Subject: [PATCH 1/2] Upgrade to API 10.32.01 --- API_VersionNum.txt | 1 + README.md | 2 +- package.json | 18 +- ref/client/Builder.java | 4 +- ref/client/ContractDetails.java | 9 +- ref/client/DefaultEWrapper.java | 6 +- ref/client/EClient.java | 118 +++- ref/client/EClientErrors.java | 3 +- ref/client/EClientSocket.java | 16 +- ref/client/EDecoder.java | 52 +- ref/client/EOrderDecoder.java | 21 +- ref/client/EReader.java | 8 +- ref/client/EWrapper.java | 6 +- ref/client/EWrapperMsgGenerator.java | 41 +- ref/client/Execution.java | 44 +- ref/client/IneligibilityReason.java | 33 + ref/client/Liquidities.java | 38 ++ ref/client/Order.java | 23 +- ref/client/OrderCancel.java | 60 ++ ref/client/Util.java | 5 +- ref/controller/ApiController.java | 32 +- src/api-next/api-next.ts | 11 +- src/api/api.ts | 23 +- src/api/contract/contractDetails.ts | 2 + src/api/contract/ineligibilityReason.ts | 7 + src/api/data/enum/min-server-version.ts | 11 + src/api/order/execution.ts | 8 +- src/api/order/liquidities.ts | 9 + src/api/order/order.ts | 4 + src/api/order/orderCancel.ts | 8 + src/common/errorCode.ts | 6 + src/core/io/decoder.ts | 84 ++- src/core/io/encoder.ts | 148 ++++- src/index.ts | 5 +- .../subscription-registry.test.ts | 2 +- .../unit/api-next/get-executed-trades.test.ts | 6 +- src/tests/unit/api/historical-data.test.ts | 4 +- src/tests/unit/api/order/issue203.test.ts | 166 +++++ src/tests/unit/api/order/placeOrder.test.ts | 61 -- src/tests/unit/api/positions.test.ts | 6 +- yarn.lock | 569 +++++++++++++----- 41 files changed, 1271 insertions(+), 409 deletions(-) create mode 100644 API_VersionNum.txt create mode 100644 ref/client/IneligibilityReason.java create mode 100644 ref/client/Liquidities.java create mode 100644 ref/client/OrderCancel.java create mode 100644 src/api/contract/ineligibilityReason.ts create mode 100644 src/api/order/liquidities.ts create mode 100644 src/api/order/orderCancel.ts create mode 100644 src/tests/unit/api/order/issue203.test.ts diff --git a/API_VersionNum.txt b/API_VersionNum.txt new file mode 100644 index 00000000..c6fe585c --- /dev/null +++ b/API_VersionNum.txt @@ -0,0 +1 @@ +API_Version=10.32.01 diff --git a/README.md b/README.md index ad175da9..c40a490e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ -`@stoqey/ib` is an [Interactive Brokers](http://interactivebrokers.com/) TWS (or IB Gateway) Typescript API client library for [Node.js](http://nodejs.org/). It is a port of Interactive Brokers' Java Client Version 10.29.01 ("latest") from June 18th, 2024. +`@stoqey/ib` is an [Interactive Brokers](http://interactivebrokers.com/) TWS (or IB Gateway) Typescript API client library for [Node.js](http://nodejs.org/). It is a port of Interactive Brokers' Java Client Version 10.32.01 ("latest" relased on Oct 9, 2024). Refer to the [Trader Workstation API](https://interactivebrokers.github.io/tws-api/) for the official documentation and the C#/Java/VB/C++/Python client. diff --git a/package.json b/package.json index 13cdedf2..4079dfa3 100644 --- a/package.json +++ b/package.json @@ -74,21 +74,21 @@ "rxjs": "^7.8.1" }, "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "^18.19.41", + "@types/jest": "^29.5.14", + "@types/node": "^18.19.64", "@types/source-map-support": "^0.5.10", - "@typescript-eslint/eslint-plugin": "^7.16.1", - "@typescript-eslint/parser": "^7.16.1", + "@typescript-eslint/eslint-plugin": "^7.18.0", + "@typescript-eslint/parser": "^7.18.0", "ajv": "^8.17.1", - "eslint": "^8.57.0", - "eslint-plugin-jest": "^28.6.0", + "eslint": "^8.57.1", + "eslint-plugin-jest": "^28.9.0", "eslint-plugin-rxjs": "^5.0.3", "jest": "^29.7.0", "jest-environment-node": "^29.7.0", "jest-junit": "^16.0.0", - "ts-jest": "^29.2.3", - "typedoc": "^0.26.4", - "typescript": "^5.5.3" + "ts-jest": "^29.2.5", + "typedoc": "^0.26.11", + "typescript": "^5.6.3" }, "engines": { "node": ">=18.0.0" diff --git a/ref/client/Builder.java b/ref/client/Builder.java index 519080e9..c0725320 100644 --- a/ref/client/Builder.java +++ b/ref/client/Builder.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; @@ -111,7 +111,7 @@ static void intToBytes(int val, byte b[], int position) { b[position+3] = (byte)(0xff & val); } - private static boolean isAsciiPrintable(String str) { + static boolean isAsciiPrintable(String str) { if (str == null) { return false; } diff --git a/ref/client/ContractDetails.java b/ref/client/ContractDetails.java index e8d18e0c..d3c918b2 100644 --- a/ref/client/ContractDetails.java +++ b/ref/client/ContractDetails.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; @@ -74,6 +74,7 @@ public class ContractDetails { private String m_fundBlueSkyTerritories; private FundDistributionPolicyIndicator m_fundDistributionPolicyIndicator; private FundAssetType m_fundAssetType; + private List m_ineligibilityReasonList; // Get public int conid() { return m_contract.conid(); } @@ -139,6 +140,7 @@ public class ContractDetails { public String fundBlueSkyTerritories() { return m_fundBlueSkyTerritories; } public FundDistributionPolicyIndicator fundDistributionPolicyIndicator() { return m_fundDistributionPolicyIndicator; } public FundAssetType fundAssetType() { return m_fundAssetType; } + public List ineligibilityReasonList() { return m_ineligibilityReasonList; } // Set public void contract(Contract contract) { m_contract = contract; } @@ -203,6 +205,7 @@ public class ContractDetails { public void fundBlueSkyTerritories(String fundBlueSkyTerritories) { m_fundBlueSkyTerritories = fundBlueSkyTerritories; } public void fundDistributionPolicyIndicator(FundDistributionPolicyIndicator fundDistributionPolicyIndicator) { m_fundDistributionPolicyIndicator = fundDistributionPolicyIndicator; } public void fundAssetType(FundAssetType fundAssetType) { m_fundAssetType = fundAssetType; } + public void ineligibilityReasonList(List ineligibilityReasonList) { m_ineligibilityReasonList = ineligibilityReasonList; } public ContractDetails() { m_contract = new Contract(); @@ -276,7 +279,9 @@ public ContractDetails() { add( sb, "fundDistributionPolicyIndicator", m_fundDistributionPolicyIndicator != null ? m_fundDistributionPolicyIndicator.name() : ""); add( sb, "fundAssetType", m_fundAssetType != null ? m_fundAssetType.name() : ""); } - + + add( sb, "ineligibilityReasonList", EWrapperMsgGenerator.contractDetailsIneligibilityReasonList(this)); + return sb.toString(); } diff --git a/ref/client/DefaultEWrapper.java b/ref/client/DefaultEWrapper.java index c53eb52e..32733b4e 100644 --- a/ref/client/DefaultEWrapper.java +++ b/ref/client/DefaultEWrapper.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; @@ -54,7 +54,7 @@ public void tickEFP(int tickerId, int tickType, double basisPoints, @Override public void orderStatus(int orderId, String status, Decimal filled, - Decimal remaining, double avgFillPrice, int permId, int parentId, + Decimal remaining, double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice) { // TODO Auto-generated method stub @@ -525,7 +525,7 @@ public void tickByTickMidPoint(int reqId, long time, double midPoint) { } @Override - public void orderBound(long orderId, int apiClientId, int apiOrderId) { + public void orderBound(long permId, int clientId, int orderId) { // TODO Auto-generated method stub } diff --git a/ref/client/EClient.java b/ref/client/EClient.java index 570f4ebb..1e29750f 100644 --- a/ref/client/EClient.java +++ b/ref/client/EClient.java @@ -309,9 +309,18 @@ public abstract class EClient { protected static final int MIN_SERVER_VER_LAST_TRADE_DATE = 182; protected static final int MIN_SERVER_VER_CUSTOMER_ACCOUNT = 183; protected static final int MIN_SERVER_VER_PROFESSIONAL_CUSTOMER = 184; + protected static final int MIN_SERVER_VER_BOND_ACCRUED_INTEREST = 185; + protected static final int MIN_SERVER_VER_INELIGIBILITY_REASONS = 186; + protected static final int MIN_SERVER_VER_RFQ_FIELDS = 187; + protected static final int MIN_SERVER_VER_BOND_TRADING_HOURS = 188; + protected static final int MIN_SERVER_VER_INCLUDE_OVERNIGHT = 189; + protected static final int MIN_SERVER_VER_UNDO_RFQ_FIELDS = 190; + protected static final int MIN_SERVER_VER_PERM_ID_AS_LONG = 191; + protected static final int MIN_SERVER_VER_CME_TAGGING_FIELDS = 192; + protected static final int MIN_SERVER_VER_CME_TAGGING_FIELDS_IN_OPEN_ORDER = 193; public static final int MIN_VERSION = 100; // envelope encoding, applicable to useV100Plus mode only - public static final int MAX_VERSION = MIN_SERVER_VER_PROFESSIONAL_CUSTOMER; // ditto + public static final int MAX_VERSION = MIN_SERVER_VER_CME_TAGGING_FIELDS_IN_OPEN_ORDER; // ditto protected EReaderSignal m_signal; protected EWrapper m_eWrapper; // msg handler @@ -1602,8 +1611,9 @@ public synchronized void placeOrder( int id, Contract contract, Order order) { } if (m_serverVersion < MIN_SERVER_VER_ALGO_ID && !IsEmpty(order.algoId()) ) { - error(id, EClientErrors.UPDATE_TWS, " It does not support algoId parameter"); - } + error(id, EClientErrors.UPDATE_TWS, " It does not support algoId parameter"); + return; + } if (m_serverVersion < MIN_SERVER_VER_SCALE_TABLE) { if (!IsEmpty(order.scaleTable()) || !IsEmpty(order.activeStartTime()) || !IsEmpty(order.activeStopTime())) { @@ -1630,12 +1640,14 @@ public synchronized void placeOrder( int id, Contract contract, Order order) { } if (m_serverVersion < MIN_SERVER_VER_EXT_OPERATOR && !IsEmpty(order.extOperator()) ) { - error(id, EClientErrors.UPDATE_TWS, " It does not support ext operator"); + error(id, EClientErrors.UPDATE_TWS, " It does not support ext operator"); + return; } if (m_serverVersion < MIN_SERVER_VER_SOFT_DOLLAR_TIER && - (!IsEmpty(order.softDollarTier().name()) || !IsEmpty(order.softDollarTier().value()))) { - error(id, EClientErrors.UPDATE_TWS, " It does not support soft dollar tier"); + (!IsEmpty(order.softDollarTier().name()) || !IsEmpty(order.softDollarTier().value()))) { + error(id, EClientErrors.UPDATE_TWS, " It does not support soft dollar tier"); + return; } @@ -1749,6 +1761,20 @@ public synchronized void placeOrder( int id, Contract contract, Order order) { } } + if (m_serverVersion < MIN_SERVER_VER_INCLUDE_OVERNIGHT) { + if (order.includeOvernight()) { + error(id, EClientErrors.UPDATE_TWS, " It does not support include overnight parameter"); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_CME_TAGGING_FIELDS) { + if (order.manualOrderIndicator() != Integer.MAX_VALUE) { + error(id, EClientErrors.UPDATE_TWS, " It does not support manual order indicator parameter"); + return; + } + } + int VERSION = (m_serverVersion < MIN_SERVER_VER_NOT_HELD) ? 27 : 45; // send place order msg @@ -2223,6 +2249,19 @@ public synchronized void placeOrder( int id, Contract contract, Order order) { b.send(order.professionalCustomer()); } + if (m_serverVersion >= MIN_SERVER_VER_RFQ_FIELDS && m_serverVersion < MIN_SERVER_VER_UNDO_RFQ_FIELDS) { + b.send(""); + b.send(Integer.MAX_VALUE); + } + + if (m_serverVersion >= MIN_SERVER_VER_INCLUDE_OVERNIGHT) { + b.send(order.includeOvernight()); + } + + if (m_serverVersion >= MIN_SERVER_VER_CME_TAGGING_FIELDS) { + b.send(order.manualOrderIndicator()); + } + closeAndSend(b); } catch(EClientException e) { @@ -2309,7 +2348,7 @@ public synchronized void reqExecutions(int reqId, ExecutionFilter filter) { } } - public synchronized void cancelOrder( int id, String manualOrderCancelTime) { + public synchronized void cancelOrder( int id, OrderCancel orderCancel) { // not connected? if( !isConnected()) { notConnected(); @@ -2317,12 +2356,19 @@ public synchronized void cancelOrder( int id, String manualOrderCancelTime) { } if (m_serverVersion < MIN_SERVER_VER_MANUAL_ORDER_TIME) { - if (!IsEmpty(manualOrderCancelTime)) { + if (!IsEmpty(orderCancel.manualOrderCancelTime())) { error(id, EClientErrors.UPDATE_TWS, " It does not support manual order cancel time attribute"); return; } } + if (m_serverVersion < MIN_SERVER_VER_CME_TAGGING_FIELDS) { + if (!IsEmpty(orderCancel.extOperator()) || orderCancel.manualOrderIndicator() != Integer.MAX_VALUE) { + error(id, EClientErrors.UPDATE_TWS, " It does not support ext operator and manual order indicator parameters"); + return; + } + } + final int VERSION = 1; // send cancel order msg @@ -2330,15 +2376,31 @@ public synchronized void cancelOrder( int id, String manualOrderCancelTime) { Builder b = prepareBuffer(); b.send( CANCEL_ORDER); - b.send( VERSION); + if (m_serverVersion < MIN_SERVER_VER_CME_TAGGING_FIELDS) { + b.send( VERSION); + } b.send( id); if (m_serverVersion >= MIN_SERVER_VER_MANUAL_ORDER_TIME) { - b.send(manualOrderCancelTime); + b.send(orderCancel.manualOrderCancelTime()); + } + + if (m_serverVersion >= MIN_SERVER_VER_RFQ_FIELDS && m_serverVersion < MIN_SERVER_VER_UNDO_RFQ_FIELDS) { + b.send(""); + b.send(""); + b.send(Integer.MAX_VALUE); + } + + if (m_serverVersion >= MIN_SERVER_VER_CME_TAGGING_FIELDS) { + b.send(orderCancel.extOperator()); + b.send(orderCancel.manualOrderIndicator()); } closeAndSend(b); } + catch( EClientException e) { + error( id, e.error(), e.text()); + } catch( Exception e) { error( id, EClientErrors.FAIL_SEND_CORDER, e.toString()); close(); @@ -2941,7 +3003,7 @@ public synchronized void cancelCalculateOptionPrice(int reqId) { } } - public synchronized void reqGlobalCancel() { + public synchronized void reqGlobalCancel(OrderCancel orderCancel) { // not connected? if( !isConnected()) { notConnected(); @@ -2954,6 +3016,13 @@ public synchronized void reqGlobalCancel() { return; } + if (m_serverVersion < MIN_SERVER_VER_CME_TAGGING_FIELDS) { + if (!IsEmpty(orderCancel.extOperator()) || orderCancel.manualOrderIndicator() != Integer.MAX_VALUE) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, " It does not support ext operator and manual order indicator parameters"); + return; + } + } + final int VERSION = 1; // send request global cancel msg @@ -2961,7 +3030,14 @@ public synchronized void reqGlobalCancel() { Builder b = prepareBuffer(); b.send( REQ_GLOBAL_CANCEL); - b.send( VERSION); + if (m_serverVersion < MIN_SERVER_VER_CME_TAGGING_FIELDS) { + b.send( VERSION); + } + + if (m_serverVersion >= MIN_SERVER_VER_CME_TAGGING_FIELDS) { + b.send(orderCancel.extOperator()); + b.send(orderCancel.manualOrderIndicator()); + } closeAndSend(b); } @@ -4231,6 +4307,9 @@ public synchronized void reqWshEventData(int reqId, WshEventData wshEventData) { closeAndSend(b); } + catch( EClientException e) { + error( reqId, e.error(), e.text()); + } catch( Exception e) { error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQ_WSH_EVENT_DATA, e.toString()); @@ -4318,6 +4397,21 @@ protected void error(int id, EClientErrors.CodeMsgPair pair, String tail) { protected abstract void closeAndSend(Builder buf) throws IOException; + + protected void validateInvalidSymbols(String host) throws EClientException { + if (host != null && !Builder.isAsciiPrintable(host)) { + throw new EClientException(EClientErrors.INVALID_SYMBOL, host); + } + + if (m_connectOptions != null && !Builder.isAsciiPrintable(m_connectOptions)) { + throw new EClientException(EClientErrors.INVALID_SYMBOL, m_connectOptions); + } + + if (m_optionalCapabilities != null && !Builder.isAsciiPrintable(m_optionalCapabilities)) { + throw new EClientException(EClientErrors.INVALID_SYMBOL, m_optionalCapabilities); + } + } + private void sendV100APIHeader() throws IOException { try (Builder builder = new Builder(1024)) { builder.send("API\0".getBytes(StandardCharsets.UTF_8)); diff --git a/ref/client/EClientErrors.java b/ref/client/EClientErrors.java index ab4e04ca..2a68093d 100644 --- a/ref/client/EClientErrors.java +++ b/ref/client/EClientErrors.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; @@ -94,6 +94,7 @@ public class EClientErrors { static final CodeMsgPair FAIL_SEND_CAN_WSH_EVENT_DATA = new CodeMsgPair(583, "Cancel WSH Event Data Sending Error - "); static final CodeMsgPair FAIL_SEND_REQ_USER_INFO = new CodeMsgPair(584, "Request User Info Sending Error - "); static final CodeMsgPair FA_PROFILE_NOT_SUPPORTED = new CodeMsgPair(585, "FA Profile is not supported anymore, use FA Group instead - "); + static final CodeMsgPair FAIL_READ_MESSAGE = new CodeMsgPair(586, "Failed to read message because not connected"); public EClientErrors() { } diff --git a/ref/client/EClientSocket.java b/ref/client/EClientSocket.java index d317cdd8..3796dd34 100644 --- a/ref/client/EClientSocket.java +++ b/ref/client/EClientSocket.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; @@ -84,6 +84,14 @@ public synchronized void eConnect( String host, int port, int clientId) { } public synchronized void eConnect( String host, int port, int clientId, boolean extraAuth) { + try { + validateInvalidSymbols(host); + } + catch(EClientException e) { + error(EClientErrors.NO_VALID_ID, e.error(), e.text()); + return; + } + // already connected? m_host = checkConnected(host); @@ -229,10 +237,16 @@ private synchronized void eDisconnect( boolean resetState ) { } public int read(byte[] buf, int off, int len) throws IOException { + if (m_dis == null) { + throw new EClientException(EClientErrors.FAIL_READ_MESSAGE, ""); + } return m_dis.read(buf, off, len); } public int readInt() throws IOException { + if (m_dis == null) { + throw new EClientException(EClientErrors.FAIL_READ_MESSAGE, ""); + } return m_dis.readInt(); } diff --git a/ref/client/EDecoder.java b/ref/client/EDecoder.java index a0a6125d..64bef6c5 100644 --- a/ref/client/EDecoder.java +++ b/ref/client/EDecoder.java @@ -1149,7 +1149,7 @@ private void processExecutionDataMsg() throws IOException { exec.shares(readDecimal()); exec.price(readDouble()); if ( version >= 2 ) { - exec.permId(readInt()); + exec.permId(readLong()); } if ( version >= 3) { exec.clientId(readInt()); @@ -1230,6 +1230,11 @@ private void processBondContractDataMsg() throws IOException { if( version >= 4) { contract.longName(readStr()); } + if (m_serverVersion >= EClient.MIN_SERVER_VER_BOND_TRADING_HOURS) { + contract.timeZoneId(readStr()); + contract.tradingHours(readStr()); + contract.liquidHours(readStr()); + } if ( version >= 6) { contract.evRule(readStr()); contract.evMultiplier(readDouble()); @@ -1372,7 +1377,19 @@ private void processContractDataMsg() throws IOException { contract.fundDistributionPolicyIndicator(FundDistributionPolicyIndicator.get(readStr())); contract.fundAssetType(FundAssetType.get(readStr())); } - + + if (m_serverVersion >= EClient.MIN_SERVER_VER_INELIGIBILITY_REASONS) { + int ineligibilityReasonCount = readInt(); + List ineligibilityReasonList = new ArrayList<>(); + + for (int i = 0; i < ineligibilityReasonCount; i++) { + String id = readStr(); + String description = readStr(); + ineligibilityReasonList.add(new IneligibilityReason(id, description)); + } + contract.ineligibilityReasonList(ineligibilityReasonList); + } + m_EWrapper.contractDetails( reqId, contract); } @@ -1502,6 +1519,9 @@ private void processOpenOrderMsg() throws IOException { eOrderDecoder.readPegBestPegMidOrderAttributes(); eOrderDecoder.readCustomerAccount(); eOrderDecoder.readProfessionalCustomer(); + eOrderDecoder.readBondAccruedInterest(); + eOrderDecoder.readIncludeOvernight(); + eOrderDecoder.readCMETaggingFields(); m_EWrapper.openOrder(order.orderId(), contract, order, orderState); } @@ -1597,9 +1617,9 @@ private void processOrderStatusMsg() throws IOException { Decimal remaining = readDecimal(); double avgFillPrice = readDouble(); - int permId = 0; + long permId = 0; if( version >= 2) { - permId = readInt(); + permId = readLong(); } int parentId = 0; @@ -1955,10 +1975,10 @@ private void processTickByTickMsg() throws IOException { } private void processOrderBoundMsg() throws IOException { - long orderId = readLong(); - int apiClientId = readInt(); - int apiOrderId = readInt(); - m_EWrapper.orderBound(orderId, apiClientId, apiOrderId); + long permId = readLong(); + int clientId = readInt(); + int orderId = readInt(); + m_EWrapper.orderBound(permId, clientId, orderId); } private void processCompletedOrderMsg() throws IOException { @@ -2092,19 +2112,19 @@ private void processUserInfo() throws IOException { private void readLastTradeDate(ContractDetails contract, boolean isBond) throws IOException { String lastTradeDateOrContractMonth = readStr(); if (lastTradeDateOrContractMonth != null) { - String[] splitted = lastTradeDateOrContractMonth.contains("-") ? lastTradeDateOrContractMonth.split("-") : lastTradeDateOrContractMonth.split("\\s+"); - if (splitted.length > 0) { + String[] split = lastTradeDateOrContractMonth.contains("-") ? lastTradeDateOrContractMonth.split("-") : lastTradeDateOrContractMonth.split("\\s+"); + if (split.length > 0) { if (isBond) { - contract.maturity(splitted[0]); + contract.maturity(split[0]); } else { - contract.contract().lastTradeDateOrContractMonth(splitted[0]); + contract.contract().lastTradeDateOrContractMonth(split[0]); } } - if (splitted.length > 1) { - contract.lastTradeTime(splitted[1]); + if (split.length > 1) { + contract.lastTradeTime(split[1]); } - if (isBond && splitted.length > 2) { - contract.timeZoneId(splitted[2]); + if (isBond && split.length > 2) { + contract.timeZoneId(split[2]); } } } diff --git a/ref/client/EOrderDecoder.java b/ref/client/EOrderDecoder.java index 44148184..2a132c52 100644 --- a/ref/client/EOrderDecoder.java +++ b/ref/client/EOrderDecoder.java @@ -113,7 +113,7 @@ public void readClientId() throws IOException { public void readPermId() throws IOException { if( m_version >= 4 ) { - m_order.permId(m_eDecoder.readInt()); + m_order.permId(m_eDecoder.readLong()); } } @@ -704,4 +704,23 @@ public void readProfessionalCustomer() throws IOException { m_order.professionalCustomer(m_eDecoder.readBoolFromInt()); } } + + public void readBondAccruedInterest() throws IOException { + if (m_serverVersion >= EClient.MIN_SERVER_VER_BOND_ACCRUED_INTEREST) { + m_order.bondAccruedInterest(m_eDecoder.readStr()); + } + } + + public void readIncludeOvernight() throws IOException { + if (m_serverVersion >= EClient.MIN_SERVER_VER_INCLUDE_OVERNIGHT) { + m_order.includeOvernight(m_eDecoder.readBoolFromInt()); + } + } + + public void readCMETaggingFields() throws IOException { + if (m_serverVersion >= EClient.MIN_SERVER_VER_CME_TAGGING_FIELDS_IN_OPEN_ORDER) { + m_order.extOperator(m_eDecoder.readStr()); + m_order.manualOrderIndicator(m_eDecoder.readIntMax()); + } + } } diff --git a/ref/client/EReader.java b/ref/client/EReader.java index 921d1a20..6a75828e 100644 --- a/ref/client/EReader.java +++ b/ref/client/EReader.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; @@ -63,8 +63,10 @@ public void run() { if( ex instanceof EOFException ) { eWrapper().error(EClientErrors.NO_VALID_ID, EClientErrors.BAD_LENGTH.code(), EClientErrors.BAD_LENGTH.msg() + " " + ex.getMessage(), null); - } - else { + } else if (ex instanceof EClientException) { + EClientException eClientException = (EClientException)ex; + eWrapper().error(EClientErrors.NO_VALID_ID, eClientException.error().code(), eClientException.error().msg(), null); + } else { eWrapper().error( ex); } diff --git a/ref/client/EWrapper.java b/ref/client/EWrapper.java index 4d865f1c..eb8e8c9a 100644 --- a/ref/client/EWrapper.java +++ b/ref/client/EWrapper.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; @@ -23,7 +23,7 @@ void tickEFP(int tickerId, int tickType, double basisPoints, String formattedBasisPoints, double impliedFuture, int holdDays, String futureLastTradeDate, double dividendImpact, double dividendsToLastTradeDate); void orderStatus( int orderId, String status, Decimal filled, Decimal remaining, - double avgFillPrice, int permId, int parentId, double lastFillPrice, + double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice); void openOrder( int orderId, Contract contract, Order order, OrderState orderState); void openOrderEnd(); @@ -103,7 +103,7 @@ void scannerData(int reqId, int rank, ContractDetails contractDetails, String di void tickByTickAllLast(int reqId, int tickType, long time, double price, Decimal size, TickAttribLast tickAttribLast, String exchange, String specialConditions); void tickByTickBidAsk(int reqId, long time, double bidPrice, double askPrice, Decimal bidSize, Decimal askSize, TickAttribBidAsk tickAttribBidAsk); void tickByTickMidPoint(int reqId, long time, double midPoint); - void orderBound(long orderId, int apiClientId, int apiOrderId); + void orderBound(long permId, int clientId, int orderId); void completedOrder(Contract contract, Order order, OrderState orderState); void completedOrdersEnd(); void replaceFAEnd(int reqId, String text); diff --git a/ref/client/EWrapperMsgGenerator.java b/ref/client/EWrapperMsgGenerator.java index e98d8c64..81164235 100644 --- a/ref/client/EWrapperMsgGenerator.java +++ b/ref/client/EWrapperMsgGenerator.java @@ -59,9 +59,9 @@ public static String tickEFP(int tickerId, int tickType, double basisPoints, } public static String orderStatus( int orderId, String status, Decimal filled, Decimal remaining, - double avgFillPrice, int permId, int parentId, double lastFillPrice, + double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice) { - return "order status: orderId=" + orderId + " clientId=" + Util.IntMaxString(clientId) + " permId=" + Util.IntMaxString(permId) + + return "order status: orderId=" + orderId + " clientId=" + Util.IntMaxString(clientId) + " permId=" + Util.LongMaxString(permId) + " status=" + status + " filled=" + filled + " remaining=" + remaining + " avgFillPrice=" + Util.DoubleMaxString(avgFillPrice) + " lastFillPrice=" + Util.DoubleMaxString(lastFillPrice) + " parent Id=" + Util.IntMaxString(parentId) + " whyHeld=" + whyHeld + " mktCapPrice=" + Util.DoubleMaxString(mktCapPrice); @@ -140,7 +140,8 @@ private static String contractDetailsMsg(ContractDetails contractDetails) { + "sizeIncrement = " + contractDetails.sizeIncrement() + "\n" + "suggestedSizeIncrement = " + contractDetails.suggestedSizeIncrement() + "\n" + contractDetailsFundData(contractDetails) - + contractDetailsSecIdList(contractDetails); + + contractDetailsSecIdList(contractDetails) + + contractDetailsIneligibilityReasons(contractDetails); } private static String contractDetailsFundData(ContractDetails contractDetails) { @@ -219,11 +220,13 @@ public static String bondContractDetails(int reqId, ContractDetails contractDeta + "nextOptionPartial = " + contractDetails.nextOptionPartial() + "\n" + "notes = " + contractDetails.notes() + "\n" + "longName = " + contractDetails.longName() + "\n" + + "timeZoneId = " + contractDetails.timeZoneId() + "\n" + + "tradingHours = " + contractDetails.tradingHours() + "\n" + + "liquidHours = " + contractDetails.liquidHours() + "\n" + "evRule = " + contractDetails.evRule() + "\n" + "evMultiplier = " + Util.DoubleMaxString(contractDetails.evMultiplier()) + "\n" + "aggGroup = " + Util.IntMaxString(contractDetails.aggGroup()) + "\n" + "marketRuleIds = " + contractDetails.marketRuleIds() + "\n" - + "timeZoneId = " + contractDetails.timeZoneId() + "\n" + "lastTradeTime = " + contractDetails.lastTradeTime() + "\n" + "minSize = " + contractDetails.minSize() + "\n" + "sizeIncrement = " + contractDetails.sizeIncrement() + "\n" @@ -246,7 +249,25 @@ private static String contractDetailsSecIdList(ContractDetails contractDetails) sb.append("}\n"); return sb.toString(); } + + public static String contractDetailsIneligibilityReasons(ContractDetails contractDetails) { + final StringBuilder sb = new StringBuilder(); + sb.append("ineligibilityReasonList={"); + sb.append(contractDetailsIneligibilityReasonList(contractDetails)); + sb.append("}\n"); + return sb.toString(); + } + public static String contractDetailsIneligibilityReasonList(ContractDetails contractDetails) { + final StringBuilder sb = new StringBuilder(); + if (contractDetails.ineligibilityReasonList() != null) { + for (IneligibilityReason ineligibilityReason : contractDetails.ineligibilityReasonList()) { + sb.append(ineligibilityReason).append(";"); + } + } + return sb.toString(); + } + public static String contractDetailsEnd(int reqId) { return "reqId = " + reqId + " =============== end ==============="; } @@ -264,7 +285,7 @@ public static String execDetails( int reqId, Contract contract, Execution execut + "side = " + execution.side() + "\n" + "shares = " + execution.shares() + "\n" + "price = " + Util.DoubleMaxString(execution.price()) + "\n" - + "permId = " + Util.IntMaxString(execution.permId()) + "\n" + + "permId = " + Util.LongMaxString(execution.permId()) + "\n" + "liquidation = " + Util.IntMaxString(execution.liquidation()) + "\n" + "cumQty = " + execution.cumQty() + "\n" + "avgPrice = " + Util.DoubleMaxString(execution.avgPrice()) + "\n" @@ -700,8 +721,8 @@ public static String tickByTickMidPoint(int reqId, long time, double midPoint){ return "MidPoint. Req Id: " + reqId + " Time: " + Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss") + " MidPoint: " + Util.DoubleMaxString(midPoint); } - public static String orderBound(long orderId, int apiClientId, int apiOrderId){ - return "order bound: apiOrderId=" + Util.IntMaxString(apiOrderId) + " apiClientId=" + Util.IntMaxString(apiClientId) + " permId=" + Util.LongMaxString(orderId); + public static String orderBound(long permId, int clientId, int orderId){ + return "order bound: orderId=" + Util.IntMaxString(orderId) + " clientId=" + Util.IntMaxString(clientId) + " permId=" + Util.LongMaxString(permId); } public static String completedOrder( Contract contract, Order order, OrderState orderState) { @@ -777,7 +798,7 @@ private static void appendOrderFields(StringBuilder sb, int orderId, Contract co Util.appendNonEmptyString(sb, "orderRef", order.orderRef()); Util.appendValidIntValue(sb, "clientId", order.clientId()); Util.appendValidIntValue(sb, "parentId", order.parentId()); - Util.appendValidIntValue(sb, "permId", order.permId()); + Util.appendValidLongValue(sb, "permId", order.permId()); Util.appendBooleanFlag(sb, "outsideRth", order.outsideRth()); Util.appendBooleanFlag(sb, "hidden", order.hidden()); Util.appendValidDoubleValue(sb, "discretionaryAmt", order.discretionaryAmt()); @@ -961,6 +982,10 @@ private static void appendOrderFields(StringBuilder sb, int orderId, Contract co Util.appendValidDoubleValue(sb, "midOffsetAtHalf", order.midOffsetAtHalf()); Util.appendNonEmptyString(sb, "customerAccount", order.customerAccount()); Util.appendBooleanFlag(sb, "professionalCustomer", order.professionalCustomer()); + Util.appendNonEmptyString(sb, "bondAccruedInterest", order.bondAccruedInterest()); + Util.appendBooleanFlag(sb, "includeOvernight", order.includeOvernight()); + Util.appendNonEmptyString(sb, "extOperator", order.extOperator()); + Util.appendValidIntValue(sb, "manualOrderIndicator", order.manualOrderIndicator()); Util.appendNonEmptyString(sb, "status", orderState.getStatus()); Util.appendNonEmptyString(sb, "completedTime", orderState.completedTime()); diff --git a/ref/client/Execution.java b/ref/client/Execution.java index 2931ef1d..c83d6fa0 100644 --- a/ref/client/Execution.java +++ b/ref/client/Execution.java @@ -1,42 +1,8 @@ -/* Copyright (C) 2023 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; -enum Liquidities { - None, - Added("Added Liquidity"), - Removed("Removed Liquidity"), - RoudedOut("Liquidity Routed Out"); - - private String m_text; - - Liquidities(String text) { - m_text = text; - } - - Liquidities() { - m_text = "None"; - } - - @Override - public String toString() { - return m_text; - } - - public static Liquidities fromInt(int n) { - if (n < 0 || n > Liquidities.values().length) { - return Liquidities.None; - } - - return Liquidities.values()[n]; - } - - public static int toInt(Liquidities l) { - return l.ordinal(); - } -} - public class Execution { private int m_orderId; private int m_clientId; @@ -47,7 +13,7 @@ public class Execution { private String m_side; private Decimal m_shares; private double m_price; - private int m_permId; + private long m_permId; private int m_liquidation; private Decimal m_cumQty; private double m_avgPrice; @@ -68,7 +34,7 @@ public class Execution { public String side() { return m_side; } public Decimal shares() { return m_shares; } public double price() { return m_price; } - public int permId() { return m_permId; } + public long permId() { return m_permId; } public int liquidation() { return m_liquidation; } public Decimal cumQty() { return m_cumQty; } public double avgPrice() { return m_avgPrice; } @@ -90,7 +56,7 @@ public class Execution { public void side(String side) { m_side = side; } public void shares(Decimal shares) { m_shares = shares; } public void price(double price) { m_price = price; } - public void permId(int permId) { m_permId = permId; } + public void permId(long permId) { m_permId = permId; } public void liquidation(int liquidation) { m_liquidation = liquidation; } public void cumQty(Decimal cumQty) { m_cumQty = cumQty; } public void avgPrice(double avgPrice) { m_avgPrice = avgPrice; } @@ -117,7 +83,7 @@ public Execution() { public Execution( int p_orderId, int p_clientId, String p_execId, String p_time, String p_acctNumber, String p_exchange, String p_side, Decimal p_shares, - double p_price, int p_permId, int p_liquidation, Decimal p_cumQty, + double p_price, long p_permId, int p_liquidation, Decimal p_cumQty, double p_avgPrice, String p_orderRef, String p_evRule, double p_evMultiplier, String p_modelCode, Liquidities lastLiquidity, boolean pendingPriceRevision) { m_orderId = p_orderId; diff --git a/ref/client/IneligibilityReason.java b/ref/client/IneligibilityReason.java new file mode 100644 index 00000000..1f5c9c1a --- /dev/null +++ b/ref/client/IneligibilityReason.java @@ -0,0 +1,33 @@ +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +public class IneligibilityReason { + private String m_id; + private String m_description; + + // Get + public String id() { return m_id; } + public String description() { return m_description; } + + // Set + public void id(String id) { m_id = id; } + public void description(String description) { m_description = description; } + + public IneligibilityReason() { + } + + public IneligibilityReason(String p_id, String p_description) { + m_id = p_id; + m_description = p_description; + } + + @Override public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[id: ").append(m_id); + sb.append(", description: ").append(m_description); + sb.append("]"); + return sb.toString(); + } +} diff --git a/ref/client/Liquidities.java b/ref/client/Liquidities.java new file mode 100644 index 00000000..f6826dc8 --- /dev/null +++ b/ref/client/Liquidities.java @@ -0,0 +1,38 @@ +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +public enum Liquidities { + None, + Added("Added Liquidity"), + Removed("Removed Liquidity"), + RoudedOut("Liquidity Routed Out"); + + private String m_text; + + Liquidities(String text) { + m_text = text; + } + + Liquidities() { + m_text = "None"; + } + + @Override + public String toString() { + return m_text; + } + + public static Liquidities fromInt(int n) { + if (n < 0 || n > Liquidities.values().length) { + return Liquidities.None; + } + + return Liquidities.values()[n]; + } + + public static int toInt(Liquidities l) { + return l.ordinal(); + } +} diff --git a/ref/client/Order.java b/ref/client/Order.java index 923dc2e2..8c94a613 100644 --- a/ref/client/Order.java +++ b/ref/client/Order.java @@ -36,7 +36,7 @@ public class Order { // order id's private int m_clientId; private int m_orderId; - private int m_permId; + private long m_permId; private int m_parentId; // Parent order Id, to associate Auto STP or TRAIL orders with the original order. // primary attributes @@ -226,7 +226,10 @@ public class Order { private double m_midOffsetAtHalf; private String m_customerAccount; private boolean m_professionalCustomer; - + private String m_bondAccruedInterest; + private boolean m_includeOvernight; + private int m_manualOrderIndicator; + // getters public Action action() { return Action.get(m_action); } public String getAction() { return m_action; } @@ -277,7 +280,7 @@ public class Order { public int scalePriceAdjustInterval() { return m_scalePriceAdjustInterval; } public int scaleSubsLevelSize() { return m_scaleSubsLevelSize; } public Decimal totalQuantity() { return m_totalQuantity; } - public int permId() { return m_permId; } + public long permId() { return m_permId; } public Method faMethod() { return Method.get(m_faMethod); } public String getFaMethod() { return m_faMethod; } public OcaType ocaType() { return OcaType.get(m_ocaType); } @@ -377,6 +380,9 @@ public class Order { public double midOffsetAtHalf() { return m_midOffsetAtHalf; } public String customerAccount() { return m_customerAccount; } public boolean professionalCustomer() { return m_professionalCustomer; } + public String bondAccruedInterest() { return m_bondAccruedInterest; } + public boolean includeOvernight() { return m_includeOvernight; } + public int manualOrderIndicator() { return m_manualOrderIndicator; } // setters public void referenceContractId(int m_referenceContractId) { this.m_referenceContractId = m_referenceContractId; } @@ -436,7 +442,7 @@ public class Order { public void exemptCode(int v) { m_exemptCode = v; } public void parentId(int v) { m_parentId = v; } public void percentOffset(double v) { m_percentOffset = v; } - public void permId(int v) { m_permId = v; } + public void permId(long v) { m_permId = v; } public void referencePriceType(ReferencePriceType v) { m_referencePriceType = ( v == null ) ? 0 : v.ordinal(); } public void referencePriceType(int v) { m_referencePriceType = v; } public void rule80A(Rule80A v) { m_rule80A = ( v == null ) ? null : v.getApiString(); } @@ -529,6 +535,9 @@ public class Order { public void midOffsetAtHalf(double v) { m_midOffsetAtHalf = v; } public void customerAccount(String v) { m_customerAccount = v; } public void professionalCustomer(boolean v) { m_professionalCustomer = v; } + public void bondAccruedInterest(String v) { m_bondAccruedInterest = v; } + public void includeOvernight(boolean v) { m_includeOvernight = v; } + public void manualOrderIndicator(int v) { m_manualOrderIndicator = v; } public Order() { @@ -587,6 +596,9 @@ public Order() { m_midOffsetAtHalf = Double.MAX_VALUE; m_customerAccount = EMPTY_STR; m_professionalCustomer = false; + m_bondAccruedInterest = EMPTY_STR; + m_includeOvernight = false; + m_manualOrderIndicator = Integer.MAX_VALUE; } public List algoParams() { @@ -696,6 +708,8 @@ public boolean equals(Object p_other) { || m_midOffsetAtWhole != l_theOther.m_midOffsetAtWhole || m_midOffsetAtHalf != l_theOther.m_midOffsetAtHalf || m_professionalCustomer != l_theOther.m_professionalCustomer + || m_includeOvernight != l_theOther.m_includeOvernight + || m_manualOrderIndicator != l_theOther.m_manualOrderIndicator ) { return false; } @@ -742,6 +756,7 @@ public boolean equals(Object p_other) { || Util.StringCompare(m_advancedErrorOverride, l_theOther.m_advancedErrorOverride) != 0 || Util.StringCompare(m_manualOrderTime, l_theOther.m_manualOrderTime) != 0 || Util.StringCompare(m_customerAccount, l_theOther.m_customerAccount) != 0 + || Util.StringCompare(m_bondAccruedInterest, l_theOther.m_bondAccruedInterest) != 0 ) { return false; } diff --git a/ref/client/OrderCancel.java b/ref/client/OrderCancel.java new file mode 100644 index 00000000..de2d94b5 --- /dev/null +++ b/ref/client/OrderCancel.java @@ -0,0 +1,60 @@ +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +public class OrderCancel { + final public static String EMPTY_STR = ""; + + private String m_manualOrderCancelTime; + private String m_extOperator; + private int m_manualOrderIndicator; + + // getters + public String manualOrderCancelTime() { return m_manualOrderCancelTime; } + public String extOperator() { return m_extOperator; } + public int manualOrderIndicator() { return m_manualOrderIndicator; } + + // setters + public void manualOrderCancelTime(String v) { m_manualOrderCancelTime = v; } + public void extOperator(String v) { m_extOperator = v; } + public void manualOrderIndicator(int v) { m_manualOrderIndicator = v; } + + public OrderCancel() { + this(EMPTY_STR); + } + + public OrderCancel(String manualOrderCancelTime) { + this(manualOrderCancelTime, EMPTY_STR, Integer.MAX_VALUE); + } + + public OrderCancel(String manualOrderCancelTime, String extOperator, int manualOrderIndicator) { + m_manualOrderCancelTime = manualOrderCancelTime; + m_extOperator = extOperator; + m_manualOrderIndicator = manualOrderIndicator; + } + + @Override + public boolean equals(Object p_other) { + if (this == p_other) { + return true; + } + if (!(p_other instanceof OrderCancel)) { + return false; + } + OrderCancel l_theOther = (OrderCancel)p_other; + + if (Util.StringCompare(m_manualOrderCancelTime, l_theOther.m_manualOrderCancelTime) != 0 || + Util.StringCompare(m_extOperator, l_theOther.m_extOperator) != 0 + ) { + return false; + } + + if (m_manualOrderIndicator != l_theOther.m_manualOrderIndicator + ) { + return false; + } + + return true; + } +} diff --git a/ref/client/Util.java b/ref/client/Util.java index 8bbf1ed8..8c85cc48 100644 --- a/ref/client/Util.java +++ b/ref/client/Util.java @@ -1,11 +1,10 @@ -/* Copyright (C) 2023 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; import static com.ib.controller.Formats.fmt; -import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; @@ -92,7 +91,7 @@ public static String DoubleMaxString(double value) { } public static String DoubleMaxString(double value, String defValue) { - return (value == Double.MAX_VALUE) ? defValue : new DecimalFormat("0.########").format(value); + return (value == Double.MAX_VALUE) ? defValue : String.valueOf(value); } public static String UnixMillisecondsToString(long milliseconds, String dateFormat){ diff --git a/ref/controller/ApiController.java b/ref/controller/ApiController.java index 63e5c28e..2e377316 100644 --- a/ref/controller/ApiController.java +++ b/ref/controller/ApiController.java @@ -416,14 +416,14 @@ private void internalReqContractDetails( Contract contract, final IInternalHandl m_orderHandlers.put(reqId, new IOrderHandler() { public void handle(int errorCode, String errorMsg) { processor.contractDetailsEnd();} @Override - public void orderState(OrderState orderState) { + public void orderState(OrderState orderState, Order order) { // TODO Auto-generated method stub } @Override public void orderStatus(OrderStatus status, Decimal filled, - Decimal remaining, double avgFillPrice, int permId, + Decimal remaining, double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice) { // TODO Auto-generated method stub @@ -830,8 +830,8 @@ public void updateGroups( List groups) { /** This interface is for receiving events for a specific order placed from the API. * Compare to ILiveOrderHandler. */ public interface IOrderHandler { - void orderState(OrderState orderState); - void orderStatus(OrderStatus status, Decimal filled, Decimal remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice); + void orderState(OrderState orderState, Order order); + void orderStatus(OrderStatus status, Decimal filled, Decimal remaining, double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice); void handle(int errorCode, String errorMsg); } @@ -847,16 +847,16 @@ public void placeOrModifyOrder(Contract contract, final Order order, final IOrde // when placing new order, assign new order id if (order.orderId() == 0) { order.orderId( m_orderId++); - if (handler != null) { - m_orderHandlers.put( order.orderId(), handler); - } + } + if (handler != null) { + m_orderHandlers.put( order.orderId(), handler); } m_client.placeOrder( contract, order); sendEOM(); } - public void cancelOrder(int orderId, String manualOrderCancelTime, final IOrderCancelHandler orderCancelHandler) { + public void cancelOrder(int orderId, OrderCancel orderCancel, final IOrderCancelHandler orderCancelHandler) { if (!checkConnection()) return; @@ -864,15 +864,15 @@ public void cancelOrder(int orderId, String manualOrderCancelTime, final IOrderC m_orderCancelHandlers.put( orderId, orderCancelHandler); } - m_client.cancelOrder( orderId, manualOrderCancelTime); + m_client.cancelOrder( orderId, orderCancel); sendEOM(); } - public void cancelAllOrders() { + public void cancelAllOrders(OrderCancel orderCancel) { if (!checkConnection()) return; - m_client.reqGlobalCancel(); + m_client.reqGlobalCancel(orderCancel); sendEOM(); } @@ -898,7 +898,7 @@ public void removeOrderCancelHandler( IOrderCancelHandler orderCancelHandler) { public interface ILiveOrderHandler { void openOrder(Contract contract, Order order, OrderState orderState); void openOrderEnd(); - void orderStatus(int orderId, OrderStatus status, Decimal filled, Decimal remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice); + void orderStatus(int orderId, OrderStatus status, Decimal filled, Decimal remaining, double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice); void handle(int orderId, int errorCode, String errorMsg); // add permId? } @@ -936,7 +936,7 @@ public void removeLiveOrderHandler(ILiveOrderHandler handler) { @Override public void openOrder(int orderId, Contract contract, Order order, OrderState orderState) { IOrderHandler handler = m_orderHandlers.get( orderId); if (handler != null) { - handler.orderState(orderState); + handler.orderState(orderState, order); } if (!order.whatIf() ) { @@ -954,7 +954,7 @@ public void removeLiveOrderHandler(ILiveOrderHandler handler) { recEOM(); } - @Override public void orderStatus(int orderId, String status, Decimal filled, Decimal remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice) { + @Override public void orderStatus(int orderId, String status, Decimal filled, Decimal remaining, double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice) { IOrderHandler handler = m_orderHandlers.get( orderId); if (handler != null) { handler.orderStatus( OrderStatus.valueOf( status), filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice); @@ -1927,8 +1927,8 @@ public void tickByTickMidPoint(int reqId, long time, double midPoint) { } @Override - public void orderBound(long orderId, int apiClientId, int apiOrderId) { - show( "Order bound. OrderId: " + orderId + ", apiClientId: " + apiClientId + ", apiOrderId: " + apiOrderId); + public void orderBound(long permId, int clientId, int orderId) { + show( "Order bound. PermId: " + permId + ", clientId: " + clientId + ", orderId: " + orderId); } // ---------------------------------------- Completed orders ---------------------------------------- diff --git a/src/api-next/api-next.ts b/src/api-next/api-next.ts index 309d2ce0..32b8ace7 100644 --- a/src/api-next/api-next.ts +++ b/src/api-next/api-next.ts @@ -23,6 +23,7 @@ import { OrderBook, OrderBookRow, OrderBookUpdate, + OrderCancel, OrderState, ScannerSubscription, SecType, @@ -2887,10 +2888,14 @@ export class IBApiNext { * Use [[cancelAllOrders]] instead. * * @param orderId Specify which order should be cancelled by its identifier. - * @param manualOrderCancelTime Specify the time the order should be cancelled. An empty string will cancel the order immediately. + * @param orderCancel Specify the time the order should be cancelled. An empty string will cancel the order immediately. */ - cancelOrder(orderId: number, manualOrderCancelTime?: string): void { - this.api.cancelOrder(orderId, manualOrderCancelTime); + cancelOrder(orderId: number, orderCancelParam?: string | OrderCancel): void { + let orderCancel: OrderCancel; + if (typeof orderCancelParam == "string") + orderCancel = { manualOrderCancelTime: orderCancelParam }; + else orderCancel = orderCancelParam; + this.api.cancelOrder(orderId, orderCancel); } /** diff --git a/src/api/api.ts b/src/api/api.ts index 64d0ccc5..4d35d08e 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -3,7 +3,13 @@ */ /* eslint @typescript-eslint/no-unsafe-declaration-merging:warn */ import { EventEmitter } from "eventemitter3"; -import { DurationUnit, MarketDataType, OrderStatus, WhatToShow } from ".."; +import { + DurationUnit, + MarketDataType, + OrderCancel, + OrderStatus, + WhatToShow, +} from ".."; import { ErrorCode } from "../common/errorCode"; import { Controller } from "../core/io/controller"; @@ -83,8 +89,7 @@ export interface IBApiCreationOptions { } /** Maximum supported version. */ -export const MAX_SUPPORTED_SERVER_VERSION = - MIN_SERVER_VER.PROFESSIONAL_CUSTOMER; +export const MAX_SUPPORTED_SERVER_VERSION = MIN_SERVER_VER.MAX_VERSION; /** Minimum supported version. */ export const MIN_SERVER_VER_SUPPORTED = 38; @@ -372,13 +377,13 @@ export class IBApi extends EventEmitter { * Use [[reqGlobalCancel]] instead. * * @param orderId Specify which order should be cancelled by its identifier. - * @param manualOrderCancelTime Specify the time the order should be cancelled. An empty string will cancel the order immediately. + * @param orderCancel Specify the time the order should be cancelled. An empty string will cancel the order immediately. * * @see [[placeOrder]], [[reqGlobalCancel]] */ - cancelOrder(orderId: number, manualOrderCancelTime?: string): IBApi { + cancelOrder(orderId: number, orderCancel?: OrderCancel): IBApi { this.controller.schedule(() => - this.controller.encoder.cancelOrder(orderId, manualOrderCancelTime), + this.controller.encoder.cancelOrder(orderId, orderCancel), ); return this; } @@ -2528,11 +2533,7 @@ export declare interface IBApi { */ on( event: EventName.orderBound, - listener: ( - orderId: number, - apiClientId: number, - apiOrderId: number, - ) => void, + listener: (permId: number, clientId: number, orderId: number) => void, ): this; /** diff --git a/src/api/contract/contractDetails.ts b/src/api/contract/contractDetails.ts index dd788a9f..8ab49cbe 100644 --- a/src/api/contract/contractDetails.ts +++ b/src/api/contract/contractDetails.ts @@ -2,6 +2,7 @@ import TagValue from "../data/container/tag-value"; import SecType from "../data/enum/sec-type"; import { Contract } from "./contract"; import { FundAssetType, FundDistributionPolicyIndicator } from "./fund"; +import { IneligibilityReason } from "./ineligibilityReason"; /** * Extended contract details. @@ -312,6 +313,7 @@ export interface ContractDetails { fundBlueSkyTerritories?: string; fundDistributionPolicyIndicator?: FundDistributionPolicyIndicator; fundAssetType?: FundAssetType; + ineligibilityReasonList?: Array; } export default ContractDetails; diff --git a/src/api/contract/ineligibilityReason.ts b/src/api/contract/ineligibilityReason.ts new file mode 100644 index 00000000..3d1c4c9c --- /dev/null +++ b/src/api/contract/ineligibilityReason.ts @@ -0,0 +1,7 @@ +/** + * Type describing ineligibility reasons + */ +export interface IneligibilityReason { + id: string; + description: string; +} diff --git a/src/api/data/enum/min-server-version.ts b/src/api/data/enum/min-server-version.ts index 1f546fa0..d22b4a77 100644 --- a/src/api/data/enum/min-server-version.ts +++ b/src/api/data/enum/min-server-version.ts @@ -131,6 +131,17 @@ export enum MIN_SERVER_VER { LAST_TRADE_DATE = 182, CUSTOMER_ACCOUNT = 183, PROFESSIONAL_CUSTOMER = 184, + BOND_ACCRUED_INTEREST = 185, + INELIGIBILITY_REASONS = 186, + RFQ_FIELDS = 187, + BOND_TRADING_HOURS = 188, + INCLUDE_OVERNIGHT = 189, + UNDO_RFQ_FIELDS = 190, + PERM_ID_AS_LONG = 191, + CME_TAGGING_FIELDS = 192, + CME_TAGGING_FIELDS_IN_OPEN_ORDER = 193, + + MAX_VERSION = CME_TAGGING_FIELDS_IN_OPEN_ORDER, } export default MIN_SERVER_VER; diff --git a/src/api/order/execution.ts b/src/api/order/execution.ts index dc405343..6ec1afa3 100644 --- a/src/api/order/execution.ts +++ b/src/api/order/execution.ts @@ -1,10 +1,4 @@ -/** - * Type describing the liquidity type of an execution - */ -export interface Liquidities { - /** The value of the liquidity type. */ - value: number; -} +import { Liquidities } from "../.."; /** * Type describing an order's execution. diff --git a/src/api/order/liquidities.ts b/src/api/order/liquidities.ts new file mode 100644 index 00000000..fa31c5fa --- /dev/null +++ b/src/api/order/liquidities.ts @@ -0,0 +1,9 @@ +/** + * Type describing the liquidity type of an execution + */ +export enum Liquidities { + None, + Added, + Removed, + RoudedOut, +} diff --git a/src/api/order/order.ts b/src/api/order/order.ts index b38566ed..55d93b5c 100644 --- a/src/api/order/order.ts +++ b/src/api/order/order.ts @@ -761,6 +761,10 @@ export interface Order { customerAccount?: string; professionalCustomer?: boolean; + + bondAccruedInterest?: string; + includeOvernight?: boolean; + manualOrderIndicator?: number; } export const COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID = Infinity; diff --git a/src/api/order/orderCancel.ts b/src/api/order/orderCancel.ts new file mode 100644 index 00000000..998be13f --- /dev/null +++ b/src/api/order/orderCancel.ts @@ -0,0 +1,8 @@ +/** + * Type describing the parameters of an order cancel + */ +export interface OrderCancel { + manualOrderCancelTime: string; + extOperator?: string; + manualOrderIndicator?: number; +} diff --git a/src/common/errorCode.ts b/src/common/errorCode.ts index 8e771a1f..88ae7956 100644 --- a/src/common/errorCode.ts +++ b/src/common/errorCode.ts @@ -4,6 +4,9 @@ /* eslint-disable @typescript-eslint/no-duplicate-enum-values */ export enum ErrorCode { + /** No request id associated to this error */ + NO_VALID_ID = -1, + /** Order Canceled - reason: */ ORDER_CANCELLED = 202, @@ -283,6 +286,9 @@ export enum ErrorCode { /** FA Profile is not supported anymore, use FA Group instead */ FA_PROFILE_NOT_SUPPORTED = 585, + /** Failed to read message because not connected */ + FAIL_READ_MESSAGE = 586, + /** Invalid position trade derived value */ INVALID_POSITION_TRADE_DERIVATED_VALUE = 2150, diff --git a/src/core/io/decoder.ts b/src/core/io/decoder.ts index 6c52e950..c87c3505 100644 --- a/src/core/io/decoder.ts +++ b/src/core/io/decoder.ts @@ -1,3 +1,4 @@ +import { IneligibilityReason } from "../.."; import { Contract } from "../../api/contract/contract"; import { ContractDescription } from "../../api/contract/contractDescription"; import { ContractDetails } from "../../api/contract/contractDetails"; @@ -466,6 +467,13 @@ export class Decoder { return parseInt(this.readStr(), 10) != 0; } + /** + * Read a token from queue and return it as boolean value. + * + * @deprecated readBool is probably what you are looking for + */ + readBoolFromInt = this.readBool; + /** * Read a token from queue and return it as floating point value. * @@ -474,7 +482,7 @@ export class Decoder { */ readDouble(): number | undefined { const token = this.readStr(); - if (!token || token === "") { + if (token === "") { return 0; } const val = parseFloat(token); @@ -488,7 +496,7 @@ export class Decoder { */ readDecimal(): number | undefined { const token = this.readStr(); - if (!token || token === "") { + if (token === "") { return undefined; } const val = parseFloat(token.replaceAll(",", "")); @@ -502,7 +510,7 @@ export class Decoder { */ readDoubleOrUndefined(): number | undefined { const token = this.readStr(); - if (!token) { + if (token === "") { return undefined; } const val = parseFloat(token); @@ -516,7 +524,7 @@ export class Decoder { */ readInt(): number { const token = this.readStr(); - if (!token || token === "") { + if (token === "") { return 0; } const val = parseInt(token, 10); @@ -538,7 +546,7 @@ export class Decoder { */ readIntOrUndefined(): number | undefined { const token = this.readStr(); - if (!token || token === "") { + if (token === "") { return undefined; } const val = parseInt(token, 10); @@ -827,6 +835,9 @@ export class Decoder { orderDecoder.readPegBestPegMidOrderAttributes(); orderDecoder.readCustomerAccount(); orderDecoder.readProfessionalCustomer(); + orderDecoder.readBondAccruedInterest(); + orderDecoder.readIncludeOvernight(); + orderDecoder.readCMETaggingFields(); this.emit(EventName.openOrder, order.orderId, contract, order, orderState); } @@ -1077,6 +1088,18 @@ export class Decoder { contract.fundAssetType = this.readStr() as FundAssetType; } + if (this.serverVersion >= MIN_SERVER_VER.INELIGIBILITY_REASONS) { + const ineligibilityReasonCount = this.readInt(); + const ineligibilityReasonList = new Array(); + + for (let i = 0; i < ineligibilityReasonCount; i++) { + const id = this.readStr(); + const description = this.readStr(); + ineligibilityReasonList.push({ id, description }); + } + contract.ineligibilityReasonList = ineligibilityReasonList; + } + this.emit(EventName.contractDetails, reqId, contract); } @@ -1163,7 +1186,7 @@ export class Decoder { } if (this.serverVersion >= MIN_SERVER_VER.LAST_LIQUIDITY) { - exec.lastLiquidity = { value: this.readInt() }; + exec.lastLiquidity = this.readInt(); } if (this.serverVersion >= MIN_SERVER_VER.PENDING_PRICE_REVISION) { @@ -1461,6 +1484,12 @@ export class Decoder { contract.longName = this.readStr(); } + if (this.serverVersion >= MIN_SERVER_VER.BOND_TRADING_HOURS) { + contract.timeZoneId = this.readStr(); + contract.tradingHours = this.readStr(); + contract.liquidHours = this.readStr(); + } + if (version >= 6) { contract.evRule = this.readStr(); contract.evMultiplier = this.readDouble(); @@ -2519,11 +2548,11 @@ export class Decoder { * Decode a ORDER_BOUND message from data queue and a emit orderBound event. */ private decodeMsg_ORDER_BOUND(): void { + const permId = this.readInt(); + const clientId = this.readDouble(); const orderId = this.readInt(); - const apiClientId = this.readDouble(); - const apiOrderId = this.readInt(); - this.emit(EventName.orderBound, orderId, apiClientId, apiOrderId); + this.emit(EventName.orderBound, permId, clientId, orderId); } /** @@ -2695,26 +2724,26 @@ export class Decoder { */ private readLastTradeDate(contract: ContractDetails, isBond: boolean): void { const lastTradeDateOrContractMonth = this.readStr(); - if (lastTradeDateOrContractMonth?.length) { - const tokens = + if (lastTradeDateOrContractMonth.length) { + const split = lastTradeDateOrContractMonth.indexOf("-") > 0 ? lastTradeDateOrContractMonth.split("-") : lastTradeDateOrContractMonth.split("\\s+"); - if (tokens.length > 0) { + if (split.length > 0) { if (isBond) { - contract.maturity = tokens[0]; + contract.maturity = split[0]; } else { - contract.contract.lastTradeDateOrContractMonth = tokens[0]; + contract.contract.lastTradeDateOrContractMonth = split[0]; } } - if (tokens.length > 1) { - contract.lastTradeTime = tokens[1]; + if (split.length > 1) { + contract.lastTradeTime = split[1]; } - if (isBond && tokens.length > 2) { - contract.timeZoneId = tokens[2]; + if (isBond && split.length > 2) { + contract.timeZoneId = split[2]; } } } @@ -3549,4 +3578,23 @@ class OrderDecoder { this.order.professionalCustomer = this.decoder.readBool(); } } + + readBondAccruedInterest() { + if (this.serverVersion >= MIN_SERVER_VER.BOND_ACCRUED_INTEREST) { + this.order.bondAccruedInterest = this.decoder.readStr(); + } + } + + readIncludeOvernight() { + if (this.serverVersion >= MIN_SERVER_VER.INCLUDE_OVERNIGHT) { + this.order.includeOvernight = this.decoder.readBool(); + } + } + + readCMETaggingFields() { + if (this.serverVersion >= MIN_SERVER_VER.CME_TAGGING_FIELDS_IN_OPEN_ORDER) { + this.order.extOperator = this.decoder.readStr(); + this.order.manualOrderIndicator = this.decoder.readIntOrUndefined(); + } + } } diff --git a/src/core/io/encoder.ts b/src/core/io/encoder.ts index a397f751..31c5d103 100644 --- a/src/core/io/encoder.ts +++ b/src/core/io/encoder.ts @@ -1,4 +1,4 @@ -import { MarketDataType, WhatToShow } from "../.."; +import { MarketDataType, OrderCancel, WhatToShow } from "../.."; import { ScanCode } from "../../api-next/market-scanner/market-scanner"; import { Contract } from "../../api/contract/contract"; import WshEventData from "../../api/contract/wsh"; @@ -120,7 +120,13 @@ export enum OUT_MSG_ID { } /** - * @@internal + * @internal + * Undefined integer value + */ +const Integer_MAX_VALUE = 2147483647; + +/** + * @internal * * Helper function to nullify a number of Number.MAX_VALUE * @@ -526,12 +532,10 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { /** * Encode a CANCEL_ORDER message to an array of tokens. */ - cancelOrder(orderId: number, manualCancelOrderTime?: string): void { - const version = 1; - + cancelOrder(orderId: number, orderCancel?: OrderCancel): void { if ( this.serverVersion < MIN_SERVER_VER.MANUAL_ORDER_TIME && - manualCancelOrderTime?.length + orderCancel?.manualOrderCancelTime.length ) { return this.emitError( "It does not support manual order cancel time attribute", @@ -540,10 +544,45 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { ); } - const tokens: unknown[] = [OUT_MSG_ID.CANCEL_ORDER, version, orderId]; + if (this.serverVersion < MIN_SERVER_VER.CME_TAGGING_FIELDS) { + if ( + (orderCancel?.extOperator && orderCancel?.extOperator != "") || + orderCancel?.manualOrderIndicator + ) { + return this.emitError( + "It does not support ext operator and manual order indicator parameters", + ErrorCode.UPDATE_TWS, + orderId, + ); + } + } + + const version = 1; + + // send cancel order msg + const tokens: unknown[] = [OUT_MSG_ID.CANCEL_ORDER]; + + if (this.serverVersion < MIN_SERVER_VER.CME_TAGGING_FIELDS) + tokens.push(version); + + tokens.push(orderId); if (this.serverVersion >= MIN_SERVER_VER.MANUAL_ORDER_TIME) - tokens.push(manualCancelOrderTime); + tokens.push(orderCancel?.manualOrderCancelTime); + + if ( + this.serverVersion >= MIN_SERVER_VER.RFQ_FIELDS && + this.serverVersion < MIN_SERVER_VER.UNDO_RFQ_FIELDS + ) { + tokens.push(""); + tokens.push(""); + tokens.push(Integer_MAX_VALUE); + } + + if (this.serverVersion >= MIN_SERVER_VER.CME_TAGGING_FIELDS) { + tokens.push(orderCancel.extOperator); + tokens.push(orderCancel.manualOrderIndicator); + } this.sendMsg(tokens); } @@ -1177,6 +1216,26 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { } } + if (this.serverVersion < MIN_SERVER_VER.INCLUDE_OVERNIGHT) { + if (order.includeOvernight) { + return this.emitError( + "It does not support include overnight parameter", + ErrorCode.UPDATE_TWS, + id, + ); + } + } + + if (this.serverVersion < MIN_SERVER_VER.CME_TAGGING_FIELDS) { + if (order.manualOrderIndicator) { + return this.emitError( + "It does not support manual order indicator parameter", + ErrorCode.UPDATE_TWS, + id, + ); + } + } + const version = this.serverVersion < MIN_SERVER_VER.NOT_HELD ? 27 : 45; // send place order msg @@ -1734,6 +1793,22 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { tokens.push(order.professionalCustomer); } + if ( + this.serverVersion >= MIN_SERVER_VER.RFQ_FIELDS && + this.serverVersion < MIN_SERVER_VER.UNDO_RFQ_FIELDS + ) { + tokens.push(""); + tokens.push(Integer_MAX_VALUE); + } + + if (this.serverVersion >= MIN_SERVER_VER.INCLUDE_OVERNIGHT) { + tokens.push(order.includeOvernight); + } + + if (this.serverVersion >= MIN_SERVER_VER.CME_TAGGING_FIELDS) { + tokens.push(order.manualOrderIndicator); + } + this.sendMsg(tokens); } @@ -2144,18 +2219,43 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { /** * Encode a REQ_GLOBAL_CANCEL message. */ - reqGlobalCancel(): void { + reqGlobalCancel(orderCancel?: OrderCancel): void { if (this.serverVersion < MIN_SERVER_VER.REQ_GLOBAL_CANCEL) { return this.emitError( "It does not support globalCancel requests.", ErrorCode.UPDATE_TWS, - -1, + ErrorCode.NO_VALID_ID, ); } + if (this.serverVersion < MIN_SERVER_VER.CME_TAGGING_FIELDS) { + if ( + (orderCancel?.extOperator && orderCancel?.extOperator != "") || + orderCancel?.manualOrderIndicator + ) { + return this.emitError( + "It does not support ext operator and manual order indicator parameters", + ErrorCode.UPDATE_TWS, + ErrorCode.NO_VALID_ID, + ); + } + } + const version = 1; - this.sendMsg(OUT_MSG_ID.REQ_GLOBAL_CANCEL, version); + // send request global cancel msg + const tokens: unknown[] = [OUT_MSG_ID.REQ_GLOBAL_CANCEL]; + + if (this.serverVersion < MIN_SERVER_VER.CME_TAGGING_FIELDS) { + tokens.push(version); + } + + if (this.serverVersion >= MIN_SERVER_VER.CME_TAGGING_FIELDS) { + tokens.push(orderCancel?.extOperator); + tokens.push(orderCancel?.manualOrderIndicator); + } + + this.sendMsg(tokens); } /** @@ -2423,7 +2523,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support marketDataType requests.", ErrorCode.UPDATE_TWS, - -1, + ErrorCode.NO_VALID_ID, ); } @@ -2685,7 +2785,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support position requests.", ErrorCode.UPDATE_TWS, - -1, + ErrorCode.NO_VALID_ID, ); } @@ -2816,7 +2916,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support API scanner subscription.", ErrorCode.UPDATE_TWS, - -1, + ErrorCode.NO_VALID_ID, ); } @@ -2913,7 +3013,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "FA Profile is not supported anymore, use FA Group instead.", ErrorCode.UPDATE_TWS, - -1, + ErrorCode.NO_VALID_ID, ); } @@ -3018,7 +3118,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support family codes request.", ErrorCode.UPDATE_TWS, - -1, + ErrorCode.NO_VALID_ID, ); } @@ -3048,7 +3148,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support market depth exchanges request.", ErrorCode.UPDATE_TWS, - -1, + ErrorCode.NO_VALID_ID, ); } @@ -3109,7 +3209,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support smart components request.", ErrorCode.UPDATE_TWS, - -1, + ErrorCode.NO_VALID_ID, ); } @@ -3234,7 +3334,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support completed orders requests.", ErrorCode.UPDATE_TWS, - -1, + ErrorCode.NO_VALID_ID, ); } @@ -3246,7 +3346,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support WSHE Calendar API.", ErrorCode.UPDATE_TWS, - -1, + reqId, ); } @@ -3258,7 +3358,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support WSHE Calendar API.", ErrorCode.UPDATE_TWS, - -1, + reqId, ); } @@ -3270,7 +3370,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support WSHE Calendar API.", ErrorCode.UPDATE_TWS, - -1, + reqId, ); } if ( @@ -3326,7 +3426,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support WSHE Calendar API.", ErrorCode.UPDATE_TWS, - -1, + reqId, ); } @@ -3338,7 +3438,7 @@ function tagValuesToTokens(tagValues: TagValue[]): unknown[] { return this.emitError( "It does not support user info requests.", ErrorCode.UPDATE_TWS, - -1, + reqId, ); } diff --git a/src/index.ts b/src/index.ts index 5507f298..b397a999 100644 --- a/src/index.ts +++ b/src/index.ts @@ -48,6 +48,7 @@ export { FOP } from "./api/contract/fop"; export { Forex } from "./api/contract/forex"; export { Future } from "./api/contract/future"; export { Index } from "./api/contract/ind"; +export { IneligibilityReason } from "./api/contract/ineligibilityReason"; export { Option } from "./api/contract/option"; export { Stock } from "./api/contract/stock"; export { WshEventData } from "./api/contract/wsh"; @@ -111,11 +112,13 @@ export { TriggerMethod } from "./api/order/enum/trigger-method"; // export order types -export { Execution, Liquidities } from "./api/order/execution"; +export { Execution } from "./api/order/execution"; export { LimitOrder } from "./api/order/limit"; +export { Liquidities } from "./api/order/liquidities"; export { MarketOrder } from "./api/order/market"; export { MarketCloseOrder } from "./api/order/marketClose"; export { Order } from "./api/order/order"; +export { OrderCancel } from "./api/order/orderCancel"; export { OrderComboLeg } from "./api/order/orderComboLeg"; export { OrderState } from "./api/order/orderState"; export { StopOrder } from "./api/order/stop"; diff --git a/src/tests/unit/api-next-live/subscription-registry.test.ts b/src/tests/unit/api-next-live/subscription-registry.test.ts index 5b0f2292..b60e3c65 100644 --- a/src/tests/unit/api-next-live/subscription-registry.test.ts +++ b/src/tests/unit/api-next-live/subscription-registry.test.ts @@ -44,7 +44,7 @@ describe("Subscription registry Tests", () => { it("Twice the same event callback bug", (done) => { // Two active subscriptions for the same Event issue #193 subscription$ = api.getOpenOrders().subscribe({ - next: (data) => { + next: (_data) => { // console.log(data); }, complete: () => { diff --git a/src/tests/unit/api-next/get-executed-trades.test.ts b/src/tests/unit/api-next/get-executed-trades.test.ts index 5182e0f6..2b3424be 100644 --- a/src/tests/unit/api-next/get-executed-trades.test.ts +++ b/src/tests/unit/api-next/get-executed-trades.test.ts @@ -1,4 +1,4 @@ -import IBApi, { ExecutionFilter, IBApiNext } from "../../.."; +import IBApi, { ExecutionFilter, IBApiNext, Liquidities } from "../../.."; import { ExecutionDetail } from "../../../api-next/order/execution-detail"; import { EventName } from "../../../api/data/enum/event-name"; import SecType from "../../../api/data/enum/sec-type"; @@ -42,9 +42,7 @@ describe("RxJS Wrapper: getExecutionDetails", () => { evRule: "", evMultiplier: 0, modelCode: "", - lastLiquidity: { - value: 2, - }, + lastLiquidity: Liquidities.Removed, }, }, ]; diff --git a/src/tests/unit/api/historical-data.test.ts b/src/tests/unit/api/historical-data.test.ts index b62cbb84..973ff486 100644 --- a/src/tests/unit/api/historical-data.test.ts +++ b/src/tests/unit/api/historical-data.test.ts @@ -113,7 +113,7 @@ describe("IBApi Historical data Tests", () => { ib.reqHistoricalData( refId, contract, - "20240719-17:00:00", + "20241110-17:00:00", "30 S", BarSizeSetting.SECONDS_FIFTEEN, WhatToShow.BID_ASK, @@ -134,7 +134,7 @@ describe("IBApi Historical data Tests", () => { count: number | undefined, WAP: number, ) => { - // console.log(counter, time, open, high, low, close, volume, count, WAP); + console.log(counter, time, open, high, low, close, volume, count, WAP); expect(reqId).toEqual(refId); if (time.startsWith("finished")) { expect(counter).toEqual(2); diff --git a/src/tests/unit/api/order/issue203.test.ts b/src/tests/unit/api/order/issue203.test.ts new file mode 100644 index 00000000..1b29acf8 --- /dev/null +++ b/src/tests/unit/api/order/issue203.test.ts @@ -0,0 +1,166 @@ +/** + * This file implement test code for the placeOrder function . + */ +import { + Contract, + ErrorCode, + EventName, + IBApi, + Order, + OrderAction, + OrderType, + SecType, +} from "../../../.."; +import configuration from "../../../../common/configuration"; +import logger from "../../../../common/logger"; +import { sample_future } from "../../sample-data/contracts"; + +describe("Issue #203", () => { + jest.setTimeout(20 * 1000); + + let ib: IBApi; + let clientId = Math.floor(Math.random() * 32766) + 1; // ensure unique client + + beforeEach(() => { + ib = new IBApi({ + host: configuration.ib_host, + port: configuration.ib_port, + clientId: clientId++, // increment clientId for each test so they don't interfere on each other + }); + }); + + afterEach(() => { + if (ib) { + ib.disconnect(); + ib = undefined; + } + }); + + test("mafianekcek", (done) => { + let refId: number; + + const refContract: Contract = sample_future; + // const refContract: Contract = sample_stock; + const refOrder: Order = { + action: OrderAction.BUY, + lmtPrice: 1, + totalQuantity: 1, + transmit: true, + orderType: OrderType.LMT, + account: "DU5784856", + tif: "DAY", + orderRef: "RS/3/9", + }; + + let isDone = false; + ib.once(EventName.nextValidId, (orderId: number) => { + refId = orderId; + ib.placeOrder(refId, refContract, refOrder); + }) + .on(EventName.openOrder, (orderId, contract, order, _orderState) => { + if (orderId == refId && !isDone) { + isDone = true; + expect(contract.symbol).toEqual(refContract.symbol); + expect(order.totalQuantity).toEqual(refOrder.totalQuantity); + done(); + } + }) + .on( + EventName.error, + ( + error: Error, + code: ErrorCode, + reqId: number, + _advancedOrderReject?: unknown, + ) => { + if (reqId === -1) { + logger.info(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else if (code == ErrorCode.NO_TRADING_PERMISSIONS) { + // Ignore this error for tests + logger.warn(msg); + done(); + } else { + ib.disconnect(); + done(msg); + } + } + }, + ); + + ib.connect().reqOpenOrders(); + }); + + test("fanazhe", (done) => { + let refId: number; + + const orderId = 2; + const refContract: Contract = { + symbol: "ES", + exchange: "CME", + currency: "USD", + lastTradeDateOrContractMonth: "20250620", + secType: SecType.FUT, + }; + const refOrder: Order = { + orderType: OrderType.LMT, + action: OrderAction.BUY, + lmtPrice: 5400, + orderId, + totalQuantity: 1, + transmit: true, + }; + + let isDone = false; + ib.once(EventName.nextValidId, (orderId: number) => { + console.log(orderId); + refId = orderId; + ib.placeOrder(refId, refContract, refOrder).reqOpenOrders(); + }) + .on(EventName.openOrder, (orderId, contract, order, _orderState) => { + console.log(orderId, contract, order, _orderState); + if (orderId == refId && !isDone) { + isDone = true; + expect(contract.symbol).toEqual(refContract.symbol); + expect(order.totalQuantity).toEqual(refOrder.totalQuantity); + done(); + } + }) + .on( + EventName.error, + ( + error: Error, + code: ErrorCode, + reqId: number, + _advancedOrderReject?: unknown, + ) => { + if (reqId === -1) { + logger.info(error.message); + } else { + const msg = `[${reqId}] ${error.message} (Error #${code})`; + if ( + error.message.includes("Warning:") || + error.message.includes("Order Message:") + ) { + logger.warn(msg); + } else if (code == ErrorCode.NO_TRADING_PERMISSIONS) { + // Ignore this error for tests + logger.warn(msg); + done(); + } else { + ib.disconnect(); + done(msg); + } + } + }, + ); + + ib.connect(); + }); +}); diff --git a/src/tests/unit/api/order/placeOrder.test.ts b/src/tests/unit/api/order/placeOrder.test.ts index 33d3b4a1..3b8e82fb 100644 --- a/src/tests/unit/api/order/placeOrder.test.ts +++ b/src/tests/unit/api/order/placeOrder.test.ts @@ -16,7 +16,6 @@ import logger from "../../../../common/logger"; import { sample_crypto, sample_etf, - sample_future, sample_option, sample_stock, } from "../../sample-data/contracts"; @@ -281,64 +280,4 @@ describe("Place Orders", () => { ib.connect().reqOpenOrders(); }); - - test("Issue #203", (done) => { - let refId: number; - - const refContract: Contract = sample_future; - const refOrder: Order = { - action: OrderAction.BUY, - lmtPrice: 1, - totalQuantity: 1, - transmit: true, - orderType: OrderType.LMT, - account: "DU5784856", - tif: "DAY", - orderRef: "RS/3/9", - }; - - let isDone = false; - ib.once(EventName.nextValidId, (orderId: number) => { - refId = orderId; - ib.placeOrder(refId, refContract, refOrder); - }) - .on(EventName.openOrder, (orderId, contract, order, _orderState) => { - if (orderId == refId && !isDone) { - isDone = true; - expect(contract.symbol).toEqual(refContract.symbol); - expect(order.totalQuantity).toEqual(refOrder.totalQuantity); - done(); - } - }) - .on( - EventName.error, - ( - error: Error, - code: ErrorCode, - reqId: number, - _advancedOrderReject?: unknown, - ) => { - if (reqId === -1) { - logger.info(error.message); - } else { - const msg = `[${reqId}] ${error.message} (Error #${code})`; - if ( - error.message.includes("Warning:") || - error.message.includes("Order Message:") - ) { - logger.warn(msg); - } else if (code == ErrorCode.NO_TRADING_PERMISSIONS) { - // Ignore this error for tests - logger.warn(msg); - done(); - } else { - ib.disconnect(); - done(msg); - } - } - }, - ); - - ib.connect().reqOpenOrders(); - }); }); diff --git a/src/tests/unit/api/positions.test.ts b/src/tests/unit/api/positions.test.ts index 65198fbf..476161be 100644 --- a/src/tests/unit/api/positions.test.ts +++ b/src/tests/unit/api/positions.test.ts @@ -26,8 +26,8 @@ describe("IBApi Tests", () => { } }); - async function delay(secs) { - const res = await new Promise((resolve, reject) => { + async function _delay(secs) { + const res = await new Promise((resolve, _reject) => { setTimeout(() => { return resolve(true); }, secs * 1_000); @@ -72,7 +72,7 @@ describe("IBApi Tests", () => { }) .on( EventName.positionMulti, - (reqId, account, modelCode, contract, pos, avgCost) => { + (reqId, account, modelCode, contract, _pos, _avgCost) => { // console.log( // "positionMulti", // reqId, diff --git a/yarn.lock b/yarn.lock index 8a4cd4f7..d08049cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -437,17 +437,17 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== +"@eslint/js@8.57.1": + version "8.57.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" + integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== +"@humanwhocodes/config-array@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" + integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== dependencies: - "@humanwhocodes/object-schema" "^2.0.2" + "@humanwhocodes/object-schema" "^2.0.3" debug "^4.3.1" minimatch "^3.0.5" @@ -456,10 +456,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" - integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== +"@humanwhocodes/object-schema@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" @@ -734,13 +734,48 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@shikijs/core@1.10.3": - version "1.10.3" - resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-1.10.3.tgz#f01763b36f08ad3d2ef46cea7e61858d9d9947d6" - integrity sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg== +"@shikijs/core@1.22.2": + version "1.22.2" + resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-1.22.2.tgz#9c22bd4cc8a4d6c062461cfd35e1faa6c617ca25" + integrity sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg== + dependencies: + "@shikijs/engine-javascript" "1.22.2" + "@shikijs/engine-oniguruma" "1.22.2" + "@shikijs/types" "1.22.2" + "@shikijs/vscode-textmate" "^9.3.0" + "@types/hast" "^3.0.4" + hast-util-to-html "^9.0.3" + +"@shikijs/engine-javascript@1.22.2": + version "1.22.2" + resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz#62e90dbd2ed1d78b972ad7d0a1f8ffaaf5e43279" + integrity sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw== + dependencies: + "@shikijs/types" "1.22.2" + "@shikijs/vscode-textmate" "^9.3.0" + oniguruma-to-js "0.4.3" + +"@shikijs/engine-oniguruma@1.22.2": + version "1.22.2" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz#b12a44e3faf486e19fbcf8952f4b56b9b9b8d9b8" + integrity sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA== + dependencies: + "@shikijs/types" "1.22.2" + "@shikijs/vscode-textmate" "^9.3.0" + +"@shikijs/types@1.22.2": + version "1.22.2" + resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.22.2.tgz#695a283f19963fe0638fc2646862ba5cfc4623a8" + integrity sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg== dependencies: + "@shikijs/vscode-textmate" "^9.3.0" "@types/hast" "^3.0.4" +"@shikijs/vscode-textmate@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz#b2f1776e488c1d6c2b6cd129bab62f71bbc9c7ab" + integrity sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA== + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -800,7 +835,7 @@ dependencies: "@types/node" "*" -"@types/hast@^3.0.4": +"@types/hast@^3.0.0", "@types/hast@^3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== @@ -826,10 +861,10 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^29.5.12": - version "29.5.12" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" - integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== +"@types/jest@^29.5.14": + version "29.5.14" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.14.tgz#2b910912fa1d6856cadcd0c1f95af7df1d6049e5" + integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ== dependencies: expect "^29.0.0" pretty-format "^29.0.0" @@ -839,15 +874,22 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== +"@types/mdast@^4.0.0": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" + integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA== + dependencies: + "@types/unist" "*" + "@types/node@*": version "18.16.19" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.19.tgz#cb03fca8910fdeb7595b755126a8a78144714eea" integrity sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA== -"@types/node@^18.19.41": - version "18.19.41" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.41.tgz#27695cf2cac63f22c202b9217c0bcf3fb192a2f0" - integrity sha512-LX84pRJ+evD2e2nrgYCHObGWkiQJ1mL+meAgbvnwk/US6vmMY7S2ygBTGV2Jw91s9vUsLSXeDEkUHZIJGLrhsg== +"@types/node@^18.19.64": + version "18.19.64" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.64.tgz#122897fb79f2a9ec9c979bded01c11461b2b1478" + integrity sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ== dependencies: undici-types "~5.26.4" @@ -873,6 +915,11 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.2.tgz#6dd61e43ef60b34086287f83683a5c1b2dc53d20" integrity sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ== +"@types/unist@^3.0.0": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c" + integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -885,16 +932,16 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^7.16.1": - version "7.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz#f5f5da52db674b1f2cdb9d5f3644e5b2ec750465" - integrity sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A== +"@typescript-eslint/eslint-plugin@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz#b16d3cf3ee76bf572fdf511e79c248bdec619ea3" + integrity sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.16.1" - "@typescript-eslint/type-utils" "7.16.1" - "@typescript-eslint/utils" "7.16.1" - "@typescript-eslint/visitor-keys" "7.16.1" + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/type-utils" "7.18.0" + "@typescript-eslint/utils" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" graphemer "^1.4.0" ignore "^5.3.1" natural-compare "^1.4.0" @@ -907,15 +954,15 @@ dependencies: "@typescript-eslint/utils" "5.62.0" -"@typescript-eslint/parser@^7.16.1": - version "7.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.16.1.tgz#84c581cf86c8b2becd48d33ddc41a6303d57b274" - integrity sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA== +"@typescript-eslint/parser@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.18.0.tgz#83928d0f1b7f4afa974098c64b5ce6f9051f96a0" + integrity sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg== dependencies: - "@typescript-eslint/scope-manager" "7.16.1" - "@typescript-eslint/types" "7.16.1" - "@typescript-eslint/typescript-estree" "7.16.1" - "@typescript-eslint/visitor-keys" "7.16.1" + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/typescript-estree" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" debug "^4.3.4" "@typescript-eslint/scope-manager@5.62.0": @@ -926,29 +973,29 @@ "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/scope-manager@7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz#6927d6451537ce648c6af67a2327378d4cc18462" - integrity sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng== +"@typescript-eslint/scope-manager@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz#c928e7a9fc2c0b3ed92ab3112c614d6bd9951c83" + integrity sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA== dependencies: - "@typescript-eslint/types" "7.13.0" - "@typescript-eslint/visitor-keys" "7.13.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" -"@typescript-eslint/scope-manager@7.16.1": - version "7.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz#2b43041caabf8ddd74512b8b550b9fc53ca3afa1" - integrity sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw== +"@typescript-eslint/scope-manager@8.13.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz#2f4aed0b87d72360e64e4ea194b1fde14a59082e" + integrity sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA== dependencies: - "@typescript-eslint/types" "7.16.1" - "@typescript-eslint/visitor-keys" "7.16.1" + "@typescript-eslint/types" "8.13.0" + "@typescript-eslint/visitor-keys" "8.13.0" -"@typescript-eslint/type-utils@7.16.1": - version "7.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz#4d7ae4f3d9e3c8cbdabae91609b1a431de6aa6ca" - integrity sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA== +"@typescript-eslint/type-utils@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz#2165ffaee00b1fbbdd2d40aa85232dab6998f53b" + integrity sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA== dependencies: - "@typescript-eslint/typescript-estree" "7.16.1" - "@typescript-eslint/utils" "7.16.1" + "@typescript-eslint/typescript-estree" "7.18.0" + "@typescript-eslint/utils" "7.18.0" debug "^4.3.4" ts-api-utils "^1.3.0" @@ -957,15 +1004,15 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/types@7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.13.0.tgz#0cca95edf1f1fdb0cfe1bb875e121b49617477c5" - integrity sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA== +"@typescript-eslint/types@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.18.0.tgz#b90a57ccdea71797ffffa0321e744f379ec838c9" + integrity sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ== -"@typescript-eslint/types@7.16.1": - version "7.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.16.1.tgz#bbab066276d18e398bc64067b23f1ce84dfc6d8c" - integrity sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ== +"@typescript-eslint/types@8.13.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.13.0.tgz#3f35dead2b2491a04339370dcbcd17bbdfc204d8" + integrity sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng== "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" @@ -980,13 +1027,13 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz#4cc24fc155088ebf3b3adbad62c7e60f72c6de1c" - integrity sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw== +"@typescript-eslint/typescript-estree@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz#b5868d486c51ce8f312309ba79bdb9f331b37931" + integrity sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA== dependencies: - "@typescript-eslint/types" "7.13.0" - "@typescript-eslint/visitor-keys" "7.13.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -994,15 +1041,15 @@ semver "^7.6.0" ts-api-utils "^1.3.0" -"@typescript-eslint/typescript-estree@7.16.1": - version "7.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz#9b145ba4fd1dde1986697e1ce57dc501a1736dd3" - integrity sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ== +"@typescript-eslint/typescript-estree@8.13.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz#db8c93dd5437ca3ce417a255fb35ddc3c12c3e95" + integrity sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g== dependencies: - "@typescript-eslint/types" "7.16.1" - "@typescript-eslint/visitor-keys" "7.16.1" + "@typescript-eslint/types" "8.13.0" + "@typescript-eslint/visitor-keys" "8.13.0" debug "^4.3.4" - globby "^11.1.0" + fast-glob "^3.3.2" is-glob "^4.0.3" minimatch "^9.0.4" semver "^7.6.0" @@ -1022,25 +1069,25 @@ eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/utils@7.16.1": - version "7.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.16.1.tgz#df42dc8ca5a4603016fd102db0346cdab415cdb7" - integrity sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA== +"@typescript-eslint/utils@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.18.0.tgz#bca01cde77f95fc6a8d5b0dbcbfb3d6ca4be451f" + integrity sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.16.1" - "@typescript-eslint/types" "7.16.1" - "@typescript-eslint/typescript-estree" "7.16.1" + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/typescript-estree" "7.18.0" -"@typescript-eslint/utils@^6.0.0 || ^7.0.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.13.0.tgz#f84e7e8aeceae945a9a3f40d077fd95915308004" - integrity sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ== +"@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.13.0.tgz#f6d40e8b5053dcaeabbd2e26463857abf27d62c0" + integrity sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.13.0" - "@typescript-eslint/types" "7.13.0" - "@typescript-eslint/typescript-estree" "7.13.0" + "@typescript-eslint/scope-manager" "8.13.0" + "@typescript-eslint/types" "8.13.0" + "@typescript-eslint/typescript-estree" "8.13.0" "@typescript-eslint/visitor-keys@5.62.0": version "5.62.0" @@ -1050,23 +1097,23 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@typescript-eslint/visitor-keys@7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz#2eb7ce8eb38c2b0d4a494d1fe1908e7071a1a353" - integrity sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw== +"@typescript-eslint/visitor-keys@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz#0564629b6124d67607378d0f0332a0495b25e7d7" + integrity sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg== dependencies: - "@typescript-eslint/types" "7.13.0" + "@typescript-eslint/types" "7.18.0" eslint-visitor-keys "^3.4.3" -"@typescript-eslint/visitor-keys@7.16.1": - version "7.16.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz#4287bcf44c34df811ff3bb4d269be6cfc7d8c74b" - integrity sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg== +"@typescript-eslint/visitor-keys@8.13.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz#e97b0d92b266ef38a1faf40a74da289b66683a5b" + integrity sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw== dependencies: - "@typescript-eslint/types" "7.16.1" + "@typescript-eslint/types" "8.13.0" eslint-visitor-keys "^3.4.3" -"@ungap/structured-clone@^1.2.0": +"@ungap/structured-clone@^1.0.0", "@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== @@ -1268,7 +1315,7 @@ browserslist@^4.21.9: node-releases "^2.0.13" update-browserslist-db "^1.0.11" -bs-logger@0.x: +bs-logger@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== @@ -1317,6 +1364,11 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== +ccount@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" + integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== + chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1339,6 +1391,16 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +character-entities-html4@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" + integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA== + +character-entities-legacy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" + integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== + ci-info@^3.2.0: version "3.8.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" @@ -1397,6 +1459,11 @@ colors@^1.4.0: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +comma-separated-tokens@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" + integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== + command-buffer@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/command-buffer/-/command-buffer-0.1.0.tgz#ced3f40f77289314db91cb77ef3b00c332e8e268" @@ -1480,11 +1547,23 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== +dequal@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +devlop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018" + integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== + dependencies: + dequal "^2.0.0" + diff-sequences@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" @@ -1572,12 +1651,12 @@ eslint-etc@^5.1.0: tsutils "^3.17.1" tsutils-etc "^1.4.1" -eslint-plugin-jest@^28.6.0: - version "28.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.6.0.tgz#8410588d60bcafa68a91b6ec272e4a415502302a" - integrity sha512-YG28E1/MIKwnz+e2H7VwYPzHUYU4aMa19w0yGcwXnnmJH6EfgHahTJ2un3IyraUxNfnz/KUhJAFXNNwWPo12tg== +eslint-plugin-jest@^28.9.0: + version "28.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.9.0.tgz#19168dfaed124339cd2252c4c4d1ac3688aeb243" + integrity sha512-rLu1s1Wf96TgUUxSw6loVIkNtUjq1Re7A9QdCCHSohnvXEBAjuL420h0T/fMmkQlNsQP2GhQzEUpYHPfxBkvYQ== dependencies: - "@typescript-eslint/utils" "^6.0.0 || ^7.0.0" + "@typescript-eslint/utils" "^6.0.0 || ^7.0.0 || ^8.0.0" eslint-plugin-rxjs@^5.0.3: version "5.0.3" @@ -1615,16 +1694,16 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.57.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== +eslint@^8.57.1: + version "8.57.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" + integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" + "@eslint/js" "8.57.1" + "@humanwhocodes/config-array" "^0.13.0" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" "@ungap/structured-clone" "^1.2.0" @@ -1765,6 +1844,17 @@ fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" +fast-glob@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -1974,11 +2064,40 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hast-util-to-html@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz#a9999a0ba6b4919576a9105129fead85d37f302b" + integrity sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + ccount "^2.0.0" + comma-separated-tokens "^2.0.0" + hast-util-whitespace "^3.0.0" + html-void-elements "^3.0.0" + mdast-util-to-hast "^13.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + stringify-entities "^4.0.0" + zwitch "^2.0.4" + +hast-util-whitespace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621" + integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw== + dependencies: + "@types/hast" "^3.0.0" + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== +html-void-elements@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" + integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg== + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -2671,7 +2790,7 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.memoize@4.x: +lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== @@ -2707,7 +2826,7 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" -make-error@1.x: +make-error@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -2731,6 +2850,21 @@ markdown-it@^14.1.0: punycode.js "^2.3.1" uc.micro "^2.1.0" +mdast-util-to-hast@^13.0.0: + version "13.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz#5ca58e5b921cc0a3ded1bc02eed79a4fe4fe41f4" + integrity sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + "@ungap/structured-clone" "^1.0.0" + devlop "^1.0.0" + micromark-util-sanitize-uri "^2.0.0" + trim-lines "^3.0.0" + unist-util-position "^5.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" + mdurl@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" @@ -2746,6 +2880,38 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +micromark-util-character@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.0.tgz#31320ace16b4644316f6bf057531689c71e2aee1" + integrity sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ== + dependencies: + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-util-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz#0921ac7953dc3f1fd281e3d1932decfdb9382ab1" + integrity sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA== + +micromark-util-sanitize-uri@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz#ec8fbf0258e9e6d8f13d9e4770f9be64342673de" + integrity sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw== + dependencies: + micromark-util-character "^2.0.0" + micromark-util-encode "^2.0.0" + micromark-util-symbol "^2.0.0" + +micromark-util-symbol@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz#12225c8f95edf8b17254e47080ce0862d5db8044" + integrity sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw== + +micromark-util-types@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.0.tgz#63b4b7ffeb35d3ecf50d1ca20e68fc7caa36d95e" + integrity sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w== + micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" @@ -2838,6 +3004,13 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +oniguruma-to-js@0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz#8d899714c21f5c7d59a3c0008ca50e848086d740" + integrity sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ== + dependencies: + regex "^4.3.2" + optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -2983,6 +3156,11 @@ prompts@^2.0.1, prompts@~2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" +property-information@^6.0.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" + integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== + punycode.js@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" @@ -3008,6 +3186,11 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +regex@^4.3.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/regex/-/regex-4.4.0.tgz#cb731e2819f230fad69089e1bd854fef7569e90a" + integrity sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -3115,6 +3298,11 @@ semver@^7.6.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== +semver@^7.6.3: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -3127,12 +3315,16 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shiki@^1.9.1: - version "1.10.3" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-1.10.3.tgz#2276fb21a07043b28c5b16001e6a04fef99dbb8f" - integrity sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ== +shiki@^1.16.2: + version "1.22.2" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-1.22.2.tgz#ed109a3d0850504ad5a1edf8496470a2121c5b7b" + integrity sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA== dependencies: - "@shikijs/core" "1.10.3" + "@shikijs/core" "1.22.2" + "@shikijs/engine-javascript" "1.22.2" + "@shikijs/engine-oniguruma" "1.22.2" + "@shikijs/types" "1.22.2" + "@shikijs/vscode-textmate" "^9.3.0" "@types/hast" "^3.0.4" signal-exit@^3.0.3, signal-exit@^3.0.7: @@ -3163,6 +3355,11 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +space-separated-tokens@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" + integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -3192,6 +3389,14 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +stringify-entities@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3" + integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg== + dependencies: + character-entities-html4 "^2.0.0" + character-entities-legacy "^3.0.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -3271,25 +3476,30 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +trim-lines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" + integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== + ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== -ts-jest@^29.2.3: - version "29.2.3" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.3.tgz#3d226ac36b8b820151a38f164414f9f6b412131f" - integrity sha512-yCcfVdiBFngVz9/keHin9EnsrQtQtEu3nRykNy9RVp+FiPFFbPJ3Sg6Qg4+TkmH0vMP5qsTKgXSsk80HRwvdgQ== +ts-jest@^29.2.5: + version "29.2.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.5.tgz#591a3c108e1f5ebd013d3152142cb5472b399d63" + integrity sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA== dependencies: - bs-logger "0.x" + bs-logger "^0.2.6" ejs "^3.1.10" - fast-json-stable-stringify "2.x" + fast-json-stable-stringify "^2.1.0" jest-util "^29.0.0" json5 "^2.2.3" - lodash.memoize "4.x" - make-error "1.x" - semver "^7.5.3" - yargs-parser "^21.0.1" + lodash.memoize "^4.1.2" + make-error "^1.3.6" + semver "^7.6.3" + yargs-parser "^21.1.1" tslib@^1.8.1: version "1.14.1" @@ -3338,21 +3548,21 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -typedoc@^0.26.4: - version "0.26.4" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.26.4.tgz#7e83047369a29a710d429dac20996680cae9a314" - integrity sha512-FlW6HpvULDKgc3rK04V+nbFyXogPV88hurarDPOjuuB5HAwuAlrCMQ5NeH7Zt68a/ikOKu6Z/0hFXAeC9xPccQ== +typedoc@^0.26.11: + version "0.26.11" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.26.11.tgz#124b43a5637b7f3237b8c721691b44738c5c9dc9" + integrity sha512-sFEgRRtrcDl2FxVP58Ze++ZK2UQAEvtvvH8rRlig1Ja3o7dDaMHmaBfvJmdGnNEFaLTpQsN8dpvZaTqJSu/Ugw== dependencies: lunr "^2.3.9" markdown-it "^14.1.0" minimatch "^9.0.5" - shiki "^1.9.1" - yaml "^2.4.5" + shiki "^1.16.2" + yaml "^2.5.1" -typescript@^5.5.3: - version "5.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.3.tgz#e1b0a3c394190838a0b168e771b0ad56a0af0faa" - integrity sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ== +typescript@^5.6.3: + version "5.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== uc.micro@^2.0.0, uc.micro@^2.1.0: version "2.1.0" @@ -3364,6 +3574,44 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +unist-util-is@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424" + integrity sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-position@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4" + integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-stringify-position@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2" + integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-visit-parents@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815" + integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + +unist-util-visit@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6" + integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" + update-browserslist-db@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" @@ -3393,6 +3641,22 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" +vfile-message@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.2.tgz#c883c9f677c72c166362fd635f21fc165a7d1181" + integrity sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw== + dependencies: + "@types/unist" "^3.0.0" + unist-util-stringify-position "^4.0.0" + +vfile@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.3.tgz#3652ab1c496531852bf55a6bac57af981ebc38ab" + integrity sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q== + dependencies: + "@types/unist" "^3.0.0" + vfile-message "^4.0.0" + walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -3449,12 +3713,12 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^2.4.5: - version "2.4.5" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e" - integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg== +yaml@^2.5.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.0.tgz#14059ad9d0b1680d0f04d3a60fe00f3a857303c3" + integrity sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ== -yargs-parser@^21.0.1, yargs-parser@^21.1.1: +yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== @@ -3476,3 +3740,8 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zwitch@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" + integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== From 54df66f6ad4b160731693b0d61e1f9debfa1b09d Mon Sep 17 00:00:00 2001 From: Ronan-Yann Lorin Date: Fri, 8 Nov 2024 18:07:24 +0100 Subject: [PATCH 2/2] Some tests improved --- src/api/order/order.ts | 2 ++ src/tests/unit/api/historical-data.test.ts | 14 +++++----- .../api/order/placeConditionalOrder.test.ts | 27 +++++++++++++++++-- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/api/order/order.ts b/src/api/order/order.ts index 55d93b5c..6dc71520 100644 --- a/src/api/order/order.ts +++ b/src/api/order/order.ts @@ -763,7 +763,9 @@ export interface Order { professionalCustomer?: boolean; bondAccruedInterest?: string; + includeOvernight?: boolean; + manualOrderIndicator?: number; } diff --git a/src/tests/unit/api/historical-data.test.ts b/src/tests/unit/api/historical-data.test.ts index 973ff486..f284ebb4 100644 --- a/src/tests/unit/api/historical-data.test.ts +++ b/src/tests/unit/api/historical-data.test.ts @@ -113,7 +113,7 @@ describe("IBApi Historical data Tests", () => { ib.reqHistoricalData( refId, contract, - "20241110-17:00:00", + "20241107-17:00:00", "30 S", BarSizeSetting.SECONDS_FIFTEEN, WhatToShow.BID_ASK, @@ -134,17 +134,17 @@ describe("IBApi Historical data Tests", () => { count: number | undefined, WAP: number, ) => { - console.log(counter, time, open, high, low, close, volume, count, WAP); + // console.log(counter, time, open, high, low, close, volume, count, WAP); expect(reqId).toEqual(refId); if (time.startsWith("finished")) { expect(counter).toEqual(2); done(); } else if (counter++ == 1) { - expect(time).toEqual("1721408385"); - expect(open).toEqual(11.95); - expect(high).toEqual(11.95); - expect(low).toEqual(11.9); - expect(close).toEqual(11.95); + expect(time).toEqual("1730998785"); + expect(open).toEqual(8.77); + expect(high).toEqual(8.77); + expect(low).toEqual(8.75); + expect(close).toEqual(8.77); expect(volume).toEqual(-1); expect(count).toEqual(-1); expect(WAP).toEqual(-1); diff --git a/src/tests/unit/api/order/placeConditionalOrder.test.ts b/src/tests/unit/api/order/placeConditionalOrder.test.ts index 2c56f05f..3d41eec6 100644 --- a/src/tests/unit/api/order/placeConditionalOrder.test.ts +++ b/src/tests/unit/api/order/placeConditionalOrder.test.ts @@ -51,7 +51,7 @@ const sample_percent_condition: OrderCondition = new PercentChangeCondition( ConjunctionConnection.OR, ); const sample_time_condition: OrderCondition = new TimeCondition( - "20250102-17:00:00", + "20260102-18:00:00", true, ConjunctionConnection.OR, ); @@ -342,8 +342,31 @@ describe("Place Conditional Orders", () => { }) .on(EventName.openOrderEnd, () => { if (isDone) done(); - else done("failed"); }) + .on( + EventName.orderStatus, + ( + orderId, + status, + filled, + remaining, + _avgFillPrice, + _permId, + _parentId, + _lastFillPrice, + _clientId, + _whyHeld, + _mktCapPrice, + ) => { + if (!isDone && orderId == refId) { + isDone = true; + expect(status).toMatch(/Pending/); + expect(filled).toEqual(0); + expect(remaining).toEqual(refOrder.totalQuantity); + done(); + } + }, + ) .on( EventName.error, (