@xoxno/sdk-js 1.0.228 → 1.0.230
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/sdk/stellar/contracts.d.ts +2 -2
- package/dist/cjs/sdk/stellar/index.d.ts +1 -0
- package/dist/cjs/sdk/stellar/lending.d.ts +34 -0
- package/dist/cjs/sdk/stellar/scval-encode.d.ts +1 -1
- package/dist/cjs/utils/soroban-errors.d.ts +18 -1
- package/dist/esm/sdk/stellar/contracts.js +1 -1
- package/dist/esm/sdk/stellar/events/decode.js +7 -2
- package/dist/esm/sdk/stellar/lending.js +45 -0
- package/dist/esm/sdk/stellar/route-verify.js +6 -3
- package/dist/esm/sdk/stellar/scval-encode.js +4 -2
- package/dist/esm/utils/soroban-errors.js +412 -19
- package/dist/index.cjs +1 -1
- package/dist/sdk/stellar/contracts.d.ts +2 -2
- package/dist/sdk/stellar/index.cjs +1 -1
- package/dist/sdk/stellar/index.d.ts +1 -0
- package/dist/sdk/stellar/index.esm.js +1 -1
- package/dist/sdk/stellar/lending.d.ts +34 -0
- package/dist/sdk/stellar/scval-encode.d.ts +1 -1
- package/dist/sdk/stellar/swap-index.cjs +1 -1
- package/dist/sdk/stellar/swap-index.esm.js +1 -1
- package/dist/utils/soroban-errors.d.ts +18 -1
- package/package.json +2 -2
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* rs-lending-xlm Soroban contract error codes → human-readable messages.
|
|
3
|
-
* Mirrors `common/src/errors.rs` (`GenericError`,
|
|
4
|
-
* `
|
|
3
|
+
* Mirrors every enum in `common/src/errors.rs` (`GenericError`,
|
|
4
|
+
* `CollateralError`, `OracleError`, `SpokeError`, `FlashLoanError`,
|
|
5
|
+
* `StrategyError`). Reserved codes stay listed so numbers are never reused.
|
|
6
|
+
* Keep in sync when that file changes.
|
|
7
|
+
*
|
|
8
|
+
* Codes are scoped per contract: the swap aggregator, XOXNO oracle and DeFindex
|
|
9
|
+
* adapter declare their own enums, so the same number can mean something else
|
|
10
|
+
* there. Pass `contracts` to map only errors emitted by the lending contracts.
|
|
5
11
|
*/ const SOROBAN_ERROR_CATALOG = {
|
|
6
12
|
// GenericError
|
|
7
13
|
1: {
|
|
@@ -16,10 +22,22 @@
|
|
|
16
22
|
name: 'InvalidTicker',
|
|
17
23
|
message: 'Invalid asset ticker.'
|
|
18
24
|
},
|
|
25
|
+
5: {
|
|
26
|
+
name: 'PoolAlreadyDeployed',
|
|
27
|
+
message: 'Singleton pool, controller, or price aggregator already recorded.'
|
|
28
|
+
},
|
|
19
29
|
6: {
|
|
20
30
|
name: 'InvalidAsset',
|
|
21
31
|
message: 'Invalid asset address.'
|
|
22
32
|
},
|
|
33
|
+
7: {
|
|
34
|
+
name: 'AssetsAreTheSame',
|
|
35
|
+
message: 'Same market or token where distinct HubAssetKeys or underlying assets, respectively, are required.'
|
|
36
|
+
},
|
|
37
|
+
8: {
|
|
38
|
+
name: 'WrongToken',
|
|
39
|
+
message: 'Params.asset_id differs from the market\'s asset.'
|
|
40
|
+
},
|
|
23
41
|
10: {
|
|
24
42
|
name: 'InvalidWasmHash',
|
|
25
43
|
message: 'The WASM hash is empty or invalid.'
|
|
@@ -32,22 +50,78 @@
|
|
|
32
50
|
name: 'PairNotActive',
|
|
33
51
|
message: 'No oracle is configured for this asset.'
|
|
34
52
|
},
|
|
53
|
+
13: {
|
|
54
|
+
name: 'AccountNotInMarket',
|
|
55
|
+
message: 'Caller lacks the account\'s position NFT, or the account has no metadata.'
|
|
56
|
+
},
|
|
35
57
|
14: {
|
|
36
58
|
name: 'AmountMustBePositive',
|
|
37
59
|
message: 'The amount must be greater than zero.'
|
|
38
60
|
},
|
|
61
|
+
16: {
|
|
62
|
+
name: 'InvalidPayments',
|
|
63
|
+
message: 'Payments or route list empty when required, non-empty when forbidden, or over the view limit.'
|
|
64
|
+
},
|
|
65
|
+
18: {
|
|
66
|
+
name: 'NotSmartContract',
|
|
67
|
+
message: 'Address is not a deployed contract.'
|
|
68
|
+
},
|
|
69
|
+
24: {
|
|
70
|
+
name: 'AccountNotFound',
|
|
71
|
+
message: 'Account id has no state, or its NFT owner is unresolvable.'
|
|
72
|
+
},
|
|
73
|
+
25: {
|
|
74
|
+
name: 'AccountModeMismatch',
|
|
75
|
+
message: 'Account mode differs from the call\'s required mode.'
|
|
76
|
+
},
|
|
77
|
+
27: {
|
|
78
|
+
name: 'AggregatorNotSet',
|
|
79
|
+
message: 'Swap or price aggregator not configured.'
|
|
80
|
+
},
|
|
81
|
+
29: {
|
|
82
|
+
name: 'PositionLimitsNotSet',
|
|
83
|
+
message: 'No position limits stored.'
|
|
84
|
+
},
|
|
85
|
+
30: {
|
|
86
|
+
name: 'PoolNotInitialized',
|
|
87
|
+
message: 'Pool or controller unset, or market params/state missing.'
|
|
88
|
+
},
|
|
39
89
|
32: {
|
|
40
90
|
name: 'OwnerNotSet',
|
|
41
91
|
message: 'The contract owner has not been set.'
|
|
42
92
|
},
|
|
93
|
+
33: {
|
|
94
|
+
name: 'MathOverflow',
|
|
95
|
+
message: 'Checked arithmetic overflow or failed narrowing conversion.'
|
|
96
|
+
},
|
|
97
|
+
34: {
|
|
98
|
+
name: 'InternalError',
|
|
99
|
+
message: 'Internal invariant failed. Report it.'
|
|
100
|
+
},
|
|
101
|
+
36: {
|
|
102
|
+
name: 'InvalidPositionLimits',
|
|
103
|
+
message: 'Supply or borrow limit is zero or above POSITION_LIMIT_MAX (5).'
|
|
104
|
+
},
|
|
105
|
+
38: {
|
|
106
|
+
name: 'SpotOnlyNotProductionSafe',
|
|
107
|
+
message: 'Every oracle source reads an unsmoothed spot market.'
|
|
108
|
+
},
|
|
43
109
|
39: {
|
|
44
110
|
name: 'InvalidTimelockDelay',
|
|
45
111
|
message: 'The timelock delay is out of the allowed range.'
|
|
46
112
|
},
|
|
113
|
+
40: {
|
|
114
|
+
name: 'TimelockOperationExpired',
|
|
115
|
+
message: 'Scheduled operation\'s grace period elapsed.'
|
|
116
|
+
},
|
|
47
117
|
41: {
|
|
48
118
|
name: 'InvalidRole',
|
|
49
119
|
message: 'The caller does not hold the required role.'
|
|
50
120
|
},
|
|
121
|
+
42: {
|
|
122
|
+
name: 'BlendPoolNotApproved',
|
|
123
|
+
message: 'Blend pool not approved.'
|
|
124
|
+
},
|
|
51
125
|
43: {
|
|
52
126
|
name: 'HubNotActive',
|
|
53
127
|
message: 'This hub is not active.'
|
|
@@ -56,15 +130,99 @@
|
|
|
56
130
|
name: 'NotAuthorized',
|
|
57
131
|
message: 'The caller is not authorized to perform this action.'
|
|
58
132
|
},
|
|
133
|
+
45: {
|
|
134
|
+
name: 'RegistryCapReached',
|
|
135
|
+
message: 'Account already has MAX_DELEGATES (16).'
|
|
136
|
+
},
|
|
59
137
|
46: {
|
|
60
138
|
name: 'OperationNotCancellable',
|
|
61
139
|
message: 'This governance operation cannot be cancelled.'
|
|
62
140
|
},
|
|
141
|
+
47: {
|
|
142
|
+
name: 'BorrowRoundsToZeroShares',
|
|
143
|
+
message: 'Positive borrow mints zero scaled debt shares.'
|
|
144
|
+
},
|
|
145
|
+
48: {
|
|
146
|
+
name: 'CannotRemoveLastProposer',
|
|
147
|
+
message: 'Revoke would leave no proposer.'
|
|
148
|
+
},
|
|
149
|
+
49: {
|
|
150
|
+
name: 'WithdrawRoundsToZeroShares',
|
|
151
|
+
message: 'Positive withdrawal burns zero scaled supply shares.'
|
|
152
|
+
},
|
|
153
|
+
50: {
|
|
154
|
+
name: 'NetSettleRoundsToZeroShares',
|
|
155
|
+
message: 'Positive net settlement burns zero shares.'
|
|
156
|
+
},
|
|
157
|
+
51: {
|
|
158
|
+
name: 'SupplyRoundsToZeroShares',
|
|
159
|
+
message: 'Positive supply mints zero scaled shares.'
|
|
160
|
+
},
|
|
161
|
+
52: {
|
|
162
|
+
name: 'RepayRoundsToZeroShares',
|
|
163
|
+
message: 'Positive net repayment burns zero scaled debt shares.'
|
|
164
|
+
},
|
|
165
|
+
53: {
|
|
166
|
+
name: 'PositionNftNotSet',
|
|
167
|
+
message: 'NFT address unset on a path needing it, such as account creation. Ownership lookup can return #24 instead.'
|
|
168
|
+
},
|
|
169
|
+
54: {
|
|
170
|
+
name: 'PositionNftAlreadyDeployed',
|
|
171
|
+
message: 'Position-NFT address already recorded.'
|
|
172
|
+
},
|
|
173
|
+
55: {
|
|
174
|
+
name: 'DivisionByZero',
|
|
175
|
+
message: 'Fixed-point multiply-divide with zero denominator.'
|
|
176
|
+
},
|
|
63
177
|
// CollateralError
|
|
178
|
+
100: {
|
|
179
|
+
name: 'InsufficientCollateral',
|
|
180
|
+
message: 'Post-operation LTV-weighted collateral below total debt, or health factor below 1 WAD.'
|
|
181
|
+
},
|
|
182
|
+
101: {
|
|
183
|
+
name: 'HealthFactorTooHigh',
|
|
184
|
+
message: 'Target has no debt or health factor >= 1 WAD; not liquidatable.'
|
|
185
|
+
},
|
|
186
|
+
102: {
|
|
187
|
+
name: 'HealthFactorTooLow',
|
|
188
|
+
message: 'Update_account_threshold with has_risks = true ends below 1.05 WAD. A gated liquidation-tuple refresh skips a tuple that fails its hypothetical health-factor check.'
|
|
189
|
+
},
|
|
190
|
+
104: {
|
|
191
|
+
name: 'NotCollateral',
|
|
192
|
+
message: 'Spoke listing disallows the asset as collateral.'
|
|
193
|
+
},
|
|
194
|
+
107: {
|
|
195
|
+
name: 'AssetNotBorrowable',
|
|
196
|
+
message: 'Spoke listing disallows borrowing the asset.'
|
|
197
|
+
},
|
|
198
|
+
109: {
|
|
199
|
+
name: 'PositionLimitExceeded',
|
|
200
|
+
message: 'New slot exceeds the position limit, or a sub-3-decimal supply leg would coexist with another supply slot.'
|
|
201
|
+
},
|
|
202
|
+
110: {
|
|
203
|
+
name: 'PositionNotFound',
|
|
204
|
+
message: 'Reserved code; no longer emitted.'
|
|
205
|
+
},
|
|
206
|
+
111: {
|
|
207
|
+
name: 'InvalidPositionMode',
|
|
208
|
+
message: 'Mode is not Multiply, Long, or Short.'
|
|
209
|
+
},
|
|
210
|
+
112: {
|
|
211
|
+
name: 'InsufficientLiquidity',
|
|
212
|
+
message: 'Market cash below the draw, or the draw breaks the liquidation buffer.'
|
|
213
|
+
},
|
|
64
214
|
113: {
|
|
65
215
|
name: 'InvalidLiqThreshold',
|
|
66
216
|
message: 'LTV, liquidation threshold, or bonus is out of bounds.'
|
|
67
217
|
},
|
|
218
|
+
114: {
|
|
219
|
+
name: 'CannotCleanBadDebt',
|
|
220
|
+
message: 'Account fails the bad-debt gate.'
|
|
221
|
+
},
|
|
222
|
+
115: {
|
|
223
|
+
name: 'WithdrawLessThanFee',
|
|
224
|
+
message: 'Liquidation protocol fee exceeds the gross withdrawal.'
|
|
225
|
+
},
|
|
68
226
|
116: {
|
|
69
227
|
name: 'InvalidBorrowParams',
|
|
70
228
|
message: 'Supply or borrow cap configuration is invalid.'
|
|
@@ -73,10 +231,179 @@
|
|
|
73
231
|
name: 'InvalidUtilRange',
|
|
74
232
|
message: 'Interest-rate utilization breakpoints are invalid.'
|
|
75
233
|
},
|
|
234
|
+
118: {
|
|
235
|
+
name: 'OptUtilTooHigh',
|
|
236
|
+
message: 'Optimal utilization >= 100%.'
|
|
237
|
+
},
|
|
238
|
+
119: {
|
|
239
|
+
name: 'InvalidReserveFactor',
|
|
240
|
+
message: 'Reserve factor >= 100%.'
|
|
241
|
+
},
|
|
242
|
+
120: {
|
|
243
|
+
name: 'DebtPositionNotFound',
|
|
244
|
+
message: 'No debt position for that hub asset.'
|
|
245
|
+
},
|
|
246
|
+
121: {
|
|
247
|
+
name: 'CollateralPositionNotFound',
|
|
248
|
+
message: 'No supply position for that hub asset.'
|
|
249
|
+
},
|
|
250
|
+
122: {
|
|
251
|
+
name: 'CannotCloseWithRemainingDebt',
|
|
252
|
+
message: 'Close_position with borrow positions open.'
|
|
253
|
+
},
|
|
254
|
+
123: {
|
|
255
|
+
name: 'PoolInsolvent',
|
|
256
|
+
message: 'Supplier claims exceed cash plus debt, or zero supply with debt outstanding.'
|
|
257
|
+
},
|
|
258
|
+
126: {
|
|
259
|
+
name: 'MinBorrowCollateralNotMet',
|
|
260
|
+
message: 'With debt outstanding, LTV-weighted collateral below the USD floor, or a sub-3-decimal supply leg under 2 raw units after floor conversion.'
|
|
261
|
+
},
|
|
262
|
+
127: {
|
|
263
|
+
name: 'UtilizationAboveMax',
|
|
264
|
+
message: 'Post-operation utilization above max_utilization.'
|
|
265
|
+
},
|
|
266
|
+
128: {
|
|
267
|
+
name: 'BaseRateNegative',
|
|
268
|
+
message: 'Negative base borrow rate.'
|
|
269
|
+
},
|
|
270
|
+
129: {
|
|
271
|
+
name: 'SlopeNonMonotonic',
|
|
272
|
+
message: 'Rate slopes do not increase monotonically.'
|
|
273
|
+
},
|
|
274
|
+
130: {
|
|
275
|
+
name: 'MaxRateBelowBase',
|
|
276
|
+
message: 'Max borrow rate not strictly above base.'
|
|
277
|
+
},
|
|
278
|
+
131: {
|
|
279
|
+
name: 'MaxBorrowRateTooHigh',
|
|
280
|
+
message: 'Max borrow rate exceeds MAX_BORROW_RATE_RAY (200% APR).'
|
|
281
|
+
},
|
|
76
282
|
132: {
|
|
77
283
|
name: 'AssetDecimalsTooHigh',
|
|
78
284
|
message: 'Asset decimals exceed the protocol maximum (27).'
|
|
79
285
|
},
|
|
286
|
+
133: {
|
|
287
|
+
name: 'SelfLiquidationNotAllowed',
|
|
288
|
+
message: 'SeizeMode::Credit(id) receiver is the liquidated account. Owners may still liquidate their own account.'
|
|
289
|
+
},
|
|
290
|
+
134: {
|
|
291
|
+
name: 'InvalidLiquidationCurve',
|
|
292
|
+
message: 'Curve bounds fail validation.'
|
|
293
|
+
},
|
|
294
|
+
135: {
|
|
295
|
+
name: 'FullCloseRequired',
|
|
296
|
+
message: 'Retired; no error site.'
|
|
297
|
+
},
|
|
298
|
+
// OracleError
|
|
299
|
+
201: {
|
|
300
|
+
name: 'InvalidAggregator',
|
|
301
|
+
message: 'Proposed aggregator is not a deployed contract.'
|
|
302
|
+
},
|
|
303
|
+
204: {
|
|
304
|
+
name: 'InvalidOracleTokenType',
|
|
305
|
+
message: 'Reflector asset given as string; only address or symbol accepted.'
|
|
306
|
+
},
|
|
307
|
+
205: {
|
|
308
|
+
name: 'UnsafePriceNotAllowed',
|
|
309
|
+
message: 'Two legs disagree beyond tolerance, or only one produced a reading.'
|
|
310
|
+
},
|
|
311
|
+
206: {
|
|
312
|
+
name: 'PriceFeedStale',
|
|
313
|
+
message: 'Observation exceeds its staleness budget. Timestamps over 60 s ahead are dropped; the error then depends on remaining sources.'
|
|
314
|
+
},
|
|
315
|
+
208: {
|
|
316
|
+
name: 'BadLastTolerance',
|
|
317
|
+
message: 'Upper ratio outside 10150..12500 (excess over BPS outside 150..2500 bps), or lower ratio is not the required rounded reciprocal.'
|
|
318
|
+
},
|
|
319
|
+
210: {
|
|
320
|
+
name: 'NoLastPrice',
|
|
321
|
+
message: 'No readable source, or an Aquarius LP read failed (for example, reserves or shares).'
|
|
322
|
+
},
|
|
323
|
+
211: {
|
|
324
|
+
name: 'NoAccumulator',
|
|
325
|
+
message: 'Controller has no revenue accumulator.'
|
|
326
|
+
},
|
|
327
|
+
212: {
|
|
328
|
+
name: 'ReflectorHistoryEmpty',
|
|
329
|
+
message: 'Reflector returns no price history.'
|
|
330
|
+
},
|
|
331
|
+
216: {
|
|
332
|
+
name: 'OracleNotConfigured',
|
|
333
|
+
message: 'No oracle for the price key, or the response omits a requested asset.'
|
|
334
|
+
},
|
|
335
|
+
217: {
|
|
336
|
+
name: 'InvalidPrice',
|
|
337
|
+
message: 'Price <= 0, or LP fair-value math non-representable.'
|
|
338
|
+
},
|
|
339
|
+
218: {
|
|
340
|
+
name: 'InvalidStalenessConfig',
|
|
341
|
+
message: 'Max_stale_seconds out of range or below the source\'s guaranteed freshness.'
|
|
342
|
+
},
|
|
343
|
+
219: {
|
|
344
|
+
name: 'TwapInsufficientObservations',
|
|
345
|
+
message: 'Record count zero or below the smoothing minimum, or history too short, too long, or denser than feed resolution.'
|
|
346
|
+
},
|
|
347
|
+
220: {
|
|
348
|
+
name: 'InvalidOracleBase',
|
|
349
|
+
message: 'The oracle quote asset/market is missing or invalid.'
|
|
350
|
+
},
|
|
351
|
+
221: {
|
|
352
|
+
name: 'InvalidOracleDecimals',
|
|
353
|
+
message: 'The oracle decimals value is invalid.'
|
|
354
|
+
},
|
|
355
|
+
222: {
|
|
356
|
+
name: 'InvalidOracleResolution',
|
|
357
|
+
message: 'Reflector resolution below minimum, above max_stale_seconds, or implying a TWAP span above it.'
|
|
358
|
+
},
|
|
359
|
+
223: {
|
|
360
|
+
name: 'SanityBoundViolated',
|
|
361
|
+
message: 'Price outside the stored sanity band.'
|
|
362
|
+
},
|
|
363
|
+
224: {
|
|
364
|
+
name: 'InvalidSanityBounds',
|
|
365
|
+
message: 'Oracle sanity bounds are invalid (require 0 < min < max).'
|
|
366
|
+
},
|
|
367
|
+
225: {
|
|
368
|
+
name: 'OracleCycleDetected',
|
|
369
|
+
message: 'A cycle was detected in the oracle quote chain.'
|
|
370
|
+
},
|
|
371
|
+
226: {
|
|
372
|
+
name: 'SanityBandTooWideForSingleSource',
|
|
373
|
+
message: 'Band exceeds the tighter limit for single-source, LP, or dual-source oracles with identical provider trust sets.'
|
|
374
|
+
},
|
|
375
|
+
227: {
|
|
376
|
+
name: 'SanityBandMustTighten',
|
|
377
|
+
message: 'Set_sanity_band would widen the band. Widen via timelocked ConfigureAssetOracle.'
|
|
378
|
+
},
|
|
379
|
+
228: {
|
|
380
|
+
name: 'TwapRecordsOutOfRange',
|
|
381
|
+
message: 'Record count above MAX_TWAP_RECORDS (12).'
|
|
382
|
+
},
|
|
383
|
+
229: {
|
|
384
|
+
name: 'OracleDepthExceeded',
|
|
385
|
+
message: 'Composition nests deeper than MAX_RESOLUTION_DEPTH (3).'
|
|
386
|
+
},
|
|
387
|
+
230: {
|
|
388
|
+
name: 'FactorOutOfBounds',
|
|
389
|
+
message: 'Scaled source\'s factor price outside its min/max.'
|
|
390
|
+
},
|
|
391
|
+
231: {
|
|
392
|
+
name: 'SourceCountOutOfRange',
|
|
393
|
+
message: 'Zero or over two sources, or Aquarius LP combined with another source.'
|
|
394
|
+
},
|
|
395
|
+
232: {
|
|
396
|
+
name: 'IndependenceNotDeclared',
|
|
397
|
+
message: 'Sources violate RequireDisjoint, or AllowShared is empty or not exactly the shared providers.'
|
|
398
|
+
},
|
|
399
|
+
234: {
|
|
400
|
+
name: 'UnsupportedAquariusPool',
|
|
401
|
+
message: 'Aquarius pool of wrong type, or zero reserve or total shares.'
|
|
402
|
+
},
|
|
403
|
+
235: {
|
|
404
|
+
name: 'InsufficientAquariusLiquidity',
|
|
405
|
+
message: 'Pool value below min_pool_value_wad.'
|
|
406
|
+
},
|
|
80
407
|
// SpokeError
|
|
81
408
|
300: {
|
|
82
409
|
name: 'SpokeNotFound',
|
|
@@ -98,6 +425,18 @@
|
|
|
98
425
|
name: 'SpokeAssetInUse',
|
|
99
426
|
message: 'This spoke asset still has live positions; drain usage before removal.'
|
|
100
427
|
},
|
|
428
|
+
310: {
|
|
429
|
+
name: 'SpokeMismatch',
|
|
430
|
+
message: 'Account\'s spoke differs from the targeted spoke.'
|
|
431
|
+
},
|
|
432
|
+
311: {
|
|
433
|
+
name: 'SpokeSupplyCapReached',
|
|
434
|
+
message: 'Supply would exceed the spoke supply cap.'
|
|
435
|
+
},
|
|
436
|
+
312: {
|
|
437
|
+
name: 'SpokeBorrowCapReached',
|
|
438
|
+
message: 'Borrow would exceed the spoke borrow cap.'
|
|
439
|
+
},
|
|
101
440
|
315: {
|
|
102
441
|
name: 'SpokeAssetPaused',
|
|
103
442
|
message: 'This spoke asset is paused.'
|
|
@@ -114,33 +453,87 @@
|
|
|
114
453
|
name: 'SpokeAssetSeizureHalted',
|
|
115
454
|
message: 'Liquidation seizure is halted for this spoke asset.'
|
|
116
455
|
},
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
message: 'The oracle quote asset/market is missing or invalid.'
|
|
456
|
+
319: {
|
|
457
|
+
name: 'SpokeFlagsEpochMismatch',
|
|
458
|
+
message: 'RelaxSpokeAssetFlags epoch is stale or wrong; checked at proposal and execution.'
|
|
121
459
|
},
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
460
|
+
// FlashLoanError
|
|
461
|
+
400: {
|
|
462
|
+
name: 'FlashLoanOngoing',
|
|
463
|
+
message: 'Flash loan in progress; re-entrant calls refused.'
|
|
125
464
|
},
|
|
126
|
-
|
|
127
|
-
name: '
|
|
128
|
-
message: '
|
|
465
|
+
401: {
|
|
466
|
+
name: 'FlashloanNotEnabled',
|
|
467
|
+
message: 'Market is_flashloanable is false.'
|
|
129
468
|
},
|
|
130
|
-
|
|
131
|
-
name: '
|
|
132
|
-
message: '
|
|
469
|
+
402: {
|
|
470
|
+
name: 'InvalidFlashloanRepay',
|
|
471
|
+
message: 'Allowance below principal plus fee, or a pool balance check after payout, callback, or repayment fails.'
|
|
472
|
+
},
|
|
473
|
+
409: {
|
|
474
|
+
name: 'StrategyFeeExceeds',
|
|
475
|
+
message: 'Strategy fee exceeds the borrowed amount.'
|
|
476
|
+
},
|
|
477
|
+
412: {
|
|
478
|
+
name: 'InvalidFlashloanReceiver',
|
|
479
|
+
message: 'Receiver not a deployed Wasm contract, or a controller payout targets the controller or pool.'
|
|
480
|
+
},
|
|
481
|
+
// StrategyError
|
|
482
|
+
500: {
|
|
483
|
+
name: 'ConvertStepsRequired',
|
|
484
|
+
message: 'Multiply initial payment is neither collateral nor debt asset, with no convert_swap.'
|
|
485
|
+
},
|
|
486
|
+
501: {
|
|
487
|
+
name: 'RouterOverspend',
|
|
488
|
+
message: 'Controller input balance rose during the swap, or router spent over amount_in.'
|
|
489
|
+
},
|
|
490
|
+
502: {
|
|
491
|
+
name: 'NoSwapOutput',
|
|
492
|
+
message: 'Swap produced no positive measured output.'
|
|
493
|
+
},
|
|
494
|
+
503: {
|
|
495
|
+
name: 'CollateralRequired',
|
|
496
|
+
message: 'Flash_position collateral list has no positive minimum. Empty list raises #16.'
|
|
497
|
+
},
|
|
498
|
+
504: {
|
|
499
|
+
name: 'CollateralMinimumNotMet',
|
|
500
|
+
message: 'Measured deposit below its minimum, or none positive.'
|
|
501
|
+
},
|
|
502
|
+
505: {
|
|
503
|
+
name: 'FlashPositionClosed',
|
|
504
|
+
message: 'Flash_position ended without supply or positive debt in its debt market.'
|
|
133
505
|
}
|
|
134
506
|
};
|
|
507
|
+
const ERROR_CODE = /Error\(Contract,\s*#(\d+)\)/;
|
|
508
|
+
const EMITTED_ERROR = /contract:(C[A-Z2-7]{55})[^\n]*?Error\(Contract,\s*#(\d+)\)/g;
|
|
509
|
+
const INVOKED_TAG = /\[xoxno-invoked:(C[A-Z2-7]{55})\]/;
|
|
510
|
+
const HAS_EVENT_LOG = /contract:C[A-Z2-7]{55}/;
|
|
511
|
+
const scopedCode = (raw, allowed)=>{
|
|
512
|
+
for (const m of raw.matchAll(EMITTED_ERROR)){
|
|
513
|
+
if (allowed.has(m[1])) return Number(m[2]);
|
|
514
|
+
}
|
|
515
|
+
if (HAS_EVENT_LOG.test(raw)) return null;
|
|
516
|
+
const tag = raw.match(INVOKED_TAG);
|
|
517
|
+
const first = raw.match(ERROR_CODE);
|
|
518
|
+
return tag && allowed.has(tag[1]) && first ? Number(first[1]) : null;
|
|
519
|
+
};
|
|
135
520
|
/**
|
|
136
521
|
* Extracts a `Error(Contract, #N)` code from a raw Soroban simulation/RPC error
|
|
137
522
|
* string and resolves it against the rs-lending-xlm catalog. Matches only the
|
|
138
523
|
* exact `Error(Contract, #N)` pattern — never loose digits, since raw error
|
|
139
524
|
* strings can contain unrelated numbers (fees, ledgers, sequence numbers).
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
525
|
+
*
|
|
526
|
+
* Without `opts.contracts` it maps the first code in the string, whichever
|
|
527
|
+
* contract emitted it.
|
|
528
|
+
*/ export function mapSorobanError(raw, opts) {
|
|
529
|
+
let code;
|
|
530
|
+
if (opts?.contracts?.length) {
|
|
531
|
+
code = scopedCode(raw, new Set(opts.contracts));
|
|
532
|
+
} else {
|
|
533
|
+
const match = raw.match(ERROR_CODE);
|
|
534
|
+
code = match ? Number(match[1]) : null;
|
|
535
|
+
}
|
|
536
|
+
if (code === null) return null;
|
|
144
537
|
const entry = SOROBAN_ERROR_CATALOG[code];
|
|
145
538
|
return entry ? {
|
|
146
539
|
code,
|