dxs-stas-sdk 3.0.1 → 3.0.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 +121 -111
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
# dxs-stas-sdk
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for building and
|
|
3
|
+
TypeScript SDK for building, reading, and validating Bitcoin SV transactions.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The public surface is split into three entrypoints:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- `dxs-stas-sdk/dstas`: canonical Divisible STAS flow API
|
|
8
|
+
- `dxs-stas-sdk/stas`: older STAS workflow helpers
|
|
9
|
+
- `dxs-stas-sdk/bsv`: low-level blockchain primitives, script tooling, and transaction utilities
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- ECDSA signing is deterministic (RFC 6979 behavior from `@noble/secp256k1`) with `lowS: true`.
|
|
12
|
-
- Strict transaction parsing is enabled by default.
|
|
13
|
-
- Strict fee-rate validation is enabled by default.
|
|
14
|
-
- Strict script evaluation defaults include a 1MB max element size limit (when strict eval is enabled).
|
|
15
|
-
- DSTAS multisig key validation enforces compressed secp256k1 points and `n <= 5`.
|
|
11
|
+
Root imports expose only the `dstas`, `stas`, and `bsv` namespaces.
|
|
16
12
|
|
|
17
13
|
## Install
|
|
18
14
|
|
|
@@ -20,43 +16,36 @@ All binary inputs/outputs are `Uint8Array` (no Node.js `Buffer` in the public AP
|
|
|
20
16
|
npm install dxs-stas-sdk
|
|
21
17
|
```
|
|
22
18
|
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
- `dxs-stas-sdk/dstas`: canonical DSTAS issue/transfer/freeze/confiscation/redeem/swap flows
|
|
26
|
-
- `dxs-stas-sdk/stas`: older STAS transaction helpers
|
|
27
|
-
- `dxs-stas-sdk`: namespace-only root entrypoint for `dstas`, `stas`, and `bsv`
|
|
28
|
-
- `dxs-stas-sdk/bsv`: low-level blockchain primitives, byte/hash helpers, transaction tooling, and script readers/builders
|
|
29
|
-
|
|
30
|
-
## AI agent onboarding
|
|
19
|
+
## Choose your entrypoint
|
|
31
20
|
|
|
32
|
-
|
|
21
|
+
Use the narrowest surface that matches your task.
|
|
33
22
|
|
|
34
|
-
- `
|
|
35
|
-
-
|
|
36
|
-
- `
|
|
23
|
+
- `dxs-stas-sdk/dstas`
|
|
24
|
+
Use for protocol-facing DSTAS flows: issue, transfer, split, merge, freeze, unfreeze, confiscation, swap, redeem.
|
|
25
|
+
- `dxs-stas-sdk/stas`
|
|
26
|
+
Use for the older STAS transaction workflow.
|
|
27
|
+
- `dxs-stas-sdk/bsv`
|
|
28
|
+
Use for low-level work: keys, addresses, scripts, transaction parsing, transaction building, and script evaluation.
|
|
29
|
+
- `dxs-stas-sdk`
|
|
30
|
+
Use only if you explicitly want namespace aggregation for `dstas`, `stas`, and `bsv`.
|
|
37
31
|
|
|
38
|
-
##
|
|
39
|
-
|
|
40
|
-
An `OutPoint` represents a spendable UTXO: txid, vout, locking script, satoshis, and owner address.
|
|
41
|
-
|
|
42
|
-
`LockingScript` is the canonical property name in API objects.
|
|
43
|
-
|
|
44
|
-
## Example: build a DSTAS issue + transfer flow
|
|
32
|
+
## Quickstart: DSTAS issue and transfer
|
|
45
33
|
|
|
46
34
|
```ts
|
|
47
|
-
import {
|
|
35
|
+
import { dstas } from "dxs-stas-sdk/dstas";
|
|
36
|
+
import { bsv } from "dxs-stas-sdk/bsv";
|
|
48
37
|
|
|
49
38
|
const {
|
|
50
39
|
OutPoint,
|
|
51
40
|
PrivateKey,
|
|
52
41
|
TokenScheme,
|
|
53
42
|
TransactionReader,
|
|
43
|
+
fromHex,
|
|
54
44
|
toHex,
|
|
55
45
|
utf8ToBytes,
|
|
56
|
-
fromHex,
|
|
57
46
|
} = bsv;
|
|
58
47
|
|
|
59
|
-
const
|
|
48
|
+
const issuer = new PrivateKey(
|
|
60
49
|
fromHex("b62fd57a07804f79291317261054eb9b19c9ccec49146c38b30a29d48636c368"),
|
|
61
50
|
);
|
|
62
51
|
const alice = new PrivateKey(
|
|
@@ -65,26 +54,25 @@ const alice = new PrivateKey(
|
|
|
65
54
|
|
|
66
55
|
const scheme = new TokenScheme(
|
|
67
56
|
"Divisible STAS",
|
|
68
|
-
toHex(
|
|
57
|
+
toHex(issuer.Address.Hash160),
|
|
69
58
|
"DSTAS",
|
|
70
59
|
1,
|
|
71
60
|
{
|
|
72
61
|
isDivisible: true,
|
|
73
62
|
freeze: true,
|
|
74
63
|
confiscation: true,
|
|
75
|
-
freezeAuthority: { m: 1, publicKeys: [toHex(
|
|
76
|
-
confiscationAuthority: { m: 1, publicKeys: [toHex(
|
|
64
|
+
freezeAuthority: { m: 1, publicKeys: [toHex(issuer.PublicKey)] },
|
|
65
|
+
confiscationAuthority: { m: 1, publicKeys: [toHex(issuer.PublicKey)] },
|
|
77
66
|
},
|
|
78
67
|
);
|
|
79
68
|
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
const fundingOut = OutPoint.fromTransaction(sourceTx, 0);
|
|
69
|
+
const fundingTx = TransactionReader.readHex("<funding-tx-hex>");
|
|
70
|
+
const fundingOut = OutPoint.fromTransaction(fundingTx, 0);
|
|
83
71
|
|
|
84
72
|
const { issueTxHex } = dstas.BuildDstasIssueTxs({
|
|
85
|
-
fundingPayment: { OutPoint: fundingOut, Owner:
|
|
73
|
+
fundingPayment: { OutPoint: fundingOut, Owner: issuer },
|
|
86
74
|
scheme,
|
|
87
|
-
destinations: [{ Satoshis: 100, To:
|
|
75
|
+
destinations: [{ Satoshis: 100, To: issuer.Address }],
|
|
88
76
|
feeRate: 0.1,
|
|
89
77
|
});
|
|
90
78
|
|
|
@@ -93,30 +81,50 @@ const stasOut = OutPoint.fromTransaction(issueTx, 0);
|
|
|
93
81
|
const feeOut = OutPoint.fromTransaction(issueTx, 1);
|
|
94
82
|
|
|
95
83
|
const transferTxHex = dstas.BuildDstasTransferTx({
|
|
96
|
-
stasPayment: { OutPoint: stasOut, Owner:
|
|
97
|
-
feePayment: { OutPoint: feeOut, Owner:
|
|
84
|
+
stasPayment: { OutPoint: stasOut, Owner: issuer },
|
|
85
|
+
feePayment: { OutPoint: feeOut, Owner: issuer },
|
|
98
86
|
destination: { Satoshis: 100, To: alice.Address },
|
|
99
87
|
scheme,
|
|
100
88
|
note: [utf8ToBytes("DSTAS"), utf8ToBytes("transfer")],
|
|
101
89
|
});
|
|
102
90
|
```
|
|
103
91
|
|
|
104
|
-
##
|
|
92
|
+
## High-level DSTAS APIs
|
|
93
|
+
|
|
94
|
+
Use these first.
|
|
95
|
+
|
|
96
|
+
### Single-flow builders
|
|
97
|
+
|
|
98
|
+
`dxs-stas-sdk/dstas` exports `BuildDstas*` helpers for individual transactions:
|
|
99
|
+
|
|
100
|
+
- `BuildDstasIssueTxs`
|
|
101
|
+
- `BuildDstasTransferTx`
|
|
102
|
+
- `BuildDstasSplitTx`
|
|
103
|
+
- `BuildDstasMergeTx`
|
|
104
|
+
- `BuildDstasFreezeTx`
|
|
105
|
+
- `BuildDstasUnfreezeTx`
|
|
106
|
+
- `BuildDstasConfiscateTx`
|
|
107
|
+
- `BuildDstasRedeemTx`
|
|
108
|
+
- `BuildDstasSwapTx`
|
|
109
|
+
|
|
110
|
+
These helpers are the right starting point when you already know the exact flow you need to build.
|
|
111
|
+
|
|
112
|
+
### Multi-step planning with `DstasBundleFactory`
|
|
113
|
+
|
|
114
|
+
Use `DstasBundleFactory` when you want the SDK to plan merge/split/service transactions for you.
|
|
115
|
+
|
|
116
|
+
Typical use cases:
|
|
117
|
+
|
|
118
|
+
- many-recipient payouts
|
|
119
|
+
- preparing UTXO sizes automatically
|
|
120
|
+
- chaining service transactions before final transfers
|
|
121
|
+
- building flows where intermediate DSTAS UTXOs must be reshaped before delivery
|
|
105
122
|
|
|
106
123
|
```ts
|
|
107
|
-
import {
|
|
124
|
+
import { dstas } from "dxs-stas-sdk/dstas";
|
|
125
|
+
import { bsv } from "dxs-stas-sdk/bsv";
|
|
108
126
|
|
|
109
|
-
const {
|
|
110
|
-
Address,
|
|
111
|
-
LockingScriptReader,
|
|
112
|
-
OutPoint,
|
|
113
|
-
ScriptType,
|
|
114
|
-
Transaction,
|
|
115
|
-
Wallet,
|
|
116
|
-
hash160,
|
|
117
|
-
toHex,
|
|
118
|
-
utf8ToBytes,
|
|
119
|
-
} = bsv;
|
|
127
|
+
const { Address, LockingScriptReader, Transaction, Wallet, utf8ToBytes } = bsv;
|
|
120
128
|
|
|
121
129
|
const { DstasBundleFactory, DstasSpendType } = dstas;
|
|
122
130
|
|
|
@@ -125,18 +133,11 @@ const stasWallet =
|
|
|
125
133
|
const feeWallet =
|
|
126
134
|
Wallet.fromMnemonic("<mnemonic>").deriveWallet("m/44'/236'/0'/0/1");
|
|
127
135
|
|
|
128
|
-
|
|
129
|
-
const getStasUtxoSet = async (minSats = 0): Promise<OutPoint[]> => {
|
|
136
|
+
const getStasUtxoSet = async (minSats = 0) => {
|
|
130
137
|
return await fetchDstasUtxosForAddress(stasWallet.Address, minSats);
|
|
131
138
|
};
|
|
132
139
|
|
|
133
|
-
const getFundingUtxo = async ({
|
|
134
|
-
estimatedFeeSatoshis,
|
|
135
|
-
}: {
|
|
136
|
-
utxoIdsToSpend: string[];
|
|
137
|
-
estimatedFeeSatoshis: number;
|
|
138
|
-
transactionsCount: number;
|
|
139
|
-
}): Promise<OutPoint> => {
|
|
140
|
+
const getFundingUtxo = async ({ estimatedFeeSatoshis }) => {
|
|
140
141
|
return await fetchFeeUtxoForAddress(feeWallet.Address, estimatedFeeSatoshis);
|
|
141
142
|
};
|
|
142
143
|
|
|
@@ -163,7 +164,7 @@ const factory = new DstasBundleFactory(
|
|
|
163
164
|
const parsed = LockingScriptReader.read(fromOutPoint.LockingScript).Dstas;
|
|
164
165
|
if (!parsed) throw new Error("Expected DSTAS input locking script");
|
|
165
166
|
if (recipient.m !== 1 || recipient.addresses.length !== 1) {
|
|
166
|
-
throw new Error("
|
|
167
|
+
throw new Error("Example keeps recipient handling at m=1");
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
return {
|
|
@@ -194,25 +195,20 @@ const factory = new DstasBundleFactory(
|
|
|
194
195
|
},
|
|
195
196
|
);
|
|
196
197
|
|
|
197
|
-
const recipients = [
|
|
198
|
-
{
|
|
199
|
-
recipient: { m: 1, addresses: [Address.fromBase58("<alice-address>")] },
|
|
200
|
-
satoshis: 150,
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
recipient: { m: 1, addresses: [Address.fromBase58("<bob-address>")] },
|
|
204
|
-
satoshis: 200,
|
|
205
|
-
},
|
|
206
|
-
];
|
|
207
|
-
|
|
208
198
|
const bundle = await factory.transfer({
|
|
209
|
-
outputs:
|
|
199
|
+
outputs: [
|
|
200
|
+
{
|
|
201
|
+
recipient: { m: 1, addresses: [Address.fromBase58("<alice-address>")] },
|
|
202
|
+
satoshis: 150,
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
recipient: { m: 1, addresses: [Address.fromBase58("<bob-address>")] },
|
|
206
|
+
satoshis: 200,
|
|
207
|
+
},
|
|
208
|
+
],
|
|
210
209
|
spendType: "transfer",
|
|
211
210
|
note: [utf8ToBytes("DSTAS"), utf8ToBytes("bundle transfer")],
|
|
212
211
|
});
|
|
213
|
-
|
|
214
|
-
console.log("transactions:", bundle.transactions?.length ?? 0);
|
|
215
|
-
console.log("paid fee satoshis:", bundle.feeSatoshis);
|
|
216
212
|
```
|
|
217
213
|
|
|
218
214
|
Notes:
|
|
@@ -220,12 +216,24 @@ Notes:
|
|
|
220
216
|
- `DstasBundleFactory` plans merge/split/transfer service transactions automatically.
|
|
221
217
|
- `note` is attached only to final transfer transaction(s), not to intermediate service transactions.
|
|
222
218
|
- `spendType` supports `transfer`, `freeze`, `unfreeze`, `confiscation`, and `swap`.
|
|
223
|
-
- For recipient multisig (`m > 1`), replace the simple `owner` derivation with your protocol-specific owner preimage/hash strategy.
|
|
224
219
|
|
|
225
|
-
##
|
|
220
|
+
## Low-level BSV toolkit
|
|
221
|
+
|
|
222
|
+
Use `dxs-stas-sdk/bsv` when you need direct blockchain primitives.
|
|
223
|
+
|
|
224
|
+
Typical surface:
|
|
225
|
+
|
|
226
|
+
- keys and wallets: `PrivateKey`, `Wallet`
|
|
227
|
+
- addressing: `Address`
|
|
228
|
+
- UTXOs: `OutPoint`
|
|
229
|
+
- transactions: `Transaction`, `TransactionReader`, `TransactionBuilder`
|
|
230
|
+
- script tooling: `ScriptBuilder`, `LockingScriptReader`, `evaluateTransactionHex`
|
|
231
|
+
- byte and hash helpers: `fromHex`, `toHex`, `utf8ToBytes`, `hash160`, `hash256`
|
|
232
|
+
|
|
233
|
+
### Example: build a simple P2PKH transaction
|
|
226
234
|
|
|
227
235
|
```ts
|
|
228
|
-
import { bsv } from "dxs-stas-sdk";
|
|
236
|
+
import { bsv } from "dxs-stas-sdk/bsv";
|
|
229
237
|
|
|
230
238
|
const {
|
|
231
239
|
Address,
|
|
@@ -246,8 +254,8 @@ const lockingScript = fromHex(
|
|
|
246
254
|
);
|
|
247
255
|
|
|
248
256
|
const utxo = new OutPoint(
|
|
249
|
-
"11".repeat(32),
|
|
250
|
-
0,
|
|
257
|
+
"11".repeat(32),
|
|
258
|
+
0,
|
|
251
259
|
lockingScript,
|
|
252
260
|
10_000,
|
|
253
261
|
from,
|
|
@@ -260,26 +268,20 @@ const txHex = TransactionBuilder.init()
|
|
|
260
268
|
.addChangeOutputWithFee(pk.Address, utxo.Satoshis - 1_000, 0.1)
|
|
261
269
|
.sign()
|
|
262
270
|
.toHex();
|
|
263
|
-
|
|
264
|
-
// Optional: pass a custom input sequence (default is 0xffffffff).
|
|
265
|
-
const txWithSequence = TransactionBuilder.init()
|
|
266
|
-
.addInput(utxo, pk, 0xfffffffe)
|
|
267
|
-
.addP2PkhOutput(1_000, to)
|
|
268
|
-
.addChangeOutputWithFee(pk.Address, utxo.Satoshis - 1_000, 0.1)
|
|
269
|
-
.sign()
|
|
270
|
-
.toHex();
|
|
271
271
|
```
|
|
272
272
|
|
|
273
|
-
##
|
|
273
|
+
## Older STAS workflow surface
|
|
274
|
+
|
|
275
|
+
Use `dxs-stas-sdk/stas` only when you need the older STAS flow helpers.
|
|
274
276
|
|
|
275
277
|
```ts
|
|
276
|
-
import {
|
|
278
|
+
import { stas } from "dxs-stas-sdk/stas";
|
|
279
|
+
import { bsv } from "dxs-stas-sdk/bsv";
|
|
277
280
|
|
|
278
281
|
const {
|
|
279
282
|
Address,
|
|
280
283
|
OutPoint,
|
|
281
284
|
PrivateKey,
|
|
282
|
-
ScriptType,
|
|
283
285
|
TokenScheme,
|
|
284
286
|
TransactionReader,
|
|
285
287
|
fromHex,
|
|
@@ -300,7 +302,6 @@ const tokenScheme = new TokenScheme(
|
|
|
300
302
|
1,
|
|
301
303
|
);
|
|
302
304
|
|
|
303
|
-
// Parse a previous transaction that produced a STAS output + fee output.
|
|
304
305
|
const prevTx = TransactionReader.readHex("<issue-tx-hex>");
|
|
305
306
|
const stasOut = OutPoint.fromTransaction(prevTx, 0);
|
|
306
307
|
const feeOut = OutPoint.fromTransaction(prevTx, 1);
|
|
@@ -314,33 +315,34 @@ const txHex = stas.BuildTransferTx({
|
|
|
314
315
|
});
|
|
315
316
|
```
|
|
316
317
|
|
|
317
|
-
##
|
|
318
|
+
## Binary and data model rules
|
|
318
319
|
|
|
319
|
-
-
|
|
320
|
-
- `OutPoint
|
|
321
|
-
-
|
|
322
|
-
- `
|
|
323
|
-
- STAS script classification relies on known token templates; unknown scripts will classify as `unknown`. (see: src/bitcoin/transaction-output.ts:21-103, src/script/script-samples.ts:5-26)
|
|
320
|
+
- Public binary inputs and outputs are `Uint8Array`, not Node.js `Buffer`.
|
|
321
|
+
- `OutPoint` represents a spendable UTXO: txid, vout, locking script, satoshis, and owner address.
|
|
322
|
+
- `LockingScript` is the canonical property name in API objects.
|
|
323
|
+
- `OutPoint.TxId` is stored as big-endian hex and serialized little-endian inside transactions.
|
|
324
324
|
|
|
325
|
-
##
|
|
325
|
+
## Security and strict mode
|
|
326
326
|
|
|
327
|
-
|
|
327
|
+
Defaults already enabled:
|
|
328
328
|
|
|
329
|
+
- deterministic ECDSA signing
|
|
330
|
+
- `lowS: true`
|
|
329
331
|
- `strictTxParse: true`
|
|
330
332
|
- `strictOutPointValidation: true`
|
|
331
333
|
- `strictFeeRateValidation: true`
|
|
332
334
|
- `strictScriptReader: true`
|
|
333
335
|
- `strictScriptEvaluation: true`
|
|
336
|
+
- strict script-eval max element size of `1024 * 1024`
|
|
337
|
+
- compressed secp256k1 multisig key validation with `n <= 5`
|
|
334
338
|
|
|
335
|
-
Other
|
|
339
|
+
Other checks remain opt-in because they are more compatibility-sensitive:
|
|
336
340
|
|
|
337
341
|
- `strictPresetUnlockingScript`
|
|
338
342
|
- `strictMultisigKeys`
|
|
339
343
|
|
|
340
|
-
Use `configureStrictMode(...)` to tighten behavior further:
|
|
341
|
-
|
|
342
344
|
```ts
|
|
343
|
-
import { bsv } from "dxs-stas-sdk";
|
|
345
|
+
import { bsv } from "dxs-stas-sdk/bsv";
|
|
344
346
|
|
|
345
347
|
bsv.configureStrictMode({
|
|
346
348
|
strictTxParse: true,
|
|
@@ -360,7 +362,15 @@ bsv.configureStrictMode({
|
|
|
360
362
|
});
|
|
361
363
|
```
|
|
362
364
|
|
|
365
|
+
## AI agent onboarding
|
|
366
|
+
|
|
367
|
+
If you are integrating this SDK through an AI coding agent, start with:
|
|
368
|
+
|
|
369
|
+
- `AGENTS.md`
|
|
370
|
+
- `docs/AGENT_RUNBOOK.md`
|
|
371
|
+
- `docs/DSTAS_SDK_SPEC.md`
|
|
372
|
+
|
|
363
373
|
## Author
|
|
364
374
|
|
|
365
|
-
- Author: [Oleg Panagushin](https://github.com/panagushin)
|
|
366
|
-
CTO / System Architect
|
|
375
|
+
- Author: [Oleg Panagushin](https://github.com/panagushin)
|
|
376
|
+
CTO / System Architect - Crypto & FinTech
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dxs-stas-sdk",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "TypeScript SDK for building and validating multiple Bitcoin SV transaction flows, including DSTAS token issue, transfer, split, merge, swap, freeze/unfreeze, and redeem.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|