InteropError with a kind. Branch on the class, the kind or
the hub’s code, never on a message.
The error classes
All entry points share one copy of these classes, so
instanceof works whichever entry point
threw. isAbortError(error) is also true for a platform AbortError.
HubError
Two getters sort the codes that are not about the request:
isCredentialRefused: the gateway refused your credential (401:EPX0001a missing or malformed key,EPX0002an unknown, revoked or expired one,EPX0008orEPX0009a malformed or unknown project id), or a page’s origin that is not on the project’s list (403,EPX0010). An operator matter: retrying cannot fix it, and refused credentials count toward the gateway’s lockout of the caller’s IP (EPX0081).isClientBug: a framework code that means the request itself was malformed (CLIENT_BUG_CODES).
What to tell the user
adviseError(error) sorts any error the SDK throws into an action, who it is for, and a default
message:
audience is operator for the codes that describe your key, your project, your origins or your
client: the user only needs to hear that the service is unavailable. DEFAULT_ERROR_MESSAGES holds
the default English copy.
Pass the route when you know it: adviseError(error, { route: "orderOpenFor" }) reads availability
answers and a HubUnavailableError as resubmit, because on a submission they say nothing about
whether the order exists.
Retrying
What the SDK already does
- Timeouts. Every transport waits a little longer than the gateway, so the gateway’s own answer
ends a slow call:
hubTransportandprojectTransportwait 25 s on quotes, 12 s on reads and 15 s on submissions;proxyTransportwaits 30 s, 15 s and 35 s, longer than your proxy. - Submissions. When an order submission’s answer is lost (a timeout, a dropped connection, the
gateway’s
EPX0050–EPX0053), the SDK looks the order up by its derived hub order id, then re-posts the same body once. See Lost answers. - Tracking. Status polls ride out availability and busy answers, waiting at least
retryAfterMs. - Quotes.
executeQuotere-quotes when too little time is left to sign. See How long a quote lives. - Catalog. When the hub cannot be reached, the last good copy is used.
Your rules
retryableistrue: back off and retry. On a rate limit (EIN0080, the gateway’s429), waitretryAfterMsfirst.isCredentialRefusedistrue: stop, and alert your operators. Check the key or project id, and the project’s origin list, in the hub dashboard. Don’t retry meanwhile: 20 refused credentials within a minute lock the caller’s IP out of every call for the rest of that minute (EPX0081).- A terminal code (
0001–0049): never retry unchanged. Fix the input, or quote again. - Once the user has sent a transaction for a quote (the
wrap-nativeandswap-tokenlanes), never quote again or ask them to sign again for it: the deposit is on chain. Follow the order instead, withclient.findOrderByTx(sourceChain, transactionHash)if you lost its id. - A
HubUnavailableErroron a POST may have been accepted. For quotes, just ask again. For submissions, the SDK’s recovery has already run: anOutcomeUnknownErrormeans follow the order. - Your own abort: do not retry.
In the browser
Through your proxy, the browser gets:HubErrorfor the hub’s refusals about the request, relayed unchanged, and for the gateway’s rate limits and outages (429,5xx), with their status andRetry-After;ProxyErrorfor everything about your key or your proxy: the proxy never relays a refused key. It reports it to you (onError) and answersPXY0503, as it does for history while its subject canary fails; a client bug or another refusal about the integration isPXY0500;HubUnavailableErrorwhen the proxy cannot be reached, and aProxyErrorPXY0502when the proxy cannot reach the hub.
HubErrors with an EPX
code and a real status: EPX0010 (403), for one, means the page’s origin is not on your project’s
list. GET /orders, the one route not open to a project id, never gets that far: projectTransport
refuses it before calling, with an InteropError (invalid-input).