@lumenwipe/sdk 0.8.0 → 0.9.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/CHANGELOG.md +382 -0
- package/LICENSE +201 -0
- package/README.md +99 -12
- package/dist/index.cjs +485 -58
- package/dist/index.d.cts +606 -22
- package/dist/index.d.ts +606 -22
- package/dist/index.js +470 -57
- package/package.json +34 -16
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@lumenwipe/sdk` are documented here. Format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows
|
|
5
|
+
[Semantic Versioning](https://semver.org/). See [`RELEASING.md`](../../RELEASING.md) for how a
|
|
6
|
+
release is cut.
|
|
7
|
+
|
|
8
|
+
Versions 0.4.0 to 0.6.0 were cut in the repository but never published to npm; each says which
|
|
9
|
+
published release first contains it. There was never a 0.3.x release: 0.3.0 was only a working
|
|
10
|
+
version number before 0.4.0. Neither has a git tag.
|
|
11
|
+
|
|
12
|
+
## [Unreleased]
|
|
13
|
+
|
|
14
|
+
## [0.9.0] - 2026-11-08
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `client.batchPlan(body, network?)` for `POST /v1/{network}/close/batch-plan`: up to 20
|
|
19
|
+
accounts planned into one shared destination, read-only. Retried like the other stateless
|
|
20
|
+
posts. New type `BatchPlanRequest`.
|
|
21
|
+
- `client.getExchangeRegistry()` for `GET /v1/config/exchange-registry`, retried like the other
|
|
22
|
+
reads. New types `ServedExchangeRegistry` and `ExchangeRegistryEntry`.
|
|
23
|
+
- `client.healthDeep()` for `GET /health/deep`. A degraded service answers 503, thrown as a
|
|
24
|
+
`LumenWipeApiError` whose `body` is the `HealthDeepResponse` with `status: "error"`; it is never
|
|
25
|
+
retried. New types `HealthDeepResponse` and `HealthDeepIndicator`.
|
|
26
|
+
- `client.getStats(network?)`, `client.getStatsFeed(network?)` and
|
|
27
|
+
`client.recordMerge(txHash, network?)` for the `/v1/{network}/stats` routes. New type
|
|
28
|
+
`RecordMergeRequest`.
|
|
29
|
+
- `LumenWipeIntegratorClient`, a separate entry point for a wallet's own API keys: `challenge`,
|
|
30
|
+
`session`, `listKeys`, `createKey(token, { label?, networks? })`, `revokeKey` and `rotateKey`.
|
|
31
|
+
It takes no API key and never sends one; the key calls send only the session token, and a key
|
|
32
|
+
id is percent-encoded. Creating, revoking and rotating a key are never retried. New types
|
|
33
|
+
`LumenWipeIntegratorClientOptions`, `IntegratorChallengeResponse`, `IntegratorSessionRequest`,
|
|
34
|
+
`IntegratorSessionResponse`, `CreateIntegratorKeyRequest`, `IntegratorKeyRecord`,
|
|
35
|
+
`IntegratorKeyListEntry`, `IntegratorKeyUsage`, `IntegratorOwnerUsage`, `IntegratorKeyList`,
|
|
36
|
+
`IssuedIntegratorKey` and `RevokedIntegratorKey`.
|
|
37
|
+
|
|
38
|
+
- The error codes `key_network_not_allowed` (403: the API key is limited to other networks),
|
|
39
|
+
`invalid_label` and `invalid_networks` (400, from `POST /v1/integrator/keys`). Types only; no
|
|
40
|
+
runtime change.
|
|
41
|
+
- `client.closeDelivered(destination, hashes, network?)`: the XLM confirmed close transactions
|
|
42
|
+
delivered to `destination`, read by the API from each transaction's ledger result. An entry
|
|
43
|
+
that cannot be read as delivered comes back as `unavailable` with its `reason`, never thrown,
|
|
44
|
+
and `totalStroops` is set only when every entry is `delivered`. Retried like the other reads.
|
|
45
|
+
- The types `CloseDeliveredResponse` and `CloseDeliveredEntry`, for
|
|
46
|
+
`GET /v1/{network}/close/delivered`: the XLM confirmed close transactions delivered to their
|
|
47
|
+
destination, one entry per hash, with `totalStroops` only when every entry is `delivered`.
|
|
48
|
+
Types only; no runtime change.
|
|
49
|
+
- `runClose` takes an optional `onProgressEvent(event)`. It is told each step of the close: a
|
|
50
|
+
`preparing` event before each round is fetched, then `verifying`, `awaiting-signature`,
|
|
51
|
+
`submitting` and `confirmed` for each transaction, carrying `round`, `txIndex`, `txCount`,
|
|
52
|
+
`covers` and `moreRoundsExpected`. Each event is a fresh object, and a callback that throws or
|
|
53
|
+
rejects cannot stop the close. `onProgress` messages are unchanged. New types
|
|
54
|
+
`CloseProgressEvent`, `CloseProgressPhase`, `CloseRoundProgress` and
|
|
55
|
+
`CloseTransactionProgress`. `PendingRound` gains optional `round`, `txIndex` and `txCount`, set
|
|
56
|
+
by `runClose`, so a resumed close keeps its numbering.
|
|
57
|
+
- `CloseTransactionsRequest.memoType` (`"text"` or `"id"`): the type of `memo`. A destination the
|
|
58
|
+
exchange registry does not list uses it, `text` when omitted; a listed exchange keeps the
|
|
59
|
+
registry's type and answers `422 invalid_memo` with `details.memoType` when another is named.
|
|
60
|
+
An unknown value is `400 invalid_body` and `"hash"` is `422 unsupported_memo_type`. An id memo
|
|
61
|
+
with a leading zero is now `422 invalid_memo`: the network would keep only the number. Types
|
|
62
|
+
only; no runtime change.
|
|
63
|
+
- `PhoenixLpPosition.shareToken` and `FxdaoCdpPosition.debtToken`: the contract of the token a
|
|
64
|
+
position's exit moves, read from the pool's `CONFIG` and the vault's currency. Types only; no
|
|
65
|
+
runtime change.
|
|
66
|
+
- The types `TokenQuoteFlag` and `TokenUnquotedReason` are exported, with the error code
|
|
67
|
+
`conversion_impact_not_acknowledged`. A Soroban token's `subject.quote` carries `priceImpactBps`,
|
|
68
|
+
`flags` and an optional `runnerUp`; a flagged conversion is not recommended and needs its
|
|
69
|
+
`conversion_impact:<contract>` decision answered `acknowledged` with the convert answer's
|
|
70
|
+
`params.minAmountOut`. A token with no quote carries `subject.reason`. Types only; no runtime
|
|
71
|
+
change.
|
|
72
|
+
- The type `ClassicConversionQuote` is exported: the `quote` a convertible classic asset's
|
|
73
|
+
`asset_disposition` subject already carries (`estimatedReceive` and `minAmountOut`, in stroops).
|
|
74
|
+
Types only; no runtime change.
|
|
75
|
+
- `runClose` takes an opt-in `reconcile` and a `prepare` step. With them, an unknown submit outcome
|
|
76
|
+
is settled by the hash the client computed: the same bytes are sent again at most
|
|
77
|
+
`SUBMIT_RESEND_ATTEMPTS` (2) times, then the hash is looked up, then `CloseOutcomeUnknownError`
|
|
78
|
+
carries a submission to pass back as `reconcile.unresolved`. `CloseTransactionFailedError` reports
|
|
79
|
+
a failure on the ledger. `resolveSubmission`, `isSubmitRefused` and `submissionClosesAccount` are
|
|
80
|
+
exported. Without `reconcile`, nothing is sent twice. `client.submit` is still never retried.
|
|
81
|
+
- `DemolishPhase` gains `STEP_UNCONFIRMED`.
|
|
82
|
+
- `client.getTransaction(hash)` looks a transaction up by hash without sending anything, and
|
|
83
|
+
`client.closeStatus(source)` reports a close's phase and remaining work from live state. Both
|
|
84
|
+
are retried like every other read. `closed` from `closeStatus` is informational: it never proves
|
|
85
|
+
that a given close finished.
|
|
86
|
+
- The types `SubmitPendingDetails`, `TransactionLookupResponse`, `CloseStatusResponse` and
|
|
87
|
+
`CloseStatusRemaining` are exported.
|
|
88
|
+
- Error code `state_changed` (409) from `close/transactions` and `close/plan`: the account changed
|
|
89
|
+
between the API's read and its build, so nothing was built. Plan again.
|
|
90
|
+
- `runClose` fetches a round refused as `state_changed` again, at most `STATE_CHANGED_REFETCHES`
|
|
91
|
+
(2) times, each after waiting `STATE_CHANGED_REFETCH_DELAY_MS` (3000 ms, about one ledger
|
|
92
|
+
close), since each call re-reads the account and a read provider can lag a transaction that just
|
|
93
|
+
confirmed. `CloseEngineDeps.sleep` replaces the timer, for tests. If it is still refused, `runClose` throws the
|
|
94
|
+
new `CloseStateChangedError`: nothing was submitted for that round, so plan again and run the
|
|
95
|
+
close from the new plan.
|
|
96
|
+
- `CloseTransactionsRequest.planHash` and `CloseEngineDeps.planHash`: the hash of the plan the
|
|
97
|
+
user reviewed. `close/transactions` answers `409 state_changed` when the account's sequence or
|
|
98
|
+
the answers differ from those the plan was built from, and `400 invalid_plan_hash` when it is not a 64-character hex string. `runClose`
|
|
99
|
+
sends it until the first transaction of the run confirms and never after, and does not fetch a
|
|
100
|
+
round again that was refused against it.
|
|
101
|
+
- `getTransactions` now receives `{ planHash }`; a function that takes no argument still works.
|
|
102
|
+
- `AccountState.snapshotLedger`: the latest ledger the account read reflects, when the provider
|
|
103
|
+
reports one.
|
|
104
|
+
- `ErrorCode` gains `time_bounds_required` and `transaction_expired`, returned by the mediator
|
|
105
|
+
co-sign and the fee sponsor for an envelope with no expiry, too long a validity or one that has
|
|
106
|
+
expired; `sponsor_source_unusable`, returned by the fee sponsor when the inner transaction is
|
|
107
|
+
not the next one of an existing account; and `sponsorship_budget_exhausted` (429), returned by
|
|
108
|
+
the fee sponsor once a daily budget is spent.
|
|
109
|
+
- `TransactionsResponse.sourceAccount`: the closing account's signers and thresholds as read at
|
|
110
|
+
the start of that round, the read its transactions were built from. A transaction can remove
|
|
111
|
+
signers and lower thresholds, so judge signing weight against it, with each confirmed
|
|
112
|
+
`SetOptions` of the round applied on top, rather than against an earlier read.
|
|
113
|
+
- Error code `close_fee_balance_short` (422) and the same plan blocker: the account lacks the XLM
|
|
114
|
+
above its reserve to pay the fees of the steps no sponsor can cover (Soroban rounds, the exchange
|
|
115
|
+
merge, and any transaction the sponsor would not accept or when no sponsor is configured). It is
|
|
116
|
+
raised before such a round is built, and the message states how much XLM to add.
|
|
117
|
+
- `AccountState.numSponsored`: the reserves another account pays for this one. It lowers the
|
|
118
|
+
minimum balance used to judge fees.
|
|
119
|
+
- `CloseDidNotConvergeError`, thrown by `runClose` instead of a bare `Error` when a close cannot
|
|
120
|
+
finish. It carries `rounds`, `bound` and `reason` (`round_limit` or `empty_batch`).
|
|
121
|
+
- Error code `claimable_balance_not_claimable_now` (422): a balance answered `claim` or
|
|
122
|
+
`add_trustline_then_claim` can no longer be claimed in this close because its claim window has
|
|
123
|
+
closed or has not opened. Plan again.
|
|
124
|
+
- Error code `claimable_balance_reserve_short` (422) and the same plan blocker: the account lacks the
|
|
125
|
+
XLM above its reserve to add the trustlines a claim needs, and the message states the shortfall.
|
|
126
|
+
An unanswered balance of that kind is no longer offered `add_trustline_then_claim`; its decision
|
|
127
|
+
carries only `forfeit` with the shortfall in the note. Several balances of one asset need one
|
|
128
|
+
new reserve.
|
|
129
|
+
- Error code `claimable_balances_too_many` (422) and the same plan blocker: the account holds more
|
|
130
|
+
claimable balances than one read returns and the ones left unclaimed fill it, so the rest cannot
|
|
131
|
+
be reached and the account is not closed.
|
|
132
|
+
- Optional decision `claim_bulk:forfeit_unclaimable` (type `choice`, never required), offered when
|
|
133
|
+
two or more balances cannot be claimed now. Answering `forfeit_unclaimable` forfeits every such
|
|
134
|
+
balance that has no answer of its own; it never touches a balance claimable now.
|
|
135
|
+
- Claimable-balance decision `subject.claimableFromEpoch`: when a balance is claimable later, the
|
|
136
|
+
epoch seconds from which it can be claimed, otherwise null.
|
|
137
|
+
|
|
138
|
+
### Changed
|
|
139
|
+
|
|
140
|
+
- The package declares `engines.node` `>=22` (Node 18 and 20 are end-of-life and untested) and
|
|
141
|
+
`sideEffects: false`, and ships its `LICENSE` (Apache-2.0) and this `CHANGELOG.md`. TypeScript
|
|
142
|
+
consumers need 4.7 or later, with `moduleResolution` set to `node16`, `nodenext` or `bundler`.
|
|
143
|
+
- `getAccount`, `getPaths`, `getAllowances`, `revokeAllowance`, `mediatorCheck`, `mediatorSign`
|
|
144
|
+
and `feeBumpSponsor` call their `/v1/{network}/...` paths. The SDK no longer calls any legacy
|
|
145
|
+
unversioned path; those answer with `Deprecation` and `Sunset` headers until 2027-06-01.
|
|
146
|
+
Request bodies and headers are unchanged. The network segment is percent-encoded after it is
|
|
147
|
+
checked.
|
|
148
|
+
- `runClose` resolves with `{ mergeConfirmed }` instead of `undefined`. It is true only with
|
|
149
|
+
`reconcile`, for a transaction the client parsed as a merge and saw confirmed under its own hash.
|
|
150
|
+
Without `reconcile` it is always false: a caller must establish the merge itself, because `covers`
|
|
151
|
+
is API metadata.
|
|
152
|
+
- `submit_rejected` is `422` instead of `502`, and `mediator_key_misconfiguration` is `503` instead
|
|
153
|
+
of `500`. `isApiErrorCode` is unaffected; anything branching on the status is not.
|
|
154
|
+
- `confirmation_timeout` arrives within about 35 seconds rather than 90 and carries `details` with
|
|
155
|
+
`status: "pending"` and the `hash`. It stays an error on purpose: a client that reads `hash` from
|
|
156
|
+
a success must never count a pending transaction as confirmed.
|
|
157
|
+
- `submit_failed` carries `details.hash` once the API has tried to send.
|
|
158
|
+
- `mediatorSign` and `feeBumpSponsor` now refuse an envelope that does not expire within 330
|
|
159
|
+
seconds. Envelopes from `close/transactions` already do; an integration that builds its own
|
|
160
|
+
must set a time bound.
|
|
161
|
+
- Fee affordability counts the XLM held by open offers selling XLM as unavailable, as the network
|
|
162
|
+
does, so a transaction that would otherwise be rejected for insufficient balance is flagged
|
|
163
|
+
`needsSponsoredFee` instead.
|
|
164
|
+
- A transaction is flagged `needsSponsoredFee` only when the fee sponsor is configured and would
|
|
165
|
+
accept its operations; otherwise the build is refused with `close_fee_balance_short`.
|
|
166
|
+
- The trustline reserve shortfall for a claim counts the claim round's fees as the account's own,
|
|
167
|
+
since no sponsor pays for a round that opens a trustline.
|
|
168
|
+
- Declarations are now emitted by the TypeScript 6 compiler, so an optional parameter typed
|
|
169
|
+
`unknown` (the `reason` of `CloseDidNotConvergeError`) is written `unknown` instead of
|
|
170
|
+
`unknown | undefined`. The two are the same type, and no runtime code changed.
|
|
171
|
+
- `runClose` derives its round bound from the API's `remaining.steps` (rounds done, plus steps
|
|
172
|
+
left, plus a margin of 5), recomputed every round and capped at 200, instead of a fixed 25. An
|
|
173
|
+
explicit `maxRounds` still overrides it. A close with many claimable balances or token transfers
|
|
174
|
+
no longer stops early.
|
|
175
|
+
- `runClose` stops on the first response that asks for another call but carries no transactions.
|
|
176
|
+
- `close/transactions` refuses (422 `claimable_balance_not_claimable_now`) instead of building the
|
|
177
|
+
merge when a claimable balance still on-chain is neither answered `forfeit` nor part of the claim
|
|
178
|
+
round: an answer that does not fit what the account can do with it (`claim` for a balance that
|
|
179
|
+
needs a trustline, `add_trustline_then_claim` for one that does not), a balance that closed since
|
|
180
|
+
the plan, or one with no answer. The bulk forfeit is not offered or applied while the ledger time
|
|
181
|
+
is unknown.
|
|
182
|
+
|
|
183
|
+
- Accounts with many claimable balances close in batches. The read returns up to 1500 balances
|
|
184
|
+
(it used to refuse above 1000), each claim round claims at most 100 and reports
|
|
185
|
+
`requiresAnotherCall`, and the merge is only built once a read finds nothing left to claim and
|
|
186
|
+
nothing beyond the read.
|
|
187
|
+
|
|
188
|
+
- A claimable balance whose own claim predicate is false at the ledger close time (an expired
|
|
189
|
+
`abs_before`, a future `not(before)`, an expired `rel_before`) is no longer defaulted to `claim`.
|
|
190
|
+
Its decision offers only `forfeit` with no default and states the date from which it becomes
|
|
191
|
+
claimable, and it is left out of the claim round. A predicate that is about to expire within the
|
|
192
|
+
transaction window counts as closed. If the ledger time cannot be read, only unconditional
|
|
193
|
+
claims count as claimable.
|
|
194
|
+
|
|
195
|
+
### Fixed
|
|
196
|
+
|
|
197
|
+
- Every client method that takes a network rejects with the new `LumenWipeInvalidNetworkError`,
|
|
198
|
+
with no request made, when the network is not `"mainnet"` or `"testnet"`. This includes a
|
|
199
|
+
`network` client option and an empty string, which used to fall back to the default network.
|
|
200
|
+
|
|
201
|
+
## [0.8.0] - 2026-10-12
|
|
202
|
+
|
|
203
|
+
### Added
|
|
204
|
+
|
|
205
|
+
- Plan blocker and error code `route_lookup_unavailable` (retryable): the swap route lookup failed,
|
|
206
|
+
so the asset was not classified. It is distinct from an asset with no route. `close/transactions`
|
|
207
|
+
reports a failed lookup as 503 `service_unavailable`, and `quote_drifted` only when the route
|
|
208
|
+
was confirmed gone.
|
|
209
|
+
- Asset decision `subject.reason`: `dust_below_minimum` when a market exists but the balance would
|
|
210
|
+
receive nothing once slippage is applied. It is absent for an asset with no market.
|
|
211
|
+
|
|
212
|
+
### Changed
|
|
213
|
+
|
|
214
|
+
- Asset decision points no longer carry `default: "return_to_issuer"`. An asset with no swap route,
|
|
215
|
+
or a balance too small to swap, has an empty `default` and needs an explicit answer; an
|
|
216
|
+
unanswered decision is refused with `needs_decisions`. A convertible asset still defaults to
|
|
217
|
+
`convert_to_xlm`. Returning an asset to its issuer is never recommended or applied automatically.
|
|
218
|
+
A caller that echoed `default` back as its answer for an asset with no route is now asked for a
|
|
219
|
+
decision.
|
|
220
|
+
- A price source answer that is not a well-formed list of routes, and a rejected lookup, is a
|
|
221
|
+
failed lookup rather than "no route".
|
|
222
|
+
|
|
223
|
+
## [0.7.0] - 2026-10-12
|
|
224
|
+
|
|
225
|
+
### Added
|
|
226
|
+
|
|
227
|
+
- Closing an account that issued assets still held by other accounts now needs an explicit
|
|
228
|
+
acknowledgement. `close/plan` returns a `confirmation` decision point with id
|
|
229
|
+
`issuer_supply:<address>` and the counts in its `subject`, plus a plan blocker with the code
|
|
230
|
+
`issuer_supply_not_acknowledged` until it is answered with the choice
|
|
231
|
+
`stranding_holders_acknowledged`. `close/transactions` refuses with the same error code (422)
|
|
232
|
+
without the answer.
|
|
233
|
+
- Error code `issuer_read_failed` (503, retry): the account's issued assets could not be read.
|
|
234
|
+
It is never reported as "issues nothing".
|
|
235
|
+
|
|
236
|
+
## [0.6.0] - 2026-10-12
|
|
237
|
+
|
|
238
|
+
Not published to npm; first available in 0.7.0.
|
|
239
|
+
|
|
240
|
+
### Added
|
|
241
|
+
|
|
242
|
+
- `Trustline` gains `authorization` (`"authorized" | "maintain_liabilities" | "unauthorized"`) and
|
|
243
|
+
`clawbackEnabled`. `authorized` stays and is true only when `authorization` is `"authorized"`.
|
|
244
|
+
Asset decision points carry both on their `subject` when the account holds the trustline.
|
|
245
|
+
- Error code `trustline_maintain_liabilities_with_balance`, also the `code` of the plan blocker for
|
|
246
|
+
a line its issuer limited to keeping existing offers, which holds a balance.
|
|
247
|
+
|
|
248
|
+
### Changed
|
|
249
|
+
|
|
250
|
+
- The plan blocker for an unauthorized line holding a balance now carries the stable `code`
|
|
251
|
+
`trustline_deauthorized_with_balance` instead of the generic `plan_blocker`. Its message is
|
|
252
|
+
unchanged.
|
|
253
|
+
- An account read whose credit balances omit `is_authorized` (or `is_authorized_to_maintain_liabilities`
|
|
254
|
+
on a line that is not authorized) now fails with the retryable `provider_response_unusable`
|
|
255
|
+
instead of reading as authorized. `close/transactions` reports it as 502 `provider_response_unusable`
|
|
256
|
+
rather than a 500 `transactions_failed`.
|
|
257
|
+
|
|
258
|
+
## [0.5.1] - 2026-10-10
|
|
259
|
+
|
|
260
|
+
### Added
|
|
261
|
+
|
|
262
|
+
- `StructuredApiError.error` gains an optional `requestId`: every API error body now carries the
|
|
263
|
+
id of the request, the same value as the `x-request-id` response header that
|
|
264
|
+
`LumenWipeApiError.requestId` already reads. Quote it when reporting a problem. Purely additive.
|
|
265
|
+
|
|
266
|
+
## [0.5.0] - 2026-10-10
|
|
267
|
+
|
|
268
|
+
Not published to npm; first available in 0.5.1.
|
|
269
|
+
|
|
270
|
+
### Changed
|
|
271
|
+
|
|
272
|
+
- **Breaking:** `PlanResponse.execution.estimatedTransactionCount` is now `number | null`. It is
|
|
273
|
+
counted with the splitter the builder packs transactions with, so it is no longer always `1`:
|
|
274
|
+
an exchange destination, claimable balances, Soroban token moves and a close over 100
|
|
275
|
+
operations each add transactions, and `execution.transactions` lists them with the plan steps
|
|
276
|
+
each `covers`. It is `null`, with `transactions` empty, when the count cannot be known yet: a
|
|
277
|
+
DeFi exit in the plan, a held token with no decision, or no destination. Anyone who reads the
|
|
278
|
+
field as a number (arithmetic, `toFixed`, a `number` annotation, displaying it) must handle
|
|
279
|
+
`null` first and must not show an unknown count as a figure.
|
|
280
|
+
|
|
281
|
+
## [0.4.2] - 2026-10-10
|
|
282
|
+
|
|
283
|
+
Not published to npm; first available in 0.5.1.
|
|
284
|
+
|
|
285
|
+
### Added
|
|
286
|
+
|
|
287
|
+
- `ErrorCode` gains `merge_destination_unusable`, `source_sequence_too_far` and
|
|
288
|
+
`destination_read_failed`: a close whose merge destination is the closing account, a LumenWipe
|
|
289
|
+
service account or an unfunded account, or whose source sequence number is beyond what the
|
|
290
|
+
network accepts, is now refused with a 422 before any transaction is built; an unreadable
|
|
291
|
+
destination is a retryable 503. Purely additive.
|
|
292
|
+
|
|
293
|
+
## [0.4.1] - 2026-10-10
|
|
294
|
+
|
|
295
|
+
Not published to npm; first available in 0.5.1.
|
|
296
|
+
|
|
297
|
+
### Added
|
|
298
|
+
|
|
299
|
+
- `MediatorCheckResult.registryFresh`: whether the exchange registry is inside its verification
|
|
300
|
+
window, so a client learns of staleness before an exchange close is refused.
|
|
301
|
+
|
|
302
|
+
## [0.4.0] - 2026-10-10
|
|
303
|
+
|
|
304
|
+
Not published to npm; first available in 0.5.1.
|
|
305
|
+
|
|
306
|
+
### Removed
|
|
307
|
+
|
|
308
|
+
- **Breaking:** the deprecated `PlainApiError` type, and with it the `ApiErrorBody` union member.
|
|
309
|
+
`ApiErrorBody` is now just `StructuredApiError`; every API error already used that envelope.
|
|
310
|
+
|
|
311
|
+
### Added
|
|
312
|
+
|
|
313
|
+
- `LumenWipeApiError` now exposes `code`, `details`, `retryAfterMs` (from `Retry-After`) and
|
|
314
|
+
`requestId` (from `X-Request-Id`, when the API sends one) next to `status` and `body`, and its
|
|
315
|
+
message reads `LumenWipe API error 422 destination_not_acknowledged: <message>`. A non-JSON
|
|
316
|
+
upstream failure has `code: "upstream_error"`.
|
|
317
|
+
- `isApiErrorCode(error, code)` type guard and the `ApiErrorCode` type.
|
|
318
|
+
- Every client method takes a trailing `{ signal }`. A caller abort rejects with the new
|
|
319
|
+
`LumenWipeAbortError`, distinct from `LumenWipeTimeoutError`.
|
|
320
|
+
- Opt-in `retry: { attempts, baseDelayMs }` client option, honoring `Retry-After`. Off by default;
|
|
321
|
+
`submit` and `mediatorSign` are never retried.
|
|
322
|
+
- Every request sends `X-LumenWipe-SDK: sdk/<version>`.
|
|
323
|
+
- The client logs once when a call falls back to the `"testnet"` default network, and once when
|
|
324
|
+
`baseUrl` is plaintext `http://` on a non-local host. Pass `network`, or a `logger`, to control
|
|
325
|
+
both; `logger` replaces the default `console.warn`.
|
|
326
|
+
- `ErrorCode`, the closed union of every `error.code` the API can return. Purely additive;
|
|
327
|
+
`StructuredApiError.error.code` stays a `string` for now.
|
|
328
|
+
- `StatsTotals`, `StatsFeed`, `MergeRecord`, `DailyActivity` and `RecordMergeResponse` types,
|
|
329
|
+
matching the API's new public close counter: `GET /v1/:network/stats`,
|
|
330
|
+
`GET /v1/:network/stats/feed` and `POST /v1/:network/stats/merges`. Purely additive; no existing
|
|
331
|
+
field changed shape.
|
|
332
|
+
- `DefiProtocol` gains `"xbull"`: xBull Swap is now a second, mainnet-only conversion-quote
|
|
333
|
+
source alongside Soroswap for the Soroban-token-to-XLM step of a close. `DecisionAnswer.params`
|
|
334
|
+
gains an optional `provider?: "soroswap" | "xbull"`, pinning which provider's quote a
|
|
335
|
+
`convert_to_xlm` answer was accepted from. Both are purely additive; no existing field changed
|
|
336
|
+
shape.
|
|
337
|
+
- `BatchPlanResult` and `BatchPlanResponse` types, matching the API's new
|
|
338
|
+
`POST /v1/:network/close/batch-plan` endpoint: plans a bounded list of addresses in one call,
|
|
339
|
+
isolating any address that can't be read or planned safely as its own blocked result rather
|
|
340
|
+
than failing the whole batch. Purely additive; no existing field changed shape.
|
|
341
|
+
- A headless example, `examples/headless-close.ts`, that closes a testnet account driven entirely
|
|
342
|
+
through the SDK with no web UI, verifying each transaction before signing it
|
|
343
|
+
(`examples/verify.ts`). Linked from the README; not part of the published package.
|
|
344
|
+
|
|
345
|
+
## [0.2.0] - 2026-09-23
|
|
346
|
+
|
|
347
|
+
### Added
|
|
348
|
+
|
|
349
|
+
- `LumenWipeClient.feeBumpSponsor()`: wraps a wind-down transaction in a signed CAP-15 fee-bump
|
|
350
|
+
envelope for an account that can't pay its own fee.
|
|
351
|
+
- `LumenWipeClient.getAllowances()`: every live SEP-41 allowance the account has granted -
|
|
352
|
+
independent of closing an account, a standalone security utility.
|
|
353
|
+
- `LumenWipeClient.revokeAllowance()`: builds the unsigned `approve(owner, spender, 0, 0)`
|
|
354
|
+
transaction that revokes one allowance.
|
|
355
|
+
- `coversTargets` on a `closeTransactions` step/transaction: which step types a transaction
|
|
356
|
+
confirms, for cases where one transaction covers more than one step of the same type. Additive
|
|
357
|
+
and optional - absent, every step of the named types is confirmed exactly as before.
|
|
358
|
+
|
|
359
|
+
## [0.1.0] - 2026-09-07
|
|
360
|
+
|
|
361
|
+
Initial public release. `LumenWipeClient` at this point covered the core close flow only - the
|
|
362
|
+
fee-bump/allowance endpoints above weren't added until after this tag.
|
|
363
|
+
|
|
364
|
+
### Added
|
|
365
|
+
|
|
366
|
+
- `LumenWipeClient`: typed fetch client for `health`, `getAccount`, `getPaths`, `closePlan`,
|
|
367
|
+
`closeTransactions`, `submit`, `mediatorCheck`, and `mediatorSign`.
|
|
368
|
+
- `runClose`: pure, dependency-injected multi-round close runner (verify -> sign -> submit,
|
|
369
|
+
looping until the account is closed), with `InsufficientSignatureWeightError` for resuming a
|
|
370
|
+
partially-signed transaction once more signing weight is available.
|
|
371
|
+
- Dual ESM + CJS build with bundled type declarations (`@lumenwipe/types` rolled into the SDK's
|
|
372
|
+
own `dist/index.d.ts` via `api-extractor` - no separate type-only dependency to install).
|
|
373
|
+
- Configurable timeout and custom `fetch` injection, for non-browser/non-Node environments and
|
|
374
|
+
testing.
|
|
375
|
+
|
|
376
|
+
[Unreleased]: https://github.com/LumenWipe/lumenwipe/compare/sdk-v0.9.0...HEAD
|
|
377
|
+
[0.9.0]: https://github.com/LumenWipe/lumenwipe/compare/sdk-v0.8.0...sdk-v0.9.0
|
|
378
|
+
[0.8.0]: https://github.com/LumenWipe/lumenwipe/compare/sdk-v0.7.0...sdk-v0.8.0
|
|
379
|
+
[0.7.0]: https://github.com/LumenWipe/lumenwipe/compare/sdk-v0.5.1...sdk-v0.7.0
|
|
380
|
+
[0.5.1]: https://github.com/LumenWipe/lumenwipe/compare/sdk-v0.2.0...sdk-v0.5.1
|
|
381
|
+
[0.2.0]: https://github.com/LumenWipe/lumenwipe/compare/sdk-v0.1.0...sdk-v0.2.0
|
|
382
|
+
[0.1.0]: https://github.com/LumenWipe/lumenwipe/tree/sdk-v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|