@lumenwipe/sdk 0.1.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.
@@ -0,0 +1,577 @@
1
+ export declare interface AccountSigner {
2
+ key: string;
3
+ weight: number;
4
+ type: "ed25519_public_key" | "hash_x" | "preauth_tx" | "ed25519_signed_payload";
5
+ }
6
+
7
+ export declare interface AccountState {
8
+ address: string;
9
+ network: Network;
10
+ sequence: string;
11
+ nativeBalanceLumens: string;
12
+ dataEntries: DataEntry[];
13
+ signers: AccountSigner[];
14
+ thresholds: AccountThresholds;
15
+ numSubEntries: number;
16
+ numSponsoring: number;
17
+ /** Ledger entries this account currently sponsors (on other accounts, or itself via a
18
+ * fully-sponsored account creation). Populated by replaying sponsorship-relevant
19
+ * operations and re-verifying each candidate's live sponsor - see sponsorship.ts. */
20
+ sponsoredEntries: SponsoredEntry[];
21
+ /** True when sponsoredEntries could not be enumerated completely (pagination cut off,
22
+ * a live re-verification fetch failed, or the enumerated count doesn't match
23
+ * numSponsoring). Mirrors subEntryMismatch: an incomplete read must never be treated
24
+ * as "sponsors nothing" downstream. */
25
+ sponsorshipEnumerationIncomplete: boolean;
26
+ /** Account whose reserve covers this account's base reserve, or null. Populated by the
27
+ * Horizon-based scan path only; the RPC getLedgerEntries response strips the outer
28
+ * LedgerEntry extension where sponsoringID lives, so it remains null on that path. */
29
+ sponsoredBy: string | null;
30
+ /** AUTH_IMMUTABLE flag is set - ACCOUNT_MERGE is permanently blocked. */
31
+ authImmutable: boolean;
32
+ trustlines: Trustline[];
33
+ openOffers: OpenOffer[];
34
+ poolShares: PoolShareEntry[];
35
+ /** Claimable balances where this account is listed as a claimant. Does not affect
36
+ * numSubEntries on this account; populated via the Horizon adapter. */
37
+ claimableBalances: ClaimableBalance[];
38
+ subEntryMismatch: boolean;
39
+ }
40
+
41
+ export declare interface AccountThresholds {
42
+ low: number;
43
+ med: number;
44
+ high: number;
45
+ }
46
+
47
+ export declare type ApiErrorBody = StructuredApiError | PlainApiError;
48
+
49
+ /**
50
+ * What happens to a non-XLM balance before its trustline is removed.
51
+ *
52
+ * `convert` swaps it to XLM and `issuer` sends it back to be burned - both end the close with the
53
+ * position destroyed. `transfer` keeps the asset, as the asset, by paying it to another account
54
+ * that already holds the trustline.
55
+ */
56
+ export declare type AssetDisposition = "convert" | "issuer" | "transfer";
57
+
58
+ export declare interface BuildPlanResult {
59
+ steps: PlannedStep[];
60
+ blockers: PlanBlocker[];
61
+ }
62
+
63
+ export declare interface ClaimableBalance {
64
+ /** Full 72-char hex balance ID as returned by Horizon ("00000000" + 64-char hash). */
65
+ id: string;
66
+ /** "CODE:ISSUER" or "native" */
67
+ asset: string;
68
+ amount: string;
69
+ /** One entry per claimant on the balance, each with its own predicate. */
70
+ claimants: {
71
+ destination: string;
72
+ predicate: ClaimPredicate;
73
+ }[];
74
+ /** Account sponsoring this balance's reserve, or null if unsponsored. */
75
+ sponsor: string | null;
76
+ }
77
+
78
+ export declare type ClaimableBalanceSelection = "claim" | "add_trustline_then_claim" | "forfeit";
79
+
80
+ export declare type ClaimPredicate = {
81
+ type: "unconditional";
82
+ } | {
83
+ type: "and";
84
+ predicates: ClaimPredicate[];
85
+ } | {
86
+ type: "or";
87
+ predicates: ClaimPredicate[];
88
+ } | {
89
+ type: "not";
90
+ predicate: ClaimPredicate;
91
+ } | {
92
+ type: "before_absolute_time";
93
+ absBeforeEpoch: string;
94
+ } | {
95
+ type: "before_relative_time";
96
+ relBeforeSeconds: string;
97
+ deadlineEpoch: string;
98
+ };
99
+
100
+ export declare type CloseApiStatus = "ready" | "needs_decisions" | "blocked" | "complete";
101
+
102
+ export declare interface CloseEngineDeps {
103
+ /** Fetches the next round of unsigned transactions from the API (via the proxy). */
104
+ getTransactions: () => Promise<TransactionsResponse>;
105
+ /**
106
+ * Verifies one server-built transaction against what the client independently expects.
107
+ * MUST throw on any mismatch. This is the trust anchor: the browser never signs a
108
+ * server-built transaction it cannot fully account for. Injected so it can be tested in
109
+ * isolation; the hook supplies the real `verifyCloseTransaction`.
110
+ * May be sync or async - the engine always awaits it, so a future async verifier
111
+ * (e.g. one that resolves a key or does a lookup) can never be silently bypassed.
112
+ */
113
+ verify: (tx: CloseTransaction) => void | Promise<void>;
114
+ /** The signing weight this transaction actually needs, from its operation set and the
115
+ * account's real per-category thresholds - never a single account-wide number. */
116
+ requiredWeight: (tx: CloseTransaction) => number;
117
+ /** Signs the given xdr (which may already carry earlier signatures) with the currently
118
+ * available signer, returning the updated xdr and its total accumulated signing weight
119
+ * against the account's known signer set. */
120
+ sign: (tx: CloseTransaction, xdr: string) => Promise<{
121
+ xdr: string;
122
+ weight: number;
123
+ }>;
124
+ /** Submits a transaction whose accumulated weight already meets its requirement; resolves
125
+ * to the tx hash. */
126
+ submit: (tx: CloseTransaction, xdr: string) => Promise<string>;
127
+ /** Called after a transaction confirms, with the transaction and its hash. */
128
+ onConfirmed?: (tx: CloseTransaction, hash: string) => void;
129
+ onProgress?: (message: string) => void;
130
+ /** Safety bound so a misbehaving API can never spin the loop forever. */
131
+ maxRounds?: number;
132
+ }
133
+
134
+ /** Body for `POST /v1/:network/close/plan`. */
135
+ export declare interface ClosePlanRequest {
136
+ source: string;
137
+ destination?: string;
138
+ decisions?: DecisionAnswer[];
139
+ }
140
+
141
+ export declare interface CloseTransaction {
142
+ id: string;
143
+ order: number;
144
+ dependsOn: string[];
145
+ xdr: string;
146
+ networkPassphrase: string;
147
+ sourceSequence: string;
148
+ validUntilLedger: number;
149
+ covers: StepType[];
150
+ intent: TxIntent;
151
+ }
152
+
153
+ /** Body for `POST /v1/:network/close/transactions`. */
154
+ export declare interface CloseTransactionsRequest {
155
+ source: string;
156
+ destination: string;
157
+ decisions?: DecisionAnswer[];
158
+ /**
159
+ * Deposit memo value for exchange destinations that require one. The memo type
160
+ * is taken from the exchange registry, not the client. Required when the
161
+ * destination is an exchange that mandates a memo.
162
+ */
163
+ memo?: string;
164
+ }
165
+
166
+ export declare interface ConversionPath {
167
+ fromAsset: string;
168
+ toAsset: string;
169
+ path: string[];
170
+ estimatedReceive: string;
171
+ destMin: string;
172
+ }
173
+
174
+ export declare interface DataEntry {
175
+ key: string;
176
+ value: string;
177
+ }
178
+
179
+ export declare interface DecisionAnswer {
180
+ id: string;
181
+ choice: string;
182
+ params?: {
183
+ maxSlippageBps?: number;
184
+ /**
185
+ * Required by the `transfer_to_account` choice: the `G...` address the balance is paid to.
186
+ *
187
+ * It travels with the answer rather than in a separate map so a destination cannot become
188
+ * detached from the asset it was chosen for - the same reason the unrecognized-destination
189
+ * acknowledgement is keyed by address instead of being a boolean. A `transfer_to_account`
190
+ * answer without a valid destination is a 422; there is no default, because every available
191
+ * fallback would destroy the balance the user asked to keep.
192
+ */
193
+ destination?: string;
194
+ };
195
+ }
196
+
197
+ export declare interface DecisionOption {
198
+ id: string;
199
+ recommended?: boolean;
200
+ quote?: QuoteInfo;
201
+ note?: string;
202
+ }
203
+
204
+ export declare interface DecisionPoint {
205
+ id: string;
206
+ type: "asset_disposition" | "confirmation" | "choice" | "claimable_balance";
207
+ subject: Record<string, unknown>;
208
+ options: DecisionOption[];
209
+ default: string;
210
+ required: boolean;
211
+ }
212
+
213
+ export declare type DemolishPhase = "IDLE" | "ANALYZING" | "PREFLIGHT_COMPLETE" | "SIGNER_SETUP" | "STEP_EXECUTING" | "STEP_CONFIRMED" | "STEP_FAILED" | "COMPLETE" | "ABORTED";
214
+
215
+ export declare interface ExecutionTxBreakdown {
216
+ order: number;
217
+ covers: StepType[];
218
+ reason?: "op_batch" | "defi_dependency";
219
+ }
220
+
221
+ export declare type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
222
+
223
+ /** Response from `GET /health`. */
224
+ export declare interface HealthResponse {
225
+ status: string;
226
+ }
227
+
228
+ /** Thrown when a transaction's accumulated signing weight is still short of what it actually
229
+ * needs after the currently available signer has contributed. Carries everything needed to
230
+ * resume with a different signer onto the same partially-signed envelope. */
231
+ export declare class InsufficientSignatureWeightError extends Error {
232
+ readonly pending: PendingRound;
233
+ constructor(pending: PendingRound);
234
+ }
235
+
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
+ export declare type IntentOperation = IntentOperationBody & {
247
+ source: string;
248
+ };
249
+
250
+ export declare type IntentOperationBody = {
251
+ type: "path_payment_strict_send";
252
+ sendAsset: string;
253
+ sendAmount: string;
254
+ destination: string;
255
+ destAsset: string;
256
+ destMin: string;
257
+ path: string[];
258
+ } | {
259
+ type: "payment";
260
+ destination: string;
261
+ asset: string;
262
+ amount: string;
263
+ } | {
264
+ type: "change_trust";
265
+ asset: string;
266
+ limit: string;
267
+ } | {
268
+ type: "account_merge";
269
+ destination: string;
270
+ } | {
271
+ type: "manage_sell_offer";
272
+ offerId: string;
273
+ amount: string;
274
+ } | {
275
+ type: "manage_data";
276
+ name: string;
277
+ value: string | null;
278
+ } | {
279
+ type: "set_options";
280
+ signer: AccountSigner | null;
281
+ masterWeight: number | null;
282
+ lowThreshold: number | null;
283
+ medThreshold: number | null;
284
+ highThreshold: number | null;
285
+ homeDomain: string | null;
286
+ setFlags: number | null;
287
+ clearFlags: number | null;
288
+ inflationDest: string | null;
289
+ } | {
290
+ type: "claim_claimable_balance";
291
+ balanceId: string;
292
+ } | {
293
+ type: "revoke_sponsorship";
294
+ entryKind: "account" | "trustline" | "offer" | "data_entry" | "signer";
295
+ owner: string;
296
+ } | {
297
+ type: "unknown";
298
+ };
299
+
300
+ /** Thrown when the API responds with a non-2xx status. `body` is the parsed error payload. */
301
+ export declare class LumenWipeApiError extends Error {
302
+ readonly status: number;
303
+ readonly body: unknown;
304
+ constructor(status: number, body: unknown);
305
+ }
306
+
307
+ /**
308
+ * Thin, typed client over the LumenWipe REST API. It only relays JSON and XDR
309
+ * strings - transaction building and signing stay with the caller, so this
310
+ * package has no `@stellar/stellar-sdk` dependency.
311
+ */
312
+ export declare class LumenWipeClient {
313
+ private readonly http;
314
+ private readonly defaultNetwork;
315
+ constructor(options: LumenWipeClientOptions);
316
+ health(): Promise<HealthResponse>;
317
+ getAccount(address: string, network?: Network): Promise<AccountState>;
318
+ getPaths(params: {
319
+ fromAsset: string;
320
+ amount: string;
321
+ }, network?: Network): Promise<PathResponse>;
322
+ closePlan(body: ClosePlanRequest, network?: Network): Promise<PlanResponse>;
323
+ /**
324
+ * Builds the next unsigned transaction(s) for a close. A close can span several
325
+ * transactions (a fused close, or separate claim / cleanup / mediator-merge steps),
326
+ * so the response's `remaining.requiresAnotherCall` says whether more follow: sign and
327
+ * submit the returned transactions in `order`, wait for confirmation, then call this
328
+ * again until `requiresAnotherCall` is false.
329
+ */
330
+ closeTransactions(body: CloseTransactionsRequest, network?: Network): Promise<TransactionsResponse>;
331
+ submit(signedXdr: string, network?: Network): Promise<SubmitResponse>;
332
+ mediatorCheck(address: string, network?: Network): Promise<MediatorCheckResult>;
333
+ mediatorSign(transaction: string, network?: Network): Promise<MediatorSignResponse>;
334
+ }
335
+
336
+ export declare interface LumenWipeClientOptions {
337
+ /** Base URL of the LumenWipe API, e.g. `https://api.lumenwipe.com`. */
338
+ baseUrl: string;
339
+ /** Integrator API key, sent as `Authorization: Bearer <apiKey>`. */
340
+ apiKey: string;
341
+ /** Default network for calls that omit it. Defaults to `"testnet"`. */
342
+ network?: Network;
343
+ /** Custom fetch (for environments without a global `fetch`, or for testing). */
344
+ fetch?: FetchLike;
345
+ /** Per-request timeout in milliseconds. Defaults to 30000. `0`/`Infinity` disables it. */
346
+ timeout?: number;
347
+ }
348
+
349
+ /** Thrown when a request exceeds the configured timeout. */
350
+ export declare class LumenWipeTimeoutError extends Error {
351
+ readonly timeoutMs: number;
352
+ constructor(timeoutMs: number);
353
+ }
354
+
355
+ export declare interface MediatorCheckResult {
356
+ requiresMediator: boolean;
357
+ reason: string;
358
+ requiresMemo: boolean;
359
+ memoType: "text" | "id" | "hash" | null;
360
+ exchangeName: string | null;
361
+ /** Whether the server can actually perform the mediator flow (secret configured). */
362
+ available: boolean;
363
+ }
364
+
365
+ /** Response from `POST /:network/mediator/sign`. */
366
+ export declare interface MediatorSignResponse {
367
+ transaction: string;
368
+ }
369
+
370
+ export declare type Network = "mainnet" | "testnet";
371
+
372
+ export declare interface OpenOffer {
373
+ id: string;
374
+ selling: string;
375
+ buying: string;
376
+ amount: string;
377
+ price: string;
378
+ }
379
+
380
+ /** Response from `GET /:network/paths`. */
381
+ export declare interface PathResponse {
382
+ path: ConversionPath | null;
383
+ }
384
+
385
+ /** Everything needed to resume signing a transaction that stopped short of its required
386
+ * signing weight, without re-fetching (which would discard any signature already
387
+ * collected) or re-verifying (the tx body is unchanged - verified once, before the first
388
+ * signature; a later signer only adds a signature, never alters the body). */
389
+ export declare interface PendingRound {
390
+ tx: CloseTransaction;
391
+ xdr: string;
392
+ requiredWeight: number;
393
+ accumulatedWeight: number;
394
+ queue: CloseTransaction[];
395
+ requiresAnotherCall: boolean;
396
+ }
397
+
398
+ /** @deprecated The API emits one envelope (`StructuredApiError`). Kept only so a consumer
399
+ * pinned to an older deployment still type-checks during a rollout; remove once none remain. */
400
+ export declare interface PlainApiError {
401
+ error: string;
402
+ }
403
+
404
+ export declare interface PlanBlocker {
405
+ message: string;
406
+ helpUrl?: string;
407
+ /** Distinguishes an acknowledged, non-trapping warning (e.g. a chosen forfeit) from a hard
408
+ * blocker. Absent means the generic hard-blocking case. */
409
+ code?: string;
410
+ }
411
+
412
+ export declare interface PlannedStep {
413
+ index: number;
414
+ type: StepType;
415
+ title: string;
416
+ description: string;
417
+ operationCount: number;
418
+ estimatedFeeLumens: string;
419
+ txXdr: string | null;
420
+ status: StepStatus;
421
+ txHash: string | null;
422
+ error: string | null;
423
+ affectedAsset?: string;
424
+ fallbackToIssuer?: boolean;
425
+ }
426
+
427
+ export declare interface PlanResponse {
428
+ planHash: string;
429
+ status: CloseApiStatus;
430
+ steps: unknown[];
431
+ decisionPoints: DecisionPoint[];
432
+ blockers: {
433
+ code: string;
434
+ message: string;
435
+ helpUrl?: string;
436
+ }[];
437
+ estimate: {
438
+ feeStroops: string;
439
+ freedReserveXlm: string;
440
+ };
441
+ execution: {
442
+ estimatedTransactionCount: number;
443
+ transactions: ExecutionTxBreakdown[];
444
+ };
445
+ }
446
+
447
+ export declare interface PoolShareEntry {
448
+ poolId: string;
449
+ }
450
+
451
+ export declare interface QuoteInfo {
452
+ estimatedReceive: string;
453
+ path: string[];
454
+ source: "soroswap" | "sdex";
455
+ expiresAtLedger: number;
456
+ }
457
+
458
+ /**
459
+ * Runs the full multi-round close. Each round: fetch a batch of unsigned transactions,
460
+ * verify every one before signing, sign it, and submit only once its accumulated signing
461
+ * weight meets what its operations actually require - otherwise throw
462
+ * InsufficientSignatureWeightError with everything needed to resume onto the same
463
+ * envelope once a different signer is available. Pass that error's `.pending` back in as
464
+ * `resume` to continue exactly where it stopped.
465
+ */
466
+ export declare function runClose(deps: CloseEngineDeps, resume?: PendingRound): Promise<void>;
467
+
468
+ /**
469
+ * A ledger entry this account currently sponsors, on another account (or itself, for
470
+ * "account" - a fully-sponsored account creation). Mirrors the ledger-key kinds
471
+ * RevokeSponsorship supports. Claimable balances have no owning-account concept in
472
+ * their ledger key (unlike the other five kinds), so they carry only balanceId.
473
+ */
474
+ export declare type SponsoredEntry = {
475
+ kind: "account";
476
+ owner: string;
477
+ } | {
478
+ kind: "trustline";
479
+ owner: string;
480
+ asset: string;
481
+ } | {
482
+ kind: "offer";
483
+ owner: string;
484
+ offerId: string;
485
+ } | {
486
+ kind: "data_entry";
487
+ owner: string;
488
+ name: string;
489
+ } | {
490
+ kind: "signer";
491
+ owner: string;
492
+ signerKey: string;
493
+ } | {
494
+ kind: "claimable_balance";
495
+ balanceId: string;
496
+ };
497
+
498
+ export declare type StepStatus = "pending" | "signing" | "submitted" | "confirmed" | "failed" | "skipped";
499
+
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";
501
+
502
+ /** Structured error body used by the v1 (`/v1/...`) endpoints. */
503
+ export declare interface StructuredApiError {
504
+ error: {
505
+ code: string;
506
+ message: string;
507
+ details?: unknown;
508
+ };
509
+ }
510
+
511
+ /** Body for `POST /v1/:network/submit`. */
512
+ export declare interface SubmitRequest {
513
+ signedXdr: string;
514
+ }
515
+
516
+ /** Response from `POST /v1/:network/submit`. */
517
+ export declare interface SubmitResponse {
518
+ status: "success";
519
+ hash: string;
520
+ ledger: number;
521
+ }
522
+
523
+ export declare interface TransactionsResponse {
524
+ planHash: string;
525
+ status: CloseApiStatus;
526
+ transactions: CloseTransaction[];
527
+ /**
528
+ * `requiresAnotherCall` is true when more transactions follow the returned batch:
529
+ * submit these, wait for confirmation, then request transactions again. `steps` is the
530
+ * approximate number of build rounds still remaining.
531
+ */
532
+ remaining: {
533
+ steps: number;
534
+ requiresAnotherCall: boolean;
535
+ };
536
+ }
537
+
538
+ /**
539
+ * Where a `transfer` disposition sends its balance, keyed by the same canonical `CODE:ISSUER`
540
+ * string the disposition itself is keyed by.
541
+ *
542
+ * Per asset and arbitrary: the API takes any address here, independently for each asset. Offering
543
+ * "the same account you are merging into" is a UI convenience, not a constraint of the contract -
544
+ * an SDK consumer can send each asset somewhere different.
545
+ *
546
+ * There is deliberately no amount. The `ChangeTrust` that removes the trustline runs immediately
547
+ * after and fails on a non-zero balance, so anything short of the full balance would strand the
548
+ * close midway.
549
+ */
550
+ export declare type TransferDestinations = Record<string, string>;
551
+
552
+ export declare interface Trustline {
553
+ asset: string;
554
+ balance: string;
555
+ limit?: string;
556
+ authorized: boolean;
557
+ issuer: string;
558
+ code: string;
559
+ }
560
+
561
+ export declare interface TxIntent {
562
+ summary: string;
563
+ source: string;
564
+ fee: string;
565
+ memo: string | null;
566
+ /** The memo's type, so a check can assert it matches what the destination requires rather
567
+ * than only that some memo is present. */
568
+ memoType: "text" | "id" | "hash" | null;
569
+ guarantees: {
570
+ mergeDestination: string | null;
571
+ paymentsOnlyTo: string[];
572
+ minXlmFromConversions: string | null;
573
+ };
574
+ operations: IntentOperation[];
575
+ }
576
+
577
+ export { }