Repository navigation
Expand file tree
/
Copy patherrors.js
More file actions
158 lines (147 loc) · 4.83 KB
/
Copy patherrors.js
File metadata and controls
158 lines (147 loc) · 4.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
const HORIZON_TIMEOUT_MESSAGE =
"The Stellar Horizon node did not respond in time.";
const HORIZON_TIMEOUT_SUGGESTION =
"Try again in a few seconds. If the issue persists check the Stellar network status at https://status.stellar.org.";
/**
* Returns true when an error indicates Horizon did not respond before the timeout.
*
* @param {Error} err
* @returns {boolean}
*/
function isHorizonTimeoutError(err) {
if (!err) return false;
if (err.isHorizonTimeout) return true;
// Horizon HTTP errors include response.data and are not timeouts
if (err.response && err.response.data) return false;
const code = err.code || (err.cause && err.cause.code);
if (code === "ECONNABORTED" || code === "ETIMEDOUT") return true;
if (err.name === "AbortError") return true;
const msg = (err.message || "").toLowerCase();
return msg.includes("timeout") || msg.includes("timed out");
}
/**
* Creates a structured HorizonTimeout error for slow or unresponsive Horizon nodes.
*
* @returns {Error}
*/
function makeHorizonTimeoutError() {
const err = new Error(HORIZON_TIMEOUT_MESSAGE);
err.isHorizonTimeout = true;
err.status = 504;
return err;
}
/**
* Creates a structured AccountNotFound error for Horizon 404 responses.
*
* @param {string} accountId - Stellar public key that was not found
* @param {string} network - Network name ("testnet" or "mainnet")
* @returns {Error}
*/
function makeAccountNotFoundError(accountId, network) {
const err = new Error(
`Account ${accountId} was not found on the Stellar ${network} network.`
);
err.isAccountNotFound = true;
err.accountId = accountId;
err.network = network;
err.status = 404;
return err;
}
function makeAssetNotFoundError(code, issuer, network) {
const err = new Error(
`Asset ${code}:${issuer} was not found on the Stellar ${network} network.`
);
err.isAssetNotFound = true;
err.assetCode = code;
err.assetIssuer = issuer;
err.network = network;
err.status = 404;
return err;
}
/**
* Creates a structured TrustlineNotFound error for when a specific asset
* trustline does not exist on the given account.
*
* @param {string} address - Stellar account public key
* @param {string} code - Asset code (e.g. "USDC")
* @param {string} issuer - Asset issuer public key
* @returns {Error}
*/
function makeTrustlineNotFoundError(address, code, issuer) {
const err = new Error(
`Account '${address}' does not hold a trustline for ${code}:${issuer}.`
);
err.isTrustlineNotFound = true;
err.address = address;
err.assetCode = code;
err.assetIssuer = issuer;
err.status = 404;
return err;
}
/**
* Creates a structured TomlFetchFailed error for when an issuer's
* stellar.toml file cannot be fetched — due to a network error, a
* missing file, or invalid TOML content.
*
* @param {string} issuer - Stellar public key of the asset issuer
* @returns {Error}
*/
function makeTomlFetchFailedError(issuer) {
const err = new Error(
`Could not fetch stellar.toml for issuer '${issuer}'.`
);
err.isTomlFetchFailed = true;
err.issuer = issuer;
err.status = 502;
return err;
}
/**
* Builds the structured OrderBookEmpty error body returned by the DEX and
* asset-price routes when Horizon reports no active order book for a pair.
*
* Unlike the other factories in this module this returns a plain object, not
* an Error: the DEX routes embed it directly as the `error` field of a 404
* response rather than passing it to the error handler.
*
* @param {string} sellAssetCode - Code of the asset being sold (base).
* @param {string} buyAssetCode - Code of the asset being bought (counter).
* @returns {{ type: string, message: string, suggestion: string }}
*/
function makeOrderBookEmptyError(sellAssetCode, buyAssetCode) {
return {
type: "OrderBookEmpty",
message: `No active order book found for ${sellAssetCode}/${buyAssetCode}.`,
suggestion:
"This pair has no active offers on the Stellar DEX. Check the asset codes and issuers, or try a more liquid pair such as XLM/USDC.",
};
}
/**
* Creates a structured LiquidityPoolNotFound error for Horizon 404 responses
* on liquidity pool lookups.
*
* @param {string} poolId - The liquidity pool ID that was not found
* @param {string} network - Network name ("testnet" or "mainnet")
* @returns {Error}
*/
function makeLiquidityPoolNotFoundError(poolId, network) {
const err = new Error(
`Liquidity pool ${poolId} was not found on the Stellar ${network} network.`
);
err.isLiquidityPoolNotFound = true;
err.poolId = poolId;
err.network = network;
err.status = 404;
return err;
}
module.exports = {
HORIZON_TIMEOUT_MESSAGE,
HORIZON_TIMEOUT_SUGGESTION,
isHorizonTimeoutError,
makeHorizonTimeoutError,
makeAccountNotFoundError,
makeAssetNotFoundError,
makeTrustlineNotFoundError,
makeTomlFetchFailedError,
makeOrderBookEmptyError,
makeLiquidityPoolNotFoundError,
};