@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.
Files changed (42) hide show
  1. package/CHANGELOG.md +585 -0
  2. package/package.json +5 -5
  3. package/src/BitcoinLocalStorageCache.cjs +0 -16
  4. package/src/BitcoinLocalStorageCache.d.ts +0 -7
  5. package/src/BitcoinLocalStorageCache.js +0 -16
  6. package/src/connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.cjs +70 -23
  7. package/src/connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.d.ts +4 -2
  8. package/src/connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.js +71 -24
  9. package/src/connectors/BitcoinWalletConnector.cjs +64 -31
  10. package/src/connectors/BitcoinWalletConnector.d.ts +13 -5
  11. package/src/connectors/BitcoinWalletConnector.js +65 -32
  12. package/src/connectors/FallbackBitcoinConnector/FallbackBitcoinConnector.cjs +7 -1
  13. package/src/connectors/FallbackBitcoinConnector/FallbackBitcoinConnector.d.ts +1 -1
  14. package/src/connectors/FallbackBitcoinConnector/FallbackBitcoinConnector.js +7 -1
  15. package/src/connectors/OkxConnector/OkxConnector.cjs +19 -2
  16. package/src/connectors/OkxConnector/OkxConnector.d.ts +1 -1
  17. package/src/connectors/OkxConnector/OkxConnector.js +19 -2
  18. package/src/connectors/PhantomConnector/PhantomConnector.cjs +13 -9
  19. package/src/connectors/PhantomConnector/PhantomConnector.d.ts +1 -1
  20. package/src/connectors/PhantomConnector/PhantomConnector.js +13 -9
  21. package/src/connectors/UnisatConnector/UnisatConnector.cjs +26 -1
  22. package/src/connectors/UnisatConnector/UnisatConnector.d.ts +2 -1
  23. package/src/connectors/UnisatConnector/UnisatConnector.js +26 -1
  24. package/src/connectors/UnknownInjected/UnknownInjected.cjs +7 -1
  25. package/src/connectors/UnknownInjected/UnknownInjected.d.ts +1 -1
  26. package/src/connectors/UnknownInjected/UnknownInjected.js +7 -1
  27. package/src/index.cjs +4 -0
  28. package/src/index.d.ts +3 -2
  29. package/src/index.js +2 -0
  30. package/src/utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.cjs +1 -1
  31. package/src/utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.js +1 -1
  32. package/src/utils/psbt/createSignPsbtOptions.cjs +17 -1
  33. package/src/utils/psbt/createSignPsbtOptions.d.ts +2 -0
  34. package/src/utils/psbt/createSignPsbtOptions.js +17 -2
  35. package/src/wallet/BitcoinWallet.cjs +54 -0
  36. package/src/wallet/BitcoinWallet.d.ts +27 -0
  37. package/src/wallet/BitcoinWallet.js +50 -0
  38. package/src/wallet/index.d.ts +2 -0
  39. package/src/wallet/isBitcoinWallet/index.d.ts +1 -0
  40. package/src/wallet/isBitcoinWallet/isBitcoinWallet.cjs +8 -0
  41. package/src/wallet/isBitcoinWallet/isBitcoinWallet.d.ts +3 -0
  42. 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.6",
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.470",
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.6",
36
- "@dynamic-labs/wallet-book": "3.0.0-alpha.6",
37
- "@dynamic-labs/wallet-connector-core": "3.0.0-alpha.6",
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() && !this.isInstalledOnBrowser() && inAppBrowserUrl) {
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
- signMessage(messageToSign) {
83
+ signMessageWithAddress(messageToSign, address) {
85
84
  return _tslib.__awaiter(this, void 0, void 0, function* () {
86
- const [walletAddress] = yield this.getConnectedAccounts();
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: walletAddress,
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, _b, _c, _d;
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() && !this.isInstalledOnBrowser() && inAppBrowserUrl) {
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
- signMessage(messageToSign) {
79
+ signMessageWithAddress(messageToSign, address) {
81
80
  return __awaiter(this, void 0, void 0, function* () {
82
- const [walletAddress] = yield this.getConnectedAccounts();
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: walletAddress,
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, _b, _c, _d;
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
- this.bitcoinProviderHelper = new bitcoinProviderHelper.BitcoinProviderHelper(opts.walletData || walletBook.getWalletBookWallet(this.walletBook, this.key));
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 Promise.all([
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
- var _a, _b;
65
- const [connectedAddress] = yield this.getConnectedAccounts();
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 this.cache.getLastBalance();
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
- return;
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('sendRawTransaction - No connected address found!');
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) => (account.purpose === 'ordinals' ? -1 : 1))
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 (currentConnectedAccounts[0] === connectedAccounts[0]) {
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;