@dynamic-labs-wallet/btc-utils 1.1.28 → 1.1.30

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/index.cjs CHANGED
@@ -182,7 +182,7 @@ function _instanceof$8(left, right) {
182
182
  return left instanceof right;
183
183
  }
184
184
  }
185
- function _type_of$1(obj) {
185
+ function _type_of$2(obj) {
186
186
  "@swc/helpers - typeof";
187
187
  return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
188
188
  }
@@ -207,7 +207,7 @@ function _type_of$1(obj) {
207
207
  }
208
208
  return result;
209
209
  }
210
- if ((typeof actualPubkey === "undefined" ? "undefined" : _type_of$1(actualPubkey)) === 'object' && actualPubkey !== null) {
210
+ if ((typeof actualPubkey === "undefined" ? "undefined" : _type_of$2(actualPubkey)) === 'object' && actualPubkey !== null) {
211
211
  return convertObjectToBuffer(actualPubkey);
212
212
  }
213
213
  throw new Error('Invalid public key format');
@@ -816,6 +816,54 @@ function _instanceof$3(left, right) {
816
816
  return network === core.BitcoinNetwork.MAINNET ? 'https://mempool.space/api' : 'https://mempool.space/testnet/api';
817
817
  };
818
818
 
819
+ var LOOPBACK_HOSTNAMES = new Set([
820
+ 'localhost',
821
+ '127.0.0.1',
822
+ '[::1]'
823
+ ]);
824
+ /**
825
+ * Resolves the Esplora-compatible base URL to use for a network.
826
+ * Falls back to the default (mempool.space) when no custom URL is given.
827
+ *
828
+ * @param network - The Bitcoin network
829
+ * @param rpcUrl - Optional custom Esplora-compatible base URL
830
+ * @returns The base URL without a trailing slash
831
+ */ var resolveRpcUrl = function(param) {
832
+ var network = param.network, rpcUrl = param.rpcUrl;
833
+ if (!rpcUrl) {
834
+ return getDefaultRpcUrl(network);
835
+ }
836
+ var parsed;
837
+ try {
838
+ parsed = new URL(rpcUrl);
839
+ } catch (e) {
840
+ throw new Error('Invalid Bitcoin RPC URL');
841
+ }
842
+ var isSecure = parsed.protocol === 'https:';
843
+ var isLocalHttp = parsed.protocol === 'http:' && LOOPBACK_HOSTNAMES.has(parsed.hostname);
844
+ if (!isSecure && !isLocalHttp) {
845
+ throw new Error('Bitcoin RPC URL must use https (http is only allowed for localhost)');
846
+ }
847
+ // Manual trim: a /\/+$/ regex backtracks quadratically on long runs of slashes.
848
+ var end = rpcUrl.length;
849
+ while(end > 0 && rpcUrl[end - 1] === '/'){
850
+ end -= 1;
851
+ }
852
+ return rpcUrl.slice(0, end);
853
+ };
854
+
855
+ /**
856
+ * fetch wrapper for Esplora requests. Requests to a custom `rpcUrl` do not follow
857
+ * redirects, so they cannot be bounced to a host other than the configured backend.
858
+ *
859
+ * @param url - The full request URL
860
+ * @param rpcUrl - The custom RPC URL the request was built from, if any
861
+ */ var rpcFetch = function(url, rpcUrl) {
862
+ return rpcUrl ? fetch(url, {
863
+ redirect: 'error'
864
+ }) : fetch(url);
865
+ };
866
+
819
867
  function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
820
868
  try {
821
869
  var info = gen[key](arg);
@@ -941,11 +989,11 @@ function _ts_generator$1(thisArg, body) {
941
989
  }
942
990
  }
943
991
  /**
944
- * Fetches UTXOs for a given address using mempool.space API
992
+ * Fetches UTXOs for a given address using an Esplora-compatible API (mempool.space by default)
945
993
  *
946
994
  * @param address - The address to fetch UTXOs for
947
995
  * @param network - The Bitcoin network (default: MAINNET)
948
- * @param rpcUrl - Optional custom RPC URL
996
+ * @param rpcUrl - Optional custom Esplora-compatible RPC URL
949
997
  * @returns The list of UTXOs
950
998
  */ var getUTXOs = /*#__PURE__*/ function() {
951
999
  var _ref = _async_to_generator$1(function(param) {
@@ -954,7 +1002,10 @@ function _ts_generator$1(thisArg, body) {
954
1002
  switch(_state.label){
955
1003
  case 0:
956
1004
  address = param.address, _param_network = param.network, network = _param_network === void 0 ? core.BitcoinNetwork.MAINNET : _param_network, rpcUrl = param.rpcUrl;
957
- baseUrl = rpcUrl || getDefaultRpcUrl(network);
1005
+ baseUrl = resolveRpcUrl({
1006
+ network: network,
1007
+ rpcUrl: rpcUrl
1008
+ });
958
1009
  _state.label = 1;
959
1010
  case 1:
960
1011
  _state.trys.push([
@@ -965,7 +1016,7 @@ function _ts_generator$1(thisArg, body) {
965
1016
  ]);
966
1017
  return [
967
1018
  4,
968
- fetch("".concat(baseUrl, "/address/").concat(address, "/utxo"))
1019
+ rpcFetch("".concat(baseUrl, "/address/").concat(address, "/utxo"), rpcUrl)
969
1020
  ];
970
1021
  case 2:
971
1022
  response = _state.sent();
@@ -1003,30 +1054,30 @@ function _ts_generator$1(thisArg, body) {
1003
1054
  };
1004
1055
  }();
1005
1056
 
1006
- function _array_like_to_array(arr, len) {
1057
+ function _array_like_to_array$1(arr, len) {
1007
1058
  if (len == null || len > arr.length) len = arr.length;
1008
1059
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
1009
1060
  return arr2;
1010
1061
  }
1011
- function _array_without_holes(arr) {
1012
- if (Array.isArray(arr)) return _array_like_to_array(arr);
1062
+ function _array_without_holes$1(arr) {
1063
+ if (Array.isArray(arr)) return _array_like_to_array$1(arr);
1013
1064
  }
1014
- function _iterable_to_array(iter) {
1065
+ function _iterable_to_array$1(iter) {
1015
1066
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
1016
1067
  }
1017
- function _non_iterable_spread() {
1068
+ function _non_iterable_spread$1() {
1018
1069
  throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1019
1070
  }
1020
- function _to_consumable_array(arr) {
1021
- return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
1071
+ function _to_consumable_array$1(arr) {
1072
+ return _array_without_holes$1(arr) || _iterable_to_array$1(arr) || _unsupported_iterable_to_array$1(arr) || _non_iterable_spread$1();
1022
1073
  }
1023
- function _unsupported_iterable_to_array(o, minLen) {
1074
+ function _unsupported_iterable_to_array$1(o, minLen) {
1024
1075
  if (!o) return;
1025
- if (typeof o === "string") return _array_like_to_array(o, minLen);
1076
+ if (typeof o === "string") return _array_like_to_array$1(o, minLen);
1026
1077
  var n = Object.prototype.toString.call(o).slice(8, -1);
1027
1078
  if (n === "Object" && o.constructor) n = o.constructor.name;
1028
1079
  if (n === "Map" || n === "Set") return Array.from(n);
1029
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
1080
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$1(o, minLen);
1030
1081
  }
1031
1082
  /**
1032
1083
  * Simple greedy coin selection
@@ -1038,7 +1089,7 @@ function _unsupported_iterable_to_array(o, minLen) {
1038
1089
  */ var selectUTXOs = function(param) {
1039
1090
  var utxos = param.utxos, amount = param.amount, feeRate = param.feeRate;
1040
1091
  // Sort by value descending
1041
- var sorted = _to_consumable_array(utxos).sort(function(a, b) {
1092
+ var sorted = _to_consumable_array$1(utxos).sort(function(a, b) {
1042
1093
  return Number(b.value - a.value);
1043
1094
  });
1044
1095
  var inputs = [];
@@ -1084,6 +1135,14 @@ function _unsupported_iterable_to_array(o, minLen) {
1084
1135
  throw new Error('Insufficient funds');
1085
1136
  };
1086
1137
 
1138
+ function _array_like_to_array(arr, len) {
1139
+ if (len == null || len > arr.length) len = arr.length;
1140
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
1141
+ return arr2;
1142
+ }
1143
+ function _array_without_holes(arr) {
1144
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
1145
+ }
1087
1146
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
1088
1147
  try {
1089
1148
  var info = gen[key](arg);
@@ -1113,6 +1172,27 @@ function _async_to_generator(fn) {
1113
1172
  });
1114
1173
  };
1115
1174
  }
1175
+ function _iterable_to_array(iter) {
1176
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
1177
+ }
1178
+ function _non_iterable_spread() {
1179
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1180
+ }
1181
+ function _to_consumable_array(arr) {
1182
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
1183
+ }
1184
+ function _type_of$1(obj) {
1185
+ "@swc/helpers - typeof";
1186
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
1187
+ }
1188
+ function _unsupported_iterable_to_array(o, minLen) {
1189
+ if (!o) return;
1190
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
1191
+ var n = Object.prototype.toString.call(o).slice(8, -1);
1192
+ if (n === "Object" && o.constructor) n = o.constructor.name;
1193
+ if (n === "Map" || n === "Set") return Array.from(n);
1194
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
1195
+ }
1116
1196
  function _ts_generator(thisArg, body) {
1117
1197
  var f, y, t, g, _ = {
1118
1198
  label: 0,
@@ -1208,30 +1288,65 @@ function _ts_generator(thisArg, body) {
1208
1288
  };
1209
1289
  }
1210
1290
  }
1291
+ // Block targets approximating mempool's fastest / half-hour / hour fees.
1292
+ var ESPLORA_TARGETS = {
1293
+ fast: 1,
1294
+ medium: 3,
1295
+ slow: 6
1296
+ };
1297
+ // Backends are untrusted input: reject anything that is not a positive finite number.
1298
+ var assertFeeRate = function(value) {
1299
+ if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
1300
+ throw new Error('invalid fee estimate');
1301
+ }
1302
+ return value;
1303
+ };
1304
+ var pickEstimate = function(estimates, target) {
1305
+ var targets = Object.keys(estimates).map(Number).filter(function(key) {
1306
+ return Number.isFinite(key);
1307
+ }).sort(function(a, b) {
1308
+ return a - b;
1309
+ });
1310
+ if (targets.length === 0) {
1311
+ throw new Error('empty fee estimates');
1312
+ }
1313
+ var _reverse_find;
1314
+ // Closest target not exceeding the wanted one, else the fastest available.
1315
+ var key = (_reverse_find = _to_consumable_array(targets).reverse().find(function(candidate) {
1316
+ return candidate <= target;
1317
+ })) !== null && _reverse_find !== void 0 ? _reverse_find : targets[0];
1318
+ return Math.ceil(assertFeeRate(estimates[String(key)]));
1319
+ };
1211
1320
  /**
1212
- * Fetches current fee rates from mempool.space
1213
- * Returns fees in sat/vByte
1321
+ * Fetches current fee rates in sat/vByte.
1322
+ * Uses the mempool.space `/v1/fees/recommended` endpoint. For a custom Esplora-compatible
1323
+ * `rpcUrl` that does not serve it, falls back to the standard `/fee-estimates` endpoint
1324
+ * on the same backend. Never falls back to a different host.
1214
1325
  *
1215
1326
  * @param network - The Bitcoin network (default: MAINNET)
1216
- * @param rpcUrl - Optional custom RPC URL
1327
+ * @param rpcUrl - Optional custom Esplora-compatible RPC URL
1217
1328
  * @returns The fee rates for fast, medium, and slow transactions
1218
1329
  */ var getFeeRates = /*#__PURE__*/ function() {
1219
1330
  var _ref = _async_to_generator(function(param) {
1220
- var _param_network, network, rpcUrl, baseUrl, response, fees;
1331
+ var _param_network, network, rpcUrl, baseUrl, response, fees, fallback, estimates, rates;
1221
1332
  return _ts_generator(this, function(_state) {
1222
1333
  switch(_state.label){
1223
1334
  case 0:
1224
1335
  _param_network = param.network, network = _param_network === void 0 ? core.BitcoinNetwork.MAINNET : _param_network, rpcUrl = param.rpcUrl;
1225
- baseUrl = rpcUrl || getDefaultRpcUrl(network);
1336
+ baseUrl = resolveRpcUrl({
1337
+ network: network,
1338
+ rpcUrl: rpcUrl
1339
+ });
1226
1340
  return [
1227
1341
  4,
1228
- fetch("".concat(baseUrl, "/v1/fees/recommended"))
1342
+ rpcFetch("".concat(baseUrl, "/v1/fees/recommended"), rpcUrl)
1229
1343
  ];
1230
1344
  case 1:
1231
1345
  response = _state.sent();
1232
- if (!response.ok) {
1233
- throw new Error("Failed to fetch fee rates: ".concat(response.statusText));
1234
- }
1346
+ if (!response.ok) return [
1347
+ 3,
1348
+ 3
1349
+ ];
1235
1350
  return [
1236
1351
  4,
1237
1352
  response.json()
@@ -1241,9 +1356,41 @@ function _ts_generator(thisArg, body) {
1241
1356
  return [
1242
1357
  2,
1243
1358
  {
1244
- fast: fees.fastestFee,
1245
- medium: fees.halfHourFee,
1246
- slow: fees.hourFee
1359
+ fast: assertFeeRate(fees.fastestFee),
1360
+ medium: assertFeeRate(fees.halfHourFee),
1361
+ slow: assertFeeRate(fees.hourFee)
1362
+ }
1363
+ ];
1364
+ case 3:
1365
+ if (!rpcUrl) {
1366
+ throw new Error("Failed to fetch fee rates: ".concat(response.statusText));
1367
+ }
1368
+ return [
1369
+ 4,
1370
+ rpcFetch("".concat(baseUrl, "/fee-estimates"), rpcUrl)
1371
+ ];
1372
+ case 4:
1373
+ fallback = _state.sent();
1374
+ if (!fallback.ok) {
1375
+ // Report the origin only; custom URLs may embed credentials or API keys in the path.
1376
+ throw new Error("Failed to fetch fee rates from ".concat(new URL(baseUrl).origin, ": ").concat(fallback.statusText, ". ") + 'Provide an explicit feeRate to skip the fee lookup.');
1377
+ }
1378
+ return [
1379
+ 4,
1380
+ fallback.json()
1381
+ ];
1382
+ case 5:
1383
+ estimates = _state.sent();
1384
+ if ((typeof estimates === "undefined" ? "undefined" : _type_of$1(estimates)) !== 'object' || estimates === null || Array.isArray(estimates)) {
1385
+ throw new Error('invalid fee estimates response');
1386
+ }
1387
+ rates = estimates;
1388
+ return [
1389
+ 2,
1390
+ {
1391
+ fast: pickEstimate(rates, ESPLORA_TARGETS.fast),
1392
+ medium: pickEstimate(rates, ESPLORA_TARGETS.medium),
1393
+ slow: pickEstimate(rates, ESPLORA_TARGETS.slow)
1247
1394
  }
1248
1395
  ];
1249
1396
  }
@@ -1796,6 +1943,8 @@ exports.normalizePublicKey = normalizePublicKey;
1796
1943
  exports.privateKeyToWIF = privateKeyToWIF;
1797
1944
  exports.publicKeyToBitcoinAddress = publicKeyToBitcoinAddress;
1798
1945
  exports.resolveBitcoinAddressType = resolveBitcoinAddressType;
1946
+ exports.resolveRpcUrl = resolveRpcUrl;
1947
+ exports.rpcFetch = rpcFetch;
1799
1948
  exports.selectUTXOs = selectUTXOs;
1800
1949
  exports.toBitcoinNetwork = toBitcoinNetwork;
1801
1950
  exports.toBuffer = toBuffer;
package/index.esm.js CHANGED
@@ -162,7 +162,7 @@ function _instanceof$8(left, right) {
162
162
  return left instanceof right;
163
163
  }
164
164
  }
165
- function _type_of$1(obj) {
165
+ function _type_of$2(obj) {
166
166
  "@swc/helpers - typeof";
167
167
  return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
168
168
  }
@@ -187,7 +187,7 @@ function _type_of$1(obj) {
187
187
  }
188
188
  return result;
189
189
  }
190
- if ((typeof actualPubkey === "undefined" ? "undefined" : _type_of$1(actualPubkey)) === 'object' && actualPubkey !== null) {
190
+ if ((typeof actualPubkey === "undefined" ? "undefined" : _type_of$2(actualPubkey)) === 'object' && actualPubkey !== null) {
191
191
  return convertObjectToBuffer(actualPubkey);
192
192
  }
193
193
  throw new Error('Invalid public key format');
@@ -796,6 +796,54 @@ function _instanceof$3(left, right) {
796
796
  return network === BitcoinNetwork.MAINNET ? 'https://mempool.space/api' : 'https://mempool.space/testnet/api';
797
797
  };
798
798
 
799
+ var LOOPBACK_HOSTNAMES = new Set([
800
+ 'localhost',
801
+ '127.0.0.1',
802
+ '[::1]'
803
+ ]);
804
+ /**
805
+ * Resolves the Esplora-compatible base URL to use for a network.
806
+ * Falls back to the default (mempool.space) when no custom URL is given.
807
+ *
808
+ * @param network - The Bitcoin network
809
+ * @param rpcUrl - Optional custom Esplora-compatible base URL
810
+ * @returns The base URL without a trailing slash
811
+ */ var resolveRpcUrl = function(param) {
812
+ var network = param.network, rpcUrl = param.rpcUrl;
813
+ if (!rpcUrl) {
814
+ return getDefaultRpcUrl(network);
815
+ }
816
+ var parsed;
817
+ try {
818
+ parsed = new URL(rpcUrl);
819
+ } catch (e) {
820
+ throw new Error('Invalid Bitcoin RPC URL');
821
+ }
822
+ var isSecure = parsed.protocol === 'https:';
823
+ var isLocalHttp = parsed.protocol === 'http:' && LOOPBACK_HOSTNAMES.has(parsed.hostname);
824
+ if (!isSecure && !isLocalHttp) {
825
+ throw new Error('Bitcoin RPC URL must use https (http is only allowed for localhost)');
826
+ }
827
+ // Manual trim: a /\/+$/ regex backtracks quadratically on long runs of slashes.
828
+ var end = rpcUrl.length;
829
+ while(end > 0 && rpcUrl[end - 1] === '/'){
830
+ end -= 1;
831
+ }
832
+ return rpcUrl.slice(0, end);
833
+ };
834
+
835
+ /**
836
+ * fetch wrapper for Esplora requests. Requests to a custom `rpcUrl` do not follow
837
+ * redirects, so they cannot be bounced to a host other than the configured backend.
838
+ *
839
+ * @param url - The full request URL
840
+ * @param rpcUrl - The custom RPC URL the request was built from, if any
841
+ */ var rpcFetch = function(url, rpcUrl) {
842
+ return rpcUrl ? fetch(url, {
843
+ redirect: 'error'
844
+ }) : fetch(url);
845
+ };
846
+
799
847
  function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
800
848
  try {
801
849
  var info = gen[key](arg);
@@ -921,11 +969,11 @@ function _ts_generator$1(thisArg, body) {
921
969
  }
922
970
  }
923
971
  /**
924
- * Fetches UTXOs for a given address using mempool.space API
972
+ * Fetches UTXOs for a given address using an Esplora-compatible API (mempool.space by default)
925
973
  *
926
974
  * @param address - The address to fetch UTXOs for
927
975
  * @param network - The Bitcoin network (default: MAINNET)
928
- * @param rpcUrl - Optional custom RPC URL
976
+ * @param rpcUrl - Optional custom Esplora-compatible RPC URL
929
977
  * @returns The list of UTXOs
930
978
  */ var getUTXOs = /*#__PURE__*/ function() {
931
979
  var _ref = _async_to_generator$1(function(param) {
@@ -934,7 +982,10 @@ function _ts_generator$1(thisArg, body) {
934
982
  switch(_state.label){
935
983
  case 0:
936
984
  address = param.address, _param_network = param.network, network = _param_network === void 0 ? BitcoinNetwork.MAINNET : _param_network, rpcUrl = param.rpcUrl;
937
- baseUrl = rpcUrl || getDefaultRpcUrl(network);
985
+ baseUrl = resolveRpcUrl({
986
+ network: network,
987
+ rpcUrl: rpcUrl
988
+ });
938
989
  _state.label = 1;
939
990
  case 1:
940
991
  _state.trys.push([
@@ -945,7 +996,7 @@ function _ts_generator$1(thisArg, body) {
945
996
  ]);
946
997
  return [
947
998
  4,
948
- fetch("".concat(baseUrl, "/address/").concat(address, "/utxo"))
999
+ rpcFetch("".concat(baseUrl, "/address/").concat(address, "/utxo"), rpcUrl)
949
1000
  ];
950
1001
  case 2:
951
1002
  response = _state.sent();
@@ -983,30 +1034,30 @@ function _ts_generator$1(thisArg, body) {
983
1034
  };
984
1035
  }();
985
1036
 
986
- function _array_like_to_array(arr, len) {
1037
+ function _array_like_to_array$1(arr, len) {
987
1038
  if (len == null || len > arr.length) len = arr.length;
988
1039
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
989
1040
  return arr2;
990
1041
  }
991
- function _array_without_holes(arr) {
992
- if (Array.isArray(arr)) return _array_like_to_array(arr);
1042
+ function _array_without_holes$1(arr) {
1043
+ if (Array.isArray(arr)) return _array_like_to_array$1(arr);
993
1044
  }
994
- function _iterable_to_array(iter) {
1045
+ function _iterable_to_array$1(iter) {
995
1046
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
996
1047
  }
997
- function _non_iterable_spread() {
1048
+ function _non_iterable_spread$1() {
998
1049
  throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
999
1050
  }
1000
- function _to_consumable_array(arr) {
1001
- return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
1051
+ function _to_consumable_array$1(arr) {
1052
+ return _array_without_holes$1(arr) || _iterable_to_array$1(arr) || _unsupported_iterable_to_array$1(arr) || _non_iterable_spread$1();
1002
1053
  }
1003
- function _unsupported_iterable_to_array(o, minLen) {
1054
+ function _unsupported_iterable_to_array$1(o, minLen) {
1004
1055
  if (!o) return;
1005
- if (typeof o === "string") return _array_like_to_array(o, minLen);
1056
+ if (typeof o === "string") return _array_like_to_array$1(o, minLen);
1006
1057
  var n = Object.prototype.toString.call(o).slice(8, -1);
1007
1058
  if (n === "Object" && o.constructor) n = o.constructor.name;
1008
1059
  if (n === "Map" || n === "Set") return Array.from(n);
1009
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
1060
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$1(o, minLen);
1010
1061
  }
1011
1062
  /**
1012
1063
  * Simple greedy coin selection
@@ -1018,7 +1069,7 @@ function _unsupported_iterable_to_array(o, minLen) {
1018
1069
  */ var selectUTXOs = function(param) {
1019
1070
  var utxos = param.utxos, amount = param.amount, feeRate = param.feeRate;
1020
1071
  // Sort by value descending
1021
- var sorted = _to_consumable_array(utxos).sort(function(a, b) {
1072
+ var sorted = _to_consumable_array$1(utxos).sort(function(a, b) {
1022
1073
  return Number(b.value - a.value);
1023
1074
  });
1024
1075
  var inputs = [];
@@ -1064,6 +1115,14 @@ function _unsupported_iterable_to_array(o, minLen) {
1064
1115
  throw new Error('Insufficient funds');
1065
1116
  };
1066
1117
 
1118
+ function _array_like_to_array(arr, len) {
1119
+ if (len == null || len > arr.length) len = arr.length;
1120
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
1121
+ return arr2;
1122
+ }
1123
+ function _array_without_holes(arr) {
1124
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
1125
+ }
1067
1126
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
1068
1127
  try {
1069
1128
  var info = gen[key](arg);
@@ -1093,6 +1152,27 @@ function _async_to_generator(fn) {
1093
1152
  });
1094
1153
  };
1095
1154
  }
1155
+ function _iterable_to_array(iter) {
1156
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
1157
+ }
1158
+ function _non_iterable_spread() {
1159
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1160
+ }
1161
+ function _to_consumable_array(arr) {
1162
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
1163
+ }
1164
+ function _type_of$1(obj) {
1165
+ "@swc/helpers - typeof";
1166
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
1167
+ }
1168
+ function _unsupported_iterable_to_array(o, minLen) {
1169
+ if (!o) return;
1170
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
1171
+ var n = Object.prototype.toString.call(o).slice(8, -1);
1172
+ if (n === "Object" && o.constructor) n = o.constructor.name;
1173
+ if (n === "Map" || n === "Set") return Array.from(n);
1174
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
1175
+ }
1096
1176
  function _ts_generator(thisArg, body) {
1097
1177
  var f, y, t, g, _ = {
1098
1178
  label: 0,
@@ -1188,30 +1268,65 @@ function _ts_generator(thisArg, body) {
1188
1268
  };
1189
1269
  }
1190
1270
  }
1271
+ // Block targets approximating mempool's fastest / half-hour / hour fees.
1272
+ var ESPLORA_TARGETS = {
1273
+ fast: 1,
1274
+ medium: 3,
1275
+ slow: 6
1276
+ };
1277
+ // Backends are untrusted input: reject anything that is not a positive finite number.
1278
+ var assertFeeRate = function(value) {
1279
+ if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
1280
+ throw new Error('invalid fee estimate');
1281
+ }
1282
+ return value;
1283
+ };
1284
+ var pickEstimate = function(estimates, target) {
1285
+ var targets = Object.keys(estimates).map(Number).filter(function(key) {
1286
+ return Number.isFinite(key);
1287
+ }).sort(function(a, b) {
1288
+ return a - b;
1289
+ });
1290
+ if (targets.length === 0) {
1291
+ throw new Error('empty fee estimates');
1292
+ }
1293
+ var _reverse_find;
1294
+ // Closest target not exceeding the wanted one, else the fastest available.
1295
+ var key = (_reverse_find = _to_consumable_array(targets).reverse().find(function(candidate) {
1296
+ return candidate <= target;
1297
+ })) !== null && _reverse_find !== void 0 ? _reverse_find : targets[0];
1298
+ return Math.ceil(assertFeeRate(estimates[String(key)]));
1299
+ };
1191
1300
  /**
1192
- * Fetches current fee rates from mempool.space
1193
- * Returns fees in sat/vByte
1301
+ * Fetches current fee rates in sat/vByte.
1302
+ * Uses the mempool.space `/v1/fees/recommended` endpoint. For a custom Esplora-compatible
1303
+ * `rpcUrl` that does not serve it, falls back to the standard `/fee-estimates` endpoint
1304
+ * on the same backend. Never falls back to a different host.
1194
1305
  *
1195
1306
  * @param network - The Bitcoin network (default: MAINNET)
1196
- * @param rpcUrl - Optional custom RPC URL
1307
+ * @param rpcUrl - Optional custom Esplora-compatible RPC URL
1197
1308
  * @returns The fee rates for fast, medium, and slow transactions
1198
1309
  */ var getFeeRates = /*#__PURE__*/ function() {
1199
1310
  var _ref = _async_to_generator(function(param) {
1200
- var _param_network, network, rpcUrl, baseUrl, response, fees;
1311
+ var _param_network, network, rpcUrl, baseUrl, response, fees, fallback, estimates, rates;
1201
1312
  return _ts_generator(this, function(_state) {
1202
1313
  switch(_state.label){
1203
1314
  case 0:
1204
1315
  _param_network = param.network, network = _param_network === void 0 ? BitcoinNetwork.MAINNET : _param_network, rpcUrl = param.rpcUrl;
1205
- baseUrl = rpcUrl || getDefaultRpcUrl(network);
1316
+ baseUrl = resolveRpcUrl({
1317
+ network: network,
1318
+ rpcUrl: rpcUrl
1319
+ });
1206
1320
  return [
1207
1321
  4,
1208
- fetch("".concat(baseUrl, "/v1/fees/recommended"))
1322
+ rpcFetch("".concat(baseUrl, "/v1/fees/recommended"), rpcUrl)
1209
1323
  ];
1210
1324
  case 1:
1211
1325
  response = _state.sent();
1212
- if (!response.ok) {
1213
- throw new Error("Failed to fetch fee rates: ".concat(response.statusText));
1214
- }
1326
+ if (!response.ok) return [
1327
+ 3,
1328
+ 3
1329
+ ];
1215
1330
  return [
1216
1331
  4,
1217
1332
  response.json()
@@ -1221,9 +1336,41 @@ function _ts_generator(thisArg, body) {
1221
1336
  return [
1222
1337
  2,
1223
1338
  {
1224
- fast: fees.fastestFee,
1225
- medium: fees.halfHourFee,
1226
- slow: fees.hourFee
1339
+ fast: assertFeeRate(fees.fastestFee),
1340
+ medium: assertFeeRate(fees.halfHourFee),
1341
+ slow: assertFeeRate(fees.hourFee)
1342
+ }
1343
+ ];
1344
+ case 3:
1345
+ if (!rpcUrl) {
1346
+ throw new Error("Failed to fetch fee rates: ".concat(response.statusText));
1347
+ }
1348
+ return [
1349
+ 4,
1350
+ rpcFetch("".concat(baseUrl, "/fee-estimates"), rpcUrl)
1351
+ ];
1352
+ case 4:
1353
+ fallback = _state.sent();
1354
+ if (!fallback.ok) {
1355
+ // Report the origin only; custom URLs may embed credentials or API keys in the path.
1356
+ throw new Error("Failed to fetch fee rates from ".concat(new URL(baseUrl).origin, ": ").concat(fallback.statusText, ". ") + 'Provide an explicit feeRate to skip the fee lookup.');
1357
+ }
1358
+ return [
1359
+ 4,
1360
+ fallback.json()
1361
+ ];
1362
+ case 5:
1363
+ estimates = _state.sent();
1364
+ if ((typeof estimates === "undefined" ? "undefined" : _type_of$1(estimates)) !== 'object' || estimates === null || Array.isArray(estimates)) {
1365
+ throw new Error('invalid fee estimates response');
1366
+ }
1367
+ rates = estimates;
1368
+ return [
1369
+ 2,
1370
+ {
1371
+ fast: pickEstimate(rates, ESPLORA_TARGETS.fast),
1372
+ medium: pickEstimate(rates, ESPLORA_TARGETS.medium),
1373
+ slow: pickEstimate(rates, ESPLORA_TARGETS.slow)
1227
1374
  }
1228
1375
  ];
1229
1376
  }
@@ -1743,4 +1890,4 @@ function _type_of(obj) {
1743
1890
  return Buffer.from(formattedMessage).toString('hex');
1744
1891
  };
1745
1892
 
1746
- export { assertSighashAllowed, calculateBip322Hash, calculateTaprootTweak, collectPSBTInputData, computeBip322HashHex, convertSignatureToDER, convertSignatureToTaprootBuffer, createLegacyAddress, createNativeSegWitAddress, createSegWitAddress, createTaprootAddress, doesInputBelongToAddress, encodeBip322Signature, extractPsbtSighashes, extractPublicKeyHex, filterInputsBySigningIndexes, getAddressTypeFromAddress, getAddressTypeFromDerivationPath, getBitcoinNetwork, getDefaultRpcUrl, getFeeRates, getPublicKeyFromPrivateKey, getSegwitV0ScriptCode, getSigHashType, getUTXOs, initEccLib, isP2wshOutputScript, normalizeForCompressed, normalizeForTaproot, normalizePublicKey, privateKeyToWIF, publicKeyToBitcoinAddress, resolveBitcoinAddressType, selectUTXOs, toBitcoinNetwork, toBuffer, wifToPrivateKey };
1893
+ export { assertSighashAllowed, calculateBip322Hash, calculateTaprootTweak, collectPSBTInputData, computeBip322HashHex, convertSignatureToDER, convertSignatureToTaprootBuffer, createLegacyAddress, createNativeSegWitAddress, createSegWitAddress, createTaprootAddress, doesInputBelongToAddress, encodeBip322Signature, extractPsbtSighashes, extractPublicKeyHex, filterInputsBySigningIndexes, getAddressTypeFromAddress, getAddressTypeFromDerivationPath, getBitcoinNetwork, getDefaultRpcUrl, getFeeRates, getPublicKeyFromPrivateKey, getSegwitV0ScriptCode, getSigHashType, getUTXOs, initEccLib, isP2wshOutputScript, normalizeForCompressed, normalizeForTaproot, normalizePublicKey, privateKeyToWIF, publicKeyToBitcoinAddress, resolveBitcoinAddressType, resolveRpcUrl, rpcFetch, selectUTXOs, toBitcoinNetwork, toBuffer, wifToPrivateKey };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@dynamic-labs-wallet/btc-utils",
3
- "version": "1.1.28",
3
+ "version": "1.1.30",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "dependencies": {
8
- "@dynamic-labs-wallet/core": "1.1.28",
8
+ "@dynamic-labs-wallet/core": "1.1.30",
9
9
  "bitcoinjs-lib": "^7.0.0",
10
10
  "bip322-js": "^3.0.0",
11
11
  "@noble/hashes": "1.7.1",
@@ -1,18 +1,22 @@
1
1
  import { BitcoinNetwork } from '@dynamic-labs-wallet/core';
2
+ type FeeRates = {
3
+ fast: number;
4
+ medium: number;
5
+ slow: number;
6
+ };
2
7
  /**
3
- * Fetches current fee rates from mempool.space
4
- * Returns fees in sat/vByte
8
+ * Fetches current fee rates in sat/vByte.
9
+ * Uses the mempool.space `/v1/fees/recommended` endpoint. For a custom Esplora-compatible
10
+ * `rpcUrl` that does not serve it, falls back to the standard `/fee-estimates` endpoint
11
+ * on the same backend. Never falls back to a different host.
5
12
  *
6
13
  * @param network - The Bitcoin network (default: MAINNET)
7
- * @param rpcUrl - Optional custom RPC URL
14
+ * @param rpcUrl - Optional custom Esplora-compatible RPC URL
8
15
  * @returns The fee rates for fast, medium, and slow transactions
9
16
  */
10
17
  export declare const getFeeRates: ({ network, rpcUrl, }: {
11
18
  network?: BitcoinNetwork;
12
19
  rpcUrl?: string;
13
- }) => Promise<{
14
- fast: number;
15
- medium: number;
16
- slow: number;
17
- }>;
20
+ }) => Promise<FeeRates>;
21
+ export {};
18
22
  //# sourceMappingURL=getFeeRates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getFeeRates.d.ts","sourceRoot":"","sources":["../../src/getFeeRates/getFeeRates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,yBAGrB;IACD,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,KAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAkBzD,CAAC"}
1
+ {"version":3,"file":"getFeeRates.d.ts","sourceRoot":"","sources":["../../src/getFeeRates/getFeeRates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,KAAK,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AA2B/D;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,yBAGrB;IACD,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,KAAG,OAAO,CAAC,QAAQ,CAyCnB,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import { BitcoinNetwork } from '@dynamic-labs-wallet/core';
2
2
  import type { UTXO } from '../types.js';
3
3
  /**
4
- * Fetches UTXOs for a given address using mempool.space API
4
+ * Fetches UTXOs for a given address using an Esplora-compatible API (mempool.space by default)
5
5
  *
6
6
  * @param address - The address to fetch UTXOs for
7
7
  * @param network - The Bitcoin network (default: MAINNET)
8
- * @param rpcUrl - Optional custom RPC URL
8
+ * @param rpcUrl - Optional custom Esplora-compatible RPC URL
9
9
  * @returns The list of UTXOs
10
10
  */
11
11
  export declare const getUTXOs: ({ address, network, rpcUrl, }: {
@@ -1 +1 @@
1
- {"version":3,"file":"getUTXOs.d.ts","sourceRoot":"","sources":["../../src/getUTXOs/getUTXOs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,kCAIlB;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,KAAG,OAAO,CAAC,IAAI,EAAE,CAmBjB,CAAC"}
1
+ {"version":3,"file":"getUTXOs.d.ts","sourceRoot":"","sources":["../../src/getUTXOs/getUTXOs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAIxC;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,kCAIlB;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,KAAG,OAAO,CAAC,IAAI,EAAE,CAmBjB,CAAC"}
package/src/index.d.ts CHANGED
@@ -12,6 +12,8 @@ export { getUTXOs } from './getUTXOs/index.js';
12
12
  export { selectUTXOs } from './selectUTXOs/index.js';
13
13
  export { getFeeRates } from './getFeeRates/index.js';
14
14
  export { getDefaultRpcUrl } from './getDefaultRpcUrl/index.js';
15
+ export { resolveRpcUrl } from './resolveRpcUrl/index.js';
16
+ export { rpcFetch } from './rpcFetch/index.js';
15
17
  export { calculateTaprootTweak } from './calculateTaprootTweak/index.js';
16
18
  export { convertSignatureToTaprootBuffer } from './convertSignatureToTaprootBuffer/index.js';
17
19
  export { collectPSBTInputData } from './collectPSBTInputData/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../packages/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAC;AAC/F,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAC5G,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,+BAA+B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../packages/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAC;AAC/F,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAC5G,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,+BAA+B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { resolveRpcUrl } from './resolveRpcUrl.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resolveRpcUrl/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { BitcoinNetwork } from '@dynamic-labs-wallet/core';
2
+ /**
3
+ * Resolves the Esplora-compatible base URL to use for a network.
4
+ * Falls back to the default (mempool.space) when no custom URL is given.
5
+ *
6
+ * @param network - The Bitcoin network
7
+ * @param rpcUrl - Optional custom Esplora-compatible base URL
8
+ * @returns The base URL without a trailing slash
9
+ */
10
+ export declare const resolveRpcUrl: ({ network, rpcUrl }: {
11
+ network: BitcoinNetwork;
12
+ rpcUrl?: string;
13
+ }) => string;
14
+ //# sourceMappingURL=resolveRpcUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveRpcUrl.d.ts","sourceRoot":"","sources":["../../src/resolveRpcUrl/resolveRpcUrl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAKhE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,wBAAyB;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,MAwBjG,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { rpcFetch } from './rpcFetch.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rpcFetch/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * fetch wrapper for Esplora requests. Requests to a custom `rpcUrl` do not follow
3
+ * redirects, so they cannot be bounced to a host other than the configured backend.
4
+ *
5
+ * @param url - The full request URL
6
+ * @param rpcUrl - The custom RPC URL the request was built from, if any
7
+ */
8
+ export declare const rpcFetch: (url: string, rpcUrl?: string) => Promise<Response>;
9
+ //# sourceMappingURL=rpcFetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpcFetch.d.ts","sourceRoot":"","sources":["../../src/rpcFetch/rpcFetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,QAAS,MAAM,WAAW,MAAM,KAAG,OAAO,CAAC,QAAQ,CACf,CAAC"}