Skip to content

Commit

Permalink
chore: vendor in axios-fetch-adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
thecookfrankie committed Dec 21, 2023
1 parent 861432d commit 1a6b844
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 1 deletion.
3 changes: 2 additions & 1 deletion packages/accounts/src/kernel-zerodev/paymaster/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { ENTRYPOINT_ADDRESS } from "../constants.js";
import type { ZeroDevProvider } from "../provider.js";
import { hexifyUserOp } from "../utils/ERC4337-utils.js";
import type { PaymasterAndBundlerProviders } from "./types.js";
import fetchAdapter from '@vespaiach/axios-fetch-adapter';
// @ts-ignore
import fetchAdapter from '../utils/fetchAdapter.js';

if (typeof fetch === 'function') {
axios.defaults.adapter = fetchAdapter
Expand Down
215 changes: 215 additions & 0 deletions packages/accounts/src/kernel-zerodev/utils/fetchAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
import axios from 'axios';
import settle from 'axios/lib/core/settle';
import buildURL from 'axios/lib/helpers/buildURL';
import buildFullPath from 'axios/lib/core/buildFullPath';
import { isUndefined, isStandardBrowserEnv, isFormData } from 'axios/lib/utils';

/**
* - Create a request object
* - Get response body
* - Check if timeout
*/
export default async function fetchAdapter(config) {
const request = createRequest(config);
const promiseChain = [getResponse(request, config)];

if (config.timeout && config.timeout > 0) {
promiseChain.push(
new Promise((res) => {
setTimeout(() => {
const message = config.timeoutErrorMessage
? config.timeoutErrorMessage
: 'timeout of ' + config.timeout + 'ms exceeded';
res(createError(message, config, 'ECONNABORTED', request));
}, config.timeout);
})
);
}

const data = await Promise.race(promiseChain);
return new Promise((resolve, reject) => {
if (data instanceof Error) {
reject(data);
} else {
Object.prototype.toString.call(config.settle) === '[object Function]'
? config.settle(resolve, reject, data)
: settle(resolve, reject, data);
}
});
}


/**
* Fetch API stage two is to get response body. This funtion tries to retrieve
* response body based on response's type
*/
async function getResponse(request, config) {
let stageOne;
try {
stageOne = await fetch(request);
} catch (e) {
return createError('Network Error', config, 'ERR_NETWORK', request);
}

const response = {
ok: stageOne.ok,
status: stageOne.status,
statusText: stageOne.statusText,
headers: new Headers(stageOne.headers), // Make a copy of headers
config: config,
request,
};

if (stageOne.status >= 200 && stageOne.status !== 204) {
switch (config.responseType) {
case 'arraybuffer':
response.data = await stageOne.arrayBuffer();
break;
case 'blob':
response.data = await stageOne.blob();
break;
case 'json':
response.data = await stageOne.json();
break;
case 'formData':
response.data = await stageOne.formData();
break;
default:
response.data = await stageOne.text();
break;
}
}

return response;
}

/**
* This function will create a Request object based on configuration's axios
*/
function createRequest(config) {
const headers = new Headers(config.headers);

// HTTP basic authentication
if (config.auth) {
const username = config.auth.username || '';
const password = config.auth.password ? decodeURI(encodeURIComponent(config.auth.password)) : '';
headers.set('Authorization', `Basic ${btoa(username + ':' + password)}`);
}

const method = config.method.toUpperCase();
const options = {
headers: headers,
method,
};
if (method !== 'GET' && method !== 'HEAD') {
options.body = config.data;

// In these cases the browser will automatically set the correct Content-Type,
// but only if that header hasn't been set yet. So that's why we're deleting it.
if (isFormData(options.body) && isStandardBrowserEnv()) {
headers.delete('Content-Type');
}
}
if (config.mode) {
options.mode = config.mode;
}
if (config.cache) {
options.cache = config.cache;
}
if (config.integrity) {
options.integrity = config.integrity;
}
if (config.redirect) {
options.redirect = config.redirect;
}
if (config.referrer) {
options.referrer = config.referrer;
}
// This config is similar to XHR’s withCredentials flag, but with three available values instead of two.
// So if withCredentials is not set, default value 'same-origin' will be used
if (!isUndefined(config.withCredentials)) {
options.credentials = config.withCredentials ? 'include' : 'omit';
}

const fullPath = buildFullPath(config.baseURL, config.url);
const url = buildURL(fullPath, config.params, config.paramsSerializer);

// Expected browser to throw error if there is any wrong configuration value
return new Request(url, options);
}



/**
* Note:
*
* From version >= 0.27.0, createError function is replaced by AxiosError class.
* So I copy the old createError function here for backward compatible.
*
*
*
* Create an Error with the specified message, config, error code, request and response.
*
* @param {string} message The error message.
* @param {Object} config The config.
* @param {string} [code] The error code (for example, 'ECONNABORTED').
* @param {Object} [request] The request.
* @param {Object} [response] The response.
* @returns {Error} The created error.
*/
function createError(message, config, code, request, response) {
if (axios.AxiosError && typeof axios.AxiosError === 'function') {
return new axios.AxiosError(message, axios.AxiosError[code], config, request, response);
}

var error = new Error(message);
return enhanceError(error, config, code, request, response);
};

/**
*
* Note:
*
* This function is for backward compatible.
*
*
* Update an Error with the specified config, error code, and response.
*
* @param {Error} error The error to update.
* @param {Object} config The config.
* @param {string} [code] The error code (for example, 'ECONNABORTED').
* @param {Object} [request] The request.
* @param {Object} [response] The response.
* @returns {Error} The error.
*/
function enhanceError(error, config, code, request, response) {
error.config = config;
if (code) {
error.code = code;
}

error.request = request;
error.response = response;
error.isAxiosError = true;

error.toJSON = function toJSON() {
return {
// Standard
message: this.message,
name: this.name,
// Microsoft
description: this.description,
number: this.number,
// Mozilla
fileName: this.fileName,
lineNumber: this.lineNumber,
columnNumber: this.columnNumber,
stack: this.stack,
// Axios
config: this.config,
code: this.code,
status: this.response && this.response.status ? this.response.status : null
};
};
return error;
};

0 comments on commit 1a6b844

Please sign in to comment.