@arkade-os/sdk 0.1.4 → 0.2.1
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 +157 -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 +43 -17
- package/dist/cjs/providers/ark.js +261 -321
- 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 +61 -20
- package/dist/cjs/script/vhtlc.js +85 -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 +61 -34
- package/dist/cjs/wallet/serviceWorker/worker.js +120 -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 +31 -12
- package/dist/esm/providers/ark.js +259 -320
- 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 +61 -20
- package/dist/esm/script/vhtlc.js +85 -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 +62 -35
- package/dist/esm/wallet/serviceWorker/worker.js +120 -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 +24 -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 +37 -35
- 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,9 @@
|
|
|
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
|
+
[](https://deepwiki.com/arkade-os/ts-sdk)
|
|
6
|
+
|
|
4
7
|
## Installation
|
|
5
8
|
|
|
6
9
|
```bash
|
|
@@ -12,40 +15,84 @@ npm install @arkade-os/sdk
|
|
|
12
15
|
### Creating a Wallet
|
|
13
16
|
|
|
14
17
|
```typescript
|
|
15
|
-
import {
|
|
18
|
+
import { SingleKey, Wallet } from '@arkade-os/sdk'
|
|
16
19
|
|
|
17
20
|
// Create a new in-memory key (or use an external signer)
|
|
18
|
-
const identity =
|
|
21
|
+
const identity = SingleKey.fromHex('your_private_key_hex')
|
|
19
22
|
|
|
20
23
|
// Create a wallet with Ark support
|
|
21
24
|
const wallet = await Wallet.create({
|
|
22
|
-
network: 'mutinynet', // 'bitcoin', 'testnet', 'regtest', 'signet' or 'mutinynet'
|
|
23
25
|
identity: identity,
|
|
24
26
|
// Esplora API, can be left empty mempool.space API will be used
|
|
25
27
|
esploraUrl: 'https://mutinynet.com/api',
|
|
26
|
-
// OPTIONAL Ark Server connection information
|
|
27
28
|
arkServerUrl: 'https://mutinynet.arkade.sh',
|
|
28
|
-
arkServerPublicKey: 'fa73c6e4876ffb2dfc961d763cca9abc73d4b88efcb8f5e7ff92dc55e9aa553d'
|
|
29
29
|
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Receiving Bitcoin
|
|
30
33
|
|
|
34
|
+
```typescript
|
|
31
35
|
// Get wallet addresses
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
console.log('Ark Address:',
|
|
35
|
-
console.log('Boarding Address:',
|
|
36
|
-
|
|
36
|
+
const arkAddress = await wallet.getAddress()
|
|
37
|
+
const boardingAddress = await wallet.getBoardingAddress()
|
|
38
|
+
console.log('Ark Address:', arkAddress)
|
|
39
|
+
console.log('Boarding Address:', boardingAddress)
|
|
40
|
+
|
|
41
|
+
const incomingFunds = await waitForIncomingFunds(wallet)
|
|
42
|
+
if (incomingFunds.type === "vtxo") {
|
|
43
|
+
// virtual coins received
|
|
44
|
+
console.log("VTXOs: ", incomingFunds.vtxos)
|
|
45
|
+
} else if (incomingFunds.type === "utxo") {
|
|
46
|
+
// boarding coins received
|
|
47
|
+
console.log("UTXOs: ", incomingFunds.coins)
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Onboarding
|
|
52
|
+
|
|
53
|
+
Onboarding allows you to swap onchain funds into VTXOs
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { Ramps } from '@arkade-os/sdk'
|
|
57
|
+
|
|
58
|
+
const onboardTxid = await new Ramps(wallet).onboard();
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Checking Balance
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// Get detailed balance information
|
|
65
|
+
const balance = await wallet.getBalance()
|
|
66
|
+
console.log('Total Balance:', balance.total)
|
|
67
|
+
console.log('Boarding Total:', balance.boarding.total)
|
|
68
|
+
console.log('Offchain Available:', balance.available)
|
|
69
|
+
console.log('Offchain Settled:', balance.settled)
|
|
70
|
+
console.log('Offchain Preconfirmed:', balance.preconfirmed)
|
|
71
|
+
console.log('Recoverable:', balance.recoverable)
|
|
72
|
+
|
|
73
|
+
// Get virtual UTXOs (off-chain)
|
|
74
|
+
const virtualCoins = await wallet.getVtxos()
|
|
75
|
+
|
|
76
|
+
// Get boarding UTXOs
|
|
77
|
+
const boardingUtxos = await wallet.getBoardingUtxos()
|
|
37
78
|
```
|
|
38
79
|
|
|
39
80
|
### Sending Bitcoin
|
|
40
81
|
|
|
41
82
|
```typescript
|
|
42
|
-
// Send bitcoin
|
|
83
|
+
// Send bitcoin via Ark
|
|
43
84
|
const txid = await wallet.sendBitcoin({
|
|
44
85
|
address: 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx',
|
|
45
86
|
amount: 50000, // in satoshis
|
|
46
87
|
feeRate: 1 // optional, in sats/vbyte
|
|
47
88
|
})
|
|
89
|
+
```
|
|
48
90
|
|
|
91
|
+
### Batch Settlements
|
|
92
|
+
|
|
93
|
+
This can be used to move preconfirmed balances into finalized balances, to convert manually UTXOs and VTXOs.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
49
96
|
// For settling transactions
|
|
50
97
|
const settleTxid = await wallet.settle({
|
|
51
98
|
inputs, // from getVtxos() or getBoardingUtxos()
|
|
@@ -56,20 +103,6 @@ const settleTxid = await wallet.settle({
|
|
|
56
103
|
})
|
|
57
104
|
```
|
|
58
105
|
|
|
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
106
|
|
|
74
107
|
### Transaction History
|
|
75
108
|
|
|
@@ -80,26 +113,94 @@ console.log('History:', history)
|
|
|
80
113
|
|
|
81
114
|
// Example history entry:
|
|
82
115
|
{
|
|
83
|
-
type: TxType.TxReceived, // or TxType.TxSent
|
|
84
|
-
amount: 50000,
|
|
85
|
-
settled: true,
|
|
86
116
|
key: {
|
|
87
117
|
boardingTxid: '...', // for boarding transactions
|
|
118
|
+
commitmentTxid: '...', // for commitment transactions
|
|
88
119
|
redeemTxid: '...' // for regular transactions
|
|
89
|
-
}
|
|
120
|
+
},
|
|
121
|
+
type: TxType.TxReceived, // or TxType.TxSent
|
|
122
|
+
amount: 50000,
|
|
123
|
+
settled: true,
|
|
124
|
+
createdAt: 1234567890
|
|
90
125
|
}
|
|
91
126
|
```
|
|
92
127
|
|
|
128
|
+
### Offboarding
|
|
129
|
+
|
|
130
|
+
Collaborative exit or "offboarding" allows you to withdraw your virtual funds to an onchain address.
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { Ramps } from '@arkade-os/sdk'
|
|
134
|
+
|
|
135
|
+
const exitTxid = await new Ramps(wallet).offboard(onchainAddress);
|
|
136
|
+
```
|
|
137
|
+
|
|
93
138
|
### Unilateral Exit
|
|
94
139
|
|
|
140
|
+
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:
|
|
141
|
+
|
|
142
|
+
1. **Unrolling**: Broadcasting the transaction chain from off-chain back to on-chain
|
|
143
|
+
2. **Completing the exit**: Spending the unrolled VTXOs after the timelock expires
|
|
144
|
+
|
|
145
|
+
#### Step 1: Unrolling VTXOs
|
|
146
|
+
|
|
95
147
|
```typescript
|
|
96
|
-
|
|
97
|
-
|
|
148
|
+
import { Unroll, OnchainWallet } from '@arkade-os/sdk'
|
|
149
|
+
|
|
150
|
+
// Create an onchain wallet to pay for P2A outputs in VTXO branches
|
|
151
|
+
// OnchainWallet implements the AnchorBumper interface
|
|
152
|
+
const onchainWallet = new OnchainWallet(wallet.identity, 'regtest');
|
|
153
|
+
|
|
154
|
+
// Unroll a specific VTXO
|
|
155
|
+
const vtxo = { txid: 'your_vtxo_txid', vout: 0 };
|
|
156
|
+
const session = await Unroll.Session.create(
|
|
157
|
+
vtxo,
|
|
158
|
+
onchainWallet,
|
|
159
|
+
onchainWallet.provider,
|
|
160
|
+
wallet.indexerProvider
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// Iterate through the unrolling steps
|
|
164
|
+
for await (const step of session) {
|
|
165
|
+
switch (step.type) {
|
|
166
|
+
case Unroll.StepType.WAIT:
|
|
167
|
+
console.log(`Waiting for transaction ${step.txid} to be confirmed`);
|
|
168
|
+
break;
|
|
169
|
+
case Unroll.StepType.UNROLL:
|
|
170
|
+
console.log(`Broadcasting transaction ${step.tx.id}`);
|
|
171
|
+
break;
|
|
172
|
+
case Unroll.StepType.DONE:
|
|
173
|
+
console.log(`Unrolling complete for VTXO ${step.vtxoTxid}`);
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The unrolling process works by:
|
|
180
|
+
- Traversing the transaction chain from the root (most recent) to the leaf (oldest)
|
|
181
|
+
- Broadcasting each transaction that isn't already on-chain
|
|
182
|
+
- Waiting for confirmations between steps
|
|
183
|
+
- Using P2A (Pay-to-Anchor) transactions to pay for fees
|
|
98
184
|
|
|
99
|
-
|
|
100
|
-
|
|
185
|
+
#### Step 2: Completing the Exit
|
|
186
|
+
|
|
187
|
+
Once VTXOs are fully unrolled and the unilateral exit timelock has expired, you can complete the exit:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
// Complete the exit for specific VTXOs
|
|
191
|
+
await Unroll.completeUnroll(
|
|
192
|
+
wallet,
|
|
193
|
+
[vtxo.txid], // Array of VTXO transaction IDs to complete
|
|
194
|
+
onchainWallet.address // Address to receive the exit amount
|
|
195
|
+
);
|
|
101
196
|
```
|
|
102
197
|
|
|
198
|
+
**Important Notes:**
|
|
199
|
+
- Each VTXO may require multiple unroll steps depending on the transaction chain length
|
|
200
|
+
- Each unroll step must be confirmed before proceeding to the next
|
|
201
|
+
- The `completeUnroll` method can only be called after VTXOs are fully unrolled and the timelock has expired
|
|
202
|
+
- You need sufficient on-chain funds in the `OnchainWallet` to pay for P2A transaction fees
|
|
203
|
+
|
|
103
204
|
### Running the wallet in a service worker
|
|
104
205
|
|
|
105
206
|
1. Create a service worker file
|
|
@@ -108,7 +209,7 @@ await wallet.exit([{ txid: vtxo.txid, vout: vtxo.vout }]);
|
|
|
108
209
|
// service-worker.ts
|
|
109
210
|
import { Worker } from '@arkade-os/sdk'
|
|
110
211
|
|
|
111
|
-
// Worker
|
|
212
|
+
// Worker handles communication between the main thread and service worker
|
|
112
213
|
new Worker().start()
|
|
113
214
|
```
|
|
114
215
|
|
|
@@ -120,15 +221,13 @@ new Worker().start()
|
|
|
120
221
|
const serviceWorker = await setupServiceWorker('/service-worker.js')
|
|
121
222
|
const wallet = new ServiceWorkerWallet(serviceWorker)
|
|
122
223
|
|
|
123
|
-
//
|
|
224
|
+
// Initialize the wallet
|
|
124
225
|
await wallet.init({
|
|
125
|
-
network: 'mutinynet', // 'bitcoin', 'testnet', 'regtest', 'signet' or 'mutinynet'
|
|
126
226
|
privateKey: 'your_private_key_hex',
|
|
127
227
|
// Esplora API, can be left empty mempool.space API will be used
|
|
128
228
|
esploraUrl: 'https://mutinynet.com/api',
|
|
129
229
|
// OPTIONAL Ark Server connection information
|
|
130
230
|
arkServerUrl: 'https://mutinynet.arkade.sh',
|
|
131
|
-
arkServerPublicKey: 'fa73c6e4876ffb2dfc961d763cca9abc73d4b88efcb8f5e7ff92dc55e9aa553d'
|
|
132
231
|
})
|
|
133
232
|
|
|
134
233
|
// check service worker status
|
|
@@ -139,140 +238,7 @@ console.log('Service worker status:', status.walletInitialized)
|
|
|
139
238
|
await wallet.clear()
|
|
140
239
|
```
|
|
141
240
|
|
|
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
|
-
```
|
|
241
|
+
_For complete API documentation, visit our [TypeScript documentation](https://arkade-os.github.io/ts-sdk/)._
|
|
276
242
|
|
|
277
243
|
## Development
|
|
278
244
|
|
|
@@ -291,7 +257,7 @@ pnpm format
|
|
|
291
257
|
pnpm lint
|
|
292
258
|
```
|
|
293
259
|
|
|
294
|
-
2.Install nigiri for integration tests:
|
|
260
|
+
2. Install nigiri for integration tests:
|
|
295
261
|
|
|
296
262
|
```bash
|
|
297
263
|
curl https://getnigiri.vulpem.com | bash
|
|
@@ -306,12 +272,20 @@ pnpm test
|
|
|
306
272
|
# Run unit tests only
|
|
307
273
|
pnpm test:unit
|
|
308
274
|
|
|
309
|
-
# Run integration tests
|
|
275
|
+
# Run integration tests with ark provided by nigiri
|
|
310
276
|
nigiri start --ark
|
|
311
|
-
pnpm test:setup
|
|
277
|
+
pnpm test:setup # Run setup script for integration tests
|
|
312
278
|
pnpm test:integration
|
|
313
279
|
nigiri stop --delete
|
|
314
280
|
|
|
281
|
+
# Run integration tests with ark provided by docker (requires nigiri)
|
|
282
|
+
nigiri start
|
|
283
|
+
pnpm test:up-docker
|
|
284
|
+
pnpm test:setup-docker # Run setup script for integration tests
|
|
285
|
+
pnpm test:integration-docker
|
|
286
|
+
pnpm test:down-docker
|
|
287
|
+
nigiri stop --delete
|
|
288
|
+
|
|
315
289
|
# Watch mode for development
|
|
316
290
|
pnpm test:watch
|
|
317
291
|
|
|
@@ -319,6 +293,15 @@ pnpm test:watch
|
|
|
319
293
|
pnpm test:coverage
|
|
320
294
|
```
|
|
321
295
|
|
|
296
|
+
### Building the documentation
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# Build the TS doc
|
|
300
|
+
pnpm docs:build
|
|
301
|
+
# open the docs in the browser
|
|
302
|
+
pnpm docs:open
|
|
303
|
+
```
|
|
304
|
+
|
|
322
305
|
### Releasing
|
|
323
306
|
|
|
324
307
|
```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");
|