@lumenwipe/sdk 0.1.0 → 0.2.0
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/index.cjs +25 -0
- package/dist/index.d.cts +435 -15
- package/dist/index.d.ts +435 -15
- package/dist/index.js +25 -0
- package/package.json +9 -7
package/dist/index.cjs
CHANGED
|
@@ -146,6 +146,31 @@ var LumenWipeClient = class {
|
|
|
146
146
|
transaction
|
|
147
147
|
});
|
|
148
148
|
}
|
|
149
|
+
/** Wraps a wind-down transaction (its own fee already zero) in a signed CAP-15 fee-bump
|
|
150
|
+
* envelope for an account that cannot pay its own fee (architecture.md §8.1). The caller
|
|
151
|
+
* submits the returned XDR through `submit()`, exactly like any other close transaction. */
|
|
152
|
+
feeBumpSponsor(transaction, network = this.defaultNetwork) {
|
|
153
|
+
return this.http.request("POST", `/${network}/fee-bump/sponsor`, {
|
|
154
|
+
transaction
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
/** Every live SEP-41 allowance the account has granted (architecture.md §12). Independent of
|
|
158
|
+
* closing an account - a standalone security utility. */
|
|
159
|
+
getAllowances(address, network = this.defaultNetwork) {
|
|
160
|
+
return this.http.request(
|
|
161
|
+
"GET",
|
|
162
|
+
`/${network}/allowances/${encodeURIComponent(address)}`
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
/** Builds the unsigned `approve(owner, spender, 0, 0)` transaction that revokes one allowance.
|
|
166
|
+
* The caller signs and submits it through `submit()`, like any other transaction here. */
|
|
167
|
+
revokeAllowance(params, network = this.defaultNetwork) {
|
|
168
|
+
return this.http.request(
|
|
169
|
+
"POST",
|
|
170
|
+
`/${network}/allowances/revoke`,
|
|
171
|
+
params
|
|
172
|
+
);
|
|
173
|
+
}
|
|
149
174
|
};
|
|
150
175
|
|
|
151
176
|
// src/close-engine.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -36,6 +36,20 @@ export declare interface AccountState {
|
|
|
36
36
|
* numSubEntries on this account; populated via the Horizon adapter. */
|
|
37
37
|
claimableBalances: ClaimableBalance[];
|
|
38
38
|
subEntryMismatch: boolean;
|
|
39
|
+
/** Detected DeFi positions (Blend, Aquarius, Soroswap, Phoenix, FxDAO), resolved via OctoPos on
|
|
40
|
+
* mainnet or a direct contract read on testnet / mainnet degraded mode - architecture.md §7.1.
|
|
41
|
+
* Never absent: an unconfigured deployment or provider outage still returns a result, stamped
|
|
42
|
+
* with a null `timestamp` and reflected in `defiPositionsWarnings` rather than being omitted. */
|
|
43
|
+
defiPositions: DefiPositionsResult;
|
|
44
|
+
/** Plain-language notices from `assessDefiPositionsGate` (issue #147) - stale/unconfirmed data
|
|
45
|
+
* or an unrecognized position - reusing the exact same typed-blocker signal close/plan already
|
|
46
|
+
* gates on, so the analysis view and the plan never disagree about what's trustworthy. Empty
|
|
47
|
+
* when nothing needs flagging. */
|
|
48
|
+
defiPositionsWarnings: PlanBlocker[];
|
|
49
|
+
/** Soroban token balances held directly, best effort (see `SorobanTokensResult`). Absent on
|
|
50
|
+
* account reads produced before this field existed; a consumer treats absence as "nothing
|
|
51
|
+
* known", never as "nothing held". */
|
|
52
|
+
sorobanTokens?: SorobanTokensResult;
|
|
39
53
|
}
|
|
40
54
|
|
|
41
55
|
export declare interface AccountThresholds {
|
|
@@ -44,16 +58,118 @@ export declare interface AccountThresholds {
|
|
|
44
58
|
high: number;
|
|
45
59
|
}
|
|
46
60
|
|
|
61
|
+
/**
|
|
62
|
+
* A live, non-zero SEP-41 allowance the account has granted a spender on one token
|
|
63
|
+
* (architecture.md §12). The amount always comes from a live `allowance(from, spender)` read -
|
|
64
|
+
* `approve` neither decrements on spend nor is the only way the amount could have changed since
|
|
65
|
+
* it was set, so the event that discovered the pair is never trusted for the amount itself.
|
|
66
|
+
*/
|
|
67
|
+
export declare interface Allowance {
|
|
68
|
+
/** The token contract, `C...`. */
|
|
69
|
+
token: string;
|
|
70
|
+
/** From the token's own `symbol()`, null when it does not answer. */
|
|
71
|
+
tokenSymbol: string | null;
|
|
72
|
+
/** From the token's own `decimals()`, null when it does not answer. */
|
|
73
|
+
tokenDecimals: number | null;
|
|
74
|
+
/** The approved spender. Almost always a contract (`C...`) - a DeFi protocol - but SEP-41's
|
|
75
|
+
* `approve(from, spender, ...)` types `spender` as `Address`, so a plain account (`G...`) is a
|
|
76
|
+
* legitimate, if unusual, spender too. */
|
|
77
|
+
spender: string;
|
|
78
|
+
/** The spender's protocol, when its address resolves to a known DeFi contract registry entry
|
|
79
|
+
* on this network. Null does not mean unsafe - most legitimate spenders (a specific vault, an
|
|
80
|
+
* integrator's own contract) are simply not in the registry. */
|
|
81
|
+
spenderProtocol: DefiProtocol | null;
|
|
82
|
+
/** Base units, integer string, as `allowance(from, spender)` reports it live on the ledger. */
|
|
83
|
+
amount: string;
|
|
84
|
+
/** The ledger this allowance expires at, from the most recent `approve` event that discovered
|
|
85
|
+
* this pair. Null when the amount is confirmed live but no `approve` event for this exact pair
|
|
86
|
+
* was found within the event scan's retention window (e.g. approved long enough ago that the
|
|
87
|
+
* event has aged out) - the amount is still ground truth, the expiration simply is not
|
|
88
|
+
* observable from this discovery path, since SEP-41's `allowance()` returns only the amount. */
|
|
89
|
+
expirationLedger: number | null;
|
|
90
|
+
/** Every source that proposed this pair. */
|
|
91
|
+
sources: AllowanceSource[];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** How one candidate source fared, so the interface can say exactly what was consulted. */
|
|
95
|
+
export declare interface AllowanceCoverage {
|
|
96
|
+
source: AllowanceSource;
|
|
97
|
+
status: "ok" | "failed" | "skipped";
|
|
98
|
+
detail?: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Where an allowance candidate (token, spender) pair came from before its live amount was
|
|
102
|
+
* confirmed on the ledger. */
|
|
103
|
+
export declare type AllowanceSource = "events" | "registry";
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Every live allowance the account has granted, across every token it has approved anything on.
|
|
107
|
+
* Soroban has no on-chain index of an account's approvals, so this is a best-effort union of
|
|
108
|
+
* candidate (token, spender) pairs - recent `approve` events naming this account as `from`, and
|
|
109
|
+
* the known DeFi contract registry's spenders crossed with a small curated token list - each
|
|
110
|
+
* confirmed by reading `allowance(from, spender)` on the ledger. A zero allowance, live or never
|
|
111
|
+
* granted, is not reported: only what is actually outstanding right now.
|
|
112
|
+
*/
|
|
113
|
+
export declare interface AllowancesResult {
|
|
114
|
+
allowances: Allowance[];
|
|
115
|
+
coverage: AllowanceCoverage[];
|
|
116
|
+
/** The ledger range the event scan covered, or null when it ran out of budget before starting. */
|
|
117
|
+
eventsScanned: {
|
|
118
|
+
fromLedger: number;
|
|
119
|
+
toLedger: number;
|
|
120
|
+
} | null;
|
|
121
|
+
/** Plain-language warnings: a source that failed, candidates dropped by the cap. */
|
|
122
|
+
warnings: PlanBlocker[];
|
|
123
|
+
}
|
|
124
|
+
|
|
47
125
|
export declare type ApiErrorBody = StructuredApiError | PlainApiError;
|
|
48
126
|
|
|
127
|
+
export declare interface AquariusLpPosition extends DefiPositionBase {
|
|
128
|
+
protocol: "aquarius";
|
|
129
|
+
positionType: "lp";
|
|
130
|
+
shareAmount: string;
|
|
131
|
+
/** Reported by OctoPos alongside the LP position rather than as its own position. */
|
|
132
|
+
claimableAquaAmount?: string;
|
|
133
|
+
/** The pool's tokens in the pool's own order - the order `withdraw` pays them out and
|
|
134
|
+
* `min_amounts` is given in. Read from the pool when detection can. */
|
|
135
|
+
tokens?: string[];
|
|
136
|
+
/** The pool's LP share token: a separate contract in Aquarius, where the account's shares live. */
|
|
137
|
+
shareToken?: string;
|
|
138
|
+
/** Which pool code the pool runs, from the registry. */
|
|
139
|
+
poolType?: AquariusPoolType;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Aquarius deploys three pool codes; only the share-based ones can be exited by shares. */
|
|
143
|
+
export declare type AquariusPoolType = "constant_product" | "stable" | "concentrated";
|
|
144
|
+
|
|
49
145
|
/**
|
|
50
|
-
* What happens to a non-XLM balance before
|
|
146
|
+
* What happens to a non-XLM balance before the account is merged.
|
|
51
147
|
*
|
|
52
148
|
* `convert` swaps it to XLM and `issuer` sends it back to be burned - both end the close with the
|
|
53
149
|
* position destroyed. `transfer` keeps the asset, as the asset, by paying it to another account
|
|
54
|
-
* that already holds the trustline.
|
|
150
|
+
* (one that already holds the trustline, for a classic asset). `leave` applies only to a Soroban
|
|
151
|
+
* token balance, which sits in the token contract's storage and does not stop a merge: the user
|
|
152
|
+
* acknowledges that it stays with this address, recoverable only by funding the same key again.
|
|
153
|
+
* A classic trustline can never be left - the merge fails while it holds a balance.
|
|
55
154
|
*/
|
|
56
|
-
export declare type AssetDisposition = "convert" | "issuer" | "transfer";
|
|
155
|
+
export declare type AssetDisposition = "convert" | "issuer" | "transfer" | "leave";
|
|
156
|
+
|
|
157
|
+
export declare interface BlendBorrowPosition extends DefiPositionBase {
|
|
158
|
+
protocol: "blend";
|
|
159
|
+
positionType: "borrow";
|
|
160
|
+
assetAddress: string;
|
|
161
|
+
dTokenAmount: string;
|
|
162
|
+
healthFactor?: string;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export declare interface BlendSupplyPosition extends DefiPositionBase {
|
|
166
|
+
protocol: "blend";
|
|
167
|
+
positionType: "supply";
|
|
168
|
+
assetAddress: string;
|
|
169
|
+
bTokenAmount: string;
|
|
170
|
+
/** True when this supply is also posted as backstop collateral. */
|
|
171
|
+
isBackstop?: boolean;
|
|
172
|
+
}
|
|
57
173
|
|
|
58
174
|
export declare interface BuildPlanResult {
|
|
59
175
|
steps: PlannedStep[];
|
|
@@ -127,7 +243,14 @@ export declare interface CloseEngineDeps {
|
|
|
127
243
|
/** Called after a transaction confirms, with the transaction and its hash. */
|
|
128
244
|
onConfirmed?: (tx: CloseTransaction, hash: string) => void;
|
|
129
245
|
onProgress?: (message: string) => void;
|
|
130
|
-
/**
|
|
246
|
+
/**
|
|
247
|
+
* Safety bound so a misbehaving API can never spin the loop forever. This is what covers
|
|
248
|
+
* #59's mediator-cleanup concern: the API is stateless and re-reads live state every round,
|
|
249
|
+
* so `remaining.requiresAnotherCall` for that flow reflects "cleanup still sees something to
|
|
250
|
+
* remove," not a bounded countdown - if an asset keeps getting re-funded between rounds (or
|
|
251
|
+
* any other close path never converges for whatever reason), this stops it after `maxRounds`
|
|
252
|
+
* with a clear thrown error instead of looping indefinitely.
|
|
253
|
+
*/
|
|
131
254
|
maxRounds?: number;
|
|
132
255
|
}
|
|
133
256
|
|
|
@@ -147,6 +270,24 @@ export declare interface CloseTransaction {
|
|
|
147
270
|
sourceSequence: string;
|
|
148
271
|
validUntilLedger: number;
|
|
149
272
|
covers: StepType[];
|
|
273
|
+
/**
|
|
274
|
+
* Which of the covered steps this transaction is for, by the same identity a plan step carries
|
|
275
|
+
* (`PlannedStep.affectedContract` for an exit, `affectedAsset` for an asset or token). `covers`
|
|
276
|
+
* names step TYPES, and a close can hold several steps of one type - three DeFi exits, two
|
|
277
|
+
* token transfers - so a client marking by type alone marked them all done off one transaction
|
|
278
|
+
* and stamped them all with its hash. The permanent receipt then listed one exit where three
|
|
279
|
+
* had run. Absent when the transaction covers every step of the types it names, which is the
|
|
280
|
+
* only shape an older client ever saw.
|
|
281
|
+
*/
|
|
282
|
+
coversTargets?: string[];
|
|
283
|
+
/**
|
|
284
|
+
* True when the account cannot pay this transaction's own fee without dropping below its
|
|
285
|
+
* reserve (architecture.md §8.1): the API built it with its own fee at zero, and the client
|
|
286
|
+
* must route the signed envelope through `POST /:network/fee-bump/sponsor` before submitting
|
|
287
|
+
* it, instead of submitting it directly. Absent (not `false`) on every ordinary transaction -
|
|
288
|
+
* an older client reading this field sees nothing here and simply submits as it always has.
|
|
289
|
+
*/
|
|
290
|
+
needsSponsoredFee?: true;
|
|
150
291
|
intent: TxIntent;
|
|
151
292
|
}
|
|
152
293
|
|
|
@@ -181,6 +322,13 @@ export declare interface DecisionAnswer {
|
|
|
181
322
|
choice: string;
|
|
182
323
|
params?: {
|
|
183
324
|
maxSlippageBps?: number;
|
|
325
|
+
/**
|
|
326
|
+
* Required by `convert_to_xlm` on a Soroban token: the least XLM, in stroops, the user was
|
|
327
|
+
* shown the swap would deliver (the plan's `quote.minAmountOut`). The build refuses a route
|
|
328
|
+
* that no longer clears it (`quote_drifted`) instead of swapping at a rate nobody agreed to,
|
|
329
|
+
* and the browser holds the built swap's own minimum to at least this figure.
|
|
330
|
+
*/
|
|
331
|
+
minAmountOut?: string;
|
|
184
332
|
/**
|
|
185
333
|
* Required by the `transfer_to_account` choice: the `G...` address the balance is paid to.
|
|
186
334
|
*
|
|
@@ -210,6 +358,120 @@ export declare interface DecisionPoint {
|
|
|
210
358
|
required: boolean;
|
|
211
359
|
}
|
|
212
360
|
|
|
361
|
+
/** Keyed by asset/contract address. Built from OctoPos's queryKeys.tokenInfos. */
|
|
362
|
+
export declare interface DefiEnrichmentEntry {
|
|
363
|
+
symbol: string;
|
|
364
|
+
decimals: number;
|
|
365
|
+
usdPrice: string | null;
|
|
366
|
+
priceSource: string | null;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export declare type DefiPosition = BlendSupplyPosition | BlendBorrowPosition | AquariusLpPosition | SoroswapLpPosition | PhoenixLpPosition | PhoenixStakePosition | FxdaoCdpPosition;
|
|
370
|
+
|
|
371
|
+
declare interface DefiPositionBase {
|
|
372
|
+
protocol: DefiProtocol;
|
|
373
|
+
/** Pool, market, or vault contract this position lives in. */
|
|
374
|
+
contractAddress: string;
|
|
375
|
+
/** Human-readable view of the position, when the analysis could resolve one. */
|
|
376
|
+
display?: DefiPositionDisplay;
|
|
377
|
+
/** Left as an optional hook: the wasmHash -\> protocol-version contract registry
|
|
378
|
+
* architecture.md describes does not exist in code yet (a later contribution). */
|
|
379
|
+
wasmHash?: string;
|
|
380
|
+
usdValue: string | null;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* What a person should read about a position, in the protocol's own terms, resolved by the API
|
|
385
|
+
* from a live read at analysis time (issue #197). Presentation only: every field is nullable, a
|
|
386
|
+
* failed read leaves the whole object absent, and nothing here feeds the plan, the gate, or an
|
|
387
|
+
* exit - those re-read the ledger themselves.
|
|
388
|
+
*/
|
|
389
|
+
export declare interface DefiPositionDisplay {
|
|
390
|
+
/** The pool, pair, or vault by name (the protocol's own metadata or the registry label). */
|
|
391
|
+
pool: string | null;
|
|
392
|
+
/** Symbol of the position's asset; for an LP position the pair, e.g. "XLM/USDC". */
|
|
393
|
+
asset: string | null;
|
|
394
|
+
/** Underlying amount in the asset's own units as a decimal string - not shares or bTokens. */
|
|
395
|
+
amount: string | null;
|
|
396
|
+
/** The part of `amount` posted as collateral (lending protocols), decimal string; null when
|
|
397
|
+
* the protocol has no such distinction. */
|
|
398
|
+
collateralAmount: string | null;
|
|
399
|
+
/** Current yield as a percentage with two decimals ("3.99"): earned on a supply, paid on debt. */
|
|
400
|
+
yieldPct: string | null;
|
|
401
|
+
yieldKind: "earned" | "paid" | null;
|
|
402
|
+
/** One protocol-specific clause the line ends with, e.g. what an LP share is worth in its two
|
|
403
|
+
* tokens ("9.95 XLM + 19.90 USDC"). Null when there is nothing to add. */
|
|
404
|
+
detail?: string | null;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* The normalized DeFi position model every downstream consumer (exit adapters, plan preview)
|
|
409
|
+
* depends on - no OctoPos-specific field names beyond this boundary (architecture.md §7.1).
|
|
410
|
+
*/
|
|
411
|
+
export declare interface DefiPositionsResult {
|
|
412
|
+
address: string;
|
|
413
|
+
network: Network;
|
|
414
|
+
positions: DefiPosition[];
|
|
415
|
+
unrecognizedPositions: UnrecognizedDefiPosition[];
|
|
416
|
+
enrichment: Record<string, DefiEnrichmentEntry>;
|
|
417
|
+
/** OctoPos's own freshness/provenance signal ("snapshot" | "empty" | "cache" | "not-tracked").
|
|
418
|
+
* Passed through verbatim rather than architecture.md's described (but not actually shipped)
|
|
419
|
+
* partial_result/attribution_confidence fields - see issue #147 for the gating that consumes
|
|
420
|
+
* this. */
|
|
421
|
+
source: string;
|
|
422
|
+
timestamp: string | null;
|
|
423
|
+
queryKeys: DefiQueryKeys;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Lowercased from OctoPos's own SUPPLY/BORROW/LP/STAKE tags. FxDAO's COLLATERAL+BORROW pair is
|
|
428
|
+
* one vault - one exit unit per architecture.md §9.7 - so it collapses to a single "cdp" position
|
|
429
|
+
* carrying both legs rather than two positions. WALLET positions are out of scope: classic
|
|
430
|
+
* balances already come from AccountState.trustlines, and Soroban token balance handling is a
|
|
431
|
+
* separate Phase-2 deliverable, not this epic.
|
|
432
|
+
*/
|
|
433
|
+
export declare type DefiPositionType = "supply" | "borrow" | "lp" | "cdp" | "stake";
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Protocols LumenWipe actually knows how to exit (architecture.md §9's table). OctoPos itself
|
|
437
|
+
* indexes more than this (e.g. "untangled-vault", "stellar-wallet") - those are dropped by the
|
|
438
|
+
* adapter rather than represented here, since the type system should not claim LumenWipe can act
|
|
439
|
+
* on a protocol it has no exit path for.
|
|
440
|
+
*/
|
|
441
|
+
export declare type DefiProtocol = "blend" | "aquarius" | "soroswap" | "phoenix" | "fxdao";
|
|
442
|
+
|
|
443
|
+
export declare interface DefiQueryKeys {
|
|
444
|
+
rpcEndpoints: DefiRpcEndpoint[];
|
|
445
|
+
rpcPolicy: DefiRpcPolicy;
|
|
446
|
+
slices: Partial<Record<DefiProtocol, DefiQueryKeysSlice>>;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Ready-made ledger keys plus pool/vault metadata for one protocol, letting a caller read
|
|
451
|
+
* positions directly over RPC without OctoPos storing anything server-side (architecture.md
|
|
452
|
+
* §7.1). Passed through typed rather than discarded, since issue #148's RPC fallback needs
|
|
453
|
+
* exactly this and would otherwise have to refetch it.
|
|
454
|
+
*/
|
|
455
|
+
export declare interface DefiQueryKeysSlice {
|
|
456
|
+
protocol: string;
|
|
457
|
+
ledgerKeys: string[];
|
|
458
|
+
poolAddresses: string[];
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** A public Soroban RPC endpoint OctoPos suggests for a direct getLedgerEntries read. */
|
|
462
|
+
export declare interface DefiRpcEndpoint {
|
|
463
|
+
url: string;
|
|
464
|
+
health: string;
|
|
465
|
+
avgLatencyMs: number;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export declare interface DefiRpcPolicy {
|
|
469
|
+
maxKeysPerCall: number;
|
|
470
|
+
recommendedConcurrency: number;
|
|
471
|
+
backoffOn429Ms: number[];
|
|
472
|
+
timeoutMs: number;
|
|
473
|
+
}
|
|
474
|
+
|
|
213
475
|
export declare type DemolishPhase = "IDLE" | "ANALYZING" | "PREFLIGHT_COMPLETE" | "SIGNER_SETUP" | "STEP_EXECUTING" | "STEP_CONFIRMED" | "STEP_FAILED" | "COMPLETE" | "ABORTED";
|
|
214
476
|
|
|
215
477
|
export declare interface ExecutionTxBreakdown {
|
|
@@ -218,8 +480,21 @@ export declare interface ExecutionTxBreakdown {
|
|
|
218
480
|
reason?: "op_batch" | "defi_dependency";
|
|
219
481
|
}
|
|
220
482
|
|
|
483
|
+
/** Response from `POST /:network/fee-bump/sponsor`. */
|
|
484
|
+
export declare interface FeeBumpSponsorResponse {
|
|
485
|
+
transaction: string;
|
|
486
|
+
}
|
|
487
|
+
|
|
221
488
|
export declare type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
222
489
|
|
|
490
|
+
export declare interface FxdaoCdpPosition extends DefiPositionBase {
|
|
491
|
+
protocol: "fxdao";
|
|
492
|
+
positionType: "cdp";
|
|
493
|
+
denomination: string;
|
|
494
|
+
collateralAmount: string;
|
|
495
|
+
debtAmount: string;
|
|
496
|
+
}
|
|
497
|
+
|
|
223
498
|
/** Response from `GET /health`. */
|
|
224
499
|
export declare interface HealthResponse {
|
|
225
500
|
status: string;
|
|
@@ -233,16 +508,6 @@ export declare class InsufficientSignatureWeightError extends Error {
|
|
|
233
508
|
constructor(pending: PendingRound);
|
|
234
509
|
}
|
|
235
510
|
|
|
236
|
-
/**
|
|
237
|
-
* One operation in a decoded close transaction.
|
|
238
|
-
*
|
|
239
|
-
* `source` is the account the operation acts as - the operation's own source account when it
|
|
240
|
-
* carries one, otherwise the transaction's. It is what lets verification assert relationships
|
|
241
|
-
* *between* operations rather than trusting each in isolation: in a mediated close the forward
|
|
242
|
-
* payment must be sent by the very account the merge just paid into, which is what makes the
|
|
243
|
-
* intermediary a conduit rather than a destination. Without it the only available check is
|
|
244
|
-
* pinning the intermediary's address, which every consumer would then have to be told.
|
|
245
|
-
*/
|
|
246
511
|
export declare type IntentOperation = IntentOperationBody & {
|
|
247
512
|
source: string;
|
|
248
513
|
};
|
|
@@ -293,6 +558,33 @@ export declare type IntentOperationBody = {
|
|
|
293
558
|
type: "revoke_sponsorship";
|
|
294
559
|
entryKind: "account" | "trustline" | "offer" | "data_entry" | "signer";
|
|
295
560
|
owner: string;
|
|
561
|
+
} | {
|
|
562
|
+
type: "invoke_host_function";
|
|
563
|
+
contract: string;
|
|
564
|
+
function: string;
|
|
565
|
+
/** The decoded arguments rendered for a human, in order. */
|
|
566
|
+
args: string[];
|
|
567
|
+
/** Every Stellar account (G...) named anywhere in the arguments or in the authorization
|
|
568
|
+
* tree the signature would satisfy. A verifier insists these are all the closing account. */
|
|
569
|
+
accountsReferenced: string[];
|
|
570
|
+
/** Every contract (C...) named the same way, including nested calls the signature would
|
|
571
|
+
* authorize. A verifier insists these are contracts the account is known to deal with. */
|
|
572
|
+
contractsReferenced: string[];
|
|
573
|
+
/** Address forms that cannot be pinned to anything (muxed accounts, claimable balances,
|
|
574
|
+
* liquidity pools). A verifier refuses any. */
|
|
575
|
+
unsupportedAddressCount: number;
|
|
576
|
+
/** True when the signature would authorize more than the account's own plain contract
|
|
577
|
+
* calls: another party's credentials, or a contract creation, in the auth entries. */
|
|
578
|
+
authorizesBeyondSelf: boolean;
|
|
579
|
+
/** How deep the authorization tree nests: 0 when every entry is a single plain call with
|
|
580
|
+
* no sub-invocations, 1 when a call authorizes one level of nested calls, and so on. A
|
|
581
|
+
* token transfer must be 0 - the token may not make the account authorize anything else. */
|
|
582
|
+
authDepth: number;
|
|
583
|
+
/** Every non-root call in the authorization tree - what the root call (a pool, router, or
|
|
584
|
+
* backstop) would itself be authorized to do on the account's behalf, one level down. A
|
|
585
|
+
* DeFi exit's top-level contract/function pinning says nothing about these: a hostile
|
|
586
|
+
* build could keep a legitimate top-level call while hiding an unrelated transfer here. */
|
|
587
|
+
subInvocations: SubInvocationCall[];
|
|
296
588
|
} | {
|
|
297
589
|
type: "unknown";
|
|
298
590
|
};
|
|
@@ -331,6 +623,20 @@ export declare class LumenWipeClient {
|
|
|
331
623
|
submit(signedXdr: string, network?: Network): Promise<SubmitResponse>;
|
|
332
624
|
mediatorCheck(address: string, network?: Network): Promise<MediatorCheckResult>;
|
|
333
625
|
mediatorSign(transaction: string, network?: Network): Promise<MediatorSignResponse>;
|
|
626
|
+
/** Wraps a wind-down transaction (its own fee already zero) in a signed CAP-15 fee-bump
|
|
627
|
+
* envelope for an account that cannot pay its own fee (architecture.md §8.1). The caller
|
|
628
|
+
* submits the returned XDR through `submit()`, exactly like any other close transaction. */
|
|
629
|
+
feeBumpSponsor(transaction: string, network?: Network): Promise<FeeBumpSponsorResponse>;
|
|
630
|
+
/** Every live SEP-41 allowance the account has granted (architecture.md §12). Independent of
|
|
631
|
+
* closing an account - a standalone security utility. */
|
|
632
|
+
getAllowances(address: string, network?: Network): Promise<AllowancesResult>;
|
|
633
|
+
/** Builds the unsigned `approve(owner, spender, 0, 0)` transaction that revokes one allowance.
|
|
634
|
+
* The caller signs and submits it through `submit()`, like any other transaction here. */
|
|
635
|
+
revokeAllowance(params: {
|
|
636
|
+
owner: string;
|
|
637
|
+
token: string;
|
|
638
|
+
spender: string;
|
|
639
|
+
}, network?: Network): Promise<RevokeAllowanceResponse>;
|
|
334
640
|
}
|
|
335
641
|
|
|
336
642
|
export declare interface LumenWipeClientOptions {
|
|
@@ -395,6 +701,20 @@ export declare interface PendingRound {
|
|
|
395
701
|
requiresAnotherCall: boolean;
|
|
396
702
|
}
|
|
397
703
|
|
|
704
|
+
export declare interface PhoenixLpPosition extends DefiPositionBase {
|
|
705
|
+
protocol: "phoenix";
|
|
706
|
+
positionType: "lp";
|
|
707
|
+
shareAmount: string;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
export declare interface PhoenixStakePosition extends DefiPositionBase {
|
|
711
|
+
protocol: "phoenix";
|
|
712
|
+
positionType: "stake";
|
|
713
|
+
stakedAmount: string;
|
|
714
|
+
/** Unix seconds; unbonding requires the original stake's timestamp (architecture.md §9.6). */
|
|
715
|
+
stakedAtEpoch: string;
|
|
716
|
+
}
|
|
717
|
+
|
|
398
718
|
/** @deprecated The API emits one envelope (`StructuredApiError`). Kept only so a consumer
|
|
399
719
|
* pinned to an older deployment still type-checks during a rollout; remove once none remain. */
|
|
400
720
|
export declare interface PlainApiError {
|
|
@@ -420,7 +740,15 @@ export declare interface PlannedStep {
|
|
|
420
740
|
status: StepStatus;
|
|
421
741
|
txHash: string | null;
|
|
422
742
|
error: string | null;
|
|
743
|
+
/** What the user's own account paid for this step, once confirmed - exactly "0" when a
|
|
744
|
+
* dedicated sponsor account covered the fee-bump instead. Otherwise the plan-time estimate
|
|
745
|
+
* copied forward: the close-engine's confirmation callback carries only a tx hash, not the
|
|
746
|
+
* fee Horizon actually charged, so this cannot correct for surge pricing. Absent until the
|
|
747
|
+
* step is confirmed. */
|
|
748
|
+
actualFeeLumens?: string;
|
|
423
749
|
affectedAsset?: string;
|
|
750
|
+
/** The pool, pair, or vault an EXIT_POSITIONS step leaves. */
|
|
751
|
+
affectedContract?: string;
|
|
424
752
|
fallbackToIssuer?: boolean;
|
|
425
753
|
}
|
|
426
754
|
|
|
@@ -455,6 +783,11 @@ export declare interface QuoteInfo {
|
|
|
455
783
|
expiresAtLedger: number;
|
|
456
784
|
}
|
|
457
785
|
|
|
786
|
+
/** Response from `POST /:network/allowances/revoke`. */
|
|
787
|
+
export declare interface RevokeAllowanceResponse {
|
|
788
|
+
transaction: string;
|
|
789
|
+
}
|
|
790
|
+
|
|
458
791
|
/**
|
|
459
792
|
* Runs the full multi-round close. Each round: fetch a batch of unsigned transactions,
|
|
460
793
|
* verify every one before signing, sign it, and submit only once its accumulated signing
|
|
@@ -465,6 +798,60 @@ export declare interface QuoteInfo {
|
|
|
465
798
|
*/
|
|
466
799
|
export declare function runClose(deps: CloseEngineDeps, resume?: PendingRound): Promise<void>;
|
|
467
800
|
|
|
801
|
+
/** A SEP-41 token balance the account holds in a contract's storage - not a classic trustline. */
|
|
802
|
+
export declare interface SorobanTokenBalance {
|
|
803
|
+
/** The token contract, `C...`. */
|
|
804
|
+
contract: string;
|
|
805
|
+
/** Base units, integer string, as `balance(account)` reports it on the ledger. "0" only for a
|
|
806
|
+
* token the account does not hold yet but a detected position's exit will pay out. */
|
|
807
|
+
balance: string;
|
|
808
|
+
/** From the contract's own `symbol()` / `decimals()`, null when it does not answer them. */
|
|
809
|
+
symbol: string | null;
|
|
810
|
+
decimals: number | null;
|
|
811
|
+
/** Every source that proposed this contract; the balance itself always comes from the ledger. */
|
|
812
|
+
sources: SorobanTokenSource[];
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/** How one candidate source fared, so the interface can say exactly what was consulted. */
|
|
816
|
+
export declare interface SorobanTokenCoverage {
|
|
817
|
+
source: SorobanTokenSource;
|
|
818
|
+
status: "ok" | "failed" | "skipped";
|
|
819
|
+
detail?: string;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/** Where a Soroban token candidate came from before its balance was confirmed on the ledger. */
|
|
823
|
+
export declare type SorobanTokenSource = "explorer" | "positions" | "list" | "events" | "manual";
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Soroban token balances the account holds directly. Soroban has no per-account token index, so
|
|
827
|
+
* this is a best-effort union of candidate sources - an explorer, the tokens named by detected
|
|
828
|
+
* positions, bundled lists, recent on-chain `transfer`/`mint` events, and contracts the user added
|
|
829
|
+
* by hand - each confirmed by reading `balance(account)` on the ledger. What could not be read is
|
|
830
|
+
* listed, never dropped; classic assets' contracts are excluded (their balance is the trustline).
|
|
831
|
+
*/
|
|
832
|
+
export declare interface SorobanTokensResult {
|
|
833
|
+
tokens: SorobanTokenBalance[];
|
|
834
|
+
/** Candidate contracts whose balance could not be read (a hostile, broken, or archived token). */
|
|
835
|
+
unreadable: string[];
|
|
836
|
+
coverage: SorobanTokenCoverage[];
|
|
837
|
+
/** The ledger range the event scan covered, or null when it ran out of budget before starting. */
|
|
838
|
+
eventsScanned: {
|
|
839
|
+
fromLedger: number;
|
|
840
|
+
toLedger: number;
|
|
841
|
+
} | null;
|
|
842
|
+
/** Plain-language warnings for the plan: a source that failed, contracts that could not be read. */
|
|
843
|
+
warnings: PlanBlocker[];
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
export declare interface SoroswapLpPosition extends DefiPositionBase {
|
|
847
|
+
protocol: "soroswap";
|
|
848
|
+
positionType: "lp";
|
|
849
|
+
shareAmount: string;
|
|
850
|
+
/** The pair's two token contracts (token_0, token_1), read from the pair when detection can;
|
|
851
|
+
* what a withdrawal receives and the exit's arguments name. */
|
|
852
|
+
tokens?: [string, string];
|
|
853
|
+
}
|
|
854
|
+
|
|
468
855
|
/**
|
|
469
856
|
* A ledger entry this account currently sponsors, on another account (or itself, for
|
|
470
857
|
* "account" - a fully-sponsored account creation). Mirrors the ledger-key kinds
|
|
@@ -497,7 +884,7 @@ export declare type SponsoredEntry = {
|
|
|
497
884
|
|
|
498
885
|
export declare type StepStatus = "pending" | "signing" | "submitted" | "confirmed" | "failed" | "skipped";
|
|
499
886
|
|
|
500
|
-
export declare type StepType = "NORMALIZE_SIGNERS" | "REVOKE_SPONSORSHIP" | "REMOVE_DATA_ENTRIES" | "CANCEL_OFFERS" | "ADD_TRUSTLINE_FOR_CLAIM" | "CLAIM_BALANCES" | "HANDLE_ASSETS" | "REMOVE_TRUSTLINES" | "CLOSE_ACCOUNT" | "MERGE";
|
|
887
|
+
export declare type StepType = "NORMALIZE_SIGNERS" | "REVOKE_SPONSORSHIP" | "REMOVE_DATA_ENTRIES" | "CANCEL_OFFERS" | "ADD_TRUSTLINE_FOR_CLAIM" | "CLAIM_BALANCES" | "EXIT_POSITIONS" | "HANDLE_ASSETS" | "REMOVE_TRUSTLINES" | "CLOSE_ACCOUNT" | "MERGE";
|
|
501
888
|
|
|
502
889
|
/** Structured error body used by the v1 (`/v1/...`) endpoints. */
|
|
503
890
|
export declare interface StructuredApiError {
|
|
@@ -508,6 +895,26 @@ export declare interface StructuredApiError {
|
|
|
508
895
|
};
|
|
509
896
|
}
|
|
510
897
|
|
|
898
|
+
/**
|
|
899
|
+
* One operation in a decoded close transaction.
|
|
900
|
+
*
|
|
901
|
+
* `source` is the account the operation acts as - the operation's own source account when it
|
|
902
|
+
* carries one, otherwise the transaction's. It is what lets verification assert relationships
|
|
903
|
+
* *between* operations rather than trusting each in isolation: in a mediated close the forward
|
|
904
|
+
* payment must be sent by the very account the merge just paid into, which is what makes the
|
|
905
|
+
* intermediary a conduit rather than a destination. Without it the only available check is
|
|
906
|
+
* pinning the intermediary's address, which every consumer would then have to be told.
|
|
907
|
+
*/
|
|
908
|
+
/** One non-root call in a Soroban authorization tree: what a DeFi exit's own contract (a pool,
|
|
909
|
+
* router, or backstop) would itself be authorized to call on the account's behalf. */
|
|
910
|
+
export declare interface SubInvocationCall {
|
|
911
|
+
contract: string;
|
|
912
|
+
function: string;
|
|
913
|
+
/** The decoded arguments rendered for a human, in order - same rendering as the top-level
|
|
914
|
+
* invocation's own `args`. */
|
|
915
|
+
args: string[];
|
|
916
|
+
}
|
|
917
|
+
|
|
511
918
|
/** Body for `POST /v1/:network/submit`. */
|
|
512
919
|
export declare interface SubmitRequest {
|
|
513
920
|
signedXdr: string;
|
|
@@ -574,4 +981,17 @@ export declare interface TxIntent {
|
|
|
574
981
|
operations: IntentOperation[];
|
|
575
982
|
}
|
|
576
983
|
|
|
984
|
+
/**
|
|
985
|
+
* A position tagged with a supported protocol whose shape the adapter could not validate. Kept
|
|
986
|
+
* distinct from "no position" so a caller (issue #147's gating) can surface it rather than treat
|
|
987
|
+
* a parse failure as an account with nothing to unwind - the "no silent skips" invariant applied
|
|
988
|
+
* to a provider field OctoPos does not formally type.
|
|
989
|
+
*/
|
|
990
|
+
export declare interface UnrecognizedDefiPosition {
|
|
991
|
+
protocol: DefiProtocol;
|
|
992
|
+
/** OctoPos's raw type tag (e.g. "SUPPLY"), kept for diagnostics even though it didn't parse. */
|
|
993
|
+
rawType: string;
|
|
994
|
+
reason: string;
|
|
995
|
+
}
|
|
996
|
+
|
|
577
997
|
export { }
|
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,20 @@ export declare interface AccountState {
|
|
|
36
36
|
* numSubEntries on this account; populated via the Horizon adapter. */
|
|
37
37
|
claimableBalances: ClaimableBalance[];
|
|
38
38
|
subEntryMismatch: boolean;
|
|
39
|
+
/** Detected DeFi positions (Blend, Aquarius, Soroswap, Phoenix, FxDAO), resolved via OctoPos on
|
|
40
|
+
* mainnet or a direct contract read on testnet / mainnet degraded mode - architecture.md §7.1.
|
|
41
|
+
* Never absent: an unconfigured deployment or provider outage still returns a result, stamped
|
|
42
|
+
* with a null `timestamp` and reflected in `defiPositionsWarnings` rather than being omitted. */
|
|
43
|
+
defiPositions: DefiPositionsResult;
|
|
44
|
+
/** Plain-language notices from `assessDefiPositionsGate` (issue #147) - stale/unconfirmed data
|
|
45
|
+
* or an unrecognized position - reusing the exact same typed-blocker signal close/plan already
|
|
46
|
+
* gates on, so the analysis view and the plan never disagree about what's trustworthy. Empty
|
|
47
|
+
* when nothing needs flagging. */
|
|
48
|
+
defiPositionsWarnings: PlanBlocker[];
|
|
49
|
+
/** Soroban token balances held directly, best effort (see `SorobanTokensResult`). Absent on
|
|
50
|
+
* account reads produced before this field existed; a consumer treats absence as "nothing
|
|
51
|
+
* known", never as "nothing held". */
|
|
52
|
+
sorobanTokens?: SorobanTokensResult;
|
|
39
53
|
}
|
|
40
54
|
|
|
41
55
|
export declare interface AccountThresholds {
|
|
@@ -44,16 +58,118 @@ export declare interface AccountThresholds {
|
|
|
44
58
|
high: number;
|
|
45
59
|
}
|
|
46
60
|
|
|
61
|
+
/**
|
|
62
|
+
* A live, non-zero SEP-41 allowance the account has granted a spender on one token
|
|
63
|
+
* (architecture.md §12). The amount always comes from a live `allowance(from, spender)` read -
|
|
64
|
+
* `approve` neither decrements on spend nor is the only way the amount could have changed since
|
|
65
|
+
* it was set, so the event that discovered the pair is never trusted for the amount itself.
|
|
66
|
+
*/
|
|
67
|
+
export declare interface Allowance {
|
|
68
|
+
/** The token contract, `C...`. */
|
|
69
|
+
token: string;
|
|
70
|
+
/** From the token's own `symbol()`, null when it does not answer. */
|
|
71
|
+
tokenSymbol: string | null;
|
|
72
|
+
/** From the token's own `decimals()`, null when it does not answer. */
|
|
73
|
+
tokenDecimals: number | null;
|
|
74
|
+
/** The approved spender. Almost always a contract (`C...`) - a DeFi protocol - but SEP-41's
|
|
75
|
+
* `approve(from, spender, ...)` types `spender` as `Address`, so a plain account (`G...`) is a
|
|
76
|
+
* legitimate, if unusual, spender too. */
|
|
77
|
+
spender: string;
|
|
78
|
+
/** The spender's protocol, when its address resolves to a known DeFi contract registry entry
|
|
79
|
+
* on this network. Null does not mean unsafe - most legitimate spenders (a specific vault, an
|
|
80
|
+
* integrator's own contract) are simply not in the registry. */
|
|
81
|
+
spenderProtocol: DefiProtocol | null;
|
|
82
|
+
/** Base units, integer string, as `allowance(from, spender)` reports it live on the ledger. */
|
|
83
|
+
amount: string;
|
|
84
|
+
/** The ledger this allowance expires at, from the most recent `approve` event that discovered
|
|
85
|
+
* this pair. Null when the amount is confirmed live but no `approve` event for this exact pair
|
|
86
|
+
* was found within the event scan's retention window (e.g. approved long enough ago that the
|
|
87
|
+
* event has aged out) - the amount is still ground truth, the expiration simply is not
|
|
88
|
+
* observable from this discovery path, since SEP-41's `allowance()` returns only the amount. */
|
|
89
|
+
expirationLedger: number | null;
|
|
90
|
+
/** Every source that proposed this pair. */
|
|
91
|
+
sources: AllowanceSource[];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** How one candidate source fared, so the interface can say exactly what was consulted. */
|
|
95
|
+
export declare interface AllowanceCoverage {
|
|
96
|
+
source: AllowanceSource;
|
|
97
|
+
status: "ok" | "failed" | "skipped";
|
|
98
|
+
detail?: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Where an allowance candidate (token, spender) pair came from before its live amount was
|
|
102
|
+
* confirmed on the ledger. */
|
|
103
|
+
export declare type AllowanceSource = "events" | "registry";
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Every live allowance the account has granted, across every token it has approved anything on.
|
|
107
|
+
* Soroban has no on-chain index of an account's approvals, so this is a best-effort union of
|
|
108
|
+
* candidate (token, spender) pairs - recent `approve` events naming this account as `from`, and
|
|
109
|
+
* the known DeFi contract registry's spenders crossed with a small curated token list - each
|
|
110
|
+
* confirmed by reading `allowance(from, spender)` on the ledger. A zero allowance, live or never
|
|
111
|
+
* granted, is not reported: only what is actually outstanding right now.
|
|
112
|
+
*/
|
|
113
|
+
export declare interface AllowancesResult {
|
|
114
|
+
allowances: Allowance[];
|
|
115
|
+
coverage: AllowanceCoverage[];
|
|
116
|
+
/** The ledger range the event scan covered, or null when it ran out of budget before starting. */
|
|
117
|
+
eventsScanned: {
|
|
118
|
+
fromLedger: number;
|
|
119
|
+
toLedger: number;
|
|
120
|
+
} | null;
|
|
121
|
+
/** Plain-language warnings: a source that failed, candidates dropped by the cap. */
|
|
122
|
+
warnings: PlanBlocker[];
|
|
123
|
+
}
|
|
124
|
+
|
|
47
125
|
export declare type ApiErrorBody = StructuredApiError | PlainApiError;
|
|
48
126
|
|
|
127
|
+
export declare interface AquariusLpPosition extends DefiPositionBase {
|
|
128
|
+
protocol: "aquarius";
|
|
129
|
+
positionType: "lp";
|
|
130
|
+
shareAmount: string;
|
|
131
|
+
/** Reported by OctoPos alongside the LP position rather than as its own position. */
|
|
132
|
+
claimableAquaAmount?: string;
|
|
133
|
+
/** The pool's tokens in the pool's own order - the order `withdraw` pays them out and
|
|
134
|
+
* `min_amounts` is given in. Read from the pool when detection can. */
|
|
135
|
+
tokens?: string[];
|
|
136
|
+
/** The pool's LP share token: a separate contract in Aquarius, where the account's shares live. */
|
|
137
|
+
shareToken?: string;
|
|
138
|
+
/** Which pool code the pool runs, from the registry. */
|
|
139
|
+
poolType?: AquariusPoolType;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Aquarius deploys three pool codes; only the share-based ones can be exited by shares. */
|
|
143
|
+
export declare type AquariusPoolType = "constant_product" | "stable" | "concentrated";
|
|
144
|
+
|
|
49
145
|
/**
|
|
50
|
-
* What happens to a non-XLM balance before
|
|
146
|
+
* What happens to a non-XLM balance before the account is merged.
|
|
51
147
|
*
|
|
52
148
|
* `convert` swaps it to XLM and `issuer` sends it back to be burned - both end the close with the
|
|
53
149
|
* position destroyed. `transfer` keeps the asset, as the asset, by paying it to another account
|
|
54
|
-
* that already holds the trustline.
|
|
150
|
+
* (one that already holds the trustline, for a classic asset). `leave` applies only to a Soroban
|
|
151
|
+
* token balance, which sits in the token contract's storage and does not stop a merge: the user
|
|
152
|
+
* acknowledges that it stays with this address, recoverable only by funding the same key again.
|
|
153
|
+
* A classic trustline can never be left - the merge fails while it holds a balance.
|
|
55
154
|
*/
|
|
56
|
-
export declare type AssetDisposition = "convert" | "issuer" | "transfer";
|
|
155
|
+
export declare type AssetDisposition = "convert" | "issuer" | "transfer" | "leave";
|
|
156
|
+
|
|
157
|
+
export declare interface BlendBorrowPosition extends DefiPositionBase {
|
|
158
|
+
protocol: "blend";
|
|
159
|
+
positionType: "borrow";
|
|
160
|
+
assetAddress: string;
|
|
161
|
+
dTokenAmount: string;
|
|
162
|
+
healthFactor?: string;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export declare interface BlendSupplyPosition extends DefiPositionBase {
|
|
166
|
+
protocol: "blend";
|
|
167
|
+
positionType: "supply";
|
|
168
|
+
assetAddress: string;
|
|
169
|
+
bTokenAmount: string;
|
|
170
|
+
/** True when this supply is also posted as backstop collateral. */
|
|
171
|
+
isBackstop?: boolean;
|
|
172
|
+
}
|
|
57
173
|
|
|
58
174
|
export declare interface BuildPlanResult {
|
|
59
175
|
steps: PlannedStep[];
|
|
@@ -127,7 +243,14 @@ export declare interface CloseEngineDeps {
|
|
|
127
243
|
/** Called after a transaction confirms, with the transaction and its hash. */
|
|
128
244
|
onConfirmed?: (tx: CloseTransaction, hash: string) => void;
|
|
129
245
|
onProgress?: (message: string) => void;
|
|
130
|
-
/**
|
|
246
|
+
/**
|
|
247
|
+
* Safety bound so a misbehaving API can never spin the loop forever. This is what covers
|
|
248
|
+
* #59's mediator-cleanup concern: the API is stateless and re-reads live state every round,
|
|
249
|
+
* so `remaining.requiresAnotherCall` for that flow reflects "cleanup still sees something to
|
|
250
|
+
* remove," not a bounded countdown - if an asset keeps getting re-funded between rounds (or
|
|
251
|
+
* any other close path never converges for whatever reason), this stops it after `maxRounds`
|
|
252
|
+
* with a clear thrown error instead of looping indefinitely.
|
|
253
|
+
*/
|
|
131
254
|
maxRounds?: number;
|
|
132
255
|
}
|
|
133
256
|
|
|
@@ -147,6 +270,24 @@ export declare interface CloseTransaction {
|
|
|
147
270
|
sourceSequence: string;
|
|
148
271
|
validUntilLedger: number;
|
|
149
272
|
covers: StepType[];
|
|
273
|
+
/**
|
|
274
|
+
* Which of the covered steps this transaction is for, by the same identity a plan step carries
|
|
275
|
+
* (`PlannedStep.affectedContract` for an exit, `affectedAsset` for an asset or token). `covers`
|
|
276
|
+
* names step TYPES, and a close can hold several steps of one type - three DeFi exits, two
|
|
277
|
+
* token transfers - so a client marking by type alone marked them all done off one transaction
|
|
278
|
+
* and stamped them all with its hash. The permanent receipt then listed one exit where three
|
|
279
|
+
* had run. Absent when the transaction covers every step of the types it names, which is the
|
|
280
|
+
* only shape an older client ever saw.
|
|
281
|
+
*/
|
|
282
|
+
coversTargets?: string[];
|
|
283
|
+
/**
|
|
284
|
+
* True when the account cannot pay this transaction's own fee without dropping below its
|
|
285
|
+
* reserve (architecture.md §8.1): the API built it with its own fee at zero, and the client
|
|
286
|
+
* must route the signed envelope through `POST /:network/fee-bump/sponsor` before submitting
|
|
287
|
+
* it, instead of submitting it directly. Absent (not `false`) on every ordinary transaction -
|
|
288
|
+
* an older client reading this field sees nothing here and simply submits as it always has.
|
|
289
|
+
*/
|
|
290
|
+
needsSponsoredFee?: true;
|
|
150
291
|
intent: TxIntent;
|
|
151
292
|
}
|
|
152
293
|
|
|
@@ -181,6 +322,13 @@ export declare interface DecisionAnswer {
|
|
|
181
322
|
choice: string;
|
|
182
323
|
params?: {
|
|
183
324
|
maxSlippageBps?: number;
|
|
325
|
+
/**
|
|
326
|
+
* Required by `convert_to_xlm` on a Soroban token: the least XLM, in stroops, the user was
|
|
327
|
+
* shown the swap would deliver (the plan's `quote.minAmountOut`). The build refuses a route
|
|
328
|
+
* that no longer clears it (`quote_drifted`) instead of swapping at a rate nobody agreed to,
|
|
329
|
+
* and the browser holds the built swap's own minimum to at least this figure.
|
|
330
|
+
*/
|
|
331
|
+
minAmountOut?: string;
|
|
184
332
|
/**
|
|
185
333
|
* Required by the `transfer_to_account` choice: the `G...` address the balance is paid to.
|
|
186
334
|
*
|
|
@@ -210,6 +358,120 @@ export declare interface DecisionPoint {
|
|
|
210
358
|
required: boolean;
|
|
211
359
|
}
|
|
212
360
|
|
|
361
|
+
/** Keyed by asset/contract address. Built from OctoPos's queryKeys.tokenInfos. */
|
|
362
|
+
export declare interface DefiEnrichmentEntry {
|
|
363
|
+
symbol: string;
|
|
364
|
+
decimals: number;
|
|
365
|
+
usdPrice: string | null;
|
|
366
|
+
priceSource: string | null;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export declare type DefiPosition = BlendSupplyPosition | BlendBorrowPosition | AquariusLpPosition | SoroswapLpPosition | PhoenixLpPosition | PhoenixStakePosition | FxdaoCdpPosition;
|
|
370
|
+
|
|
371
|
+
declare interface DefiPositionBase {
|
|
372
|
+
protocol: DefiProtocol;
|
|
373
|
+
/** Pool, market, or vault contract this position lives in. */
|
|
374
|
+
contractAddress: string;
|
|
375
|
+
/** Human-readable view of the position, when the analysis could resolve one. */
|
|
376
|
+
display?: DefiPositionDisplay;
|
|
377
|
+
/** Left as an optional hook: the wasmHash -\> protocol-version contract registry
|
|
378
|
+
* architecture.md describes does not exist in code yet (a later contribution). */
|
|
379
|
+
wasmHash?: string;
|
|
380
|
+
usdValue: string | null;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* What a person should read about a position, in the protocol's own terms, resolved by the API
|
|
385
|
+
* from a live read at analysis time (issue #197). Presentation only: every field is nullable, a
|
|
386
|
+
* failed read leaves the whole object absent, and nothing here feeds the plan, the gate, or an
|
|
387
|
+
* exit - those re-read the ledger themselves.
|
|
388
|
+
*/
|
|
389
|
+
export declare interface DefiPositionDisplay {
|
|
390
|
+
/** The pool, pair, or vault by name (the protocol's own metadata or the registry label). */
|
|
391
|
+
pool: string | null;
|
|
392
|
+
/** Symbol of the position's asset; for an LP position the pair, e.g. "XLM/USDC". */
|
|
393
|
+
asset: string | null;
|
|
394
|
+
/** Underlying amount in the asset's own units as a decimal string - not shares or bTokens. */
|
|
395
|
+
amount: string | null;
|
|
396
|
+
/** The part of `amount` posted as collateral (lending protocols), decimal string; null when
|
|
397
|
+
* the protocol has no such distinction. */
|
|
398
|
+
collateralAmount: string | null;
|
|
399
|
+
/** Current yield as a percentage with two decimals ("3.99"): earned on a supply, paid on debt. */
|
|
400
|
+
yieldPct: string | null;
|
|
401
|
+
yieldKind: "earned" | "paid" | null;
|
|
402
|
+
/** One protocol-specific clause the line ends with, e.g. what an LP share is worth in its two
|
|
403
|
+
* tokens ("9.95 XLM + 19.90 USDC"). Null when there is nothing to add. */
|
|
404
|
+
detail?: string | null;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* The normalized DeFi position model every downstream consumer (exit adapters, plan preview)
|
|
409
|
+
* depends on - no OctoPos-specific field names beyond this boundary (architecture.md §7.1).
|
|
410
|
+
*/
|
|
411
|
+
export declare interface DefiPositionsResult {
|
|
412
|
+
address: string;
|
|
413
|
+
network: Network;
|
|
414
|
+
positions: DefiPosition[];
|
|
415
|
+
unrecognizedPositions: UnrecognizedDefiPosition[];
|
|
416
|
+
enrichment: Record<string, DefiEnrichmentEntry>;
|
|
417
|
+
/** OctoPos's own freshness/provenance signal ("snapshot" | "empty" | "cache" | "not-tracked").
|
|
418
|
+
* Passed through verbatim rather than architecture.md's described (but not actually shipped)
|
|
419
|
+
* partial_result/attribution_confidence fields - see issue #147 for the gating that consumes
|
|
420
|
+
* this. */
|
|
421
|
+
source: string;
|
|
422
|
+
timestamp: string | null;
|
|
423
|
+
queryKeys: DefiQueryKeys;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Lowercased from OctoPos's own SUPPLY/BORROW/LP/STAKE tags. FxDAO's COLLATERAL+BORROW pair is
|
|
428
|
+
* one vault - one exit unit per architecture.md §9.7 - so it collapses to a single "cdp" position
|
|
429
|
+
* carrying both legs rather than two positions. WALLET positions are out of scope: classic
|
|
430
|
+
* balances already come from AccountState.trustlines, and Soroban token balance handling is a
|
|
431
|
+
* separate Phase-2 deliverable, not this epic.
|
|
432
|
+
*/
|
|
433
|
+
export declare type DefiPositionType = "supply" | "borrow" | "lp" | "cdp" | "stake";
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Protocols LumenWipe actually knows how to exit (architecture.md §9's table). OctoPos itself
|
|
437
|
+
* indexes more than this (e.g. "untangled-vault", "stellar-wallet") - those are dropped by the
|
|
438
|
+
* adapter rather than represented here, since the type system should not claim LumenWipe can act
|
|
439
|
+
* on a protocol it has no exit path for.
|
|
440
|
+
*/
|
|
441
|
+
export declare type DefiProtocol = "blend" | "aquarius" | "soroswap" | "phoenix" | "fxdao";
|
|
442
|
+
|
|
443
|
+
export declare interface DefiQueryKeys {
|
|
444
|
+
rpcEndpoints: DefiRpcEndpoint[];
|
|
445
|
+
rpcPolicy: DefiRpcPolicy;
|
|
446
|
+
slices: Partial<Record<DefiProtocol, DefiQueryKeysSlice>>;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Ready-made ledger keys plus pool/vault metadata for one protocol, letting a caller read
|
|
451
|
+
* positions directly over RPC without OctoPos storing anything server-side (architecture.md
|
|
452
|
+
* §7.1). Passed through typed rather than discarded, since issue #148's RPC fallback needs
|
|
453
|
+
* exactly this and would otherwise have to refetch it.
|
|
454
|
+
*/
|
|
455
|
+
export declare interface DefiQueryKeysSlice {
|
|
456
|
+
protocol: string;
|
|
457
|
+
ledgerKeys: string[];
|
|
458
|
+
poolAddresses: string[];
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** A public Soroban RPC endpoint OctoPos suggests for a direct getLedgerEntries read. */
|
|
462
|
+
export declare interface DefiRpcEndpoint {
|
|
463
|
+
url: string;
|
|
464
|
+
health: string;
|
|
465
|
+
avgLatencyMs: number;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export declare interface DefiRpcPolicy {
|
|
469
|
+
maxKeysPerCall: number;
|
|
470
|
+
recommendedConcurrency: number;
|
|
471
|
+
backoffOn429Ms: number[];
|
|
472
|
+
timeoutMs: number;
|
|
473
|
+
}
|
|
474
|
+
|
|
213
475
|
export declare type DemolishPhase = "IDLE" | "ANALYZING" | "PREFLIGHT_COMPLETE" | "SIGNER_SETUP" | "STEP_EXECUTING" | "STEP_CONFIRMED" | "STEP_FAILED" | "COMPLETE" | "ABORTED";
|
|
214
476
|
|
|
215
477
|
export declare interface ExecutionTxBreakdown {
|
|
@@ -218,8 +480,21 @@ export declare interface ExecutionTxBreakdown {
|
|
|
218
480
|
reason?: "op_batch" | "defi_dependency";
|
|
219
481
|
}
|
|
220
482
|
|
|
483
|
+
/** Response from `POST /:network/fee-bump/sponsor`. */
|
|
484
|
+
export declare interface FeeBumpSponsorResponse {
|
|
485
|
+
transaction: string;
|
|
486
|
+
}
|
|
487
|
+
|
|
221
488
|
export declare type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
222
489
|
|
|
490
|
+
export declare interface FxdaoCdpPosition extends DefiPositionBase {
|
|
491
|
+
protocol: "fxdao";
|
|
492
|
+
positionType: "cdp";
|
|
493
|
+
denomination: string;
|
|
494
|
+
collateralAmount: string;
|
|
495
|
+
debtAmount: string;
|
|
496
|
+
}
|
|
497
|
+
|
|
223
498
|
/** Response from `GET /health`. */
|
|
224
499
|
export declare interface HealthResponse {
|
|
225
500
|
status: string;
|
|
@@ -233,16 +508,6 @@ export declare class InsufficientSignatureWeightError extends Error {
|
|
|
233
508
|
constructor(pending: PendingRound);
|
|
234
509
|
}
|
|
235
510
|
|
|
236
|
-
/**
|
|
237
|
-
* One operation in a decoded close transaction.
|
|
238
|
-
*
|
|
239
|
-
* `source` is the account the operation acts as - the operation's own source account when it
|
|
240
|
-
* carries one, otherwise the transaction's. It is what lets verification assert relationships
|
|
241
|
-
* *between* operations rather than trusting each in isolation: in a mediated close the forward
|
|
242
|
-
* payment must be sent by the very account the merge just paid into, which is what makes the
|
|
243
|
-
* intermediary a conduit rather than a destination. Without it the only available check is
|
|
244
|
-
* pinning the intermediary's address, which every consumer would then have to be told.
|
|
245
|
-
*/
|
|
246
511
|
export declare type IntentOperation = IntentOperationBody & {
|
|
247
512
|
source: string;
|
|
248
513
|
};
|
|
@@ -293,6 +558,33 @@ export declare type IntentOperationBody = {
|
|
|
293
558
|
type: "revoke_sponsorship";
|
|
294
559
|
entryKind: "account" | "trustline" | "offer" | "data_entry" | "signer";
|
|
295
560
|
owner: string;
|
|
561
|
+
} | {
|
|
562
|
+
type: "invoke_host_function";
|
|
563
|
+
contract: string;
|
|
564
|
+
function: string;
|
|
565
|
+
/** The decoded arguments rendered for a human, in order. */
|
|
566
|
+
args: string[];
|
|
567
|
+
/** Every Stellar account (G...) named anywhere in the arguments or in the authorization
|
|
568
|
+
* tree the signature would satisfy. A verifier insists these are all the closing account. */
|
|
569
|
+
accountsReferenced: string[];
|
|
570
|
+
/** Every contract (C...) named the same way, including nested calls the signature would
|
|
571
|
+
* authorize. A verifier insists these are contracts the account is known to deal with. */
|
|
572
|
+
contractsReferenced: string[];
|
|
573
|
+
/** Address forms that cannot be pinned to anything (muxed accounts, claimable balances,
|
|
574
|
+
* liquidity pools). A verifier refuses any. */
|
|
575
|
+
unsupportedAddressCount: number;
|
|
576
|
+
/** True when the signature would authorize more than the account's own plain contract
|
|
577
|
+
* calls: another party's credentials, or a contract creation, in the auth entries. */
|
|
578
|
+
authorizesBeyondSelf: boolean;
|
|
579
|
+
/** How deep the authorization tree nests: 0 when every entry is a single plain call with
|
|
580
|
+
* no sub-invocations, 1 when a call authorizes one level of nested calls, and so on. A
|
|
581
|
+
* token transfer must be 0 - the token may not make the account authorize anything else. */
|
|
582
|
+
authDepth: number;
|
|
583
|
+
/** Every non-root call in the authorization tree - what the root call (a pool, router, or
|
|
584
|
+
* backstop) would itself be authorized to do on the account's behalf, one level down. A
|
|
585
|
+
* DeFi exit's top-level contract/function pinning says nothing about these: a hostile
|
|
586
|
+
* build could keep a legitimate top-level call while hiding an unrelated transfer here. */
|
|
587
|
+
subInvocations: SubInvocationCall[];
|
|
296
588
|
} | {
|
|
297
589
|
type: "unknown";
|
|
298
590
|
};
|
|
@@ -331,6 +623,20 @@ export declare class LumenWipeClient {
|
|
|
331
623
|
submit(signedXdr: string, network?: Network): Promise<SubmitResponse>;
|
|
332
624
|
mediatorCheck(address: string, network?: Network): Promise<MediatorCheckResult>;
|
|
333
625
|
mediatorSign(transaction: string, network?: Network): Promise<MediatorSignResponse>;
|
|
626
|
+
/** Wraps a wind-down transaction (its own fee already zero) in a signed CAP-15 fee-bump
|
|
627
|
+
* envelope for an account that cannot pay its own fee (architecture.md §8.1). The caller
|
|
628
|
+
* submits the returned XDR through `submit()`, exactly like any other close transaction. */
|
|
629
|
+
feeBumpSponsor(transaction: string, network?: Network): Promise<FeeBumpSponsorResponse>;
|
|
630
|
+
/** Every live SEP-41 allowance the account has granted (architecture.md §12). Independent of
|
|
631
|
+
* closing an account - a standalone security utility. */
|
|
632
|
+
getAllowances(address: string, network?: Network): Promise<AllowancesResult>;
|
|
633
|
+
/** Builds the unsigned `approve(owner, spender, 0, 0)` transaction that revokes one allowance.
|
|
634
|
+
* The caller signs and submits it through `submit()`, like any other transaction here. */
|
|
635
|
+
revokeAllowance(params: {
|
|
636
|
+
owner: string;
|
|
637
|
+
token: string;
|
|
638
|
+
spender: string;
|
|
639
|
+
}, network?: Network): Promise<RevokeAllowanceResponse>;
|
|
334
640
|
}
|
|
335
641
|
|
|
336
642
|
export declare interface LumenWipeClientOptions {
|
|
@@ -395,6 +701,20 @@ export declare interface PendingRound {
|
|
|
395
701
|
requiresAnotherCall: boolean;
|
|
396
702
|
}
|
|
397
703
|
|
|
704
|
+
export declare interface PhoenixLpPosition extends DefiPositionBase {
|
|
705
|
+
protocol: "phoenix";
|
|
706
|
+
positionType: "lp";
|
|
707
|
+
shareAmount: string;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
export declare interface PhoenixStakePosition extends DefiPositionBase {
|
|
711
|
+
protocol: "phoenix";
|
|
712
|
+
positionType: "stake";
|
|
713
|
+
stakedAmount: string;
|
|
714
|
+
/** Unix seconds; unbonding requires the original stake's timestamp (architecture.md §9.6). */
|
|
715
|
+
stakedAtEpoch: string;
|
|
716
|
+
}
|
|
717
|
+
|
|
398
718
|
/** @deprecated The API emits one envelope (`StructuredApiError`). Kept only so a consumer
|
|
399
719
|
* pinned to an older deployment still type-checks during a rollout; remove once none remain. */
|
|
400
720
|
export declare interface PlainApiError {
|
|
@@ -420,7 +740,15 @@ export declare interface PlannedStep {
|
|
|
420
740
|
status: StepStatus;
|
|
421
741
|
txHash: string | null;
|
|
422
742
|
error: string | null;
|
|
743
|
+
/** What the user's own account paid for this step, once confirmed - exactly "0" when a
|
|
744
|
+
* dedicated sponsor account covered the fee-bump instead. Otherwise the plan-time estimate
|
|
745
|
+
* copied forward: the close-engine's confirmation callback carries only a tx hash, not the
|
|
746
|
+
* fee Horizon actually charged, so this cannot correct for surge pricing. Absent until the
|
|
747
|
+
* step is confirmed. */
|
|
748
|
+
actualFeeLumens?: string;
|
|
423
749
|
affectedAsset?: string;
|
|
750
|
+
/** The pool, pair, or vault an EXIT_POSITIONS step leaves. */
|
|
751
|
+
affectedContract?: string;
|
|
424
752
|
fallbackToIssuer?: boolean;
|
|
425
753
|
}
|
|
426
754
|
|
|
@@ -455,6 +783,11 @@ export declare interface QuoteInfo {
|
|
|
455
783
|
expiresAtLedger: number;
|
|
456
784
|
}
|
|
457
785
|
|
|
786
|
+
/** Response from `POST /:network/allowances/revoke`. */
|
|
787
|
+
export declare interface RevokeAllowanceResponse {
|
|
788
|
+
transaction: string;
|
|
789
|
+
}
|
|
790
|
+
|
|
458
791
|
/**
|
|
459
792
|
* Runs the full multi-round close. Each round: fetch a batch of unsigned transactions,
|
|
460
793
|
* verify every one before signing, sign it, and submit only once its accumulated signing
|
|
@@ -465,6 +798,60 @@ export declare interface QuoteInfo {
|
|
|
465
798
|
*/
|
|
466
799
|
export declare function runClose(deps: CloseEngineDeps, resume?: PendingRound): Promise<void>;
|
|
467
800
|
|
|
801
|
+
/** A SEP-41 token balance the account holds in a contract's storage - not a classic trustline. */
|
|
802
|
+
export declare interface SorobanTokenBalance {
|
|
803
|
+
/** The token contract, `C...`. */
|
|
804
|
+
contract: string;
|
|
805
|
+
/** Base units, integer string, as `balance(account)` reports it on the ledger. "0" only for a
|
|
806
|
+
* token the account does not hold yet but a detected position's exit will pay out. */
|
|
807
|
+
balance: string;
|
|
808
|
+
/** From the contract's own `symbol()` / `decimals()`, null when it does not answer them. */
|
|
809
|
+
symbol: string | null;
|
|
810
|
+
decimals: number | null;
|
|
811
|
+
/** Every source that proposed this contract; the balance itself always comes from the ledger. */
|
|
812
|
+
sources: SorobanTokenSource[];
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/** How one candidate source fared, so the interface can say exactly what was consulted. */
|
|
816
|
+
export declare interface SorobanTokenCoverage {
|
|
817
|
+
source: SorobanTokenSource;
|
|
818
|
+
status: "ok" | "failed" | "skipped";
|
|
819
|
+
detail?: string;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/** Where a Soroban token candidate came from before its balance was confirmed on the ledger. */
|
|
823
|
+
export declare type SorobanTokenSource = "explorer" | "positions" | "list" | "events" | "manual";
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Soroban token balances the account holds directly. Soroban has no per-account token index, so
|
|
827
|
+
* this is a best-effort union of candidate sources - an explorer, the tokens named by detected
|
|
828
|
+
* positions, bundled lists, recent on-chain `transfer`/`mint` events, and contracts the user added
|
|
829
|
+
* by hand - each confirmed by reading `balance(account)` on the ledger. What could not be read is
|
|
830
|
+
* listed, never dropped; classic assets' contracts are excluded (their balance is the trustline).
|
|
831
|
+
*/
|
|
832
|
+
export declare interface SorobanTokensResult {
|
|
833
|
+
tokens: SorobanTokenBalance[];
|
|
834
|
+
/** Candidate contracts whose balance could not be read (a hostile, broken, or archived token). */
|
|
835
|
+
unreadable: string[];
|
|
836
|
+
coverage: SorobanTokenCoverage[];
|
|
837
|
+
/** The ledger range the event scan covered, or null when it ran out of budget before starting. */
|
|
838
|
+
eventsScanned: {
|
|
839
|
+
fromLedger: number;
|
|
840
|
+
toLedger: number;
|
|
841
|
+
} | null;
|
|
842
|
+
/** Plain-language warnings for the plan: a source that failed, contracts that could not be read. */
|
|
843
|
+
warnings: PlanBlocker[];
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
export declare interface SoroswapLpPosition extends DefiPositionBase {
|
|
847
|
+
protocol: "soroswap";
|
|
848
|
+
positionType: "lp";
|
|
849
|
+
shareAmount: string;
|
|
850
|
+
/** The pair's two token contracts (token_0, token_1), read from the pair when detection can;
|
|
851
|
+
* what a withdrawal receives and the exit's arguments name. */
|
|
852
|
+
tokens?: [string, string];
|
|
853
|
+
}
|
|
854
|
+
|
|
468
855
|
/**
|
|
469
856
|
* A ledger entry this account currently sponsors, on another account (or itself, for
|
|
470
857
|
* "account" - a fully-sponsored account creation). Mirrors the ledger-key kinds
|
|
@@ -497,7 +884,7 @@ export declare type SponsoredEntry = {
|
|
|
497
884
|
|
|
498
885
|
export declare type StepStatus = "pending" | "signing" | "submitted" | "confirmed" | "failed" | "skipped";
|
|
499
886
|
|
|
500
|
-
export declare type StepType = "NORMALIZE_SIGNERS" | "REVOKE_SPONSORSHIP" | "REMOVE_DATA_ENTRIES" | "CANCEL_OFFERS" | "ADD_TRUSTLINE_FOR_CLAIM" | "CLAIM_BALANCES" | "HANDLE_ASSETS" | "REMOVE_TRUSTLINES" | "CLOSE_ACCOUNT" | "MERGE";
|
|
887
|
+
export declare type StepType = "NORMALIZE_SIGNERS" | "REVOKE_SPONSORSHIP" | "REMOVE_DATA_ENTRIES" | "CANCEL_OFFERS" | "ADD_TRUSTLINE_FOR_CLAIM" | "CLAIM_BALANCES" | "EXIT_POSITIONS" | "HANDLE_ASSETS" | "REMOVE_TRUSTLINES" | "CLOSE_ACCOUNT" | "MERGE";
|
|
501
888
|
|
|
502
889
|
/** Structured error body used by the v1 (`/v1/...`) endpoints. */
|
|
503
890
|
export declare interface StructuredApiError {
|
|
@@ -508,6 +895,26 @@ export declare interface StructuredApiError {
|
|
|
508
895
|
};
|
|
509
896
|
}
|
|
510
897
|
|
|
898
|
+
/**
|
|
899
|
+
* One operation in a decoded close transaction.
|
|
900
|
+
*
|
|
901
|
+
* `source` is the account the operation acts as - the operation's own source account when it
|
|
902
|
+
* carries one, otherwise the transaction's. It is what lets verification assert relationships
|
|
903
|
+
* *between* operations rather than trusting each in isolation: in a mediated close the forward
|
|
904
|
+
* payment must be sent by the very account the merge just paid into, which is what makes the
|
|
905
|
+
* intermediary a conduit rather than a destination. Without it the only available check is
|
|
906
|
+
* pinning the intermediary's address, which every consumer would then have to be told.
|
|
907
|
+
*/
|
|
908
|
+
/** One non-root call in a Soroban authorization tree: what a DeFi exit's own contract (a pool,
|
|
909
|
+
* router, or backstop) would itself be authorized to call on the account's behalf. */
|
|
910
|
+
export declare interface SubInvocationCall {
|
|
911
|
+
contract: string;
|
|
912
|
+
function: string;
|
|
913
|
+
/** The decoded arguments rendered for a human, in order - same rendering as the top-level
|
|
914
|
+
* invocation's own `args`. */
|
|
915
|
+
args: string[];
|
|
916
|
+
}
|
|
917
|
+
|
|
511
918
|
/** Body for `POST /v1/:network/submit`. */
|
|
512
919
|
export declare interface SubmitRequest {
|
|
513
920
|
signedXdr: string;
|
|
@@ -574,4 +981,17 @@ export declare interface TxIntent {
|
|
|
574
981
|
operations: IntentOperation[];
|
|
575
982
|
}
|
|
576
983
|
|
|
984
|
+
/**
|
|
985
|
+
* A position tagged with a supported protocol whose shape the adapter could not validate. Kept
|
|
986
|
+
* distinct from "no position" so a caller (issue #147's gating) can surface it rather than treat
|
|
987
|
+
* a parse failure as an account with nothing to unwind - the "no silent skips" invariant applied
|
|
988
|
+
* to a provider field OctoPos does not formally type.
|
|
989
|
+
*/
|
|
990
|
+
export declare interface UnrecognizedDefiPosition {
|
|
991
|
+
protocol: DefiProtocol;
|
|
992
|
+
/** OctoPos's raw type tag (e.g. "SUPPLY"), kept for diagnostics even though it didn't parse. */
|
|
993
|
+
rawType: string;
|
|
994
|
+
reason: string;
|
|
995
|
+
}
|
|
996
|
+
|
|
577
997
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -116,6 +116,31 @@ var LumenWipeClient = class {
|
|
|
116
116
|
transaction
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
|
+
/** Wraps a wind-down transaction (its own fee already zero) in a signed CAP-15 fee-bump
|
|
120
|
+
* envelope for an account that cannot pay its own fee (architecture.md §8.1). The caller
|
|
121
|
+
* submits the returned XDR through `submit()`, exactly like any other close transaction. */
|
|
122
|
+
feeBumpSponsor(transaction, network = this.defaultNetwork) {
|
|
123
|
+
return this.http.request("POST", `/${network}/fee-bump/sponsor`, {
|
|
124
|
+
transaction
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/** Every live SEP-41 allowance the account has granted (architecture.md §12). Independent of
|
|
128
|
+
* closing an account - a standalone security utility. */
|
|
129
|
+
getAllowances(address, network = this.defaultNetwork) {
|
|
130
|
+
return this.http.request(
|
|
131
|
+
"GET",
|
|
132
|
+
`/${network}/allowances/${encodeURIComponent(address)}`
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
/** Builds the unsigned `approve(owner, spender, 0, 0)` transaction that revokes one allowance.
|
|
136
|
+
* The caller signs and submits it through `submit()`, like any other transaction here. */
|
|
137
|
+
revokeAllowance(params, network = this.defaultNetwork) {
|
|
138
|
+
return this.http.request(
|
|
139
|
+
"POST",
|
|
140
|
+
`/${network}/allowances/revoke`,
|
|
141
|
+
params
|
|
142
|
+
);
|
|
143
|
+
}
|
|
119
144
|
};
|
|
120
145
|
|
|
121
146
|
// src/close-engine.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumenwipe/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Typed fetch client for the LumenWipe API - non-custodial Stellar account closing.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -41,18 +41,20 @@
|
|
|
41
41
|
"account-merge"
|
|
42
42
|
],
|
|
43
43
|
"scripts": {
|
|
44
|
-
"build": "bun run
|
|
44
|
+
"build": "bun run build:types && api-extractor run --local && cp dist/index.d.ts dist/index.d.cts",
|
|
45
|
+
"build:types": "bun run --filter '@lumenwipe/types' build && tsup src/index.ts --format esm,cjs --clean && tsc -p tsconfig.build.json",
|
|
46
|
+
"check-api": "api-extractor run",
|
|
45
47
|
"type-check": "tsc --noEmit && tsc -p tests/tsconfig.json --noEmit",
|
|
46
48
|
"lint": "eslint src",
|
|
47
49
|
"test": "bun test tests"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
50
|
-
"@microsoft/api-extractor": "^7.
|
|
51
|
-
"@types/bun": "^1.
|
|
52
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
53
|
-
"@typescript-eslint/parser": "^8.
|
|
52
|
+
"@microsoft/api-extractor": "^7.59.0",
|
|
53
|
+
"@types/bun": "^1.4.0",
|
|
54
|
+
"@typescript-eslint/eslint-plugin": "^8.69.0",
|
|
55
|
+
"@typescript-eslint/parser": "^8.69.0",
|
|
54
56
|
"eslint": "^8.57.1",
|
|
55
|
-
"tsup": "^8.
|
|
57
|
+
"tsup": "^8.5.1",
|
|
56
58
|
"typescript": "^5.9.3",
|
|
57
59
|
"@lumenwipe/types": "workspace:*"
|
|
58
60
|
}
|