@xchainjs/xchain-dash 2.2.3 → 2.2.4

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/lib/index.js CHANGED
@@ -75,7 +75,7 @@ const AssetDASH = { chain: DASHChain, symbol: 'DASH', ticker: 'DASH', type: xcha
75
75
  /**
76
76
  * Explorer provider for Dash mainnet.
77
77
  */
78
- const DASH_MAINNET_EXPLORER = new xchainClient.ExplorerProvider('https://insight.dash.org/insight', 'https://insight.dash.org/insight/address/%%ADDRESS%%', 'https://insight.dash.org/insight/tx/%%TX_ID%%');
78
+ const DASH_MAINNET_EXPLORER = new xchainClient.ExplorerProvider('https://blockchair.com/dash', 'https://blockchair.com/dash/address/%%ADDRESS%%', 'https://blockchair.com/dash/transaction/%%TX_ID%%');
79
79
  /**
80
80
  * Explorer provider for Dash testnet.
81
81
  */
@@ -418,16 +418,16 @@ const G = getGlobal();
418
418
  const FormDataCtor = typeof G.FormData !== 'undefined' ? G.FormData : undefined;
419
419
 
420
420
  const isFormData = (thing) => {
421
- let kind;
422
- return thing && (
423
- (FormDataCtor && thing instanceof FormDataCtor) || (
424
- isFunction$1(thing.append) && (
425
- (kind = kindOf(thing)) === 'formdata' ||
426
- // detect form-data instance
427
- (kind === 'object' && isFunction$1(thing.toString) && thing.toString() === '[object FormData]')
428
- )
429
- )
430
- );
421
+ if (!thing) return false;
422
+ if (FormDataCtor && thing instanceof FormDataCtor) return true;
423
+ // Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData (GHSA-6chq-wfr3-2hj9).
424
+ const proto = getPrototypeOf(thing);
425
+ if (!proto || proto === Object.prototype) return false;
426
+ if (!isFunction$1(thing.append)) return false;
427
+ const kind = kindOf(thing);
428
+ return kind === 'formdata' ||
429
+ // detect form-data instance
430
+ (kind === 'object' && isFunction$1(thing.toString) && thing.toString() === '[object FormData]');
431
431
  };
432
432
 
433
433
  /**
@@ -1094,40 +1094,40 @@ let AxiosError$1 = class AxiosError extends Error {
1094
1094
  return axiosError;
1095
1095
  }
1096
1096
 
1097
- /**
1098
- * Create an Error with the specified message, config, error code, request and response.
1099
- *
1100
- * @param {string} message The error message.
1101
- * @param {string} [code] The error code (for example, 'ECONNABORTED').
1102
- * @param {Object} [config] The config.
1103
- * @param {Object} [request] The request.
1104
- * @param {Object} [response] The response.
1105
- *
1106
- * @returns {Error} The created error.
1107
- */
1108
- constructor(message, code, config, request, response) {
1109
- super(message);
1110
-
1111
- // Make message enumerable to maintain backward compatibility
1112
- // The native Error constructor sets message as non-enumerable,
1113
- // but axios < v1.13.3 had it as enumerable
1114
- Object.defineProperty(this, 'message', {
1115
- value: message,
1116
- enumerable: true,
1117
- writable: true,
1118
- configurable: true
1119
- });
1120
-
1121
- this.name = 'AxiosError';
1122
- this.isAxiosError = true;
1123
- code && (this.code = code);
1124
- config && (this.config = config);
1125
- request && (this.request = request);
1126
- if (response) {
1127
- this.response = response;
1128
- this.status = response.status;
1129
- }
1097
+ /**
1098
+ * Create an Error with the specified message, config, error code, request and response.
1099
+ *
1100
+ * @param {string} message The error message.
1101
+ * @param {string} [code] The error code (for example, 'ECONNABORTED').
1102
+ * @param {Object} [config] The config.
1103
+ * @param {Object} [request] The request.
1104
+ * @param {Object} [response] The response.
1105
+ *
1106
+ * @returns {Error} The created error.
1107
+ */
1108
+ constructor(message, code, config, request, response) {
1109
+ super(message);
1110
+
1111
+ // Make message enumerable to maintain backward compatibility
1112
+ // The native Error constructor sets message as non-enumerable,
1113
+ // but axios < v1.13.3 had it as enumerable
1114
+ Object.defineProperty(this, 'message', {
1115
+ value: message,
1116
+ enumerable: true,
1117
+ writable: true,
1118
+ configurable: true,
1119
+ });
1120
+
1121
+ this.name = 'AxiosError';
1122
+ this.isAxiosError = true;
1123
+ code && (this.code = code);
1124
+ config && (this.config = config);
1125
+ request && (this.request = request);
1126
+ if (response) {
1127
+ this.response = response;
1128
+ this.status = response.status;
1130
1129
  }
1130
+ }
1131
1131
 
1132
1132
  toJSON() {
1133
1133
  return {
@@ -1163,6 +1163,7 @@ AxiosError$1.ERR_BAD_REQUEST = 'ERR_BAD_REQUEST';
1163
1163
  AxiosError$1.ERR_CANCELED = 'ERR_CANCELED';
1164
1164
  AxiosError$1.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT';
1165
1165
  AxiosError$1.ERR_INVALID_URL = 'ERR_INVALID_URL';
1166
+ AxiosError$1.ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED';
1166
1167
 
1167
1168
  // eslint-disable-next-line strict
1168
1169
  var httpAdapter = null;
@@ -1277,6 +1278,7 @@ function toFormData$1(obj, formData, options) {
1277
1278
  const dots = options.dots;
1278
1279
  const indexes = options.indexes;
1279
1280
  const _Blob = options.Blob || (typeof Blob !== 'undefined' && Blob);
1281
+ const maxDepth = options.maxDepth === undefined ? 100 : options.maxDepth;
1280
1282
  const useBlob = _Blob && utils$1.isSpecCompliantForm(formData);
1281
1283
 
1282
1284
  if (!utils$1.isFunction(visitor)) {
@@ -1369,9 +1371,16 @@ function toFormData$1(obj, formData, options) {
1369
1371
  isVisitable,
1370
1372
  });
1371
1373
 
1372
- function build(value, path) {
1374
+ function build(value, path, depth = 0) {
1373
1375
  if (utils$1.isUndefined(value)) return;
1374
1376
 
1377
+ if (depth > maxDepth) {
1378
+ throw new AxiosError$1(
1379
+ 'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth,
1380
+ AxiosError$1.ERR_FORM_DATA_DEPTH_EXCEEDED
1381
+ );
1382
+ }
1383
+
1375
1384
  if (stack.indexOf(value) !== -1) {
1376
1385
  throw Error('Circular reference detected in ' + path.join('.'));
1377
1386
  }
@@ -1384,7 +1393,7 @@ function toFormData$1(obj, formData, options) {
1384
1393
  visitor.call(formData, el, utils$1.isString(key) ? key.trim() : key, path, exposedHelpers);
1385
1394
 
1386
1395
  if (result === true) {
1387
- build(el, path ? path.concat(key) : [key]);
1396
+ build(el, path ? path.concat(key) : [key], depth + 1);
1388
1397
  }
1389
1398
  });
1390
1399
 
@@ -1416,9 +1425,8 @@ function encode$1(str) {
1416
1425
  ')': '%29',
1417
1426
  '~': '%7E',
1418
1427
  '%20': '+',
1419
- '%00': '\x00',
1420
1428
  };
1421
- return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) {
1429
+ return encodeURIComponent(str).replace(/[!'()~]|%20/g, function replacer(match) {
1422
1430
  return charMap[match];
1423
1431
  });
1424
1432
  }
@@ -1738,7 +1746,9 @@ function formDataToJSON(formData) {
1738
1746
 
1739
1747
  if (isLast) {
1740
1748
  if (utils$1.hasOwnProp(target, name)) {
1741
- target[name] = [target[name], value];
1749
+ target[name] = utils$1.isArray(target[name])
1750
+ ? target[name].concat(value)
1751
+ : [target[name], value];
1742
1752
  } else {
1743
1753
  target[name] = value;
1744
1754
  }
@@ -1772,6 +1782,8 @@ function formDataToJSON(formData) {
1772
1782
  return null;
1773
1783
  }
1774
1784
 
1785
+ const own = (obj, key) => (obj != null && utils$1.hasOwnProp(obj, key) ? obj[key] : undefined);
1786
+
1775
1787
  /**
1776
1788
  * It takes a string, tries to parse it, and if it fails, it returns the stringified version
1777
1789
  * of the input
@@ -1839,20 +1851,22 @@ const defaults = {
1839
1851
  let isFileList;
1840
1852
 
1841
1853
  if (isObjectPayload) {
1854
+ const formSerializer = own(this, 'formSerializer');
1842
1855
  if (contentType.indexOf('application/x-www-form-urlencoded') > -1) {
1843
- return toURLEncodedForm(data, this.formSerializer).toString();
1856
+ return toURLEncodedForm(data, formSerializer).toString();
1844
1857
  }
1845
1858
 
1846
1859
  if (
1847
1860
  (isFileList = utils$1.isFileList(data)) ||
1848
1861
  contentType.indexOf('multipart/form-data') > -1
1849
1862
  ) {
1850
- const _FormData = this.env && this.env.FormData;
1863
+ const env = own(this, 'env');
1864
+ const _FormData = env && env.FormData;
1851
1865
 
1852
1866
  return toFormData$1(
1853
1867
  isFileList ? { 'files[]': data } : data,
1854
1868
  _FormData && new _FormData(),
1855
- this.formSerializer
1869
+ formSerializer
1856
1870
  );
1857
1871
  }
1858
1872
  }
@@ -1868,9 +1882,10 @@ const defaults = {
1868
1882
 
1869
1883
  transformResponse: [
1870
1884
  function transformResponse(data) {
1871
- const transitional = this.transitional || defaults.transitional;
1885
+ const transitional = own(this, 'transitional') || defaults.transitional;
1872
1886
  const forcedJSONParsing = transitional && transitional.forcedJSONParsing;
1873
- const JSONRequested = this.responseType === 'json';
1887
+ const responseType = own(this, 'responseType');
1888
+ const JSONRequested = responseType === 'json';
1874
1889
 
1875
1890
  if (utils$1.isResponse(data) || utils$1.isReadableStream(data)) {
1876
1891
  return data;
@@ -1879,17 +1894,17 @@ const defaults = {
1879
1894
  if (
1880
1895
  data &&
1881
1896
  utils$1.isString(data) &&
1882
- ((forcedJSONParsing && !this.responseType) || JSONRequested)
1897
+ ((forcedJSONParsing && !responseType) || JSONRequested)
1883
1898
  ) {
1884
1899
  const silentJSONParsing = transitional && transitional.silentJSONParsing;
1885
1900
  const strictJSONParsing = !silentJSONParsing && JSONRequested;
1886
1901
 
1887
1902
  try {
1888
- return JSON.parse(data, this.parseReviver);
1903
+ return JSON.parse(data, own(this, 'parseReviver'));
1889
1904
  } catch (e) {
1890
1905
  if (strictJSONParsing) {
1891
1906
  if (e.name === 'SyntaxError') {
1892
- throw AxiosError$1.from(e, AxiosError$1.ERR_BAD_RESPONSE, this, null, this.response);
1907
+ throw AxiosError$1.from(e, AxiosError$1.ERR_BAD_RESPONSE, this, null, own(this, 'response'));
1893
1908
  }
1894
1909
  throw e;
1895
1910
  }
@@ -2001,41 +2016,41 @@ var parseHeaders = (rawHeaders) => {
2001
2016
 
2002
2017
  const $internals = Symbol('internals');
2003
2018
 
2004
- const isValidHeaderValue = (value) => !/[\r\n]/.test(value);
2019
+ const INVALID_HEADER_VALUE_CHARS_RE = /[^\x09\x20-\x7E\x80-\xFF]/g;
2005
2020
 
2006
- function assertValidHeaderValue(value, header) {
2007
- if (value === false || value == null) {
2008
- return;
2009
- }
2010
-
2011
- if (utils$1.isArray(value)) {
2012
- value.forEach((v) => assertValidHeaderValue(v, header));
2013
- return;
2014
- }
2021
+ function trimSPorHTAB(str) {
2022
+ let start = 0;
2023
+ let end = str.length;
2015
2024
 
2016
- if (!isValidHeaderValue(String(value))) {
2017
- throw new Error(`Invalid character in header content ["${header}"]`);
2018
- }
2019
- }
2025
+ while (start < end) {
2026
+ const code = str.charCodeAt(start);
2020
2027
 
2021
- function normalizeHeader(header) {
2022
- return header && String(header).trim().toLowerCase();
2023
- }
2028
+ if (code !== 0x09 && code !== 0x20) {
2029
+ break;
2030
+ }
2024
2031
 
2025
- function stripTrailingCRLF(str) {
2026
- let end = str.length;
2032
+ start += 1;
2033
+ }
2027
2034
 
2028
- while (end > 0) {
2029
- const charCode = str.charCodeAt(end - 1);
2035
+ while (end > start) {
2036
+ const code = str.charCodeAt(end - 1);
2030
2037
 
2031
- if (charCode !== 10 && charCode !== 13) {
2038
+ if (code !== 0x09 && code !== 0x20) {
2032
2039
  break;
2033
2040
  }
2034
2041
 
2035
2042
  end -= 1;
2036
2043
  }
2037
2044
 
2038
- return end === str.length ? str : str.slice(0, end);
2045
+ return start === 0 && end === str.length ? str : str.slice(start, end);
2046
+ }
2047
+
2048
+ function normalizeHeader(header) {
2049
+ return header && String(header).trim().toLowerCase();
2050
+ }
2051
+
2052
+ function sanitizeHeaderValue(str) {
2053
+ return trimSPorHTAB(str.replace(INVALID_HEADER_VALUE_CHARS_RE, ''));
2039
2054
  }
2040
2055
 
2041
2056
  function normalizeValue(value) {
@@ -2043,7 +2058,7 @@ function normalizeValue(value) {
2043
2058
  return value;
2044
2059
  }
2045
2060
 
2046
- return utils$1.isArray(value) ? value.map(normalizeValue) : stripTrailingCRLF(String(value));
2061
+ return utils$1.isArray(value) ? value.map(normalizeValue) : sanitizeHeaderValue(String(value));
2047
2062
  }
2048
2063
 
2049
2064
  function parseTokens(str) {
@@ -2125,7 +2140,6 @@ let AxiosHeaders$1 = class AxiosHeaders {
2125
2140
  _rewrite === true ||
2126
2141
  (_rewrite === undefined && self[key] !== false)
2127
2142
  ) {
2128
- assertValidHeaderValue(_value, _header);
2129
2143
  self[key || _header] = normalizeValue(_value);
2130
2144
  }
2131
2145
  }
@@ -2548,13 +2562,13 @@ const progressEventReducer = (listener, isDownloadStream, freq = 3) => {
2548
2562
  const _speedometer = speedometer(50, 250);
2549
2563
 
2550
2564
  return throttle((e) => {
2551
- const loaded = e.loaded;
2565
+ const rawLoaded = e.loaded;
2552
2566
  const total = e.lengthComputable ? e.total : undefined;
2553
- const progressBytes = loaded - bytesNotified;
2567
+ const loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded;
2568
+ const progressBytes = Math.max(0, loaded - bytesNotified);
2554
2569
  const rate = _speedometer(progressBytes);
2555
- const inRange = loaded <= total;
2556
2570
 
2557
- bytesNotified = loaded;
2571
+ bytesNotified = Math.max(bytesNotified, loaded);
2558
2572
 
2559
2573
  const data = {
2560
2574
  loaded,
@@ -2562,7 +2576,7 @@ const progressEventReducer = (listener, isDownloadStream, freq = 3) => {
2562
2576
  progress: total ? loaded / total : undefined,
2563
2577
  bytes: progressBytes,
2564
2578
  rate: rate ? rate : undefined,
2565
- estimated: rate && total && inRange ? (total - loaded) / rate : undefined,
2579
+ estimated: rate && total ? (total - loaded) / rate : undefined,
2566
2580
  event: e,
2567
2581
  lengthComputable: total != null,
2568
2582
  [isDownloadStream ? 'download' : 'upload']: true,
@@ -2696,7 +2710,7 @@ function combineURLs(baseURL, relativeURL) {
2696
2710
  */
2697
2711
  function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) {
2698
2712
  let isRelativeUrl = !isAbsoluteURL(requestedURL);
2699
- if (baseURL && (isRelativeUrl || allowAbsoluteUrls == false)) {
2713
+ if (baseURL && (isRelativeUrl || allowAbsoluteUrls === false)) {
2700
2714
  return combineURLs(baseURL, requestedURL);
2701
2715
  }
2702
2716
  return requestedURL;
@@ -2716,7 +2730,18 @@ const headersToObject = (thing) => (thing instanceof AxiosHeaders$1 ? { ...thing
2716
2730
  function mergeConfig$1(config1, config2) {
2717
2731
  // eslint-disable-next-line no-param-reassign
2718
2732
  config2 = config2 || {};
2719
- const config = {};
2733
+
2734
+ // Use a null-prototype object so that downstream reads such as `config.auth`
2735
+ // or `config.baseURL` cannot inherit polluted values from Object.prototype
2736
+ // (see GHSA-q8qp-cvcw-x6jj). `hasOwnProperty` is restored as a non-enumerable
2737
+ // own slot to preserve ergonomics for user code that relies on it.
2738
+ const config = Object.create(null);
2739
+ Object.defineProperty(config, 'hasOwnProperty', {
2740
+ value: Object.prototype.hasOwnProperty,
2741
+ enumerable: false,
2742
+ writable: true,
2743
+ configurable: true,
2744
+ });
2720
2745
 
2721
2746
  function getMergedValue(target, source, prop, caseless) {
2722
2747
  if (utils$1.isPlainObject(target) && utils$1.isPlainObject(source)) {
@@ -2755,9 +2780,9 @@ function mergeConfig$1(config1, config2) {
2755
2780
 
2756
2781
  // eslint-disable-next-line consistent-return
2757
2782
  function mergeDirectKeys(a, b, prop) {
2758
- if (prop in config2) {
2783
+ if (utils$1.hasOwnProp(config2, prop)) {
2759
2784
  return getMergedValue(a, b);
2760
- } else if (prop in config1) {
2785
+ } else if (utils$1.hasOwnProp(config1, prop)) {
2761
2786
  return getMergedValue(undefined, a);
2762
2787
  }
2763
2788
  }
@@ -2789,6 +2814,7 @@ function mergeConfig$1(config1, config2) {
2789
2814
  httpsAgent: defaultToConfig2,
2790
2815
  cancelToken: defaultToConfig2,
2791
2816
  socketPath: defaultToConfig2,
2817
+ allowedSocketPaths: defaultToConfig2,
2792
2818
  responseEncoding: defaultToConfig2,
2793
2819
  validateStatus: mergeDirectKeys,
2794
2820
  headers: (a, b, prop) =>
@@ -2798,7 +2824,9 @@ function mergeConfig$1(config1, config2) {
2798
2824
  utils$1.forEach(Object.keys({ ...config1, ...config2 }), function computeConfigValue(prop) {
2799
2825
  if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') return;
2800
2826
  const merge = utils$1.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : mergeDeepProperties;
2801
- const configValue = merge(config1[prop], config2[prop], prop);
2827
+ const a = utils$1.hasOwnProp(config1, prop) ? config1[prop] : undefined;
2828
+ const b = utils$1.hasOwnProp(config2, prop) ? config2[prop] : undefined;
2829
+ const configValue = merge(a, b, prop);
2802
2830
  (utils$1.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);
2803
2831
  });
2804
2832
 
@@ -2808,12 +2836,24 @@ function mergeConfig$1(config1, config2) {
2808
2836
  var resolveConfig = (config) => {
2809
2837
  const newConfig = mergeConfig$1({}, config);
2810
2838
 
2811
- let { data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth } = newConfig;
2839
+ // Read only own properties to prevent prototype pollution gadgets
2840
+ // (e.g. Object.prototype.baseURL = 'https://evil.com'). See GHSA-q8qp-cvcw-x6jj.
2841
+ const own = (key) => (utils$1.hasOwnProp(newConfig, key) ? newConfig[key] : undefined);
2842
+
2843
+ const data = own('data');
2844
+ let withXSRFToken = own('withXSRFToken');
2845
+ const xsrfHeaderName = own('xsrfHeaderName');
2846
+ const xsrfCookieName = own('xsrfCookieName');
2847
+ let headers = own('headers');
2848
+ const auth = own('auth');
2849
+ const baseURL = own('baseURL');
2850
+ const allowAbsoluteUrls = own('allowAbsoluteUrls');
2851
+ const url = own('url');
2812
2852
 
2813
2853
  newConfig.headers = headers = AxiosHeaders$1.from(headers);
2814
2854
 
2815
2855
  newConfig.url = buildURL(
2816
- buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls),
2856
+ buildFullPath(baseURL, url, allowAbsoluteUrls),
2817
2857
  config.params,
2818
2858
  config.paramsSerializer
2819
2859
  );
@@ -2852,10 +2892,18 @@ var resolveConfig = (config) => {
2852
2892
  // Specifically not if we're in a web worker, or react-native.
2853
2893
 
2854
2894
  if (platform.hasStandardBrowserEnv) {
2855
- withXSRFToken && utils$1.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig));
2895
+ if (utils$1.isFunction(withXSRFToken)) {
2896
+ withXSRFToken = withXSRFToken(newConfig);
2897
+ }
2856
2898
 
2857
- if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(newConfig.url))) {
2858
- // Add xsrf header
2899
+ // Strict boolean check prevents proto-pollution gadgets (e.g. Object.prototype.withXSRFToken = 1)
2900
+ // and misconfigurations (e.g. "false") from short-circuiting the same-origin check and leaking
2901
+ // the XSRF token cross-origin. See GHSA-xx6v-rp6x-q39c.
2902
+ const shouldSendXSRF =
2903
+ withXSRFToken === true ||
2904
+ (withXSRFToken == null && isURLSameOrigin(newConfig.url));
2905
+
2906
+ if (shouldSendXSRF) {
2859
2907
  const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName);
2860
2908
 
2861
2909
  if (xsrfValue) {
@@ -3274,18 +3322,20 @@ const factory = (env) => {
3274
3322
  test(() => {
3275
3323
  let duplexAccessed = false;
3276
3324
 
3277
- const body = new ReadableStream$1();
3278
-
3279
- const hasContentType = new Request(platform.origin, {
3280
- body,
3325
+ const request = new Request(platform.origin, {
3326
+ body: new ReadableStream$1(),
3281
3327
  method: 'POST',
3282
3328
  get duplex() {
3283
3329
  duplexAccessed = true;
3284
3330
  return 'half';
3285
3331
  },
3286
- }).headers.has('Content-Type');
3332
+ });
3287
3333
 
3288
- body.cancel();
3334
+ const hasContentType = request.headers.has('Content-Type');
3335
+
3336
+ if (request.body != null) {
3337
+ request.body.cancel();
3338
+ }
3289
3339
 
3290
3340
  return duplexAccessed && !hasContentType;
3291
3341
  });
@@ -3429,6 +3479,19 @@ const factory = (env) => {
3429
3479
  // see https://github.com/cloudflare/workerd/issues/902
3430
3480
  const isCredentialsSupported = isRequestSupported && 'credentials' in Request.prototype;
3431
3481
 
3482
+ // If data is FormData and Content-Type is multipart/form-data without boundary,
3483
+ // delete it so fetch can set it correctly with the boundary
3484
+ if (utils$1.isFormData(data)) {
3485
+ const contentType = headers.getContentType();
3486
+ if (
3487
+ contentType &&
3488
+ /^multipart\/form-data/i.test(contentType) &&
3489
+ !/boundary=/i.test(contentType)
3490
+ ) {
3491
+ headers.delete('content-type');
3492
+ }
3493
+ }
3494
+
3432
3495
  const resolvedOptions = {
3433
3496
  ...fetchOptions,
3434
3497
  signal: composedSignal,
@@ -3737,7 +3800,7 @@ function dispatchRequest(config) {
3737
3800
  );
3738
3801
  }
3739
3802
 
3740
- const VERSION$1 = "1.15.0";
3803
+ const VERSION$1 = "1.15.2";
3741
3804
 
3742
3805
  const validators$1 = {};
3743
3806
 
@@ -3822,7 +3885,9 @@ function assertOptions(options, schema, allowUnknown) {
3822
3885
  let i = keys.length;
3823
3886
  while (i-- > 0) {
3824
3887
  const opt = keys[i];
3825
- const validator = schema[opt];
3888
+ // Use hasOwnProperty so a polluted Object.prototype.<opt> cannot supply
3889
+ // a non-function validator and cause a TypeError. See GHSA-q8qp-cvcw-x6jj.
3890
+ const validator = Object.prototype.hasOwnProperty.call(schema, opt) ? schema[opt] : undefined;
3826
3891
  if (validator) {
3827
3892
  const value = options[opt];
3828
3893
  const result = value === undefined || validator(value, opt, options);
@@ -4455,26 +4520,6 @@ const urlForNetwork = (network) => {
4455
4520
  return 'http://insight.testnet.networks.dash.org:3001/insight-api';
4456
4521
  }
4457
4522
  };
4458
- /**
4459
- * Fetch address details from the Insight API.
4460
- *
4461
- * @param {InsightAddressParams} p Parameters for fetching address details.
4462
- * @returns {Promise<InsightAddressResponse>} Address details fetched from the Insight API.
4463
- */
4464
- const getAddress = (p) => __awaiter(void 0, void 0, void 0, function* () {
4465
- const data = (yield axios.get(`${urlForNetwork(p.network)}/addr/${p.address}`)).data;
4466
- return data;
4467
- });
4468
- /**
4469
- * Fetch transactions associated with an address from the Insight API.
4470
- *
4471
- * @param {InsightAddressParams} p Parameters for fetching address transactions.
4472
- * @returns {Promise<{ txs: InsightTxResponse[]; pagesTotal: number }>} Transactions associated with the address.
4473
- */
4474
- const getAddressTxs = (p) => __awaiter(void 0, void 0, void 0, function* () {
4475
- const pageNum = (p === null || p === void 0 ? void 0 : p.pageNum) || 0;
4476
- return (yield axios.get(`${urlForNetwork(p.network)}/txs?address=${p.address}&pageNum=${pageNum}`)).data;
4477
- });
4478
4523
  /**
4479
4524
  * Fetch UTXOs associated with an address from the Insight API.
4480
4525
  *
@@ -4484,15 +4529,6 @@ const getAddressTxs = (p) => __awaiter(void 0, void 0, void 0, function* () {
4484
4529
  const getAddressUtxos = (p) => __awaiter(void 0, void 0, void 0, function* () {
4485
4530
  return (yield axios.get(`${urlForNetwork(p.network)}/addr/${p.address}/utxo`)).data;
4486
4531
  });
4487
- /**
4488
- * Fetch transaction details from the Insight API.
4489
- *
4490
- * @param {InsightTransactionParams} p Parameters for fetching transaction details.
4491
- * @returns {Promise<InsightTxResponse>} Transaction details fetched from the Insight API.
4492
- */
4493
- const getTx = (p) => __awaiter(void 0, void 0, void 0, function* () {
4494
- return (yield axios.get(`${urlForNetwork(p.network)}/tx/${p.txid}`)).data;
4495
- });
4496
4532
  /**
4497
4533
  * Fetch raw transaction data from the Insight API.
4498
4534
  *
@@ -4644,7 +4680,7 @@ const defaultDashParams = {
4644
4680
  network: xchainClient.Network.Mainnet,
4645
4681
  phrase: '',
4646
4682
  explorerProviders: explorerProviders,
4647
- dataProviders: [BitgoProviders, BlockcypherDataProviders],
4683
+ dataProviders: [BlockcypherDataProviders, BitgoProviders],
4648
4684
  rootDerivationPaths: {
4649
4685
  [xchainClient.Network.Mainnet]: `m/44'/5'/0'/0/`,
4650
4686
  [xchainClient.Network.Stagenet]: `m/44'/5'/0'/0/`,
@@ -4695,120 +4731,6 @@ class Client extends xchainUtxo.Client {
4695
4731
  validateAddress(address) {
4696
4732
  return validateAddress(address, this.network);
4697
4733
  }
4698
- /**
4699
- * Asynchronously get the balance for a DASH address.
4700
- * @param {string} address The DASH address.
4701
- * @returns {Promise<Balance[]>} A promise resolving to an array of balances.
4702
- */
4703
- getBalance(address) {
4704
- return __awaiter(this, void 0, void 0, function* () {
4705
- const addressResponse = yield getAddress({ network: this.network, address });
4706
- const confirmed = xchainUtil.baseAmount(addressResponse.balanceSat);
4707
- const unconfirmed = xchainUtil.baseAmount(addressResponse.unconfirmedBalanceSat);
4708
- return [
4709
- {
4710
- asset: AssetDASH,
4711
- amount: confirmed.plus(unconfirmed),
4712
- },
4713
- ];
4714
- });
4715
- }
4716
- /**
4717
- * Asynchronously retrieves transactions for a given address.
4718
- * @param {TxHistoryParams} params - Parameters for transaction retrieval.
4719
- * @returns {Promise<TxsPage>} A promise resolving to a page of transactions.
4720
- */
4721
- getTransactions(params) {
4722
- return __awaiter(this, void 0, void 0, function* () {
4723
- var _a;
4724
- // Extract offset and limit from parameters or set default values
4725
- const offset = (_a = params === null || params === void 0 ? void 0 : params.offset) !== null && _a !== void 0 ? _a : 0;
4726
- const limit = (params === null || params === void 0 ? void 0 : params.limit) || 10;
4727
- // Insight uses pages rather than offset/limit indexes, so we have to
4728
- // iterate through each page within the offset/limit range.
4729
- const perPage = 10;
4730
- const startPage = Math.floor(offset / perPage);
4731
- const endPage = Math.floor((offset + limit - 1) / perPage);
4732
- const firstPageOffset = offset % perPage;
4733
- const lastPageLimit = (firstPageOffset + (limit - 1)) % perPage;
4734
- let totalPages = -1;
4735
- let lastPageTotal = -1;
4736
- let insightTxs = [];
4737
- // Iterate through each page within the offset/limit range
4738
- for (let pageNum = startPage; pageNum <= endPage; pageNum++) {
4739
- const response = yield getAddressTxs({
4740
- network: this.network,
4741
- address: `${params === null || params === void 0 ? void 0 : params.address}`,
4742
- pageNum,
4743
- });
4744
- let startIndex = 0;
4745
- let endIndex = perPage - 1;
4746
- if (pageNum == startPage) {
4747
- startIndex = firstPageOffset;
4748
- }
4749
- if (pageNum === endPage) {
4750
- endIndex = lastPageLimit;
4751
- }
4752
- insightTxs = [...insightTxs, ...response.txs.slice(startIndex, endIndex + 1)];
4753
- // Insight only returns the number of pages not the total number of
4754
- // transactions. If the last page is within the offset/limit range then we
4755
- // can set the lastPageTotal here and avoid having to send another request,
4756
- // otherwise we can fetch the last page later to determine the total
4757
- // transaction count
4758
- totalPages = response.pagesTotal;
4759
- if (pageNum === totalPages - 1) {
4760
- lastPageTotal = response.txs.length;
4761
- }
4762
- }
4763
- // Map insight transactions to XChain transactions
4764
- const txs = insightTxs.map(this.insightTxToXChainTx);
4765
- // Fetch transactions count for last page if not obtained
4766
- if (lastPageTotal < 0) {
4767
- const lastPageResponse = yield getAddressTxs({
4768
- network: this.network,
4769
- address: `${params === null || params === void 0 ? void 0 : params.address}`,
4770
- pageNum: totalPages - 1,
4771
- });
4772
- lastPageTotal = lastPageResponse.txs.length;
4773
- }
4774
- // Calculate total transactions count and return the page of transactions
4775
- return {
4776
- total: (totalPages - 1) * perPage + lastPageTotal,
4777
- txs,
4778
- };
4779
- });
4780
- }
4781
- /**
4782
- * Asynchronously retrieves transaction data for a given transaction ID.
4783
- * @param {string} txid - The transaction ID.
4784
- * @returns {Promise<Tx>} A promise resolving to the transaction data.
4785
- */
4786
- getTransactionData(txid) {
4787
- return __awaiter(this, void 0, void 0, function* () {
4788
- const tx = yield getTx({ network: this.network, txid });
4789
- return this.insightTxToXChainTx(tx);
4790
- });
4791
- }
4792
- /**
4793
- * Converts an Insight transaction response to XChain transaction.
4794
- * @param {InsightTxResponse} tx - The Insight transaction response.
4795
- * @returns {Tx} The XChain transaction.
4796
- */
4797
- insightTxToXChainTx(tx) {
4798
- return {
4799
- asset: AssetDASH,
4800
- from: tx.vin.map((i) => ({
4801
- from: i.addr,
4802
- amount: xchainUtil.assetToBase(xchainUtil.assetAmount(i.value)),
4803
- })),
4804
- to: tx.vout
4805
- .filter((i) => i.scriptPubKey.type !== 'nulldata')
4806
- .map((i) => { var _a; return ({ to: (_a = i.scriptPubKey.addresses) === null || _a === void 0 ? void 0 : _a[0], amount: xchainUtil.assetToBase(xchainUtil.assetAmount(i.value)) }); }),
4807
- date: new Date(tx.time * 1000),
4808
- type: xchainClient.TxType.Transfer,
4809
- hash: tx.txid,
4810
- };
4811
- }
4812
4734
  /**
4813
4735
  * Asynchronously prepares a transaction for sending assets.
4814
4736
  * @deprecated Use `prepareTxEnhanced` instead for better UTXO selection and error handling.
@@ -4878,6 +4800,15 @@ class Client extends xchainUtxo.Client {
4878
4800
  // Ensure fee meets minimum requirement
4879
4801
  return fee > TX_MIN_FEE ? fee : TX_MIN_FEE;
4880
4802
  }
4803
+ getUtxoScriptHex(utxo) {
4804
+ var _a;
4805
+ // Providers may populate either scriptPubKey (Insight) or witnessUtxo.script (Blockcypher)
4806
+ const scriptHex = utxo.scriptPubKey || ((_a = utxo.witnessUtxo) === null || _a === void 0 ? void 0 : _a.script.toString('hex'));
4807
+ if (!scriptHex) {
4808
+ throw xchainUtxo.UtxoError.validationError(`UTXO ${utxo.hash}:${utxo.index} is missing scriptPubKey and witnessUtxo.script`);
4809
+ }
4810
+ return scriptHex;
4811
+ }
4881
4812
  // ==================== Enhanced Transaction Methods ====================
4882
4813
  /**
4883
4814
  * Prepare transaction with enhanced UTXO selection.
@@ -4913,7 +4844,7 @@ class Client extends xchainUtxo.Client {
4913
4844
  const tx = new dashcore__default.default.Transaction().to(recipient, targetValue);
4914
4845
  // Add selected inputs
4915
4846
  for (const utxo of selectionResult.inputs) {
4916
- const scriptBuffer = Buffer.from(utxo.scriptPubKey || '', 'hex');
4847
+ const scriptBuffer = Buffer.from(this.getUtxoScriptHex(utxo), 'hex');
4917
4848
  const script = new dashcore__default.default.Script(scriptBuffer);
4918
4849
  const input = new dashcore__default.default.Transaction.Input.PublicKeyHash({
4919
4850
  prevTxId: Buffer.from(utxo.hash, 'hex'),
@@ -4974,7 +4905,7 @@ class Client extends xchainUtxo.Client {
4974
4905
  const tx = new dashcore__default.default.Transaction().to(recipient, maxCalc.amount);
4975
4906
  // Add inputs
4976
4907
  for (const utxo of maxCalc.inputs) {
4977
- const scriptBuffer = Buffer.from(utxo.scriptPubKey || '', 'hex');
4908
+ const scriptBuffer = Buffer.from(this.getUtxoScriptHex(utxo), 'hex');
4978
4909
  const script = new dashcore__default.default.Script(scriptBuffer);
4979
4910
  const input = new dashcore__default.default.Transaction.Input.PublicKeyHash({
4980
4911
  prevTxId: Buffer.from(utxo.hash, 'hex'),
@@ -5011,37 +4942,6 @@ class Client extends xchainUtxo.Client {
5011
4942
  }
5012
4943
  }
5013
4944
 
5014
- /**
5015
- * Function to broadcast a transaction to the Dash network.
5016
- *
5017
- * @param {BroadcastTxParams} params Parameters for broadcasting the transaction.
5018
- * @returns {Promise<TxHash>} Promise that resolves with the transaction hash if successful, or rejects with an error message if unsuccessful.
5019
- */
5020
- const broadcastTx = (params) => __awaiter(void 0, void 0, void 0, function* () {
5021
- const uniqueId = new Date().getTime().toString(); // Generate a unique identifier for the transaction request.
5022
- try {
5023
- const response = (yield axios.post(`${params.nodeUrl}/tx/send`, // URL endpoint for broadcasting the transaction.
5024
- {
5025
- jsonrpc: '2.0',
5026
- rawtx: [params.txHex], // Include the hexadecimal transaction in the request body.
5027
- id: uniqueId,
5028
- }, {
5029
- auth: params.auth, // Include authentication credentials if provided.
5030
- timeout: 30 * 1000, // Set a timeout for the request.
5031
- })).data;
5032
- if (response.error) {
5033
- // If there is an error in the response, reject the promise with the error message.
5034
- return Promise.reject(Error(`failed to broadcast a transaction: ${response.error}`));
5035
- }
5036
- // If no error, return the transaction ID indicating successful broadcast.
5037
- return response.txid;
5038
- }
5039
- catch (ex) {
5040
- // If an exception occurs during the request, reject the promise with the caught error message.
5041
- return Promise.reject(Error(`failed to broadcast a transaction caught: ${String(ex)}`));
5042
- }
5043
- });
5044
-
5045
4945
  const ECPair = ecpair.ECPairFactory(ecc__namespace);
5046
4946
  class ClientKeystore extends Client {
5047
4947
  /**
@@ -5114,13 +5014,16 @@ class ClientKeystore extends Client {
5114
5014
  const tx = new dashcore__default.default.Transaction(rawUnsignedTx);
5115
5015
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5116
5016
  tx.inputs.forEach((input, index) => {
5017
+ var _a;
5117
5018
  const insightUtxo = utxos.find((utxo) => {
5118
5019
  return utxo.hash === input.prevTxId.toString('hex') && utxo.index == input.outputIndex;
5119
5020
  });
5120
5021
  if (!insightUtxo) {
5121
5022
  throw new Error('Unable to match accumulative inputs with insight utxos');
5122
5023
  }
5123
- const scriptBuffer = Buffer.from(insightUtxo.scriptPubKey || '', 'hex');
5024
+ // Providers may populate either scriptPubKey (Insight) or witnessUtxo.script (Blockcypher)
5025
+ const scriptHex = insightUtxo.scriptPubKey || ((_a = insightUtxo.witnessUtxo) === null || _a === void 0 ? void 0 : _a.script.toString('hex')) || '';
5026
+ const scriptBuffer = Buffer.from(scriptHex, 'hex');
5124
5027
  const script = new dashcore__default.default.Script(scriptBuffer);
5125
5028
  tx.inputs[index] = new dashcore__default.default.Transaction.Input.PublicKeyHash({
5126
5029
  prevTxId: Buffer.from(insightUtxo.hash, 'hex'),
@@ -5135,11 +5038,7 @@ class ClientKeystore extends Client {
5135
5038
  const dashKeys = this.getDashKeys(this.phrase, fromAddressIndex);
5136
5039
  tx.sign(`${(_a = dashKeys.privateKey) === null || _a === void 0 ? void 0 : _a.toString('hex')}`);
5137
5040
  const txHex = tx.checkedSerialize({});
5138
- return yield broadcastTx({
5139
- txHex,
5140
- nodeUrl: this.nodeUrls[this.network],
5141
- auth: this.nodeAuth,
5142
- });
5041
+ return yield this.broadcastTx(txHex);
5143
5042
  });
5144
5043
  }
5145
5044
  /**
@@ -5172,13 +5071,16 @@ class ClientKeystore extends Client {
5172
5071
  const tx = new dashcore__default.default.Transaction(rawUnsignedTx);
5173
5072
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5174
5073
  tx.inputs.forEach((input, index) => {
5074
+ var _a;
5175
5075
  const insightUtxo = utxos.find((utxo) => {
5176
5076
  return utxo.hash === input.prevTxId.toString('hex') && utxo.index == input.outputIndex;
5177
5077
  });
5178
5078
  if (!insightUtxo) {
5179
5079
  throw new Error('Unable to match accumulative inputs with insight utxos');
5180
5080
  }
5181
- const scriptBuffer = Buffer.from(insightUtxo.scriptPubKey || '', 'hex');
5081
+ // Providers may populate either scriptPubKey (Insight) or witnessUtxo.script (Blockcypher)
5082
+ const scriptHex = insightUtxo.scriptPubKey || ((_a = insightUtxo.witnessUtxo) === null || _a === void 0 ? void 0 : _a.script.toString('hex')) || '';
5083
+ const scriptBuffer = Buffer.from(scriptHex, 'hex');
5182
5084
  const script = new dashcore__default.default.Script(scriptBuffer);
5183
5085
  tx.inputs[index] = new dashcore__default.default.Transaction.Input.PublicKeyHash({
5184
5086
  prevTxId: Buffer.from(insightUtxo.hash, 'hex'),
@@ -5193,11 +5095,7 @@ class ClientKeystore extends Client {
5193
5095
  const dashKeys = this.getDashKeys(this.phrase, fromAddressIndex);
5194
5096
  tx.sign(`${(_a = dashKeys.privateKey) === null || _a === void 0 ? void 0 : _a.toString('hex')}`);
5195
5097
  const txHex = tx.checkedSerialize({});
5196
- const hash = yield broadcastTx({
5197
- txHex,
5198
- nodeUrl: this.nodeUrls[this.network],
5199
- auth: this.nodeAuth,
5200
- });
5098
+ const hash = yield this.broadcastTx(txHex);
5201
5099
  return { hash, maxAmount, fee };
5202
5100
  });
5203
5101
  }
@@ -5280,13 +5178,8 @@ class ClientLedger extends Client {
5280
5178
  useTrustedInputForSegwit: false,
5281
5179
  additionals: [],
5282
5180
  });
5283
- // Broadcast transaction
5284
- const txHash = yield broadcastTx({
5285
- txHex,
5286
- nodeUrl: this.nodeUrls[this.network],
5287
- auth: this.nodeAuth,
5288
- });
5289
- // Throw error if no transaction hash is received
5181
+ // Broadcast transaction via the configured data providers
5182
+ const txHash = yield this.broadcastTx(txHex);
5290
5183
  if (!txHash) {
5291
5184
  throw Error('No Tx hash');
5292
5185
  }
@@ -5334,11 +5227,7 @@ class ClientLedger extends Client {
5334
5227
  useTrustedInputForSegwit: false,
5335
5228
  additionals: [],
5336
5229
  });
5337
- const hash = yield broadcastTx({
5338
- txHex,
5339
- nodeUrl: this.nodeUrls[this.network],
5340
- auth: this.nodeAuth,
5341
- });
5230
+ const hash = yield this.broadcastTx(txHex);
5342
5231
  if (!hash) {
5343
5232
  throw Error('No Tx hash');
5344
5233
  }