@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.
Files changed (121) hide show
  1. package/README.md +107 -2
  2. package/dist/client.d.ts +534 -0
  3. package/dist/client.js +1319 -0
  4. package/dist/errors.d.ts +17 -0
  5. package/dist/errors.js +75 -0
  6. package/dist/index.d.ts +51 -0
  7. package/dist/index.js +53 -0
  8. package/dist/lib/config.d.ts +42 -0
  9. package/dist/lib/config.js +64 -0
  10. package/dist/lib/keys.d.ts +42 -0
  11. package/dist/lib/keys.js +48 -0
  12. package/dist/lib/overlay.d.ts +190 -0
  13. package/dist/lib/overlay.js +302 -0
  14. package/dist/lib/skein.d.ts +82 -0
  15. package/dist/lib/skein.js +142 -0
  16. package/dist/lib/tokenId.d.ts +72 -0
  17. package/dist/lib/tokenId.js +121 -0
  18. package/dist/lp/amounts.d.ts +12 -0
  19. package/dist/lp/amounts.js +38 -0
  20. package/dist/lp/close.d.ts +90 -0
  21. package/dist/lp/close.js +140 -0
  22. package/dist/lp/images.d.ts +11 -0
  23. package/dist/lp/images.js +45 -0
  24. package/dist/lp/inventory.d.ts +68 -0
  25. package/dist/lp/inventory.js +84 -0
  26. package/dist/lp/poolDeploy.d.ts +220 -0
  27. package/dist/lp/poolDeploy.js +291 -0
  28. package/dist/lp/poolRows.d.ts +13 -0
  29. package/dist/lp/poolRows.js +19 -0
  30. package/dist/lp/positions.d.ts +81 -0
  31. package/dist/lp/positions.js +144 -0
  32. package/dist/lp/rebalance.d.ts +101 -0
  33. package/dist/lp/rebalance.js +168 -0
  34. package/dist/lp/wallet.d.ts +12 -0
  35. package/dist/lp/wallet.js +19 -0
  36. package/dist/market/activeSwap.d.ts +158 -0
  37. package/dist/market/activeSwap.js +320 -0
  38. package/dist/market/plan.d.ts +85 -0
  39. package/dist/market/plan.js +149 -0
  40. package/dist/market/prices.d.ts +13 -0
  41. package/dist/market/prices.js +14 -0
  42. package/dist/market/relay.d.ts +84 -0
  43. package/dist/market/relay.js +201 -0
  44. package/dist/market/swapAction.d.ts +306 -0
  45. package/dist/market/swapAction.js +508 -0
  46. package/dist/market/swapFlow.d.ts +58 -0
  47. package/dist/market/swapFlow.js +86 -0
  48. package/dist/market/view.d.ts +58 -0
  49. package/dist/market/view.js +63 -0
  50. package/dist/pool/artifact.d.ts +23 -0
  51. package/dist/pool/artifact.js +38 -0
  52. package/dist/pool/index.d.ts +8 -0
  53. package/dist/pool/index.js +8 -0
  54. package/dist/pool/oneColor.d.ts +19 -0
  55. package/dist/pool/oneColor.js +39 -0
  56. package/dist/pool/pool.artifact.json +5069 -0
  57. package/dist/pool/runar-ir-schema.d.ts +21 -0
  58. package/dist/pool/runar-ir-schema.js +18 -0
  59. package/dist/pool/template.d.ts +295 -0
  60. package/dist/pool/template.js +715 -0
  61. package/dist/vendor/runar/LICENSE +21 -0
  62. package/dist/vendor/runar/NOTICE +15 -0
  63. package/dist/vendor/runar/runar-ir-schema/src/abi-type-encoding.d.ts +42 -0
  64. package/dist/vendor/runar/runar-ir-schema/src/abi-type-encoding.js +53 -0
  65. package/dist/vendor/runar/runar-ir-schema/src/anf-ir.d.ts +221 -0
  66. package/dist/vendor/runar/runar-ir-schema/src/anf-ir.js +33 -0
  67. package/dist/vendor/runar/runar-ir-schema/src/artifact.d.ts +288 -0
  68. package/dist/vendor/runar/runar-ir-schema/src/artifact.js +8 -0
  69. package/dist/vendor/runar/runar-ir-schema/src/canonical-json.d.ts +43 -0
  70. package/dist/vendor/runar/runar-ir-schema/src/canonical-json.js +204 -0
  71. package/dist/vendor/runar/runar-ir-schema/src/input-limits.d.ts +89 -0
  72. package/dist/vendor/runar/runar-ir-schema/src/input-limits.js +100 -0
  73. package/dist/vendor/runar/runar-ir-schema/src/stack-ir.d.ts +118 -0
  74. package/dist/vendor/runar/runar-ir-schema/src/stack-ir.js +8 -0
  75. package/dist/vendor/runar/runar-ir-schema/src/state-layout.d.ts +56 -0
  76. package/dist/vendor/runar/runar-ir-schema/src/state-layout.js +145 -0
  77. package/dist/vendor/runar/runar-ir-schema/src/unknown-anf-kind-error.d.ts +18 -0
  78. package/dist/vendor/runar/runar-ir-schema/src/unknown-anf-kind-error.js +25 -0
  79. package/dist/vendor/runar/runar-sdk/src/anf-interpreter.d.ts +160 -0
  80. package/dist/vendor/runar/runar-sdk/src/anf-interpreter.js +1149 -0
  81. package/dist/vendor/runar/runar-sdk/src/calling.d.ts +98 -0
  82. package/dist/vendor/runar/runar-sdk/src/calling.js +209 -0
  83. package/dist/vendor/runar/runar-sdk/src/contract.d.ts +443 -0
  84. package/dist/vendor/runar/runar-sdk/src/contract.js +2516 -0
  85. package/dist/vendor/runar/runar-sdk/src/deployment.d.ts +36 -0
  86. package/dist/vendor/runar/runar-sdk/src/deployment.js +119 -0
  87. package/dist/vendor/runar/runar-sdk/src/errors.d.ts +46 -0
  88. package/dist/vendor/runar/runar-sdk/src/errors.js +59 -0
  89. package/dist/vendor/runar/runar-sdk/src/oppushtx.d.ts +23 -0
  90. package/dist/vendor/runar/runar-sdk/src/oppushtx.js +95 -0
  91. package/dist/vendor/runar/runar-sdk/src/ordinals/envelope.d.ts +31 -0
  92. package/dist/vendor/runar/runar-sdk/src/ordinals/envelope.js +272 -0
  93. package/dist/vendor/runar/runar-sdk/src/ordinals/types.d.ts +21 -0
  94. package/dist/vendor/runar/runar-sdk/src/ordinals/types.js +4 -0
  95. package/dist/vendor/runar/runar-sdk/src/providers/provider.d.ts +65 -0
  96. package/dist/vendor/runar/runar-sdk/src/providers/provider.js +59 -0
  97. package/dist/vendor/runar/runar-sdk/src/providers/wallet-provider.d.ts +94 -0
  98. package/dist/vendor/runar/runar-sdk/src/providers/wallet-provider.js +297 -0
  99. package/dist/vendor/runar/runar-sdk/src/script-utils.d.ts +54 -0
  100. package/dist/vendor/runar/runar-sdk/src/script-utils.js +252 -0
  101. package/dist/vendor/runar/runar-sdk/src/signers/signer.d.ts +17 -0
  102. package/dist/vendor/runar/runar-sdk/src/signers/signer.js +4 -0
  103. package/dist/vendor/runar/runar-sdk/src/spend-safety.d.ts +31 -0
  104. package/dist/vendor/runar/runar-sdk/src/spend-safety.js +35 -0
  105. package/dist/vendor/runar/runar-sdk/src/state.d.ts +54 -0
  106. package/dist/vendor/runar/runar-sdk/src/state.js +584 -0
  107. package/dist/vendor/runar/runar-sdk/src/types.d.ts +227 -0
  108. package/dist/vendor/runar/runar-sdk/src/types.js +4 -0
  109. package/dist/vendor/runar/runar-sdk/src/unsound-primitives.d.ts +30 -0
  110. package/dist/vendor/runar/runar-sdk/src/unsound-primitives.js +42 -0
  111. package/dist/vendor/runar/runar-sdk.d.ts +9 -0
  112. package/dist/vendor/runar/runar-sdk.js +8 -0
  113. package/dist/wallet/action.d.ts +28 -0
  114. package/dist/wallet/action.js +42 -0
  115. package/dist/wallet/brc29.d.ts +83 -0
  116. package/dist/wallet/brc29.js +80 -0
  117. package/dist/wallet/color.d.ts +110 -0
  118. package/dist/wallet/color.js +134 -0
  119. package/dist/wallet/swapPayouts.d.ts +35 -0
  120. package/dist/wallet/swapPayouts.js +146 -0
  121. package/package.json +39 -4
