@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 +7 -1
- package/dist/client.d.ts +36 -2
- package/dist/client.js +166 -2
- package/dist/lib/skein.d.ts +20 -0
- package/dist/lib/skein.js +15 -0
- package/package.json +2 -2
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
|
}
|
package/dist/lib/skein.d.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
33
|
+
"@dcasegr/amm-engine": "0.42.3",
|
|
34
34
|
"cbor2": "^2.3.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|