@dcasegr/amm-client 0.41.1 → 0.42.3

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
@@ -72,7 +72,13 @@ The client (each an async function unless noted):
72
72
  every sats row: txid, amount, BEEF, submit), `moveBackStagedSats` (the sats alone), `sendTokens`;
73
73
  - settings (root): `deployBeef`, `enableToken`, `tokensToEnable`, `disableToken`, `defaults`,
74
74
  `setDefaultTerms`, `clearDefaultTerms`, `setDefaultMarket`, `clearDefaultMarket`, `tokenTerms`,
75
- `setTokenTerms` (0.40.0: the terms `{lpBps, validatorBps, commissionBps, minLegSats?}`), `discoveryState`, `setDiscovery`.
75
+ `setTokenTerms` (0.40.0: the terms `{lpBps, validatorBps, commissionBps, minLegSats?}`), `discoveryState`, `setDiscovery`,
76
+ `setEnablePrice`, `exchangeWallet`, `withdrawAll`, `settleWithdrawals` (0.42.x);
77
+ - the paid enable (0.42.2, anyone signed; open-exchange 0.15.3): `enableTokenPaid(tokenId, {deployBeef?})` — the price
78
+ from `/amm/defaults`, a BRC-29 payment to the exchange built as a protected noSend (0.42.3: BRC-177, `p nosend expiry seconds 600`; not sent: the exchange's take-in sends it),
79
+ ONE BEEF with the deploy and the payment, `POST /amm/enable?tokenId=&paymentTxid=&paymentVout=&derivationPrefix=
80
+ &derivationSuffix=` signed; the enabled row back; on any refusal or failure the unsent payment is aborted
81
+ (`abortAction`). Refusals are `ClientError` kind `refused`, the exchange's code first in the message.
76
82
 
77
83
  Pure helpers beside it: `hostedFrom`, `parsePoolEventMessage`, `poolViews`, `poolFees`, `poolsWithMinimums`, `pairPrice`, `legCarrySats`, `hasTerms`,
78
84
  `enableCandidates`, `topicOf`, `lookupOf`, `ammLookupOf`, `walletDeployBeef`, `exchangeBase`,
package/dist/client.d.ts CHANGED
@@ -45,7 +45,7 @@ import { type WalletInterface } from "@bsv/sdk";
45
45
  import { type Send1ColorResult } from "@1sat/actions";
46
46
  import { type Leg, type PoolState, type Plan, type PricePair } from "@dcasegr/amm-engine";
47
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";
48
- import { type Defaults, type Discovery, type EnabledToken, type ListedToken } from "./lib/skein.js";
48
+ import { type Defaults, type Discovery, type EnabledToken, type ExchangeWallet, type ListedToken } from "./lib/skein.js";
49
49
  import type { AuthFetchLike } from "./market/relay.js";
50
50
  import { type MovedBack } from "./market/activeSwap.js";
51
51
  import { type PositionRow } from "./lp/positions.js";
@@ -308,7 +308,7 @@ export interface RegisteredToken {
308
308
  icon?: string;
309
309
  status: EnabledToken["status"];
310
310
  }
311
- export type { EnabledToken, Defaults, Discovery, PoolRow, PoolsAnswer, Candle, CandleSeries, CandleTf, Holders, PoolAt, PoolHistoryPage, SpendAll, TokenPosition, TokenStats, Trade, TradesPage };
311
+ export type { EnabledToken, Defaults, Discovery, ExchangeWallet, PoolRow, PoolsAnswer, Candle, CandleSeries, CandleTf, Holders, PoolAt, PoolHistoryPage, SpendAll, TokenPosition, TokenStats, Trade, TradesPage };
312
312
  export type { PoolEvent, PoolEventMessage, PoolRevert } from "./lib/overlay.js";
313
313
  export type { Price } from "./lib/overlay.js";
314
314
  export { parsePoolEventMessage } from "./lib/overlay.js";
@@ -391,6 +391,8 @@ export interface EnableCandidate {
391
391
  onDiscovery: boolean;
392
392
  inWallet: boolean;
393
393
  }
394
+ /** 0.42.3: the paid enable's payment is a protected noSend (BRC-177): the wallet reclaims it if nobody sends it within 600 s. */
395
+ export declare const ENABLE_PAYMENT_EXPIRY_LABEL = "p nosend expiry seconds 600";
394
396
  /**
395
397
  * The candidates to enable: discovery's token list (its order, newest first, with its metadata),
396
398
  * then the tokens only this wallet holds (in the order held); every token already on the swap
@@ -591,6 +593,22 @@ declare function makeClient(opts: ClientOptions, s: Shared): {
591
593
  clearDefaultMarket: () => Promise<void>;
592
594
  discoveryState: () => Promise<Discovery>;
593
595
  setDiscovery: (on: boolean) => Promise<void>;
596
+ setEnablePrice: (sats: number | null) => Promise<void>;
597
+ exchangeWallet: () => Promise<ExchangeWallet>;
598
+ withdrawAll: () => Promise<{
599
+ n: number;
600
+ txid: string;
601
+ sats: number;
602
+ at: number;
603
+ outputIndex: number;
604
+ derivationPrefix: string;
605
+ derivationSuffix: string;
606
+ senderIdentityKey: string;
607
+ }>;
608
+ enableTokenPaid: (tokenId: string, o?: {
609
+ deployBeef?: number[];
610
+ } | undefined) => Promise<EnabledToken & Record<string, unknown>>;
611
+ settleWithdrawals: () => Promise<string[]>;
594
612
  };
595
613
  onDataChange: (fn: () => void) => () => void;
596
614
  forgetReads: () => void;
@@ -675,4 +693,20 @@ declare function makeClient(opts: ClientOptions, s: Shared): {
675
693
  clearDefaultMarket: () => Promise<void>;
676
694
  discoveryState: () => Promise<Discovery>;
677
695
  setDiscovery: (on: boolean) => Promise<void>;
696
+ setEnablePrice: (sats: number | null) => Promise<void>;
697
+ exchangeWallet: () => Promise<ExchangeWallet>;
698
+ withdrawAll: () => Promise<{
699
+ n: number;
700
+ txid: string;
701
+ sats: number;
702
+ at: number;
703
+ outputIndex: number;
704
+ derivationPrefix: string;
705
+ derivationSuffix: string;
706
+ senderIdentityKey: string;
707
+ }>;
708
+ enableTokenPaid: (tokenId: string, o?: {
709
+ deployBeef?: number[];
710
+ } | undefined) => Promise<EnabledToken & Record<string, unknown>>;
711
+ settleWithdrawals: () => Promise<string[]>;
678
712
  };
package/dist/client.js CHANGED
@@ -41,13 +41,14 @@
41
41
  * an outpoint is `<txid>.<vout>`. Amounts are bigints in base units; prices
42
42
  * are numbers: sats per whole token.
43
43
  */
44
- import { Beef, Transaction } from "@bsv/sdk";
44
+ import { Beef, Transaction, createNonce } from "@bsv/sdk";
45
+ import { BRC29_PROTOCOL, WALLET_PAYMENT, p2pkhHexOf } from "./wallet/brc29.js";
45
46
  import { send1Color } from "@1sat/actions";
46
47
  import { nextLeg, priceOf } from "@dcasegr/amm-engine";
47
48
  import { outpointText, parseOutpoint, parseTokenId, sdkTokenId, tokenIdText } from "./lib/tokenId.js";
48
49
  import { DEFAULT_FEE_RATE_SATS_PER_KB, appName, exchangeBase, tokenBase } from "./lib/config.js";
49
50
  import { ammLookupService, liveOfPools, parseTokenTopic, poolOutputOf, readDiscoveryDeploy, readDiscoveryIds, readDiscoveryList, readAllPositions, readAllStats, readCandles, readHolders, readPoolHistory, readPoolsAt, readPoolsBeef, readPools, readPositions, readSpendsAll, readStats, readTerms, readTrade, readTrades, readTx, eventsUrl, watchPoolEvents as watchFeed, } from "./lib/overlay.js";
50
- import { authFetchPerInstance, instanceBase, readDefaults, readDiscovery, readTokens, sendMessage } from "./lib/skein.js";
51
+ import { authFetchPerInstance, instanceBase, readDefaults, readDiscovery, readTokens, readWallet, sendMessage } from "./lib/skein.js";
51
52
  import { depthOf } from "./market/prices.js";
52
53
  import { buildPlanRequest, legMinerFeeSats, quote as planQuote } from "./market/plan.js";
53
54
  import { prepareSwap, selectLegInputs } from "./market/swapAction.js";
@@ -211,6 +212,8 @@ export async function walletDeployBeef(wallet, tokenId) {
211
212
  }
212
213
  return undefined;
213
214
  }
