@arkade-os/sdk 0.2.2 → 0.3.0-alpha.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 +114 -43
- package/dist/cjs/adapters/asyncStorage.js +5 -0
- package/dist/cjs/adapters/fileSystem.js +5 -0
- package/dist/cjs/adapters/indexedDB.js +5 -0
- package/dist/cjs/adapters/localStorage.js +5 -0
- package/dist/cjs/bip322/index.js +2 -2
- package/dist/cjs/identity/index.js +15 -0
- package/dist/cjs/identity/singleKey.js +20 -1
- package/dist/cjs/index.js +5 -3
- package/dist/cjs/musig2/keys.js +6 -6
- package/dist/cjs/musig2/sign.js +5 -5
- package/dist/cjs/repositories/contractRepository.js +130 -0
- package/dist/cjs/repositories/index.js +18 -0
- package/dist/cjs/repositories/walletRepository.js +136 -0
- package/dist/cjs/storage/asyncStorage.js +47 -0
- package/dist/cjs/storage/fileSystem.js +138 -0
- package/dist/cjs/storage/inMemory.js +21 -0
- package/dist/cjs/storage/indexedDB.js +97 -0
- package/dist/cjs/storage/localStorage.js +48 -0
- package/dist/cjs/tree/signingSession.js +4 -4
- package/dist/cjs/wallet/onchain.js +12 -6
- package/dist/cjs/wallet/serviceWorker/request.js +4 -14
- package/dist/cjs/wallet/serviceWorker/response.js +0 -13
- package/dist/cjs/wallet/serviceWorker/wallet.js +124 -130
- package/dist/cjs/wallet/serviceWorker/worker.js +89 -53
- package/dist/cjs/wallet/wallet.js +21 -4
- package/dist/esm/adapters/asyncStorage.js +1 -0
- package/dist/esm/adapters/fileSystem.js +1 -0
- package/dist/esm/adapters/indexedDB.js +1 -0
- package/dist/esm/adapters/localStorage.js +1 -0
- package/dist/esm/bip322/index.js +1 -1
- package/dist/esm/identity/index.js +1 -1
- package/dist/esm/identity/singleKey.js +21 -2
- package/dist/esm/index.js +4 -3
- package/dist/esm/musig2/keys.js +6 -6
- package/dist/esm/musig2/sign.js +4 -4
- package/dist/esm/repositories/contractRepository.js +126 -0
- package/dist/esm/repositories/index.js +2 -0
- package/dist/esm/repositories/walletRepository.js +132 -0
- package/dist/esm/storage/asyncStorage.js +43 -0
- package/dist/esm/storage/fileSystem.js +101 -0
- package/dist/esm/storage/inMemory.js +17 -0
- package/dist/esm/storage/indexedDB.js +93 -0
- package/dist/esm/storage/localStorage.js +44 -0
- package/dist/esm/tree/signingSession.js +1 -1
- package/dist/esm/wallet/onchain.js +12 -6
- package/dist/esm/wallet/serviceWorker/request.js +4 -14
- package/dist/esm/wallet/serviceWorker/response.js +0 -13
- package/dist/esm/wallet/serviceWorker/wallet.js +125 -131
- package/dist/esm/wallet/serviceWorker/worker.js +90 -54
- package/dist/esm/wallet/wallet.js +21 -4
- package/dist/types/adapters/asyncStorage.d.ts +2 -0
- package/dist/types/adapters/fileSystem.d.ts +2 -0
- package/dist/types/adapters/indexedDB.d.ts +2 -0
- package/dist/types/adapters/localStorage.d.ts +2 -0
- package/dist/types/identity/index.d.ts +3 -1
- package/dist/types/identity/singleKey.d.ts +12 -1
- package/dist/types/index.d.ts +4 -4
- package/dist/types/repositories/contractRepository.d.ts +20 -0
- package/dist/types/repositories/index.d.ts +2 -0
- package/dist/types/repositories/walletRepository.d.ts +38 -0
- package/dist/types/storage/asyncStorage.d.ts +9 -0
- package/dist/types/storage/fileSystem.d.ts +11 -0
- package/dist/types/storage/inMemory.d.ts +8 -0
- package/dist/types/storage/index.d.ts +6 -0
- package/dist/types/storage/indexedDB.d.ts +12 -0
- package/dist/types/storage/localStorage.d.ts +8 -0
- package/dist/types/wallet/index.d.ts +3 -0
- package/dist/types/wallet/onchain.d.ts +3 -2
- package/dist/types/wallet/serviceWorker/request.d.ts +1 -7
- package/dist/types/wallet/serviceWorker/response.d.ts +1 -8
- package/dist/types/wallet/serviceWorker/wallet.d.ts +67 -21
- package/dist/types/wallet/serviceWorker/worker.d.ts +17 -4
- package/dist/types/wallet/wallet.d.ts +4 -0
- package/package.json +38 -14
- package/dist/cjs/wallet/serviceWorker/db/vtxo/idb.js +0 -185
- package/dist/esm/wallet/serviceWorker/db/vtxo/idb.js +0 -181
- package/dist/types/wallet/serviceWorker/db/vtxo/idb.d.ts +0 -20
- package/dist/types/wallet/serviceWorker/db/vtxo/index.d.ts +0 -14
- /package/dist/cjs/{wallet/serviceWorker/db/vtxo → storage}/index.js +0 -0
- /package/dist/esm/{wallet/serviceWorker/db/vtxo → storage}/index.js +0 -0
|
@@ -5,19 +5,53 @@ import { Wallet } from '../wallet.js';
|
|
|
5
5
|
import { Request } from './request.js';
|
|
6
6
|
import { Response } from './response.js';
|
|
7
7
|
import { RestArkProvider } from '../../providers/ark.js';
|
|
8
|
-
import { IndexedDBVtxoRepository } from './db/vtxo/idb.js';
|
|
9
8
|
import { vtxosToTxs } from '../../utils/transactionHistory.js';
|
|
10
9
|
import { RestIndexerProvider } from '../../providers/indexer.js';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import { hex } from "@scure/base";
|
|
11
|
+
import { IndexedDBStorageAdapter } from '../../storage/indexedDB.js';
|
|
12
|
+
import { WalletRepositoryImpl, } from '../../repositories/walletRepository.js';
|
|
13
13
|
/**
|
|
14
14
|
* Worker is a class letting to interact with ServiceWorkerWallet from the client
|
|
15
15
|
* it aims to be run in a service worker context
|
|
16
16
|
*/
|
|
17
17
|
export class Worker {
|
|
18
|
-
constructor(
|
|
19
|
-
this.vtxoRepository = vtxoRepository;
|
|
18
|
+
constructor(messageCallback = () => { }) {
|
|
20
19
|
this.messageCallback = messageCallback;
|
|
20
|
+
this.storage = new IndexedDBStorageAdapter("arkade-service-worker", 1);
|
|
21
|
+
this.walletRepository = new WalletRepositoryImpl(this.storage);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get spendable vtxos for the current wallet address
|
|
25
|
+
*/
|
|
26
|
+
async getSpendableVtxos() {
|
|
27
|
+
if (!this.wallet)
|
|
28
|
+
return [];
|
|
29
|
+
const address = await this.wallet.getAddress();
|
|
30
|
+
const allVtxos = await this.walletRepository.getVtxos(address);
|
|
31
|
+
return allVtxos.filter(isSpendable);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get swept vtxos for the current wallet address
|
|
35
|
+
*/
|
|
36
|
+
async getSweptVtxos() {
|
|
37
|
+
if (!this.wallet)
|
|
38
|
+
return [];
|
|
39
|
+
const address = await this.wallet.getAddress();
|
|
40
|
+
const allVtxos = await this.walletRepository.getVtxos(address);
|
|
41
|
+
return allVtxos.filter((vtxo) => vtxo.virtualStatus.state === "swept" && isSpendable(vtxo));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get all vtxos categorized by type
|
|
45
|
+
*/
|
|
46
|
+
async getAllVtxos() {
|
|
47
|
+
if (!this.wallet)
|
|
48
|
+
return { spendable: [], spent: [] };
|
|
49
|
+
const address = await this.wallet.getAddress();
|
|
50
|
+
const allVtxos = await this.walletRepository.getVtxos(address);
|
|
51
|
+
return {
|
|
52
|
+
spendable: allVtxos.filter(isSpendable),
|
|
53
|
+
spent: allVtxos.filter((vtxo) => !isSpendable(vtxo)),
|
|
54
|
+
};
|
|
21
55
|
}
|
|
22
56
|
async start(withServiceWorkerUpdate = true) {
|
|
23
57
|
self.addEventListener("message", async (event) => {
|
|
@@ -38,12 +72,18 @@ export class Worker {
|
|
|
38
72
|
if (this.vtxoSubscription) {
|
|
39
73
|
this.vtxoSubscription.abort();
|
|
40
74
|
}
|
|
41
|
-
|
|
75
|
+
// Clear storage - this replaces vtxoRepository.close()
|
|
76
|
+
await this.storage.clear();
|
|
42
77
|
this.wallet = undefined;
|
|
43
78
|
this.arkProvider = undefined;
|
|
44
79
|
this.indexerProvider = undefined;
|
|
45
80
|
this.vtxoSubscription = undefined;
|
|
46
81
|
}
|
|
82
|
+
async reload() {
|
|
83
|
+
if (this.vtxoSubscription)
|
|
84
|
+
this.vtxoSubscription.abort();
|
|
85
|
+
await this.onWalletInitialized();
|
|
86
|
+
}
|
|
47
87
|
async onWalletInitialized() {
|
|
48
88
|
if (!this.wallet ||
|
|
49
89
|
!this.arkProvider ||
|
|
@@ -52,8 +92,6 @@ export class Worker {
|
|
|
52
92
|
!this.wallet.boardingTapscript) {
|
|
53
93
|
return;
|
|
54
94
|
}
|
|
55
|
-
// subscribe to address updates
|
|
56
|
-
await this.vtxoRepository.open();
|
|
57
95
|
const encodedOffchainTapscript = this.wallet.offchainTapscript.encode();
|
|
58
96
|
const forfeit = this.wallet.offchainTapscript.forfeit();
|
|
59
97
|
const exit = this.wallet.offchainTapscript.exit();
|
|
@@ -68,7 +106,9 @@ export class Worker {
|
|
|
68
106
|
intentTapLeafScript: exit,
|
|
69
107
|
tapTree: encodedOffchainTapscript,
|
|
70
108
|
}));
|
|
71
|
-
|
|
109
|
+
// Get wallet address and save vtxos using unified repository
|
|
110
|
+
const address = await this.wallet.getAddress();
|
|
111
|
+
await this.walletRepository.saveVtxos(address, vtxos);
|
|
72
112
|
this.processVtxoSubscription({
|
|
73
113
|
script,
|
|
74
114
|
vtxoScript: this.wallet.offchainTapscript,
|
|
@@ -94,7 +134,11 @@ export class Worker {
|
|
|
94
134
|
intentTapLeafScript,
|
|
95
135
|
tapTree,
|
|
96
136
|
}));
|
|
97
|
-
|
|
137
|
+
// Get wallet address and save vtxos using unified repository
|
|
138
|
+
const address = await this.wallet.getAddress();
|
|
139
|
+
await this.walletRepository.saveVtxos(address, extendedVtxos);
|
|
140
|
+
// Notify all clients about the vtxo update
|
|
141
|
+
this.sendMessageToAllClients("VTXO_UPDATE", "");
|
|
98
142
|
}
|
|
99
143
|
}
|
|
100
144
|
catch (error) {
|
|
@@ -102,7 +146,7 @@ export class Worker {
|
|
|
102
146
|
}
|
|
103
147
|
}
|
|
104
148
|
async handleClear(event) {
|
|
105
|
-
this.clear();
|
|
149
|
+
await this.clear();
|
|
106
150
|
if (Request.isBase(event.data)) {
|
|
107
151
|
event.source?.postMessage(Response.clearResponse(event.data.id, true));
|
|
108
152
|
}
|
|
@@ -114,13 +158,22 @@ export class Worker {
|
|
|
114
158
|
event.source?.postMessage(Response.error(message.id, "Invalid INIT_WALLET message format"));
|
|
115
159
|
return;
|
|
116
160
|
}
|
|
161
|
+
if (!message.privateKey) {
|
|
162
|
+
const err = "Missing privateKey";
|
|
163
|
+
event.source?.postMessage(Response.error(message.id, err));
|
|
164
|
+
console.error(err);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
117
167
|
try {
|
|
118
|
-
|
|
119
|
-
|
|
168
|
+
const { arkServerPublicKey, arkServerUrl, privateKey } = message;
|
|
169
|
+
const identity = SingleKey.fromHex(privateKey);
|
|
170
|
+
this.arkProvider = new RestArkProvider(arkServerUrl);
|
|
171
|
+
this.indexerProvider = new RestIndexerProvider(arkServerUrl);
|
|
120
172
|
this.wallet = await Wallet.create({
|
|
121
|
-
identity
|
|
122
|
-
arkServerUrl
|
|
123
|
-
arkServerPublicKey
|
|
173
|
+
identity,
|
|
174
|
+
arkServerUrl,
|
|
175
|
+
arkServerPublicKey,
|
|
176
|
+
storage: this.storage, // Use unified storage for wallet too
|
|
124
177
|
});
|
|
125
178
|
event.source?.postMessage(Response.walletInitialized(message.id));
|
|
126
179
|
await this.onWalletInitialized();
|
|
@@ -246,8 +299,8 @@ export class Worker {
|
|
|
246
299
|
try {
|
|
247
300
|
const [boardingUtxos, spendableVtxos, sweptVtxos] = await Promise.all([
|
|
248
301
|
this.wallet.getBoardingUtxos(),
|
|
249
|
-
this.
|
|
250
|
-
this.
|
|
302
|
+
this.getSpendableVtxos(),
|
|
303
|
+
this.getSweptVtxos(),
|
|
251
304
|
]);
|
|
252
305
|
// boarding
|
|
253
306
|
let confirmed = 0;
|
|
@@ -313,7 +366,7 @@ export class Worker {
|
|
|
313
366
|
return;
|
|
314
367
|
}
|
|
315
368
|
try {
|
|
316
|
-
let vtxos = await this.
|
|
369
|
+
let vtxos = await this.getSpendableVtxos();
|
|
317
370
|
if (!message.filter?.withRecoverable) {
|
|
318
371
|
if (!this.wallet)
|
|
319
372
|
throw new Error("Wallet not initialized");
|
|
@@ -322,7 +375,7 @@ export class Worker {
|
|
|
322
375
|
}
|
|
323
376
|
if (message.filter?.withRecoverable) {
|
|
324
377
|
// get also swept and spendable vtxos
|
|
325
|
-
const sweptVtxos = await this.
|
|
378
|
+
const sweptVtxos = await this.getSweptVtxos();
|
|
326
379
|
vtxos.push(...sweptVtxos.filter(isSpendable));
|
|
327
380
|
}
|
|
328
381
|
event.source?.postMessage(Response.vtxos(message.id, vtxos));
|
|
@@ -373,7 +426,7 @@ export class Worker {
|
|
|
373
426
|
}
|
|
374
427
|
try {
|
|
375
428
|
const { boardingTxs, commitmentsToIgnore: roundsToIgnore } = await this.wallet.getBoardingTxs();
|
|
376
|
-
const { spendable, spent } = await this.
|
|
429
|
+
const { spendable, spent } = await this.getAllVtxos();
|
|
377
430
|
// convert VTXOs to offchain transactions
|
|
378
431
|
const offchainTxs = vtxosToTxs(spendable, spent, roundsToIgnore);
|
|
379
432
|
const txs = [...boardingTxs, ...offchainTxs];
|
|
@@ -404,35 +457,10 @@ export class Worker {
|
|
|
404
457
|
event.source?.postMessage(Response.error(message.id, "Invalid GET_STATUS message format"));
|
|
405
458
|
return;
|
|
406
459
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
if (!Request.isSign(message)) {
|
|
412
|
-
console.error("Invalid SIGN message format", message);
|
|
413
|
-
event.source?.postMessage(Response.error(message.id, "Invalid SIGN message format"));
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
416
|
-
if (!this.wallet) {
|
|
417
|
-
console.error("Wallet not initialized");
|
|
418
|
-
event.source?.postMessage(Response.error(message.id, "Wallet not initialized"));
|
|
419
|
-
return;
|
|
420
|
-
}
|
|
421
|
-
try {
|
|
422
|
-
const tx = Transaction.fromPSBT(base64.decode(message.tx), {
|
|
423
|
-
allowUnknown: true,
|
|
424
|
-
allowUnknownInputs: true,
|
|
425
|
-
});
|
|
426
|
-
const signedTx = await this.wallet.identity.sign(tx, message.inputIndexes);
|
|
427
|
-
event.source?.postMessage(Response.signSuccess(message.id, base64.encode(signedTx.toPSBT())));
|
|
428
|
-
}
|
|
429
|
-
catch (error) {
|
|
430
|
-
console.error("Error signing:", error);
|
|
431
|
-
const errorMessage = error instanceof Error
|
|
432
|
-
? error.message
|
|
433
|
-
: "Unknown error occurred";
|
|
434
|
-
event.source?.postMessage(Response.error(message.id, errorMessage));
|
|
435
|
-
}
|
|
460
|
+
const pubKey = this.wallet
|
|
461
|
+
? await this.wallet.identity.xOnlyPublicKey()
|
|
462
|
+
: undefined;
|
|
463
|
+
event.source?.postMessage(Response.walletStatus(message.id, this.wallet !== undefined, pubKey));
|
|
436
464
|
}
|
|
437
465
|
async handleMessage(event) {
|
|
438
466
|
this.messageCallback(event);
|
|
@@ -487,12 +515,20 @@ export class Worker {
|
|
|
487
515
|
await this.handleClear(event);
|
|
488
516
|
break;
|
|
489
517
|
}
|
|
490
|
-
case "SIGN": {
|
|
491
|
-
await this.handleSign(event);
|
|
492
|
-
break;
|
|
493
|
-
}
|
|
494
518
|
default:
|
|
495
519
|
event.source?.postMessage(Response.error(message.id, "Unknown message type"));
|
|
496
520
|
}
|
|
497
521
|
}
|
|
522
|
+
async sendMessageToAllClients(type, message) {
|
|
523
|
+
self.clients
|
|
524
|
+
.matchAll({ includeUncontrolled: true, type: "window" })
|
|
525
|
+
.then((clients) => {
|
|
526
|
+
clients.forEach((client) => {
|
|
527
|
+
client.postMessage({
|
|
528
|
+
type,
|
|
529
|
+
message,
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
}
|
|
498
534
|
}
|
|
@@ -20,6 +20,9 @@ import { ArkNote } from '../arknote/index.js';
|
|
|
20
20
|
import { BIP322 } from '../bip322/index.js';
|
|
21
21
|
import { RestIndexerProvider } from '../providers/indexer.js';
|
|
22
22
|
import { TxTree } from '../tree/txTree.js';
|
|
23
|
+
import { InMemoryStorageAdapter } from '../storage/inMemory.js';
|
|
24
|
+
import { WalletRepositoryImpl, } from '../repositories/walletRepository.js';
|
|
25
|
+
import { ContractRepositoryImpl, } from '../repositories/contractRepository.js';
|
|
23
26
|
/**
|
|
24
27
|
* Main wallet implementation for Bitcoin transactions with Ark protocol support.
|
|
25
28
|
* The wallet does not store any data locally and relies on Ark and onchain
|
|
@@ -46,7 +49,7 @@ import { TxTree } from '../tree/txTree.js';
|
|
|
46
49
|
* ```
|
|
47
50
|
*/
|
|
48
51
|
export class Wallet {
|
|
49
|
-
constructor(identity, network, networkName, onchainProvider, arkProvider, indexerProvider, arkServerPublicKey, offchainTapscript, boardingTapscript, serverUnrollScript, forfeitOutputScript, dustAmount) {
|
|
52
|
+
constructor(identity, network, networkName, onchainProvider, arkProvider, indexerProvider, arkServerPublicKey, offchainTapscript, boardingTapscript, serverUnrollScript, forfeitOutputScript, dustAmount, walletRepository, contractRepository) {
|
|
50
53
|
this.identity = identity;
|
|
51
54
|
this.network = network;
|
|
52
55
|
this.networkName = networkName;
|
|
@@ -59,9 +62,11 @@ export class Wallet {
|
|
|
59
62
|
this.serverUnrollScript = serverUnrollScript;
|
|
60
63
|
this.forfeitOutputScript = forfeitOutputScript;
|
|
61
64
|
this.dustAmount = dustAmount;
|
|
65
|
+
this.walletRepository = walletRepository;
|
|
66
|
+
this.contractRepository = contractRepository;
|
|
62
67
|
}
|
|
63
68
|
static async create(config) {
|
|
64
|
-
const pubkey = config.identity.xOnlyPublicKey();
|
|
69
|
+
const pubkey = await config.identity.xOnlyPublicKey();
|
|
65
70
|
if (!pubkey) {
|
|
66
71
|
throw new Error("Invalid configured public key");
|
|
67
72
|
}
|
|
@@ -101,7 +106,11 @@ export class Wallet {
|
|
|
101
106
|
// server is expecting funds to be sent to this address
|
|
102
107
|
const forfeitAddress = Address(network).decode(info.forfeitAddress);
|
|
103
108
|
const forfeitOutputScript = OutScript.encode(forfeitAddress);
|
|
104
|
-
|
|
109
|
+
// Set up storage and repositories
|
|
110
|
+
const storage = config.storage || new InMemoryStorageAdapter();
|
|
111
|
+
const walletRepository = new WalletRepositoryImpl(storage);
|
|
112
|
+
const contractRepository = new ContractRepositoryImpl(storage);
|
|
113
|
+
return new Wallet(config.identity, network, info.network, onchainProvider, arkProvider, indexerProvider, serverPubKey, offchainTapscript, boardingTapscript, serverUnrollScript, forfeitOutputScript, info.dust, walletRepository, contractRepository);
|
|
105
114
|
}
|
|
106
115
|
get arkAddress() {
|
|
107
116
|
return this.offchainTapscript.address(this.network.hrp, this.arkServerPublicKey);
|
|
@@ -157,16 +166,24 @@ export class Wallet {
|
|
|
157
166
|
};
|
|
158
167
|
}
|
|
159
168
|
async getVtxos(filter) {
|
|
169
|
+
const address = await this.getAddress();
|
|
170
|
+
// Try to get from cache first
|
|
171
|
+
const cachedVtxos = await this.walletRepository.getVtxos(address);
|
|
172
|
+
// For now, always fetch fresh data from provider and update cache
|
|
173
|
+
// In future, we can add cache invalidation logic based on timestamps
|
|
160
174
|
const spendableVtxos = await this.getVirtualCoins(filter);
|
|
161
175
|
const encodedOffchainTapscript = this.offchainTapscript.encode();
|
|
162
176
|
const forfeit = this.offchainTapscript.forfeit();
|
|
163
177
|
const exit = this.offchainTapscript.exit();
|
|
164
|
-
|
|
178
|
+
const extendedVtxos = spendableVtxos.map((vtxo) => ({
|
|
165
179
|
...vtxo,
|
|
166
180
|
forfeitTapLeafScript: forfeit,
|
|
167
181
|
intentTapLeafScript: exit,
|
|
168
182
|
tapTree: encodedOffchainTapscript,
|
|
169
183
|
}));
|
|
184
|
+
// Update cache with fresh data
|
|
185
|
+
await this.walletRepository.saveVtxos(address, extendedVtxos);
|
|
186
|
+
return extendedVtxos;
|
|
170
187
|
}
|
|
171
188
|
async getVirtualCoins(filter = { withRecoverable: true, withUnrolled: false }) {
|
|
172
189
|
const scripts = [hex.encode(this.offchainTapscript.pkScript)];
|
|
@@ -2,6 +2,8 @@ import { Transaction } from "@scure/btc-signer";
|
|
|
2
2
|
import { SignerSession } from "../tree/signingSession";
|
|
3
3
|
export interface Identity {
|
|
4
4
|
sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
|
|
5
|
-
xOnlyPublicKey(): Uint8Array
|
|
5
|
+
xOnlyPublicKey(): Promise<Uint8Array>;
|
|
6
6
|
signerSession(): SignerSession;
|
|
7
|
+
signMessage(message: string): Promise<Uint8Array>;
|
|
7
8
|
}
|
|
9
|
+
export * from "./singleKey";
|
|
@@ -12,6 +12,9 @@ import { SignerSession } from "../tree/signingSession";
|
|
|
12
12
|
* // Create from raw bytes
|
|
13
13
|
* const key = SingleKey.fromPrivateKey(privateKeyBytes);
|
|
14
14
|
*
|
|
15
|
+
* // Create random key
|
|
16
|
+
* const randomKey = SingleKey.fromRandomBytes();
|
|
17
|
+
*
|
|
15
18
|
* // Sign a transaction
|
|
16
19
|
* const signedTx = await key.sign(transaction);
|
|
17
20
|
* ```
|
|
@@ -21,7 +24,15 @@ export declare class SingleKey implements Identity {
|
|
|
21
24
|
private constructor();
|
|
22
25
|
static fromPrivateKey(privateKey: Uint8Array): SingleKey;
|
|
23
26
|
static fromHex(privateKeyHex: string): SingleKey;
|
|
27
|
+
static fromRandomBytes(): SingleKey;
|
|
28
|
+
/**
|
|
29
|
+
* Export the private key as a hex string.
|
|
30
|
+
*
|
|
31
|
+
* @returns The private key as a hex string
|
|
32
|
+
*/
|
|
33
|
+
toHex(): string;
|
|
24
34
|
sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
|
|
25
|
-
xOnlyPublicKey(): Uint8Array
|
|
35
|
+
xOnlyPublicKey(): Promise<Uint8Array>;
|
|
26
36
|
signerSession(): SignerSession;
|
|
37
|
+
signMessage(message: string): Promise<Uint8Array>;
|
|
27
38
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -23,13 +23,13 @@ import { buildOffchainTx, ArkTxInput, OffchainTx } from "./utils/arkTransaction"
|
|
|
23
23
|
import { VtxoTaprootTree, ConditionWitness, getArkPsbtFields, setArkPsbtField, ArkPsbtFieldCoder, ArkPsbtFieldKey, ArkPsbtFieldKeyType, CosignerPublicKey, VtxoTreeExpiry } from "./utils/unknownFields";
|
|
24
24
|
import { BIP322 } from "./bip322";
|
|
25
25
|
import { ArkNote } from "./arknote";
|
|
26
|
-
import { IndexedDBVtxoRepository } from "./wallet/serviceWorker/db/vtxo/idb";
|
|
27
|
-
import { VtxoRepository } from "./wallet/serviceWorker/db/vtxo";
|
|
28
26
|
import { networks, Network, NetworkName } from "./networks";
|
|
29
27
|
import { RestIndexerProvider, IndexerProvider, IndexerTxType, ChainTxType, PageResponse, Batch, ChainTx, CommitmentTx, TxHistoryRecord, VtxoChain, Tx, Vtxo, PaginationOptions, SubscriptionResponse } from "./providers/indexer";
|
|
30
28
|
import { Nonces } from "./musig2/nonces";
|
|
31
29
|
import { PartialSig } from "./musig2/sign";
|
|
32
30
|
import { AnchorBumper, P2A } from "./utils/anchor";
|
|
33
31
|
import { Unroll } from "./wallet/unroll";
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
import { WalletRepositoryImpl } from "./repositories/walletRepository";
|
|
33
|
+
import { ContractRepositoryImpl } from "./repositories/contractRepository";
|
|
34
|
+
export { Wallet, SingleKey, OnchainWallet, Ramps, ESPLORA_URL, EsploraProvider, RestArkProvider, RestIndexerProvider, ArkAddress, DefaultVtxo, VtxoScript, VHTLC, TxType, IndexerTxType, ChainTxType, SettlementEventType, setupServiceWorker, Worker, ServiceWorkerWallet, Request, Response, decodeTapscript, MultisigTapscript, CSVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CLTVMultisigTapscript, ArkPsbtFieldKey, ArkPsbtFieldKeyType, setArkPsbtField, getArkPsbtFields, CosignerPublicKey, VtxoTreeExpiry, VtxoTaprootTree, ConditionWitness, buildOffchainTx, waitForIncomingFunds, ArkNote, networks, WalletRepositoryImpl, ContractRepositoryImpl, BIP322, TxTree, P2A, Unroll, Transaction, };
|
|
35
|
+
export type { Identity, IWallet, WalletConfig, ArkTransaction, Coin, ExtendedCoin, ExtendedVirtualCoin, WalletBalance, SendBitcoinParams, Recipient, SettleParams, Status, VirtualStatus, Outpoint, VirtualCoin, TxKey, TapscriptType, ArkTxInput, OffchainTx, TapLeaves, IncomingFunds, IndexerProvider, PageResponse, Batch, ChainTx, CommitmentTx, TxHistoryRecord, Vtxo, VtxoChain, Tx, OnchainProvider, ArkProvider, SettlementEvent, ArkInfo, Intent, Output, TxNotification, ExplorerTransaction, BatchFinalizationEvent, BatchFinalizedEvent, BatchFailedEvent, TreeSigningStartedEvent, TreeNoncesAggregatedEvent, BatchStartedEvent, TreeTxEvent, TreeSignatureEvent, MarketHour, PaginationOptions, SubscriptionResponse, Network, NetworkName, ArkTapscript, RelativeTimelock, EncodedVtxoScript, TapLeafScript, SignerSession, TreeNonces, TreePartialSigs, GetVtxosFilter, Nonces, PartialSig, ArkPsbtFieldCoder, TxTreeNode, AnchorBumper, };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { StorageAdapter } from "../storage";
|
|
2
|
+
export interface ContractRepository {
|
|
3
|
+
getContractData<T>(contractId: string, key: string): Promise<T | null>;
|
|
4
|
+
setContractData<T>(contractId: string, key: string, data: T): Promise<void>;
|
|
5
|
+
deleteContractData(contractId: string, key: string): Promise<void>;
|
|
6
|
+
getContractCollection<T>(contractType: string): Promise<ReadonlyArray<T>>;
|
|
7
|
+
saveToContractCollection<T, K extends keyof T>(contractType: string, item: T, idField: K): Promise<void>;
|
|
8
|
+
removeFromContractCollection<T, K extends keyof T>(contractType: string, id: T[K], idField: K): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export declare class ContractRepositoryImpl implements ContractRepository {
|
|
11
|
+
private storage;
|
|
12
|
+
private cache;
|
|
13
|
+
constructor(storage: StorageAdapter);
|
|
14
|
+
getContractData<T>(contractId: string, key: string): Promise<T | null>;
|
|
15
|
+
setContractData<T>(contractId: string, key: string, data: T): Promise<void>;
|
|
16
|
+
deleteContractData(contractId: string, key: string): Promise<void>;
|
|
17
|
+
getContractCollection<T>(contractType: string): Promise<ReadonlyArray<T>>;
|
|
18
|
+
saveToContractCollection<T, K extends keyof T>(contractType: string, item: T, idField: K): Promise<void>;
|
|
19
|
+
removeFromContractCollection<T, K extends keyof T>(contractType: string, id: T[K], idField: K): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { StorageAdapter } from "../storage";
|
|
2
|
+
import { ExtendedVirtualCoin } from "../wallet";
|
|
3
|
+
export interface WalletState {
|
|
4
|
+
lastSyncTime?: number;
|
|
5
|
+
settings?: Record<string, any>;
|
|
6
|
+
}
|
|
7
|
+
export interface Transaction {
|
|
8
|
+
id: string;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
amount: number;
|
|
11
|
+
type: "send" | "receive";
|
|
12
|
+
status: "pending" | "confirmed" | "failed";
|
|
13
|
+
}
|
|
14
|
+
export interface WalletRepository {
|
|
15
|
+
getVtxos(address: string): Promise<ExtendedVirtualCoin[]>;
|
|
16
|
+
saveVtxo(address: string, vtxo: ExtendedVirtualCoin): Promise<void>;
|
|
17
|
+
saveVtxos(address: string, vtxos: ExtendedVirtualCoin[]): Promise<void>;
|
|
18
|
+
removeVtxo(address: string, vtxoId: string): Promise<void>;
|
|
19
|
+
clearVtxos(address: string): Promise<void>;
|
|
20
|
+
getTransactionHistory(address: string): Promise<Transaction[]>;
|
|
21
|
+
saveTransaction(address: string, tx: Transaction): Promise<void>;
|
|
22
|
+
getWalletState(): Promise<WalletState | null>;
|
|
23
|
+
saveWalletState(state: WalletState): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export declare class WalletRepositoryImpl implements WalletRepository {
|
|
26
|
+
private storage;
|
|
27
|
+
private cache;
|
|
28
|
+
constructor(storage: StorageAdapter);
|
|
29
|
+
getVtxos(address: string): Promise<ExtendedVirtualCoin[]>;
|
|
30
|
+
saveVtxo(address: string, vtxo: ExtendedVirtualCoin): Promise<void>;
|
|
31
|
+
saveVtxos(address: string, vtxos: ExtendedVirtualCoin[]): Promise<void>;
|
|
32
|
+
removeVtxo(address: string, vtxoId: string): Promise<void>;
|
|
33
|
+
clearVtxos(address: string): Promise<void>;
|
|
34
|
+
getTransactionHistory(address: string): Promise<Transaction[]>;
|
|
35
|
+
saveTransaction(address: string, tx: Transaction): Promise<void>;
|
|
36
|
+
getWalletState(): Promise<WalletState | null>;
|
|
37
|
+
saveWalletState(state: WalletState): Promise<void>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { StorageAdapter } from "./index";
|
|
2
|
+
export declare class AsyncStorageAdapter implements StorageAdapter {
|
|
3
|
+
private AsyncStorage;
|
|
4
|
+
constructor();
|
|
5
|
+
getItem(key: string): Promise<string | null>;
|
|
6
|
+
setItem(key: string, value: string): Promise<void>;
|
|
7
|
+
removeItem(key: string): Promise<void>;
|
|
8
|
+
clear(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { StorageAdapter } from "./index";
|
|
2
|
+
export declare class FileSystemStorageAdapter implements StorageAdapter {
|
|
3
|
+
private readonly basePath;
|
|
4
|
+
constructor(dirPath: string);
|
|
5
|
+
private validateAndGetFilePath;
|
|
6
|
+
private ensureDirectory;
|
|
7
|
+
getItem(key: string): Promise<string | null>;
|
|
8
|
+
setItem(key: string, value: string): Promise<void>;
|
|
9
|
+
removeItem(key: string): Promise<void>;
|
|
10
|
+
clear(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StorageAdapter } from "./index";
|
|
2
|
+
export declare class InMemoryStorageAdapter implements StorageAdapter {
|
|
3
|
+
private store;
|
|
4
|
+
getItem(key: string): Promise<string | null>;
|
|
5
|
+
setItem(key: string, value: string): Promise<void>;
|
|
6
|
+
removeItem(key: string): Promise<void>;
|
|
7
|
+
clear(): Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { StorageAdapter } from "./index";
|
|
2
|
+
export declare class IndexedDBStorageAdapter implements StorageAdapter {
|
|
3
|
+
private dbName;
|
|
4
|
+
private version;
|
|
5
|
+
private db;
|
|
6
|
+
constructor(dbName: string, version?: number);
|
|
7
|
+
private getDB;
|
|
8
|
+
getItem(key: string): Promise<string | null>;
|
|
9
|
+
setItem(key: string, value: string): Promise<void>;
|
|
10
|
+
removeItem(key: string): Promise<void>;
|
|
11
|
+
clear(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StorageAdapter } from "./index";
|
|
2
|
+
export declare class LocalStorageAdapter implements StorageAdapter {
|
|
3
|
+
private getSafeLocalStorage;
|
|
4
|
+
getItem(key: string): Promise<string | null>;
|
|
5
|
+
setItem(key: string, value: string): Promise<void>;
|
|
6
|
+
removeItem(key: string): Promise<void>;
|
|
7
|
+
clear(): Promise<void>;
|
|
8
|
+
}
|
|
@@ -3,6 +3,7 @@ import { Identity } from "../identity";
|
|
|
3
3
|
import { RelativeTimelock } from "../script/tapscript";
|
|
4
4
|
import { EncodedVtxoScript, TapLeafScript } from "../script/base";
|
|
5
5
|
import { Bytes } from "@scure/btc-signer/utils";
|
|
6
|
+
import { StorageAdapter } from "../storage";
|
|
6
7
|
/**
|
|
7
8
|
* Configuration options for wallet initialization.
|
|
8
9
|
*
|
|
@@ -18,6 +19,7 @@ export interface WalletConfig {
|
|
|
18
19
|
arkServerPublicKey?: string;
|
|
19
20
|
boardingTimelock?: RelativeTimelock;
|
|
20
21
|
exitTimelock?: RelativeTimelock;
|
|
22
|
+
storage?: StorageAdapter;
|
|
21
23
|
}
|
|
22
24
|
export interface WalletBalance {
|
|
23
25
|
boarding: {
|
|
@@ -113,6 +115,7 @@ export type GetVtxosFilter = {
|
|
|
113
115
|
* operations, and transaction management including sending, settling, and unrolling.
|
|
114
116
|
*/
|
|
115
117
|
export interface IWallet {
|
|
118
|
+
identity: Identity;
|
|
116
119
|
getAddress(): Promise<string>;
|
|
117
120
|
getBoardingAddress(): Promise<string>;
|
|
118
121
|
getBalance(): Promise<WalletBalance>;
|
|
@@ -14,7 +14,7 @@ import { AnchorBumper } from "../utils/anchor";
|
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```typescript
|
|
17
|
-
* const wallet =
|
|
17
|
+
* const wallet = await OnchainWallet.create(identity, 'mainnet');
|
|
18
18
|
* const balance = await wallet.getBalance();
|
|
19
19
|
* const txid = await wallet.send({
|
|
20
20
|
* address: 'bc1...',
|
|
@@ -29,7 +29,8 @@ export declare class OnchainWallet implements AnchorBumper {
|
|
|
29
29
|
readonly onchainP2TR: P2TR;
|
|
30
30
|
readonly provider: OnchainProvider;
|
|
31
31
|
readonly network: Network;
|
|
32
|
-
constructor(
|
|
32
|
+
private constructor();
|
|
33
|
+
static create(identity: Identity, networkName: NetworkName, provider?: OnchainProvider): Promise<OnchainWallet>;
|
|
33
34
|
get address(): string;
|
|
34
35
|
getCoins(): Promise<Coin[]>;
|
|
35
36
|
getBalance(): Promise<number>;
|
|
@@ -3,7 +3,7 @@ import { SettleParams, SendBitcoinParams, GetVtxosFilter } from "..";
|
|
|
3
3
|
* Request is the namespace that contains the request types for the service worker.
|
|
4
4
|
*/
|
|
5
5
|
export declare namespace Request {
|
|
6
|
-
type Type = "INIT_WALLET" | "SETTLE" | "GET_ADDRESS" | "GET_BOARDING_ADDRESS" | "GET_BALANCE" | "GET_VTXOS" | "GET_VIRTUAL_COINS" | "GET_BOARDING_UTXOS" | "SEND_BITCOIN" | "GET_TRANSACTION_HISTORY" | "GET_STATUS" | "CLEAR"
|
|
6
|
+
type Type = "INIT_WALLET" | "SETTLE" | "GET_ADDRESS" | "GET_BOARDING_ADDRESS" | "GET_BALANCE" | "GET_VTXOS" | "GET_VIRTUAL_COINS" | "GET_BOARDING_UTXOS" | "SEND_BITCOIN" | "GET_TRANSACTION_HISTORY" | "GET_STATUS" | "CLEAR";
|
|
7
7
|
interface Base {
|
|
8
8
|
type: Type;
|
|
9
9
|
id: string;
|
|
@@ -62,10 +62,4 @@ export declare namespace Request {
|
|
|
62
62
|
interface Clear extends Base {
|
|
63
63
|
type: "CLEAR";
|
|
64
64
|
}
|
|
65
|
-
interface Sign extends Base {
|
|
66
|
-
type: "SIGN";
|
|
67
|
-
tx: string;
|
|
68
|
-
inputIndexes?: number[];
|
|
69
|
-
}
|
|
70
|
-
function isSign(message: Base): message is Sign;
|
|
71
65
|
}
|
|
@@ -4,7 +4,7 @@ import { SettlementEvent } from "../../providers/ark";
|
|
|
4
4
|
* Response is the namespace that contains the response types for the service worker.
|
|
5
5
|
*/
|
|
6
6
|
export declare namespace Response {
|
|
7
|
-
type Type = "WALLET_INITIALIZED" | "SETTLE_EVENT" | "SETTLE_SUCCESS" | "ADDRESS" | "BOARDING_ADDRESS" | "BALANCE" | "VTXOS" | "VIRTUAL_COINS" | "BOARDING_UTXOS" | "SEND_BITCOIN_SUCCESS" | "TRANSACTION_HISTORY" | "WALLET_STATUS" | "ERROR" | "CLEAR_RESPONSE"
|
|
7
|
+
type Type = "WALLET_INITIALIZED" | "SETTLE_EVENT" | "SETTLE_SUCCESS" | "ADDRESS" | "BOARDING_ADDRESS" | "BALANCE" | "VTXOS" | "VIRTUAL_COINS" | "BOARDING_UTXOS" | "SEND_BITCOIN_SUCCESS" | "TRANSACTION_HISTORY" | "WALLET_STATUS" | "ERROR" | "CLEAR_RESPONSE";
|
|
8
8
|
interface Base {
|
|
9
9
|
type: Type;
|
|
10
10
|
success: boolean;
|
|
@@ -101,11 +101,4 @@ export declare namespace Response {
|
|
|
101
101
|
}
|
|
102
102
|
function isClearResponse(response: Base): response is ClearResponse;
|
|
103
103
|
function clearResponse(id: string, success: boolean): ClearResponse;
|
|
104
|
-
interface SignSuccess extends Base {
|
|
105
|
-
type: "SIGN_SUCCESS";
|
|
106
|
-
success: true;
|
|
107
|
-
tx: string;
|
|
108
|
-
}
|
|
109
|
-
function signSuccess(id: string, tx: string): SignSuccess;
|
|
110
|
-
function isSignSuccess(response: Base): response is SignSuccess;
|
|
111
104
|
}
|