bip388 1.0.0
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/LICENSE +21 -0
- package/README.md +220 -0
- package/dist/index.cjs +1391 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1020 -0
- package/dist/index.d.ts +1020 -0
- package/dist/index.js +1305 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Evan Feenstra
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# bip388
|
|
2
|
+
|
|
3
|
+
TypeScript library for building Bitcoin scripts and BIP-388 wallet policies, with first-class support for Ledger hardware wallets.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install bip388
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **BIP-388 Wallet Policies** - Descriptor templates with key placeholders for Ledger registration
|
|
14
|
+
- **BIP-379 Miniscript** - Typesafe miniscript fragment builders
|
|
15
|
+
- **HTLCs** - Hash Time-Locked Contracts for both Taproot and SegWit
|
|
16
|
+
- **Multisig** - k-of-n multisig for Taproot and SegWit
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
### Taproot HTLC
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { taprootHtlc } from "bip388";
|
|
24
|
+
|
|
25
|
+
const htlc = taprootHtlc({
|
|
26
|
+
payee: {
|
|
27
|
+
xpub: "tpub...",
|
|
28
|
+
fingerprint: "3442193e",
|
|
29
|
+
originPath: "86'/1'/0'",
|
|
30
|
+
},
|
|
31
|
+
payer: {
|
|
32
|
+
xpub: "tpub...",
|
|
33
|
+
fingerprint: "3442193e",
|
|
34
|
+
originPath: "86'/1'/1'",
|
|
35
|
+
},
|
|
36
|
+
secretHash: "deadbeef...",
|
|
37
|
+
timelock: 800000,
|
|
38
|
+
network: "testnet",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Address to fund
|
|
42
|
+
console.log(htlc.address);
|
|
43
|
+
|
|
44
|
+
// BIP-388 policy for Ledger
|
|
45
|
+
console.log(htlc.policy?.template);
|
|
46
|
+
// => tr(@0/**,{and_v(v:sha256(...),pk(@1/**)),and_v(v:after(800000),pk(@2/**))})
|
|
47
|
+
|
|
48
|
+
// Witness for spending with preimage
|
|
49
|
+
const witness = htlc.witness.secret(signature, preimage);
|
|
50
|
+
|
|
51
|
+
// Witness for timeout refund
|
|
52
|
+
const witness = htlc.witness.timeout(signature);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### SegWit HTLC
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { segwitHtlc } from "bip388";
|
|
59
|
+
|
|
60
|
+
const htlc = segwitHtlc({
|
|
61
|
+
payee: { xpub: "tpub...", fingerprint: "...", originPath: "..." },
|
|
62
|
+
payer: { xpub: "tpub...", fingerprint: "...", originPath: "..." },
|
|
63
|
+
secretHash: "deadbeef...",
|
|
64
|
+
timelock: 800000,
|
|
65
|
+
network: "testnet",
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
console.log(htlc.address); // tb1q...
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Taproot Multisig (2-of-3)
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { taprootMultisig } from "bip388";
|
|
75
|
+
|
|
76
|
+
const multisig = taprootMultisig({
|
|
77
|
+
threshold: 2,
|
|
78
|
+
keys: [
|
|
79
|
+
{ xpub: "tpub...", fingerprint: "...", originPath: "..." },
|
|
80
|
+
{ xpub: "tpub...", fingerprint: "...", originPath: "..." },
|
|
81
|
+
{ xpub: "tpub...", fingerprint: "...", originPath: "..." },
|
|
82
|
+
],
|
|
83
|
+
network: "testnet",
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
console.log(multisig.address);
|
|
87
|
+
console.log(multisig.policy?.template);
|
|
88
|
+
// => tr(@0/**,sortedmulti_a(2,@1/**,@2/**,@3/**))
|
|
89
|
+
|
|
90
|
+
// Build witness with signatures (empty buffer for non-signers)
|
|
91
|
+
const witness = multisig.witness([sig1, sig2, Buffer.alloc(0)]);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### SegWit Multisig
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { segwitMultisig } from "bip388";
|
|
98
|
+
|
|
99
|
+
const multisig = segwitMultisig({
|
|
100
|
+
threshold: 2,
|
|
101
|
+
keys: [key1, key2, key3],
|
|
102
|
+
network: "testnet",
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
console.log(multisig.policy?.template);
|
|
106
|
+
// => wsh(sortedmulti(2,@0/**,@1/**,@2/**))
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Key Types
|
|
110
|
+
|
|
111
|
+
Keys can be either `XpubKey` (for BIP-388 policy generation) or `RawKey` (just a pubkey):
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// XpubKey - enables BIP-388 policy generation
|
|
115
|
+
const xpubKey: XpubKey = {
|
|
116
|
+
xpub: "tpub...",
|
|
117
|
+
fingerprint: "3442193e", // master fingerprint
|
|
118
|
+
originPath: "86'/1'/0'", // derivation path
|
|
119
|
+
index: 0, // optional, default 0
|
|
120
|
+
change: 0, // optional, 0=receive, 1=change
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// RawKey - no policy generated
|
|
124
|
+
const rawKey: RawKey = {
|
|
125
|
+
pubkey: "02abc...", // 33-byte compressed or 32-byte x-only
|
|
126
|
+
};
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
When all keys are `XpubKey`, a `WalletPolicy` is generated for Ledger registration. When using `RawKey`, `policy` will be `null`.
|
|
130
|
+
|
|
131
|
+
## Miniscript Fragments
|
|
132
|
+
|
|
133
|
+
Build miniscript expressions directly:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { pk, sha256, and_v, or_i, older, after, multi_a } from "bip388";
|
|
137
|
+
|
|
138
|
+
// pk(@0/**)
|
|
139
|
+
pk(keyPlaceholder(0));
|
|
140
|
+
|
|
141
|
+
// and_v(v:sha256(H),pk(@0/**))
|
|
142
|
+
and_v(sha256("deadbeef..."), pk(keyPlaceholder(0)));
|
|
143
|
+
|
|
144
|
+
// or_i(and_v(v:sha256(H),pk(@0/**)),and_v(v:after(144),pk(@1/**)))
|
|
145
|
+
or_i(
|
|
146
|
+
and_v(sha256("..."), pk(keyPlaceholder(0))),
|
|
147
|
+
and_v(after(144), pk(keyPlaceholder(1))),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// multi_a(2,@0/**,@1/**,@2/**) - Taproot
|
|
151
|
+
multi_a(2, [keyPlaceholder(0), keyPlaceholder(1), keyPlaceholder(2)]);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Low-Level Scripts
|
|
155
|
+
|
|
156
|
+
For direct Bitcoin Script building:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import {
|
|
160
|
+
pkScript,
|
|
161
|
+
pkhScript,
|
|
162
|
+
multiScript,
|
|
163
|
+
cltvScript,
|
|
164
|
+
csvScript,
|
|
165
|
+
} from "bip388";
|
|
166
|
+
|
|
167
|
+
// <pubkey> OP_CHECKSIG
|
|
168
|
+
pkScript(pubkey);
|
|
169
|
+
|
|
170
|
+
// OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG
|
|
171
|
+
pkhScript(pubkey);
|
|
172
|
+
|
|
173
|
+
// OP_2 <key1> <key2> <key3> OP_3 OP_CHECKMULTISIG
|
|
174
|
+
multiScript(2, [key1, key2, key3]);
|
|
175
|
+
|
|
176
|
+
// <time> OP_CHECKLOCKTIMEVERIFY OP_DROP <pubkey> OP_CHECKSIG
|
|
177
|
+
cltvScript(pubkey, locktime);
|
|
178
|
+
|
|
179
|
+
// <blocks> OP_CHECKSEQUENCEVERIFY OP_DROP <pubkey> OP_CHECKSIG
|
|
180
|
+
csvScript(pubkey, blocks);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## API Reference
|
|
184
|
+
|
|
185
|
+
### Pattern Builders
|
|
186
|
+
|
|
187
|
+
| Function | Description |
|
|
188
|
+
| ------------------------- | ------------------------------------------ |
|
|
189
|
+
| `taprootHtlc(params)` | Taproot HTLC with secret and timeout paths |
|
|
190
|
+
| `segwitHtlc(params)` | SegWit P2WSH HTLC |
|
|
191
|
+
| `taprootMultisig(params)` | Taproot k-of-n multisig |
|
|
192
|
+
| `segwitMultisig(params)` | SegWit P2WSH k-of-n multisig |
|
|
193
|
+
|
|
194
|
+
### BIP-388 Builders
|
|
195
|
+
|
|
196
|
+
| Function | Description |
|
|
197
|
+
| ---------------------- | -------------------------------------- |
|
|
198
|
+
| `buildTaprootPolicy()` | Build a `tr()` wallet policy |
|
|
199
|
+
| `buildSegwitPolicy()` | Build a `wsh()` wallet policy |
|
|
200
|
+
| `keyPlaceholder(n)` | Create `@n/**` key placeholder |
|
|
201
|
+
| `formatKeyInfo()` | Format key as `[fingerprint/path]xpub` |
|
|
202
|
+
|
|
203
|
+
### Miniscript Fragments
|
|
204
|
+
|
|
205
|
+
| Function | Description |
|
|
206
|
+
| ------------------------ | ------------------------- |
|
|
207
|
+
| `pk(key)` | Public key check |
|
|
208
|
+
| `sha256(hash)` | SHA256 preimage check |
|
|
209
|
+
| `and_v(left, right)` | Verify AND |
|
|
210
|
+
| `or_i(left, right)` | IF/ELSE OR |
|
|
211
|
+
| `older(blocks)` | Relative timelock (CSV) |
|
|
212
|
+
| `after(time)` | Absolute timelock (CLTV) |
|
|
213
|
+
| `multi(k, keys)` | k-of-n multisig (SegWit) |
|
|
214
|
+
| `multi_a(k, keys)` | k-of-n multisig (Taproot) |
|
|
215
|
+
| `sortedmulti(k, keys)` | Sorted k-of-n (SegWit) |
|
|
216
|
+
| `sortedmulti_a(k, keys)` | Sorted k-of-n (Taproot) |
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
MIT
|