@dynamic-labs/bitcoin 3.0.0-alpha.5 → 3.0.0-alpha.50

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 (36) hide show
  1. package/CHANGELOG.md +463 -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/bitcoinProviderHelper.d.ts +4 -0
  7. package/src/connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.cjs +59 -28
  8. package/src/connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.d.ts +3 -2
  9. package/src/connectors/BitcoinSatsConnectConnector/BitcoinSatsConnectConnector.js +60 -29
  10. package/src/connectors/BitcoinWalletConnector.cjs +44 -23
  11. package/src/connectors/BitcoinWalletConnector.d.ts +5 -1
  12. package/src/connectors/BitcoinWalletConnector.js +45 -24
  13. package/src/connectors/FallbackBitcoinConnector/FallbackBitcoinConnector.cjs +44 -0
  14. package/src/connectors/FallbackBitcoinConnector/FallbackBitcoinConnector.d.ts +12 -0
  15. package/src/connectors/FallbackBitcoinConnector/FallbackBitcoinConnector.js +40 -0
  16. package/src/connectors/FallbackBitcoinConnector/index.d.ts +1 -0
  17. package/src/connectors/OkxConnector/OkxConnector.cjs +19 -2
  18. package/src/connectors/OkxConnector/OkxConnector.d.ts +1 -1
  19. package/src/connectors/OkxConnector/OkxConnector.js +19 -2
  20. package/src/connectors/PhantomConnector/PhantomConnector.cjs +1 -2
  21. package/src/connectors/PhantomConnector/PhantomConnector.d.ts +0 -1
  22. package/src/connectors/PhantomConnector/PhantomConnector.js +1 -2
  23. package/src/connectors/UnisatConnector/UnisatConnector.cjs +26 -1
  24. package/src/connectors/UnisatConnector/UnisatConnector.d.ts +2 -1
  25. package/src/connectors/UnisatConnector/UnisatConnector.js +26 -1
  26. package/src/connectors/UnknownInjected/UnknownInjected.cjs +7 -1
  27. package/src/connectors/UnknownInjected/UnknownInjected.d.ts +1 -1
  28. package/src/connectors/UnknownInjected/UnknownInjected.js +7 -1
  29. package/src/connectors/index.d.ts +1 -0
  30. package/src/index.cjs +2 -1
  31. package/src/index.js +2 -1
  32. package/src/utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.cjs +1 -1
  33. package/src/utils/fetchSatsConnectConnectors/fetchSatsConnectConnectors.js +1 -1
  34. package/src/utils/psbt/createSignPsbtOptions.cjs +17 -1
  35. package/src/utils/psbt/createSignPsbtOptions.d.ts +2 -0
  36. package/src/utils/psbt/createSignPsbtOptions.js +17 -2
@@ -6,29 +6,23 @@ Object.defineProperty(exports, '__esModule', { value: true });
6
6
  var _tslib = require('../../../_virtual/_tslib.cjs');
7
7
  var bitcoinjsLib = require('bitcoinjs-lib');
8
8
  var satsConnect = require('sats-connect');
9
- var sdkApiCore = require('@dynamic-labs/sdk-api-core');
10
9
  var utils = require('@dynamic-labs/utils');
11
10
  var walletBook = require('@dynamic-labs/wallet-book');
12
11
  var _const = require('../../const.cjs');
13
12
  require('@dynamic-labs/wallet-connector-core');
14
13
  var BitcoinWalletConnector = require('../BitcoinWalletConnector.cjs');
15
- var validatePsbt = require('../../utils/psbt/validator/validatePsbt.cjs');
16
- var getSigHashType = require('../../utils/psbt/getSigHashType.cjs');
17
14
  var bitcoinNetworkTypeToNetworks = require('../../utils/psbt/bitcoinNetworkTypeToNetworks.cjs');
15
+ var createSignPsbtOptions = require('../../utils/psbt/createSignPsbtOptions.cjs');
18
16
  var supportsSatsConnect = require('../../utils/supportsSatsConnect.cjs');
19
17
 
