@dcasegr/amm-client 0.0.0-stage → 0.38.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 +107 -2
- package/dist/client.d.ts +534 -0
- package/dist/client.js +1319 -0
- package/dist/errors.d.ts +17 -0
- package/dist/errors.js +75 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +53 -0
- package/dist/lib/config.d.ts +42 -0
- package/dist/lib/config.js +64 -0
- package/dist/lib/keys.d.ts +42 -0
- package/dist/lib/keys.js +48 -0
- package/dist/lib/overlay.d.ts +190 -0
- package/dist/lib/overlay.js +302 -0
- package/dist/lib/skein.d.ts +82 -0
- package/dist/lib/skein.js +142 -0
- package/dist/lib/tokenId.d.ts +72 -0
- package/dist/lib/tokenId.js +121 -0
- package/dist/lp/amounts.d.ts +12 -0
- package/dist/lp/amounts.js +38 -0
- package/dist/lp/close.d.ts +90 -0
- package/dist/lp/close.js +140 -0
- package/dist/lp/images.d.ts +11 -0
- package/dist/lp/images.js +45 -0
- package/dist/lp/inventory.d.ts +68 -0
- package/dist/lp/inventory.js +84 -0
- package/dist/lp/poolDeploy.d.ts +220 -0
- package/dist/lp/poolDeploy.js +291 -0
- package/dist/lp/poolRows.d.ts +13 -0
- package/dist/lp/poolRows.js +19 -0
- package/dist/lp/positions.d.ts +81 -0
- package/dist/lp/positions.js +144 -0
- package/dist/lp/rebalance.d.ts +101 -0
- package/dist/lp/rebalance.js +168 -0
- package/dist/lp/wallet.d.ts +12 -0
- package/dist/lp/wallet.js +19 -0
- package/dist/market/activeSwap.d.ts +158 -0
- package/dist/market/activeSwap.js +320 -0
- package/dist/market/plan.d.ts +85 -0
- package/dist/market/plan.js +149 -0
- package/dist/market/prices.d.ts +13 -0
- package/dist/market/prices.js +14 -0
- package/dist/market/relay.d.ts +84 -0
- package/dist/market/relay.js +201 -0
- package/dist/market/swapAction.d.ts +306 -0
- package/dist/market/swapAction.js +508 -0
- package/dist/market/swapFlow.d.ts +58 -0
- package/dist/market/swapFlow.js +86 -0
- package/dist/market/view.d.ts +58 -0
- package/dist/market/view.js +63 -0
- package/dist/pool/artifact.d.ts +23 -0
- package/dist/pool/artifact.js +38 -0
- package/dist/pool/index.d.ts +8 -0
- package/dist/pool/index.js +8 -0
- package/dist/pool/oneColor.d.ts +19 -0
- package/dist/pool/oneColor.js +39 -0
- package/dist/pool/pool.artifact.json +5069 -0
- package/dist/pool/runar-ir-schema.d.ts +21 -0
- package/dist/pool/runar-ir-schema.js +18 -0
- package/dist/pool/template.d.ts +295 -0
- package/dist/pool/template.js +715 -0
- package/dist/vendor/runar/LICENSE +21 -0
- package/dist/vendor/runar/NOTICE +15 -0
- package/dist/vendor/runar/runar-ir-schema/src/abi-type-encoding.d.ts +42 -0
- package/dist/vendor/runar/runar-ir-schema/src/abi-type-encoding.js +53 -0
- package/dist/vendor/runar/runar-ir-schema/src/anf-ir.d.ts +221 -0
- package/dist/vendor/runar/runar-ir-schema/src/anf-ir.js +33 -0
- package/dist/vendor/runar/runar-ir-schema/src/artifact.d.ts +288 -0
- package/dist/vendor/runar/runar-ir-schema/src/artifact.js +8 -0
- package/dist/vendor/runar/runar-ir-schema/src/canonical-json.d.ts +43 -0
- package/dist/vendor/runar/runar-ir-schema/src/canonical-json.js +204 -0
- package/dist/vendor/runar/runar-ir-schema/src/input-limits.d.ts +89 -0
- package/dist/vendor/runar/runar-ir-schema/src/input-limits.js +100 -0
- package/dist/vendor/runar/runar-ir-schema/src/stack-ir.d.ts +118 -0
- package/dist/vendor/runar/runar-ir-schema/src/stack-ir.js +8 -0
- package/dist/vendor/runar/runar-ir-schema/src/state-layout.d.ts +56 -0
- package/dist/vendor/runar/runar-ir-schema/src/state-layout.js +145 -0
- package/dist/vendor/runar/runar-ir-schema/src/unknown-anf-kind-error.d.ts +18 -0
- package/dist/vendor/runar/runar-ir-schema/src/unknown-anf-kind-error.js +25 -0
- package/dist/vendor/runar/runar-sdk/src/anf-interpreter.d.ts +160 -0
- package/dist/vendor/runar/runar-sdk/src/anf-interpreter.js +1149 -0
- package/dist/vendor/runar/runar-sdk/src/calling.d.ts +98 -0
- package/dist/vendor/runar/runar-sdk/src/calling.js +209 -0
- package/dist/vendor/runar/runar-sdk/src/contract.d.ts +443 -0
- package/dist/vendor/runar/runar-sdk/src/contract.js +2516 -0
- package/dist/vendor/runar/runar-sdk/src/deployment.d.ts +36 -0
- package/dist/vendor/runar/runar-sdk/src/deployment.js +119 -0
- package/dist/vendor/runar/runar-sdk/src/errors.d.ts +46 -0
- package/dist/vendor/runar/runar-sdk/src/errors.js +59 -0
- package/dist/vendor/runar/runar-sdk/src/oppushtx.d.ts +23 -0
- package/dist/vendor/runar/runar-sdk/src/oppushtx.js +95 -0
- package/dist/vendor/runar/runar-sdk/src/ordinals/envelope.d.ts +31 -0
- package/dist/vendor/runar/runar-sdk/src/ordinals/envelope.js +272 -0
- package/dist/vendor/runar/runar-sdk/src/ordinals/types.d.ts +21 -0
- package/dist/vendor/runar/runar-sdk/src/ordinals/types.js +4 -0
- package/dist/vendor/runar/runar-sdk/src/providers/provider.d.ts +65 -0
- package/dist/vendor/runar/runar-sdk/src/providers/provider.js +59 -0
- package/dist/vendor/runar/runar-sdk/src/providers/wallet-provider.d.ts +94 -0
- package/dist/vendor/runar/runar-sdk/src/providers/wallet-provider.js +297 -0
- package/dist/vendor/runar/runar-sdk/src/script-utils.d.ts +54 -0
- package/dist/vendor/runar/runar-sdk/src/script-utils.js +252 -0
- package/dist/vendor/runar/runar-sdk/src/signers/signer.d.ts +17 -0
- package/dist/vendor/runar/runar-sdk/src/signers/signer.js +4 -0
- package/dist/vendor/runar/runar-sdk/src/spend-safety.d.ts +31 -0
- package/dist/vendor/runar/runar-sdk/src/spend-safety.js +35 -0
- package/dist/vendor/runar/runar-sdk/src/state.d.ts +54 -0
- package/dist/vendor/runar/runar-sdk/src/state.js +584 -0
- package/dist/vendor/runar/runar-sdk/src/types.d.ts +227 -0
- package/dist/vendor/runar/runar-sdk/src/types.js +4 -0
- package/dist/vendor/runar/runar-sdk/src/unsound-primitives.d.ts +30 -0
- package/dist/vendor/runar/runar-sdk/src/unsound-primitives.js +42 -0
- package/dist/vendor/runar/runar-sdk.d.ts +9 -0
- package/dist/vendor/runar/runar-sdk.js +8 -0
- package/dist/wallet/action.d.ts +28 -0
- package/dist/wallet/action.js +42 -0
- package/dist/wallet/brc29.d.ts +83 -0
- package/dist/wallet/brc29.js +80 -0
- package/dist/wallet/color.d.ts +110 -0
- package/dist/wallet/color.js +134 -0
- package/dist/wallet/swapPayouts.d.ts +35 -0
- package/dist/wallet/swapPayouts.js +146 -0
- package/package.json +39 -4
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.34.0 (D9): the rows are read here; their pools' state and fees come from ONE `GET
|
|
3
|
+
* /@<token>/amm/positions?lp=k1,k2` per token (src/client.ts `myPositions`), not from
|
|
4
|
+
* `/spends` per row as below; the pool output's BEEF is read only when the LP acts (Close: `GET
|
|
5
|
+
* /@<token>/amm/pools/beef?lp=<its key>`).
|
|
6
|
+
*
|
|
7
|
+
* The connected wallet's positions (skein-amm 0.9.0, David Case 2026-10-09;
|
|
8
|
+
* 0.12.0: the rows in the exchange's basket `amm-pools`, no claim): the pool
|
|
9
|
+
* rows its deploys filed (op `amm-pool`, the LP key in their
|
|
10
|
+
* customInstructions), each read from the CHAIN STATE by outpoint —
|
|
11
|
+
* `GET <base>/spends` (amm-p2p reads.zig, the chain app's `spent` as the
|
|
12
|
+
* overlay reads it): the pool followed from the deploy's output to its
|
|
13
|
+
* current output (each swap's continuation), or closed (by the LP or by the
|
|
14
|
+
* validator, docs/AMM.md "The validator's Close").
|
|
15
|
+
*
|
|
16
|
+
* 0.29.3: the deploy HISTORY is the first source (`historyPoolRows`): 0.29.4,
|
|
17
|
+
* each `amm-pool-deploy` action's pool output names its LP keyID in its
|
|
18
|
+
* description (`… · amm-lp <hex>`) and its script is the pool (no
|
|
19
|
+
* customInstructions needed: BRC-100's listActions does not answer them). 0.28.0: the rows also come from the wallet's HISTORY (`historyPoolRows`):
|
|
20
|
+
* `listOutputs` answers spendable outputs only, so a pool output the wallet
|
|
21
|
+
* itself spent (the LP swapped against its own pool) left no row and the
|
|
22
|
+
* position vanished; the deploys' actions (label `amm-pool-deploy`) still
|
|
23
|
+
* carry the output filed in `amm-pools` with its customInstructions. Both
|
|
24
|
+
* sets, deduped by outpoint, are followed by `/spends` as before.
|
|
25
|
+
*
|
|
26
|
+
* The current output's BEEF comes from the token's 1Color lookup
|
|
27
|
+
* (0.20.1: BRC-207's `color-spendability` at `ls_color_<tokenId>`: the
|
|
28
|
+
* output if admitted and unspent, with its BEEF; `ls_color {txid,
|
|
29
|
+
* outputIndex}` until 0.19.0).
|
|
30
|
+
*/
|
|
31
|
+
import { Utils } from "@bsv/sdk";
|
|
32
|
+
import { PoolTemplate } from "../pool/index.js";
|
|
33
|
+
import { parseOutpoint, sdkTokenId, tokenIdOfWire, tokenIdText } from "../lib/tokenId.js";
|
|
34
|
+
import { POOLS_BASKET } from "../wallet/color.js";
|
|
35
|
+
import { POOL_TAG, isPoolRow } from "./poolRows.js";
|
|
36
|
+
import { LP_KEY_PROTOCOL, lpKeyIdOfDescription, poolCustomInstructions } from "./poolDeploy.js";
|
|
37
|
+
/** The label a pool deploy gives its action (src/lp/poolDeploy.ts). */
|
|
38
|
+
export const POOL_DEPLOY_LABEL = "amm-pool-deploy";
|
|
39
|
+
/**
|
|
40
|
+
* The pool rows of the wallet's deploy actions (0.28.0): every output of an action labelled
|
|
41
|
+
* `amm-pool-deploy` filed in `amm-pools` as a pool row (tag `amm-pool` or op `amm-pool` in its
|
|
42
|
+
* customInstructions), spent or not. `listActions` with `includeOutputs` (and, where the wallet
|
|
43
|
+
* takes it, `includeCustomInstructions`), paged; a wallet that refuses the read: none.
|
|
44
|
+
*/
|
|
45
|
+
export async function historyPoolRows(wallet) {
|
|
46
|
+
const out = [];
|
|
47
|
+
const limit = 1000;
|
|
48
|
+
try {
|
|
49
|
+
for (let offset = 0; offset < 100_000; offset += limit) {
|
|
50
|
+
const r = await wallet.listActions({ labels: [POOL_DEPLOY_LABEL], includeOutputs: true, includeOutputLockingScripts: true, includeCustomInstructions: true, limit, offset });
|
|
51
|
+
for (const a of r.actions ?? []) {
|
|
52
|
+
for (const o of a.outputs ?? []) {
|
|
53
|
+
const outpoint = `${a.txid}.${o.outputIndex}`;
|
|
54
|
+
// 0.29.4: the LP keyID from the pool output's description (`… · amm-lp <hex>`), the pool from its script.
|
|
55
|
+
const keyID = lpKeyIdOfDescription(o.outputDescription);
|
|
56
|
+
const pool = keyID && o.lockingScript ? PoolTemplate.decode(o.lockingScript) : null;
|
|
57
|
+
if (pool && keyID) {
|
|
58
|
+
const tokenId = sdkTokenId(tokenIdOfWire(Utils.toArray(pool.args.assetId, "hex")));
|
|
59
|
+
out.push({
|
|
60
|
+
outpoint,
|
|
61
|
+
satoshis: o.satoshis,
|
|
62
|
+
lockingScript: o.lockingScript,
|
|
63
|
+
tags: [POOL_TAG],
|
|
64
|
+
customInstructions: poolCustomInstructions({ tokenId, protocolID: LP_KEY_PROTOCOL, keyID, args: pool.args, validatorIdentity: pool.state.validatorIdentity, ...(pool.state.nonce ? { nonce: pool.state.nonce } : {}) }),
|
|
65
|
+
});
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// A wallet that answers the output's customInstructions (0.28.0): the filed row as it is.
|
|
69
|
+
if (o.basket !== POOLS_BASKET)
|
|
70
|
+
continue;
|
|
71
|
+
const row = { outpoint, satoshis: o.satoshis, ...(o.lockingScript ? { lockingScript: o.lockingScript } : {}), ...(o.tags ? { tags: o.tags } : {}), ...(o.customInstructions ? { customInstructions: o.customInstructions } : {}) };
|
|
72
|
+
if (isPoolRow(row))
|
|
73
|
+
out.push(row);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if ((r.actions?.length ?? 0) < limit || offset + limit >= (r.totalActions ?? 0))
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* no history read: the basket's rows alone */
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
/** Rows deduped by outpoint (`<txid>.<vout>`), the first kept (the basket's before the history's). */
|
|
86
|
+
export function mergePoolRows(...sets) {
|
|
87
|
+
const seen = new Set();
|
|
88
|
+
const out = [];
|
|
89
|
+
for (const r of sets.flat()) {
|
|
90
|
+
const op = parseOutpoint(r.outpoint);
|
|
91
|
+
const k = op ? `${op.txid}.${op.vout}` : r.outpoint;
|
|
92
|
+
if (seen.has(k))
|
|
93
|
+
continue;
|
|
94
|
+
seen.add(k);
|
|
95
|
+
out.push(r);
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
/** The wallet's pool rows (`isPoolRow`). */
|
|
100
|
+
export function positionRowsOf(rows) {
|
|
101
|
+
const out = [];
|
|
102
|
+
for (const r of rows) {
|
|
103
|
+
if (!isPoolRow(r))
|
|
104
|
+
continue;
|
|
105
|
+
const op = parseOutpoint(r.outpoint);
|
|
106
|
+
if (!op)
|
|
107
|
+
continue;
|
|
108
|
+
try {
|
|
109
|
+
const ci = JSON.parse(r.customInstructions ?? "{}");
|
|
110
|
+
if (!Array.isArray(ci.protocolID) || typeof ci.keyID !== "string" || typeof ci.id !== "string")
|
|
111
|
+
continue;
|
|
112
|
+
const tid = parseOutpoint(ci.id.replace("_", "."));
|
|
113
|
+
const filed = r.lockingScript ? PoolTemplate.decode(r.lockingScript) : null;
|
|
114
|
+
out.push({
|
|
115
|
+
deployOutpoint: `${op.txid}.${op.vout}`,
|
|
116
|
+
tokenId: tid ? tokenIdText(tid) : ci.id,
|
|
117
|
+
...(ci.sym ? { sym: ci.sym } : {}),
|
|
118
|
+
...(ci.dec !== undefined ? { dec: Number(ci.dec) } : {}),
|
|
119
|
+
lpKey: { protocolID: ci.protocolID, keyID: ci.keyID, counterparty: typeof ci.counterparty === "string" ? ci.counterparty : "self" },
|
|
120
|
+
...(typeof ci.amm?.validatorIdentity === "string" ? { validatorIdentity: ci.amm.validatorIdentity } : {}),
|
|
121
|
+
...(filed ? { lpPubKey: filed.state.lpPubKey } : {}),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
/* skip */
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
/** Positions (live and closed) summed per token, in the order each token first appears; fees not told count as 0. */
|
|
131
|
+
export function feesByToken(ps) {
|
|
132
|
+
const by = new Map();
|
|
133
|
+
for (const p of ps) {
|
|
134
|
+
let t = by.get(p.tokenId);
|
|
135
|
+
if (!t) {
|
|
136
|
+
t = { tokenId: p.tokenId, sym: p.sym, dec: p.dec, positions: 0, sats: 0n, tokens: 0n };
|
|
137
|
+
by.set(p.tokenId, t);
|
|
138
|
+
}
|
|
139
|
+
t.positions += 1;
|
|
140
|
+
t.sats += p.feesEarnedSats ?? 0n;
|
|
141
|
+
t.tokens += p.feesEarnedTokens ?? 0n;
|
|
142
|
+
}
|
|
143
|
+
return [...by.values()];
|
|
144
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rebalance (skein-amm 0.38.0, D11, David Case 2026-11-05): a position's pool closed and a new
|
|
3
|
+
* one deployed in ONE wallet createAction — what Close (src/lp/close.ts) and the deploy
|
|
4
|
+
* (src/lp/poolDeploy.ts) do, in the same transaction. A position is still only deployed or
|
|
5
|
+
* closed (the pool A's Close, a new pool B with a new LP key); wallet-built, so nothing is
|
|
6
|
+
* broadcast-then-taken-in (that is the page-built swap's).
|
|
7
|
+
*
|
|
8
|
+
* 1. The old pool A's current output and its BEEF (the caller's: `GET
|
|
9
|
+
* /@<token>/amm/pools/beef?lp=<A's LP key>`), A's LP key checked against the wallet's.
|
|
10
|
+
* 2. The new pool B as the deploy makes it: a new LP key (`newLpKey`), the proposed pool
|
|
11
|
+
* (`planPoolDeploy`), the validator's affirmation (`amm.pool.affirm`, `affirmPool`: the same
|
|
12
|
+
* call a deploy makes, with B's sats and tokens).
|
|
13
|
+
* 3. ONE createAction through the wallet's BRC-207 module, a `p color plan` transfer:
|
|
14
|
+
* - input 0: A, explicit (its BEEF in `inputBEEF`, `unlockingScriptLength`
|
|
15
|
+
* `PoolTemplate.maxCallUnlockLength`) — to the module a FOREIGN token input, checked
|
|
16
|
+
* admitted and unspent on the token's overlay, its tokens counted;
|
|
17
|
+
* - output 0: B (a foreign script to the module; its description the deploy's, naming B's
|
|
18
|
+
* LP keyID: `lpKeyDescription`);
|
|
19
|
+
* - the token difference through the module: B holding MORE tokens than A — the module
|
|
20
|
+
* selects the wallet's token inputs for the rest and adds token change (the deploy's
|
|
21
|
+
* path); FEWER — output 1, the rest to a NEW module receiving key of the user's own, the
|
|
22
|
+
* plan's owned output 1 (the Close's path; the module files it in `p color <assetTag>`);
|
|
23
|
+
* - the sats difference: the wallet funds what B needs beyond A's sats, its change takes
|
|
24
|
+
* what A had beyond B's (and pays the fee);
|
|
25
|
+
* - labels: the plan's, `amm-pool-deploy` (the deploy's: the positions reader finds B in the
|
|
26
|
+
* history) and `amm-close` (the Close's); `randomizeOutputs: false`.
|
|
27
|
+
* The page fills A's input over the wallet's transaction at signAction (`callUnlock` + the
|
|
28
|
+
* LP's `createSignature`, checked with `Spend`; Close's outputs are free, so the preimage
|
|
29
|
+
* covers B and every output the module and the wallet added); the module signs its inputs,
|
|
30
|
+
* approves and submits; the wallet broadcasts.
|
|
31
|
+
* 4. The page's own submit at the host root (`tm_color_<assetId>`), then B's position row filed
|
|
32
|
+
* in `amm-pools` (basket insertion, as the deploy files it).
|
|
33
|
+
*/
|
|
34
|
+
import { type WalletInterface } from "@bsv/sdk";
|
|
35
|
+
import type { LookupOutput } from "../lib/overlay.js";
|
|
36
|
+
import type { AuthFetchLike } from "../market/relay.js";
|
|
37
|
+
import type { LpKeyRef } from "./positions.js";
|
|
38
|
+
import { type HeldOutput } from "../wallet/color.js";
|
|
39
|
+
import { newLpKey, type Affirmation, type BasketFiling, type PoolDeployPlan, type ValidatorChoice } from "./poolDeploy.js";
|
|
40
|
+
export declare class RebalanceShapeError extends Error {
|
|
41
|
+
constructor(message: string);
|
|
42
|
+
}
|
|
43
|
+
export interface RebalanceInput {
|
|
44
|
+
wallet: WalletInterface;
|
|
45
|
+
/** The wallet's BRC-104 client for the token instance (`amm.pool.affirm` on `/call`). */
|
|
46
|
+
af: AuthFetchLike;
|
|
47
|
+
/** The token instance's AMM base URL. */
|
|
48
|
+
base: string;
|
|
49
|
+
tokenId: string;
|
|
50
|
+
/** The old pool A's current output (step 1). */
|
|
51
|
+
poolOutput: LookupOutput;
|
|
52
|
+
/** A's LP key in the wallet. */
|
|
53
|
+
lpKey: LpKeyRef;
|
|
54
|
+
/** The new pool B's reserves: token base units and sats. */
|
|
55
|
+
tokens: bigint;
|
|
56
|
+
sats: bigint;
|
|
57
|
+
/** B's fees: the validator's terms now, as a deploy takes them. */
|
|
58
|
+
fees: {
|
|
59
|
+
lpFeeBps: bigint;
|
|
60
|
+
validatorFeeBps: bigint;
|
|
61
|
+
commissionBps: bigint;
|
|
62
|
+
};
|
|
63
|
+
validator: ValidatorChoice;
|
|
64
|
+
/** The wallet's held token outputs (`p color assets`): B holding more than A needs the rest there. */
|
|
65
|
+
held: HeldOutput[];
|
|
66
|
+
meta?: {
|
|
67
|
+
sym?: string;
|
|
68
|
+
dec?: number;
|
|
69
|
+
};
|
|
70
|
+
/** The submit to this skein (default: `POST <origin>/submit`, plain fetch). */
|
|
71
|
+
submit?: (topic: string, beef: number[]) => Promise<{
|
|
72
|
+
steak?: unknown;
|
|
73
|
+
}>;
|
|
74
|
+
}
|
|
75
|
+
export interface RebalancedPool {
|
|
76
|
+
/** A's output spent, `txid.vout`. */
|
|
77
|
+
closed: string;
|
|
78
|
+
plan: PoolDeployPlan;
|
|
79
|
+
lpKey: Awaited<ReturnType<typeof newLpKey>>;
|
|
80
|
+
affirmation: Affirmation;
|
|
81
|
+
/** The createAction arguments the wallet was given. */
|
|
82
|
+
createArgs: Parameters<WalletInterface["createAction"]>[0];
|
|
83
|
+
txid: string;
|
|
84
|
+
/** The transaction as the wallet's AtomicBEEF. */
|
|
85
|
+
tx: number[];
|
|
86
|
+
/** B, `<txid>.0`. */
|
|
87
|
+
outpoint: string;
|
|
88
|
+
/** B's token difference against A: positive, taken from the wallet; negative, returned to it (output 1). */
|
|
89
|
+
tokenDelta: bigint;
|
|
90
|
+
/** B's sats difference against A: positive, funded by the wallet; negative, into its change. */
|
|
91
|
+
satsDelta: bigint;
|
|
92
|
+
/** B's position row (`amm-pools`). */
|
|
93
|
+
filing: BasketFiling;
|
|
94
|
+
filed: boolean;
|
|
95
|
+
/** The page's own submit, in words (src/lp/close.ts `steakText`), or its error. */
|
|
96
|
+
submitted: string;
|
|
97
|
+
/** Filing or submit errors (the transaction itself is broadcast). */
|
|
98
|
+
errors: string[];
|
|
99
|
+
}
|
|
100
|
+
/** Steps 1-4 (see the module comment). Throws before the wallet's action exists or when it is refused; after the broadcast, errors are collected. */
|
|
101
|
+
export declare function rebalancePool(i: RebalanceInput): Promise<RebalancedPool>;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rebalance (skein-amm 0.38.0, D11, David Case 2026-11-05): a position's pool closed and a new
|
|
3
|
+
* one deployed in ONE wallet createAction — what Close (src/lp/close.ts) and the deploy
|
|
4
|
+
* (src/lp/poolDeploy.ts) do, in the same transaction. A position is still only deployed or
|
|
5
|
+
* closed (the pool A's Close, a new pool B with a new LP key); wallet-built, so nothing is
|
|
6
|
+
* broadcast-then-taken-in (that is the page-built swap's).
|
|
7
|
+
*
|
|
8
|
+
* 1. The old pool A's current output and its BEEF (the caller's: `GET
|
|
9
|
+
* /@<token>/amm/pools/beef?lp=<A's LP key>`), A's LP key checked against the wallet's.
|
|
10
|
+
* 2. The new pool B as the deploy makes it: a new LP key (`newLpKey`), the proposed pool
|
|
11
|
+
* (`planPoolDeploy`), the validator's affirmation (`amm.pool.affirm`, `affirmPool`: the same
|
|
12
|
+
* call a deploy makes, with B's sats and tokens).
|
|
13
|
+
* 3. ONE createAction through the wallet's BRC-207 module, a `p color plan` transfer:
|
|
14
|
+
* - input 0: A, explicit (its BEEF in `inputBEEF`, `unlockingScriptLength`
|
|
15
|
+
* `PoolTemplate.maxCallUnlockLength`) — to the module a FOREIGN token input, checked
|
|
16
|
+
* admitted and unspent on the token's overlay, its tokens counted;
|
|
17
|
+
* - output 0: B (a foreign script to the module; its description the deploy's, naming B's
|
|
18
|
+
* LP keyID: `lpKeyDescription`);
|
|
19
|
+
* - the token difference through the module: B holding MORE tokens than A — the module
|
|
20
|
+
* selects the wallet's token inputs for the rest and adds token change (the deploy's
|
|
21
|
+
* path); FEWER — output 1, the rest to a NEW module receiving key of the user's own, the
|
|
22
|
+
* plan's owned output 1 (the Close's path; the module files it in `p color <assetTag>`);
|
|
23
|
+
* - the sats difference: the wallet funds what B needs beyond A's sats, its change takes
|
|
24
|
+
* what A had beyond B's (and pays the fee);
|
|
25
|
+
* - labels: the plan's, `amm-pool-deploy` (the deploy's: the positions reader finds B in the
|
|
26
|
+
* history) and `amm-close` (the Close's); `randomizeOutputs: false`.
|
|
27
|
+
* The page fills A's input over the wallet's transaction at signAction (`callUnlock` + the
|
|
28
|
+
* LP's `createSignature`, checked with `Spend`; Close's outputs are free, so the preimage
|
|
29
|
+
* covers B and every output the module and the wallet added); the module signs its inputs,
|
|
30
|
+
* approves and submits; the wallet broadcasts.
|
|
31
|
+
* 4. The page's own submit at the host root (`tm_color_<assetId>`), then B's position row filed
|
|
32
|
+
* in `amm-pools` (basket insertion, as the deploy files it).
|
|
33
|
+
*/
|
|
34
|
+
import { Beef, PublicKey, Transaction } from "@bsv/sdk";
|
|
35
|
+
import { PoolTemplate } from "../pool/index.js";
|
|
36
|
+
import { poolUtxoFrom, spendValid } from "../market/swapAction.js";
|
|
37
|
+
import { identityKeyOf, isBrc29Protocol } from "../wallet/brc29.js";
|
|
38
|
+
import { sdkTokenId } from "../lib/tokenId.js";
|
|
39
|
+
import { POOLS_BASKET, newReceivingKey, transferPlanLabels } from "../wallet/color.js";
|
|
40
|
+
import { inputIndexOf, runAppSignedAction } from "../wallet/action.js";
|
|
41
|
+
import { submitToOverlay, steakText } from "./close.js";
|
|
42
|
+
import { POOL_TAG, PoolDeployError, affirmPool, lpKeyDescription, newLpKey, planPoolDeploy, poolCustomInstructions, tokenP2pkhScript, valueOutputsOf } from "./poolDeploy.js";
|
|
43
|
+
import { POOL_DEPLOY_LABEL } from "./positions.js";
|
|
44
|
+
export class RebalanceShapeError extends Error {
|
|
45
|
+
constructor(message) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.name = "RebalanceShapeError";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function describe(text) {
|
|
51
|
+
return text.length <= 50 ? text : `${text.slice(0, 49)}…`;
|
|
52
|
+
}
|
|
53
|
+
/** Steps 1-4 (see the module comment). Throws before the wallet's action exists or when it is refused; after the broadcast, errors are collected. */
|
|
54
|
+
export async function rebalancePool(i) {
|
|
55
|
+
const { wallet } = i;
|
|
56
|
+
const meta = i.meta ?? {};
|
|
57
|
+
const sdkId = sdkTokenId(i.tokenId);
|
|
58
|
+
const sym = meta.sym ?? "token";
|
|
59
|
+
// 1. A, and its LP key.
|
|
60
|
+
const poolUtxo = poolUtxoFrom(i.poolOutput);
|
|
61
|
+
const old = PoolTemplate.decode(poolUtxo.script);
|
|
62
|
+
if (!old)
|
|
63
|
+
throw new RebalanceShapeError("the output is not a pool");
|
|
64
|
+
if (!isBrc29Protocol(i.lpKey.protocolID) || i.lpKey.counterparty !== "self")
|
|
65
|
+
throw new RebalanceShapeError(`the LP key ${i.lpKey.keyID} is not a BRC-29 key to self`);
|
|
66
|
+
const lpArgs = { protocolID: i.lpKey.protocolID, keyID: i.lpKey.keyID, counterparty: i.lpKey.counterparty };
|
|
67
|
+
const { publicKey: lpPub } = await wallet.getPublicKey({ ...lpArgs, forSelf: true });
|
|
68
|
+
if (PublicKey.fromString(lpPub).toString() !== old.state.lpPubKey)
|
|
69
|
+
throw new RebalanceShapeError(`the wallet key ${i.lpKey.keyID} is not this pool's LP key`);
|
|
70
|
+
const tokenDelta = i.tokens - old.state.tokenReserve;
|
|
71
|
+
const satsDelta = i.sats - BigInt(poolUtxo.satoshis);
|
|
72
|
+
if (tokenDelta > 0n) {
|
|
73
|
+
const held = valueOutputsOf(i.held, i.tokenId).reduce((a, o) => a + o.amount, 0n);
|
|
74
|
+
if (held < tokenDelta)
|
|
75
|
+
throw new PoolDeployError(`Your wallet holds fewer than ${tokenDelta} base units of that token`);
|
|
76
|
+
}
|
|
77
|
+
// 2. B: a new LP key, the proposed pool, the validator's affirmation.
|
|
78
|
+
const lpKey = await newLpKey(wallet);
|
|
79
|
+
const plan = planPoolDeploy({
|
|
80
|
+
tokenId: i.tokenId,
|
|
81
|
+
tokens: i.tokens,
|
|
82
|
+
sats: i.sats,
|
|
83
|
+
...i.fees,
|
|
84
|
+
lpPubKey: lpKey.publicKey,
|
|
85
|
+
lpKeyId: lpKey.keyID,
|
|
86
|
+
validator: i.validator,
|
|
87
|
+
...(meta.dec !== undefined ? { dec: meta.dec } : {}),
|
|
88
|
+
});
|
|
89
|
+
const affirmation = await affirmPool(i.af, i.base, plan);
|
|
90
|
+
const poolScript = affirmation.lockingScript;
|
|
91
|
+
// 3. The one action: A in, B at output 0, the token difference through the module.
|
|
92
|
+
const outputs = [{ lockingScript: poolScript, satoshis: Number(plan.sats), outputDescription: lpKeyDescription(describe(`AMM pool: ${sym} / BSV`), lpKey.keyID) }];
|
|
93
|
+
let owned = {};
|
|
94
|
+
if (tokenDelta < 0n) {
|
|
95
|
+
const me = await identityKeyOf(wallet);
|
|
96
|
+
const k = await newReceivingKey(wallet, sdkId, me);
|
|
97
|
+
outputs.push({ lockingScript: tokenP2pkhScript(sdkId, -tokenDelta, k.publicKey), satoshis: 1, outputDescription: describe(`${sym} pool tokens to you`) });
|
|
98
|
+
owned = { ownedOutputs: [{ outputIndex: 1, ...k.receipt }] };
|
|
99
|
+
}
|
|
100
|
+
const first = PoolTemplate.planClose({ pool: poolUtxo, outputs: outputs.map((o) => ({ satoshis: BigInt(o.satoshis), script: o.lockingScript })) });
|
|
101
|
+
const poolOutpoint = `${poolUtxo.txid}.${poolUtxo.vout}`;
|
|
102
|
+
const lpSigner = async (sighash) => (await wallet.createSignature({ ...lpArgs, hashToDirectlySign: sighash })).signature;
|
|
103
|
+
const createArgs = {
|
|
104
|
+
description: describe(`AMM close + pool deploy: ${sym}`),
|
|
105
|
+
inputBEEF: Beef.fromBinary(i.poolOutput.beef).toBinary(),
|
|
106
|
+
inputs: [{ outpoint: poolOutpoint, unlockingScriptLength: PoolTemplate.maxCallUnlockLength(first), inputDescription: describe(`The ${sym} pool`) }],
|
|
107
|
+
outputs,
|
|
108
|
+
labels: [...transferPlanLabels(sdkId, owned), POOL_DEPLOY_LABEL, "amm-close"],
|
|
109
|
+
options: { randomizeOutputs: false, acceptDelayedBroadcast: false },
|
|
110
|
+
};
|
|
111
|
+
const signed = await runAppSignedAction(wallet, createArgs, async (tx) => {
|
|
112
|
+
// The contract reads input 0 (the preimage is input 0's); the wallet places named inputs first.
|
|
113
|
+
if (inputIndexOf(tx, poolUtxo.txid, poolUtxo.vout) !== 0)
|
|
114
|
+
throw new RebalanceShapeError("the wallet did not place the pool as input 0");
|
|
115
|
+
outputs.forEach((o, n) => {
|
|
116
|
+
if (tx.outputs[n]?.lockingScript.toHex() !== o.lockingScript || tx.outputs[n]?.satoshis !== o.satoshis)
|
|
117
|
+
throw new RebalanceShapeError(`the wallet moved output ${n} of the rebalance`);
|
|
118
|
+
});
|
|
119
|
+
// Close's outputs are free: the call's preimage covers B and every output the wallet added.
|
|
120
|
+
const callPlan = PoolTemplate.planClose({ pool: poolUtxo, outputs: tx.outputs.map((o) => ({ satoshis: BigInt(o.satoshis), script: o.lockingScript.toHex() })) });
|
|
121
|
+
tx.inputs[0].unlockingScript = PoolTemplate.callUnlock(callPlan, tx, null).unlockingScript;
|
|
122
|
+
await PoolTemplate.signPoolInput({ tx, pool: callPlan.pool, method: "close", unsigned: ["lp"], sourceSatoshis: poolUtxo.satoshis }, "lp", lpSigner);
|
|
123
|
+
if (!spendValid(tx, 0))
|
|
124
|
+
throw new RebalanceShapeError("input 0 of the rebalance does not validate");
|
|
125
|
+
return { 0: { unlockingScript: tx.inputs[0].unlockingScript.toHex() } };
|
|
126
|
+
});
|
|
127
|
+
const out = {
|
|
128
|
+
closed: poolOutpoint,
|
|
129
|
+
plan,
|
|
130
|
+
lpKey,
|
|
131
|
+
affirmation,
|
|
132
|
+
createArgs,
|
|
133
|
+
txid: signed.txid,
|
|
134
|
+
tx: signed.tx,
|
|
135
|
+
outpoint: `${signed.txid}.0`,
|
|
136
|
+
tokenDelta,
|
|
137
|
+
satsDelta,
|
|
138
|
+
filing: {
|
|
139
|
+
outputIndex: 0,
|
|
140
|
+
basket: POOLS_BASKET,
|
|
141
|
+
tags: [POOL_TAG],
|
|
142
|
+
customInstructions: poolCustomInstructions({ tokenId: sdkId, ...meta, protocolID: lpKey.protocolID, keyID: lpKey.keyID, args: plan.args, validatorIdentity: plan.state.validatorIdentity, nonce: affirmation.nonce }),
|
|
143
|
+
},
|
|
144
|
+
filed: false,
|
|
145
|
+
submitted: "not submitted",
|
|
146
|
+
errors: [],
|
|
147
|
+
};
|
|
148
|
+
if (Transaction.fromAtomicBEEF(signed.tx).outputs[0]?.lockingScript.toHex() !== poolScript)
|
|
149
|
+
out.errors.push("the wallet's transaction has another output 0 than the affirmed pool");
|
|
150
|
+
// 4. The page's own submit, then B's position row.
|
|
151
|
+
try {
|
|
152
|
+
const submit = i.submit ?? ((topic, beef) => submitToOverlay(i.base, topic, beef));
|
|
153
|
+
out.submitted = steakText((await submit(plan.topic, signed.tx)));
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
out.submitted = "the submit failed";
|
|
157
|
+
out.errors.push(`submit: ${err instanceof Error ? err.message : String(err)}`);
|
|
158
|
+
}
|
|
159
|
+
const row = { outputIndex: 0, protocol: "basket insertion", insertionRemittance: { basket: out.filing.basket, tags: out.filing.tags, customInstructions: out.filing.customInstructions } };
|
|
160
|
+
try {
|
|
161
|
+
const r = await wallet.internalizeAction({ tx: signed.tx, outputs: [row], description: describe(`AMM pool deploy: ${sym}`), labels: [POOL_DEPLOY_LABEL] });
|
|
162
|
+
out.filed = r.accepted;
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
out.errors.push(`internalizeAction: ${err instanceof Error ? err.message : String(err)}`);
|
|
166
|
+
}
|
|
167
|
+
return out;
|
|
168
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The wallet reads of the exchange's own baskets (skein-amm 0.12.0): the
|
|
3
|
+
* LP's position rows (`amm-pools`) and the active swap basket (`amm-swap`),
|
|
4
|
+
* src/wallet/color.ts. The user's tokens themselves are the BRC-207
|
|
5
|
+
* module's (`p color assets`, `p color balance <assetTag>`), read there.
|
|
6
|
+
* Nothing here talks to an overlay.
|
|
7
|
+
*/
|
|
8
|
+
import { Beef, type WalletInterface, type WalletOutput } from "@bsv/sdk";
|
|
9
|
+
/** A basket's outputs with locking scripts, tags and customInstructions. */
|
|
10
|
+
export declare function basketRows(wallet: WalletInterface, basket: string): Promise<WalletOutput[]>;
|
|
11
|
+
/** A basket's source transactions (for a spend's BEEF), or null when the wallet answers none. */
|
|
12
|
+
export declare function basketBeef(wallet: WalletInterface, basket: string): Promise<Beef | null>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The wallet reads of the exchange's own baskets (skein-amm 0.12.0): the
|
|
3
|
+
* LP's position rows (`amm-pools`) and the active swap basket (`amm-swap`),
|
|
4
|
+
* src/wallet/color.ts. The user's tokens themselves are the BRC-207
|
|
5
|
+
* module's (`p color assets`, `p color balance <assetTag>`), read there.
|
|
6
|
+
* Nothing here talks to an overlay.
|
|
7
|
+
*/
|
|
8
|
+
import { Beef } from "@bsv/sdk";
|
|
9
|
+
import { LIST_LIMIT } from "../wallet/color.js";
|
|
10
|
+
/** A basket's outputs with locking scripts, tags and customInstructions. */
|
|
11
|
+
export async function basketRows(wallet, basket) {
|
|
12
|
+
const r = await wallet.listOutputs({ basket, include: "locking scripts", includeTags: true, includeCustomInstructions: true, limit: LIST_LIMIT });
|
|
13
|
+
return r.outputs;
|
|
14
|
+
}
|
|
15
|
+
/** A basket's source transactions (for a spend's BEEF), or null when the wallet answers none. */
|
|
16
|
+
export async function basketBeef(wallet, basket) {
|
|
17
|
+
const r = await wallet.listOutputs({ basket, include: "entire transactions", limit: LIST_LIMIT });
|
|
18
|
+
return r.BEEF ? Beef.fromBinary(Array.from(r.BEEF)) : null;
|
|
19
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The active swap basket (skein-amm 0.12.0, David Case 2026-10-21/22; 0.29.0,
|
|
3
|
+
* 2026-11-02): everything the swap legs spend, held outside the BRC-207 module
|
|
4
|
+
* in the exchange's own basket `amm-swap` (src/wallet/color.ts): the token
|
|
5
|
+
* outputs and each leg's sats.
|
|
6
|
+
*
|
|
7
|
+
* - **In** (`sendToSwapBasket`): before the legs of a tokens-in swap, ONE
|
|
8
|
+
* wallet-built send through the module: one 1Color value output per leg
|
|
9
|
+
* not covered by what `amm-swap` already holds, each exactly the leg's
|
|
10
|
+
* amount in (the pool takes no token change, so a leg needs inputs that
|
|
11
|
+
* sum to its amount exactly), locked to a key derived from the leg's pool outpoint (`swapKeyID`) under `[2, "amm
|
|
12
|
+
* swap"]` (counterparty self), the plan naming them a transfer out; and
|
|
13
|
+
* (0.29.0) one P2PKH sats output per leg not covered (the leg's exact
|
|
14
|
+
* sats, `swapFunding`), to that outpoint's `:sats` key, filed in
|
|
15
|
+
* `amm-swap` by the createAction itself (customInstructions `{sats: true,
|
|
16
|
+
* assetId, protocolID, keyID, counterparty}`). The module passes the sats outputs
|
|
17
|
+
* through, selects the token inputs, adds change, asks once, signs and
|
|
18
|
+
* submits to `tm_color_<assetId>`; the wallet funds the sats; the page
|
|
19
|
+
* submits it to this skein too (a repeat is harmless), then files each
|
|
20
|
+
* token output in `amm-swap` (basket insertion, customInstructions
|
|
21
|
+
* `{assetId, amount, protocolID, keyID, counterparty}`). A sats-in swap,
|
|
22
|
+
* or a tokens-in swap whose tokens are all staged already, sends only the
|
|
23
|
+
* sats (`sendSatsToSwapBasket`: a plain createAction, no `p color` labels).
|
|
24
|
+
* - **Spent** by the legs (src/market/swapAction.ts): app-built,
|
|
25
|
+
* `createSignature` under the key the customInstructions name; the
|
|
26
|
+
* wallet marks them spent when it takes the accepted swap in (0.29.0: no
|
|
27
|
+
* relinquishOutput). An output a failed leg did not spend stays for a
|
|
28
|
+
* later swap.
|
|
29
|
+
* - **Move back** (`moveBack`, the recovery path; 0.29.3: a module plan,
|
|
30
|
+
* David Case 2026-11-02): ONE createAction through the wallet's BRC-207
|
|
31
|
+
* module, a `p color plan` transfer: every `amm-swap` token output of the
|
|
32
|
+
* token and (0.29.1) the sats rows staged for its legs (their `assetId`)
|
|
33
|
+
* as explicit inputs (their source transactions in `inputBEEF`) — to the
|
|
34
|
+
* module FOREIGN inputs (not in a `p color` basket): the token rows
|
|
35
|
+
* checked admitted and unspent on the token's overlay, the sats rows
|
|
36
|
+
* adding nothing; one output, the whole amount to a NEW module receiving
|
|
37
|
+
* key of the user's own, the plan's owned output 0 (the module checks it
|
|
38
|
+
* pays the remittance's key and files it in `p color <assetTag>` with its
|
|
39
|
+
* custody in the same call). The page unlocks its inputs at signAction;
|
|
40
|
+
* the wallet funds the fee and takes the sats rows into its change; the
|
|
41
|
+
* module approves and submits, the wallet broadcasts. The page submits it
|
|
42
|
+
* to this skein's token topic too. Nothing is taken in afterwards and
|
|
43
|
+
* nothing is kept in the browser. * (0.29.6) With no token row and only sats rows staged for the token
|
|
44
|
+
* (a sats-in leg that failed): one plain createAction (no `p color`
|
|
45
|
+
* labels), the sats rows as explicit inputs and no outputs — the wallet
|
|
46
|
+
* keeps them as its change and pays the fee (`moveBackSats`).
|
|
47
|
+
*/
|
|
48
|
+
import { Beef, Transaction, type WalletInterface } from "@bsv/sdk";
|
|
49
|
+
import { type Steak } from "../lp/close.js";
|
|
50
|
+
import { type Spends } from "../wallet/action.js";
|
|
51
|
+
import { type SatsInput, type TokenInput } from "./swapAction.js";
|
|
52
|
+
/** The keyID prefix of an `amm-swap` key (`SWAP_PROTOCOL`, counterparty self). */
|
|
53
|
+
export declare const SWAP_KEY_PREFIX = "amm-swap-";
|
|
54
|
+
/**
|
|
55
|
+
* The keyID of a staged `amm-swap` output (0.29.2, David Case 2026-11-02: derived, not random):
|
|
56
|
+
* `amm-swap-<txid>.<vout>` for a leg's token row and `amm-swap-<txid>.<vout>:sats` for its sats
|
|
57
|
+
* row, `<txid>.<vout>` the leg's pool outpoint as quoted (`leg.outpoint`, `_` written `.`).
|
|
58
|
+
* Protocol `[2, "amm swap"]`, counterparty self, as before. A leg refused and retried against the
|
|
59
|
+
* same pool outpoint stages to the same key again, which is fine.
|
|
60
|
+
*/
|
|
61
|
+
export declare function swapKeyID(poolOutpoint: string, kind: "token" | "sats"): string;
|
|
62
|
+
/** The `amm-swap` outputs of `tokenId` the legs can spend. */
|
|
63
|
+
export declare function swapHoldings(wallet: WalletInterface, tokenId: string): Promise<TokenInput[]>;
|
|
64
|
+
/** The `amm-swap` sats outputs the legs can spend (0.29.0). */
|
|
65
|
+
export declare function swapSatsHoldings(wallet: WalletInterface): Promise<SatsInput[]>;
|
|
66
|
+
/**
|
|
67
|
+
* What `amm-swap` holds, per token id: the token amount and the number of token outputs, and
|
|
68
|
+
* (0.29.6) the sats staged for the token's legs (the sats rows whose customInstructions name its
|
|
69
|
+
* `assetId`). A token with only sats staged has amount 0n and outputs 0.
|
|
70
|
+
*/
|
|
71
|
+
export declare function swapTotals(wallet: WalletInterface): Promise<Map<string, {
|
|
72
|
+
amount: bigint;
|
|
73
|
+
outputs: number;
|
|
74
|
+
sats: number;
|
|
75
|
+
}>>;
|
|
76
|
+
/** The source transactions of `amm-swap`'s outputs (a leg's BEEF), with `extra` merged in. */
|
|
77
|
+
export declare function swapHoldingBeef(wallet: WalletInterface, extra?: number[]): Promise<Beef>;
|
|
78
|
+
export interface SentToSwapBasket {
|
|
79
|
+
txid: string;
|
|
80
|
+
/** The send as the wallet's AtomicBEEF. */
|
|
81
|
+
tx: number[];
|
|
82
|
+
/** The new `amm-swap` token outputs, in the order of `stage.tokens`. */
|
|
83
|
+
holdings: TokenInput[];
|
|
84
|
+
/** The new `amm-swap` sats outputs, in the order of `stage.sats` (0.29.0). */
|
|
85
|
+
sats: SatsInput[];
|
|
86
|
+
filed: boolean;
|
|
87
|
+
submitted: string;
|
|
88
|
+
errors: string[];
|
|
89
|
+
}
|
|
90
|
+
/** A staged sats output: the leg's exact sats, keyed by the leg's pool outpoint (`swapKeyID`). */
|
|
91
|
+
export interface StagedSats {
|
|
92
|
+
satoshis: number;
|
|
93
|
+
/** The leg's pool outpoint, `<txid>_<vout>` or `<txid>.<vout>`. */
|
|
94
|
+
pool: string;
|
|
95
|
+
}
|
|
96
|
+
/** What one send stages: a token output per leg (its amount in), then a sats output per leg. */
|
|
97
|
+
export interface SwapStage {
|
|
98
|
+
tokens: {
|
|
99
|
+
amount: bigint;
|
|
100
|
+
pool: string;
|
|
101
|
+
}[];
|
|
102
|
+
sats: StagedSats[];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* "In" (see the module comment): one module send of `stage.tokens` (each one
|
|
106
|
+
* output) to `amm-swap` keys derived from each leg's pool (`swapKeyID`), filed in `amm-swap`, and of `stage.sats`
|
|
107
|
+
* (each one output) after them. Throws when the wallet refuses or fails the
|
|
108
|
+
* send; filing and the page's own submit are reported in `errors`.
|
|
109
|
+
*/
|
|
110
|
+
export declare function sendToSwapBasket(wallet: WalletInterface, base: string, tokenId: string, stage: SwapStage, meta?: {
|
|
111
|
+
sym?: string;
|
|
112
|
+
}, submit?: (topic: string, beef: number[]) => Promise<{
|
|
113
|
+
steak?: Steak;
|
|
114
|
+
}>): Promise<SentToSwapBasket>;
|
|
115
|
+
export interface SentSats {
|
|
116
|
+
txid: string;
|
|
117
|
+
/** The send as the wallet's AtomicBEEF. */
|
|
118
|
+
tx: number[];
|
|
119
|
+
/** The new `amm-swap` sats outputs, in the order of `sats`. */
|
|
120
|
+
sats: SatsInput[];
|
|
121
|
+
errors: string[];
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The sats-only send (0.29.0): one plain createAction (no `p color` labels: the module is not in
|
|
125
|
+
* the path) with one P2PKH output per amount to the leg's "amm swap" `:sats` key (`swapKeyID`), filed in `amm-swap`; the
|
|
126
|
+
* wallet funds it, adds change and broadcasts. Throws when the wallet refuses or fails it.
|
|
127
|
+
*/
|
|
128
|
+
export declare function sendSatsToSwapBasket(wallet: WalletInterface, tokenId: string, sats: StagedSats[], meta?: {
|
|
129
|
+
sym?: string;
|
|
130
|
+
}): Promise<SentSats>;
|
|
131
|
+
export interface MovedBack {
|
|
132
|
+
txid: string;
|
|
133
|
+
amount: bigint;
|
|
134
|
+
/** The transaction as the wallet's AtomicBEEF. */
|
|
135
|
+
beef: number[];
|
|
136
|
+
submitted: string;
|
|
137
|
+
errors: string[];
|
|
138
|
+
}
|
|
139
|
+
/** The page's unlocking scripts for the `amm-swap` outputs `holdings` in the wallet's transaction `tx`, each checked with `Spend`. */
|
|
140
|
+
export declare function swapBasketSpends(wallet: WalletInterface, tx: Transaction, holdings: (TokenInput | SatsInput)[], what: string): Promise<Spends>;
|
|
141
|
+
/**
|
|
142
|
+
* "Move back" (see the module comment; 0.29.3: a module plan). Throws before anything is
|
|
143
|
+
* broadcast (no outputs, a wallet or module refusal, an input that does not validate: the action
|
|
144
|
+
* is aborted). The module files the output in `p color <assetTag>` with its custody in the same
|
|
145
|
+
* createAction: no take-in afterwards, nothing kept in the browser. The page's own submit to this
|
|
146
|
+
* skein's token topic (the module submitted at the wallet's overlay too) is reported in `errors`.
|
|
147
|
+
*/
|
|
148
|
+
export declare function moveBack(i: {
|
|
149
|
+
wallet: WalletInterface;
|
|
150
|
+
base: string;
|
|
151
|
+
tokenId: string;
|
|
152
|
+
meta?: {
|
|
153
|
+
sym?: string;
|
|
154
|
+
};
|
|
155
|
+
submit?: (topic: string, beef: number[]) => Promise<{
|
|
156
|
+
steak?: Steak;
|
|
157
|
+
}>;
|
|
158
|
+
}): Promise<MovedBack>;
|