@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
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ramps is a class wrapping IWallet.settle method to provide a more convenient interface for onboarding and offboarding operations.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* const ramps = new Ramps(wallet);
|
|
7
|
+
* await ramps.onboard(); // onboard all boarding utxos
|
|
8
|
+
* await ramps.offboard(myOnchainAddress); // collaborative exit all vtxos to onchain address
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export class Ramps {
|
|
12
|
+
constructor(wallet) {
|
|
13
|
+
this.wallet = wallet;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Onboard boarding utxos.
|
|
17
|
+
*
|
|
18
|
+
* @param boardingUtxos - The boarding utxos to onboard. If not provided, all boarding utxos will be used.
|
|
19
|
+
* @param amount - The amount to onboard. If not provided, the total amount of boarding utxos will be onboarded.
|
|
20
|
+
* @param eventCallback - The callback to receive settlement events. optional.
|
|
21
|
+
*/
|
|
22
|
+
async onboard(boardingUtxos, amount, eventCallback) {
|
|
23
|
+
boardingUtxos = boardingUtxos ?? (await this.wallet.getBoardingUtxos());
|
|
24
|
+
const totalAmount = boardingUtxos.reduce((acc, coin) => acc + BigInt(coin.value), 0n);
|
|
25
|
+
let change = 0n;
|
|
26
|
+
if (amount) {
|
|
27
|
+
if (amount > totalAmount) {
|
|
28
|
+
throw new Error("Amount is greater than total amount of boarding utxos");
|
|
29
|
+
}
|
|
30
|
+
change = totalAmount - amount;
|
|
31
|
+
}
|
|
32
|
+
amount = amount ?? totalAmount;
|
|
33
|
+
const offchainAddress = await this.wallet.getAddress();
|
|
34
|
+
const outputs = [
|
|
35
|
+
{
|
|
36
|
+
address: offchainAddress,
|
|
37
|
+
amount,
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
if (change > 0n) {
|
|
41
|
+
const boardingAddress = await this.wallet.getBoardingAddress();
|
|
42
|
+
outputs.push({
|
|
43
|
+
address: boardingAddress,
|
|
44
|
+
amount: change,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return this.wallet.settle({
|
|
48
|
+
inputs: boardingUtxos,
|
|
49
|
+
outputs,
|
|
50
|
+
}, eventCallback);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Offboard vtxos, or "collaborative exit" vtxos to onchain address.
|
|
54
|
+
*
|
|
55
|
+
* @param destinationAddress - The destination address to offboard to.
|
|
56
|
+
* @param amount - The amount to offboard. If not provided, the total amount of vtxos will be offboarded.
|
|
57
|
+
* @param eventCallback - The callback to receive settlement events. optional.
|
|
58
|
+
*/
|
|
59
|
+
async offboard(destinationAddress, amount, eventCallback) {
|
|
60
|
+
const vtxos = await this.wallet.getVtxos({
|
|
61
|
+
withRecoverable: true,
|
|
62
|
+
withUnrolled: false,
|
|
63
|
+
});
|
|
64
|
+
const totalAmount = vtxos.reduce((acc, coin) => acc + BigInt(coin.value), 0n);
|
|
65
|
+
let change = 0n;
|
|
66
|
+
if (amount) {
|
|
67
|
+
if (amount > totalAmount) {
|
|
68
|
+
throw new Error("Amount is greater than total amount of vtxos");
|
|
69
|
+
}
|
|
70
|
+
change = totalAmount - amount;
|
|
71
|
+
}
|
|
72
|
+
amount = amount ?? totalAmount;
|
|
73
|
+
const outputs = [
|
|
74
|
+
{
|
|
75
|
+
address: destinationAddress,
|
|
76
|
+
amount,
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
if (change > 0n) {
|
|
80
|
+
const offchainAddress = await this.wallet.getAddress();
|
|
81
|
+
outputs.push({
|
|
82
|
+
address: offchainAddress,
|
|
83
|
+
amount: change,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return this.wallet.settle({
|
|
87
|
+
inputs: vtxos,
|
|
88
|
+
outputs,
|
|
89
|
+
}, eventCallback);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -108,6 +108,38 @@ export class IndexedDBVtxoRepository {
|
|
|
108
108
|
request.onerror = () => reject(request.error);
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
|
+
async getSweptVtxos() {
|
|
112
|
+
if (!this.db) {
|
|
113
|
+
throw new Error("Database not opened");
|
|
114
|
+
}
|
|
115
|
+
return new Promise((resolve, reject) => {
|
|
116
|
+
const transaction = this.db.transaction(IndexedDBVtxoRepository.STORE_NAME, "readonly");
|
|
117
|
+
const store = transaction.objectStore(IndexedDBVtxoRepository.STORE_NAME);
|
|
118
|
+
const stateIndex = store.index("state");
|
|
119
|
+
// Get vtxos where state is "swept"
|
|
120
|
+
const request = stateIndex.getAll(IDBKeyRange.only("swept"));
|
|
121
|
+
request.onsuccess = () => {
|
|
122
|
+
resolve(request.result);
|
|
123
|
+
};
|
|
124
|
+
request.onerror = () => reject(request.error);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
async getSpentVtxos() {
|
|
128
|
+
if (!this.db) {
|
|
129
|
+
throw new Error("Database not opened");
|
|
130
|
+
}
|
|
131
|
+
return new Promise((resolve, reject) => {
|
|
132
|
+
const transaction = this.db.transaction(IndexedDBVtxoRepository.STORE_NAME, "readonly");
|
|
133
|
+
const store = transaction.objectStore(IndexedDBVtxoRepository.STORE_NAME);
|
|
134
|
+
const spentByIndex = store.index("spentBy");
|
|
135
|
+
// Get vtxos where spentBy is not empty string
|
|
136
|
+
const request = spentByIndex.getAll(IDBKeyRange.lowerBound("", true));
|
|
137
|
+
request.onsuccess = () => {
|
|
138
|
+
resolve(request.result);
|
|
139
|
+
};
|
|
140
|
+
request.onerror = () => reject(request.error);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
111
143
|
async getAllVtxos() {
|
|
112
144
|
if (!this.db) {
|
|
113
145
|
throw new Error("Database not opened");
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request is the namespace that contains the request types for the service worker.
|
|
3
|
+
*/
|
|
1
4
|
export var Request;
|
|
2
5
|
(function (Request) {
|
|
3
6
|
function isBase(message) {
|
|
@@ -10,8 +13,6 @@ export var Request;
|
|
|
10
13
|
typeof message.privateKey === "string" &&
|
|
11
14
|
"arkServerUrl" in message &&
|
|
12
15
|
typeof message.arkServerUrl === "string" &&
|
|
13
|
-
"network" in message &&
|
|
14
|
-
typeof message.network === "string" &&
|
|
15
16
|
("arkServerPublicKey" in message
|
|
16
17
|
? typeof message.arkServerPublicKey === "string" ||
|
|
17
18
|
message.arkServerPublicKey === undefined
|
|
@@ -26,18 +27,14 @@ export var Request;
|
|
|
26
27
|
return message.type === "GET_ADDRESS";
|
|
27
28
|
}
|
|
28
29
|
Request.isGetAddress = isGetAddress;
|
|
29
|
-
function
|
|
30
|
-
return message.type === "
|
|
30
|
+
function isGetBoardingAddress(message) {
|
|
31
|
+
return message.type === "GET_BOARDING_ADDRESS";
|
|
31
32
|
}
|
|
32
|
-
Request.
|
|
33
|
+
Request.isGetBoardingAddress = isGetBoardingAddress;
|
|
33
34
|
function isGetBalance(message) {
|
|
34
35
|
return message.type === "GET_BALANCE";
|
|
35
36
|
}
|
|
36
37
|
Request.isGetBalance = isGetBalance;
|
|
37
|
-
function isGetCoins(message) {
|
|
38
|
-
return message.type === "GET_COINS";
|
|
39
|
-
}
|
|
40
|
-
Request.isGetCoins = isGetCoins;
|
|
41
38
|
function isGetVtxos(message) {
|
|
42
39
|
return message.type === "GET_VTXOS";
|
|
43
40
|
}
|
|
@@ -69,8 +66,14 @@ export var Request;
|
|
|
69
66
|
return message.type === "GET_STATUS";
|
|
70
67
|
}
|
|
71
68
|
Request.isGetStatus = isGetStatus;
|
|
72
|
-
function
|
|
73
|
-
return message.type === "
|
|
69
|
+
function isSign(message) {
|
|
70
|
+
return (message.type === "SIGN" &&
|
|
71
|
+
"tx" in message &&
|
|
72
|
+
typeof message.tx === "string" &&
|
|
73
|
+
("inputIndexes" in message && message.inputIndexes != undefined
|
|
74
|
+
? Array.isArray(message.inputIndexes) &&
|
|
75
|
+
message.inputIndexes.every((index) => typeof index === "number")
|
|
76
|
+
: true));
|
|
74
77
|
}
|
|
75
|
-
Request.
|
|
78
|
+
Request.isSign = isSign;
|
|
76
79
|
})(Request || (Request = {}));
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response is the namespace that contains the response types for the service worker.
|
|
3
|
+
*/
|
|
1
4
|
export var Response;
|
|
2
5
|
(function (Response) {
|
|
3
6
|
Response.walletInitialized = (id) => ({
|
|
@@ -40,28 +43,28 @@ export var Response;
|
|
|
40
43
|
return response.type === "ADDRESS" && response.success === true;
|
|
41
44
|
}
|
|
42
45
|
Response.isAddress = isAddress;
|
|
43
|
-
function
|
|
46
|
+
function isBoardingAddress(response) {
|
|
47
|
+
return (response.type === "BOARDING_ADDRESS" && response.success === true);
|
|
48
|
+
}
|
|
49
|
+
Response.isBoardingAddress = isBoardingAddress;
|
|
50
|
+
function address(id, address) {
|
|
44
51
|
return {
|
|
45
52
|
type: "ADDRESS",
|
|
46
53
|
success: true,
|
|
47
|
-
|
|
54
|
+
address,
|
|
48
55
|
id,
|
|
49
56
|
};
|
|
50
57
|
}
|
|
51
|
-
Response.
|
|
52
|
-
function
|
|
53
|
-
return response.type === "ADDRESS_INFO" && response.success === true;
|
|
54
|
-
}
|
|
55
|
-
Response.isAddressInfo = isAddressInfo;
|
|
56
|
-
function addressInfo(id, addressInfo) {
|
|
58
|
+
Response.address = address;
|
|
59
|
+
function boardingAddress(id, address) {
|
|
57
60
|
return {
|
|
58
|
-
type: "
|
|
61
|
+
type: "BOARDING_ADDRESS",
|
|
59
62
|
success: true,
|
|
60
|
-
|
|
63
|
+
address,
|
|
61
64
|
id,
|
|
62
65
|
};
|
|
63
66
|
}
|
|
64
|
-
Response.
|
|
67
|
+
Response.boardingAddress = boardingAddress;
|
|
65
68
|
function isBalance(response) {
|
|
66
69
|
return response.type === "BALANCE" && response.success === true;
|
|
67
70
|
}
|
|
@@ -75,19 +78,6 @@ export var Response;
|
|
|
75
78
|
};
|
|
76
79
|
}
|
|
77
80
|
Response.balance = balance;
|
|
78
|
-
function isCoins(response) {
|
|
79
|
-
return response.type === "COINS" && response.success === true;
|
|
80
|
-
}
|
|
81
|
-
Response.isCoins = isCoins;
|
|
82
|
-
function coins(id, coins) {
|
|
83
|
-
return {
|
|
84
|
-
type: "COINS",
|
|
85
|
-
success: true,
|
|
86
|
-
coins,
|
|
87
|
-
id,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
Response.coins = coins;
|
|
91
81
|
function isVtxos(response) {
|
|
92
82
|
return response.type === "VTXOS" && response.success === true;
|
|
93
83
|
}
|
|
@@ -181,12 +171,17 @@ export var Response;
|
|
|
181
171
|
};
|
|
182
172
|
}
|
|
183
173
|
Response.clearResponse = clearResponse;
|
|
184
|
-
function
|
|
174
|
+
function signSuccess(id, tx) {
|
|
185
175
|
return {
|
|
186
|
-
type: "
|
|
176
|
+
type: "SIGN_SUCCESS",
|
|
187
177
|
success: true,
|
|
178
|
+
tx,
|
|
188
179
|
id,
|
|
189
180
|
};
|
|
190
181
|
}
|
|
191
|
-
Response.
|
|
182
|
+
Response.signSuccess = signSuccess;
|
|
183
|
+
function isSignSuccess(response) {
|
|
184
|
+
return response.type === "SIGN_SUCCESS" && response.success === true;
|
|
185
|
+
}
|
|
186
|
+
Response.isSignSuccess = isSignSuccess;
|
|
192
187
|
})(Response || (Response = {}));
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* setupServiceWorker sets up the service worker.
|
|
3
|
+
* @param path - the path to the service worker script
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* const serviceWorker = await setupServiceWorker("/service-worker.js");
|
|
7
|
+
* ```
|
|
8
|
+
*/
|
|
1
9
|
export async function setupServiceWorker(path) {
|
|
2
10
|
// check if service workers are supported
|
|
3
11
|
if (!("serviceWorker" in navigator)) {
|
|
@@ -1,12 +1,37 @@
|
|
|
1
1
|
import { Response } from './response.js';
|
|
2
|
-
import { hex } from "@scure/base";
|
|
2
|
+
import { base64, hex } from "@scure/base";
|
|
3
|
+
import { SingleKey } from '../../identity/singleKey.js';
|
|
4
|
+
import { TreeSignerSession } from '../../tree/signingSession.js';
|
|
5
|
+
import { Transaction } from "@scure/btc-signer";
|
|
3
6
|
class UnexpectedResponseError extends Error {
|
|
4
7
|
constructor(response) {
|
|
5
8
|
super(`Unexpected response type. Got: ${JSON.stringify(response, null, 2)}`);
|
|
6
9
|
this.name = "UnexpectedResponseError";
|
|
7
10
|
}
|
|
8
11
|
}
|
|
9
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Service Worker-based wallet implementation for browser environments.
|
|
14
|
+
*
|
|
15
|
+
* This wallet uses a service worker as a backend to handle wallet logic,
|
|
16
|
+
* providing secure key storage and transaction signing in web applications.
|
|
17
|
+
* The service worker runs in a separate thread and can persist data between
|
|
18
|
+
* browser sessions.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* // Create and initialize the service worker wallet
|
|
23
|
+
* const serviceWorker = await setupServiceWorker("/service-worker.js");
|
|
24
|
+
* const wallet = new ServiceWorkerWallet(serviceWorker);
|
|
25
|
+
* await wallet.init({
|
|
26
|
+
* privateKey: 'your_private_key_hex',
|
|
27
|
+
* arkServerUrl: 'https://ark.example.com'
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Use like any other wallet
|
|
31
|
+
* const address = await wallet.getAddress();
|
|
32
|
+
* const balance = await wallet.getBalance();
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
10
35
|
export class ServiceWorkerWallet {
|
|
11
36
|
constructor(serviceWorker) {
|
|
12
37
|
this.serviceWorker = serviceWorker;
|
|
@@ -41,11 +66,14 @@ export class ServiceWorkerWallet {
|
|
|
41
66
|
type: "INIT_WALLET",
|
|
42
67
|
id: getRandomId(),
|
|
43
68
|
privateKey: config.privateKey,
|
|
44
|
-
|
|
45
|
-
arkServerUrl: config.arkServerUrl || "",
|
|
69
|
+
arkServerUrl: config.arkServerUrl,
|
|
46
70
|
arkServerPublicKey: config.arkServerPublicKey,
|
|
47
71
|
};
|
|
48
72
|
await this.sendMessage(message);
|
|
73
|
+
const privKeyBytes = hex.decode(config.privateKey);
|
|
74
|
+
// cache the identity xOnlyPublicKey
|
|
75
|
+
this.cachedXOnlyPublicKey =
|
|
76
|
+
SingleKey.fromPrivateKey(privKeyBytes).xOnlyPublicKey();
|
|
49
77
|
}
|
|
50
78
|
async clear() {
|
|
51
79
|
const message = {
|
|
@@ -53,6 +81,8 @@ export class ServiceWorkerWallet {
|
|
|
53
81
|
id: getRandomId(),
|
|
54
82
|
};
|
|
55
83
|
await this.sendMessage(message);
|
|
84
|
+
// clear the cached xOnlyPublicKey
|
|
85
|
+
this.cachedXOnlyPublicKey = undefined;
|
|
56
86
|
}
|
|
57
87
|
// send a message and wait for a response
|
|
58
88
|
async sendMessage(message) {
|
|
@@ -86,7 +116,7 @@ export class ServiceWorkerWallet {
|
|
|
86
116
|
try {
|
|
87
117
|
const response = await this.sendMessage(message);
|
|
88
118
|
if (Response.isAddress(response)) {
|
|
89
|
-
return response.
|
|
119
|
+
return response.address;
|
|
90
120
|
}
|
|
91
121
|
throw new UnexpectedResponseError(response);
|
|
92
122
|
}
|
|
@@ -94,20 +124,20 @@ export class ServiceWorkerWallet {
|
|
|
94
124
|
throw new Error(`Failed to get address: ${error}`);
|
|
95
125
|
}
|
|
96
126
|
}
|
|
97
|
-
async
|
|
127
|
+
async getBoardingAddress() {
|
|
98
128
|
const message = {
|
|
99
|
-
type: "
|
|
129
|
+
type: "GET_BOARDING_ADDRESS",
|
|
100
130
|
id: getRandomId(),
|
|
101
131
|
};
|
|
102
132
|
try {
|
|
103
133
|
const response = await this.sendMessage(message);
|
|
104
|
-
if (Response.
|
|
105
|
-
return response.
|
|
134
|
+
if (Response.isBoardingAddress(response)) {
|
|
135
|
+
return response.address;
|
|
106
136
|
}
|
|
107
137
|
throw new UnexpectedResponseError(response);
|
|
108
138
|
}
|
|
109
139
|
catch (error) {
|
|
110
|
-
throw new Error(`Failed to get address
|
|
140
|
+
throw new Error(`Failed to get boarding address: ${error}`);
|
|
111
141
|
}
|
|
112
142
|
}
|
|
113
143
|
async getBalance() {
|
|
@@ -126,26 +156,11 @@ export class ServiceWorkerWallet {
|
|
|
126
156
|
throw new Error(`Failed to get balance: ${error}`);
|
|
127
157
|
}
|
|
128
158
|
}
|
|
129
|
-
async
|
|
130
|
-
const message = {
|
|
131
|
-
type: "GET_COINS",
|
|
132
|
-
id: getRandomId(),
|
|
133
|
-
};
|
|
134
|
-
try {
|
|
135
|
-
const response = await this.sendMessage(message);
|
|
136
|
-
if (Response.isCoins(response)) {
|
|
137
|
-
return response.coins;
|
|
138
|
-
}
|
|
139
|
-
throw new UnexpectedResponseError(response);
|
|
140
|
-
}
|
|
141
|
-
catch (error) {
|
|
142
|
-
throw new Error(`Failed to get coins: ${error}`);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
async getVtxos() {
|
|
159
|
+
async getVtxos(filter) {
|
|
146
160
|
const message = {
|
|
147
161
|
type: "GET_VTXOS",
|
|
148
162
|
id: getRandomId(),
|
|
163
|
+
filter,
|
|
149
164
|
};
|
|
150
165
|
try {
|
|
151
166
|
const response = await this.sendMessage(message);
|
|
@@ -174,11 +189,10 @@ export class ServiceWorkerWallet {
|
|
|
174
189
|
throw new Error(`Failed to get boarding UTXOs: ${error}`);
|
|
175
190
|
}
|
|
176
191
|
}
|
|
177
|
-
async sendBitcoin(params
|
|
192
|
+
async sendBitcoin(params) {
|
|
178
193
|
const message = {
|
|
179
194
|
type: "SEND_BITCOIN",
|
|
180
195
|
params,
|
|
181
|
-
zeroFee,
|
|
182
196
|
id: getRandomId(),
|
|
183
197
|
};
|
|
184
198
|
try {
|
|
@@ -245,21 +259,34 @@ export class ServiceWorkerWallet {
|
|
|
245
259
|
throw new Error(`Failed to get transaction history: ${error}`);
|
|
246
260
|
}
|
|
247
261
|
}
|
|
248
|
-
|
|
262
|
+
xOnlyPublicKey() {
|
|
263
|
+
if (!this.cachedXOnlyPublicKey) {
|
|
264
|
+
throw new Error("Wallet not initialized");
|
|
265
|
+
}
|
|
266
|
+
return this.cachedXOnlyPublicKey;
|
|
267
|
+
}
|
|
268
|
+
signerSession() {
|
|
269
|
+
return TreeSignerSession.random();
|
|
270
|
+
}
|
|
271
|
+
async sign(tx, inputIndexes) {
|
|
249
272
|
const message = {
|
|
250
|
-
type: "
|
|
251
|
-
|
|
273
|
+
type: "SIGN",
|
|
274
|
+
tx: base64.encode(tx.toPSBT()),
|
|
275
|
+
inputIndexes,
|
|
252
276
|
id: getRandomId(),
|
|
253
277
|
};
|
|
254
278
|
try {
|
|
255
279
|
const response = await this.sendMessage(message);
|
|
256
|
-
if (response
|
|
257
|
-
return
|
|
280
|
+
if (Response.isSignSuccess(response)) {
|
|
281
|
+
return Transaction.fromPSBT(base64.decode(response.tx), {
|
|
282
|
+
allowUnknown: true,
|
|
283
|
+
allowUnknownInputs: true,
|
|
284
|
+
});
|
|
258
285
|
}
|
|
259
286
|
throw new UnexpectedResponseError(response);
|
|
260
287
|
}
|
|
261
288
|
catch (error) {
|
|
262
|
-
throw new Error(`Failed to
|
|
289
|
+
throw new Error(`Failed to sign: ${error}`);
|
|
263
290
|
}
|
|
264
291
|
}
|
|
265
292
|
}
|