20
18
  class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletConnector {
21
19
  constructor(opts) {
22
20
  super(opts);
23
21
  this.currentNetwork = satsConnect.BitcoinNetworkType.Mainnet;
24
- this.canFetchConnectedAccounts = true;
25
- // xverse does't support fetching connected accounts without prompting
26
- // for a connection, so we handle getConnectedAccounts differently
27
- this.canFetchConnectedAccounts = this.key !== 'xverse';
28
22
  }
29
23
  getAddress() {
30
24
  return _tslib.__awaiter(this, void 0, void 0, function* () {
31
- var _a, _b;
25
+ var _a;
32
26
  // xverse doesn't support wallet standard, so we won't have a wallet object,
33
27
  // but it's already the default provider for sats-connect, so it's ok
34
28
  // for getProvider in getAddress to return undefined
@@ -39,7 +33,10 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletCo
39
33
  }
40
34
  const wallet = walletBook.findWalletBookWallet(this.walletBook, this.key);
41
35
  const inAppBrowserUrl = (_a = wallet === null || wallet === void 0 ? void 0 : wallet.mobile) === null || _a === void 0 ? void 0 : _a.inAppBrowser;
42
- if (utils.isMobile() && !this.isInstalledOnBrowser() && inAppBrowserUrl) {
36
+ if (utils.isMobile() &&
37
+ !this.isInstalledOnBrowser() &&
38
+ inAppBrowserUrl &&
39
+ this.mobileExperience === 'in-app-browser') {
43
40
  const inAppBrowserTemplate = utils.template(inAppBrowserUrl);
44
41
  const deepLink = inAppBrowserTemplate({
45
42
  encodedDappURI: encodeURIComponent(window.location.toString()),
@@ -47,12 +44,6 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletCo
47
44
  window.location.href = deepLink;
48
45
  return;
49
46
  }
50
- const cachedActiveAccount = yield this.cache.getActiveAccount();
51
- if (cachedActiveAccount) {
52
- const ordinalsAddress = cachedActiveAccount.additionalAddresses.find((address) => address.type === sdkApiCore.WalletAddressType.Ordinals);
53
- const paymentAddress = cachedActiveAccount.additionalAddresses.find((address) => address.type === sdkApiCore.WalletAddressType.Payment);
54
- return (_b = ordinalsAddress === null || ordinalsAddress === void 0 ? void 0 : ordinalsAddress.address) !== null && _b !== void 0 ? _b : paymentAddress === null || paymentAddress === void 0 ? void 0 : paymentAddress.address;
55
- }
56
47
  return new Promise((resolve, reject) => {
57
48
  satsConnect.getAddress({
58
49
  getProvider: () => _tslib.__awaiter(this, void 0, void 0, function* () {
@@ -195,29 +186,44 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletCo
195
186
  });
196
187
  });
197
188
  }
189
+ signTransactions(transactions) {
190
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
191
+ const { message, psbts, network } = transactions;
192
+ return new Promise((resolve, reject) => {
193
+ satsConnect.signMultipleTransactions({
194
+ getProvider: () => _tslib.__awaiter(this, void 0, void 0, function* () {
195
+ var _a, _b;
196
+ return (_b = (_a = this.wallet) === null || _a === void 0 ? void 0 : _a.features[_const.SATSCONNECT_FEATURE]) === null || _b === void 0 ? void 0 : _b.provider;
197
+ }),
198
+ onCancel: () => {
199
+ const error = new Error();
200
+ error.code = '-32000'; // error code for user cancelled
201
+ reject(error);
202
+ },
203
+ onFinish: (response) => {
204
+ resolve(response);
205
+ },
206
+ payload: {
207
+ message: message || 'Sign Transaction',
208
+ network,
209
+ psbts,
210
+ },
211
+ });
212
+ });
213
+ });
214
+ }
198
215
  signPsbt(request) {
199
216
  return _tslib.__awaiter(this, void 0, void 0, function* () {
200
- var _a, _b, _c, _d;
217
+ var _a;
201
218
  if (!((_a = request.allowedSighash) === null || _a === void 0 ? void 0 : _a.length))
202
219
  throw new Error('allowedSighash cannot be an empty array');
203
220
  const network = bitcoinNetworkTypeToNetworks.convertNetworkTypeForPsbt(this.currentNetwork);
204
221
  const psbtFromBase64 = bitcoinjsLib.Psbt.fromBase64(request.unsignedPsbtBase64, {
205
222
  network,
206
223
  });
207
- if ((_b = request.signature) === null || _b === void 0 ? void 0 : _b.length) {
208
- validatePsbt.validatePsbt(psbtFromBase64, request.allowedSighash, request.signature);
209
- }
210
- const inputsToSign = ((_d = (_c = request.signature) === null || _c === void 0 ? void 0 : _c.map((sig) => {
211
- var _a;
212
- return ((_a = sig.signingIndexes) !== null && _a !== void 0 ? _a : []).map((inputIndex) => ({
213
- address: sig.address,
214
- sigHash: getSigHashType.getSigHashType(psbtFromBase64.data.inputs[inputIndex]),
215
- signingIndexes: [inputIndex],
216
- }));
217
- })) !== null && _d !== void 0 ? _d : []).flat();
218
224
  const signedPsbt = yield this.signTransaction({
219
225
  broadcast: false,
220
- inputsToSign,
226
+ inputsToSign: createSignPsbtOptions.createSignPsbtOptionsForSatsConnect(psbtFromBase64, request),
221
227
  psbtBase64: request.unsignedPsbtBase64,
222
228
  });
223
229
  if (!signedPsbt) {
@@ -226,6 +232,31 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector.BitcoinWalletCo
226
232
  return { signedPsbt: signedPsbt.psbtBase64 };
227
233
  });
228
234
  }
235
+ signPsbts(requests) {
236
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
237
+ var _a;
238
+ const network = bitcoinNetworkTypeToNetworks.convertNetworkTypeForPsbt(this.currentNetwork);
239
+ const signMultipleTransactionPayload = {
240
+ message: 'Sign Transaction',
241
+ network: {
242
+ type: this.currentNetwork,
243
+ },
244
+ psbts: [],
245
+ };
246
+ for (const request of requests) {
247
+ const psbtFromBase64 = bitcoinjsLib.Psbt.fromBase64(request.unsignedPsbtBase64, {
248
+ network,
249
+ });
250
+ const inputsToSign = createSignPsbtOptions.createSignPsbtOptionsForSatsConnect(psbtFromBase64, request);
251
+ signMultipleTransactionPayload.psbts.push({
252
+ inputsToSign,
253
+ psbtBase64: request.unsignedPsbtBase64,
254
+ });
255
+ }
256
+ const signedPsbts = yield this.signTransactions(signMultipleTransactionPayload);
257
+ return (_a = signedPsbts === null || signedPsbts === void 0 ? void 0 : signedPsbts.map((signedPsbts) => signedPsbts.psbtBase64)) !== null && _a !== void 0 ? _a : [];
258
+ });
259
+ }
229
260
  }
230
261
 
231
262
  exports.BitcoinSatsConnectConnector = BitcoinSatsConnectConnector;
@@ -1,13 +1,14 @@
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>;
9
8
  signMessage(messageToSign: string): Promise<string | undefined>;
10
9
  sendBitcoin(transaction: BitcoinTransaction): Promise<string | undefined>;
11
10
  signTransaction(params: SatsConnectSignTransactionInput): Promise<SignTransactionResponse | undefined>;
11
+ signTransactions(transactions: SignMultipleTransactionsPayload): Promise<SignTransactionResponse[] | undefined>;
12
12
  signPsbt(request: BitcoinSignPsbtRequest): Promise<BitcoinSignPsbtResponse | undefined>;
13
+ signPsbts(requests: BitcoinSignPsbtRequest[]): Promise<string[] | undefined>;
13
14
  }
@@ -1,30 +1,24 @@
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';
5
- import { WalletAddressType } from '@dynamic-labs/sdk-api-core';
4
+ import { BitcoinNetworkType, getAddress, AddressPurpose, signMessage, sendBtcTransaction, signTransaction, signMultipleTransactions } from 'sats-connect';
6
5
  import { isMobile, template } from '@dynamic-labs/utils';
7
6
  import { findWalletBookWallet } from '@dynamic-labs/wallet-book';
8
7
  import { SATSCONNECT_FEATURE } from '../../const.js';
9
8
  import '@dynamic-labs/wallet-connector-core';
10
9
  import { BitcoinWalletConnector } from '../BitcoinWalletConnector.js';
11
- import { validatePsbt } from '../../utils/psbt/validator/validatePsbt.js';
12
- import { getSigHashType } from '../../utils/psbt/getSigHashType.js';
13
10
  import { convertNetworkTypeForPsbt } from '../../utils/psbt/bitcoinNetworkTypeToNetworks.js';
11
+ import { createSignPsbtOptionsForSatsConnect } from '../../utils/psbt/createSignPsbtOptions.js';
14
12
  import { supportsSatsConnect } from '../../utils/supportsSatsConnect.js';
15
13
 
16
14
  class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
17
15
  constructor(opts) {
18
16
  super(opts);
19
17
  this.currentNetwork = BitcoinNetworkType.Mainnet;
20
- this.canFetchConnectedAccounts = true;
21
- // xverse does't support fetching connected accounts without prompting
22
- // for a connection, so we handle getConnectedAccounts differently
23
- this.canFetchConnectedAccounts = this.key !== 'xverse';
24
18
  }
25
19
  getAddress() {
26
20
  return __awaiter(this, void 0, void 0, function* () {
27
- var _a, _b;
21
+ var _a;
28
22
  // xverse doesn't support wallet standard, so we won't have a wallet object,
29
23
  // but it's already the default provider for sats-connect, so it's ok
30
24
  // for getProvider in getAddress to return undefined
@@ -35,7 +29,10 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
35
29
  }
36
30
  const wallet = findWalletBookWallet(this.walletBook, this.key);
37
31
  const inAppBrowserUrl = (_a = wallet === null || wallet === void 0 ? void 0 : wallet.mobile) === null || _a === void 0 ? void 0 : _a.inAppBrowser;
38
- if (isMobile() && !this.isInstalledOnBrowser() && inAppBrowserUrl) {
32
+ if (isMobile() &&
33
+ !this.isInstalledOnBrowser() &&
34
+ inAppBrowserUrl &&
35
+ this.mobileExperience === 'in-app-browser') {
39
36
  const inAppBrowserTemplate = template(inAppBrowserUrl);
40
37
  const deepLink = inAppBrowserTemplate({
41
38
  encodedDappURI: encodeURIComponent(window.location.toString()),
@@ -43,12 +40,6 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
43
40
  window.location.href = deepLink;
44
41
  return;
45
42
  }
46
- const cachedActiveAccount = yield this.cache.getActiveAccount();
47
- if (cachedActiveAccount) {
48
- const ordinalsAddress = cachedActiveAccount.additionalAddresses.find((address) => address.type === WalletAddressType.Ordinals);
49
- const paymentAddress = cachedActiveAccount.additionalAddresses.find((address) => address.type === WalletAddressType.Payment);
50
- return (_b = ordinalsAddress === null || ordinalsAddress === void 0 ? void 0 : ordinalsAddress.address) !== null && _b !== void 0 ? _b : paymentAddress === null || paymentAddress === void 0 ? void 0 : paymentAddress.address;
51
- }
52
43
  return new Promise((resolve, reject) => {
53
44
  getAddress({
54
45
  getProvider: () => __awaiter(this, void 0, void 0, function* () {
@@ -191,29 +182,44 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
191
182
  });
192
183
  });
193
184
  }
185
+ signTransactions(transactions) {
186
+ return __awaiter(this, void 0, void 0, function* () {
187
+ const { message, psbts, network } = transactions;
188
+ return new Promise((resolve, reject) => {
189
+ signMultipleTransactions({
190
+ getProvider: () => __awaiter(this, void 0, void 0, function* () {
191
+ var _a, _b;
192
+ return (_b = (_a = this.wallet) === null || _a === void 0 ? void 0 : _a.features[SATSCONNECT_FEATURE]) === null || _b === void 0 ? void 0 : _b.provider;
193
+ }),
194
+ onCancel: () => {
195
+ const error = new Error();
196
+ error.code = '-32000'; // error code for user cancelled
197
+ reject(error);
198
+ },
199
+ onFinish: (response) => {
200
+ resolve(response);
201
+ },
202
+ payload: {
203
+ message: message || 'Sign Transaction',
204
+ network,
205
+ psbts,
206
+ },
207
+ });
208
+ });
209
+ });
210
+ }
194
211
  signPsbt(request) {
195
212
  return __awaiter(this, void 0, void 0, function* () {
196
- var _a, _b, _c, _d;
213
+ var _a;
197
214
  if (!((_a = request.allowedSighash) === null || _a === void 0 ? void 0 : _a.length))
198
215
  throw new Error('allowedSighash cannot be an empty array');
199
216
  const network = convertNetworkTypeForPsbt(this.currentNetwork);
200
217
  const psbtFromBase64 = Psbt.fromBase64(request.unsignedPsbtBase64, {
201
218
  network,
202
219
  });
203
- if ((_b = request.signature) === null || _b === void 0 ? void 0 : _b.length) {
204
- validatePsbt(psbtFromBase64, request.allowedSighash, request.signature);
205
- }
206
- const inputsToSign = ((_d = (_c = request.signature) === null || _c === void 0 ? void 0 : _c.map((sig) => {
207
- var _a;
208
- return ((_a = sig.signingIndexes) !== null && _a !== void 0 ? _a : []).map((inputIndex) => ({
209
- address: sig.address,
210
- sigHash: getSigHashType(psbtFromBase64.data.inputs[inputIndex]),
211
- signingIndexes: [inputIndex],
212
- }));
213
- })) !== null && _d !== void 0 ? _d : []).flat();
214
220
  const signedPsbt = yield this.signTransaction({
215
221
  broadcast: false,
216
- inputsToSign,
222
+ inputsToSign: createSignPsbtOptionsForSatsConnect(psbtFromBase64, request),
217
223
  psbtBase64: request.unsignedPsbtBase64,
218
224
  });
219
225
  if (!signedPsbt) {
@@ -222,6 +228,31 @@ class BitcoinSatsConnectConnector extends BitcoinWalletConnector {
222
228
  return { signedPsbt: signedPsbt.psbtBase64 };
223
229
  });
224
230
  }
231
+ signPsbts(requests) {
232
+ return __awaiter(this, void 0, void 0, function* () {
233
+ var _a;
234
+ const network = convertNetworkTypeForPsbt(this.currentNetwork);
235
+ const signMultipleTransactionPayload = {
236
+ message: 'Sign Transaction',
237
+ network: {
238
+ type: this.currentNetwork,
239
+ },
240
+ psbts: [],
241
+ };
242
+ for (const request of requests) {
243
+ const psbtFromBase64 = Psbt.fromBase64(request.unsignedPsbtBase64, {
244
+ network,
245
+ });
246
+ const inputsToSign = createSignPsbtOptionsForSatsConnect(psbtFromBase64, request);
247
+ signMultipleTransactionPayload.psbts.push({
248
+ inputsToSign,
249
+ psbtBase64: request.unsignedPsbtBase64,
250
+ });
251
+ }
252
+ const signedPsbts = yield this.signTransactions(signMultipleTransactionPayload);
253
+ return (_a = signedPsbts === null || signedPsbts === void 0 ? void 0 : signedPsbts.map((signedPsbts) => signedPsbts.psbtBase64)) !== null && _a !== void 0 ? _a : [];
254
+ });
255
+ }
225
256
  }
226
257
 
227
258
  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');
@@ -26,12 +27,20 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
26
27
  this.verifiedCredentials = [];
27
28
  // this is the key from the wallet book entry so that we don't purely rely on the normalized name
28
29
  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));
30
+ const walletBookWallet = opts.walletData || walletBook.getWalletBookWallet(this.walletBook, this.key);
31
+ this.bitcoinProviderHelper = new bitcoinProviderHelper.BitcoinProviderHelper(walletBookWallet);
30
32
  this.wallet = this.bitcoinProviderHelper.findWallet();
31
33
  if (this.wallet) {
32
34
  this.walletMethods = this.bitcoinProviderHelper.getWalletMethods(this.wallet);
33
35
  }
34
36
  this.cache = new BitcoinLocalStorageCache.BitcoinLocalStorageCache(this.overrideKey);
37
+ this.canFetchConnectedAccounts = walletBook.isWalletMethodSupported(walletBookWallet, 'getConnectedAccounts', 'browserExtension');
38
+ }
39
+ isSameAccountChangeRequest(to) {
40
+ return this.lastAccountChange === to;
41
+ }
42
+ setLastAccountChangeRequest(to) {
43
+ this.lastAccountChange = to;
35
44
  }
36
45
  clearConnectedAccounts() {
37
46
  return _tslib.__awaiter(this, void 0, void 0, function* () {
@@ -53,31 +62,17 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
53
62
  }
54
63
  endSession() {
55
64
  return _tslib.__awaiter(this, void 0, void 0, function* () {
56
- yield this.cache.clearLastBalance();
65
+ yield this.cache.clearConnectedAcccounts();
57
66
  });
58
67
  }
59
- getBalance() {
68
+ getBalance(address) {
60
69
  return _tslib.__awaiter(this, void 0, void 0, function* () {
61
- var _a, _b;
62
- const [connectedAddress] = yield this.getConnectedAccounts();
63
- if (!connectedAddress) {
64
- throw new utils.DynamicError('getBalance - No connected address found!');
65
- }
66
- const additionalAddresses = yield this.getAdditionalAddresses(connectedAddress);
67
- const ordinalsAdditionalAddress = (_a = additionalAddresses.find((address) => address.type === sdkApiCore.WalletAddressType.Ordinals)) === null || _a === void 0 ? void 0 : _a.address;
68
- const paymentAdditionalAddress = (_b = additionalAddresses.find((address) => address.type === sdkApiCore.WalletAddressType.Payment)) === null || _b === void 0 ? void 0 : _b.address;
69
- // Some BTC wallet connectors only have 1 address type. when this is the case, it would always be `ordinals`
70
- // if a BTC walletConnector does NOT have a payment address, just use the ordinal address
71
- const paymentAddress = paymentAdditionalAddress !== null && paymentAdditionalAddress !== void 0 ? paymentAdditionalAddress : ordinalsAdditionalAddress;
72
- if (!paymentAddress) {
73
- throw new utils.DynamicError('getBalance - No payment address found!');
74
- }
75
- const API_URL = getMempoolApiUrl.getMempoolApiUrl(paymentAddress);
76
- const response = yield fetch(`${API_URL}/address/${paymentAddress}`);
70
+ const API_URL = getMempoolApiUrl.getMempoolApiUrl(address);
71
+ const response = yield fetch(`${API_URL}/address/${address}`);
77
72
  if (!response.ok) {
78
73
  // if the request fails due to rate limits, return cached value
79
74
  if (response.status === _const.HTTP_STATUS_TOO_MANY_REQUESTS) {
80
- return this.cache.getLastBalance();
75
+ return '0';
81
76
  }
82
77
  // new accounts not yet indexed will return a 404
83
78
  if (response.status === _const.HTTP_STATUS_NOT_FOUND) {
@@ -94,7 +89,6 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
94
89
  const unconfirmedBalanceInSats = Number(addressInfo.mempool_stats.funded_txo_sum) -
95
90
  Number(addressInfo.mempool_stats.spent_txo_sum);
96
91
  const balance = satoshisToBtc.satoshisToBtc(confirmedBalanceInSats + unconfirmedBalanceInSats);
97
- yield this.cache.setLastBalance(balance.toString());
98
92
  return balance.toString();
99
93
  });
100
94
  }
@@ -191,6 +185,18 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
191
185
  var _a;
192
186
  return (_a = this.bitcoinProviderHelper) === null || _a === void 0 ? void 0 : _a.getProvider();
193
187
  }
188
+ signPsbts(requests) {
189
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
190
+ const signedPsbtResponses = [];
191
+ for (const request of requests) {
192
+ const signedPsbtResponse = yield this.signPsbt(request);
193
+ if (signedPsbtResponse) {
194
+ signedPsbtResponses.push(signedPsbtResponse);
195
+ }
196
+ }
197
+ return signedPsbtResponses.map((response) => response.signedPsbt);
198
+ });
199
+ }
194
200
  setConnectedAccountWithAddresses(_a) {
195
201
  return _tslib.__awaiter(this, arguments, void 0, function* ({ mainAddress, ordinalsAddress, paymentAddress, active, }) {
196
202
  if (!mainAddress) {
@@ -225,18 +231,33 @@ class BitcoinWalletConnector extends walletConnectorCore.WalletConnectorBase {
225
231
  const { handleAccountChange, handleChainChange, handleDisconnect } = walletConnectorCore.eventListenerHandlers(this);
226
232
  const handleBitcoinAccountChange = (accounts) => _tslib.__awaiter(this, void 0, void 0, function* () {
227
233
  let connectedAccounts = accounts;
234
+ let ordinalsAccount, paymentAccount;
228
235
  // if accounts is an array of objects, we need to parse them to return only addresses
229
236
  // since ordinals is the main address we use, we should return it as the first address
230
237
  if (typeof accounts[0] === 'object') {
231
238
  connectedAccounts = accounts
232
- .sort((account) => (account.purpose === 'ordinals' ? -1 : 1))
239
+ .sort((account) => account.purpose === satsConnect.AddressPurpose.Ordinals ? -1 : 1)
233
240
  .map((account) => account.address);
241
+ [ordinalsAccount, paymentAccount] = connectedAccounts;
234
242
  }
235
243
  const currentConnectedAccounts = yield this.getConnectedAccountsFromCache();
236
244
  // don't do anything if the connected accounts haven't changed
237
- if (currentConnectedAccounts[0] === connectedAccounts[0]) {
245
+ // or if the account change request is the same as previous request
246
+ if (currentConnectedAccounts[0] === connectedAccounts[0] ||
247
+ this.isSameAccountChangeRequest(connectedAccounts[0])) {
238
248
  return;
239
249
  }
250
+ // set the last account change request with the from and to addresses
251
+ // to ensure that the requests are not duplicated
252
+ this.setLastAccountChangeRequest(connectedAccounts[0]);
253
+ if (ordinalsAccount || paymentAccount) {
254
+ this.setConnectedAccountWithAddresses({
255
+ active: true,
256
+ mainAddress: ordinalsAccount !== null && ordinalsAccount !== void 0 ? ordinalsAccount : paymentAccount,
257
+ ordinalsAddress: ordinalsAccount,
258
+ paymentAddress: paymentAccount,
259
+ });
260
+ }
240
261
  handleAccountChange(connectedAccounts);
241
262
  });
242
263
  provider.on('accountsChanged', handleBitcoinAccountChange);
@@ -23,13 +23,16 @@ export declare abstract class BitcoinWalletConnector extends WalletConnectorBase
23
23
  canFetchConnectedAccounts: boolean;
24
24
  isHardwareWalletEnabled: boolean;
25
25
  verifiedCredentials: JwtVerifiedCredential[];
26
+ private lastAccountChange;
26
27
  constructor(opts: BitcoinWalletConnectorOpts);
28
+ private isSameAccountChangeRequest;
29
+ private setLastAccountChangeRequest;
27
30
  clearConnectedAccounts(): Promise<void>;
28
31
  canConnectWithHardwareWallet(): boolean;
29
32
  isInstalledOnBrowser(): boolean;
30
33
  getDeepLink(): string | undefined;
31
34
  endSession(): Promise<void>;
32
- getBalance(): Promise<string | undefined>;
35
+ getBalance(address: string): Promise<string | undefined>;
33
36
  getConnectedAccountsFromCache(): Promise<string[]>;
34
37
  getConnectedAccounts(): Promise<string[]>;
35
38
  getAdditionalAddresses(mainAddress?: string): Promise<WalletAdditionalAddress[]>;
@@ -38,6 +41,7 @@ export declare abstract class BitcoinWalletConnector extends WalletConnectorBase
38
41
  abstract sendBitcoin(transaction: BitcoinTransaction): Promise<string | undefined>;
39
42
  getProvider<T>(): T & EventEmitter;
40
43
  abstract signPsbt(request: BitcoinSignPsbtRequest): Promise<BitcoinSignPsbtResponse | undefined>;
44
+ signPsbts(requests: BitcoinSignPsbtRequest[]): Promise<string[] | undefined>;
41
45
  setConnectedAccountWithAddresses({ mainAddress, ordinalsAddress, paymentAddress, active, }: ConnectedAccountWithAddressesProps): Promise<void>;
42
46
  setupEventListeners(): void;
43
47
  setVerifiedCredentials(verifiedCredentials: JwtVerifiedCredential[]): void;
@@ -1,7 +1,8 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../_virtual/_tslib.js';
3
+ import { AddressPurpose } from 'sats-connect';
3
4
  import { WalletConnectorBase, eventListenerHandlers, logger } from '@dynamic-labs/wallet-connector-core';
4
- import { getWalletBookWallet, findWalletBookWallet } from '@dynamic-labs/wallet-book';
5
+ import { getWalletBookWallet, isWalletMethodSupported, findWalletBookWallet } from '@dynamic-labs/wallet-book';
5
6
  import { isLedgerAddressViaVerifiedCredentials, DynamicError } from '@dynamic-labs/utils';
6
7
  import { WalletAddressType } from '@dynamic-labs/sdk-api-core';
7
8
  import { BitcoinLocalStorageCache } from '../BitcoinLocalStorageCache.js';
@@ -22,12 +23,20 @@ class BitcoinWalletConnector extends WalletConnectorBase {
22
23
  this.verifiedCredentials = [];
23
24
  // this is the key from the wallet book entry so that we don't purely rely on the normalized name
24
25
  this.overrideKey = (_a = opts.overrideKey) !== null && _a !== void 0 ? _a : this.key;
25
- this.bitcoinProviderHelper = new BitcoinProviderHelper(opts.walletData || getWalletBookWallet(this.walletBook, this.key));
26
+ const walletBookWallet = opts.walletData || getWalletBookWallet(this.walletBook, this.key);
27
+ this.bitcoinProviderHelper = new BitcoinProviderHelper(walletBookWallet);
26
28
  this.wallet = this.bitcoinProviderHelper.findWallet();
27
29
  if (this.wallet) {
28
30
  this.walletMethods = this.bitcoinProviderHelper.getWalletMethods(this.wallet);
29
31
  }
30
32
  this.cache = new BitcoinLocalStorageCache(this.overrideKey);
33
+ this.canFetchConnectedAccounts = isWalletMethodSupported(walletBookWallet, 'getConnectedAccounts', 'browserExtension');
34
+ }
35
+ isSameAccountChangeRequest(to) {
36
+ return this.lastAccountChange === to;
37
+ }
38
+ setLastAccountChangeRequest(to) {
39
+ this.lastAccountChange = to;
31
40
  }
32
41
  clearConnectedAccounts() {
33
42
  return __awaiter(this, void 0, void 0, function* () {
@@ -49,31 +58,17 @@ class BitcoinWalletConnector extends WalletConnectorBase {
49
58
  }
50
59
  endSession() {
51
60
  return __awaiter(this, void 0, void 0, function* () {
52
- yield this.cache.clearLastBalance();
61
+ yield this.cache.clearConnectedAcccounts();
53
62
  });
54
63
  }
55
- getBalance() {
64
+ getBalance(address) {
56
65
  return __awaiter(this, void 0, void 0, function* () {
57
- var _a, _b;
58
- const [connectedAddress] = yield this.getConnectedAccounts();
59
- if (!connectedAddress) {
60
- throw new DynamicError('getBalance - No connected address found!');
61
- }
62
- const additionalAddresses = yield this.getAdditionalAddresses(connectedAddress);
63
- const ordinalsAdditionalAddress = (_a = additionalAddresses.find((address) => address.type === WalletAddressType.Ordinals)) === null || _a === void 0 ? void 0 : _a.address;
64
- const paymentAdditionalAddress = (_b = additionalAddresses.find((address) => address.type === WalletAddressType.Payment)) === null || _b === void 0 ? void 0 : _b.address;
65
- // Some BTC wallet connectors only have 1 address type. when this is the case, it would always be `ordinals`
66
- // if a BTC walletConnector does NOT have a payment address, just use the ordinal address
67
- const paymentAddress = paymentAdditionalAddress !== null && paymentAdditionalAddress !== void 0 ? paymentAdditionalAddress : ordinalsAdditionalAddress;
68
- if (!paymentAddress) {
69
- throw new DynamicError('getBalance - No payment address found!');
70
- }
71
- const API_URL = getMempoolApiUrl(paymentAddress);
72
- const response = yield fetch(`${API_URL}/address/${paymentAddress}`);
66
+ const API_URL = getMempoolApiUrl(address);
67
+ const response = yield fetch(`${API_URL}/address/${address}`);
73
68
  if (!response.ok) {
74
69
  // if the request fails due to rate limits, return cached value
75
70
  if (response.status === HTTP_STATUS_TOO_MANY_REQUESTS) {
76
- return this.cache.getLastBalance();
71
+ return '0';
77
72
  }
78
73
  // new accounts not yet indexed will return a 404
79
74
  if (response.status === HTTP_STATUS_NOT_FOUND) {
@@ -90,7 +85,6 @@ class BitcoinWalletConnector extends WalletConnectorBase {
90
85
  const unconfirmedBalanceInSats = Number(addressInfo.mempool_stats.funded_txo_sum) -
91
86
  Number(addressInfo.mempool_stats.spent_txo_sum);
92
87
  const balance = satoshisToBtc(confirmedBalanceInSats + unconfirmedBalanceInSats);
93
- yield this.cache.setLastBalance(balance.toString());
94
88
  return balance.toString();
95
89
  });
96
90
  }
@@ -187,6 +181,18 @@ class BitcoinWalletConnector extends WalletConnectorBase {
187
181
  var _a;
188
182
  return (_a = this.bitcoinProviderHelper) === null || _a === void 0 ? void 0 : _a.getProvider();
189
183
  }
184
+ signPsbts(requests) {
185
+ return __awaiter(this, void 0, void 0, function* () {
186
+ const signedPsbtResponses = [];
187
+ for (const request of requests) {
188
+ const signedPsbtResponse = yield this.signPsbt(request);
189
+ if (signedPsbtResponse) {
190
+ signedPsbtResponses.push(signedPsbtResponse);
191
+ }
192
+ }
193
+ return signedPsbtResponses.map((response) => response.signedPsbt);
194
+ });
195
+ }
190
196
  setConnectedAccountWithAddresses(_a) {
191
197
  return __awaiter(this, arguments, void 0, function* ({ mainAddress, ordinalsAddress, paymentAddress, active, }) {
192
198
  if (!mainAddress) {
@@ -221,18 +227,33 @@ class BitcoinWalletConnector extends WalletConnectorBase {
221
227
  const { handleAccountChange, handleChainChange, handleDisconnect } = eventListenerHandlers(this);
222
228
  const handleBitcoinAccountChange = (accounts) => __awaiter(this, void 0, void 0, function* () {
223
229
  let connectedAccounts = accounts;
230
+ let ordinalsAccount, paymentAccount;
224
231
  // if accounts is an array of objects, we need to parse them to return only addresses
225
232
  // since ordinals is the main address we use, we should return it as the first address
226
233
  if (typeof accounts[0] === 'object') {
227
234
  connectedAccounts = accounts
228
- .sort((account) => (account.purpose === 'ordinals' ? -1 : 1))
235
+ .sort((account) => account.purpose === AddressPurpose.Ordinals ? -1 : 1)
229
236
  .map((account) => account.address);
237
+ [ordinalsAccount, paymentAccount] = connectedAccounts;
230
238
  }
231
239
  const currentConnectedAccounts = yield this.getConnectedAccountsFromCache();
232
240
  // don't do anything if the connected accounts haven't changed
233
- if (currentConnectedAccounts[0] === connectedAccounts[0]) {
241
+ // or if the account change request is the same as previous request
242
+ if (currentConnectedAccounts[0] === connectedAccounts[0] ||
243
+ this.isSameAccountChangeRequest(connectedAccounts[0])) {
234
244
  return;
235
245
  }
246
+ // set the last account change request with the from and to addresses
247
+ // to ensure that the requests are not duplicated
248
+ this.setLastAccountChangeRequest(connectedAccounts[0]);
249
+ if (ordinalsAccount || paymentAccount) {
250
+ this.setConnectedAccountWithAddresses({
251
+ active: true,
252
+ mainAddress: ordinalsAccount !== null && ordinalsAccount !== void 0 ? ordinalsAccount : paymentAccount,
253
+ ordinalsAddress: ordinalsAccount,
254
+ paymentAddress: paymentAccount,
255
+ });
256
+ }
236
257
  handleAccountChange(connectedAccounts);
237
258
  });
238
259
  provider.on('accountsChanged', handleBitcoinAccountChange);
@@ -0,0 +1,44 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var _tslib = require('../../../_virtual/_tslib.cjs');
7
+ var BitcoinWalletConnector = require('../BitcoinWalletConnector.cjs');
8
+
9
+ class FallbackBitcoinConnector extends BitcoinWalletConnector.BitcoinWalletConnector {
10
+ constructor(opts) {
11
+ super(Object.assign(Object.assign({}, opts), { overrideKey: 'fallbackconnector' }));
12
+ this.name = 'Fallback Connector';
13
+ this.overrideKey = 'fallbackconnector';
14
+ this.isAvailable = false;
15
+ }
16
+ getAddress() {
17
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
18
+ return;
19
+ });
20
+ }
21
+ signPsbt(
22
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
23
+ _request) {
24
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
25
+ return;
26
+ });
27
+ }
28
+ signPsbts(
29
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
30
+ _requests) {
31
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
32
+ return;
33
+ });
34
+ }
35
+ sendBitcoin(
36
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
37
+ _transaction) {
38
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
39
+ return;
40
+ });
41
+ }
42
+ }
43
+
44
+ exports.FallbackBitcoinConnector = FallbackBitcoinConnector;
@@ -0,0 +1,12 @@
1
+ import { BitcoinSignPsbtRequest, BitcoinSignPsbtResponse, BitcoinTransaction } from '../../types';
2
+ import { BitcoinWalletConnector, BitcoinWalletConnectorOpts } from '../BitcoinWalletConnector';
3
+ export declare class FallbackBitcoinConnector extends BitcoinWalletConnector {
4
+ name: string;
5
+ overrideKey: string;
6
+ isAvailable: boolean;
7
+ constructor(opts: BitcoinWalletConnectorOpts);
8
+ getAddress(): Promise<string | undefined>;
9
+ signPsbt(_request: BitcoinSignPsbtRequest): Promise<BitcoinSignPsbtResponse | undefined>;
10
+ signPsbts(_requests: BitcoinSignPsbtRequest[]): Promise<string[] | undefined>;
11
+ sendBitcoin(_transaction: BitcoinTransaction): Promise<string | undefined>;
12
+ }