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