@dcasegr/amm-client 0.0.0-stage → 0.38.2
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,227 @@
|
|
|
1
|
+
import type { Transaction as BsvTransaction } from '@bsv/sdk';
|
|
2
|
+
import type { Signer } from './signers/signer.js';
|
|
3
|
+
/**
|
|
4
|
+
* Plain data shape returned by Provider.getTransaction().
|
|
5
|
+
* Renamed from `Transaction` to avoid collision with the @bsv/sdk Transaction class
|
|
6
|
+
* which is now the primary transaction type used throughout the SDK.
|
|
7
|
+
*/
|
|
8
|
+
export interface TransactionData {
|
|
9
|
+
txid: string;
|
|
10
|
+
version: number;
|
|
11
|
+
inputs: TxInput[];
|
|
12
|
+
outputs: TxOutput[];
|
|
13
|
+
locktime: number;
|
|
14
|
+
raw?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Re-export @bsv/sdk Transaction as the primary transaction type. */
|
|
17
|
+
export type { BsvTransaction as Transaction };
|
|
18
|
+
export interface TxInput {
|
|
19
|
+
txid: string;
|
|
20
|
+
outputIndex: number;
|
|
21
|
+
script: string;
|
|
22
|
+
sequence: number;
|
|
23
|
+
}
|
|
24
|
+
export interface TxOutput {
|
|
25
|
+
satoshis: number;
|
|
26
|
+
script: string;
|
|
27
|
+
}
|
|
28
|
+
export interface UTXO {
|
|
29
|
+
txid: string;
|
|
30
|
+
outputIndex: number;
|
|
31
|
+
satoshis: number;
|
|
32
|
+
script: string;
|
|
33
|
+
}
|
|
34
|
+
export interface DeployOptions {
|
|
35
|
+
/** Satoshis to lock in the contract UTXO. Defaults to 1. */
|
|
36
|
+
satoshis?: number;
|
|
37
|
+
changeAddress?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Signer for the P2PKH funding inputs (issue #134). When the funding UTXOs
|
|
40
|
+
* are owned by a different key than the connected deploy signer, set this so
|
|
41
|
+
* the funding inputs are signed by their real owner. Defaults to the
|
|
42
|
+
* connected signer (zero behaviour change).
|
|
43
|
+
*/
|
|
44
|
+
fundingSigner?: Signer;
|
|
45
|
+
/**
|
|
46
|
+
* Builtins the caller accepts despite the compiler not claiming they are
|
|
47
|
+
* sound (R-062). Required — naming each one — when the artifact declares
|
|
48
|
+
* `unsoundPrimitives`; ignored otherwise. See `unsound-primitives.ts`.
|
|
49
|
+
*/
|
|
50
|
+
acknowledgeUnsound?: string[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Result of `prepareCall()` — contains everything needed for external signing
|
|
54
|
+
* and subsequent `finalizeCall()`.
|
|
55
|
+
*
|
|
56
|
+
* Public fields (`sighash`, `preimage`, `opPushTxSig`, `tx`, `sigIndices`)
|
|
57
|
+
* are for external signer coordination. Fields prefixed with `_` are opaque
|
|
58
|
+
* internals consumed by `finalizeCall()`.
|
|
59
|
+
*/
|
|
60
|
+
export interface PreparedCall {
|
|
61
|
+
/**
|
|
62
|
+
* BIP-143 sighash (hex) — `hash256(preimage)`, i.e. `sha256(sha256(...))`.
|
|
63
|
+
* External signers ECDSA-sign these 32 bytes DIRECTLY, with no further
|
|
64
|
+
* hashing (see `WalletSigner.signHash`).
|
|
65
|
+
*/
|
|
66
|
+
sighash: string;
|
|
67
|
+
/** Full BIP-143 preimage (hex). */
|
|
68
|
+
preimage: string;
|
|
69
|
+
/** OP_PUSH_TX DER signature + sighash byte (hex). Empty if not needed. */
|
|
70
|
+
opPushTxSig: string;
|
|
71
|
+
/** Built transaction (P2PKH funding signed, primary contract input uses placeholder sigs). */
|
|
72
|
+
tx: BsvTransaction;
|
|
73
|
+
/** User-visible arg positions that need external Sig values. */
|
|
74
|
+
sigIndices: number[];
|
|
75
|
+
/** @internal */ _methodName: string;
|
|
76
|
+
/** @internal */ _resolvedArgs: unknown[];
|
|
77
|
+
/** @internal */ _methodSelectorHex: string;
|
|
78
|
+
/** @internal */ _isStateful: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* @internal
|
|
81
|
+
* True when the contract extends StatefulSmartContract (from artifact
|
|
82
|
+
* `parentClass`), independent of whether it has mutable state fields.
|
|
83
|
+
* Gates the issue-#42/#44 terminal sighash subscript trim: a stateful
|
|
84
|
+
* contract with ZERO mutable fields still auto-injects checkPreimage at
|
|
85
|
+
* method entry, so its user checkSig runs after the OP_CODESEPARATOR.
|
|
86
|
+
*/
|
|
87
|
+
_parentStateful: boolean;
|
|
88
|
+
/** @internal */ _isTerminal: boolean;
|
|
89
|
+
/** @internal */ _needsOpPushTx: boolean;
|
|
90
|
+
/** @internal */ _methodNeedsChange: boolean;
|
|
91
|
+
/** @internal Whether the unlocking script is prefixed with `_codePart` (issue #100). */ _methodUsesCodePart?: boolean;
|
|
92
|
+
/** @internal */ _changePKHHex: string;
|
|
93
|
+
/** @internal */ _changeAmount: number;
|
|
94
|
+
/** @internal */ _methodNeedsNewAmount: boolean;
|
|
95
|
+
/** @internal */ _newAmount: number;
|
|
96
|
+
/** @internal */ _preimageIndex: number;
|
|
97
|
+
/** @internal */ _contractUtxo: UTXO;
|
|
98
|
+
/** @internal */ _newLockingScript: string;
|
|
99
|
+
/** @internal */ _newSatoshis: number;
|
|
100
|
+
/** @internal */ _hasMultiOutput: boolean;
|
|
101
|
+
/** @internal */ _contractOutputs: Array<{
|
|
102
|
+
script: string;
|
|
103
|
+
satoshis: number;
|
|
104
|
+
}>;
|
|
105
|
+
/**
|
|
106
|
+
* @internal
|
|
107
|
+
* Pre-resolved intent-intrinsic witness hex (PUSHDATA-encoded
|
|
108
|
+
* `_prevOutScript_*` followed by `_serialisedOutputs`, ABI order).
|
|
109
|
+
* Empty when the method has no auto-injected intent params.
|
|
110
|
+
*/
|
|
111
|
+
_intentWitnessHex: string;
|
|
112
|
+
}
|
|
113
|
+
export interface CallOptions {
|
|
114
|
+
satoshis?: number;
|
|
115
|
+
changeAddress?: string;
|
|
116
|
+
/** Override the public key used for the change output (hex-encoded).
|
|
117
|
+
* Defaults to the signer's public key. */
|
|
118
|
+
changePubKey?: string;
|
|
119
|
+
/** New state values for the continuation output (stateful contracts). */
|
|
120
|
+
newState?: Record<string, unknown>;
|
|
121
|
+
/**
|
|
122
|
+
* Multiple continuation outputs for multi-output methods (e.g., `transfer`).
|
|
123
|
+
* Each entry specifies the satoshis and state for one output UTXO.
|
|
124
|
+
* When provided, replaces the single continuation output from `newState`.
|
|
125
|
+
*/
|
|
126
|
+
outputs?: Array<{
|
|
127
|
+
satoshis: number;
|
|
128
|
+
state: Record<string, unknown>;
|
|
129
|
+
}>;
|
|
130
|
+
/**
|
|
131
|
+
* Additional contract UTXOs to include as inputs (e.g., for merge, swap,
|
|
132
|
+
* or any multi-input spending pattern). Each UTXO's unlocking script uses
|
|
133
|
+
* the same method as the primary call, with OP_PUSH_TX and Sig
|
|
134
|
+
* auto-computed per input.
|
|
135
|
+
*/
|
|
136
|
+
additionalContractInputs?: UTXO[];
|
|
137
|
+
/**
|
|
138
|
+
* Per-input args for additional contract inputs. When provided,
|
|
139
|
+
* `additionalContractInputArgs[i]` overrides the args for
|
|
140
|
+
* `additionalContractInputs[i]`. Sig params (null) are still
|
|
141
|
+
* auto-computed per input.
|
|
142
|
+
*
|
|
143
|
+
* If not provided, all additional inputs use the same args as the
|
|
144
|
+
* primary call.
|
|
145
|
+
*/
|
|
146
|
+
additionalContractInputArgs?: unknown[][];
|
|
147
|
+
/**
|
|
148
|
+
* Terminal outputs for methods that verify exact output structure via
|
|
149
|
+
* extractOutputHash(). When set, the transaction is built with ONLY
|
|
150
|
+
* the contract UTXO as input (no funding inputs, no change output).
|
|
151
|
+
* The fee comes from the contract balance. The contract is considered
|
|
152
|
+
* fully spent after this call (currentUtxo becomes null).
|
|
153
|
+
*
|
|
154
|
+
* Each output specifies the exact locking script hex and satoshis.
|
|
155
|
+
*/
|
|
156
|
+
terminalOutputs?: Array<{
|
|
157
|
+
scriptHex: string;
|
|
158
|
+
satoshis: number;
|
|
159
|
+
}>;
|
|
160
|
+
/**
|
|
161
|
+
* Additional funding UTXOs to include as P2PKH inputs for terminal
|
|
162
|
+
* method calls. Enables terminal methods to receive additional funds
|
|
163
|
+
* when the contract's own balance is insufficient for outputs + fees.
|
|
164
|
+
*/
|
|
165
|
+
fundingUtxos?: UTXO[];
|
|
166
|
+
/**
|
|
167
|
+
* A single plain P2PKH UTXO added to a terminal call tx purely to pay the
|
|
168
|
+
* miner fee (issue #118). A true terminal method pays out the full contract
|
|
169
|
+
* balance, so fee would be 0 and ARC rejects; the covenant asserts its exact
|
|
170
|
+
* output set, so no change output can absorb a fee. The fee input is added
|
|
171
|
+
* BEFORE the OP_PUSH_TX preimage is computed (so hashPrevouts covers it) and
|
|
172
|
+
* is consumed entirely as fee — no change output is created. Signed with
|
|
173
|
+
* `fundingSigner ?? signer`. The covenant's output assertions are untouched.
|
|
174
|
+
*
|
|
175
|
+
* IMPORTANT: because there is no change output, the ENTIRE feeUtxo is spent
|
|
176
|
+
* as fee — any amount beyond the actual miner fee is BURNED, not returned.
|
|
177
|
+
* Size the feeUtxo close to the intended fee (a few hundred sats at the BSV
|
|
178
|
+
* standard 0.1 sat/byte is typical for a small terminal tx). The SDK emits a
|
|
179
|
+
* `console.warn` when the supplied feeUtxo dwarfs the terminal tx's estimated
|
|
180
|
+
* fee (> 5x and > ~1000 sats of excess), so an accidental large coin is
|
|
181
|
+
* caught before broadcast.
|
|
182
|
+
*/
|
|
183
|
+
feeUtxo?: UTXO;
|
|
184
|
+
/**
|
|
185
|
+
* Optional explicit override for data outputs emitted via
|
|
186
|
+
* `this.addDataOutput(...)` in the method body. When omitted, the SDK
|
|
187
|
+
* resolves data outputs automatically by running the ANF interpreter on
|
|
188
|
+
* the method body (the common case). Pass a non-empty array to bypass
|
|
189
|
+
* the interpreter.
|
|
190
|
+
*/
|
|
191
|
+
dataOutputs?: Array<{
|
|
192
|
+
script: string;
|
|
193
|
+
satoshis: number | bigint;
|
|
194
|
+
}>;
|
|
195
|
+
/**
|
|
196
|
+
* Override the call tx's nLockTime field. Defaults to unset → SDK uses 0
|
|
197
|
+
* (legacy behavior, preserves existing contracts). Set for contracts that
|
|
198
|
+
* assert `extractLocktime(preimage) >= deadline` (e.g. auction close/claim).
|
|
199
|
+
* Threaded through both the non-terminal and terminal call-tx build sites.
|
|
200
|
+
*/
|
|
201
|
+
locktime?: number;
|
|
202
|
+
/**
|
|
203
|
+
* Override the nSequence written onto EVERY input of the call tx (issue #131).
|
|
204
|
+
* Defaults are zero-config: when `locktime` is set and non-zero, sequence
|
|
205
|
+
* defaults to 0xfffffffe (non-final, so consensus actually enforces
|
|
206
|
+
* nLockTime); otherwise it stays 0xffffffff (final, legacy). Set explicitly
|
|
207
|
+
* only for RBF or custom relative-locktime scenarios. Threaded through the
|
|
208
|
+
* non-terminal and terminal call-tx build sites.
|
|
209
|
+
*/
|
|
210
|
+
sequence?: number;
|
|
211
|
+
/**
|
|
212
|
+
* Cap the number of P2PKH funding inputs added to a non-terminal call tx
|
|
213
|
+
* (issue #133). Funding is chosen by smallest-sufficient, largest-first
|
|
214
|
+
* selection (the same `selectUtxos` strategy deploy uses). If covering the
|
|
215
|
+
* outputs + fee would need more than this many inputs, the call throws
|
|
216
|
+
* rather than silently sweeping the wallet. Unset → no cap.
|
|
217
|
+
*/
|
|
218
|
+
maxFundingInputs?: number;
|
|
219
|
+
/**
|
|
220
|
+
* Signer for the P2PKH funding (and terminal fee) inputs (issue #134). When
|
|
221
|
+
* the funding/fee UTXOs are owned by a different key than the connected
|
|
222
|
+
* method signer, set this so those inputs are signed by their real owner.
|
|
223
|
+
* The method's own `Sig` args are still signed by the connected signer.
|
|
224
|
+
* Defaults to the connected signer (zero behaviour change).
|
|
225
|
+
*/
|
|
226
|
+
fundingSigner?: Signer;
|
|
227
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* R-062 / CL-BUG-105 — deploy-time gate on builtins the project does not claim
|
|
3
|
+
* are sound.
|
|
4
|
+
*
|
|
5
|
+
* The compiler refuses to emit a script reaching `verifySP1FRI` unless the
|
|
6
|
+
* author wrote `@acknowledgeUnsoundSP1FriVerifier` or the invoker passed
|
|
7
|
+
* `--acknowledge-unsound-sp1-fri` (R-012). That acknowledgement stopped at
|
|
8
|
+
* whoever ran the compiler: the artifact handed on afterwards looked like any
|
|
9
|
+
* other, carried no marker of the gap, and every SDK funded it in silence —
|
|
10
|
+
* which is how an acknowledged proof-of-concept verifier reaches a
|
|
11
|
+
* value-bearing deployment with no friction.
|
|
12
|
+
*
|
|
13
|
+
* The compiler now stamps `unsoundPrimitives` into the artifact. This guard is
|
|
14
|
+
* the SDK half: every deploy path calls it BEFORE any signing or broadcast, and
|
|
15
|
+
* the caller must name each listed primitive to proceed.
|
|
16
|
+
*
|
|
17
|
+
* Deploy only, deliberately. Spending an already-deployed contract is how funds
|
|
18
|
+
* are RECOVERED from one, and refusing that would strand coins whose risk was
|
|
19
|
+
* taken at deploy time. The friction belongs where the value first enters.
|
|
20
|
+
*/
|
|
21
|
+
import type { RunarArtifact } from '../../../../pool/runar-ir-schema.js';
|
|
22
|
+
/**
|
|
23
|
+
* Throw unless every unsound primitive the artifact declares appears in
|
|
24
|
+
* `acknowledged`.
|
|
25
|
+
*
|
|
26
|
+
* @param artifact the artifact about to be funded
|
|
27
|
+
* @param acknowledged primitives the caller explicitly accepts (DeployOptions.acknowledgeUnsound)
|
|
28
|
+
* @param context call site for the message, e.g. `"Counter.deploy"`
|
|
29
|
+
*/
|
|
30
|
+
export declare function assertUnsoundPrimitivesAcknowledged(artifact: RunarArtifact, acknowledged: readonly string[] | undefined, context: string): void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* R-062 / CL-BUG-105 — deploy-time gate on builtins the project does not claim
|
|
3
|
+
* are sound.
|
|
4
|
+
*
|
|
5
|
+
* The compiler refuses to emit a script reaching `verifySP1FRI` unless the
|
|
6
|
+
* author wrote `@acknowledgeUnsoundSP1FriVerifier` or the invoker passed
|
|
7
|
+
* `--acknowledge-unsound-sp1-fri` (R-012). That acknowledgement stopped at
|
|
8
|
+
* whoever ran the compiler: the artifact handed on afterwards looked like any
|
|
9
|
+
* other, carried no marker of the gap, and every SDK funded it in silence —
|
|
10
|
+
* which is how an acknowledged proof-of-concept verifier reaches a
|
|
11
|
+
* value-bearing deployment with no friction.
|
|
12
|
+
*
|
|
13
|
+
* The compiler now stamps `unsoundPrimitives` into the artifact. This guard is
|
|
14
|
+
* the SDK half: every deploy path calls it BEFORE any signing or broadcast, and
|
|
15
|
+
* the caller must name each listed primitive to proceed.
|
|
16
|
+
*
|
|
17
|
+
* Deploy only, deliberately. Spending an already-deployed contract is how funds
|
|
18
|
+
* are RECOVERED from one, and refusing that would strand coins whose risk was
|
|
19
|
+
* taken at deploy time. The friction belongs where the value first enters.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Throw unless every unsound primitive the artifact declares appears in
|
|
23
|
+
* `acknowledged`.
|
|
24
|
+
*
|
|
25
|
+
* @param artifact the artifact about to be funded
|
|
26
|
+
* @param acknowledged primitives the caller explicitly accepts (DeployOptions.acknowledgeUnsound)
|
|
27
|
+
* @param context call site for the message, e.g. `"Counter.deploy"`
|
|
28
|
+
*/
|
|
29
|
+
export function assertUnsoundPrimitivesAcknowledged(artifact, acknowledged, context) {
|
|
30
|
+
const declared = artifact.unsoundPrimitives ?? [];
|
|
31
|
+
if (declared.length === 0)
|
|
32
|
+
return;
|
|
33
|
+
const ok = new Set(acknowledged ?? []);
|
|
34
|
+
const missing = declared.filter((p) => !ok.has(p));
|
|
35
|
+
if (missing.length === 0)
|
|
36
|
+
return;
|
|
37
|
+
throw new Error(`${context}: this artifact reaches ${missing.length} builtin${missing.length === 1 ? '' : 's'} ` +
|
|
38
|
+
`the compiler does not claim is sound: ${missing.join(', ')}. ` +
|
|
39
|
+
`The compiler emitted it only because the gap was acknowledged at COMPILE time; ` +
|
|
40
|
+
`funding it is a second decision, and this SDK will not make it for you. ` +
|
|
41
|
+
`Pass acknowledgeUnsound: [${missing.map((p) => `'${p}'`).join(', ')}] to proceed.`);
|
|
42
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runar-sdk names the Pool template uses (src/pool/template.ts, src/pool/artifact.ts), from
|
|
3
|
+
* the vendored modules beside this file (`runar-sdk/src`, runar d207ee8e; NOTICE). runar-sdk's
|
|
4
|
+
* own barrel also re-exports its providers, signers and codegen, which are not vendored.
|
|
5
|
+
*/
|
|
6
|
+
export { EMPTY_SIG, RunarContract, encodeArg, encodePushData, encodeScriptNumber } from "./runar-sdk/src/contract.js";
|
|
7
|
+
export { extractConstructorArgs, matchesArtifact } from "./runar-sdk/src/script-utils.js";
|
|
8
|
+
export { extractStateFromScript, findLastOpReturn, serializeState } from "./runar-sdk/src/state.js";
|
|
9
|
+
export type { RunarArtifact } from "../../pool/runar-ir-schema.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runar-sdk names the Pool template uses (src/pool/template.ts, src/pool/artifact.ts), from
|
|
3
|
+
* the vendored modules beside this file (`runar-sdk/src`, runar d207ee8e; NOTICE). runar-sdk's
|
|
4
|
+
* own barrel also re-exports its providers, signers and codegen, which are not vendored.
|
|
5
|
+
*/
|
|
6
|
+
export { EMPTY_SIG, RunarContract, encodeArg, encodePushData, encodeScriptNumber } from "./runar-sdk/src/contract.js";
|
|
7
|
+
export { extractConstructorArgs, matchesArtifact } from "./runar-sdk/src/script-utils.js";
|
|
8
|
+
export { extractStateFromScript, findLastOpReturn, serializeState } from "./runar-sdk/src/state.js";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A wallet-built action whose inputs the page unlocks (skein-amm 0.29.0, David Case 2026-11-02:
|
|
3
|
+
* Move back and Close are wallet createActions). The page names the inputs it spends (an
|
|
4
|
+
* `amm-swap` output, a pool), their source transactions (`inputBEEF`) and the outputs; the wallet
|
|
5
|
+
* adds its own inputs for the miner fee and its change, and hands the transaction back for
|
|
6
|
+
* signing (BRC-100: an input with `unlockingScriptLength` and no `unlockingScript`). The page
|
|
7
|
+
* computes its unlocking scripts over that transaction (`createSignature` under the key each
|
|
8
|
+
* input's row names) and passes them to `signAction`; the wallet signs its own inputs,
|
|
9
|
+
* broadcasts, and records the action, every output with the customInstructions the page gave it.
|
|
10
|
+
* Aborted when anything fails before the wallet has the signatures.
|
|
11
|
+
*/
|
|
12
|
+
import { Transaction, type CreateActionArgs, type WalletInterface } from "@bsv/sdk";
|
|
13
|
+
export type Spends = Record<number, {
|
|
14
|
+
unlockingScript: string;
|
|
15
|
+
}>;
|
|
16
|
+
export interface SignedAction {
|
|
17
|
+
txid: string;
|
|
18
|
+
/** The signed transaction as the wallet's AtomicBEEF. */
|
|
19
|
+
tx: number[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* `createAction(args)` → `sign(the wallet's transaction)` → `signAction({reference, spends})`.
|
|
23
|
+
* `sign` gets the unsigned transaction with every input's source transaction linked (the
|
|
24
|
+
* signable BEEF) and answers the page's unlocking scripts by input index.
|
|
25
|
+
*/
|
|
26
|
+
export declare function runAppSignedAction(wallet: WalletInterface, args: CreateActionArgs, sign: (tx: Transaction) => Promise<Spends>): Promise<SignedAction>;
|
|
27
|
+
/** The index of the input spending `txid.vout` in `tx`, or -1. */
|
|
28
|
+
export declare function inputIndexOf(tx: Transaction, txid: string, vout: number): number;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A wallet-built action whose inputs the page unlocks (skein-amm 0.29.0, David Case 2026-11-02:
|
|
3
|
+
* Move back and Close are wallet createActions). The page names the inputs it spends (an
|
|
4
|
+
* `amm-swap` output, a pool), their source transactions (`inputBEEF`) and the outputs; the wallet
|
|
5
|
+
* adds its own inputs for the miner fee and its change, and hands the transaction back for
|
|
6
|
+
* signing (BRC-100: an input with `unlockingScriptLength` and no `unlockingScript`). The page
|
|
7
|
+
* computes its unlocking scripts over that transaction (`createSignature` under the key each
|
|
8
|
+
* input's row names) and passes them to `signAction`; the wallet signs its own inputs,
|
|
9
|
+
* broadcasts, and records the action, every output with the customInstructions the page gave it.
|
|
10
|
+
* Aborted when anything fails before the wallet has the signatures.
|
|
11
|
+
*/
|
|
12
|
+
import { Transaction } from "@bsv/sdk";
|
|
13
|
+
/**
|
|
14
|
+
* `createAction(args)` → `sign(the wallet's transaction)` → `signAction({reference, spends})`.
|
|
15
|
+
* `sign` gets the unsigned transaction with every input's source transaction linked (the
|
|
16
|
+
* signable BEEF) and answers the page's unlocking scripts by input index.
|
|
17
|
+
*/
|
|
18
|
+
export async function runAppSignedAction(wallet, args, sign) {
|
|
19
|
+
const created = await wallet.createAction(args);
|
|
20
|
+
const signable = created.signableTransaction;
|
|
21
|
+
if (!signable)
|
|
22
|
+
throw new Error("the wallet did not hand the transaction back for the page's signatures");
|
|
23
|
+
const reference = signable.reference;
|
|
24
|
+
try {
|
|
25
|
+
const tx = Transaction.fromAtomicBEEF(Array.from(signable.tx));
|
|
26
|
+
for (const input of tx.inputs)
|
|
27
|
+
input.sourceTXID ??= input.sourceTransaction?.id("hex");
|
|
28
|
+
const spends = await sign(tx);
|
|
29
|
+
const signed = await wallet.signAction({ reference, spends, ...(args.options?.acceptDelayedBroadcast !== undefined ? { options: { acceptDelayedBroadcast: args.options.acceptDelayedBroadcast } } : {}) });
|
|
30
|
+
if (!signed.txid || !signed.tx)
|
|
31
|
+
throw new Error("the wallet returned no signed transaction");
|
|
32
|
+
return { txid: signed.txid, tx: Array.from(signed.tx) };
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
await wallet.abortAction({ reference }).catch(() => undefined);
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** The index of the input spending `txid.vout` in `tx`, or -1. */
|
|
40
|
+
export function inputIndexOf(tx, txid, vout) {
|
|
41
|
+
return tx.inputs.findIndex((i) => (i.sourceTXID ?? i.sourceTransaction?.id("hex")) === txid && i.sourceOutputIndex === vout);
|
|
42
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BRC-29 ("wallet payment") outputs to the user's own wallet: the sats a
|
|
3
|
+
* user receives from a pool (a token-in swap's payout, a RemoveLiquidity
|
|
4
|
+
* sats withdrawal). No basket: the wallet does not track the output when the
|
|
5
|
+
* action is created; it takes it in with `internalizeAction({protocol:
|
|
6
|
+
* "wallet payment", paymentRemittance})` once the transaction is final, and
|
|
7
|
+
* from then on spends it as its own change.
|
|
8
|
+
*
|
|
9
|
+
* The derivation, as wallet-toolbox checks it
|
|
10
|
+
* (src/signer/methods/internalizeAction.ts `setupWalletPaymentForOutput`):
|
|
11
|
+
*
|
|
12
|
+
* keyID = `${derivationPrefix} ${derivationSuffix}`
|
|
13
|
+
* privKey = keyDeriver.derivePrivateKey([2, "3241645161d8"], keyID, senderIdentityKey)
|
|
14
|
+
* lock = P2PKH(privKey.toAddress())
|
|
15
|
+
*
|
|
16
|
+
* The page is both payer-side author and payee, so senderIdentityKey is the
|
|
17
|
+
* user's own identity key. The payee side of that derivation is
|
|
18
|
+
* `rootKey.deriveChild(identityPub, invoice)`; the page asks for the same
|
|
19
|
+
* key with `getPublicKey({protocolID: BRC29, keyID, counterparty: "self",
|
|
20
|
+
* forSelf: true})`, which is `rootKey.deriveChild(rootKey.toPublicKey(),
|
|
21
|
+
* invoice).toPublicKey()` (@bsv/sdk KeyDeriver: `normalizeCounterparty("self")`
|
|
22
|
+
* is `rootKey.toPublicKey()`, which is the identity key). "self" rather than
|
|
23
|
+
* the identity key's hex, because WalletPermissionsManager keys level-2
|
|
24
|
+
* grants by the exact counterparty string and the manifest can only name
|
|
25
|
+
* "self" (public/manifest.json, README "Permissions"). With counterparty =
|
|
26
|
+
* self, forSelf true and false give the same key (the ECDH secret is
|
|
27
|
+
* root·root·G either way).
|
|
28
|
+
*/
|
|
29
|
+
import { type WalletInterface, type WalletProtocol } from "@bsv/sdk";
|
|
30
|
+
export declare const BRC29_PROTOCOL: WalletProtocol;
|
|
31
|
+
export declare const WALLET_PAYMENT: "wallet payment";
|
|
32
|
+
export interface PaymentRemittance {
|
|
33
|
+
derivationPrefix: string;
|
|
34
|
+
derivationSuffix: string;
|
|
35
|
+
senderIdentityKey: string;
|
|
36
|
+
}
|
|
37
|
+
/** A BRC-29 payout as the page records it: the output, its remittance. */
|
|
38
|
+
export interface Brc29Payout {
|
|
39
|
+
outputIndex: number;
|
|
40
|
+
satoshis: number;
|
|
41
|
+
/** P2PKH to the derived key, hex. */
|
|
42
|
+
lockingScript: string;
|
|
43
|
+
remittance: PaymentRemittance;
|
|
44
|
+
}
|
|
45
|
+
/** Random base64, as wallet-toolbox's `randomBytesBase64(8)` for a payment's prefix and suffix. */
|
|
46
|
+
export declare function randomBase64(bytes?: number): string;
|
|
47
|
+
export declare function brc29KeyID(r: {
|
|
48
|
+
derivationPrefix: string;
|
|
49
|
+
derivationSuffix: string;
|
|
50
|
+
}): string;
|
|
51
|
+
/** `${prefix} ${suffix}` → the two parts, or null (base64 has no spaces). */
|
|
52
|
+
export declare function splitBrc29KeyID(keyID: string): {
|
|
53
|
+
derivationPrefix: string;
|
|
54
|
+
derivationSuffix: string;
|
|
55
|
+
} | null;
|
|
56
|
+
export declare function isBrc29Protocol(p: WalletProtocol | readonly unknown[] | undefined): boolean;
|
|
57
|
+
/** The user's identity key (one `getPublicKey({identityKey: true})`). */
|
|
58
|
+
export declare function identityKeyOf(wallet: WalletInterface): Promise<string>;
|
|
59
|
+
/** The payee key of a BRC-29 payment to self (see the module comment). */
|
|
60
|
+
export declare function brc29PublicKey(wallet: WalletInterface, r: {
|
|
61
|
+
derivationPrefix: string;
|
|
62
|
+
derivationSuffix: string;
|
|
63
|
+
}): Promise<string>;
|
|
64
|
+
export declare function p2pkhHexOf(publicKey: string): string;
|
|
65
|
+
/** A payout key: random prefix and suffix unless `derivation` names them (0.29.1: a swap leg's, derived from its input), sender = the user's identity. */
|
|
66
|
+
export declare function newBrc29Payout(wallet: WalletInterface, identityKey?: string, derivation?: {
|
|
67
|
+
derivationPrefix: string;
|
|
68
|
+
derivationSuffix: string;
|
|
69
|
+
}): Promise<{
|
|
70
|
+
remittance: PaymentRemittance;
|
|
71
|
+
publicKey: string;
|
|
72
|
+
lockingScript: string;
|
|
73
|
+
}>;
|
|
74
|
+
/**
|
|
75
|
+
* The final step: the wallet takes the payout in. `atomicBeef` is the
|
|
76
|
+
* AtomicBEEF of the final transaction (all signatures in).
|
|
77
|
+
*/
|
|
78
|
+
export declare function internalizePayout(wallet: WalletInterface, atomicBeef: number[], payout: {
|
|
79
|
+
outputIndex: number;
|
|
80
|
+
remittance: PaymentRemittance;
|
|
81
|
+
}, description: string): Promise<{
|
|
82
|
+
accepted: boolean;
|
|
83
|
+
}>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BRC-29 ("wallet payment") outputs to the user's own wallet: the sats a
|
|
3
|
+
* user receives from a pool (a token-in swap's payout, a RemoveLiquidity
|
|
4
|
+
* sats withdrawal). No basket: the wallet does not track the output when the
|
|
5
|
+
* action is created; it takes it in with `internalizeAction({protocol:
|
|
6
|
+
* "wallet payment", paymentRemittance})` once the transaction is final, and
|
|
7
|
+
* from then on spends it as its own change.
|
|
8
|
+
*
|
|
9
|
+
* The derivation, as wallet-toolbox checks it
|
|
10
|
+
* (src/signer/methods/internalizeAction.ts `setupWalletPaymentForOutput`):
|
|
11
|
+
*
|
|
12
|
+
* keyID = `${derivationPrefix} ${derivationSuffix}`
|
|
13
|
+
* privKey = keyDeriver.derivePrivateKey([2, "3241645161d8"], keyID, senderIdentityKey)
|
|
14
|
+
* lock = P2PKH(privKey.toAddress())
|
|
15
|
+
*
|
|
16
|
+
* The page is both payer-side author and payee, so senderIdentityKey is the
|
|
17
|
+
* user's own identity key. The payee side of that derivation is
|
|
18
|
+
* `rootKey.deriveChild(identityPub, invoice)`; the page asks for the same
|
|
19
|
+
* key with `getPublicKey({protocolID: BRC29, keyID, counterparty: "self",
|
|
20
|
+
* forSelf: true})`, which is `rootKey.deriveChild(rootKey.toPublicKey(),
|
|
21
|
+
* invoice).toPublicKey()` (@bsv/sdk KeyDeriver: `normalizeCounterparty("self")`
|
|
22
|
+
* is `rootKey.toPublicKey()`, which is the identity key). "self" rather than
|
|
23
|
+
* the identity key's hex, because WalletPermissionsManager keys level-2
|
|
24
|
+
* grants by the exact counterparty string and the manifest can only name
|
|
25
|
+
* "self" (public/manifest.json, README "Permissions"). With counterparty =
|
|
26
|
+
* self, forSelf true and false give the same key (the ECDH secret is
|
|
27
|
+
* root·root·G either way).
|
|
28
|
+
*/
|
|
29
|
+
import { P2PKH, PublicKey, Utils } from "@bsv/sdk";
|
|
30
|
+
export const BRC29_PROTOCOL = [2, "3241645161d8"];
|
|
31
|
+
export const WALLET_PAYMENT = "wallet payment";
|
|
32
|
+
/** Random base64, as wallet-toolbox's `randomBytesBase64(8)` for a payment's prefix and suffix. */
|
|
33
|
+
export function randomBase64(bytes = 8) {
|
|
34
|
+
return Utils.toBase64(Array.from(crypto.getRandomValues(new Uint8Array(bytes))));
|
|
35
|
+
}
|
|
36
|
+
export function brc29KeyID(r) {
|
|
37
|
+
return `${r.derivationPrefix} ${r.derivationSuffix}`;
|
|
38
|
+
}
|
|
39
|
+
/** `${prefix} ${suffix}` → the two parts, or null (base64 has no spaces). */
|
|
40
|
+
export function splitBrc29KeyID(keyID) {
|
|
41
|
+
const parts = keyID.split(" ");
|
|
42
|
+
if (parts.length !== 2 || !parts[0] || !parts[1])
|
|
43
|
+
return null;
|
|
44
|
+
return { derivationPrefix: parts[0], derivationSuffix: parts[1] };
|
|
45
|
+
}
|
|
46
|
+
export function isBrc29Protocol(p) {
|
|
47
|
+
return Array.isArray(p) && p[0] === BRC29_PROTOCOL[0] && p[1] === BRC29_PROTOCOL[1];
|
|
48
|
+
}
|
|
49
|
+
/** The user's identity key (one `getPublicKey({identityKey: true})`). */
|
|
50
|
+
export async function identityKeyOf(wallet) {
|
|
51
|
+
return (await wallet.getPublicKey({ identityKey: true })).publicKey;
|
|
52
|
+
}
|
|
53
|
+
/** The payee key of a BRC-29 payment to self (see the module comment). */
|
|
54
|
+
export async function brc29PublicKey(wallet, r) {
|
|
55
|
+
const { publicKey } = await wallet.getPublicKey({ protocolID: BRC29_PROTOCOL, keyID: brc29KeyID(r), counterparty: "self", forSelf: true });
|
|
56
|
+
return publicKey;
|
|
57
|
+
}
|
|
58
|
+
export function p2pkhHexOf(publicKey) {
|
|
59
|
+
return new P2PKH().lock(PublicKey.fromString(publicKey).toAddress()).toHex();
|
|
60
|
+
}
|
|
61
|
+
/** A payout key: random prefix and suffix unless `derivation` names them (0.29.1: a swap leg's, derived from its input), sender = the user's identity. */
|
|
62
|
+
export async function newBrc29Payout(wallet, identityKey, derivation) {
|
|
63
|
+
const senderIdentityKey = identityKey ?? (await identityKeyOf(wallet));
|
|
64
|
+
const remittance = { derivationPrefix: derivation?.derivationPrefix ?? randomBase64(), derivationSuffix: derivation?.derivationSuffix ?? randomBase64(), senderIdentityKey };
|
|
65
|
+
const publicKey = await brc29PublicKey(wallet, remittance);
|
|
66
|
+
return { remittance, publicKey, lockingScript: p2pkhHexOf(publicKey) };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The final step: the wallet takes the payout in. `atomicBeef` is the
|
|
70
|
+
* AtomicBEEF of the final transaction (all signatures in).
|
|
71
|
+
*/
|
|
72
|
+
export async function internalizePayout(wallet, atomicBeef, payout, description) {
|
|
73
|
+
const r = await wallet.internalizeAction({
|
|
74
|
+
tx: atomicBeef,
|
|
75
|
+
outputs: [{ outputIndex: payout.outputIndex, protocol: WALLET_PAYMENT, paymentRemittance: { ...payout.remittance } }],
|
|
76
|
+
description: description.length <= 50 ? description : `${description.slice(0, 49)}…`,
|
|
77
|
+
labels: ["amm-payout"],
|
|
78
|
+
});
|
|
79
|
+
return { accepted: r.accepted };
|
|
80
|
+
}
|