@lumenwipe/sdk 0.2.0 → 0.7.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.d.ts CHANGED
@@ -122,7 +122,11 @@ export declare interface AllowancesResult {
122
122
  warnings: PlanBlocker[];
123
123
  }
124
124
 
125
- export declare type ApiErrorBody = StructuredApiError | PlainApiError;
125
+ export declare type ApiErrorBody = StructuredApiError;
126
+
127
+ /** An `ErrorCode` the API can return, or `"upstream_error"` for a non-JSON failure from a proxy
128
+ * or CDN in front of it. The open `string` arm keeps a newer API's code from breaking a build. */
129
+ export declare type ApiErrorCode = ErrorCode | "upstream_error" | (string & {});
126
130
 
127
131
  export declare interface AquariusLpPosition extends DefiPositionBase {
128
132
  protocol: "aquarius";
@@ -154,6 +158,18 @@ export declare type AquariusPoolType = "constant_product" | "stable" | "concentr
154
158
  */
155
159
  export declare type AssetDisposition = "convert" | "issuer" | "transfer" | "leave";
156
160
 
161
+ export declare interface BatchPlanResponse {
162
+ results: BatchPlanResult[];
163
+ }
164
+
165
+ /** One address's plan within a batch call - always present, even when the account could not be
166
+ * read or planned safely (that failure surfaces as a `blocked` plan with its own blocker,
167
+ * never as a missing entry). */
168
+ export declare interface BatchPlanResult {
169
+ address: string;
170
+ plan: PlanResponse;
171
+ }
172
+
157
173
  export declare interface BlendBorrowPosition extends DefiPositionBase {
158
174
  protocol: "blend";
159
175
  positionType: "borrow";
@@ -312,6 +328,12 @@ export declare interface ConversionPath {
312
328
  destMin: string;
313
329
  }
314
330
 
331
+ export declare interface DailyActivity {
332
+ /** UTC day, YYYY-MM-DD. */
333
+ date: string;
334
+ accountsClosed: number;
335
+ }
336
+
315
337
  export declare interface DataEntry {
316
338
  key: string;
317
339
  value: string;
@@ -329,6 +351,13 @@ export declare interface DecisionAnswer {
329
351
  * and the browser holds the built swap's own minimum to at least this figure.
330
352
  */
331
353
  minAmountOut?: string;
354
+ /**
355
+ * Pinned alongside `minAmountOut`: which provider's quote the user was shown and accepted.
356
+ * The build re-quotes and builds through exactly this provider, never a different one that
357
+ * might look better right now but that the user never saw priced (architecture.md, this
358
+ * feature's spec §5.2).
359
+ */
360
+ provider?: "soroswap" | "xbull";
332
361
  /**
333
362
  * Required by the `transfer_to_account` choice: the `G...` address the balance is paid to.
334
363
  *
@@ -433,12 +462,14 @@ export declare interface DefiPositionsResult {
433
462
  export declare type DefiPositionType = "supply" | "borrow" | "lp" | "cdp" | "stake";
434
463
 
435
464
  /**
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.
465
+ * Protocols LumenWipe knows how to act on: most are DeFi positions it knows how to exit
466
+ * (architecture.md §9's table); `xbull` is the one exception, a swap router with no position to
467
+ * exit, registered here only so it can share the contract registry's protocol-keyed lookups.
468
+ * OctoPos itself indexes more than this (e.g. "untangled-vault", "stellar-wallet") - those are
469
+ * dropped by the adapter rather than represented here, since the type system should not claim
470
+ * LumenWipe can act on a protocol it has no exit path for.
440
471
  */
441
- export declare type DefiProtocol = "blend" | "aquarius" | "soroswap" | "phoenix" | "fxdao";
472
+ export declare type DefiProtocol = "blend" | "aquarius" | "soroswap" | "phoenix" | "fxdao" | "xbull";
442
473
 
443
474
  export declare interface DefiQueryKeys {
444
475
  rpcEndpoints: DefiRpcEndpoint[];
@@ -474,8 +505,18 @@ export declare interface DefiRpcPolicy {
474
505
 
475
506
  export declare type DemolishPhase = "IDLE" | "ANALYZING" | "PREFLIGHT_COMPLETE" | "SIGNER_SETUP" | "STEP_EXECUTING" | "STEP_CONFIRMED" | "STEP_FAILED" | "COMPLETE" | "ABORTED";
476
507
 
508
+ /**
509
+ * Every code the API can put in `error.code`. A code is a contract: it is added here first and
510
+ * never renamed or removed without a deprecation window. The API's runtime list
511
+ * (apps/api/src/common/error-codes.ts) is checked against this union at compile time.
512
+ */
513
+ export declare type ErrorCode = "account_not_found" | "account_read_failed" | "account_too_large" | "admin_api_not_configured" | "allowances_read_failed" | "api_key_not_found" | "aquarius_trustline_missing" | "backstop_emissions_unclaimed" | "backstop_token_unconvertible" | "backstop_withdrawal_cooling_down" | "backstop_withdrawal_not_queued" | "bad_request" | "blend_emissions_trustline_missing" | "blend_repay_asset_balance_unknown" | "blend_repay_asset_missing" | "confirmation_timeout" | "conversion_floor_missing" | "conversion_provider_unrecognized" | "defi_exit_blocked" | "defi_exit_unsupported" | "defi_position_unrecognized" | "defi_positions_blocked" | "defi_positions_stale" | "defi_positions_unavailable" | "destination_not_acknowledged" | "destination_read_failed" | "fee_bump_exceeds_cap" | "fee_bump_not_configured" | "forbidden" | "forward_amount_exceeds_balance" | "inner_fee_not_zero" | "integrator_api_not_configured" | "internal_error" | "invalid_address" | "invalid_addresses" | "invalid_body" | "invalid_challenge" | "invalid_decisions" | "invalid_destination" | "invalid_memo" | "invalid_network" | "invalid_owner" | "invalid_rate_limit" | "invalid_request" | "invalid_signature" | "invalid_signed_xdr" | "invalid_source" | "invalid_spender" | "invalid_token" | "invalid_tokens" | "invalid_transaction_xdr" | "invalid_tx_hash" | "issuer_read_failed" | "issuer_supply_not_acknowledged" | "key_limit_reached" | "mediator_key_misconfiguration" | "mediator_not_configured" | "memo_required" | "merge_destination_unusable" | "merged_account_not_found" | "missing_parameters" | "missing_transaction" | "needs_decisions" | "not_found" | "operation_not_sponsorable" | "owner_not_found" | "path_lookup_failed" | "payload_too_large" | "phoenix_trustline_missing" | "plan_failed" | "provider_response_unusable" | "quote_drifted" | "rate_limited" | "registry_expired" | "request_failed" | "revoke_build_failed" | "revoke_needs_restore" | "revoke_simulation_failed" | "revoke_unsafe" | "service_unavailable" | "signer_normalization_unsafe" | "soroban_token_conversion_failed" | "soroban_token_conversion_unavailable" | "soroban_token_conversion_unsafe" | "soroban_token_needs_restore" | "soroban_token_route_lost" | "soroban_token_transfer_failed" | "soroban_token_transfer_unsafe" | "soroban_token_unreadable" | "soroswap_trustline_missing" | "source_sequence_too_far" | "stats_unavailable" | "submit_failed" | "submit_rejected" | "too_many_addresses" | "transaction_structure_not_allowed" | "transactions_failed" | "transfer_destination_missing" | "transfer_destination_unusable" | "trustline_cannot_be_left" | "trustline_deauthorized_with_balance" | "trustline_maintain_liabilities_with_balance" | "tx_not_verified" | "unauthorized" | "unprocessable_entity" | "unsupported_media_type" | "unsupported_memo_type" | "vault_undercollateralized" | "withdraw_before_repay";
514
+
515
+ /** One transaction the close is expected to take. */
477
516
  export declare interface ExecutionTxBreakdown {
517
+ /** Position among the transactions, from 0, in the order they are built and submitted. */
478
518
  order: number;
519
+ /** The plan step types this transaction carries operations for. */
479
520
  covers: StepType[];
480
521
  reason?: "op_batch" | "defi_dependency";
481
522
  }
@@ -589,11 +630,26 @@ export declare type IntentOperationBody = {
589
630
  type: "unknown";
590
631
  };
591
632
 
633
+ /** Narrows an unknown error to a `LumenWipeApiError` carrying the given `code`. */
634
+ export declare function isApiErrorCode<C extends ApiErrorCode>(error: unknown, code: C): error is LumenWipeApiError & {
635
+ code: C;
636
+ };
637
+
638
+ /** Thrown when the caller's `signal` aborts a request. Distinct from a timeout. */
639
+ export declare class LumenWipeAbortError extends Error {
640
+ readonly reason?: unknown | undefined;
641
+ constructor(reason?: unknown | undefined);
642
+ }
643
+
592
644
  /** Thrown when the API responds with a non-2xx status. `body` is the parsed error payload. */
593
645
  export declare class LumenWipeApiError extends Error {
594
646
  readonly status: number;
595
647
  readonly body: unknown;
596
- constructor(status: number, body: unknown);
648
+ readonly code: ApiErrorCode;
649
+ readonly details: unknown;
650
+ readonly retryAfterMs: number | undefined;
651
+ readonly requestId: string | undefined;
652
+ constructor(status: number, body: unknown, headers?: Pick<Headers, "get">);
597
653
  }
598
654
 
599
655
  /**
@@ -604,39 +660,42 @@ export declare class LumenWipeApiError extends Error {
604
660
  export declare class LumenWipeClient {
605
661
  private readonly http;
606
662
  private readonly defaultNetwork;
663
+ private readonly log;
664
+ private warnedDefaultNetwork;
607
665
  constructor(options: LumenWipeClientOptions);
608
- health(): Promise<HealthResponse>;
609
- getAccount(address: string, network?: Network): Promise<AccountState>;
666
+ private resolveNetwork;
667
+ health(options?: RequestOptions): Promise<HealthResponse>;
668
+ getAccount(address: string, network?: Network, options?: RequestOptions): Promise<AccountState>;
610
669
  getPaths(params: {
611
670
  fromAsset: string;
612
671
  amount: string;
613
- }, network?: Network): Promise<PathResponse>;
614
- closePlan(body: ClosePlanRequest, network?: Network): Promise<PlanResponse>;
672
+ }, network?: Network, options?: RequestOptions): Promise<PathResponse>;
673
+ closePlan(body: ClosePlanRequest, network?: Network, options?: RequestOptions): Promise<PlanResponse>;
615
674
  /**
616
675
  * Builds the next unsigned transaction(s) for a close. A close can span several
617
- * transactions (a fused close, or separate claim / cleanup / mediator-merge steps),
676
+ * transactions (a single transaction, or separate claim / cleanup / mediator-merge steps),
618
677
  * so the response's `remaining.requiresAnotherCall` says whether more follow: sign and
619
678
  * submit the returned transactions in `order`, wait for confirmation, then call this
620
679
  * again until `requiresAnotherCall` is false.
621
680
  */
622
- closeTransactions(body: CloseTransactionsRequest, network?: Network): Promise<TransactionsResponse>;
623
- submit(signedXdr: string, network?: Network): Promise<SubmitResponse>;
624
- mediatorCheck(address: string, network?: Network): Promise<MediatorCheckResult>;
625
- mediatorSign(transaction: string, network?: Network): Promise<MediatorSignResponse>;
681
+ closeTransactions(body: CloseTransactionsRequest, network?: Network, options?: RequestOptions): Promise<TransactionsResponse>;
682
+ submit(signedXdr: string, network?: Network, options?: RequestOptions): Promise<SubmitResponse>;
683
+ mediatorCheck(address: string, network?: Network, options?: RequestOptions): Promise<MediatorCheckResult>;
684
+ mediatorSign(transaction: string, network?: Network, options?: RequestOptions): Promise<MediatorSignResponse>;
626
685
  /** Wraps a wind-down transaction (its own fee already zero) in a signed CAP-15 fee-bump
627
686
  * envelope for an account that cannot pay its own fee (architecture.md §8.1). The caller
628
687
  * submits the returned XDR through `submit()`, exactly like any other close transaction. */
629
- feeBumpSponsor(transaction: string, network?: Network): Promise<FeeBumpSponsorResponse>;
688
+ feeBumpSponsor(transaction: string, network?: Network, options?: RequestOptions): Promise<FeeBumpSponsorResponse>;
630
689
  /** Every live SEP-41 allowance the account has granted (architecture.md §12). Independent of
631
690
  * closing an account - a standalone security utility. */
632
- getAllowances(address: string, network?: Network): Promise<AllowancesResult>;
691
+ getAllowances(address: string, network?: Network, options?: RequestOptions): Promise<AllowancesResult>;
633
692
  /** Builds the unsigned `approve(owner, spender, 0, 0)` transaction that revokes one allowance.
634
693
  * The caller signs and submits it through `submit()`, like any other transaction here. */
635
694
  revokeAllowance(params: {
636
695
  owner: string;
637
696
  token: string;
638
697
  spender: string;
639
- }, network?: Network): Promise<RevokeAllowanceResponse>;
698
+ }, network?: Network, options?: RequestOptions): Promise<RevokeAllowanceResponse>;
640
699
  }
641
700
 
642
701
  export declare interface LumenWipeClientOptions {
@@ -644,12 +703,16 @@ export declare interface LumenWipeClientOptions {
644
703
  baseUrl: string;
645
704
  /** Integrator API key, sent as `Authorization: Bearer <apiKey>`. */
646
705
  apiKey: string;
647
- /** Default network for calls that omit it. Defaults to `"testnet"`. */
706
+ /** Default network for calls that omit it. Defaults to `"testnet"`, with a one-time notice. */
648
707
  network?: Network;
649
708
  /** Custom fetch (for environments without a global `fetch`, or for testing). */
650
709
  fetch?: FetchLike;
651
710
  /** Per-request timeout in milliseconds. Defaults to 30000. `0`/`Infinity` disables it. */
652
711
  timeout?: number;
712
+ /** Opt-in retries. Off by default; never applied to `submit` or `mediatorSign`. */
713
+ retry?: RetryOptions;
714
+ /** Receives one-time notices (plaintext `baseUrl`, defaulted network). Defaults to `console.warn`. */
715
+ logger?: (message: string) => void;
653
716
  }
654
717
 
655
718
  /** Thrown when a request exceeds the configured timeout. */
@@ -666,6 +729,8 @@ export declare interface MediatorCheckResult {
666
729
  exchangeName: string | null;
667
730
  /** Whether the server can actually perform the mediator flow (secret configured). */
668
731
  available: boolean;
732
+ /** Whether the exchange registry is inside its verification window; false means exchange closes are refused. */
733
+ registryFresh: boolean;
669
734
  }
670
735
 
671
736
  /** Response from `POST /:network/mediator/sign`. */
@@ -673,6 +738,16 @@ export declare interface MediatorSignResponse {
673
738
  transaction: string;
674
739
  }
675
740
 
741
+ /** One verified, counted close transaction. */
742
+ export declare interface MergeRecord {
743
+ txHash: string;
744
+ network: Network;
745
+ accountsClosed: number;
746
+ xlmStroops: string;
747
+ /** Ledger close time of the transaction, ISO 8601. */
748
+ timestamp: string;
749
+ }
750
+
676
751
  export declare type Network = "mainnet" | "testnet";
677
752
 
678
753
  export declare interface OpenOffer {
@@ -715,12 +790,6 @@ export declare interface PhoenixStakePosition extends DefiPositionBase {
715
790
  stakedAtEpoch: string;
716
791
  }
717
792
 
718
- /** @deprecated The API emits one envelope (`StructuredApiError`). Kept only so a consumer
719
- * pinned to an older deployment still type-checks during a rollout; remove once none remain. */
720
- export declare interface PlainApiError {
721
- error: string;
722
- }
723
-
724
793
  export declare interface PlanBlocker {
725
794
  message: string;
726
795
  helpUrl?: string;
@@ -766,8 +835,19 @@ export declare interface PlanResponse {
766
835
  feeStroops: string;
767
836
  freedReserveXlm: string;
768
837
  };
838
+ /**
839
+ * The transactions this close is expected to take, counted with the splitter the builder
840
+ * packs them with: Soroban token moves, the claim round, the classic close split at the
841
+ * per-transaction operation cap, and, for an exchange destination, the mediator transfer.
842
+ *
843
+ * `estimatedTransactionCount` is `null`, with `transactions` empty, when it cannot be known
844
+ * yet: the plan has a DeFi exit (its transaction count depends on live debt), a held token has
845
+ * no decision, or no destination was given. Never read it as a number without checking, and
846
+ * never show an unknown count as a figure. It is an estimate from the account as planned; the
847
+ * close re-reads live state each round.
848
+ */
769
849
  execution: {
770
- estimatedTransactionCount: number;
850
+ estimatedTransactionCount: number | null;
771
851
  transactions: ExecutionTxBreakdown[];
772
852
  };
773
853
  }
@@ -783,6 +863,23 @@ export declare interface QuoteInfo {
783
863
  expiresAtLedger: number;
784
864
  }
785
865
 
866
+ /** Response from `POST /v1/:network/stats/merges`. `counted` is false for an already-counted hash. */
867
+ export declare interface RecordMergeResponse {
868
+ counted: boolean;
869
+ }
870
+
871
+ export declare interface RequestOptions {
872
+ /** Aborts the request. Rejects with `LumenWipeAbortError`, distinct from a timeout. */
873
+ signal?: AbortSignal;
874
+ }
875
+
876
+ export declare interface RetryOptions {
877
+ /** Total attempts including the first. Values below 2 disable retrying. */
878
+ attempts: number;
879
+ /** Base delay for exponential backoff when the response has no `Retry-After`. */
880
+ baseDelayMs: number;
881
+ }
882
+
786
883
  /** Response from `POST /:network/allowances/revoke`. */
787
884
  export declare interface RevokeAllowanceResponse {
788
885
  transaction: string;
@@ -882,16 +979,31 @@ export declare type SponsoredEntry = {
882
979
  balanceId: string;
883
980
  };
884
981
 
982
+ /** Response from `GET /v1/:network/stats/feed`. `daily` is oldest first, one entry per day. */
983
+ export declare interface StatsFeed {
984
+ totals: StatsTotals;
985
+ recent: MergeRecord[];
986
+ daily: DailyActivity[];
987
+ }
988
+
989
+ /** Response from `GET /v1/:network/stats`. Stroops are decimal strings: the total can exceed 2^53. */
990
+ export declare interface StatsTotals {
991
+ network: Network;
992
+ accountsClosed: number;
993
+ xlmRecoveredStroops: string;
994
+ }
995
+
885
996
  export declare type StepStatus = "pending" | "signing" | "submitted" | "confirmed" | "failed" | "skipped";
886
997
 
887
998
  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";
888
999
 
889
- /** Structured error body used by the v1 (`/v1/...`) endpoints. */
1000
+ /** The single error envelope every API error response carries. */
890
1001
  export declare interface StructuredApiError {
891
1002
  error: {
892
1003
  code: string;
893
1004
  message: string;
894
1005
  details?: unknown;
1006
+ requestId?: string;
895
1007
  };
896
1008
  }
897
1009
 
@@ -960,11 +1072,19 @@ export declare interface Trustline {
960
1072
  asset: string;
961
1073
  balance: string;
962
1074
  limit?: string;
1075
+ /** True only when `authorization` is `authorized`. */
963
1076
  authorized: boolean;
1077
+ authorization: TrustlineAuthorization;
1078
+ /** The issuer can reclaim this balance at any time. */
1079
+ clawbackEnabled: boolean;
964
1080
  issuer: string;
965
1081
  code: string;
966
1082
  }
967
1083
 
1084
+ /** The issuer's authorization of a trustline. Only `authorized` can send or receive payments;
1085
+ * `maintain_liabilities` keeps existing offers alive and nothing else. */
1086
+ export declare type TrustlineAuthorization = "authorized" | "maintain_liabilities" | "unauthorized";
1087
+
968
1088
  export declare interface TxIntent {
969
1089
  summary: string;
970
1090
  source: string;