@xchainjs/xchain-aggregator 2.3.2 → 2.3.3

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
@@ -42,7 +42,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
42
42
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
43
43
  };
44
44
 
45
- const SupportedProtocols = ['Thorchain', 'Mayachain', 'Chainflip'];
45
+ const SupportedProtocols = ['Thorchain', 'Mayachain', 'Chainflip', 'OneClick'];
46
46
  const DEFAULT_CONFIG = {
47
47
  protocols: SupportedProtocols,
48
48
  network: xchainClient.Network.Mainnet,
@@ -573,16 +573,16 @@ const G = getGlobal();
573
573
  const FormDataCtor = typeof G.FormData !== 'undefined' ? G.FormData : undefined;
574
574
 
575
575
  const isFormData = (thing) => {
576
- let kind;
577
- return thing && (
578
- (FormDataCtor && thing instanceof FormDataCtor) || (
579
- isFunction$1(thing.append) && (
580
- (kind = kindOf(thing)) === 'formdata' ||
581
- // detect form-data instance
582
- (kind === 'object' && isFunction$1(thing.toString) && thing.toString() === '[object FormData]')
583
- )
584
- )
585
- );
576
+ if (!thing) return false;
577
+ if (FormDataCtor && thing instanceof FormDataCtor) return true;
578
+ // Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData (GHSA-6chq-wfr3-2hj9).
579
+ const proto = getPrototypeOf(thing);
580
+ if (!proto || proto === Object.prototype) return false;
581
+ if (!isFunction$1(thing.append)) return false;
582
+ const kind = kindOf(thing);
583
+ return kind === 'formdata' ||
584
+ // detect form-data instance
585
+ (kind === 'object' && isFunction$1(thing.toString) && thing.toString() === '[object FormData]');
586
586
  };
587
587
 
588
588
  /**
@@ -1249,40 +1249,40 @@ let AxiosError$1 = class AxiosError extends Error {
1249
1249
  return axiosError;
1250
1250
  }
1251
1251
 
1252
- /**
1253
- * Create an Error with the specified message, config, error code, request and response.
1254
- *
1255
- * @param {string} message The error message.
1256
- * @param {string} [code] The error code (for example, 'ECONNABORTED').
1257
- * @param {Object} [config] The config.
1258
- * @param {Object} [request] The request.
1259
- * @param {Object} [response] The response.
1260
- *
1261
- * @returns {Error} The created error.
1262
- */
1263
- constructor(message, code, config, request, response) {
1264
- super(message);
1265
-
1266
- // Make message enumerable to maintain backward compatibility
1267
- // The native Error constructor sets message as non-enumerable,
1268
- // but axios < v1.13.3 had it as enumerable
1269
- Object.defineProperty(this, 'message', {
1270
- value: message,
1271
- enumerable: true,
1272
- writable: true,
1273
- configurable: true
1274
- });
1275
-
1276
- this.name = 'AxiosError';
1277
- this.isAxiosError = true;
1278
- code && (this.code = code);
1279
- config && (this.config = config);
1280
- request && (this.request = request);
1281
- if (response) {
1282
- this.response = response;
1283
- this.status = response.status;
1284
- }
1252
+ /**
1253
+ * Create an Error with the specified message, config, error code, request and response.
1254
+ *
1255
+ * @param {string} message The error message.
1256
+ * @param {string} [code] The error code (for example, 'ECONNABORTED').
1257
+ * @param {Object} [config] The config.
1258
+ * @param {Object} [request] The request.
1259
+ * @param {Object} [response] The response.
1260
+ *
1261
+ * @returns {Error} The created error.
1262
+ */
1263
+ constructor(message, code, config, request, response) {
1264
+ super(message);
1265
+
1266
+ // Make message enumerable to maintain backward compatibility
1267
+ // The native Error constructor sets message as non-enumerable,
1268
+ // but axios < v1.13.3 had it as enumerable
1269
+ Object.defineProperty(this, 'message', {
1270
+ value: message,
1271
+ enumerable: true,
1272
+ writable: true,
1273
+ configurable: true,
1274
+ });
1275
+
1276
+ this.name = 'AxiosError';
1277
+ this.isAxiosError = true;
1278
+ code && (this.code = code);
1279
+ config && (this.config = config);
1280
+ request && (this.request = request);
1281
+ if (response) {
1282
+ this.response = response;
1283
+ this.status = response.status;
1285
1284
  }
1285
+ }
1286
1286
 
1287
1287
  toJSON() {
1288
1288
  return {
@@ -1318,6 +1318,7 @@ AxiosError$1.ERR_BAD_REQUEST = 'ERR_BAD_REQUEST';
1318
1318
  AxiosError$1.ERR_CANCELED = 'ERR_CANCELED';
1319
1319
  AxiosError$1.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT';
1320
1320
  AxiosError$1.ERR_INVALID_URL = 'ERR_INVALID_URL';
1321
+ AxiosError$1.ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED';
1321
1322
 
1322
1323
  // eslint-disable-next-line strict
1323
1324
  var httpAdapter = null;
@@ -1432,6 +1433,7 @@ function toFormData$1(obj, formData, options) {
1432
1433
  const dots = options.dots;
1433
1434
  const indexes = options.indexes;
1434
1435
  const _Blob = options.Blob || (typeof Blob !== 'undefined' && Blob);
1436
+ const maxDepth = options.maxDepth === undefined ? 100 : options.maxDepth;
1435
1437
  const useBlob = _Blob && utils$1.isSpecCompliantForm(formData);
1436
1438
 
1437
1439
  if (!utils$1.isFunction(visitor)) {
@@ -1524,9 +1526,16 @@ function toFormData$1(obj, formData, options) {
1524
1526
  isVisitable,
1525
1527
  });
1526
1528
 
1527
- function build(value, path) {
1529
+ function build(value, path, depth = 0) {
1528
1530
  if (utils$1.isUndefined(value)) return;
1529
1531
 
1532
+ if (depth > maxDepth) {
1533
+ throw new AxiosError$1(
1534
+ 'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth,
1535
+ AxiosError$1.ERR_FORM_DATA_DEPTH_EXCEEDED
1536
+ );
1537
+ }
1538
+
1530
1539
  if (stack.indexOf(value) !== -1) {
1531
1540
  throw Error('Circular reference detected in ' + path.join('.'));
1532
1541
  }
@@ -1539,7 +1548,7 @@ function toFormData$1(obj, formData, options) {
1539
1548
  visitor.call(formData, el, utils$1.isString(key) ? key.trim() : key, path, exposedHelpers);
1540
1549
 
1541
1550
  if (result === true) {
1542
- build(el, path ? path.concat(key) : [key]);
1551
+ build(el, path ? path.concat(key) : [key], depth + 1);
1543
1552
  }
1544
1553
  });
1545
1554
 
@@ -1571,9 +1580,8 @@ function encode$1(str) {
1571
1580
  ')': '%29',
1572
1581
  '~': '%7E',
1573
1582
  '%20': '+',
1574
- '%00': '\x00',
1575
1583
  };
1576
- return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) {
1584
+ return encodeURIComponent(str).replace(/[!'()~]|%20/g, function replacer(match) {
1577
1585
  return charMap[match];
1578
1586
  });
1579
1587
  }
@@ -1893,7 +1901,9 @@ function formDataToJSON(formData) {
1893
1901
 
1894
1902
  if (isLast) {
1895
1903
  if (utils$1.hasOwnProp(target, name)) {
1896
- target[name] = [target[name], value];
1904
+ target[name] = utils$1.isArray(target[name])
1905
+ ? target[name].concat(value)
1906
+ : [target[name], value];
1897
1907
  } else {
1898
1908
  target[name] = value;
1899
1909
  }
@@ -1927,6 +1937,8 @@ function formDataToJSON(formData) {
1927
1937
  return null;
1928
1938
  }
1929
1939
 
1940
+ const own = (obj, key) => (obj != null && utils$1.hasOwnProp(obj, key) ? obj[key] : undefined);
1941
+
1930
1942
  /**
1931
1943
  * It takes a string, tries to parse it, and if it fails, it returns the stringified version
1932
1944
  * of the input
@@ -1994,20 +2006,22 @@ const defaults = {
1994
2006
  let isFileList;
1995
2007
 
1996
2008
  if (isObjectPayload) {
2009
+ const formSerializer = own(this, 'formSerializer');
1997
2010
  if (contentType.indexOf('application/x-www-form-urlencoded') > -1) {
1998
- return toURLEncodedForm(data, this.formSerializer).toString();
2011
+ return toURLEncodedForm(data, formSerializer).toString();
1999
2012
  }
2000
2013
 
2001
2014
  if (
2002
2015
  (isFileList = utils$1.isFileList(data)) ||
2003
2016
  contentType.indexOf('multipart/form-data') > -1
2004
2017
  ) {
2005
- const _FormData = this.env && this.env.FormData;
2018
+ const env = own(this, 'env');
2019
+ const _FormData = env && env.FormData;
2006
2020
 
2007
2021
  return toFormData$1(
2008
2022
  isFileList ? { 'files[]': data } : data,
2009
2023
  _FormData && new _FormData(),
2010
- this.formSerializer
2024
+ formSerializer
2011
2025
  );
2012
2026
  }
2013
2027
  }
@@ -2023,9 +2037,10 @@ const defaults = {
2023
2037
 
2024
2038
  transformResponse: [
2025
2039
  function transformResponse(data) {
2026
- const transitional = this.transitional || defaults.transitional;
2040
+ const transitional = own(this, 'transitional') || defaults.transitional;
2027
2041
  const forcedJSONParsing = transitional && transitional.forcedJSONParsing;
2028
- const JSONRequested = this.responseType === 'json';
2042
+ const responseType = own(this, 'responseType');
2043
+ const JSONRequested = responseType === 'json';
2029
2044
 
2030
2045
  if (utils$1.isResponse(data) || utils$1.isReadableStream(data)) {
2031
2046
  return data;
@@ -2034,17 +2049,17 @@ const defaults = {
2034
2049
  if (
2035
2050
  data &&
2036
2051
  utils$1.isString(data) &&
2037
- ((forcedJSONParsing && !this.responseType) || JSONRequested)
2052
+ ((forcedJSONParsing && !responseType) || JSONRequested)
2038
2053
  ) {
2039
2054
  const silentJSONParsing = transitional && transitional.silentJSONParsing;
2040
2055
  const strictJSONParsing = !silentJSONParsing && JSONRequested;
2041
2056
 
2042
2057
  try {
2043
- return JSON.parse(data, this.parseReviver);
2058
+ return JSON.parse(data, own(this, 'parseReviver'));
2044
2059
  } catch (e) {
2045
2060
  if (strictJSONParsing) {
2046
2061
  if (e.name === 'SyntaxError') {
2047
- throw AxiosError$1.from(e, AxiosError$1.ERR_BAD_RESPONSE, this, null, this.response);
2062
+ throw AxiosError$1.from(e, AxiosError$1.ERR_BAD_RESPONSE, this, null, own(this, 'response'));
2048
2063
  }
2049
2064
  throw e;
2050
2065
  }
@@ -2156,41 +2171,41 @@ var parseHeaders = (rawHeaders) => {
2156
2171
 
2157
2172
  const $internals = Symbol('internals');
2158
2173
 
2159
- const isValidHeaderValue = (value) => !/[\r\n]/.test(value);
2160
-
2161
- function assertValidHeaderValue(value, header) {
2162
- if (value === false || value == null) {
2163
- return;
2164
- }
2174
+ const INVALID_HEADER_VALUE_CHARS_RE = /[^\x09\x20-\x7E\x80-\xFF]/g;
2165
2175
 
2166
- if (utils$1.isArray(value)) {
2167
- value.forEach((v) => assertValidHeaderValue(v, header));
2168
- return;
2169
- }
2176
+ function trimSPorHTAB(str) {
2177
+ let start = 0;
2178
+ let end = str.length;
2170
2179
 
2171
- if (!isValidHeaderValue(String(value))) {
2172
- throw new Error(`Invalid character in header content ["${header}"]`);
2173
- }
2174
- }
2180
+ while (start < end) {
2181
+ const code = str.charCodeAt(start);
2175
2182
 
2176
- function normalizeHeader(header) {
2177
- return header && String(header).trim().toLowerCase();
2178
- }
2183
+ if (code !== 0x09 && code !== 0x20) {
2184
+ break;
2185
+ }
2179
2186
 
2180
- function stripTrailingCRLF(str) {
2181
- let end = str.length;
2187
+ start += 1;
2188
+ }
2182
2189
 
2183
- while (end > 0) {
2184
- const charCode = str.charCodeAt(end - 1);
2190
+ while (end > start) {
2191
+ const code = str.charCodeAt(end - 1);
2185
2192
 
2186
- if (charCode !== 10 && charCode !== 13) {
2193
+ if (code !== 0x09 && code !== 0x20) {
2187
2194
  break;
2188
2195
  }
2189
2196
 
2190
2197
  end -= 1;
2191
2198
  }
2192
2199
 
2193
- return end === str.length ? str : str.slice(0, end);
2200
+ return start === 0 && end === str.length ? str : str.slice(start, end);
2201
+ }
2202
+
2203
+ function normalizeHeader(header) {
2204
+ return header && String(header).trim().toLowerCase();
2205
+ }
2206
+
2207
+ function sanitizeHeaderValue(str) {
2208
+ return trimSPorHTAB(str.replace(INVALID_HEADER_VALUE_CHARS_RE, ''));
2194
2209
  }
2195
2210
 
2196
2211
  function normalizeValue(value) {
@@ -2198,7 +2213,7 @@ function normalizeValue(value) {
2198
2213
  return value;
2199
2214
  }
2200
2215
 
2201
- return utils$1.isArray(value) ? value.map(normalizeValue) : stripTrailingCRLF(String(value));
2216
+ return utils$1.isArray(value) ? value.map(normalizeValue) : sanitizeHeaderValue(String(value));
2202
2217
  }
2203
2218
 
2204
2219
  function parseTokens(str) {
@@ -2280,7 +2295,6 @@ let AxiosHeaders$1 = class AxiosHeaders {
2280
2295
  _rewrite === true ||
2281
2296
  (_rewrite === undefined && self[key] !== false)
2282
2297
  ) {
2283
- assertValidHeaderValue(_value, _header);
2284
2298
  self[key || _header] = normalizeValue(_value);
2285
2299
  }
2286
2300
  }
@@ -2703,13 +2717,13 @@ const progressEventReducer = (listener, isDownloadStream, freq = 3) => {
2703
2717
  const _speedometer = speedometer(50, 250);
2704
2718
 
2705
2719
  return throttle((e) => {
2706
- const loaded = e.loaded;
2720
+ const rawLoaded = e.loaded;
2707
2721
  const total = e.lengthComputable ? e.total : undefined;
2708
- const progressBytes = loaded - bytesNotified;
2722
+ const loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded;
2723
+ const progressBytes = Math.max(0, loaded - bytesNotified);
2709
2724
  const rate = _speedometer(progressBytes);
2710
- const inRange = loaded <= total;
2711
2725
 
2712
- bytesNotified = loaded;
2726
+ bytesNotified = Math.max(bytesNotified, loaded);
2713
2727
 
2714
2728
  const data = {
2715
2729
  loaded,
@@ -2717,7 +2731,7 @@ const progressEventReducer = (listener, isDownloadStream, freq = 3) => {
2717
2731
  progress: total ? loaded / total : undefined,
2718
2732
  bytes: progressBytes,
2719
2733
  rate: rate ? rate : undefined,
2720
- estimated: rate && total && inRange ? (total - loaded) / rate : undefined,
2734
+ estimated: rate && total ? (total - loaded) / rate : undefined,
2721
2735
  event: e,
2722
2736
  lengthComputable: total != null,
2723
2737
  [isDownloadStream ? 'download' : 'upload']: true,
@@ -2851,7 +2865,7 @@ function combineURLs(baseURL, relativeURL) {
2851
2865
  */
2852
2866
  function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) {
2853
2867
  let isRelativeUrl = !isAbsoluteURL(requestedURL);
2854
- if (baseURL && (isRelativeUrl || allowAbsoluteUrls == false)) {
2868
+ if (baseURL && (isRelativeUrl || allowAbsoluteUrls === false)) {
2855
2869
  return combineURLs(baseURL, requestedURL);
2856
2870
  }
2857
2871
  return requestedURL;
@@ -2871,7 +2885,18 @@ const headersToObject = (thing) => (thing instanceof AxiosHeaders$1 ? { ...thing
2871
2885
  function mergeConfig$1(config1, config2) {
2872
2886
  // eslint-disable-next-line no-param-reassign
2873
2887
  config2 = config2 || {};
2874
- const config = {};
2888
+
2889
+ // Use a null-prototype object so that downstream reads such as `config.auth`
2890
+ // or `config.baseURL` cannot inherit polluted values from Object.prototype
2891
+ // (see GHSA-q8qp-cvcw-x6jj). `hasOwnProperty` is restored as a non-enumerable
2892
+ // own slot to preserve ergonomics for user code that relies on it.
2893
+ const config = Object.create(null);
2894
+ Object.defineProperty(config, 'hasOwnProperty', {
2895
+ value: Object.prototype.hasOwnProperty,
2896
+ enumerable: false,
2897
+ writable: true,
2898
+ configurable: true,
2899
+ });
2875
2900
 
2876
2901
  function getMergedValue(target, source, prop, caseless) {
2877
2902
  if (utils$1.isPlainObject(target) && utils$1.isPlainObject(source)) {
@@ -2910,9 +2935,9 @@ function mergeConfig$1(config1, config2) {
2910
2935
 
2911
2936
  // eslint-disable-next-line consistent-return
2912
2937
  function mergeDirectKeys(a, b, prop) {
2913
- if (prop in config2) {
2938
+ if (utils$1.hasOwnProp(config2, prop)) {
2914
2939
  return getMergedValue(a, b);
2915
- } else if (prop in config1) {
2940
+ } else if (utils$1.hasOwnProp(config1, prop)) {
2916
2941
  return getMergedValue(undefined, a);
2917
2942
  }
2918
2943
  }
@@ -2944,6 +2969,7 @@ function mergeConfig$1(config1, config2) {
2944
2969
  httpsAgent: defaultToConfig2,
2945
2970
  cancelToken: defaultToConfig2,
2946
2971
  socketPath: defaultToConfig2,
2972
+ allowedSocketPaths: defaultToConfig2,
2947
2973
  responseEncoding: defaultToConfig2,
2948
2974
  validateStatus: mergeDirectKeys,
2949
2975
  headers: (a, b, prop) =>
@@ -2953,7 +2979,9 @@ function mergeConfig$1(config1, config2) {
2953
2979
  utils$1.forEach(Object.keys({ ...config1, ...config2 }), function computeConfigValue(prop) {
2954
2980
  if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') return;
2955
2981
  const merge = utils$1.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : mergeDeepProperties;
2956
- const configValue = merge(config1[prop], config2[prop], prop);
2982
+ const a = utils$1.hasOwnProp(config1, prop) ? config1[prop] : undefined;
2983
+ const b = utils$1.hasOwnProp(config2, prop) ? config2[prop] : undefined;
2984
+ const configValue = merge(a, b, prop);
2957
2985
  (utils$1.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);
2958
2986
  });
2959
2987
 
@@ -2963,12 +2991,24 @@ function mergeConfig$1(config1, config2) {
2963
2991
  var resolveConfig = (config) => {
2964
2992
  const newConfig = mergeConfig$1({}, config);
2965
2993
 
2966
- let { data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth } = newConfig;
2994
+ // Read only own properties to prevent prototype pollution gadgets
2995
+ // (e.g. Object.prototype.baseURL = 'https://evil.com'). See GHSA-q8qp-cvcw-x6jj.
2996
+ const own = (key) => (utils$1.hasOwnProp(newConfig, key) ? newConfig[key] : undefined);
2997
+
2998
+ const data = own('data');
2999
+ let withXSRFToken = own('withXSRFToken');
3000
+ const xsrfHeaderName = own('xsrfHeaderName');
3001
+ const xsrfCookieName = own('xsrfCookieName');
3002
+ let headers = own('headers');
3003
+ const auth = own('auth');
3004
+ const baseURL = own('baseURL');
3005
+ const allowAbsoluteUrls = own('allowAbsoluteUrls');
3006
+ const url = own('url');
2967
3007
 
2968
3008
  newConfig.headers = headers = AxiosHeaders$1.from(headers);
2969
3009
 
2970
3010
  newConfig.url = buildURL(
2971
- buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls),
3011
+ buildFullPath(baseURL, url, allowAbsoluteUrls),
2972
3012
  config.params,
2973
3013
  config.paramsSerializer
2974
3014
  );
@@ -3007,10 +3047,18 @@ var resolveConfig = (config) => {
3007
3047
  // Specifically not if we're in a web worker, or react-native.
3008
3048
 
3009
3049
  if (platform.hasStandardBrowserEnv) {
3010
- withXSRFToken && utils$1.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig));
3050
+ if (utils$1.isFunction(withXSRFToken)) {
3051
+ withXSRFToken = withXSRFToken(newConfig);
3052
+ }
3053
+
3054
+ // Strict boolean check — prevents proto-pollution gadgets (e.g. Object.prototype.withXSRFToken = 1)
3055
+ // and misconfigurations (e.g. "false") from short-circuiting the same-origin check and leaking
3056
+ // the XSRF token cross-origin. See GHSA-xx6v-rp6x-q39c.
3057
+ const shouldSendXSRF =
3058
+ withXSRFToken === true ||
3059
+ (withXSRFToken == null && isURLSameOrigin(newConfig.url));
3011
3060
 
3012
- if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(newConfig.url))) {
3013
- // Add xsrf header
3061
+ if (shouldSendXSRF) {
3014
3062
  const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName);
3015
3063
 
3016
3064
  if (xsrfValue) {
@@ -3429,18 +3477,20 @@ const factory = (env) => {
3429
3477
  test(() => {
3430
3478
  let duplexAccessed = false;
3431
3479
 
3432
- const body = new ReadableStream$1();
3433
-
3434
- const hasContentType = new Request(platform.origin, {
3435
- body,
3480
+ const request = new Request(platform.origin, {
3481
+ body: new ReadableStream$1(),
3436
3482
  method: 'POST',
3437
3483
  get duplex() {
3438
3484
  duplexAccessed = true;
3439
3485
  return 'half';
3440
3486
  },
3441
- }).headers.has('Content-Type');
3487
+ });
3488
+
3489
+ const hasContentType = request.headers.has('Content-Type');
3442
3490
 
3443
- body.cancel();
3491
+ if (request.body != null) {
3492
+ request.body.cancel();
3493
+ }
3444
3494
 
3445
3495
  return duplexAccessed && !hasContentType;
3446
3496
  });
@@ -3584,6 +3634,19 @@ const factory = (env) => {
3584
3634
  // see https://github.com/cloudflare/workerd/issues/902
3585
3635
  const isCredentialsSupported = isRequestSupported && 'credentials' in Request.prototype;
3586
3636
 
3637
+ // If data is FormData and Content-Type is multipart/form-data without boundary,
3638
+ // delete it so fetch can set it correctly with the boundary
3639
+ if (utils$1.isFormData(data)) {
3640
+ const contentType = headers.getContentType();
3641
+ if (
3642
+ contentType &&
3643
+ /^multipart\/form-data/i.test(contentType) &&
3644
+ !/boundary=/i.test(contentType)
3645
+ ) {
3646
+ headers.delete('content-type');
3647
+ }
3648
+ }
3649
+
3587
3650
  const resolvedOptions = {
3588
3651
  ...fetchOptions,
3589
3652
  signal: composedSignal,
@@ -3892,7 +3955,7 @@ function dispatchRequest(config) {
3892
3955
  );
3893
3956
  }
3894
3957
 
3895
- const VERSION$1 = "1.15.0";
3958
+ const VERSION$1 = "1.15.2";
3896
3959
 
3897
3960
  const validators$1 = {};
3898
3961
 
@@ -3977,7 +4040,9 @@ function assertOptions(options, schema, allowUnknown) {
3977
4040
  let i = keys.length;
3978
4041
  while (i-- > 0) {
3979
4042
  const opt = keys[i];
3980
- const validator = schema[opt];
4043
+ // Use hasOwnProperty so a polluted Object.prototype.<opt> cannot supply
4044
+ // a non-function validator and cause a TypeError. See GHSA-q8qp-cvcw-x6jj.
4045
+ const validator = Object.prototype.hasOwnProperty.call(schema, opt) ? schema[opt] : undefined;
3981
4046
  if (validator) {
3982
4047
  const value = options[opt];
3983
4048
  const result = value === undefined || validator(value, opt, options);
@@ -7680,10 +7745,255 @@ class MayachainProtocol {
7680
7745
  }
7681
7746
  }
7682
7747
 
7748
+ const BASE_URL = 'https://1click.chaindefuser.com';
7749
+ class OneClickApi {
7750
+ constructor(apiKey) {
7751
+ this.headers = { 'Content-Type': 'application/json' };
7752
+ if (apiKey) {
7753
+ this.headers['Authorization'] = `Bearer ${apiKey}`;
7754
+ }
7755
+ }
7756
+ getTokens() {
7757
+ return __awaiter$4(this, void 0, void 0, function* () {
7758
+ const resp = yield fetch(`${BASE_URL}/v0/tokens`, { headers: this.headers });
7759
+ if (!resp.ok)
7760
+ throw new Error(`1Click getTokens failed: ${resp.status}`);
7761
+ return resp.json();
7762
+ });
7763
+ }
7764
+ getQuote(params) {
7765
+ return __awaiter$4(this, void 0, void 0, function* () {
7766
+ const resp = yield fetch(`${BASE_URL}/v0/quote`, {
7767
+ method: 'POST',
7768
+ headers: this.headers,
7769
+ body: JSON.stringify(params),
7770
+ });
7771
+ if (!resp.ok)
7772
+ throw new Error(`1Click getQuote failed: ${resp.status}`);
7773
+ return resp.json();
7774
+ });
7775
+ }
7776
+ submitDeposit(txHash, depositAddress) {
7777
+ return __awaiter$4(this, void 0, void 0, function* () {
7778
+ yield fetch(`${BASE_URL}/v0/deposit/submit`, {
7779
+ method: 'POST',
7780
+ headers: this.headers,
7781
+ body: JSON.stringify({ txHash, depositAddress }),
7782
+ }).catch(() => {
7783
+ // Fire-and-forget
7784
+ });
7785
+ });
7786
+ }
7787
+ }
7788
+
7789
+ const X_TO_ONECLICK = {
7790
+ BTC: 'btc',
7791
+ ETH: 'eth',
7792
+ ARB: 'arb',
7793
+ AVAX: 'avax',
7794
+ BSC: 'bsc',
7795
+ SOL: 'sol',
7796
+ DOGE: 'doge',
7797
+ DASH: 'dash',
7798
+ LTC: 'ltc',
7799
+ BCH: 'bch',
7800
+ XRP: 'xrp',
7801
+ ADA: 'cardano',
7802
+ SUI: 'sui',
7803
+ };
7804
+ const ONECLICK_TO_X = Object.fromEntries(Object.entries(X_TO_ONECLICK).map(([k, v]) => [v, k]));
7805
+ const xChainToOneClickBlockchain = (chain) => {
7806
+ var _a;
7807
+ return (_a = X_TO_ONECLICK[chain]) !== null && _a !== void 0 ? _a : null;
7808
+ };
7809
+ const oneClickBlockchainToXChain = (blockchain) => {
7810
+ var _a;
7811
+ return (_a = ONECLICK_TO_X[blockchain]) !== null && _a !== void 0 ? _a : null;
7812
+ };
7813
+ const findOneClickToken = (asset, tokens) => {
7814
+ if (xchainUtil.isSynthAsset(asset) || xchainUtil.isTradeAsset(asset) || xchainUtil.isSecuredAsset(asset))
7815
+ return undefined;
7816
+ const blockchain = xChainToOneClickBlockchain(asset.chain);
7817
+ if (!blockchain)
7818
+ return undefined;
7819
+ return tokens.find((token) => {
7820
+ if (token.blockchain !== blockchain)
7821
+ return false;
7822
+ if (xchainUtil.isTokenAsset(asset)) {
7823
+ // Match by contract address (case-insensitive)
7824
+ const assetContract = asset.symbol.includes('-') ? asset.symbol.split('-')[1] : undefined;
7825
+ return assetContract && token.contractAddress
7826
+ ? token.contractAddress.toLowerCase() === assetContract.toLowerCase()
7827
+ : false;
7828
+ }
7829
+ // Native asset: match by symbol, ensure no contract address on token
7830
+ return token.symbol.toUpperCase() === asset.symbol.toUpperCase() && !token.contractAddress;
7831
+ });
7832
+ };
7833
+
7834
+ class OneClickProtocol {
7835
+ constructor(configuration) {
7836
+ this.name = 'OneClick';
7837
+ this.api = new OneClickApi(configuration === null || configuration === void 0 ? void 0 : configuration.oneClickApiKey);
7838
+ this.wallet = configuration === null || configuration === void 0 ? void 0 : configuration.wallet;
7839
+ this.affiliateAddress = configuration === null || configuration === void 0 ? void 0 : configuration.affiliateAddress;
7840
+ this.affiliateBps = configuration === null || configuration === void 0 ? void 0 : configuration.affiliateBps;
7841
+ this.tokensCache = new xchainUtil.CachedValue(() => this.api.getTokens(), 24 * 60 * 60 * 1000);
7842
+ }
7843
+ approveRouterToSpend(_params) {
7844
+ return __awaiter$4(this, void 0, void 0, function* () {
7845
+ throw new Error('Not implemented');
7846
+ });
7847
+ }
7848
+ shouldBeApproved(_params) {
7849
+ return __awaiter$4(this, void 0, void 0, function* () {
7850
+ return false;
7851
+ });
7852
+ }
7853
+ isAssetSupported(asset) {
7854
+ return __awaiter$4(this, void 0, void 0, function* () {
7855
+ if (xchainUtil.isSynthAsset(asset) || xchainUtil.isTradeAsset(asset) || xchainUtil.isSecuredAsset(asset))
7856
+ return false;
7857
+ const tokens = yield this.tokensCache.getValue();
7858
+ return findOneClickToken(asset, tokens) !== undefined;
7859
+ });
7860
+ }
7861
+ getSupportedChains() {
7862
+ return __awaiter$4(this, void 0, void 0, function* () {
7863
+ const tokens = yield this.tokensCache.getValue();
7864
+ const chains = new Set();
7865
+ for (const token of tokens) {
7866
+ const chain = oneClickBlockchainToXChain(token.blockchain);
7867
+ if (chain)
7868
+ chains.add(chain);
7869
+ }
7870
+ return Array.from(chains);
7871
+ });
7872
+ }
7873
+ estimateSwap(params) {
7874
+ return __awaiter$4(this, void 0, void 0, function* () {
7875
+ var _a, _b, _c;
7876
+ const tokens = yield this.tokensCache.getValue();
7877
+ const srcToken = findOneClickToken(params.fromAsset, tokens);
7878
+ const destToken = findOneClickToken(params.destinationAsset, tokens);
7879
+ if (!srcToken || !destToken) {
7880
+ return this.errorQuote(params, srcToken ? 'Destination asset not supported' : 'Source asset not supported');
7881
+ }
7882
+ try {
7883
+ const isDry = !(params.fromAddress && params.destinationAddress);
7884
+ const deadline = new Date(Date.now() + 10 * 60 * 1000).toISOString();
7885
+ const appFees = this.affiliateAddress && this.affiliateBps
7886
+ ? [{ recipient: this.affiliateAddress, fee: this.affiliateBps }]
7887
+ : undefined;
7888
+ const resp = yield this.api.getQuote({
7889
+ dry: isDry,
7890
+ swapType: 'EXACT_INPUT',
7891
+ depositType: 'ORIGIN_CHAIN',
7892
+ recipientType: 'DESTINATION_CHAIN',
7893
+ refundType: 'ORIGIN_CHAIN',
7894
+ originAsset: srcToken.assetId,
7895
+ destinationAsset: destToken.assetId,
7896
+ amount: params.amount.baseAmount.amount().toString(),
7897
+ refundTo: params.fromAddress || '',
7898
+ recipient: params.destinationAddress || '',
7899
+ slippageTolerance: (_a = params.toleranceBps) !== null && _a !== void 0 ? _a : 100,
7900
+ deadline,
7901
+ appFees,
7902
+ });
7903
+ if (resp.error || resp.message) {
7904
+ return this.errorQuote(params, resp.error || resp.message || 'Unknown error');
7905
+ }
7906
+ const quote = resp.quote;
7907
+ const toAddress = (_b = quote.depositAddress) !== null && _b !== void 0 ? _b : '';
7908
+ return {
7909
+ protocol: this.name,
7910
+ toAddress,
7911
+ memo: '',
7912
+ expectedAmount: new xchainUtil.CryptoAmount(xchainUtil.baseAmount(quote.amountOut, destToken.decimals), params.destinationAsset),
7913
+ dustThreshold: new xchainUtil.CryptoAmount(xchainUtil.baseAmount(0), params.fromAsset),
7914
+ totalSwapSeconds: (_c = quote.timeEstimate) !== null && _c !== void 0 ? _c : 0,
7915
+ maxStreamingQuantity: undefined,
7916
+ canSwap: toAddress !== '',
7917
+ warning: '',
7918
+ errors: [],
7919
+ slipBasisPoints: 0,
7920
+ fees: {
7921
+ asset: params.fromAsset,
7922
+ affiliateFee: new xchainUtil.CryptoAmount(xchainUtil.baseAmount(0), params.fromAsset),
7923
+ outboundFee: new xchainUtil.CryptoAmount(xchainUtil.baseAmount(0), params.destinationAsset),
7924
+ },
7925
+ };
7926
+ }
7927
+ catch (e) {
7928
+ return this.errorQuote(params, e instanceof Error ? e.message : 'Unknown error');
7929
+ }
7930
+ });
7931
+ }
7932
+ doSwap(params) {
7933
+ return __awaiter$4(this, void 0, void 0, function* () {
7934
+ const quoteSwap = yield this.estimateSwap(params);
7935
+ if (!quoteSwap.canSwap) {
7936
+ throw new Error(`Can not make swap. ${quoteSwap.errors.join('\n')}`);
7937
+ }
7938
+ if (!this.wallet)
7939
+ throw new Error('Wallet not configured. Can not do swap');
7940
+ const hash = yield this.wallet.transfer({
7941
+ recipient: quoteSwap.toAddress,
7942
+ amount: params.amount.baseAmount,
7943
+ asset: params.fromAsset,
7944
+ memo: quoteSwap.memo,
7945
+ });
7946
+ // Funds are already on the wire. Awaiting submitDeposit lets callers distinguish
7947
+ // "deposit registered, swap will settle" from "registration silently failed, swap will
7948
+ // never settle" — surface the failure with the broadcast hash so it can be retried.
7949
+ try {
7950
+ yield this.api.submitDeposit(hash, quoteSwap.toAddress);
7951
+ }
7952
+ catch (e) {
7953
+ throw new Error(`1Click deposit tx ${hash} was broadcast, but submitDeposit failed: ${e instanceof Error ? e.message : 'unknown error'}`);
7954
+ }
7955
+ // Explorer URL is best-effort; the hash is what callers actually need for tracking.
7956
+ let url = '';
7957
+ try {
7958
+ url = yield this.wallet.getExplorerTxUrl(params.fromAsset.chain, hash);
7959
+ }
7960
+ catch (_a) {
7961
+ // swallow: explorer URL lookup must not reject a successful swap
7962
+ }
7963
+ return { hash, url };
7964
+ });
7965
+ }
7966
+ getSwapHistory(_params) {
7967
+ return __awaiter$4(this, void 0, void 0, function* () {
7968
+ return { count: 0, swaps: [] };
7969
+ });
7970
+ }
7971
+ errorQuote(params, error) {
7972
+ return {
7973
+ protocol: this.name,
7974
+ toAddress: '',
7975
+ memo: '',
7976
+ expectedAmount: new xchainUtil.CryptoAmount(xchainUtil.baseAmount(0), params.destinationAsset),
7977
+ dustThreshold: new xchainUtil.CryptoAmount(xchainUtil.baseAmount(0), params.fromAsset),
7978
+ totalSwapSeconds: 0,
7979
+ maxStreamingQuantity: undefined,
7980
+ canSwap: false,
7981
+ warning: '',
7982
+ errors: [error],
7983
+ slipBasisPoints: 0,
7984
+ fees: {
7985
+ asset: params.fromAsset,
7986
+ affiliateFee: new xchainUtil.CryptoAmount(xchainUtil.baseAmount(0), params.fromAsset),
7987
+ outboundFee: new xchainUtil.CryptoAmount(xchainUtil.baseAmount(0), params.destinationAsset),
7988
+ },
7989
+ };
7990
+ }
7991
+ }
7992
+
7683
7993
  /**
7684
7994
  * The base URL for the Midgard API endpoint.
7685
7995
  */
7686
- const MIDGARD_API_URL = 'https://gateway.liquify.com/chain/thorchain_midgard/';
7996
+ const MIDGARD_API_URL = 'https://midgard.thorchain.network/';
7687
7997
 
7688
7998
  /******************************************************************************
7689
7999
  Copyright (c) Microsoft Corporation.
@@ -10512,7 +10822,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
10512
10822
  const defaultMidgardConfig = {
10513
10823
  mainnet: {
10514
10824
  apiRetries: 3,
10515
- midgardBaseUrls: ['https://gateway.liquify.com/chain/thorchain_midgard'],
10825
+ midgardBaseUrls: ['https://midgard.thorchain.network', 'https://gateway.liquify.com/chain/thorchain_midgard'],
10516
10826
  },
10517
10827
  stagenet: {
10518
10828
  apiRetries: 3,
@@ -11065,6 +11375,7 @@ const getProtocolConfig = (name, configuration) => {
11065
11375
  network: configuration.network,
11066
11376
  affiliateBrokers: configuration.affiliateBrokers,
11067
11377
  brokerUrl: configuration.brokerUrl,
11378
+ oneClickApiKey: configuration.oneClickApiKey,
11068
11379
  };
11069
11380
  };
11070
11381
  class ProtocolFactory {
@@ -11077,6 +11388,8 @@ class ProtocolFactory {
11077
11388
  return new MayachainProtocol(protocolConfig);
11078
11389
  case 'Chainflip':
11079
11390
  return new ChainflipProtocol(protocolConfig);
11391
+ case 'OneClick':
11392
+ return new OneClickProtocol(protocolConfig);
11080
11393
  }
11081
11394
  }
11082
11395
  }