@arkade-os/sdk 0.0.16
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 +312 -0
- package/dist/cjs/arknote/index.js +86 -0
- package/dist/cjs/forfeit.js +38 -0
- package/dist/cjs/identity/inMemoryKey.js +40 -0
- package/dist/cjs/identity/index.js +2 -0
- package/dist/cjs/index.js +48 -0
- package/dist/cjs/musig2/index.js +10 -0
- package/dist/cjs/musig2/keys.js +57 -0
- package/dist/cjs/musig2/nonces.js +44 -0
- package/dist/cjs/musig2/sign.js +102 -0
- package/dist/cjs/networks.js +26 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/providers/ark.js +530 -0
- package/dist/cjs/providers/onchain.js +61 -0
- package/dist/cjs/script/address.js +45 -0
- package/dist/cjs/script/base.js +51 -0
- package/dist/cjs/script/default.js +40 -0
- package/dist/cjs/script/tapscript.js +528 -0
- package/dist/cjs/script/vhtlc.js +84 -0
- package/dist/cjs/tree/signingSession.js +238 -0
- package/dist/cjs/tree/validation.js +184 -0
- package/dist/cjs/tree/vtxoTree.js +197 -0
- package/dist/cjs/utils/bip21.js +114 -0
- package/dist/cjs/utils/coinselect.js +73 -0
- package/dist/cjs/utils/psbt.js +124 -0
- package/dist/cjs/utils/transactionHistory.js +148 -0
- package/dist/cjs/utils/txSizeEstimator.js +95 -0
- package/dist/cjs/wallet/index.js +8 -0
- package/dist/cjs/wallet/serviceWorker/db/vtxo/idb.js +153 -0
- package/dist/cjs/wallet/serviceWorker/db/vtxo/index.js +2 -0
- package/dist/cjs/wallet/serviceWorker/request.js +75 -0
- package/dist/cjs/wallet/serviceWorker/response.js +187 -0
- package/dist/cjs/wallet/serviceWorker/wallet.js +332 -0
- package/dist/cjs/wallet/serviceWorker/worker.js +452 -0
- package/dist/cjs/wallet/wallet.js +720 -0
- package/dist/esm/arknote/index.js +81 -0
- package/dist/esm/forfeit.js +35 -0
- package/dist/esm/identity/inMemoryKey.js +36 -0
- package/dist/esm/identity/index.js +1 -0
- package/dist/esm/index.js +39 -0
- package/dist/esm/musig2/index.js +3 -0
- package/dist/esm/musig2/keys.js +21 -0
- package/dist/esm/musig2/nonces.js +8 -0
- package/dist/esm/musig2/sign.js +63 -0
- package/dist/esm/networks.js +22 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/providers/ark.js +526 -0
- package/dist/esm/providers/onchain.js +57 -0
- package/dist/esm/script/address.js +41 -0
- package/dist/esm/script/base.js +46 -0
- package/dist/esm/script/default.js +37 -0
- package/dist/esm/script/tapscript.js +491 -0
- package/dist/esm/script/vhtlc.js +81 -0
- package/dist/esm/tree/signingSession.js +200 -0
- package/dist/esm/tree/validation.js +179 -0
- package/dist/esm/tree/vtxoTree.js +157 -0
- package/dist/esm/utils/bip21.js +110 -0
- package/dist/esm/utils/coinselect.js +69 -0
- package/dist/esm/utils/psbt.js +118 -0
- package/dist/esm/utils/transactionHistory.js +145 -0
- package/dist/esm/utils/txSizeEstimator.js +91 -0
- package/dist/esm/wallet/index.js +5 -0
- package/dist/esm/wallet/serviceWorker/db/vtxo/idb.js +149 -0
- package/dist/esm/wallet/serviceWorker/db/vtxo/index.js +1 -0
- package/dist/esm/wallet/serviceWorker/request.js +72 -0
- package/dist/esm/wallet/serviceWorker/response.js +184 -0
- package/dist/esm/wallet/serviceWorker/wallet.js +328 -0
- package/dist/esm/wallet/serviceWorker/worker.js +448 -0
- package/dist/esm/wallet/wallet.js +716 -0
- package/dist/types/arknote/index.d.ts +17 -0
- package/dist/types/forfeit.d.ts +15 -0
- package/dist/types/identity/inMemoryKey.d.ts +12 -0
- package/dist/types/identity/index.d.ts +7 -0
- package/dist/types/index.d.ts +22 -0
- package/dist/types/musig2/index.d.ts +4 -0
- package/dist/types/musig2/keys.d.ts +9 -0
- package/dist/types/musig2/nonces.d.ts +13 -0
- package/dist/types/musig2/sign.d.ts +27 -0
- package/dist/types/networks.d.ts +16 -0
- package/dist/types/providers/ark.d.ts +126 -0
- package/dist/types/providers/onchain.d.ts +36 -0
- package/dist/types/script/address.d.ts +10 -0
- package/dist/types/script/base.d.ts +26 -0
- package/dist/types/script/default.d.ts +19 -0
- package/dist/types/script/tapscript.d.ts +94 -0
- package/dist/types/script/vhtlc.d.ts +31 -0
- package/dist/types/tree/signingSession.d.ts +32 -0
- package/dist/types/tree/validation.d.ts +22 -0
- package/dist/types/tree/vtxoTree.d.ts +32 -0
- package/dist/types/utils/bip21.d.ts +21 -0
- package/dist/types/utils/coinselect.d.ts +21 -0
- package/dist/types/utils/psbt.d.ts +11 -0
- package/dist/types/utils/transactionHistory.d.ts +2 -0
- package/dist/types/utils/txSizeEstimator.d.ts +27 -0
- package/dist/types/wallet/index.d.ts +122 -0
- package/dist/types/wallet/serviceWorker/db/vtxo/idb.d.ts +18 -0
- package/dist/types/wallet/serviceWorker/db/vtxo/index.d.ts +12 -0
- package/dist/types/wallet/serviceWorker/request.d.ts +68 -0
- package/dist/types/wallet/serviceWorker/response.d.ts +107 -0
- package/dist/types/wallet/serviceWorker/wallet.d.ts +23 -0
- package/dist/types/wallet/serviceWorker/worker.d.ts +26 -0
- package/dist/types/wallet/wallet.d.ts +42 -0
- package/package.json +88 -0
package/README.md
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# Ark Wallet SDK
|
|
2
|
+
The Ark Wallet SDK is a TypeScript library for building Bitcoin wallets with support for both on-chain and off-chain transactions via Ark protocol.
|
|
3
|
+
|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install @arkade-os/sdk
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
### Creating a Wallet
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { InMemoryKey, Wallet } from '@arkade-os/sdk'
|
|
18
|
+
|
|
19
|
+
// Create a new in-memory key (or use an external signer)
|
|
20
|
+
const identity = InMemoryKey.fromHex('your_private_key_hex')
|
|
21
|
+
|
|
22
|
+
// Create a wallet with Ark support
|
|
23
|
+
const wallet = await Wallet.create({
|
|
24
|
+
network: 'mutinynet', // 'bitcoin', 'testnet', 'regtest', 'signet' or 'mutinynet'
|
|
25
|
+
identity: identity,
|
|
26
|
+
// Esplora API, can be left empty mempool.space API will be used
|
|
27
|
+
esploraUrl: 'https://mutinynet.com/api',
|
|
28
|
+
// OPTIONAL Ark Server connection information
|
|
29
|
+
arkServerUrl: 'https://mutinynet.arkade.sh',
|
|
30
|
+
arkServerPublicKey: 'fa73c6e4876ffb2dfc961d763cca9abc73d4b88efcb8f5e7ff92dc55e9aa553d'
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// Get wallet addresses
|
|
34
|
+
const addresses = await wallet.getAddress()
|
|
35
|
+
console.log('Bitcoin Address:', addresses.onchain)
|
|
36
|
+
console.log('Ark Address:', addresses.offchain)
|
|
37
|
+
console.log('Boarding Address:', addresses.boarding)
|
|
38
|
+
console.log('BIP21 URI:', addresses.bip21)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Sending Bitcoin
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
// Send bitcoin (automatically chooses on-chain or off-chain based on the address)
|
|
45
|
+
const txid = await wallet.sendBitcoin({
|
|
46
|
+
address: 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx',
|
|
47
|
+
amount: 50000, // in satoshis
|
|
48
|
+
feeRate: 1 // optional, in sats/vbyte
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// For settling transactions
|
|
52
|
+
const settleTxid = await wallet.settle({
|
|
53
|
+
inputs, // from getVtxos() or getBoardingUtxos()
|
|
54
|
+
outputs: [{
|
|
55
|
+
address: destinationAddress,
|
|
56
|
+
amount: BigInt(amount)
|
|
57
|
+
}]
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Checking Balance
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// Get detailed balance information
|
|
65
|
+
const balance = await wallet.getBalance()
|
|
66
|
+
console.log('Total Onchain:', balance.onchain.total)
|
|
67
|
+
console.log('Total Offchain:', balance.offchain.total)
|
|
68
|
+
|
|
69
|
+
// Get virtual UTXOs (off-chain)
|
|
70
|
+
const virtualCoins = await wallet.getVtxos()
|
|
71
|
+
|
|
72
|
+
// Get boarding UTXOs
|
|
73
|
+
const boardingUtxos = await wallet.getBoardingUtxos()
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Transaction History
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// Get transaction history
|
|
80
|
+
const history = await wallet.getTransactionHistory()
|
|
81
|
+
console.log('History:', history)
|
|
82
|
+
|
|
83
|
+
// Example history entry:
|
|
84
|
+
{
|
|
85
|
+
type: TxType.TxReceived, // or TxType.TxSent
|
|
86
|
+
amount: 50000,
|
|
87
|
+
settled: true,
|
|
88
|
+
key: {
|
|
89
|
+
boardingTxid: '...', // for boarding transactions
|
|
90
|
+
redeemTxid: '...' // for regular transactions
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Running the wallet in a service worker
|
|
96
|
+
|
|
97
|
+
1. Create a service worker file
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// service-worker.ts
|
|
101
|
+
import { Worker } from '@arkade-os/sdk'
|
|
102
|
+
|
|
103
|
+
// Worker is a class handling the communication between the main thread and the service worker
|
|
104
|
+
new Worker().start()
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
2. Instantiate the ServiceWorkerWallet
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// specify the path to the service worker file
|
|
111
|
+
// this will automatically register the service worker
|
|
112
|
+
const wallet = await ServiceWorkerWallet.create('/service-worker.js')
|
|
113
|
+
|
|
114
|
+
// initialize the wallet
|
|
115
|
+
await wallet.init({
|
|
116
|
+
network: 'mutinynet', // 'bitcoin', 'testnet', 'regtest', 'signet' or 'mutinynet'
|
|
117
|
+
identity: identity,
|
|
118
|
+
// Esplora API, can be left empty mempool.space API will be used
|
|
119
|
+
esploraUrl: 'https://mutinynet.com/api',
|
|
120
|
+
// OPTIONAL Ark Server connection information
|
|
121
|
+
arkServerUrl: 'https://mutinynet.arkade.sh',
|
|
122
|
+
arkServerPublicKey: 'fa73c6e4876ffb2dfc961d763cca9abc73d4b88efcb8f5e7ff92dc55e9aa553d'
|
|
123
|
+
})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## API Reference
|
|
127
|
+
|
|
128
|
+
### Wallet
|
|
129
|
+
|
|
130
|
+
#### Constructor Options
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
interface WalletConfig {
|
|
134
|
+
/** Network to use ('bitcoin', 'testnet', 'regtest', 'signet', or 'mutinynet') */
|
|
135
|
+
network: NetworkName;
|
|
136
|
+
/** Identity for signing transactions */
|
|
137
|
+
identity: Identity;
|
|
138
|
+
/** Optional Esplora API URL */
|
|
139
|
+
esploraUrl?: string;
|
|
140
|
+
/** Ark server URL (optional) */
|
|
141
|
+
arkServerUrl?: string;
|
|
142
|
+
/** Ark server public key (optional) */
|
|
143
|
+
arkServerPublicKey?: string;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### Methods
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
interface IWallet {
|
|
151
|
+
/** Get wallet addresses */
|
|
152
|
+
getAddress(): Promise<{
|
|
153
|
+
onchain?: Address;
|
|
154
|
+
offchain?: Address;
|
|
155
|
+
boarding?: Address;
|
|
156
|
+
bip21?: string;
|
|
157
|
+
}>;
|
|
158
|
+
|
|
159
|
+
/** Get wallet balance */
|
|
160
|
+
getBalance(): Promise<{
|
|
161
|
+
onchain: {
|
|
162
|
+
total: number;
|
|
163
|
+
confirmed: number;
|
|
164
|
+
unconfirmed: number;
|
|
165
|
+
};
|
|
166
|
+
offchain: {
|
|
167
|
+
total: number;
|
|
168
|
+
settled: number;
|
|
169
|
+
pending: number;
|
|
170
|
+
};
|
|
171
|
+
}>;
|
|
172
|
+
|
|
173
|
+
/** Send bitcoin (on-chain or off-chain) */
|
|
174
|
+
sendBitcoin(params: {
|
|
175
|
+
address: string;
|
|
176
|
+
amount: number;
|
|
177
|
+
feeRate?: number;
|
|
178
|
+
}, onchain?: boolean): Promise<string>;
|
|
179
|
+
|
|
180
|
+
/** Get virtual UTXOs */
|
|
181
|
+
getVtxos(): Promise<VirtualCoin[]>;
|
|
182
|
+
|
|
183
|
+
/** Get boarding UTXOs */
|
|
184
|
+
getBoardingUtxos(): Promise<BoardingUtxo[]>;
|
|
185
|
+
|
|
186
|
+
/** Settle transactions */
|
|
187
|
+
settle(params: {
|
|
188
|
+
inputs: (VirtualCoin | BoardingUtxo)[];
|
|
189
|
+
outputs: {
|
|
190
|
+
address: string;
|
|
191
|
+
amount: bigint;
|
|
192
|
+
}[];
|
|
193
|
+
}): Promise<string>;
|
|
194
|
+
|
|
195
|
+
/** Get transaction history */
|
|
196
|
+
getTransactionHistory(): Promise<Transaction[]>;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Transaction types */
|
|
200
|
+
enum TxType {
|
|
201
|
+
TxSent = 'sent',
|
|
202
|
+
TxReceived = 'received'
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Transaction history entry */
|
|
206
|
+
interface Transaction {
|
|
207
|
+
type: TxType;
|
|
208
|
+
amount: number;
|
|
209
|
+
settled: boolean;
|
|
210
|
+
key: {
|
|
211
|
+
boardingTxid?: string;
|
|
212
|
+
redeemTxid?: string;
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Virtual coin (off-chain UTXO) */
|
|
217
|
+
interface VirtualCoin {
|
|
218
|
+
txid: string;
|
|
219
|
+
value: number;
|
|
220
|
+
virtualStatus: {
|
|
221
|
+
state: 'pending' | 'settled';
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Boarding UTXO */
|
|
226
|
+
interface BoardingUtxo {
|
|
227
|
+
txid: string;
|
|
228
|
+
vout: number;
|
|
229
|
+
value: number;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### Identity
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
export interface Identity {
|
|
237
|
+
sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
|
|
238
|
+
xOnlyPublicKey(): Uint8Array;
|
|
239
|
+
signerSession(): SignerSession;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
The SDK provides a default implementation of the `Identity` interface: `InMemoryKey` for managing private keys in memory:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
class InMemoryKey {
|
|
247
|
+
static fromPrivateKey(privateKey: Uint8Array): InMemoryKey;
|
|
248
|
+
static fromHex(privateKeyHex: string): InMemoryKey;
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Development
|
|
253
|
+
|
|
254
|
+
### Requirements
|
|
255
|
+
|
|
256
|
+
- [pnpm](https://pnpm.io/) - Package manager
|
|
257
|
+
- [nigiri](https://github.com/vulpemventures/nigiri) - For running integration tests with a local Bitcoin regtest network
|
|
258
|
+
|
|
259
|
+
### Setup
|
|
260
|
+
|
|
261
|
+
1. Install dependencies:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
pnpm install
|
|
265
|
+
pnpm format
|
|
266
|
+
pnpm lint
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
2.Install nigiri for integration tests:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
curl https://getnigiri.vulpem.com | bash
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Running Tests
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
# Run all tests
|
|
279
|
+
pnpm test
|
|
280
|
+
|
|
281
|
+
# Run unit tests only
|
|
282
|
+
pnpm test:unit
|
|
283
|
+
|
|
284
|
+
# Run integration tests (requires nigiri)
|
|
285
|
+
nigiri start --ark
|
|
286
|
+
pnpm test:setup # Run setup script for integration tests
|
|
287
|
+
pnpm test:integration
|
|
288
|
+
nigiri stop --delete
|
|
289
|
+
|
|
290
|
+
# Watch mode for development
|
|
291
|
+
pnpm test:watch
|
|
292
|
+
|
|
293
|
+
# Run tests with coverage
|
|
294
|
+
pnpm test:coverage
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Releasing
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
# Release new version (will prompt for version patch, minor, major)
|
|
301
|
+
pnpm release
|
|
302
|
+
|
|
303
|
+
# You can test release process without making changes
|
|
304
|
+
pnpm release:dry-run
|
|
305
|
+
|
|
306
|
+
# Cleanup: checkout version commit and remove release branch
|
|
307
|
+
pnpm release:cleanup
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## License
|
|
311
|
+
|
|
312
|
+
MIT
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ArkNote = exports.ArkNoteData = void 0;
|
|
4
|
+
const base_1 = require("@scure/base");
|
|
5
|
+
// ArkNoteData is the unsigned data part of a note
|
|
6
|
+
class ArkNoteData {
|
|
7
|
+
constructor(id, value) {
|
|
8
|
+
this.id = id;
|
|
9
|
+
this.value = value;
|
|
10
|
+
}
|
|
11
|
+
encode() {
|
|
12
|
+
const array = new Uint8Array(12);
|
|
13
|
+
writeBigUInt64BE(array, this.id, 0);
|
|
14
|
+
writeUInt32BE(array, this.value, 8);
|
|
15
|
+
return array;
|
|
16
|
+
}
|
|
17
|
+
static decode(data) {
|
|
18
|
+
if (data.length !== 12) {
|
|
19
|
+
throw new Error(`invalid data length: expected 12 bytes, got ${data.length}`);
|
|
20
|
+
}
|
|
21
|
+
const id = readBigUInt64BE(data, 0);
|
|
22
|
+
const value = readUInt32BE(data, 8);
|
|
23
|
+
return new ArkNoteData(id, value);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.ArkNoteData = ArkNoteData;
|
|
27
|
+
// ArkNote is a note with the issuer's signature
|
|
28
|
+
class ArkNote {
|
|
29
|
+
constructor(data, signature) {
|
|
30
|
+
this.data = data;
|
|
31
|
+
this.signature = signature;
|
|
32
|
+
}
|
|
33
|
+
encode() {
|
|
34
|
+
const detailsBytes = this.data.encode();
|
|
35
|
+
const result = new Uint8Array(detailsBytes.length + this.signature.length);
|
|
36
|
+
result.set(detailsBytes);
|
|
37
|
+
result.set(this.signature, detailsBytes.length);
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
static decode(data) {
|
|
41
|
+
if (data.length < 12) {
|
|
42
|
+
throw new Error(`invalid data length: expected at least 12 bytes, got ${data.length}`);
|
|
43
|
+
}
|
|
44
|
+
const noteData = ArkNoteData.decode(data.subarray(0, 12));
|
|
45
|
+
const signature = data.subarray(12);
|
|
46
|
+
if (signature.length !== 64) {
|
|
47
|
+
throw new Error(`invalid signature length: expected 64 bytes, got ${signature.length}`);
|
|
48
|
+
}
|
|
49
|
+
return new ArkNote(noteData, signature);
|
|
50
|
+
}
|
|
51
|
+
static fromString(noteStr) {
|
|
52
|
+
if (!noteStr.startsWith(ArkNote.HRP)) {
|
|
53
|
+
throw new Error(`invalid human-readable part: expected ${ArkNote.HRP} prefix (note '${noteStr}')`);
|
|
54
|
+
}
|
|
55
|
+
const encoded = noteStr.slice(ArkNote.HRP.length);
|
|
56
|
+
if (encoded.length < 103 || encoded.length > 104) {
|
|
57
|
+
throw new Error(`invalid note length: expected 103 or 104 chars, got ${encoded.length}`);
|
|
58
|
+
}
|
|
59
|
+
const decoded = base_1.base58.decode(encoded);
|
|
60
|
+
if (decoded.length === 0) {
|
|
61
|
+
throw new Error("failed to decode base58 string");
|
|
62
|
+
}
|
|
63
|
+
return ArkNote.decode(new Uint8Array(decoded));
|
|
64
|
+
}
|
|
65
|
+
toString() {
|
|
66
|
+
return ArkNote.HRP + base_1.base58.encode(this.encode());
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.ArkNote = ArkNote;
|
|
70
|
+
ArkNote.HRP = "arknote";
|
|
71
|
+
function writeBigUInt64BE(array, value, offset) {
|
|
72
|
+
const view = new DataView(array.buffer, array.byteOffset + offset, 8);
|
|
73
|
+
view.setBigUint64(0, value, false);
|
|
74
|
+
}
|
|
75
|
+
function readBigUInt64BE(array, offset) {
|
|
76
|
+
const view = new DataView(array.buffer, array.byteOffset + offset, 8);
|
|
77
|
+
return view.getBigUint64(0, false);
|
|
78
|
+
}
|
|
79
|
+
function writeUInt32BE(array, value, offset) {
|
|
80
|
+
const view = new DataView(array.buffer, array.byteOffset + offset, 4);
|
|
81
|
+
view.setUint32(0, value, false);
|
|
82
|
+
}
|
|
83
|
+
function readUInt32BE(array, offset) {
|
|
84
|
+
const view = new DataView(array.buffer, array.byteOffset + offset, 4);
|
|
85
|
+
return view.getUint32(0, false);
|
|
86
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildForfeitTx = buildForfeitTx;
|
|
4
|
+
const btc_signer_1 = require("@scure/btc-signer");
|
|
5
|
+
function buildForfeitTx({ connectorInput, vtxoInput, vtxoAmount, connectorAmount, feeAmount, vtxoPkScript, connectorPkScript, serverPkScript, txLocktime, }) {
|
|
6
|
+
const tx = new btc_signer_1.Transaction({
|
|
7
|
+
version: 2,
|
|
8
|
+
lockTime: txLocktime,
|
|
9
|
+
});
|
|
10
|
+
// Add connector input
|
|
11
|
+
tx.addInput({
|
|
12
|
+
txid: connectorInput.txid,
|
|
13
|
+
index: connectorInput.vout,
|
|
14
|
+
witnessUtxo: {
|
|
15
|
+
script: connectorPkScript,
|
|
16
|
+
amount: connectorAmount,
|
|
17
|
+
},
|
|
18
|
+
sequence: 0xffffffff,
|
|
19
|
+
});
|
|
20
|
+
// Add VTXO input
|
|
21
|
+
tx.addInput({
|
|
22
|
+
txid: vtxoInput.txid,
|
|
23
|
+
index: vtxoInput.vout,
|
|
24
|
+
witnessUtxo: {
|
|
25
|
+
script: vtxoPkScript,
|
|
26
|
+
amount: vtxoAmount,
|
|
27
|
+
},
|
|
28
|
+
sequence: txLocktime ? 0xfffffffe : 0xffffffff, // MAX_SEQUENCE - 1 if locktime is set
|
|
29
|
+
sighashType: btc_signer_1.SigHash.DEFAULT,
|
|
30
|
+
});
|
|
31
|
+
const amount = BigInt(vtxoAmount) + BigInt(connectorAmount) - BigInt(feeAmount);
|
|
32
|
+
// Add main output to server
|
|
33
|
+
tx.addOutput({
|
|
34
|
+
script: serverPkScript,
|
|
35
|
+
amount,
|
|
36
|
+
});
|
|
37
|
+
return tx;
|
|
38
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InMemoryKey = void 0;
|
|
4
|
+
const utils_1 = require("@scure/btc-signer/utils");
|
|
5
|
+
const base_1 = require("@scure/base");
|
|
6
|
+
const signingSession_1 = require("../tree/signingSession");
|
|
7
|
+
const ZERO_32 = new Uint8Array(32).fill(0);
|
|
8
|
+
class InMemoryKey {
|
|
9
|
+
constructor(key) {
|
|
10
|
+
this.key = key || (0, utils_1.randomPrivateKeyBytes)();
|
|
11
|
+
}
|
|
12
|
+
static fromPrivateKey(privateKey) {
|
|
13
|
+
return new InMemoryKey(privateKey);
|
|
14
|
+
}
|
|
15
|
+
static fromHex(privateKeyHex) {
|
|
16
|
+
return new InMemoryKey(base_1.hex.decode(privateKeyHex));
|
|
17
|
+
}
|
|
18
|
+
async sign(tx, inputIndexes) {
|
|
19
|
+
const txCpy = tx.clone();
|
|
20
|
+
if (!inputIndexes) {
|
|
21
|
+
if (!txCpy.sign(this.key, undefined, ZERO_32)) {
|
|
22
|
+
throw new Error("Failed to sign transaction");
|
|
23
|
+
}
|
|
24
|
+
return txCpy;
|
|
25
|
+
}
|
|
26
|
+
for (const inputIndex of inputIndexes) {
|
|
27
|
+
if (!txCpy.signIdx(this.key, inputIndex, undefined, ZERO_32)) {
|
|
28
|
+
throw new Error(`Failed to sign input #${inputIndex}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return txCpy;
|
|
32
|
+
}
|
|
33
|
+
xOnlyPublicKey() {
|
|
34
|
+
return (0, utils_1.pubSchnorr)(this.key);
|
|
35
|
+
}
|
|
36
|
+
signerSession() {
|
|
37
|
+
return signingSession_1.TreeSignerSession.random();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.InMemoryKey = InMemoryKey;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IndexedDBVtxoRepository = exports.networks = exports.ArkNoteData = exports.ArkNote = exports.createVirtualTx = exports.CONDITION_WITNESS_KEY_PREFIX = exports.addConditionWitness = exports.CLTVMultisigTapscript = exports.ConditionMultisigTapscript = exports.ConditionCSVMultisigTapscript = exports.CSVMultisigTapscript = exports.MultisigTapscript = exports.decodeTapscript = exports.Response = exports.Request = exports.Worker = exports.TxType = exports.VHTLC = exports.VtxoScript = exports.DefaultVtxo = exports.ArkAddress = exports.RestArkProvider = exports.EsploraProvider = exports.ESPLORA_URL = exports.InMemoryKey = exports.ServiceWorkerWallet = exports.Wallet = void 0;
|
|
4
|
+
const inMemoryKey_1 = require("./identity/inMemoryKey");
|
|
5
|
+
Object.defineProperty(exports, "InMemoryKey", { enumerable: true, get: function () { return inMemoryKey_1.InMemoryKey; } });
|
|
6
|
+
const address_1 = require("./script/address");
|
|
7
|
+
Object.defineProperty(exports, "ArkAddress", { enumerable: true, get: function () { return address_1.ArkAddress; } });
|
|
8
|
+
const vhtlc_1 = require("./script/vhtlc");
|
|
9
|
+
Object.defineProperty(exports, "VHTLC", { enumerable: true, get: function () { return vhtlc_1.VHTLC; } });
|
|
10
|
+
const default_1 = require("./script/default");
|
|
11
|
+
Object.defineProperty(exports, "DefaultVtxo", { enumerable: true, get: function () { return default_1.DefaultVtxo; } });
|
|
12
|
+
const base_1 = require("./script/base");
|
|
13
|
+
Object.defineProperty(exports, "VtxoScript", { enumerable: true, get: function () { return base_1.VtxoScript; } });
|
|
14
|
+
const index_1 = require("./wallet/index");
|
|
15
|
+
Object.defineProperty(exports, "TxType", { enumerable: true, get: function () { return index_1.TxType; } });
|
|
16
|
+
const wallet_1 = require("./wallet/wallet");
|
|
17
|
+
Object.defineProperty(exports, "Wallet", { enumerable: true, get: function () { return wallet_1.Wallet; } });
|
|
18
|
+
const wallet_2 = require("./wallet/serviceWorker/wallet");
|
|
19
|
+
Object.defineProperty(exports, "ServiceWorkerWallet", { enumerable: true, get: function () { return wallet_2.ServiceWorkerWallet; } });
|
|
20
|
+
const worker_1 = require("./wallet/serviceWorker/worker");
|
|
21
|
+
Object.defineProperty(exports, "Worker", { enumerable: true, get: function () { return worker_1.Worker; } });
|
|
22
|
+
const request_1 = require("./wallet/serviceWorker/request");
|
|
23
|
+
Object.defineProperty(exports, "Request", { enumerable: true, get: function () { return request_1.Request; } });
|
|
24
|
+
const response_1 = require("./wallet/serviceWorker/response");
|
|
25
|
+
Object.defineProperty(exports, "Response", { enumerable: true, get: function () { return response_1.Response; } });
|
|
26
|
+
const onchain_1 = require("./providers/onchain");
|
|
27
|
+
Object.defineProperty(exports, "ESPLORA_URL", { enumerable: true, get: function () { return onchain_1.ESPLORA_URL; } });
|
|
28
|
+
Object.defineProperty(exports, "EsploraProvider", { enumerable: true, get: function () { return onchain_1.EsploraProvider; } });
|
|
29
|
+
const ark_1 = require("./providers/ark");
|
|
30
|
+
Object.defineProperty(exports, "RestArkProvider", { enumerable: true, get: function () { return ark_1.RestArkProvider; } });
|
|
31
|
+
const tapscript_1 = require("./script/tapscript");
|
|
32
|
+
Object.defineProperty(exports, "CLTVMultisigTapscript", { enumerable: true, get: function () { return tapscript_1.CLTVMultisigTapscript; } });
|
|
33
|
+
Object.defineProperty(exports, "ConditionCSVMultisigTapscript", { enumerable: true, get: function () { return tapscript_1.ConditionCSVMultisigTapscript; } });
|
|
34
|
+
Object.defineProperty(exports, "ConditionMultisigTapscript", { enumerable: true, get: function () { return tapscript_1.ConditionMultisigTapscript; } });
|
|
35
|
+
Object.defineProperty(exports, "CSVMultisigTapscript", { enumerable: true, get: function () { return tapscript_1.CSVMultisigTapscript; } });
|
|
36
|
+
Object.defineProperty(exports, "decodeTapscript", { enumerable: true, get: function () { return tapscript_1.decodeTapscript; } });
|
|
37
|
+
Object.defineProperty(exports, "MultisigTapscript", { enumerable: true, get: function () { return tapscript_1.MultisigTapscript; } });
|
|
38
|
+
const psbt_1 = require("./utils/psbt");
|
|
39
|
+
Object.defineProperty(exports, "addConditionWitness", { enumerable: true, get: function () { return psbt_1.addConditionWitness; } });
|
|
40
|
+
Object.defineProperty(exports, "CONDITION_WITNESS_KEY_PREFIX", { enumerable: true, get: function () { return psbt_1.CONDITION_WITNESS_KEY_PREFIX; } });
|
|
41
|
+
Object.defineProperty(exports, "createVirtualTx", { enumerable: true, get: function () { return psbt_1.createVirtualTx; } });
|
|
42
|
+
const arknote_1 = require("./arknote");
|
|
43
|
+
Object.defineProperty(exports, "ArkNote", { enumerable: true, get: function () { return arknote_1.ArkNote; } });
|
|
44
|
+
Object.defineProperty(exports, "ArkNoteData", { enumerable: true, get: function () { return arknote_1.ArkNoteData; } });
|
|
45
|
+
const idb_1 = require("./wallet/serviceWorker/db/vtxo/idb");
|
|
46
|
+
Object.defineProperty(exports, "IndexedDBVtxoRepository", { enumerable: true, get: function () { return idb_1.IndexedDBVtxoRepository; } });
|
|
47
|
+
const networks_1 = require("./networks");
|
|
48
|
+
Object.defineProperty(exports, "networks", { enumerable: true, get: function () { return networks_1.networks; } });
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.aggregateKeys = exports.sign = exports.PartialSig = exports.generateNonces = void 0;
|
|
4
|
+
var nonces_1 = require("./nonces");
|
|
5
|
+
Object.defineProperty(exports, "generateNonces", { enumerable: true, get: function () { return nonces_1.generateNonces; } });
|
|
6
|
+
var sign_1 = require("./sign");
|
|
7
|
+
Object.defineProperty(exports, "PartialSig", { enumerable: true, get: function () { return sign_1.PartialSig; } });
|
|
8
|
+
Object.defineProperty(exports, "sign", { enumerable: true, get: function () { return sign_1.sign; } });
|
|
9
|
+
var keys_1 = require("./keys");
|
|
10
|
+
Object.defineProperty(exports, "aggregateKeys", { enumerable: true, get: function () { return keys_1.aggregateKeys; } });
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.aggregateKeys = aggregateKeys;
|
|
37
|
+
const musig = __importStar(require("@scure/btc-signer/musig2"));
|
|
38
|
+
const secp256k1_1 = require("@noble/curves/secp256k1");
|
|
39
|
+
// Aggregates multiple public keys according to the MuSig2 algorithm
|
|
40
|
+
function aggregateKeys(publicKeys, sort, options = {}) {
|
|
41
|
+
if (sort) {
|
|
42
|
+
publicKeys = musig.sortKeys(publicKeys);
|
|
43
|
+
}
|
|
44
|
+
const { aggPublicKey: preTweakedKey } = musig.keyAggregate(publicKeys);
|
|
45
|
+
if (!options.taprootTweak) {
|
|
46
|
+
return {
|
|
47
|
+
preTweakedKey: preTweakedKey.toRawBytes(true),
|
|
48
|
+
finalKey: preTweakedKey.toRawBytes(true),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const tweakBytes = secp256k1_1.schnorr.utils.taggedHash("TapTweak", preTweakedKey.toRawBytes(true).subarray(1), options.taprootTweak ?? new Uint8Array(0));
|
|
52
|
+
const { aggPublicKey: finalKey } = musig.keyAggregate(publicKeys, [tweakBytes], [true]);
|
|
53
|
+
return {
|
|
54
|
+
preTweakedKey: preTweakedKey.toRawBytes(true),
|
|
55
|
+
finalKey: finalKey.toRawBytes(true),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.generateNonces = generateNonces;
|
|
37
|
+
const musig = __importStar(require("@scure/btc-signer/musig2"));
|
|
38
|
+
/**
|
|
39
|
+
* Generates a pair of public and secret nonces for MuSig2 signing
|
|
40
|
+
*/
|
|
41
|
+
function generateNonces(publicKey) {
|
|
42
|
+
const nonces = musig.nonceGen(publicKey);
|
|
43
|
+
return { secNonce: nonces.secret, pubNonce: nonces.public };
|
|
44
|
+
}
|