215
+ /** 0.42.3: the paid enable's payment is a protected noSend (BRC-177): the wallet reclaims it if nobody sends it within 600 s. */
216
+ export const ENABLE_PAYMENT_EXPIRY_LABEL = "p nosend expiry seconds 600";
214
217
  const canonicalId = (tokenId) => {
215
218
  const ref = parseTokenId(tokenId);
216
219
  return ref ? tokenIdText(ref) : null;
@@ -1286,6 +1289,162 @@ function makeClient(opts, s) {
1286
1289
  async function clearDefaultMarket() {
1287
1290
  await sendDefaults({ market: null });
1288
1291
  }
1292
+ /**
1293
+ * Sets the price to enable a token (0.42.0, open-exchange 0.15.0): the admin's `{fn: "price", args: {sats}}`
1294
+ * to swap's `<app>/admin`; the host sets it as the price of `POST /amm/enable` (any signed sender enables a
1295
+ * token for it). `null` turns the paid enable off. Refused here unless a whole number of sats, 1 or more.
1296
+ */
1297
+ async function setEnablePrice(sats) {
1298
+ if (sats !== null && (!Number.isSafeInteger(sats) || sats < 1))
1299
+ throw new Error("sats: a whole number, 1 or more (or null: off)");
1300
+ const { signedFor } = needWallet();
1301
+ const me = await swapIdentity();
1302
+ await sendMessage(signedFor(swapBase), swapBase, me, `${app()}/admin`, { fn: "price", args: { sats } });
1303
+ emit();
1304
+ }
1305
+ /** The exchange's wallet (0.42.0, open-exchange 0.15.0; `GET <swap>/wallet`, the host's read): the sats swap's wallet holds and its coin count. */
1306
+ async function exchangeWallet() {
1307
+ return readWallet(swapBase, ff);
1308
+ }
1309
+ /**
1310
+ * Enables a token for the exchange's fee (0.42.2, open-exchange 0.15.3: a BEEF submission; anyone signed, not the
1311
+ * admin): the price from `GET <swap>/defaults` (`enablePriceSats`; none → refused, "paid enable is off"); the
1312
+ * exchange's identity from `GET <swap's origin>/.well-known/skein`; the deploy's BEEF given, else discovery's
1313
+ * (`GET <origin>/@discovery/1color/<token>/deploy`). The payment, ts-stack's standard (sdk BasicBRC29): a prefix and
1314
+ * a suffix from `createNonce`, the payee key `getPublicKey({protocolID: [2, "3241645161d8"], keyID: "<prefix>
1315
+ * <suffix>", counterparty: <the exchange>})`, ONE P2PKH output of exactly the price, `createAction` with
1316
+ * `{noSend: true, randomizeOutputs: false}` and the BRC-177 label `ENABLE_PAYMENT_EXPIRY_LABEL` (0.42.3: a protected
1317
+ * noSend — the wallet prefunds an exact anchor and stores the payment, no change; a plain noSend lived only in the
1318
+ * toolbox's client-side batch, so the payer's storage never learned of it) — built and signed, NOT sent: the
1319
+ * exchange's take-in sends it; a wallet whose storage has no BRC-177 fails the createAction (surfaced). Then ONE
1320
+ * BEEF merging the deploy's and the payment's, `POST <swap>/enable?tokenId=&paymentTxid=&paymentVout=0
1321
+ * &derivationPrefix=&derivationSuffix=` signed (BRC-104). On any refusal or failure after the payment was built, the
1322
+ * unsent payment is aborted in the wallet (`abortAction`), so its coins are free again. → the enabled row.
1323
+ * Refusals are `ClientError` kind `refused` (the exchange's code first in the message); a fetch that does not get
1324
+ * through, `network`; the user declining in the wallet, `user_rejected`.
1325
+ */
1326
+ async function enableTokenPaid(tokenId, o = {}) {
1327
+ const { wallet, signedFor } = needWallet();
1328
+ const id = parseOutpoint(sdkTokenId(tokenId).replace("_", "."));
1329
+ if (!id)
1330
+ throw new Error(`not a token id: ${tokenId}`);
1331
+ const canonical = tokenIdText(id);
1332
+ const price = (await readDefaults(swapBase, freshFetch)).enablePriceSats;
1333
+ if (!price)
1334
+ throw new ClientError("refused", "paid enable is off");
1335
+ const exchange = await swapIdentity();
1336
+ let deploy = o.deployBeef;
1337
+ if (!deploy) {
1338
+ const res = await freshFetch(`${discoveryBase()}/${canonical}/deploy`);
1339
+ if (!res.ok)
1340
+ throw new ClientError("refused", `no deploy for ${canonical} on discovery (${res.status}): pass deployBeef`);
1341
+ deploy = Array.from(new Uint8Array(await res.arrayBuffer()));
1342
+ }
1343
+ const derivationPrefix = await createNonce(wallet, "self");
1344
+ const derivationSuffix = await createNonce(wallet, "self");
1345
+ const { publicKey } = await wallet.getPublicKey({ protocolID: BRC29_PROTOCOL, keyID: `${derivationPrefix} ${derivationSuffix}`, counterparty: exchange });
1346
+ const created = await wallet.createAction({
1347
+ description: "Open Exchange: enable a token",
1348
+ outputs: [{ satoshis: price, lockingScript: p2pkhHexOf(publicKey), outputDescription: "Open Exchange enable fee", customInstructions: JSON.stringify({ derivationPrefix, derivationSuffix, payee: exchange }) }],
1349
+ // 0.42.3: a protected noSend (BRC-177, as @1sat/actions' payment to a handle): the wallet prefunds an exact anchor,
1350
+ // stores the payment in its storage with no change, and reclaims it if nobody sends it in time.
1351
+ labels: [ENABLE_PAYMENT_EXPIRY_LABEL],
1352
+ options: { noSend: true, randomizeOutputs: false },
1353
+ }).catch((e) => {
1354
+ // No fallback to a plain noSend: a wallet that cannot make a protected one (BRC-177) says why.
1355
+ const c = toClientError(e);
1356
+ throw c instanceof ClientError ? c : new ClientError("refused", `the wallet could not build the protected payment (BRC-177 noSend): ${errText(e)}`, { cause: e });
1357
+ });
1358
+ const txid = created.txid;
1359
+ if (!txid || !created.tx)
1360
+ throw new Error("the wallet built no payment");
1361
+ try {
1362
+ const b = new Beef();
1363
+ b.mergeBeef(deploy);
1364
+ b.mergeBeef(created.tx);
1365
+ const q = new URLSearchParams({ tokenId: canonical, paymentTxid: txid, paymentVout: "0", derivationPrefix, derivationSuffix });
1366
+ let res;
1367
+ try {
1368
+ res = await signedFor(swapBase).fetch(`${swapBase}/enable?${q.toString()}`, { method: "POST", headers: { "content-type": "application/octet-stream" }, body: Uint8Array.from(b.toBinary()) });
1369
+ }
1370
+ catch (e) {
1371
+ // The stock AuthFetch takes every 402 for its own payment wire and throws on this route's (no x-bsv-payment-* headers).
1372
+ if (/x-bsv-payment/.test(errText(e)))
1373
+ throw new ClientError("refused", "ERR_PAYMENT_REQUIRED: the exchange did not take this payment (402; its price may have changed)", { cause: e });
1374
+ throw e;
1375
+ }
1376
+ const v = (await res.json().catch(() => ({})));
1377
+ if (res.status !== 200)
1378
+ throw new ClientError("refused", `${String(v.code ?? res.status)}: ${String(v.description ?? v.message ?? "refused")}`);
1379
+ s.listRead = null;
1380
+ emit();
1381
+ return v.result;
1382
+ }
1383
+ catch (e) {
1384
+ await wallet.abortAction({ reference: txid }).catch(() => { });
1385
+ throw e;
1386
+ }
1387
+ }
1388
+ /** A withdrawal's payment taken in by the admin's wallet: `internalizeAction`, output `outputIndex` as a wallet payment from swap (BRC-29, ts-stack's recipient side). */
1389
+ async function takeInWithdrawal(wallet, x, tx) {
1390
+ const r = await wallet.internalizeAction({
1391
+ tx,
1392
+ outputs: [{ outputIndex: x.outputIndex, protocol: WALLET_PAYMENT, paymentRemittance: { derivationPrefix: x.derivationPrefix, derivationSuffix: x.derivationSuffix, senderIdentityKey: x.senderIdentityKey } }],
1393
+ description: `Open Exchange withdraw ${x.n}`,
1394
+ });
1395
+ return r.accepted;
1396
+ }
1397
+ /** Withdrawal `n`'s Atomic BEEF (`GET <swap>/wallet/tx?n=`). */
1398
+ async function withdrawalTx(n) {
1399
+ const res = await freshFetch(`${swapBase}/wallet/tx?n=${n}`);
1400
+ if (!res.ok)
1401
+ throw new Error(`GET ${swapBase}/wallet/tx?n=${n}: ${res.status}`);
1402
+ return Array.from(new Uint8Array(await res.arrayBuffer()));
1403
+ }
1404
+ /**
1405
+ * Withdraws everything in the exchange's wallet to the admin's own (0.42.1, open-exchange 0.15.2): the admin's
1406
+ * `{fn: "withdraw"}` to swap's `<app>/admin`. swap's program pays every coin to a BRC-29 key derived for the
1407
+ * sender and hands the transaction over unsent; this function waits for the read to list it (`GET <swap>/wallet`,
1408
+ * at most 10 s — the message's answer reaches no page), then takes it in (`internalizeAction`, a wallet payment:
1409
+ * that is what sends it). → the withdrawal.
1410
+ */
1411
+ async function withdrawAll() {
1412
+ const { wallet, signedFor } = needWallet();
1413
+ const w = await readWallet(swapBase, freshFetch);
1414
+ if (w.sats <= 0)
1415
+ throw new Error("the exchange's wallet holds nothing to withdraw");
1416
+ const me = await swapIdentity();
1417
+ await sendMessage(signedFor(swapBase), swapBase, me, `${app()}/admin`, { fn: "withdraw" });
1418
+ let x;
1419
+ for (let i = 0; i < 40 && !x; i++) {
1420
+ await new Promise((r) => setTimeout(r, 250));
1421
+ x = (await readWallet(swapBase, freshFetch)).withdrawals.find((y) => y.n > w.withdrawals.length);
1422
+ }
1423
+ if (!x)
1424
+ throw new Error("the exchange has not answered the withdraw yet: Settings takes it in when it does");
1425
+ if (!(await takeInWithdrawal(wallet, x, await withdrawalTx(x.n))))
1426
+ throw new Error("the wallet did not accept the withdrawal");
1427
+ emit();
1428
+ return x;
1429
+ }
1430
+ /**
1431
+ * The latest withdrawal taken in again (0.42.1; on Settings load): for a page lost between the withdraw's answer
1432
+ * and its take-in (taking in a payment the wallet holds is harmless). Never throws. → its txid, or none.
1433
+ */
1434
+ async function settleWithdrawals() {
1435
+ if (!boundWallet)
1436
+ return [];
1437
+ try {
1438
+ const w = await readWallet(swapBase, freshFetch);
1439
+ const x = w.withdrawals.at(-1);
1440
+ if (!x)
1441
+ return [];
1442
+ return (await takeInWithdrawal(boundWallet, x, await withdrawalTx(x.n))) ? [x.txid] : [];
1443
+ }
1444
+ catch {
1445
+ return [];
1446
+ }
1447
+ }
1289
1448
  /** The discovery instance's record (0.18.0, shruggr/skein#137; `GET <config>/discovery`): `{on: false}` until root turns it on. */
1290
1449
  async function discoveryState() {
1291
1450
  return readDiscovery(swapBase, ff);
@@ -1370,5 +1529,10 @@ function makeClient(opts, s) {
1370
1529
  clearDefaultMarket: guard(clearDefaultMarket),
1371
1530
  discoveryState: guard(discoveryState),
1372
1531
  setDiscovery: guard(setDiscovery),
1532
+ setEnablePrice: guard(setEnablePrice),
1533
+ exchangeWallet: guard(exchangeWallet),
1534
+ withdrawAll: guard(withdrawAll),
1535
+ enableTokenPaid: guard(enableTokenPaid),
1536
+ settleWithdrawals,
1373
1537
  };
1374
1538
  }
@@ -73,7 +73,27 @@ export interface Defaults {
73
73
  market?: {
74
74
  minCommissionBps: number;
75
75
  };
76
+ /** 0.42.0 (open-exchange 0.15.0): the price in sats to enable a token on `POST /amm/enable`, present when the admin set one. */
77
+ enablePriceSats?: number;
76
78
  }
79
+ /** The exchange's wallet (0.42.0, open-exchange 0.15.0; `GET <swap>/wallet`, the host's read of swap's wallet): its sats and coin count. */
80
+ export interface ExchangeWallet {
81
+ sats: number;
82
+ outputs: number;
83
+ /** The admin's withdrawals, each kept by the swap app once proven; n counts from 1. */
84
+ withdrawals: {
85
+ n: number;
86
+ txid: string;
87
+ sats: number;
88
+ at: number;
89
+ outputIndex: number;
90
+ derivationPrefix: string;
91
+ derivationSuffix: string;
92
+ senderIdentityKey: string;
93
+ }[];
94
+ }
95
+ /** `GET <swap>/wallet`: `{sats, outputs, withdrawals}`. */
96
+ export declare function readWallet(base: string, fetchFn?: typeof fetch): Promise<ExchangeWallet>;
77
97
  /** Discovery (`GET <swap>/discovery`): root's last decision, on or off, and since when (ms); the host starts or stops the discovery instance. */
78
98
  export interface Discovery {
79
99
  on: boolean;
package/dist/lib/skein.js CHANGED
@@ -122,6 +122,19 @@ export async function readTokens(base, fetchFn = fetch) {
122
122
  since: typeof t.since === "number" ? t.since : 0,
123
123
  }));
124
124
  }
