@dcasegr/amm-client 0.38.2 → 0.41.1

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/README.md CHANGED
@@ -39,22 +39,42 @@ exchange with another wallet, keeping what was read and quoted.
39
39
 
40
40
  The client (each an async function unless noted):
41
41
 
42
- - the exchange: `enabledList`, `registeredTokens`, `tokenBaseOf`, `hostedTokens`,
43
- `watchHostedPools` / `watchTokenPools` (event streams, sync, return the unsubscribe),
42
+ - the exchange: `enabledList`, `registeredTokens`, `tokenBaseOf`, `hostedTokens` (the token list
43
+ and ONE `GET /amm/stats`), `tokenPools(tokenId)` (0.41.0: the token's pools route, a plain
44
+ read past the browser's cache), `watchPoolEvents(tokenId | "all", onEvent)` (0.41.0: the host's
45
+ pool event feed, `/@<token>/amm/events` or `<origin>/amm/events`; each message `{tokenId, …row}`,
46
+ a `/pools/history` row or a `revert`; signals for display, the pools route the truth; sync,
47
+ returns the unsubscribe; reconnect is the browser EventSource's),
44
48
  `claimStatus`, `isRoot`, `claimExchange`, `discoveryBase` (sync), `onDataChange` (sync);
49
+ - history (plain GETs; 0.40.0: by pool id, `poolId` = the pool's deploy outpoint `<txid>_<vout>`):
50
+ `trades(tokenId, {from?, to?, limit?, before?, pool?})` → `{trades, next}` (each row its
51
+ `poolId` and `payoutPkh`), `trade(tokenId, txid)` → a `Trade` or null, `candles(tokenId, {tf,
52
+ from, to, series?})` (`series` `fill`, the default, or `market`), `stats(tokenId)` /
53
+ `statsAll({ids?, fresh?})` (`price` = the midpoint of what a buy and a sell of 1% of the pooled sats
54
+ would pay now, `buyPrice`, `sellPrice`, `lastTradePrice`), `holders(tokenId, {limit?, skip?})` →
55
+ `{count, rows}`, `positionsAll(poolIds)`, `poolsAt(tokenId, t)` (every pool listed at `t`),
56
+ `poolHistory(tokenId, {from?, to?, pool?, limit?, after?})` → `{events, next}` (oldest first;
57
+ forward paging: `next` as `after`), `spendsAll(outpoints)` (the host's `/amm/spends`); amounts
58
+ bigints, prices `{sats, tokens}` pairs of bigints (base units both);
45
59
  - swap: `quoteSwap(request, poolsAnswer, {sym, dec})` (sync: the engine's plan over the pools the
46
- token's pools stream gave), `executeSwap(quote, {onProgress})`, `checkSwapAgain(leg)`,
47
- `walletSats`;
60
+ token's pools route gave, each pool with its validator's `minLegSats`; the quote's price and
61
+ impact from the engine's `priceOf`, each leg's own `fees`, `stage` = what Swap sets aside
62
+ (`amount`, `feeSats`: 0.40.2, exactly `maxSources` legs), `legMinerFeeSats`); the request's
63
+ `maxSources` (required, 0.40.2; replaces `allowPartial`) is the most pools the swap may draw on —
64
+ 1 is exactly one leg; the Open Exchange pages send 1 or 5,
65
+ `executeSwap(quote, {onProgress, signal})` (below), `walletSats`;
48
66
  - liquidity: `myPositions`, `validatorTerms`, `deployPosition({tokenId, tokens, sats})`,
49
67
  `closePosition({outpoint})`, `rebalancePosition({outpoint, tokens, sats})` (the old pool closed
50
68
  and a new one deployed in ONE wallet createAction);
51
- - your tokens: `myTokens`, `settleSwaps` (the silent pass over staged swap legs: the txids taken
52
- in), `moveBackTokens(tokenId)` (what it did: txid, amount, BEEF, submit), `sendTokens`;
69
+ - your tokens: `myTokens`, `settleSwaps` (the pass over the swap basket: a staged token output the
70
+ basket lacks filed from its action's description; then every row's spender, this wallet's legs
71
+ taken in: the txids), `swapBasketSats`, `moveBackTokens(tokenId)` (every row of the token and
72
+ every sats row: txid, amount, BEEF, submit), `moveBackStagedSats` (the sats alone), `sendTokens`;
53
73
  - settings (root): `deployBeef`, `enableToken`, `tokensToEnable`, `disableToken`, `defaults`,
54
74
  `setDefaultTerms`, `clearDefaultTerms`, `setDefaultMarket`, `clearDefaultMarket`, `tokenTerms`,
55
- `setTokenTerms`, `discoveryState`, `setDiscovery`.
75
+ `setTokenTerms` (0.40.0: the terms `{lpBps, validatorBps, commissionBps, minLegSats?}`), `discoveryState`, `setDiscovery`.
56
76
 
57
- Pure helpers beside it: `hostedFrom`, `poolViews`, `poolFees`, `withLeg`, `hasTerms`,
77
+ Pure helpers beside it: `hostedFrom`, `parsePoolEventMessage`, `poolViews`, `poolFees`, `poolsWithMinimums`, `pairPrice`, `legCarrySats`, `hasTerms`,
58
78
  `enableCandidates`, `topicOf`, `lookupOf`, `ammLookupOf`, `walletDeployBeef`, `exchangeBase`,
59
79
  `tokenBase`; the types (`Quote`, `SwapResult`, `LegResult`, `Position`, `WalletToken`, …).
60
80
 
@@ -62,15 +82,19 @@ Pure helpers beside it: `hostedFrom`, `poolViews`, `poolFees`, `withLeg`, `hasTe
62
82
 
63
83
  An error of one of `CLIENT_ERROR_KINDS` is a `ClientError` with `kind` and the message the pages
64
84
  show: `stale_pool`, `fee_mismatch`, `quote_mismatch`, `slippage`, `pool_spent`, `user_rejected`,
65
- `no_answer`, `refused`, `network`. A swap leg that did not fill carries its `kind` beside its
66
- `error` text. `errorKind(e)` classifies any error; other errors stay plain `Error`s.
85
+ `no_answer`, `below_minimum` (0.40.0: under a validator's minimum leg; a quote no pool takes),
86
+ `refused`, `network`. `errorKind(e)` classifies any error; other errors stay plain `Error`s.
67
87
 
68
88
  ## The shared names
69
89
 
70
90
  What two sites must use to file identical wallet rows: `POOLS_BASKET` (`amm-pools`, the LP's
71
91
  position rows), `SWAP_BASKET` (`amm-swap`, what swap legs spend), `SWAP_PROTOCOL` (`[2, "amm
72
- swap"]`), `SWAP_KEY_PREFIX` + `swapKeyID` (the staged rows' keyIDs), `swapInstructions` /
73
- `swapSatsInstructions` (their customInstructions), `LP_KEY_PROTOCOL` (BRC-29) + `LP_KEY_MARK` +
92
+ swap"]`), `SWAP_KEY_PREFIX` + `newSwapKeyID` (a staged row's random keyID), `changeKeyID` (a leg's
93
+ change row: `amm-swap-<txid>.<vout>:change` of its first input of that kind), `SWAP_STAGE_LABEL`
94
+ (`amm-swap-stage`) + `SWAP_KEY_MARK` + `swapKeyDescription` / `swapKeyIdOfDescription` (a staged
95
+ token output's description naming its key), `legDerivation` (an order's payout, own commission and
96
+ last-leg change keys), `swapInstructions` / `swapSatsInstructions` (their customInstructions, a
97
+ change row's with `order`), `LP_KEY_PROTOCOL` (BRC-29) + `LP_KEY_MARK` +
74
98
  `lpKeyDescription` / `lpKeyIdOfDescription` (the deploy's pool output description naming the LP
75
99
  keyID), `POOL_TAG` / `POOL_OP` / `isPoolRow` / `poolCustomInstructions` (an `amm-pools` row),
76
100
  `POOL_DEPLOY_LABEL` (`amm-pool-deploy`), `SWAP_TTL_MS` (15 s), `transferPlanLabels` (the `p color
@@ -85,20 +109,36 @@ import { createClient, ClientError } from "@dcasegr/amm-client";
85
109
  const client = createClient({ origin: "https://swap.skein.nexus", wallet });
86
110
  const tokenId = "<txid>_0";
87
111
 
88
- // The token's pools route as an event stream: the pools a swap may use, the market.
89
- const stop = client.watchTokenPools(tokenId, async (pools) => {
90
- stop();
91
- const quote = client.quoteSwap({ tokenId, side: "buy", amountIn: 50_000n, maxSlippageBps: 50, allowPartial: false }, pools, { sym: "TOK", dec: 0 });
92
- try {
93
- const result = await client.executeSwap(quote, { onProgress: (p) => console.log(p.phase) });
94
- console.log(result.status, result.legs);
95
- } catch (e) {
96
- if (e instanceof ClientError && e.kind === "pool_spent") console.log("quote again");
97
- else throw e;
98
- }
99
- });
112
+ // The token's pools route: the pools a swap may use, the market (read again on a pool event).
113
+ const pools = await client.tokenPools(tokenId);
114
+ const quote = client.quoteSwap({ tokenId, side: "buy", amountIn: 50_000n, maxSlippageBps: 50, maxSources: 1 }, pools, { sym: "TOK", dec: 0 });
115
+ try {
116
+ const cancel = new AbortController();
117
+ const result = await client.executeSwap(quote, { signal: cancel.signal, onProgress: (p) => console.log(p.phase) });
118
+ console.log(result.status, result.stop, result.legs, result.returned);
119
+ } catch (e) {
120
+ if (e instanceof ClientError) console.log(e.kind, e.message);
121
+ else throw e;
122
+ }
100
123
  ```
101
124
 
125
+ `executeSwap` (0.40.0; 0.40.2: at most `maxSources` legs, the budget down by one per FILLED leg —
126
+ a refused or unanswered leg does not count, the last leg takes all that remains): ONE swap at a time. First the pass over the swap basket, then ONE wallet
127
+ action stages what `amm-swap` lacks of `quote.stage` (sats only: a plain createAction; a sell's
128
+ tokens: the module transfer). Then legs one at a time: the SERVER's pool list read fresh (0.41.0:
129
+ `GET /@<token>/amm/pools` before EACH leg; the client keeps no list of its own), the engine's
130
+ `nextLeg` over it (`minOut` = the quote's floor less what has filled), the pool's current output by
131
+ its id (`/pools/beef?pool=`), the staged rows that cover the leg (largest first), built, signed,
132
+ relayed; accepted → taken in (payout, own commission, change) before the next leg; refused
133
+ `pool_spent` → the list read again (the relaying host took the validator's state in before it
134
+ answered, 0.41.0); refused otherwise → that pool output excluded; no answer → the overlay
135
+ (a staged input spent: the leg landed), else sent once more, else raced on another pool. It stops
136
+ `filled | cancelled | floor | min | no_pool | fees`. Filled: the last leg's change went to the
137
+ wallet. Stopped early with rows left: `moveBack` runs itself (`result.returned`). Progress phases:
138
+ `staging`, `relaying` / `repricing` (the leg's pool, amounts and the legs filled so far),
139
+ `returning`, `done` / `failed`. The result: `{status, stop, legs: [{poolOutpoint, poolId,
140
+ amountIn, amountOut, txid}], totalIn, totalOut, unfilled, returned?}`.
141
+
102
142
  ## Build
103
143
 
104
144
  From skein-amm's `web/`: `npm ci` in `ui` and in `engine`, then `npm pack` here (the build
package/dist/client.d.ts CHANGED
@@ -11,23 +11,27 @@
11
11
  *
12
12
  * - **The token list** (`GET <swap>/tokens`): read ONCE per client (D4; `enabledList`), again
13
13
  * only after its own enable or disable changed it.
14
- * - **Prices** (D6, D22): the host-wide pools route `GET <origin>/amm/pools` (`hostedTokens`,
15
- * `watchHostedPools`); a token's price is Σsats / Σtokens over its listed pools.
16
- * - **Swap** (D11–D16): the token's pools route `GET /@<token>/amm/pools` held as an event stream
17
- * (`watchTokenPools`): the pools whose validator is beating and whose commission meets the
18
- * market's minimum (the host's filter), the market's commission key hash; a quote is the
19
- * matching engine's plan over that list (no request); a swap reads ONE `GET
20
- * /@<token>/amm/pools/beef?lp=` for its legs (freshness, the pools' BEEF), then each leg's relay
21
- * request (`amm.swap.submit`, held by the host until the relay rests; 15 s expiry); a lost answer
22
- * is "no answer yet" with "Check again" (`GET /@<token>/amm/swaps?id=`, once).
23
- * - **Liquidity** (D9, D23): the wallet's pool rows and deploy history, then ONE `GET
24
- * /@<token>/amm/positions?lp=` per token; a deploy the history has but the basket lacks is
25
- * filed then; Close and Rebalance read their pool's BEEF by LP key (`/pools/beef?lp=`); the
26
- * deploy's terms `GET /@<token>/amm/terms`.
14
+ * - **Prices** (0.39.0, D3, D7): ONE read of the host-wide stats `GET <origin>/amm/stats`
15
+ * (`hostedTokens`): each token's price, liquidity (TVL) and pool count; no host-wide stream.
16
+ * - **History** (0.39.0, D1–D6): `trades`, `trade`, `candles`, `stats`, `statsAll`, `holders`,
17
+ * `positionsAll` — plain GETs of the history routes (H1–H6, src/lib/overlay.ts).
18
+ * - **Swap** (D11–D16; 0.40.0; 0.41.0): the token's pools route `GET /@<token>/amm/pools`, a plain
19
+ * read (`tokenPools`): the pools whose validator is beating and whose commission meets the
20
+ * market's minimum (the host's filter), each validator's minimum leg, the market's commission key
21
+ * hash; a quote is the matching engine's plan over that list (no request); a swap (`executeSwap`)
22
+ * stages what the swap basket lacks by ONE wallet action, then per leg the pools route read fresh,
23
+ * ONE `GET /@<token>/amm/pools/beef?pool=` and the leg's relay request (`amm.swap.submit`, held by
24
+ * the host until the relay rests; 15 s expiry); no answer → the host's `GET /amm/spends`, once
25
+ * more, a race. The pool events (`watchPoolEvents`, 0.41.0: the host's feeds) are signals for
26
+ * display: a page reads the route again on one.
27
+ * - **Liquidity** (D9, D23; 0.40.0: by pool id): the wallet's pool rows and deploy history, then
28
+ * ONE `GET /@<token>/amm/positions?pool=` per token; a deploy the history has but the basket
29
+ * lacks is filed then; Close and Rebalance read their pool's BEEF by its id (`/pools/beef?pool=`);
30
+ * the deploy's terms `GET /@<token>/amm/terms`.
27
31
  * - **Your tokens** (D17, D18, D19, D24): the wallet's module and the swap basket; the token list
28
- * once and ONE discovery `GET /@discovery/1color/tokens?ids=` for held tokens the list lacks; a
29
- * silent pass over the swap basket's staged legs (src/wallet/swapPayouts.ts); Move back submits
30
- * at the host root.
32
+ * once and ONE discovery `GET /@discovery/1color/tokens?ids=` for held tokens the list lacks; the
33
+ * pass over the swap basket (0.40.0: ONE `GET /amm/spends` over every row,
34
+ * src/wallet/swapPayouts.ts); Move back submits at the host root.
31
35
  * - **Settings** (D20, D21): the claim card (`claimStatus`: swap's identity, the recipient of
32
36
  * root's messages), the token list once, discovery's list and ONE `?ids=` read; Enable's deploy
33
37
  * BEEF from the wallet's basket else `GET /@discovery/1color/<token>/deploy`.
@@ -39,14 +43,13 @@
39
43
  */
40
44
  import { type WalletInterface } from "@bsv/sdk";
41
45
  import { type Send1ColorResult } from "@1sat/actions";
42
- import { type PoolState, type Plan } from "@dcasegr/amm-engine";
43
- import { type LiveAnswer, type PoolRow, type PoolsAnswer, type SignedFetch } from "./lib/overlay.js";
46
+ import { type Leg, type PoolState, type Plan, type PricePair } from "@dcasegr/amm-engine";
47
+ import { type Candle, type CandleSeries, type CandleTf, type PoolAt, type PoolHistoryPage, type SpendAll, type Holders, type TokenPosition, type TokenStats, type Trade, type TradesPage, type PoolRow, type PoolsAnswer, type PoolEventMessage, type SignedFetch } from "./lib/overlay.js";
44
48
  import { type Defaults, type Discovery, type EnabledToken, type ListedToken } from "./lib/skein.js";
45
49
  import type { AuthFetchLike } from "./market/relay.js";
46
- import { type PreparedSwap } from "./market/swapAction.js";
47
50
  import { type MovedBack } from "./market/activeSwap.js";
48
51
  import { type PositionRow } from "./lp/positions.js";
49
- import { ClientError, type ClientErrorKind } from "./errors.js";
52
+ import { ClientError } from "./errors.js";
50
53
  /** A token id: the BRC-207 assetId `<txid>_<vout>`, `_0` included (src/lib/tokenId.ts). */
51
54
  export type TokenId = string;
52
55
  /** What a swap of 2% of the price costs: the sats a buy needs to move the marginal price up by `bps`. */
@@ -61,7 +64,10 @@ export interface HostedToken {
61
64
  dec: number;
62
65
  /** An image URL (a data: URL of the deploy's embedded icon, or an ORDFS URL). */
63
66
  icon?: string;
64
- /** Sats per whole token across the token's pools: what the next small swap pays. Null with no open pool. */
67
+ /**
68
+ * Sats per whole token (0.40.0: the stats' `price`, the midpoint of what a buy and a sell of 1% of
69
+ * the pooled sats would pay now). Null with no open pool.
70
+ */
65
71
  marginalPrice: number | null;
66
72
  depth: Depth | null;
67
73
  /** Number of open pools. */
@@ -78,6 +84,8 @@ export interface HostedToken {
78
84
  export interface PoolView {
79
85
  /** `<txid>.<vout>` */
80
86
  outpoint: string;
87
+ /** The pool's id (0.40.0): its deploy outpoint, `<txid>_<vout>`. */
88
+ poolId: string;
81
89
  tokenId: TokenId;
82
90
  sats: bigint;
83
91
  tokens: bigint;
@@ -96,11 +104,18 @@ export interface QuoteRequest {
96
104
  amountIn: bigint;
97
105
  /** Max slippage against the quoted amount out, basis points. */
98
106
  maxSlippageBps: number;
99
- allowPartial: boolean;
107
+ /**
108
+ * 0.40.2: the most pools the order may draw on, filled legs counted — a positive integer the
109
+ * caller always gives; the fee sats staged are for exactly that many legs. 1: exactly one leg
110
+ * for the whole amount. Replaces `allowPartial` (`false` was 1).
111
+ */
112
+ maxSources: number;
100
113
  }
101
114
  export interface QuoteLeg {
102
115
  /** The pool, `<txid>.<vout>`. */
103
116
  poolOutpoint: string;
117
+ /** The pool's id (0.40.0). */
118
+ poolId: string;
104
119
  amountIn: bigint;
105
120
  amountOut: bigint;
106
121
  /** Share of the amount in, basis points (the legs sum to 10000). */
@@ -111,37 +126,64 @@ export interface QuoteLeg {
111
126
  tokens: bigint;
112
127
  };
113
128
  validator: ValidatorRef;
129
+ /** The leg's own pool's fees (0.40.0: the fee line per leg). */
130
+ fees: Fees;
131
+ }
132
+ /** What Swap stages into the swap basket before its first leg (0.40.0): the swap amount exact, and the fee sats. */
133
+ export interface QuoteStage {
134
+ /** The swap amount: sats on a buy, token base units on a sell. */
135
+ amount: bigint;
136
+ /** The sats for the carriers and miner fees of `maxSources` legs (0.40.2). */
137
+ feeSats: bigint;
114
138
  }
115
139
  export interface Quote {
116
140
  request: QuoteRequest;
117
141
  legs: QuoteLeg[];
118
142
  amountOut: bigint;
119
- /** The least amount out the swap accepts: amountOut less max slippage. */
143
+ /** The least amount out the swap accepts (the floor): the route's amount out less max slippage. */
120
144
  minAmountOut: bigint;
121
145
  /** Sats per whole token this swap pays (fees included). */
122
146
  effectivePrice: number;
123
- /** Sats per whole token before the swap. */
147
+ /**
148
+ * Sats per whole token now (0.40.0: the engine's `priceOf` over the pools the page holds — what a
149
+ * buy of 1% of the pooled sats would pay on a buy, a sell of 1% of the pooled tokens on a sell).
150
+ */
124
151
  marginalPrice: number;
125
152
  /** |effective − marginal| / marginal, basis points. */
126
153
  impactBps: number;
127
- /** The validator's fees applied to every leg. */
128
- fees: Fees;
154
+ /** What Swap stages (0.40.0). */
155
+ stage: QuoteStage;
156
+ /** The miner fee estimate of one leg, sats. */
157
+ legMinerFeeSats: bigint;
129
158
  }
159
+ /** One leg of a swap that filled (0.40.0). */
130
160
  export interface LegResult {
161
+ /** The pool output it spent, `<txid>.<vout>`. */
131
162
  poolOutpoint: string;
132
- status: "filled" | "failed";
133
- txid?: string;
134
- error?: string;
135
- /** 0.31.1: the leg was refused `pool_spent`, repriced against the pool's newest state and sent again. */
136
- repriced?: true;
137
- /** 0.34.0 (D15): no answer yet — the swap's id, for "Check again" (`checkSwapAgain`). */
138
- checkId?: string;
139
- /** 0.38.0 (D13): the failure's kind, when it has one (`error` stays the text). */
140
- kind?: ClientErrorKind;
163
+ poolId: string;
164
+ amountIn: bigint;
165
+ amountOut: bigint;
166
+ txid: string;
141
167
  }
168
+ /** Why a swap stopped (0.40.0). */
169
+ export type SwapStop = "filled" | "cancelled" | "floor" | "min" | "no_pool" | "fees";
142
170
  export interface SwapResult {
171
+ /** "filled": every unit filled; "partial": some; "failed": none. */
143
172
  status: "filled" | "partial" | "failed";
173
+ stop: SwapStop;
174
+ /** The legs that filled, in order. */
144
175
  legs: LegResult[];
176
+ totalIn: bigint;
177
+ totalOut: bigint;
178
+ /** The swap amount not filled. */
179
+ unfilled: bigint;
180
+ /** What went back to the wallet when the swap stopped early (the Move back's), or why it did not. */
181
+ returned?: {
182
+ txid: string;
183
+ tokens: bigint;
184
+ } | {
185
+ error: string;
186
+ };
145
187
  }
146
188
  /** The validator's fees, basis points of the amount in. The LP accepts them; there is no fee input. */
147
189
  export interface Fees {
@@ -169,11 +211,17 @@ export interface ValidatorTerms {
169
211
  /** "this exchange's" when the validator is this skein. */
170
212
  isThisExchange: boolean;
171
213
  fees: Fees;
214
+ /** The validator's minimum leg, sats on the leg's sats side (0.40.0; 0: none). */
215
+ minLegSats: number;
172
216
  }
173
217
  /** One of the user's pools. A position is only deployed or closed (no add, no partial remove). */
174
218
  export interface Position {
175
219
  /** The pool, `<txid>.<vout>`. */
176
220
  outpoint: string;
221
+ /** The pool's id (0.40.0): its deploy outpoint, `<txid>_<vout>`. */
222
+ poolId: string;
223
+ /** The pool's swaps so far. */
224
+ swaps: number;
177
225
  tokenId: TokenId;
178
226
  sym: string;
179
227
  dec: number;
@@ -241,8 +289,6 @@ export interface WalletToken {
241
289
  outputs: number;
242
290
  /** Held in the exchange's active swap basket (`amm-swap`): spent by swap legs, or moved back. */
243
291
  inSwaps: bigint;
244
- /** Sats staged in `amm-swap` for the token's swap legs (0.29.6): spent by swap legs, or moved back. */
245
- swapSats: number;
246
292
  /** Registered on this exchange. */
247
293
  onExchange: boolean;
248
294
  }
@@ -262,7 +308,10 @@ export interface RegisteredToken {
262
308
  icon?: string;
263
309
  status: EnabledToken["status"];
264
310
  }
265
- export type { EnabledToken, Defaults, Discovery, PoolRow, PoolsAnswer };
311
+ export type { EnabledToken, Defaults, Discovery, PoolRow, PoolsAnswer, Candle, CandleSeries, CandleTf, Holders, PoolAt, PoolHistoryPage, SpendAll, TokenPosition, TokenStats, Trade, TradesPage };
312
+ export type { PoolEvent, PoolEventMessage, PoolRevert } from "./lib/overlay.js";
313
+ export type { Price } from "./lib/overlay.js";
314
+ export { parsePoolEventMessage } from "./lib/overlay.js";
266
315
  /** A token's symbol, decimals and icon, read off its deploy output. */
267
316
  export interface DeployMeta {
268
317
  sym?: string;
@@ -287,17 +336,29 @@ export interface ClaimStatus {
287
336
  claimant?: string;
288
337
  }
289
338
  /**
290
- * The hosted tokens (the enabled 1Color tokens at output 0), each priced from its rows of the
291
- * host-wide pools route (D6, D22: P1, the pools whose validator is beating): Σsats / Σtokens.
292
- * `rows` null: not read yet (no prices). Pure.
339
+ * The hosted tokens (the enabled 1Color tokens at output 0), each with its record of the host-wide
340
+ * stats (0.39.0, D3, D7: H4): the price (`price`, sats per whole token), the liquidity (`tvlSats`,
341
+ * `tvlTokens`) and the pool count. `stats` null: not read yet (no prices); a token the stats lack:
342
+ * no price, no pools. Pure.
293
343
  */
294
- export declare function hostedFrom(list: EnabledToken[], rows: PoolRow[] | null): HostedToken[];
344
+ export declare function hostedFrom(list: EnabledToken[], stats: TokenStats[] | null): HostedToken[];
295
345
  /** The pools the Swap page lists (D11, D13): the token's pools route's rows, every validator live (the host lists no other). */
296
346
  export declare function poolViews(answer: PoolsAnswer | null, tokenId: TokenId): PoolView[];
297
347
  /** The fees a pool's own record names (D13: the Swap page's fee line), basis points. */
298
348
  export declare function poolFees(p: Pick<PoolState, "liquidityFeeBps" | "validationFeeBps" | "commissionBps">): Fees;
299
- /** A swap's result with one leg replaced (after "Check again"). */
300
- export declare function withLeg(r: SwapResult, leg: LegResult): SwapResult;
349
+ /**
350
+ * A pools answer's rows as the planner takes them (0.40.0): each pool with its validator's
351
+ * minimum leg (`validators[].minLegSats`, the validator's announced terms).
352
+ */
353
+ export declare function poolsWithMinimums(answer: PoolsAnswer): PoolRow[];
354
+ /** Sats per whole token of an exact pair (`sats` per `tokens` base units), 0 when `tokens` is 0. */
355
+ export declare function pairPrice(p: PricePair, dec: number): number;
356
+ /**
357
+ * A leg's sats beyond its amount in (0.40.0, the stage's fee sats): the miner fee estimate plus its
358
+ * 1-sat carriers — on a buy the token payout; on a sell the token fee and commission outputs that
359
+ * are not zero, and the token change.
360
+ */
361
+ export declare function legCarrySats(leg: Pick<Leg, "liquidityFee" | "validationFee" | "commission">, buy: boolean, minerFeeSats: bigint): bigint;
301
362
  /**
302
363
  * wallet-toolbox's `specOpWalletBalance` (`sdk.specOpWalletBalance`, @bsv/wallet-toolbox-client): the listOutputs "basket" of its
303
364
  * balance special operation. Written out, not imported: the client package exports it only inside its `sdk` namespace, which
@@ -336,18 +397,17 @@ export interface EnableCandidate {
336
397
  * instance's list (enabled or disabled) left out. Pure: the reads are `tokensToEnable`'s.
337
398
  */
338
399
  export declare function enableCandidates(listed: ListedToken[], walletIds: string[], onList: string[]): EnableCandidate[];
339
- /** The three fees root sets (basis points, integers 0 to 10 000). */
400
+ /** The three fees root sets (basis points, integers 0 to 10 000), and (0.40.0) the minimum leg in sats (absent or 0: none). */
340
401
  export interface TermsInput {
341
402
  lpBps: number;
342
403
  validatorBps: number;
343
404
  commissionBps: number;
405
+ minLegSats?: number;
344
406
  }
345
407
  /** What a quote was planned from: kept for its execution. */
346
408
  interface Planned {
347
409
  plan: Plan;
348
- pools: PoolRow[];
349
- live: LiveAnswer;
350
- market: PoolsAnswer["market"];
410
+ answer: PoolsAnswer;
351
411
  dec: number;
352
412
  sym: string;
353
413
  }
@@ -372,15 +432,31 @@ export interface ClientOptions {
372
432
  /** The wallet's identity key, when the caller has it (the claim's check). Default: read from the wallet when needed. */
373
433
  identityKey?: string | null;
374
434
  }
375
- /** Where a swap is (`executeSwap`'s `onProgress`, D12), in this order; `leg` the pool outpoint (`<txid>.<vout>`) of a leg event. */
435
+ /**
436
+ * Where a swap is (`executeSwap`'s `onProgress`, D12; 0.40.0): `staging` (what the swap basket
437
+ * lacks is staged), `relaying` (a leg sent: its pool outpoint `<txid>.<vout>` and amounts, and the
438
+ * legs filled so far), `repricing` (a leg refused `pool_spent`, the pool's row replaced),
439
+ * `returning` (a swap that stopped early moves its rows back), then `done` or `failed`.
440
+ */
376
441
  export type SwapProgress = {
377
442
  phase: "staging";
443
+ sats: bigint;
444
+ tokens: bigint;
378
445
  } | {
379
446
  phase: "relaying";
380
447
  leg: string;
448
+ amountIn: bigint;
449
+ amountOut: bigint;
450
+ filled: LegResult[];
381
451
  } | {
382
452
  phase: "repricing";
383
453
  leg: string;
454
+ amountIn: bigint;
455
+ amountOut: bigint;
456
+ filled: LegResult[];
457
+ } | {
458
+ phase: "returning";
459
+ filled: LegResult[];
384
460
  } | {
385
461
  phase: "done";
386
462
  result: SwapResult;
@@ -390,8 +466,10 @@ export type SwapProgress = {
390
466
  error?: ClientError | Error;
391
467
  };
392
468
  export interface SwapOptions {
393
- /** Called as the swap moves (D12): `staging` (the swap basket is filled for the legs), `relaying` (per leg), `repricing` (a leg refused `pool_spent`, re-quoted), then `done` (a leg filled) or `failed` (none did, or it threw). */
469
+ /** Called as the swap moves (see `SwapProgress`). */
394
470
  onProgress?: (p: SwapProgress) => void;
471
+ /** Aborted: the swap stops before its next leg (`cancelled`). */
472
+ signal?: AbortSignal;
395
473
  }
396
474
  /** What a client remembers between calls; shared by `withWallet`'s clients. */
397
475
  interface Shared {
@@ -401,12 +479,8 @@ interface Shared {
401
479
  claimRead: ClaimStatus | null;
402
480
  /** What each quote was planned from: kept for its execution. */
403
481
  planned: WeakMap<Quote, Planned>;
404
- /** The legs whose answer did not come: their prepared swap, for "Check again" (D15). */
405
- checks: Map<string, {
406
- prepared: PreparedSwap;
407
- base: string;
408
- af: Signed;
409
- }>;
482
+ /** A swap is running (0.40.0: one at a time). */
483
+ swapping: boolean;
410
484
  /** The positions last loaded, by the output a Close acts on (`<txid>.<vout>`): the wallet's row (its LP key) and the token. */
411
485
  loaded: Map<string, PositionRow>;
412
486
  /** `onDataChange`'s listeners. */
@@ -444,15 +518,47 @@ declare function makeClient(opts: ClientOptions, s: Shared): {
444
518
  isRoot: (identityKey: string | null) => Promise<boolean>;
445
519
  claimExchange: () => Promise<boolean>;
446
520
  hostedTokens: () => Promise<HostedToken[]>;
447
- watchHostedPools: (onRows: (rows: PoolRow[]) => void, onLive?: (live: boolean) => void) => () => void;
448
- watchTokenPools: (tokenId: TokenId, onAnswer: (a: PoolsAnswer) => void, onError?: (e: unknown) => void) => () => void;
521
+ tokenPools: (tokenId: string) => Promise<PoolsAnswer>;
522
+ watchPoolEvents: (tokenId: TokenId | "all", onEvent: (e: PoolEventMessage) => void, onError?: (e: unknown) => void) => () => void;
523
+ trades: (tokenId: string, o?: {
524
+ from?: number;
525
+ to?: number;
526
+ limit?: number;
527
+ before?: string;
528
+ pool?: string;
529
+ } | undefined) => Promise<TradesPage>;
530
+ trade: (tokenId: string, txid: string) => Promise<Trade | null>;
531
+ candles: (tokenId: string, o: {
532
+ tf: CandleTf;
533
+ from: number;
534
+ to: number;
535
+ series?: CandleSeries;
536
+ }) => Promise<Candle[]>;
537
+ poolsAt: (tokenId: string, t: number) => Promise<PoolAt[]>;
538
+ poolHistory: (tokenId: string, o?: {
539
+ from?: number;
540
+ to?: number;
541
+ pool?: string;
542
+ limit?: number;
543
+ after?: string;
544
+ } | undefined) => Promise<PoolHistoryPage>;
545
+ spendsAll: (outpoints: string[]) => Promise<SpendAll[]>;
546
+ stats: (tokenId: string) => Promise<TokenStats>;
547
+ statsAll: (o?: {
548
+ ids?: TokenId[];
549
+ fresh?: boolean;
550
+ } | undefined) => Promise<TokenStats[]>;
551
+ holders: (tokenId: string, o?: {
552
+ limit?: number;
553
+ skip?: number;
554
+ } | undefined) => Promise<Holders>;
555
+ positionsAll: (poolIds: string[]) => Promise<TokenPosition[]>;
449
556
  registeredTokens: () => Promise<RegisteredToken[]>;
450
557
  quoteSwap: (req: QuoteRequest, held: PoolsAnswer | null, meta: {
451
558
  sym: string;
452
559
  dec: number;
453
560
  }) => Quote;
454
561
  executeSwap: (quote: Quote, o?: SwapOptions) => Promise<SwapResult>;
455
- checkSwapAgain: (leg: LegResult) => Promise<LegResult>;
456
562
  walletSats: () => Promise<bigint>;
457
563
  myPositions: () => Promise<Position[]>;
458
564
  validatorTerms: (tokenId: string) => Promise<NoTerms | ValidatorTerms>;
@@ -461,6 +567,8 @@ declare function makeClient(opts: ClientOptions, s: Shared): {
461
567
  rebalancePosition: (req: RebalanceRequest) => Promise<RebalanceResult>;
462
568
  myTokens: () => Promise<WalletToken[]>;
463
569
  settleSwaps: () => Promise<string[]>;
570
+ swapBasketSats: () => Promise<number>;
571
+ moveBackStagedSats: () => Promise<MovedBack>;
464
572
  moveBackTokens: (tokenId: string) => Promise<MovedBack>;
465
573
  sendTokens: (tokenId: string, handle: string, amount: bigint, memo?: string | undefined) => Promise<Send1ColorResult>;
466
574
  deployBeef: (tokenId: string, wallet?: WalletInterface | null | undefined) => Promise<DeployFound>;
@@ -475,6 +583,7 @@ declare function makeClient(opts: ClientOptions, s: Shared): {
475
583
  lpFeeBps: number;
476
584
  validatorFeeBps: number;
477
585
  commissionBps: number;
586
+ minLegSats: number;
478
587
  } | null>;
479
588
  setTokenTerms: (tokenId: string, t: TermsInput | null) => Promise<void>;
480
589
  clearDefaultTerms: () => Promise<void>;
@@ -493,15 +602,47 @@ declare function makeClient(opts: ClientOptions, s: Shared): {
493
602
  isRoot: (identityKey: string | null) => Promise<boolean>;
494
603
  claimExchange: () => Promise<boolean>;
495
604
  hostedTokens: () => Promise<HostedToken[]>;
496
- watchHostedPools: (onRows: (rows: PoolRow[]) => void, onLive?: (live: boolean) => void) => () => void;
497
- watchTokenPools: (tokenId: TokenId, onAnswer: (a: PoolsAnswer) => void, onError?: (e: unknown) => void) => () => void;
605
+ tokenPools: (tokenId: string) => Promise<PoolsAnswer>;
606
+ watchPoolEvents: (tokenId: TokenId | "all", onEvent: (e: PoolEventMessage) => void, onError?: (e: unknown) => void) => () => void;
607
+ trades: (tokenId: string, o?: {
608
+ from?: number;
609
+ to?: number;
610
+ limit?: number;
611
+ before?: string;
612
+ pool?: string;
613
+ } | undefined) => Promise<TradesPage>;
614
+ trade: (tokenId: string, txid: string) => Promise<Trade | null>;
615
+ candles: (tokenId: string, o: {
616
+ tf: CandleTf;
617
+ from: number;
618
+ to: number;
619
+ series?: CandleSeries;
620
+ }) => Promise<Candle[]>;
621
+ poolsAt: (tokenId: string, t: number) => Promise<PoolAt[]>;
622
+ poolHistory: (tokenId: string, o?: {
623
+ from?: number;
624
+ to?: number;
625
+ pool?: string;
626
+ limit?: number;
627
+ after?: string;
628
+ } | undefined) => Promise<PoolHistoryPage>;
629
+ spendsAll: (outpoints: string[]) => Promise<SpendAll[]>;
630
+ stats: (tokenId: string) => Promise<TokenStats>;
631
+ statsAll: (o?: {
632
+ ids?: TokenId[];
633
+ fresh?: boolean;
634
+ } | undefined) => Promise<TokenStats[]>;
635
+ holders: (tokenId: string, o?: {
636
+ limit?: number;
637
+ skip?: number;
638
+ } | undefined) => Promise<Holders>;
639
+ positionsAll: (poolIds: string[]) => Promise<TokenPosition[]>;
498
640
  registeredTokens: () => Promise<RegisteredToken[]>;
499
641
  quoteSwap: (req: QuoteRequest, held: PoolsAnswer | null, meta: {
500
642
  sym: string;
501
643
  dec: number;
502
644
  }) => Quote;
503
645
  executeSwap: (quote: Quote, o?: SwapOptions) => Promise<SwapResult>;
504
- checkSwapAgain: (leg: LegResult) => Promise<LegResult>;
505
646
  walletSats: () => Promise<bigint>;
506
647
  myPositions: () => Promise<Position[]>;
507
648
  validatorTerms: (tokenId: string) => Promise<NoTerms | ValidatorTerms>;
@@ -510,6 +651,8 @@ declare function makeClient(opts: ClientOptions, s: Shared): {
510
651
  rebalancePosition: (req: RebalanceRequest) => Promise<RebalanceResult>;
511
652
  myTokens: () => Promise<WalletToken[]>;
512
653
  settleSwaps: () => Promise<string[]>;
654
+ swapBasketSats: () => Promise<number>;
655
+ moveBackStagedSats: () => Promise<MovedBack>;
513
656
  moveBackTokens: (tokenId: string) => Promise<MovedBack>;
514
657
  sendTokens: (tokenId: string, handle: string, amount: bigint, memo?: string | undefined) => Promise<Send1ColorResult>;
515
658
  deployBeef: (tokenId: string, wallet?: WalletInterface | null | undefined) => Promise<DeployFound>;
@@ -524,6 +667,7 @@ declare function makeClient(opts: ClientOptions, s: Shared): {
524
667
  lpFeeBps: number;
525
668
  validatorFeeBps: number;
526
669
  commissionBps: number;
670
+ minLegSats: number;
527
671
  } | null>;
528
672
  setTokenTerms: (tokenId: string, t: TermsInput | null) => Promise<void>;
529
673
  clearDefaultTerms: () => Promise<void>;