@arkade-os/sdk 0.1.4 → 0.2.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/README.md +156 -174
- package/dist/cjs/arknote/index.js +61 -58
- package/dist/cjs/bip322/errors.js +13 -0
- package/dist/cjs/bip322/index.js +178 -0
- package/dist/cjs/forfeit.js +14 -25
- package/dist/cjs/identity/singleKey.js +68 -0
- package/dist/cjs/index.js +41 -17
- package/dist/cjs/providers/ark.js +253 -317
- package/dist/cjs/providers/indexer.js +525 -0
- package/dist/cjs/providers/onchain.js +193 -15
- package/dist/cjs/script/address.js +48 -17
- package/dist/cjs/script/base.js +120 -3
- package/dist/cjs/script/default.js +18 -4
- package/dist/cjs/script/tapscript.js +46 -14
- package/dist/cjs/script/vhtlc.js +27 -7
- package/dist/cjs/tree/signingSession.js +63 -106
- package/dist/cjs/tree/txTree.js +193 -0
- package/dist/cjs/tree/validation.js +79 -155
- package/dist/cjs/utils/anchor.js +35 -0
- package/dist/cjs/utils/arkTransaction.js +108 -0
- package/dist/cjs/utils/transactionHistory.js +84 -72
- package/dist/cjs/utils/txSizeEstimator.js +12 -0
- package/dist/cjs/utils/unknownFields.js +211 -0
- package/dist/cjs/wallet/index.js +12 -0
- package/dist/cjs/wallet/onchain.js +201 -0
- package/dist/cjs/wallet/ramps.js +95 -0
- package/dist/cjs/wallet/serviceWorker/db/vtxo/idb.js +32 -0
- package/dist/cjs/wallet/serviceWorker/request.js +15 -12
- package/dist/cjs/wallet/serviceWorker/response.js +22 -27
- package/dist/cjs/wallet/serviceWorker/utils.js +8 -0
- package/dist/cjs/wallet/serviceWorker/wallet.js +58 -34
- package/dist/cjs/wallet/serviceWorker/worker.js +117 -108
- package/dist/cjs/wallet/unroll.js +270 -0
- package/dist/cjs/wallet/wallet.js +701 -454
- package/dist/esm/arknote/index.js +61 -57
- package/dist/esm/bip322/errors.js +9 -0
- package/dist/esm/bip322/index.js +174 -0
- package/dist/esm/forfeit.js +15 -26
- package/dist/esm/identity/singleKey.js +64 -0
- package/dist/esm/index.js +30 -12
- package/dist/esm/providers/ark.js +252 -317
- package/dist/esm/providers/indexer.js +521 -0
- package/dist/esm/providers/onchain.js +193 -15
- package/dist/esm/script/address.js +48 -17
- package/dist/esm/script/base.js +120 -3
- package/dist/esm/script/default.js +18 -4
- package/dist/esm/script/tapscript.js +46 -14
- package/dist/esm/script/vhtlc.js +27 -7
- package/dist/esm/tree/signingSession.js +65 -108
- package/dist/esm/tree/txTree.js +189 -0
- package/dist/esm/tree/validation.js +75 -152
- package/dist/esm/utils/anchor.js +31 -0
- package/dist/esm/utils/arkTransaction.js +105 -0
- package/dist/esm/utils/transactionHistory.js +84 -72
- package/dist/esm/utils/txSizeEstimator.js +12 -0
- package/dist/esm/utils/unknownFields.js +173 -0
- package/dist/esm/wallet/index.js +9 -0
- package/dist/esm/wallet/onchain.js +196 -0
- package/dist/esm/wallet/ramps.js +91 -0
- package/dist/esm/wallet/serviceWorker/db/vtxo/idb.js +32 -0
- package/dist/esm/wallet/serviceWorker/request.js +15 -12
- package/dist/esm/wallet/serviceWorker/response.js +22 -27
- package/dist/esm/wallet/serviceWorker/utils.js +8 -0
- package/dist/esm/wallet/serviceWorker/wallet.js +59 -35
- package/dist/esm/wallet/serviceWorker/worker.js +117 -108
- package/dist/esm/wallet/unroll.js +267 -0
- package/dist/esm/wallet/wallet.js +674 -461
- package/dist/types/arknote/index.d.ts +40 -13
- package/dist/types/bip322/errors.d.ts +6 -0
- package/dist/types/bip322/index.d.ts +57 -0
- package/dist/types/forfeit.d.ts +2 -14
- package/dist/types/identity/singleKey.d.ts +27 -0
- package/dist/types/index.d.ts +23 -12
- package/dist/types/providers/ark.d.ts +114 -95
- package/dist/types/providers/indexer.d.ts +186 -0
- package/dist/types/providers/onchain.d.ts +41 -11
- package/dist/types/script/address.d.ts +26 -2
- package/dist/types/script/base.d.ts +13 -3
- package/dist/types/script/default.d.ts +22 -0
- package/dist/types/script/tapscript.d.ts +61 -5
- package/dist/types/script/vhtlc.d.ts +27 -0
- package/dist/types/tree/signingSession.d.ts +5 -5
- package/dist/types/tree/txTree.d.ts +28 -0
- package/dist/types/tree/validation.d.ts +15 -22
- package/dist/types/utils/anchor.d.ts +19 -0
- package/dist/types/utils/arkTransaction.d.ts +27 -0
- package/dist/types/utils/transactionHistory.d.ts +7 -1
- package/dist/types/utils/txSizeEstimator.d.ts +3 -0
- package/dist/types/utils/unknownFields.d.ts +83 -0
- package/dist/types/wallet/index.d.ts +51 -50
- package/dist/types/wallet/onchain.d.ts +49 -0
- package/dist/types/wallet/ramps.d.ts +32 -0
- package/dist/types/wallet/serviceWorker/db/vtxo/idb.d.ts +2 -0
- package/dist/types/wallet/serviceWorker/db/vtxo/index.d.ts +2 -0
- package/dist/types/wallet/serviceWorker/request.d.ts +14 -16
- package/dist/types/wallet/serviceWorker/response.d.ts +17 -19
- package/dist/types/wallet/serviceWorker/utils.d.ts +8 -0
- package/dist/types/wallet/serviceWorker/wallet.d.ts +36 -8
- package/dist/types/wallet/serviceWorker/worker.d.ts +7 -3
- package/dist/types/wallet/unroll.d.ts +102 -0
- package/dist/types/wallet/wallet.d.ts +71 -25
- package/package.json +14 -15
- package/dist/cjs/identity/inMemoryKey.js +0 -40
- package/dist/cjs/tree/vtxoTree.js +0 -231
- package/dist/cjs/utils/coinselect.js +0 -73
- package/dist/cjs/utils/psbt.js +0 -137
- package/dist/esm/identity/inMemoryKey.js +0 -36
- package/dist/esm/tree/vtxoTree.js +0 -191
- package/dist/esm/utils/coinselect.js +0 -69
- package/dist/esm/utils/psbt.js +0 -131
- package/dist/types/identity/inMemoryKey.d.ts +0 -12
- package/dist/types/tree/vtxoTree.d.ts +0 -33
- package/dist/types/utils/coinselect.d.ts +0 -21
- package/dist/types/utils/psbt.d.ts +0 -11
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Arkade TypeScript SDK
|
|
2
2
|
The Arkade SDK is a TypeScript library for building Bitcoin wallets with support for both on-chain and off-chain transactions via the Ark protocol.
|
|
3
3
|
|
|
4
|
+
[](https://arkade-os.github.io/ts-sdk/)
|
|
5
|
+
|
|
4
6
|
## Installation
|
|
5
7
|
|
|
6
8
|
```bash
|
|
@@ -12,40 +14,84 @@ npm install @arkade-os/sdk
|
|
|
12
14
|
### Creating a Wallet
|
|
13
15
|
|
|
14
16
|
```typescript
|
|
15
|
-
import {
|
|
17
|
+
import { SingleKey, Wallet } from '@arkade-os/sdk'
|
|
16
18
|
|
|
17
19
|
// Create a new in-memory key (or use an external signer)
|
|
18
|
-
const identity =
|
|
20
|
+
const identity = SingleKey.fromHex('your_private_key_hex')
|
|
19
21
|
|
|
20
22
|
// Create a wallet with Ark support
|
|
21
23
|
const wallet = await Wallet.create({
|
|
22
|
-
network: 'mutinynet', // 'bitcoin', 'testnet', 'regtest', 'signet' or 'mutinynet'
|
|
23
24
|
identity: identity,
|
|
24
25
|
// Esplora API, can be left empty mempool.space API will be used
|
|
25
26
|
esploraUrl: 'https://mutinynet.com/api',
|
|
26
|
-
// OPTIONAL Ark Server connection information
|
|
27
27
|
arkServerUrl: 'https://mutinynet.arkade.sh',
|
|
28
|
-
arkServerPublicKey: 'fa73c6e4876ffb2dfc961d763cca9abc73d4b88efcb8f5e7ff92dc55e9aa553d'
|
|
29
28
|
})
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Receiving Bitcoin
|
|
30
32
|
|
|
33
|
+
```typescript
|
|
31
34
|
// Get wallet addresses
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
console.log('Ark Address:',
|
|
35
|
-
console.log('Boarding Address:',
|
|
36
|
-
|
|
35
|
+
const arkAddress = await wallet.getAddress()
|
|
36
|
+
const boardingAddress = await wallet.getBoardingAddress()
|
|
37
|
+
console.log('Ark Address:', arkAddress)
|
|
38
|
+
console.log('Boarding Address:', boardingAddress)
|
|
39
|
+
|
|
40
|
+
const incomingFunds = await waitForIncomingFunds(wallet)
|
|
41
|
+
if (incomingFunds.type === "vtxo") {
|
|
42
|
+
// virtual coins received
|
|
43
|
+
console.log("VTXOs: ", incomingFunds.vtxos)
|
|
44
|
+
} else if (incomingFunds.type === "utxo") {
|
|
45
|
+
// boarding coins received
|
|
46
|
+
console.log("UTXOs: ", incomingFunds.coins)
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Onboarding
|
|
51
|
+
|
|
52
|
+
Onboarding allows you to swap onchain funds into VTXOs
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { Ramps } from '@arkade-os/sdk'
|
|
56
|
+
|
|
57
|
+
const onboardTxid = await new Ramps(wallet).onboard();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Checking Balance
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// Get detailed balance information
|
|
64
|
+
const balance = await wallet.getBalance()
|
|
65
|
+
console.log('Total Balance:', balance.total)
|
|
66
|
+
console.log('Boarding Total:', balance.boarding.total)
|
|
67
|
+
console.log('Offchain Available:', balance.available)
|
|
68
|
+
console.log('Offchain Settled:', balance.settled)
|
|
69
|
+
console.log('Offchain Preconfirmed:', balance.preconfirmed)
|
|
70
|
+
console.log('Recoverable:', balance.recoverable)
|
|
71
|
+
|
|
72
|
+
// Get virtual UTXOs (off-chain)
|
|
73
|
+
const virtualCoins = await wallet.getVtxos()
|
|
74
|
+
|
|
75
|
+
// Get boarding UTXOs
|
|
76
|
+
const boardingUtxos = await wallet.getBoardingUtxos()
|
|
37
77
|
```
|
|
38
78
|
|
|
39
79
|
### Sending Bitcoin
|
|
40
80
|
|
|
41
81
|
```typescript
|
|
42
|
-
// Send bitcoin
|
|
82
|
+
// Send bitcoin via Ark
|
|
43
83
|
const txid = await wallet.sendBitcoin({
|
|
44
84
|
address: 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx',
|
|
45
85
|
amount: 50000, // in satoshis
|
|
46
86
|
feeRate: 1 // optional, in sats/vbyte
|
|
47
87
|
})
|
|
88
|
+
```
|
|
48
89
|
|
|
90
|
+
### Batch Settlements
|
|
91
|
+
|
|
92
|
+
This can be used to move preconfirmed balances into finalized balances, to convert manually UTXOs and VTXOs.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
49
95
|
// For settling transactions
|
|
50
96
|
const settleTxid = await wallet.settle({
|
|
51
97
|
inputs, // from getVtxos() or getBoardingUtxos()
|
|
@@ -56,20 +102,6 @@ const settleTxid = await wallet.settle({
|
|
|
56
102
|
})
|
|
57
103
|
```
|
|
58
104
|
|
|
59
|
-
### Checking Balance
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
// Get detailed balance information
|
|
63
|
-
const balance = await wallet.getBalance()
|
|
64
|
-
console.log('Total Onchain:', balance.onchain.total)
|
|
65
|
-
console.log('Total Offchain:', balance.offchain.total)
|
|
66
|
-
|
|
67
|
-
// Get virtual UTXOs (off-chain)
|
|
68
|
-
const virtualCoins = await wallet.getVtxos()
|
|
69
|
-
|
|
70
|
-
// Get boarding UTXOs
|
|
71
|
-
const boardingUtxos = await wallet.getBoardingUtxos()
|
|
72
|
-
```
|
|
73
105
|
|
|
74
106
|
### Transaction History
|
|
75
107
|
|
|
@@ -80,26 +112,94 @@ console.log('History:', history)
|
|
|
80
112
|
|
|
81
113
|
// Example history entry:
|
|
82
114
|
{
|
|
83
|
-
type: TxType.TxReceived, // or TxType.TxSent
|
|
84
|
-
amount: 50000,
|
|
85
|
-
settled: true,
|
|
86
115
|
key: {
|
|
87
116
|
boardingTxid: '...', // for boarding transactions
|
|
117
|
+
commitmentTxid: '...', // for commitment transactions
|
|
88
118
|
redeemTxid: '...' // for regular transactions
|
|
89
|
-
}
|
|
119
|
+
},
|
|
120
|
+
type: TxType.TxReceived, // or TxType.TxSent
|
|
121
|
+
amount: 50000,
|
|
122
|
+
settled: true,
|
|
123
|
+
createdAt: 1234567890
|
|
90
124
|
}
|
|
91
125
|
```
|
|
92
126
|
|
|
127
|
+
### Offboarding
|
|
128
|
+
|
|
129
|
+
Collaborative exit or "offboarding" allows you to withdraw your virtual funds to an onchain address.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { Ramps } from '@arkade-os/sdk'
|
|
133
|
+
|
|
134
|
+
const exitTxid = await new Ramps(wallet).offboard(onchainAddress);
|
|
135
|
+
```
|
|
136
|
+
|
|
93
137
|
### Unilateral Exit
|
|
94
138
|
|
|
139
|
+
Unilateral exit allows you to withdraw your funds from the Ark protocol back to the Bitcoin blockchain without requiring cooperation from the Ark server. This process involves two main steps:
|
|
140
|
+
|
|
141
|
+
1. **Unrolling**: Broadcasting the transaction chain from off-chain back to on-chain
|
|
142
|
+
2. **Completing the exit**: Spending the unrolled VTXOs after the timelock expires
|
|
143
|
+
|
|
144
|
+
#### Step 1: Unrolling VTXOs
|
|
145
|
+
|
|
95
146
|
```typescript
|
|
96
|
-
|
|
97
|
-
|
|
147
|
+
import { Unroll, OnchainWallet } from '@arkade-os/sdk'
|
|
148
|
+
|
|
149
|
+
// Create an onchain wallet to pay for P2A outputs in VTXO branches
|
|
150
|
+
// OnchainWallet implements the AnchorBumper interface
|
|
151
|
+
const onchainWallet = new OnchainWallet(wallet.identity, 'regtest');
|
|
152
|
+
|
|
153
|
+
// Unroll a specific VTXO
|
|
154
|
+
const vtxo = { txid: 'your_vtxo_txid', vout: 0 };
|
|
155
|
+
const session = await Unroll.Session.create(
|
|
156
|
+
vtxo,
|
|
157
|
+
onchainWallet,
|
|
158
|
+
onchainWallet.provider,
|
|
159
|
+
wallet.indexerProvider
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// Iterate through the unrolling steps
|
|
163
|
+
for await (const step of session) {
|
|
164
|
+
switch (step.type) {
|
|
165
|
+
case Unroll.StepType.WAIT:
|
|
166
|
+
console.log(`Waiting for transaction ${step.txid} to be confirmed`);
|
|
167
|
+
break;
|
|
168
|
+
case Unroll.StepType.UNROLL:
|
|
169
|
+
console.log(`Broadcasting transaction ${step.tx.id}`);
|
|
170
|
+
break;
|
|
171
|
+
case Unroll.StepType.DONE:
|
|
172
|
+
console.log(`Unrolling complete for VTXO ${step.vtxoTxid}`);
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The unrolling process works by:
|
|
179
|
+
- Traversing the transaction chain from the root (most recent) to the leaf (oldest)
|
|
180
|
+
- Broadcasting each transaction that isn't already on-chain
|
|
181
|
+
- Waiting for confirmations between steps
|
|
182
|
+
- Using P2A (Pay-to-Anchor) transactions to pay for fees
|
|
98
183
|
|
|
99
|
-
|
|
100
|
-
|
|
184
|
+
#### Step 2: Completing the Exit
|
|
185
|
+
|
|
186
|
+
Once VTXOs are fully unrolled and the unilateral exit timelock has expired, you can complete the exit:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Complete the exit for specific VTXOs
|
|
190
|
+
await Unroll.completeUnroll(
|
|
191
|
+
wallet,
|
|
192
|
+
[vtxo.txid], // Array of VTXO transaction IDs to complete
|
|
193
|
+
onchainWallet.address // Address to receive the exit amount
|
|
194
|
+
);
|
|
101
195
|
```
|
|
102
196
|
|
|
197
|
+
**Important Notes:**
|
|
198
|
+
- Each VTXO may require multiple unroll steps depending on the transaction chain length
|
|
199
|
+
- Each unroll step must be confirmed before proceeding to the next
|
|
200
|
+
- The `completeUnroll` method can only be called after VTXOs are fully unrolled and the timelock has expired
|
|
201
|
+
- You need sufficient on-chain funds in the `OnchainWallet` to pay for P2A transaction fees
|
|
202
|
+
|
|
103
203
|
### Running the wallet in a service worker
|
|
104
204
|
|
|
105
205
|
1. Create a service worker file
|
|
@@ -108,7 +208,7 @@ await wallet.exit([{ txid: vtxo.txid, vout: vtxo.vout }]);
|
|
|
108
208
|
// service-worker.ts
|
|
109
209
|
import { Worker } from '@arkade-os/sdk'
|
|
110
210
|
|
|
111
|
-
// Worker
|
|
211
|
+
// Worker handles communication between the main thread and service worker
|
|
112
212
|
new Worker().start()
|
|
113
213
|
```
|
|
114
214
|
|
|
@@ -120,15 +220,13 @@ new Worker().start()
|
|
|
120
220
|
const serviceWorker = await setupServiceWorker('/service-worker.js')
|
|
121
221
|
const wallet = new ServiceWorkerWallet(serviceWorker)
|
|
122
222
|
|
|
123
|
-
//
|
|
223
|
+
// Initialize the wallet
|
|
124
224
|
await wallet.init({
|
|
125
|
-
network: 'mutinynet', // 'bitcoin', 'testnet', 'regtest', 'signet' or 'mutinynet'
|
|
126
225
|
privateKey: 'your_private_key_hex',
|
|
127
226
|
// Esplora API, can be left empty mempool.space API will be used
|
|
128
227
|
esploraUrl: 'https://mutinynet.com/api',
|
|
129
228
|
// OPTIONAL Ark Server connection information
|
|
130
229
|
arkServerUrl: 'https://mutinynet.arkade.sh',
|
|
131
|
-
arkServerPublicKey: 'fa73c6e4876ffb2dfc961d763cca9abc73d4b88efcb8f5e7ff92dc55e9aa553d'
|
|
132
230
|
})
|
|
133
231
|
|
|
134
232
|
// check service worker status
|
|
@@ -139,140 +237,7 @@ console.log('Service worker status:', status.walletInitialized)
|
|
|
139
237
|
await wallet.clear()
|
|
140
238
|
```
|
|
141
239
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
### Wallet
|
|
145
|
-
|
|
146
|
-
#### Constructor Options
|
|
147
|
-
|
|
148
|
-
```typescript
|
|
149
|
-
interface WalletConfig {
|
|
150
|
-
/** Network to use ('bitcoin', 'testnet', 'regtest', 'signet', or 'mutinynet') */
|
|
151
|
-
network: NetworkName;
|
|
152
|
-
/** Identity for signing transactions */
|
|
153
|
-
identity: Identity;
|
|
154
|
-
/** Optional Esplora API URL */
|
|
155
|
-
esploraUrl?: string;
|
|
156
|
-
/** Ark server URL (optional) */
|
|
157
|
-
arkServerUrl?: string;
|
|
158
|
-
/** Ark server public key (optional) */
|
|
159
|
-
arkServerPublicKey?: string;
|
|
160
|
-
/** Optional boarding timelock configuration */
|
|
161
|
-
boardingTimelock?: RelativeTimelock;
|
|
162
|
-
/** Optional exit timelock configuration */
|
|
163
|
-
exitTimelock?: RelativeTimelock;
|
|
164
|
-
}
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
#### Methods
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
interface IWallet {
|
|
171
|
-
/** Get wallet addresses */
|
|
172
|
-
getAddress(): Promise<{
|
|
173
|
-
onchain?: Address;
|
|
174
|
-
offchain?: Address;
|
|
175
|
-
boarding?: Address;
|
|
176
|
-
bip21?: string;
|
|
177
|
-
}>;
|
|
178
|
-
|
|
179
|
-
/** Get wallet balance */
|
|
180
|
-
getBalance(): Promise<{
|
|
181
|
-
onchain: {
|
|
182
|
-
total: number;
|
|
183
|
-
confirmed: number;
|
|
184
|
-
unconfirmed: number;
|
|
185
|
-
};
|
|
186
|
-
offchain: {
|
|
187
|
-
total: number;
|
|
188
|
-
settled: number;
|
|
189
|
-
pending: number;
|
|
190
|
-
swept: number;
|
|
191
|
-
};
|
|
192
|
-
total: number;
|
|
193
|
-
}>;
|
|
194
|
-
|
|
195
|
-
/** Send bitcoin (on-chain or off-chain) */
|
|
196
|
-
sendBitcoin(params: {
|
|
197
|
-
address: string;
|
|
198
|
-
amount: number;
|
|
199
|
-
feeRate?: number;
|
|
200
|
-
memo?: string;
|
|
201
|
-
}, zeroFee?: boolean): Promise<string>;
|
|
202
|
-
|
|
203
|
-
/** Get virtual UTXOs */
|
|
204
|
-
getVtxos(): Promise<VirtualCoin[]>;
|
|
205
|
-
|
|
206
|
-
/** Get boarding UTXOs */
|
|
207
|
-
getBoardingUtxos(): Promise<BoardingUtxo[]>;
|
|
208
|
-
|
|
209
|
-
/** Settle transactions */
|
|
210
|
-
settle(params: {
|
|
211
|
-
inputs: (VirtualCoin | BoardingUtxo)[];
|
|
212
|
-
outputs: {
|
|
213
|
-
address: string;
|
|
214
|
-
amount: bigint;
|
|
215
|
-
}[];
|
|
216
|
-
}): Promise<string>;
|
|
217
|
-
|
|
218
|
-
/** Get transaction history */
|
|
219
|
-
getTransactionHistory(): Promise<Transaction[]>;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/** Transaction types */
|
|
223
|
-
enum TxType {
|
|
224
|
-
TxSent = 'sent',
|
|
225
|
-
TxReceived = 'received'
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/** Transaction history entry */
|
|
229
|
-
interface Transaction {
|
|
230
|
-
type: TxType;
|
|
231
|
-
amount: number;
|
|
232
|
-
settled: boolean;
|
|
233
|
-
key: {
|
|
234
|
-
boardingTxid?: string;
|
|
235
|
-
redeemTxid?: string;
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/** Virtual coin (off-chain UTXO) */
|
|
240
|
-
interface VirtualCoin {
|
|
241
|
-
txid: string;
|
|
242
|
-
value: number;
|
|
243
|
-
virtualStatus: {
|
|
244
|
-
state: 'pending' | 'settled';
|
|
245
|
-
};
|
|
246
|
-
spentBy?: string;
|
|
247
|
-
createdAt: Date;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/** Boarding UTXO */
|
|
251
|
-
interface BoardingUtxo {
|
|
252
|
-
txid: string;
|
|
253
|
-
vout: number;
|
|
254
|
-
value: number;
|
|
255
|
-
}
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
#### Identity
|
|
259
|
-
|
|
260
|
-
```typescript
|
|
261
|
-
export interface Identity {
|
|
262
|
-
sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
|
|
263
|
-
xOnlyPublicKey(): Uint8Array;
|
|
264
|
-
signerSession(): SignerSession;
|
|
265
|
-
}
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
The SDK provides a default implementation of the `Identity` interface: `InMemoryKey` for managing private keys in memory:
|
|
269
|
-
|
|
270
|
-
```typescript
|
|
271
|
-
class InMemoryKey {
|
|
272
|
-
static fromPrivateKey(privateKey: Uint8Array): InMemoryKey;
|
|
273
|
-
static fromHex(privateKeyHex: string): InMemoryKey;
|
|
274
|
-
}
|
|
275
|
-
```
|
|
240
|
+
_For complete API documentation, visit our [TypeScript documentation](https://arkade-os.github.io/ts-sdk/)._
|
|
276
241
|
|
|
277
242
|
## Development
|
|
278
243
|
|
|
@@ -291,7 +256,7 @@ pnpm format
|
|
|
291
256
|
pnpm lint
|
|
292
257
|
```
|
|
293
258
|
|
|
294
|
-
2.Install nigiri for integration tests:
|
|
259
|
+
2. Install nigiri for integration tests:
|
|
295
260
|
|
|
296
261
|
```bash
|
|
297
262
|
curl https://getnigiri.vulpem.com | bash
|
|
@@ -306,12 +271,20 @@ pnpm test
|
|
|
306
271
|
# Run unit tests only
|
|
307
272
|
pnpm test:unit
|
|
308
273
|
|
|
309
|
-
# Run integration tests
|
|
274
|
+
# Run integration tests with ark provided by nigiri
|
|
310
275
|
nigiri start --ark
|
|
311
|
-
pnpm test:setup
|
|
276
|
+
pnpm test:setup # Run setup script for integration tests
|
|
312
277
|
pnpm test:integration
|
|
313
278
|
nigiri stop --delete
|
|
314
279
|
|
|
280
|
+
# Run integration tests with ark provided by docker (requires nigiri)
|
|
281
|
+
nigiri start
|
|
282
|
+
pnpm test:up-docker
|
|
283
|
+
pnpm test:setup-docker # Run setup script for integration tests
|
|
284
|
+
pnpm test:integration-docker
|
|
285
|
+
pnpm test:down-docker
|
|
286
|
+
nigiri stop --delete
|
|
287
|
+
|
|
315
288
|
# Watch mode for development
|
|
316
289
|
pnpm test:watch
|
|
317
290
|
|
|
@@ -319,6 +292,15 @@ pnpm test:watch
|
|
|
319
292
|
pnpm test:coverage
|
|
320
293
|
```
|
|
321
294
|
|
|
295
|
+
### Building the documentation
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
# Build the TS doc
|
|
299
|
+
pnpm docs:build
|
|
300
|
+
# open the docs in the browser
|
|
301
|
+
pnpm docs:open
|
|
302
|
+
```
|
|
303
|
+
|
|
322
304
|
### Releasing
|
|
323
305
|
|
|
324
306
|
```bash
|
|
@@ -1,81 +1,81 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ArkNote =
|
|
3
|
+
exports.ArkNote = void 0;
|
|
4
4
|
const base_1 = require("@scure/base");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
exports.ArkNoteData = ArkNoteData;
|
|
27
|
-
// ArkNote is a note with the issuer's signature
|
|
5
|
+
const base_2 = require("../script/base");
|
|
6
|
+
const utils_1 = require("@scure/btc-signer/utils");
|
|
7
|
+
const btc_signer_1 = require("@scure/btc-signer");
|
|
8
|
+
/**
|
|
9
|
+
* ArkNotes are special virtual coins in the Ark protocol that can be created
|
|
10
|
+
* and spent without requiring any transactions. The server mints them, and they
|
|
11
|
+
* are encoded as base58 strings with a human-readable prefix. It contains a
|
|
12
|
+
* preimage and value.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* // Create an ArkNote
|
|
17
|
+
* const note = new ArkNote(preimage, 50000);
|
|
18
|
+
*
|
|
19
|
+
* // Encode to string
|
|
20
|
+
* const noteString = note.toString();
|
|
21
|
+
*
|
|
22
|
+
* // Decode from string
|
|
23
|
+
* const decodedNote = ArkNote.fromString(noteString);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
28
26
|
class ArkNote {
|
|
29
|
-
constructor(
|
|
30
|
-
this.
|
|
31
|
-
this.
|
|
27
|
+
constructor(preimage, value, HRP = ArkNote.DefaultHRP) {
|
|
28
|
+
this.preimage = preimage;
|
|
29
|
+
this.value = value;
|
|
30
|
+
this.HRP = HRP;
|
|
31
|
+
this.vout = 0;
|
|
32
|
+
const preimageHash = (0, utils_1.sha256)(this.preimage);
|
|
33
|
+
this.vtxoScript = new base_2.VtxoScript([noteTapscript(preimageHash)]);
|
|
34
|
+
const leaf = this.vtxoScript.leaves[0];
|
|
35
|
+
this.txid = base_1.hex.encode(new Uint8Array(preimageHash).reverse());
|
|
36
|
+
this.tapTree = this.vtxoScript.encode();
|
|
37
|
+
this.forfeitTapLeafScript = leaf;
|
|
38
|
+
this.intentTapLeafScript = leaf;
|
|
39
|
+
this.value = value;
|
|
40
|
+
this.status = { confirmed: true };
|
|
41
|
+
this.extraWitness = [this.preimage];
|
|
32
42
|
}
|
|
33
43
|
encode() {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
result.
|
|
37
|
-
result.set(this.signature, detailsBytes.length);
|
|
44
|
+
const result = new Uint8Array(ArkNote.Length);
|
|
45
|
+
result.set(this.preimage, 0);
|
|
46
|
+
writeUInt32BE(result, this.value, this.preimage.length);
|
|
38
47
|
return result;
|
|
39
48
|
}
|
|
40
|
-
static decode(data) {
|
|
41
|
-
if (data.length
|
|
42
|
-
throw new Error(`invalid data length: expected
|
|
49
|
+
static decode(data, hrp = ArkNote.DefaultHRP) {
|
|
50
|
+
if (data.length !== ArkNote.Length) {
|
|
51
|
+
throw new Error(`invalid data length: expected ${ArkNote.Length} bytes, got ${data.length}`);
|
|
43
52
|
}
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
throw new Error(`invalid signature length: expected 64 bytes, got ${signature.length}`);
|
|
48
|
-
}
|
|
49
|
-
return new ArkNote(noteData, signature);
|
|
53
|
+
const preimage = data.subarray(0, ArkNote.PreimageLength);
|
|
54
|
+
const value = readUInt32BE(data, ArkNote.PreimageLength);
|
|
55
|
+
return new ArkNote(preimage, value, hrp);
|
|
50
56
|
}
|
|
51
|
-
static fromString(noteStr) {
|
|
52
|
-
|
|
53
|
-
|
|
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}`);
|
|
57
|
+
static fromString(noteStr, hrp = ArkNote.DefaultHRP) {
|
|
58
|
+
noteStr = noteStr.trim();
|
|
59
|
+
if (!noteStr.startsWith(hrp)) {
|
|
60
|
+
throw new Error(`invalid human-readable part: expected ${hrp} prefix (note '${noteStr}')`);
|
|
58
61
|
}
|
|
62
|
+
const encoded = noteStr.slice(hrp.length);
|
|
59
63
|
const decoded = base_1.base58.decode(encoded);
|
|
60
64
|
if (decoded.length === 0) {
|
|
61
65
|
throw new Error("failed to decode base58 string");
|
|
62
66
|
}
|
|
63
|
-
return ArkNote.decode(
|
|
67
|
+
return ArkNote.decode(decoded, hrp);
|
|
64
68
|
}
|
|
65
69
|
toString() {
|
|
66
|
-
return
|
|
70
|
+
return this.HRP + base_1.base58.encode(this.encode());
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
exports.ArkNote = ArkNote;
|
|
70
|
-
ArkNote.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
function readBigUInt64BE(array, offset) {
|
|
76
|
-
const view = new DataView(array.buffer, array.byteOffset + offset, 8);
|
|
77
|
-
return view.getBigUint64(0, false);
|
|
78
|
-
}
|
|
74
|
+
ArkNote.DefaultHRP = "arknote";
|
|
75
|
+
ArkNote.PreimageLength = 32; // 32 bytes for the preimage
|
|
76
|
+
ArkNote.ValueLength = 4; // 4 bytes for the value
|
|
77
|
+
ArkNote.Length = ArkNote.PreimageLength + ArkNote.ValueLength;
|
|
78
|
+
ArkNote.FakeOutpointIndex = 0;
|
|
79
79
|
function writeUInt32BE(array, value, offset) {
|
|
80
80
|
const view = new DataView(array.buffer, array.byteOffset + offset, 4);
|
|
81
81
|
view.setUint32(0, value, false);
|
|
@@ -84,3 +84,6 @@ function readUInt32BE(array, offset) {
|
|
|
84
84
|
const view = new DataView(array.buffer, array.byteOffset + offset, 4);
|
|
85
85
|
return view.getUint32(0, false);
|
|
86
86
|
}
|
|
87
|
+
function noteTapscript(preimageHash) {
|
|
88
|
+
return btc_signer_1.Script.encode(["SHA256", preimageHash, "EQUAL"]);
|
|
89
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ErrMissingWitnessUtxo = exports.ErrMissingData = exports.ErrMissingInputs = exports.BIP322Error = void 0;
|
|
4
|
+
class BIP322Error extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "BIP322Error";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.BIP322Error = BIP322Error;
|
|
11
|
+
exports.ErrMissingInputs = new BIP322Error("missing inputs");
|
|
12
|
+
exports.ErrMissingData = new BIP322Error("missing data");
|
|
13
|
+
exports.ErrMissingWitnessUtxo = new BIP322Error("missing witness utxo");
|