Repository: ccxt/ccxt
Pull request: ContractUnavailable error type
fixes: #10256

- add `ContractUnavailable` error type which extends `InvalidOrder`
- export error type `NoChange` from errors
- change error type to `ContractUnavailable` for okx errors with codes `51030` (Funding fee is being settled), 51021, 51022, 51027, 51028, and 51029

Problem statement:
[okex] incorrect error mapping
`BadSymbol: okex5 {"code":"1","data":[{"clOrdId":"ddd","ordId":"","sCode":"51030","sMsg":"Funding fee is being settled.","tag":""}],"msg":""}`

When placing a futures order during the settlement period I see the following error.  I don't think BadSymbol is quite right, though I'm sure sure exactly what the error should be.  Perhaps a subclass of OnMaintennance?

Hints from issue discussion:
@npomfret this is probably a new class of exceptions under InvalidOrder, because it's not really a maintenance thing, it's a settlement thing, we will think of how to handle it better or what would be a better exception type for it. Your suggestions are welcome:

- https://github.com/ccxt/ccxt/blob/master/js/base/errorHierarchy.js
@kroitor @frosty00  I'm thinking either `OnMaintenance`, `InvalidOrder`, `OrderNotFillable`, `BadResponse` or `ExchangeError`

Commit message: add ContractSettled error

Patch to review:
diff --git a/ts/src/base/errorHierarchy.ts b/ts/src/base/errorHierarchy.ts
index 23356c4624727..7d2f2e55a874f 100644
--- a/ts/src/base/errorHierarchy.ts
+++ b/ts/src/base/errorHierarchy.ts
@@ -26,6 +26,7 @@ const errorHierarchy = {
                 'OrderImmediatelyFillable': {},
                 'OrderNotFillable': {},
                 'DuplicateOrderId': {},
+                'ContractSettled': {},
             },
             'NotSupported': {},
         },
diff --git a/ts/src/base/errors.ts b/ts/src/base/errors.ts
index 9fbd3be1fcc6b..107ce25a32256 100644
--- a/ts/src/base/errors.ts
+++ b/ts/src/base/errors.ts
@@ -149,6 +149,12 @@ class InvalidOrder extends ExchangeError {
         this.name = 'InvalidOrder';
     }
 }
+class ContractSettled extends InvalidOrder {
+    constructor (message) {
+        super (message);
+        this.name = 'InvalidOrder';
+    }
+}
 class OrderNotFound extends InvalidOrder {
     constructor (message) {
         super (message);
@@ -241,8 +247,8 @@ class RequestTimeout extends NetworkError {
 //     // Derived class hierarchy
 //     errorHierarchy
 // )
-const errors = { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending };
+const errors = { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractSettled };
 
-export { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending };
+export { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractSettled };
 
 export default errors;
diff --git a/ts/src/okx.ts b/ts/src/okx.ts
index 670e025274a33..be7fa450807ae 100644
--- a/ts/src/okx.ts
+++ b/ts/src/okx.ts
@@ -2,7 +2,7 @@
 //  ---------------------------------------------------------------------------
 
 import Exchange from './abstract/okx.js';
-import { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, InsufficientFunds, InvalidNonce, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, BadSymbol, RateLimitExceeded, NetworkError, CancelPending, NotSupported, AccountNotEnabled } from './base/errors.js';
+import { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, InsufficientFunds, InvalidNonce, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, BadSymbol, RateLimitExceeded, NetworkError, CancelPending, NotSupported, AccountNotEnabled, ContractSettled } from './base/errors.js';
 import { Precise } from './base/Precise.js';
 import { TICK_SIZE } from './base/functions/number.js';
 import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
@@ -553,7 +553,7 @@ export default class okx extends Exchange {
                     '51027': BadSymbol, // Contract expired
                     '51028': BadSymbol, // Contract under delivery
                     '51029': BadSymbol, // Contract is being settled
-                    '51030': BadSymbol, // Funding fee is being settled
+                    '51030': ContractSettled, // Funding fee is being settled
                     '51046': InvalidOrder, // The take profit trigger price must be higher than the order price
                     '51047': InvalidOrder, // The stop loss trigger price must be lower than the order price
                     '51031': InvalidOrder, // This order price is not within the closing price range


Code review comments:
diff_hunk: @@ -553,7 +553,7 @@ export default class okx extends Exchange {
                     '51027': BadSymbol, // Contract expired
                     '51028': BadSymbol, // Contract under delivery
                     '51029': BadSymbol, // Contract is being settled
-                    '51030': BadSymbol, // Funding fee is being settled
+                    '51030': ContractSettled, // Funding fee is being settled
path: ts/src/okx.ts
text: @user1:
Can you point me to this error in the docs? Second, aren't the errors above related ?

@author:
> Can you point me to this error in the docs? 

I can't provide a direct link, but all the errors are visible under https://www.okx.com/docs-v5/en/#error-code-rest-api-public and you can just cmd/cntl + f for 51030

> aren't the errors above related ?

Yes they would be, I didn't notice those ones

@author:
Maybe a different name would work better, so that it can include these as well

                    '51021': BadSymbol, // Contract to be listed
                    '51022': BadSymbol, // Contract suspended
                    '51027': BadSymbol, // Contract expired
                    '51028': BadSymbol, // Contract under delivery
                    '51029': BadSymbol, // Contract is being settled
                    '51030': ContractSettled, // Funding fee is being settled


@user1:
> Maybe a different name would work better, so that it can include these as well

@author yeah maybe, do you have any suggestions for the name?

@author:
I cannot think of one