125
+ /** `GET <swap>/wallet`: `{sats, outputs, withdrawals}`. */
126
+ export async function readWallet(base, fetchFn = fetch) {
127
+ const a = (await getJson(`${base}/wallet`, fetchFn));
128
+ const ws = Array.isArray(a?.withdrawals) ? a.withdrawals : [];
129
+ return {
130
+ sats: typeof a?.sats === "number" ? a.sats : 0,
131
+ outputs: typeof a?.outputs === "number" ? a.outputs : 0,
132
+ withdrawals: ws.filter((w) => typeof w.n === "number" && typeof w.txid === "string").map((w) => ({
133
+ n: w.n, txid: w.txid, sats: Number(w.sats ?? 0), at: Number(w.at ?? 0), outputIndex: Number(w.outputIndex ?? 0),
134
+ derivationPrefix: String(w.derivationPrefix ?? ""), derivationSuffix: String(w.derivationSuffix ?? ""), senderIdentityKey: String(w.senderIdentityKey ?? ""),
135
+ })),
136
+ };
137
+ }
125
138
  /** `GET <swap>/discovery`: `{on, since?}`, or `{on: false}` (none, or another shape). */
126
139
  export async function readDiscovery(base, fetchFn = fetch) {
127
140
  const a = (await getJson(`${base}/discovery`, fetchFn));
@@ -138,5 +151,7 @@ export async function readDefaults(base, fetchFn = fetch) {
138
151
  const m = a?.market;
139
152
  if (m && typeof m.minCommissionBps === "number")
140
153
  out.market = { minCommissionBps: m.minCommissionBps };
154
+ if (typeof a?.enablePriceSats === "number" && a.enablePriceSats > 0)
155
+ out.enablePriceSats = a.enablePriceSats;
141
156
  return out;
142
157
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcasegr/amm-client",
3
- "version": "0.41.1",
3
+ "version": "0.42.3",
4
4
  "type": "module",
5
5
  "description": "The Open Exchange client (skein-amm): reads, swap, pool deploy / close / rebalance, move back and positions over a BRC-100 wallet, bound to one exchange by createClient. No React, no styles, no wallet provider.",
6
6
  "repository": {
@@ -30,7 +30,7 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@1sat/actions": "0.1.3",
33
- "@dcasegr/amm-engine": "0.41.1",
33
+ "@dcasegr/amm-engine": "0.42.3",
34
34
  "cbor2": "^2.3.0"
35
35
  },
36
36
  "peerDependencies": {