@dynamic-labs/bitcoin 3.0.0-alpha.6 → 3.0.0-alpha.60
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/CHANGELOG.md +585 -0
- package/package.json +5 -5
- package/src/BitcoinLocalStorageCache.cjs +0 -16
- package/src/BitcoinLocalStorageCache.d.ts +0 -7
- package/src/BitcoinLocalStorageCache.js +0 -16
- package/src/connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.cjs +70 -23
- package/src/connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.d.ts +4 -2
- package/src/connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.js +71 -24
- package/src/connectors/BitcoinWalletConnector.cjs +64 -31
- package/src/connectors/BitcoinWalletConnector.d.ts +13 -5
- package/src/connectors/BitcoinWalletConnector.js +65 -32
- package/src/connectors/FallbackBitcoinConnector/FallbackBitcoinConnector.cjs +7 -1
- package/src/connectors/FallbackBitcoinConnector/FallbackBitcoinConnector.d.ts +1 -1
- package/src/connectors/FallbackBitcoinConnector/FallbackBitcoinConnector.js +7 -1
- package/src/connectors/OkxConnector/OkxConnector.cjs +19 -2
- package/src/connectors/OkxConnector/OkxConnector.d.ts +1 -1
- package/src/connectors/OkxConnector/OkxConnector.js +19 -2
- package/src/connectors/PhantomConnector/PhantomConnector.cjs +13 -9
- package/src/connectors/PhantomConnector/PhantomConnector.d.ts +1 -1
- package/src/connectors/PhantomConnector/PhantomConnector.js +13 -9
- package/src/connectors/UnisatConnector/UnisatConnector.cjs +26 -1
- package/src/connectors/UnisatConnector/UnisatConnector.d.ts +2 -1
- package/src/connectors/UnisatConnector/UnisatConnector.js +26 -1
- package/src/connectors/UnknownInjected/UnknownInjected.cjs +7 -1
- package/src/connectors/UnknownInjected/UnknownInjected.d.ts +1 -1
- package/src/connectors/UnknownInjected/UnknownInjected.js +7 -1
- package/src/index.cjs +4 -0
- package/src/index.d.ts +3 -2
- package/src/index.js +2 -0
- package/src/utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.cjs +1 -1
- package/src/utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.js +1 -1
- package/src/utils/psbt/createSignPsbtOptions.cjs +17 -1
- package/src/utils/psbt/createSignPsbtOptions.d.ts +2 -0
- package/src/utils/psbt/createSignPsbtOptions.js +17 -2
- package/src/wallet/BitcoinWallet.cjs +54 -0
- package/src/wallet/BitcoinWallet.d.ts +27 -0
- package/src/wallet/BitcoinWallet.js +50 -0
- package/src/wallet/index.d.ts +2 -0
- package/src/wallet/isBitcoinWallet/index.d.ts +1 -0
- package/src/wallet/isBitcoinWallet/isBitcoinWallet.cjs +8 -0
- package/src/wallet/isBitcoinWallet/isBitcoinWallet.d.ts +3 -0
- package/src/wallet/isBitcoinWallet/isBitcoinWallet.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/bitcoin",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.60",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/dynamic-labs/dynamic-auth.git",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@btckit/types": "0.0.19",
|
|
30
|
-
"@dynamic-labs/sdk-api-core": "0.0.
|
|
30
|
+
"@dynamic-labs/sdk-api-core": "0.0.526",
|
|
31
31
|
"@wallet-standard/app": "1.0.1",
|
|
32
32
|
"@wallet-standard/base": "1.0.1",
|
|
33
33
|
"bitcoinjs-lib": "6.1.5",
|
|
34
34
|
"sats-connect": "2.0.0",
|
|
35
|
-
"@dynamic-labs/utils": "3.0.0-alpha.
|
|
36
|
-
"@dynamic-labs/wallet-book": "3.0.0-alpha.
|
|
37
|
-
"@dynamic-labs/wallet-connector-core": "3.0.0-alpha.
|
|
35
|
+
"@dynamic-labs/utils": "3.0.0-alpha.60",
|
|
36
|
+
"@dynamic-labs/wallet-book": "3.0.0-alpha.60",
|
|
37
|
+
"@dynamic-labs/wallet-connector-core": "3.0.0-alpha.60",
|
|
38
38
|
"stream": "0.0.2"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {}
|
|
@@ -9,7 +9,6 @@ var utils = require('@dynamic-labs/utils');
|
|
|
9
9
|
class BitcoinLocalStorageCache {
|
|
10
10
|
constructor(key) {
|
|
11
11
|
this.CONNECTED_ACCOUNTS_KEY = `bitcoin_${key}_connectedAccounts`;
|
|
12
|
-
this.LAST_BALANCE_KEY = `bitcoin_${key}_lastBalance`;
|
|
13
12
|
}
|
|
14
13
|
getActiveAccount() {
|
|
15
14
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -63,21 +62,6 @@ class BitcoinLocalStorageCache {
|
|
|
63
62
|
return utils.removeItemAsync(this.CONNECTED_ACCOUNTS_KEY);
|
|
64
63
|
});
|
|
65
64
|
}
|
|
66
|
-
getLastBalance() {
|
|
67
|
-
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
68
|
-
return utils.getItemAsync(this.LAST_BALANCE_KEY);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
setLastBalance(balance) {
|
|
72
|
-
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
73
|
-
return utils.setItemAsync(this.LAST_BALANCE_KEY, balance);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
clearLastBalance() {
|
|
77
|
-
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
78
|
-
return utils.removeItemAsync(this.LAST_BALANCE_KEY);
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
65
|
}
|
|
82
66
|
|
|
83
67
|
exports.BitcoinLocalStorageCache = BitcoinLocalStorageCache;
|
|
@@ -9,16 +9,12 @@ type BitcoinActiveAccount = {
|
|
|
9
9
|
};
|
|
10
10
|
export declare class BitcoinLocalStorageCache implements IBitcoinSessionCache {
|
|
11
11
|
private readonly CONNECTED_ACCOUNTS_KEY;
|
|
12
|
-
private readonly LAST_BALANCE_KEY;
|
|
13
12
|
constructor(key: string);
|
|
14
13
|
getActiveAccount(): Promise<BitcoinActiveAccount | undefined>;
|
|
15
14
|
getConnectedAccounts(): Promise<BitcoinConnectedAccounts | undefined>;
|
|
16
15
|
getConnectedAccount(address: string): Promise<BitcoinConnectedAccount | undefined>;
|
|
17
16
|
setConnectedAccount(addess: string, account: BitcoinConnectedAccount): Promise<void>;
|
|
18
17
|
clearConnectedAcccounts(): Promise<void>;
|
|
19
|
-
getLastBalance(): Promise<string | undefined>;
|
|
20
|
-
setLastBalance(balance: string): Promise<void>;
|
|
21
|
-
clearLastBalance(): Promise<void>;
|
|
22
18
|
}
|
|
23
19
|
export interface IBitcoinSessionCache {
|
|
24
20
|
clearConnectedAcccounts(): Promise<void>;
|
|
@@ -26,8 +22,5 @@ export interface IBitcoinSessionCache {
|
|
|
26
22
|
getConnectedAccount(address: string): Promise<BitcoinConnectedAccount | undefined>;
|
|
27
23
|
getConnectedAccounts(): Promise<BitcoinConnectedAccounts | undefined>;
|
|
28
24
|
setConnectedAccount(addess: string, account: BitcoinConnectedAccount): Promise<void>;
|
|
29
|
-
clearLastBalance(): Promise<void>;
|
|
30
|
-
getLastBalance(): Promise<string | undefined>;
|
|
31
|
-
setLastBalance(balance: string): Promise<void>;
|
|
32
25
|
}
|
|
33
26
|
export {};
|
|
@@ -5,7 +5,6 @@ import { getItemAsync, setItemAsync, removeItemAsync } from '@dynamic-labs/utils
|
|
|
5
5
|
class BitcoinLocalStorageCache {
|
|
6
6
|
constructor(key) {
|
|
7
7
|
this.CONNECTED_ACCOUNTS_KEY = `bitcoin_${key}_connectedAccounts`;
|
|
8
|
-
this.LAST_BALANCE_KEY = `bitcoin_${key}_lastBalance`;
|
|
9
8
|
}
|
|
10
9
|
getActiveAccount() {
|
|
11
10
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -59,21 +58,6 @@ class BitcoinLocalStorageCache {
|
|
|
59
58
|
return removeItemAsync(this.CONNECTED_ACCOUNTS_KEY);
|
|
60
59
|
});
|
|
61
60
|
}
|
|
62
|
-
getLastBalance() {
|
|
63
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
return getItemAsync(this.LAST_BALANCE_KEY);
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
setLastBalance(balance) {
|
|
68
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
-
return setItemAsync(this.LAST_BALANCE_KEY, balance);
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
clearLastBalance() {
|
|
73
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
-
return removeItemAsync(this.LAST_BALANCE_KEY);
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
61
|
}
|
|
78
62
|
|
|
79
63
|
export { BitcoinLocalStorageCache };
|
|
@@ -11,18 +11,14 @@ var walletBook = require('@dynamic-labs/wallet-book');
|
|
|
11
11
|
var _const = require('../../const.cjs');
|
|
12
12
|
require('@dynamic-labs/wallet-connector-core');
|
|
13
13
|
var BitcoinWalletConnector = require('../BitcoinWalletConnector.cjs');
|
|
14
|
-
var validatePsbt = require('../../utils/psbt/validator/validatePsbt.cjs');
|
|
15
|
-
var getSigHashType = require('../../utils/psbt/getSigHashType.cjs');
|
|
16
14
|
var bitcoinNetworkTypeToNetworks = require('../../utils/psbt/bitcoinNetworkTypeToNetworks.cjs');
|
|
15
|
+
var createSignPsbtOptions = require('../../utils/psbt/createSignPsbtOptions.cjs');
|
|
17
16
|
var supportsSatsConnect = require('../../utils/supportsSatsConnect.cjs');
|
|
18
17
|
|
|
19
18
|
class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletConnector {
|
|
20
19
|
constructor(opts) {
|
|
21
20
|
super(opts);
|
|
22
21
|
this.currentNetwork = satsConnect.BitcoinNetworkType.Mainnet;
|
|
23
|
-
// satsconnect wallets don't support fetching connected accounts without prompting
|
|
24
|
-
// for a connection, so we handle getConnectedAccounts differently.
|
|
25
|
-
this.canFetchConnectedAccounts = false;
|
|
26
22
|
}
|
|
27
23
|
getAddress() {
|
|
28
24
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -37,7 +33,10 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletCo
|
|
|
37
33
|
}
|
|
38
34
|
const wallet = walletBook.findWalletBookWallet(this.walletBook, this.key);
|
|
39
35
|
const inAppBrowserUrl = (_a = wallet === null || wallet === void 0 ? void 0 : wallet.mobile) === null || _a === void 0 ? void 0 : _a.inAppBrowser;
|
|
40
|
-
if (utils.isMobile() &&
|
|
36
|
+
if (utils.isMobile() &&
|
|
37
|
+
!this.isInstalledOnBrowser() &&
|
|
38
|
+
inAppBrowserUrl &&
|
|
39
|
+
this.mobileExperience === 'in-app-browser') {
|
|
41
40
|
const inAppBrowserTemplate = utils.template(inAppBrowserUrl);
|
|
42
41
|
const deepLink = inAppBrowserTemplate({
|
|
43
42
|
encodedDappURI: encodeURIComponent(window.location.toString()),
|
|
@@ -81,10 +80,9 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletCo
|
|
|
81
80
|
});
|
|
82
81
|
});
|
|
83
82
|
}
|
|
84
|
-
|
|
83
|
+
signMessageWithAddress(messageToSign, address) {
|
|
85
84
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
86
|
-
|
|
87
|
-
if (!walletAddress || !supportsSatsConnect.supportsSatsConnect(this)) {
|
|
85
|
+
if (!supportsSatsConnect.supportsSatsConnect(this)) {
|
|
88
86
|
return;
|
|
89
87
|
}
|
|
90
88
|
return new Promise((resolve, reject) => {
|
|
@@ -109,7 +107,7 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletCo
|
|
|
109
107
|
resolve(response);
|
|
110
108
|
}),
|
|
111
109
|
payload: {
|
|
112
|
-
address
|
|
110
|
+
address,
|
|
113
111
|
message: messageToSign,
|
|
114
112
|
network: {
|
|
115
113
|
type: this.currentNetwork,
|
|
@@ -119,6 +117,15 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletCo
|
|
|
119
117
|
});
|
|
120
118
|
});
|
|
121
119
|
}
|
|
120
|
+
signMessage(messageToSign) {
|
|
121
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
122
|
+
const [walletAddress] = yield this.getConnectedAccounts();
|
|
123
|
+
if (!walletAddress) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
return this.signMessageWithAddress(messageToSign, walletAddress);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
122
129
|
sendBitcoin(transaction) {
|
|
123
130
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
124
131
|
var _a;
|
|
@@ -187,29 +194,44 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletCo
|
|
|
187
194
|
});
|
|
188
195
|
});
|
|
189
196
|
}
|
|
197
|
+
signTransactions(transactions) {
|
|
198
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
const { message, psbts, network } = transactions;
|
|
200
|
+
return new Promise((resolve, reject) => {
|
|
201
|
+
satsConnect.signMultipleTransactions({
|
|
202
|
+
getProvider: () => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
203
|
+
var _a, _b;
|
|
204
|
+
return (_b = (_a = this.wallet) === null || _a === void 0 ? void 0 : _a.features[_const.SATSCONNECT_FEATURE]) === null || _b === void 0 ? void 0 : _b.provider;
|
|
205
|
+
}),
|
|
206
|
+
onCancel: () => {
|
|
207
|
+
const error = new Error();
|
|
208
|
+
error.code = '-32000'; // error code for user cancelled
|
|
209
|
+
reject(error);
|
|
210
|
+
},
|
|
211
|
+
onFinish: (response) => {
|
|
212
|
+
resolve(response);
|
|
213
|
+
},
|
|
214
|
+
payload: {
|
|
215
|
+
message: message || 'Sign Transaction',
|
|
216
|
+
network,
|
|
217
|
+
psbts,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
}
|
|
190
223
|
signPsbt(request) {
|
|
191
224
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
192
|
-
var _a
|
|
225
|
+
var _a;
|
|
193
226
|
if (!((_a = request.allowedSighash) === null || _a === void 0 ? void 0 : _a.length))
|
|
194
227
|
throw new Error('allowedSighash cannot be an empty array');
|
|
195
228
|
const network = bitcoinNetworkTypeToNetworks.convertNetworkTypeForPsbt(this.currentNetwork);
|
|
196
229
|
const psbtFromBase64 = bitcoinjsLib.Psbt.fromBase64(request.unsignedPsbtBase64, {
|
|
197
230
|
network,
|
|
198
231
|
});
|
|
199
|
-
if ((_b = request.signature) === null || _b === void 0 ? void 0 : _b.length) {
|
|
200
|
-
validatePsbt.validatePsbt(psbtFromBase64, request.allowedSighash, request.signature);
|
|
201
|
-
}
|
|
202
|
-
const inputsToSign = ((_d = (_c = request.signature) === null || _c === void 0 ? void 0 : _c.map((sig) => {
|
|
203
|
-
var _a;
|
|
204
|
-
return ((_a = sig.signingIndexes) !== null && _a !== void 0 ? _a : []).map((inputIndex) => ({
|
|
205
|
-
address: sig.address,
|
|
206
|
-
sigHash: getSigHashType.getSigHashType(psbtFromBase64.data.inputs[inputIndex]),
|
|
207
|
-
signingIndexes: [inputIndex],
|
|
208
|
-
}));
|
|
209
|
-
})) !== null && _d !== void 0 ? _d : []).flat();
|
|
210
232
|
const signedPsbt = yield this.signTransaction({
|
|
211
233
|
broadcast: false,
|
|
212
|
-
inputsToSign,
|
|
234
|
+
inputsToSign: createSignPsbtOptions.createSignPsbtOptionsForSatsConnect(psbtFromBase64, request),
|
|
213
235
|
psbtBase64: request.unsignedPsbtBase64,
|
|
214
236
|
});
|
|
215
237
|
if (!signedPsbt) {
|
|
@@ -218,6 +240,31 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletCo
|
|
|
218
240
|
return { signedPsbt: signedPsbt.psbtBase64 };
|
|
219
241
|
});
|
|
220
242
|
}
|
|
243
|
+
signPsbts(requests) {
|
|
244
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
245
|
+
var _a;
|
|
246
|
+
const network = bitcoinNetworkTypeToNetworks.convertNetworkTypeForPsbt(this.currentNetwork);
|
|
247
|
+
const signMultipleTransactionPayload = {
|
|
248
|
+
message: 'Sign Transaction',
|
|
249
|
+
network: {
|
|
250
|
+
type: this.currentNetwork,
|
|
251
|
+
},
|
|
252
|
+
psbts: [],
|
|
253
|
+
};
|
|
254
|
+
for (const request of requests) {
|
|
255
|
+
const psbtFromBase64 = bitcoinjsLib.Psbt.fromBase64(request.unsignedPsbtBase64, {
|
|
256
|
+
network,
|
|
257
|
+
});
|
|
258
|
+
const inputsToSign = createSignPsbtOptions.createSignPsbtOptionsForSatsConnect(psbtFromBase64, request);
|
|
259
|
+
signMultipleTransactionPayload.psbts.push({
|
|
260
|
+
inputsToSign,
|
|
261
|
+
psbtBase64: request.unsignedPsbtBase64,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
const signedPsbts = yield this.signTransactions(signMultipleTransactionPayload);
|
|
265
|
+
return (_a = signedPsbts === null || signedPsbts === void 0 ? void 0 : signedPsbts.map((signedPsbts) => signedPsbts.psbtBase64)) !== null && _a !== void 0 ? _a : [];
|
|
266
|
+
});
|
|
267
|
+
}
|
|
221
268
|
}
|
|
222
269
|
|
|
223
270
|
exports.BitcoinSatsConnectConnector = BitcoinSatsConnectConnector;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { BitcoinNetworkType, SignTransactionResponse } from 'sats-connect';
|
|
1
|
+
import { BitcoinNetworkType, SignMultipleTransactionsPayload, SignTransactionResponse } from 'sats-connect';
|
|
2
2
|
import { BitcoinSignPsbtRequest, BitcoinSignPsbtResponse, BitcoinTransaction, SatsConnectSignTransactionInput } from '../../types';
|
|
3
3
|
import { BitcoinWalletConnector, BitcoinWalletConnectorOpts } from '../BitcoinWalletConnector';
|
|
4
4
|
export declare abstract class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
|
|
5
5
|
currentNetwork: BitcoinNetworkType;
|
|
6
|
-
canFetchConnectedAccounts: boolean;
|
|
7
6
|
constructor(opts: BitcoinWalletConnectorOpts);
|
|
8
7
|
getAddress(): Promise<string | undefined>;
|
|
8
|
+
signMessageWithAddress(messageToSign: string, address: string): Promise<string | undefined>;
|
|
9
9
|
signMessage(messageToSign: string): Promise<string | undefined>;
|
|
10
10
|
sendBitcoin(transaction: BitcoinTransaction): Promise<string | undefined>;
|
|
11
11
|
signTransaction(params: SatsConnectSignTransactionInput): Promise<SignTransactionResponse | undefined>;
|
|
12
|
+
signTransactions(transactions: SignMultipleTransactionsPayload): Promise<SignTransactionResponse[] | undefined>;
|
|
12
13
|
signPsbt(request: BitcoinSignPsbtRequest): Promise<BitcoinSignPsbtResponse | undefined>;
|
|
14
|
+
signPsbts(requests: BitcoinSignPsbtRequest[]): Promise<string[] | undefined>;
|
|
13
15
|
}
|
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { __awaiter } from '../../../_virtual/_tslib.js';
|
|
3
3
|
import { Psbt } from 'bitcoinjs-lib';
|
|
4
|
-
import { BitcoinNetworkType, getAddress, AddressPurpose, signMessage, sendBtcTransaction, signTransaction } from 'sats-connect';
|
|
4
|
+
import { BitcoinNetworkType, getAddress, AddressPurpose, signMessage, sendBtcTransaction, signTransaction, signMultipleTransactions } from 'sats-connect';
|
|
5
5
|
import { isMobile, template } from '@dynamic-labs/utils';
|
|
6
6
|
import { findWalletBookWallet } from '@dynamic-labs/wallet-book';
|
|
7
7
|
import { SATSCONNECT_FEATURE } from '../../const.js';
|
|
8
8
|
import '@dynamic-labs/wallet-connector-core';
|
|
9
9
|
import { BitcoinWalletConnector } from '../BitcoinWalletConnector.js';
|
|
10
|
-
import { validatePsbt } from '../../utils/psbt/validator/validatePsbt.js';
|
|
11
|
-
import { getSigHashType } from '../../utils/psbt/getSigHashType.js';
|
|
12
10
|
import { convertNetworkTypeForPsbt } from '../../utils/psbt/bitcoinNetworkTypeToNetworks.js';
|
|
11
|
+
import { createSignPsbtOptionsForSatsConnect } from '../../utils/psbt/createSignPsbtOptions.js';
|
|
13
12
|
import { supportsSatsConnect } from '../../utils/supportsSatsConnect.js';
|
|
14
13
|
|
|
15
14
|
class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
|
|
16
15
|
constructor(opts) {
|
|
17
16
|
super(opts);
|
|
18
17
|
this.currentNetwork = BitcoinNetworkType.Mainnet;
|
|
19
|
-
// satsconnect wallets don't support fetching connected accounts without prompting
|
|
20
|
-
// for a connection, so we handle getConnectedAccounts differently.
|
|
21
|
-
this.canFetchConnectedAccounts = false;
|
|
22
18
|
}
|
|
23
19
|
getAddress() {
|
|
24
20
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -33,7 +29,10 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
|
|
|
33
29
|
}
|
|
34
30
|
const wallet = findWalletBookWallet(this.walletBook, this.key);
|
|
35
31
|
const inAppBrowserUrl = (_a = wallet === null || wallet === void 0 ? void 0 : wallet.mobile) === null || _a === void 0 ? void 0 : _a.inAppBrowser;
|
|
36
|
-
if (isMobile() &&
|
|
32
|
+
if (isMobile() &&
|
|
33
|
+
!this.isInstalledOnBrowser() &&
|
|
34
|
+
inAppBrowserUrl &&
|
|
35
|
+
this.mobileExperience === 'in-app-browser') {
|
|
37
36
|
const inAppBrowserTemplate = template(inAppBrowserUrl);
|
|
38
37
|
const deepLink = inAppBrowserTemplate({
|
|
39
38
|
encodedDappURI: encodeURIComponent(window.location.toString()),
|
|
@@ -77,10 +76,9 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
|
|
|
77
76
|
});
|
|
78
77
|
});
|
|
79
78
|
}
|
|
80
|
-
|
|
79
|
+
signMessageWithAddress(messageToSign, address) {
|
|
81
80
|
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
-
|
|
83
|
-
if (!walletAddress || !supportsSatsConnect(this)) {
|
|
81
|
+
if (!supportsSatsConnect(this)) {
|
|
84
82
|
return;
|
|
85
83
|
}
|
|
86
84
|
return new Promise((resolve, reject) => {
|
|
@@ -105,7 +103,7 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
|
|
|
105
103
|
resolve(response);
|
|
106
104
|
}),
|
|
107
105
|
payload: {
|
|
108
|
-
address
|
|
106
|
+
address,
|
|
109
107
|
message: messageToSign,
|
|
110
108
|
network: {
|
|
111
109
|
type: this.currentNetwork,
|
|
@@ -115,6 +113,15 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
|
|
|
115
113
|
});
|
|
116
114
|
});
|
|
117
115
|
}
|
|
116
|
+
signMessage(messageToSign) {
|
|
117
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
118
|
+
const [walletAddress] = yield this.getConnectedAccounts();
|
|
119
|
+
if (!walletAddress) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
return this.signMessageWithAddress(messageToSign, walletAddress);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
118
125
|
sendBitcoin(transaction) {
|
|
119
126
|
return __awaiter(this, void 0, void 0, function* () {
|
|
120
127
|
var _a;
|
|
@@ -183,29 +190,44 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
|
|
|
183
190
|
});
|
|
184
191
|
});
|
|
185
192
|
}
|
|
193
|
+
signTransactions(transactions) {
|
|
194
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
195
|
+
const { message, psbts, network } = transactions;
|
|
196
|
+
return new Promise((resolve, reject) => {
|
|
197
|
+
signMultipleTransactions({
|
|
198
|
+
getProvider: () => __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
var _a, _b;
|
|
200
|
+
return (_b = (_a = this.wallet) === null || _a === void 0 ? void 0 : _a.features[SATSCONNECT_FEATURE]) === null || _b === void 0 ? void 0 : _b.provider;
|
|
201
|
+
}),
|
|
202
|
+
onCancel: () => {
|
|
203
|
+
const error = new Error();
|
|
204
|
+
error.code = '-32000'; // error code for user cancelled
|
|
205
|
+
reject(error);
|
|
206
|
+
},
|
|
207
|
+
onFinish: (response) => {
|
|
208
|
+
resolve(response);
|
|
209
|
+
},
|
|
210
|
+
payload: {
|
|
211
|
+
message: message || 'Sign Transaction',
|
|
212
|
+
network,
|
|
213
|
+
psbts,
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
}
|
|
186
219
|
signPsbt(request) {
|
|
187
220
|
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
-
var _a
|
|
221
|
+
var _a;
|
|
189
222
|
if (!((_a = request.allowedSighash) === null || _a === void 0 ? void 0 : _a.length))
|
|
190
223
|
throw new Error('allowedSighash cannot be an empty array');
|
|
191
224
|
const network = convertNetworkTypeForPsbt(this.currentNetwork);
|
|
192
225
|
const psbtFromBase64 = Psbt.fromBase64(request.unsignedPsbtBase64, {
|
|
193
226
|
network,
|
|
194
227
|
});
|
|
195
|
-
if ((_b = request.signature) === null || _b === void 0 ? void 0 : _b.length) {
|
|
196
|
-
validatePsbt(psbtFromBase64, request.allowedSighash, request.signature);
|
|
197
|
-
}
|
|
198
|
-
const inputsToSign = ((_d = (_c = request.signature) === null || _c === void 0 ? void 0 : _c.map((sig) => {
|
|
199
|
-
var _a;
|
|
200
|
-
return ((_a = sig.signingIndexes) !== null && _a !== void 0 ? _a : []).map((inputIndex) => ({
|
|
201
|
-
address: sig.address,
|
|
202
|
-
sigHash: getSigHashType(psbtFromBase64.data.inputs[inputIndex]),
|
|
203
|
-
signingIndexes: [inputIndex],
|
|
204
|
-
}));
|
|
205
|
-
})) !== null && _d !== void 0 ? _d : []).flat();
|
|
206
228
|
const signedPsbt = yield this.signTransaction({
|
|
207
229
|
broadcast: false,
|
|
208
|
-
inputsToSign,
|
|
230
|
+
inputsToSign: createSignPsbtOptionsForSatsConnect(psbtFromBase64, request),
|
|
209
231
|
psbtBase64: request.unsignedPsbtBase64,
|
|
210
232
|
});
|
|
211
233
|
if (!signedPsbt) {
|
|
@@ -214,6 +236,31 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
|
|
|
214
236
|
return { signedPsbt: signedPsbt.psbtBase64 };
|
|
215
237
|
});
|
|
216
238
|
}
|
|
239
|
+
signPsbts(requests) {
|
|
240
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
241
|
+
var _a;
|
|
242
|
+
const network = convertNetworkTypeForPsbt(this.currentNetwork);
|
|
243
|
+
const signMultipleTransactionPayload = {
|
|
244
|
+
message: 'Sign Transaction',
|
|
245
|
+
network: {
|
|
246
|
+
type: this.currentNetwork,
|
|
247
|
+
},
|
|
248
|
+
psbts: [],
|
|
249
|
+
};
|
|
250
|
+
for (const request of requests) {
|
|
251
|
+
const psbtFromBase64 = Psbt.fromBase64(request.unsignedPsbtBase64, {
|
|
252
|
+
network,
|
|
253
|
+
});
|
|
254
|
+
const inputsToSign = createSignPsbtOptionsForSatsConnect(psbtFromBase64, request);
|
|
255
|
+
signMultipleTransactionPayload.psbts.push({
|
|
256
|
+
inputsToSign,
|
|
257
|
+
psbtBase64: request.unsignedPsbtBase64,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
const signedPsbts = yield this.signTransactions(signMultipleTransactionPayload);
|
|
261
|
+
return (_a = signedPsbts === null || signedPsbts === void 0 ? void 0 : signedPsbts.map((signedPsbts) => signedPsbts.psbtBase64)) !== null && _a !== void 0 ? _a : [];
|
|
262
|
+
});
|
|
263
|
+
}
|
|
217
264
|
}
|
|
218
265
|
|
|
219
266
|
export { BitcoinSatsConnectConnector };
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
5
|
|
|
6
6
|
var _tslib = require('../../_virtual/_tslib.cjs');
|
|
7
|
+
var satsConnect = require('sats-connect');
|
|
7
8
|
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
8
9
|
var walletBook = require('@dynamic-labs/wallet-book');
|
|
9
10
|
var utils = require('@dynamic-labs/utils');
|
|
@@ -13,11 +14,13 @@ var bitcoinProviderHelper = require('../bitcoinProviderHelper.cjs');
|
|
|
13
14
|
var getMempoolApiUrl = require('../utils/getMempoolApiUrl.cjs');
|
|
14
15
|
var _const = require('../const.cjs');
|
|
15
16
|
var satoshisToBtc = require('../utils/satoshisToBtc/satoshisToBtc.cjs');
|
|
17
|
+
var BitcoinWallet = require('../wallet/BitcoinWallet.cjs');
|
|
16
18
|
|
|
17
19
|
class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
18
20
|
constructor(opts) {
|
|
19
21
|
var _a;
|
|
20
22
|
super(opts);
|
|
23
|
+
this.ChainWallet = BitcoinWallet.BitcoinWallet;
|
|
21
24
|
this.connectedChain = 'BTC';
|
|
22
25
|
this.supportedChains = ['BTC'];
|
|
23
26
|
// some wallets don't support fetching connected accounts without prompting for a connection
|
|
@@ -26,12 +29,20 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
26
29
|
this.verifiedCredentials = [];
|
|
27
30
|
// this is the key from the wallet book entry so that we don't purely rely on the normalized name
|
|
28
31
|
this.overrideKey = (_a = opts.overrideKey) !== null && _a !== void 0 ? _a : this.key;
|
|
29
|
-
|
|
32
|
+
const walletBookWallet = opts.walletData || walletBook.getWalletBookWallet(this.walletBook, this.key);
|
|
33
|
+
this.bitcoinProviderHelper = new bitcoinProviderHelper.BitcoinProviderHelper(walletBookWallet);
|
|
30
34
|
this.wallet = this.bitcoinProviderHelper.findWallet();
|
|
31
35
|
if (this.wallet) {
|
|
32
36
|
this.walletMethods = this.bitcoinProviderHelper.getWalletMethods(this.wallet);
|
|
33
37
|
}
|
|
34
38
|
this.cache = new BitcoinLocalStorageCache.BitcoinLocalStorageCache(this.overrideKey);
|
|
39
|
+
this.canFetchConnectedAccounts = walletBook.isWalletMethodSupported(walletBookWallet, 'getConnectedAccounts', 'browserExtension');
|
|
40
|
+
}
|
|
41
|
+
isSameAccountChangeRequest(to) {
|
|
42
|
+
return this.lastAccountChange === to;
|
|
43
|
+
}
|
|
44
|
+
setLastAccountChangeRequest(to) {
|
|
45
|
+
this.lastAccountChange = to;
|
|
35
46
|
}
|
|
36
47
|
clearConnectedAccounts() {
|
|
37
48
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -53,34 +64,17 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
53
64
|
}
|
|
54
65
|
endSession() {
|
|
55
66
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
56
|
-
yield
|
|
57
|
-
this.cache.clearConnectedAcccounts(),
|
|
58
|
-
this.cache.clearLastBalance(),
|
|
59
|
-
]);
|
|
67
|
+
yield this.cache.clearConnectedAcccounts();
|
|
60
68
|
});
|
|
61
69
|
}
|
|
62
|
-
getBalance() {
|
|
70
|
+
getBalance(address) {
|
|
63
71
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
if (!connectedAddress) {
|
|
67
|
-
throw new utils.DynamicError('getBalance - No connected address found!');
|
|
68
|
-
}
|
|
69
|
-
const additionalAddresses = yield this.getAdditionalAddresses(connectedAddress);
|
|
70
|
-
const ordinalsAdditionalAddress = (_a = additionalAddresses.find((address) => address.type === sdkApiCore.WalletAddressType.Ordinals)) === null || _a === void 0 ? void 0 : _a.address;
|
|
71
|
-
const paymentAdditionalAddress = (_b = additionalAddresses.find((address) => address.type === sdkApiCore.WalletAddressType.Payment)) === null || _b === void 0 ? void 0 : _b.address;
|
|
72
|
-
// Some BTC wallet connectors only have 1 address type. when this is the case, it would always be `ordinals`
|
|
73
|
-
// if a BTC walletConnector does NOT have a payment address, just use the ordinal address
|
|
74
|
-
const paymentAddress = paymentAdditionalAddress !== null && paymentAdditionalAddress !== void 0 ? paymentAdditionalAddress : ordinalsAdditionalAddress;
|
|
75
|
-
if (!paymentAddress) {
|
|
76
|
-
throw new utils.DynamicError('getBalance - No payment address found!');
|
|
77
|
-
}
|
|
78
|
-
const API_URL = getMempoolApiUrl.getMempoolApiUrl(paymentAddress);
|
|
79
|
-
const response = yield fetch(`${API_URL}/address/${paymentAddress}`);
|
|
72
|
+
const API_URL = getMempoolApiUrl.getMempoolApiUrl(address);
|
|
73
|
+
const response = yield fetch(`${API_URL}/address/${address}`);
|
|
80
74
|
if (!response.ok) {
|
|
81
75
|
// if the request fails due to rate limits, return cached value
|
|
82
76
|
if (response.status === _const.HTTP_STATUS_TOO_MANY_REQUESTS) {
|
|
83
|
-
return
|
|
77
|
+
return '0';
|
|
84
78
|
}
|
|
85
79
|
// new accounts not yet indexed will return a 404
|
|
86
80
|
if (response.status === _const.HTTP_STATUS_NOT_FOUND) {
|
|
@@ -97,7 +91,6 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
97
91
|
const unconfirmedBalanceInSats = Number(addressInfo.mempool_stats.funded_txo_sum) -
|
|
98
92
|
Number(addressInfo.mempool_stats.spent_txo_sum);
|
|
99
93
|
const balance = satoshisToBtc.satoshisToBtc(confirmedBalanceInSats + unconfirmedBalanceInSats);
|
|
100
|
-
yield this.cache.setLastBalance(balance.toString());
|
|
101
94
|
return balance.toString();
|
|
102
95
|
});
|
|
103
96
|
}
|
|
@@ -117,12 +110,12 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
117
110
|
];
|
|
118
111
|
});
|
|
119
112
|
}
|
|
120
|
-
getConnectedAccounts() {
|
|
113
|
+
getConnectedAccounts(options) {
|
|
121
114
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
122
115
|
// some wallets like xverse don't support fetching connected accounts
|
|
123
116
|
// without prompting for a connection
|
|
124
117
|
// to avoid this behavior, we cache the connected accounts
|
|
125
|
-
if (!this.canFetchConnectedAccounts) {
|
|
118
|
+
if (!this.canFetchConnectedAccounts && !(options === null || options === void 0 ? void 0 : options.forceFetch)) {
|
|
126
119
|
return this.getConnectedAccountsFromCache();
|
|
127
120
|
}
|
|
128
121
|
// if we decide that is ok to prompt for a connection when fetching connected accounts
|
|
@@ -164,11 +157,12 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
164
157
|
}
|
|
165
158
|
sendRawTransaction(rawTransaction) {
|
|
166
159
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
167
|
-
if (!rawTransaction)
|
|
168
|
-
|
|
160
|
+
if (!rawTransaction) {
|
|
161
|
+
throw new utils.DynamicError('No transaction specified!');
|
|
162
|
+
}
|
|
169
163
|
const [connectedAddress] = yield this.getConnectedAccounts();
|
|
170
164
|
if (!connectedAddress) {
|
|
171
|
-
throw new utils.DynamicError('
|
|
165
|
+
throw new utils.DynamicError('No connected address found!');
|
|
172
166
|
}
|
|
173
167
|
const API_URL = getMempoolApiUrl.getMempoolApiUrl(connectedAddress);
|
|
174
168
|
const response = yield fetch(`${API_URL}/tx`, {
|
|
@@ -194,6 +188,18 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
194
188
|
var _a;
|
|
195
189
|
return (_a = this.bitcoinProviderHelper) === null || _a === void 0 ? void 0 : _a.getProvider();
|
|
196
190
|
}
|
|
191
|
+
signPsbts(requests) {
|
|
192
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
193
|
+
const signedPsbtResponses = [];
|
|
194
|
+
for (const request of requests) {
|
|
195
|
+
const signedPsbtResponse = yield this.signPsbt(request);
|
|
196
|
+
if (signedPsbtResponse) {
|
|
197
|
+
signedPsbtResponses.push(signedPsbtResponse);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return signedPsbtResponses.map((response) => response.signedPsbt);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
197
203
|
setConnectedAccountWithAddresses(_a) {
|
|
198
204
|
return _tslib.__awaiter(this, arguments, void 0, function* ({ mainAddress, ordinalsAddress, paymentAddress, active, }) {
|
|
199
205
|
if (!mainAddress) {
|
|
@@ -228,18 +234,33 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
228
234
|
const { handleAccountChange, handleChainChange, handleDisconnect } = walletConnectorCore.eventListenerHandlers(this);
|
|
229
235
|
const handleBitcoinAccountChange = (accounts) => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
230
236
|
let connectedAccounts = accounts;
|
|
237
|
+
let ordinalsAccount, paymentAccount;
|
|
231
238
|
// if accounts is an array of objects, we need to parse them to return only addresses
|
|
232
239
|
// since ordinals is the main address we use, we should return it as the first address
|
|
233
240
|
if (typeof accounts[0] === 'object') {
|
|
234
241
|
connectedAccounts = accounts
|
|
235
|
-
.sort((account) =>
|
|
242
|
+
.sort((account) => account.purpose === satsConnect.AddressPurpose.Ordinals ? -1 : 1)
|
|
236
243
|
.map((account) => account.address);
|
|
244
|
+
[ordinalsAccount, paymentAccount] = connectedAccounts;
|
|
237
245
|
}
|
|
238
246
|
const currentConnectedAccounts = yield this.getConnectedAccountsFromCache();
|
|
239
247
|
// don't do anything if the connected accounts haven't changed
|
|
240
|
-
if
|
|
248
|
+
// or if the account change request is the same as previous request
|
|
249
|
+
if (currentConnectedAccounts[0] === connectedAccounts[0] ||
|
|
250
|
+
this.isSameAccountChangeRequest(connectedAccounts[0])) {
|
|
241
251
|
return;
|
|
242
252
|
}
|
|
253
|
+
// set the last account change request with the from and to addresses
|
|
254
|
+
// to ensure that the requests are not duplicated
|
|
255
|
+
this.setLastAccountChangeRequest(connectedAccounts[0]);
|
|
256
|
+
if (ordinalsAccount || paymentAccount) {
|
|
257
|
+
this.setConnectedAccountWithAddresses({
|
|
258
|
+
active: true,
|
|
259
|
+
mainAddress: ordinalsAccount !== null && ordinalsAccount !== void 0 ? ordinalsAccount : paymentAccount,
|
|
260
|
+
ordinalsAddress: ordinalsAccount,
|
|
261
|
+
paymentAddress: paymentAccount,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
243
264
|
handleAccountChange(connectedAccounts);
|
|
244
265
|
});
|
|
245
266
|
provider.on('accountsChanged', handleBitcoinAccountChange);
|
|
@@ -262,6 +283,18 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
262
283
|
isLedgerAddress(address) {
|
|
263
284
|
return utils.isLedgerAddressViaVerifiedCredentials(address, this.verifiedCredentials);
|
|
264
285
|
}
|
|
286
|
+
proveOwnership(address, messageToSign) {
|
|
287
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
288
|
+
return this.signMessageWithAddress(messageToSign, address);
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
signMessageWithAddress(messageToSign,
|
|
292
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
293
|
+
_address) {
|
|
294
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
295
|
+
return this.signMessage(messageToSign);
|
|
296
|
+
});
|
|
297
|
+
}
|
|
265
298
|
}
|
|
266
299
|
|
|
267
300
|
exports.BitcoinWalletConnector = BitcoinWalletConnector;
|