@@ -0,0 +1,110 @@
1
+ /**
2
+ * The wallet's BRC-207 `color` module, as the pages use it (skein-amm 0.12.0,
3
+ * David Case 2026-10-21/22). The module runs inside the wallet
4
+ * (Yours, branch 1color; `@bsv/color-permission-module`); the page only
5
+ * names its baskets, keys, plans and receipts, with the module's own helpers:
6
+ *
7
+ * - reads: `listOutputs` with `p color assets` (every held token output,
8
+ * `ASSETS_SELECTOR`) and `p color balance <assetTag>` (the exact decimal
9
+ * balance of one asset), `assetTag` = `<txid>v<vout>`; the asset id is
10
+ * `<txid>_<vout>`;
11
+ * - a send: `createAction` with the token outputs, a plan in `p color plan`
12
+ * labels (`ColorPlan.toLabels`) and `randomizeOutputs: false`; the module
13
+ * selects the token inputs, adds token change, asks the user, signs and
14
+ * submits to `tm_color_<assetId>`;
15
+ * - a receive: an output locked to a module receiving key,
16
+ * `getPublicKey({protocolID: [2, "p color <assetTag> <prefixHex>
17
+ * <suffixHex>"], keyID: "color", counterparty: <sender>, forSelf: true})`,
18
+ * taken in with `internalizeAction` (`basket insertion` into
19
+ * `p color <assetTag>`, the receipt JSON as customInstructions) once the
20
+ * transaction is admitted. The sender is whoever builds the output: the
21
+ * validator for a swap's payout, the user for "move back" (BRC-42: the
22
+ * sender's key to the receiver is the receiver's key from the sender,
23
+ * so the page derives it itself; the module checks it the same way,
24
+ * `assertOwned`).
25
+ *
26
+ * The exchange's own baskets (not `p color`; the module would refuse them):
27
+ * `amm-pools` (the LP's position rows) and `amm-swap` (the active swap
28
+ * basket: tokens sent out of the module for swap legs and, 0.29.0, each leg's
29
+ * sats, under the exchange's protocol `[2, "amm swap"]`, counterparty self, a
30
+ * fresh keyID per output).
31
+ */
32
+ import { type ColorReceipt } from "@1sat/actions";
33
+ import { ASSETS_SELECTOR, assetBasket, assetTag, colorProtocolID, type ColorRemittance } from "@bsv/color-permission-module";
34
+ import { type CreateActionArgs, type InternalizeOutput, type WalletInterface, type WalletProtocol } from "@bsv/sdk";
35
+ export { ASSETS_SELECTOR, assetBasket, assetTag, colorProtocolID, type ColorReceipt };
36
+ /** The LP's position rows: one pool output per deploy (basket insertion after the deploy). */
37
+ export declare const POOLS_BASKET = "amm-pools";
38
+ /** The active swap basket: token outputs the swap legs spend, keyed under `SWAP_PROTOCOL`. */
39
+ export declare const SWAP_BASKET = "amm-swap";
40
+ /** The exchange's own key protocol for `amm-swap` outputs (counterparty self, a fresh keyID per output). */
41
+ export declare const SWAP_PROTOCOL: WalletProtocol;
42
+ /** BRC-100's largest `limit`. */
43
+ export declare const LIST_LIMIT = 10000;
44
+ /** customInstructions of an `amm-swap` output: the asset, the amount and the key that spends it. */
45
+ export declare function swapInstructions(o: {
46
+ assetId: string;
47
+ amount: bigint;
48
+ protocolID: WalletProtocol;
49
+ keyID: string;
50
+ counterparty: string;
51
+ }): string;
52
+ /**
53
+ * customInstructions of an `amm-swap` SATS output (0.29.0): a swap leg's sats (the miner fee; sats
54
+ * in, also the amount in and the token payout's sat), staged in the swap basket by the same send as
55
+ * the tokens; `sats: true` tells it from a token row; `assetId` (0.29.1) names the token whose swap
56
+ * staged it (Move back sweeps it with that token's rows). The key that spends it, as for a token row.
57
+ */
58
+ export declare function swapSatsInstructions(o: {
59
+ assetId: string;
60
+ protocolID: WalletProtocol;
61
+ keyID: string;
62
+ counterparty: string;
63
+ }): string;
64
+ /** `p color balance <assetTag>`: the selector of one asset's value balance. */
65
+ export declare function balanceSelector(assetId: string): string;
66
+ /** One asset's value balance, exact (`p color balance <assetTag>` answers it as a decimal string in `totalOutputs`). */
67
+ export declare function assetBalance(wallet: WalletInterface, assetId: string): Promise<bigint>;
68
+ /** One held token output as `p color assets` lists it. */
69
+ export interface HeldOutput {
70
+ /** `txid.vout` */
71
+ outpoint: string;
72
+ satoshis: number;
73
+ lockingScript: string;
74
+ /** False when an action in progress holds it (the module's `color_state_reserved`). */
75
+ available: boolean;
76
+ }
77
+ /** `p color assets`: every token output the module holds, with locking scripts (the page reads asset and amount from them). */
78
+ export declare function heldOutputs(wallet: WalletInterface): Promise<HeldOutput[]>;
79
+ /** A module receiving key for one output of `assetId` from `senderIdentityKey`: its receipt, key and hash160. */
80
+ export interface ReceivingKey {
81
+ receipt: ColorReceipt;
82
+ publicKey: string;
83
+ /** hash160 of the key, hex: the P2PKH remainder of the 1Color output. */
84
+ pkh: string;
85
+ }
86
+ /** A receiving key: random prefix and suffix unless `derivation` names them (0.29.1: a swap leg's, derived from its input). */
87
+ export declare function newReceivingKey(wallet: WalletInterface, assetId: string, senderIdentityKey: string, derivation?: {
88
+ derivationPrefix: string;
89
+ derivationSuffix: string;
90
+ }): Promise<ReceivingKey>;
91
+ /** The receipt's `basket insertion` into the asset's value basket, for `internalizeAction`. */
92
+ export declare function receiptOutput(outputIndex: number, receipt: ColorReceipt): InternalizeOutput;
93
+ /** The `p color plan` labels of a transfer of `assetId` (BRC-207 plan version 1). */
94
+ export declare function transferPlanLabels(assetId: string, o?: {
95
+ ownedOutputs?: ColorRemittance[];
96
+ inputPositions?: {
97
+ outpoint: string;
98
+ index: number;
99
+ }[];
100
+ }): string[];
101
+ /**
102
+ * A module token action to its signed transaction: `createAction`, then,
103
+ * when the wallet hands the action back for signing (an explicit input the
104
+ * page names), `signAction` with no spends of the page's own (the module
105
+ * signs its inputs). Aborted on a failure after the action exists.
106
+ */
107
+ export declare function runTokenAction(wallet: WalletInterface, args: CreateActionArgs): Promise<{
108
+ txid: string;
109
+ tx: number[];
110
+ }>;
@@ -0,0 +1,134 @@
1
+ /**
2
+ * The wallet's BRC-207 `color` module, as the pages use it (skein-amm 0.12.0,
3
+ * David Case 2026-10-21/22). The module runs inside the wallet
4
+ * (Yours, branch 1color; `@bsv/color-permission-module`); the page only
5
+ * names its baskets, keys, plans and receipts, with the module's own helpers:
6
+ *
7
+ * - reads: `listOutputs` with `p color assets` (every held token output,
8
+ * `ASSETS_SELECTOR`) and `p color balance <assetTag>` (the exact decimal
9
+ * balance of one asset), `assetTag` = `<txid>v<vout>`; the asset id is
10
+ * `<txid>_<vout>`;
11
+ * - a send: `createAction` with the token outputs, a plan in `p color plan`
12
+ * labels (`ColorPlan.toLabels`) and `randomizeOutputs: false`; the module
13
+ * selects the token inputs, adds token change, asks the user, signs and
14
+ * submits to `tm_color_<assetId>`;
15
+ * - a receive: an output locked to a module receiving key,
16
+ * `getPublicKey({protocolID: [2, "p color <assetTag> <prefixHex>
17
+ * <suffixHex>"], keyID: "color", counterparty: <sender>, forSelf: true})`,
18
+ * taken in with `internalizeAction` (`basket insertion` into
19
+ * `p color <assetTag>`, the receipt JSON as customInstructions) once the
20
+ * transaction is admitted. The sender is whoever builds the output: the
21
+ * validator for a swap's payout, the user for "move back" (BRC-42: the
22
+ * sender's key to the receiver is the receiver's key from the sender,
23
+ * so the page derives it itself; the module checks it the same way,
24
+ * `assertOwned`).
25
+ *
26
+ * The exchange's own baskets (not `p color`; the module would refuse them):
27
+ * `amm-pools` (the LP's position rows) and `amm-swap` (the active swap
28
+ * basket: tokens sent out of the module for swap legs and, 0.29.0, each leg's
29
+ * sats, under the exchange's protocol `[2, "amm swap"]`, counterparty self, a
30
+ * fresh keyID per output).
31
+ */
32
+ import { colorReceiptInstructions } from "@1sat/actions";
33
+ import { ASSETS_SELECTOR, COLOR_KEY_ID, ColorPlan, assetBasket, assetTag, colorProtocolID } from "@bsv/color-permission-module";
34
+ import { PublicKey, Utils } from "@bsv/sdk";
35
+ import { randomBase64 } from "./brc29.js";
36
+ export { ASSETS_SELECTOR, assetBasket, assetTag, colorProtocolID };
37
+ /** The LP's position rows: one pool output per deploy (basket insertion after the deploy). */
38
+ export const POOLS_BASKET = "amm-pools";
39
+ /** The active swap basket: token outputs the swap legs spend, keyed under `SWAP_PROTOCOL`. */
40
+ export const SWAP_BASKET = "amm-swap";
41
+ /** The exchange's own key protocol for `amm-swap` outputs (counterparty self, a fresh keyID per output). */
42
+ export const SWAP_PROTOCOL = [2, "amm swap"];
43
+ /** BRC-100's largest `limit`. */
44
+ export const LIST_LIMIT = 10000;
45
+ /** customInstructions of an `amm-swap` output: the asset, the amount and the key that spends it. */
46
+ export function swapInstructions(o) {
47
+ return JSON.stringify({ assetId: o.assetId, amount: String(o.amount), protocolID: o.protocolID, keyID: o.keyID, counterparty: o.counterparty });
48
+ }
49
+ /**
50
+ * customInstructions of an `amm-swap` SATS output (0.29.0): a swap leg's sats (the miner fee; sats
51
+ * in, also the amount in and the token payout's sat), staged in the swap basket by the same send as
52
+ * the tokens; `sats: true` tells it from a token row; `assetId` (0.29.1) names the token whose swap
53
+ * staged it (Move back sweeps it with that token's rows). The key that spends it, as for a token row.
54
+ */
55
+ export function swapSatsInstructions(o) {
56
+ return JSON.stringify({ sats: true, assetId: o.assetId, protocolID: o.protocolID, keyID: o.keyID, counterparty: o.counterparty });
57
+ }
58
+ /** `p color balance <assetTag>`: the selector of one asset's value balance. */
59
+ export function balanceSelector(assetId) {
60
+ return `p color balance ${assetTag(assetId)}`;
61
+ }
62
+ /** One asset's value balance, exact (`p color balance <assetTag>` answers it as a decimal string in `totalOutputs`). */
63
+ export async function assetBalance(wallet, assetId) {
64
+ const r = await wallet.listOutputs({ basket: balanceSelector(assetId) });
65
+ return BigInt(String(r.totalOutputs));
66
+ }
67
+ /** `p color assets`: every token output the module holds, with locking scripts (the page reads asset and amount from them). */
68
+ export async function heldOutputs(wallet) {
69
+ const r = await wallet.listOutputs({ basket: ASSETS_SELECTOR, include: "locking scripts", limit: LIST_LIMIT });
70
+ return r.outputs
71
+ .filter((o) => typeof o.lockingScript === "string")
72
+ .map((o) => ({ outpoint: o.outpoint, satoshis: o.satoshis, lockingScript: o.lockingScript, available: o.spendable !== false }));
73
+ }
74
+ /** A receiving key: random prefix and suffix unless `derivation` names them (0.29.1: a swap leg's, derived from its input). */
75
+ export async function newReceivingKey(wallet, assetId, senderIdentityKey, derivation) {
76
+ const derivationPrefix = derivation?.derivationPrefix ?? randomBase64(16);
77
+ const derivationSuffix = derivation?.derivationSuffix ?? randomBase64(16);
78
+ const { publicKey } = await wallet.getPublicKey({
79
+ protocolID: colorProtocolID(assetId, derivationPrefix, derivationSuffix),
80
+ keyID: COLOR_KEY_ID,
81
+ counterparty: senderIdentityKey,
82
+ forSelf: true,
83
+ });
84
+ return {
85
+ receipt: { assetId, derivationPrefix, derivationSuffix, senderIdentityKey },
86
+ publicKey,
87
+ pkh: Utils.toHex(PublicKey.fromString(publicKey).toHash()),
88
+ };
89
+ }
90
+ /** The receipt's `basket insertion` into the asset's value basket, for `internalizeAction`. */
91
+ export function receiptOutput(outputIndex, receipt) {
92
+ return {
93
+ outputIndex,
94
+ protocol: "basket insertion",
95
+ insertionRemittance: { basket: assetBasket(receipt.assetId, "value"), customInstructions: colorReceiptInstructions(receipt) },
96
+ };
97
+ }
98
+ /** The `p color plan` labels of a transfer of `assetId` (BRC-207 plan version 1). */
99
+ export function transferPlanLabels(assetId, o = {}) {
100
+ return ColorPlan.toLabels({
101
+ version: 1,
102
+ assets: [assetId],
103
+ ownedOutputs: o.ownedOutputs ?? [],
104
+ operations: [{ assetId, operation: "transfer" }],
105
+ inputPositions: o.inputPositions ?? [],
106
+ changePositions: [],
107
+ sighashTypes: [],
108
+ });
109
+ }
110
+ /**
111
+ * A module token action to its signed transaction: `createAction`, then,
112
+ * when the wallet hands the action back for signing (an explicit input the
113
+ * page names), `signAction` with no spends of the page's own (the module
114
+ * signs its inputs). Aborted on a failure after the action exists.
115
+ */
116
+ export async function runTokenAction(wallet, args) {
117
+ const created = await wallet.createAction(args);
118
+ if (created.signableTransaction) {
119
+ const reference = created.signableTransaction.reference;
120
+ try {
121
+ const signed = await wallet.signAction({ reference, spends: {}, ...(args.options?.acceptDelayedBroadcast !== undefined ? { options: { acceptDelayedBroadcast: args.options.acceptDelayedBroadcast } } : {}) });
122
+ if (!signed.txid || !signed.tx)
123
+ throw new Error("the wallet returned no signed transaction");
124
+ return { txid: signed.txid, tx: Array.from(signed.tx) };
125
+ }
126
+ catch (err) {
127
+ await wallet.abortAction({ reference }).catch(() => undefined);
128
+ throw err;
129
+ }
130
+ }
131
+ if (!created.txid || !created.tx)
132
+ throw new Error("the wallet returned no transaction");
133
+ return { txid: created.txid, tx: Array.from(created.tx) };
134
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Swap legs left in the wallet, settled silently (skein-amm 0.34.0; D18, D24, David Case
3
+ * 2026-11-04). No browser store: the leg's staged rows in the `amm-swap` basket ARE the note — each
4
+ * row's keyID names the pool outpoint the leg was quoted on (`amm-swap-<txid>.<vout>` /
5
+ * `…:sats`, src/market/activeSwap.ts `swapKeyID`). On Your tokens load (`settleStagedSwaps`),
6
+ * reads only, no resend, nothing shown:
7
+ *
8
+ * 1. the rows grouped by token and pool outpoint;
9
+ * 2. per token, ONE `GET /@<token>/amm/spends?outpoint=a,b` (P8): each pool's spender;
10
+ * 3. a spender: its transaction, `GET /@<token>/amm/tx?id=` (P9: the BEEF as admitted, every
11
+ * input's source with it); an output paying this wallet's leg key (`swapPayoutOf`, re-derived
12
+ * from the transaction's own inputs) → the wallet takes it in (`internalizeAction`, which also
13
+ * marks the staged rows it spends spent); no such output (another's swap) → nothing, the rows
14
+ * stay the user's;
15
+ * 4. a pool not spent → nothing (the validator checks no expiry: the leg may still land).
16
+ *
17
+ * Any failed read or take-in: nothing, the next load tries again.
18
+ */
19
+ import { Transaction, type InternalizeOutput, type WalletInterface, type WalletOutput } from "@bsv/sdk";
20
+ /**
21
+ * Whether output `vout` of `tx` (a swap: the pool at input 0 and output 0) pays this wallet's leg
22
+ * key, re-derived from the transaction's own inputs (`legDerivation`): the take-in for it, or null.
23
+ * A 1Color output is a receipt (sender the pool's validator), a P2PKH one a BRC-29 payment.
24
+ */
25
+ export declare function swapPayoutOf(wallet: WalletInterface, tx: Transaction, vout: number, tokenId: string): Promise<InternalizeOutput | null>;
26
+ /** The pool outpoint (`<txid>.<vout>`) an `amm-swap` row was staged for, from its keyID; null for another row. */
27
+ export declare function stagedPoolOf(row: Pick<WalletOutput, "customInstructions">): string | null;
28
+ /** The token an `amm-swap` row is staged for: its 1Color script's, else (a sats row) its customInstructions' `assetId`. */
29
+ export declare function stagedTokenOf(row: Pick<WalletOutput, "lockingScript" | "customInstructions">): string | null;
30
+ /** The staged legs: token → the pool outpoints its rows were staged for. */
31
+ export declare function stagedLegs(rows: Pick<WalletOutput, "lockingScript" | "customInstructions">[]): Map<string, Set<string>>;
32
+ type FetchFn = (url: string, init?: RequestInit) => Promise<Response>;
33
+ /** The silent pass (see the module comment): → the txids taken in. Never throws. */
34
+ export declare function settleStagedSwaps(wallet: WalletInterface, baseOf: (tokenId: string) => string, fetchFn?: FetchFn): Promise<string[]>;
35
+ export {};
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Swap legs left in the wallet, settled silently (skein-amm 0.34.0; D18, D24, David Case
3
+ * 2026-11-04). No browser store: the leg's staged rows in the `amm-swap` basket ARE the note — each
4
+ * row's keyID names the pool outpoint the leg was quoted on (`amm-swap-<txid>.<vout>` /
5
+ * `…:sats`, src/market/activeSwap.ts `swapKeyID`). On Your tokens load (`settleStagedSwaps`),
6
+ * reads only, no resend, nothing shown:
7
+ *
8
+ * 1. the rows grouped by token and pool outpoint;
9
+ * 2. per token, ONE `GET /@<token>/amm/spends?outpoint=a,b` (P8): each pool's spender;
10
+ * 3. a spender: its transaction, `GET /@<token>/amm/tx?id=` (P9: the BEEF as admitted, every
11
+ * input's source with it); an output paying this wallet's leg key (`swapPayoutOf`, re-derived
12
+ * from the transaction's own inputs) → the wallet takes it in (`internalizeAction`, which also
13
+ * marks the staged rows it spends spent); no such output (another's swap) → nothing, the rows
14
+ * stay the user's;
15
+ * 4. a pool not spent → nothing (the validator checks no expiry: the leg may still land).
16
+ *
17
+ * Any failed read or take-in: nothing, the next load tries again.
18
+ */
19
+ import { PublicKey, Transaction, Utils } from "@bsv/sdk";
20
+ import { WALLET_PAYMENT, brc29PublicKey, identityKeyOf, p2pkhHexOf } from "./brc29.js";
21
+ import { SWAP_BASKET, newReceivingKey, receiptOutput } from "./color.js";
22
+ import { PoolTemplate, decodeOneColor } from "../pool/index.js";
23
+ import { parseTokenId, sdkTokenId, tokenIdOfWire, tokenIdText } from "../lib/tokenId.js";
24
+ import { legDerivation, legKeyInputOf } from "../market/swapAction.js";
25
+ import { tokenP2pkhScript } from "../lp/poolDeploy.js";
26
+ import { basketRows } from "../lp/wallet.js";
27
+ import { readSpends, readTx } from "../lib/overlay.js";
28
+ /**
29
+ * Whether output `vout` of `tx` (a swap: the pool at input 0 and output 0) pays this wallet's leg
30
+ * key, re-derived from the transaction's own inputs (`legDerivation`): the take-in for it, or null.
31
+ * A 1Color output is a receipt (sender the pool's validator), a P2PKH one a BRC-29 payment.
32
+ */
33
+ export async function swapPayoutOf(wallet, tx, vout, tokenId) {
34
+ const pool = tx.outputs[0] ? PoolTemplate.decode(tx.outputs[0].lockingScript) : null;
35
+ const out = tx.outputs[vout];
36
+ const first = tx.outputs[1];
37
+ if (!pool || !out || !first || vout < 1 || tx.inputs.length < 2)
38
+ return null;
39
+ const bsvIn = decodeOneColor(first.lockingScript.toBinary()) !== null;
40
+ let keyInput;
41
+ try {
42
+ keyInput = legKeyInputOf(tx, bsvIn);
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ const d = legDerivation(keyInput, vout === 1 ? "payout" : "commission");
48
+ const script = out.lockingScript.toHex();
49
+ const token = decodeOneColor(out.lockingScript.toBinary());
50
+ if (token) {
51
+ const sdkId = sdkTokenId(tokenId);
52
+ const k = await newReceivingKey(wallet, sdkId, pool.state.validatorIdentity, d);
53
+ return tokenP2pkhScript(sdkId, token.amount, k.publicKey) === script ? receiptOutput(vout, k.receipt) : null;
54
+ }
55
+ const identity = await identityKeyOf(wallet);
56
+ const pub = await brc29PublicKey(wallet, d);
57
+ if (p2pkhHexOf(PublicKey.fromString(pub).toString()) !== script)
58
+ return null;
59
+ return { outputIndex: vout, protocol: WALLET_PAYMENT, paymentRemittance: { ...d, senderIdentityKey: identity } };
60
+ }
61
+ /** The pool outpoint (`<txid>.<vout>`) an `amm-swap` row was staged for, from its keyID; null for another row. */
62
+ export function stagedPoolOf(row) {
63
+ let ci = {};
64
+ try {
65
+ ci = JSON.parse(row.customInstructions ?? "{}");
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ const m = typeof ci.keyID === "string" ? /^amm-swap-([0-9a-f]{64})\.(\d+)(:sats)?$/.exec(ci.keyID) : null;
71
+ return m ? `${m[1]}.${m[2]}` : null;
72
+ }
73
+ /** The token an `amm-swap` row is staged for: its 1Color script's, else (a sats row) its customInstructions' `assetId`. */
74
+ export function stagedTokenOf(row) {
75
+ if (row.lockingScript) {
76
+ const t = decodeOneColor(Utils.toArray(row.lockingScript, "hex"));
77
+ if (t && t.role === "value" && t.idBytes)
78
+ return tokenIdOfWire(t.idBytes);
79
+ }
80
+ try {
81
+ const ci = JSON.parse(row.customInstructions ?? "{}");
82
+ const ref = typeof ci.assetId === "string" ? parseTokenId(ci.assetId) : null;
83
+ return ref ? tokenIdText(ref) : null;
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ }
89
+ /** The staged legs: token → the pool outpoints its rows were staged for. */
90
+ export function stagedLegs(rows) {
91
+ const out = new Map();
92
+ for (const r of rows) {
93
+ const pool = stagedPoolOf(r);
94
+ const token = pool ? stagedTokenOf(r) : null;
95
+ if (!pool || !token)
96
+ continue;
97
+ const s = out.get(token) ?? new Set();
98
+ s.add(pool);
99
+ out.set(token, s);
100
+ }
101
+ return out;
102
+ }
103
+ /** The silent pass (see the module comment): → the txids taken in. Never throws. */
104
+ export async function settleStagedSwaps(wallet, baseOf, fetchFn) {
105
+ const taken = [];
106
+ let rows;
107
+ try {
108
+ rows = await basketRows(wallet, SWAP_BASKET);
109
+ }
110
+ catch {
111
+ return taken;
112
+ }
113
+ for (const [tokenId, pools] of stagedLegs(rows)) {
114
+ try {
115
+ const base = baseOf(tokenId);
116
+ const spends = await readSpends(base, [...pools], fetchFn);
117
+ const spenders = [...new Set(spends.map((s) => s.spentBy).filter((t) => typeof t === "string"))];
118
+ for (const txid of spenders) {
119
+ try {
120
+ const beef = await readTx(base, txid, fetchFn);
121
+ if (!beef)
122
+ continue;
123
+ const tx = Transaction.fromAtomicBEEF(beef);
124
+ const outputs = [];
125
+ for (let vout = 1; vout < tx.outputs.length; vout++) {
126
+ const o = await swapPayoutOf(wallet, tx, vout, tokenId);
127
+ if (o)
128
+ outputs.push(o);
129
+ }
130
+ if (outputs.length === 0)
131
+ continue;
132
+ const r = await wallet.internalizeAction({ tx: beef, outputs, description: "AMM swap payout", labels: ["amm-swap"] });
133
+ if (r.accepted)
134
+ taken.push(txid);
135
+ }
136
+ catch {
137
+ /* the next load */
138
+ }
139
+ }
140
+ }
141
+ catch {
142
+ /* the next load */
143
+ }
144
+ }
145
+ return taken;
146
+ }
package/package.json CHANGED
@@ -1,6 +1,41 @@
1
1
  {
2
2
  "name": "@dcasegr/amm-client",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.38.1",
4
+ "type": "module",
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
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/shruggr/skein-amm.git",
9
+ "directory": "web/client"
10
+ },
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
23
+ "sideEffects": false,
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "scripts": {
28
+ "build": "npm --prefix ../engine run build && rm -rf dist && ../ui/node_modules/.bin/tsc -p tsconfig.build.json && mkdir -p dist/vendor/runar && cp ../ui/src/vendor/runar/LICENSE ../ui/src/vendor/runar/NOTICE dist/vendor/runar/",
29
+ "prepack": "npm run build"
30
+ },
31
+ "dependencies": {
32
+ "@1sat/actions": "0.1.2",
33
+ "@dcasegr/amm-engine": "0.38.1",
34
+ "cbor2": "^2.3.0"
35
+ },
36
+ "peerDependencies": {
37
+ "@1sat/templates": "^0.1.1",
38
+ "@bsv/color-permission-module": "^0.1.0",
39
+ "@bsv/sdk": "^4.0.0"
40
+ }
41
+ }