From f64e8982bc663725747fc902d7e2db99a8fa0d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Muhammed=20Tanr=C4=B1kulu?= Date: Mon, 10 Jun 2024 14:44:55 +0200 Subject: [PATCH] add agent interceptor into global fetch instance (#48) --- package.json | 2 +- src/index.ts | 4 ++++ src/specs/erc1155.ts | 14 +++++++++++++- src/specs/erc721.ts | 14 +++++++++++++- src/specs/uri.ts | 15 ++++++++++++++- src/types.ts | 6 ++++++ src/utils/detectPlatform.ts | 4 ++++ src/utils/fetch.ts | 27 +++++++++++++++++++++++++-- src/utils/index.ts | 3 ++- 9 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 src/utils/detectPlatform.ts diff --git a/package.json b/package.json index 89cf858..5175985 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-alpha.1.ethers.6", + "version": "1.0.0-alpha.2.ethers.6", "license": "MIT", "main": "dist/index.js", "module": "dist/index.esm.js", diff --git a/src/index.ts b/src/index.ts index 349a48b..1b9ab55 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import URI from './specs/uri'; import * as utils from './utils'; import { BaseError, + createAgentAdapter, createCacheAdapter, fetch, getImageURI, @@ -36,6 +37,9 @@ export class AvatarResolver implements AvatarResolver { if (options?.cache && options?.cache > 0) { createCacheAdapter(fetch, options?.cache); } + if (options?.agents) { + createAgentAdapter(fetch, options?.agents); + } } async getMetadata(ens: string) { diff --git a/src/specs/erc1155.ts b/src/specs/erc1155.ts index f260460..2b3143a 100644 --- a/src/specs/erc1155.ts +++ b/src/specs/erc1155.ts @@ -1,6 +1,11 @@ import { Contract, Provider } from 'ethers'; import { Buffer } from 'buffer/'; -import { fetch, resolveURI } from '../utils'; +import { + createAgentAdapter, + createCacheAdapter, + fetch, + resolveURI, +} from '../utils'; import { AvatarResolverOpts } from '../types'; const abi = [ @@ -26,6 +31,13 @@ export default class ERC1155 { tokenID: string, options?: AvatarResolverOpts ) { + if (options?.cache && options?.cache > 0) { + createCacheAdapter(fetch, options?.cache); + } + if (options?.agents) { + createAgentAdapter(fetch, options?.agents); + } + // exclude opensea api which does not follow erc1155 spec const tokenIDHex = !tokenID.startsWith('https://api.opensea.io/') ? tokenID.replace('0x', '').padStart(64, '0') diff --git a/src/specs/erc721.ts b/src/specs/erc721.ts index 28591d0..0bc229a 100644 --- a/src/specs/erc721.ts +++ b/src/specs/erc721.ts @@ -1,6 +1,11 @@ import { Contract, Provider } from 'ethers'; import { Buffer } from 'buffer/'; -import { fetch, resolveURI } from '../utils'; +import { + createAgentAdapter, + createCacheAdapter, + fetch, + resolveURI, +} from '../utils'; import { AvatarResolverOpts } from '../types'; const abi = [ @@ -16,6 +21,13 @@ export default class ERC721 { tokenID: string, options?: AvatarResolverOpts ) { + if (options?.cache && options?.cache > 0) { + createCacheAdapter(fetch, options?.cache); + } + if (options?.agents) { + createAgentAdapter(fetch, options?.agents); + } + const contract = new Contract(contractAddress, abi, provider); const [tokenURI, owner] = await Promise.all([ contract.tokenURI(tokenID), diff --git a/src/specs/uri.ts b/src/specs/uri.ts index 0117a8e..27784be 100644 --- a/src/specs/uri.ts +++ b/src/specs/uri.ts @@ -1,8 +1,21 @@ import { AvatarResolverOpts } from '../types'; -import { fetch, isImageURI, resolveURI } from '../utils'; +import { + createAgentAdapter, + createCacheAdapter, + fetch, + isImageURI, + resolveURI, +} from '../utils'; export default class URI { async getMetadata(uri: string, options?: AvatarResolverOpts) { + if (options?.cache && options?.cache > 0) { + createCacheAdapter(fetch, options?.cache); + } + if (options?.agents) { + createAgentAdapter(fetch, options?.agents); + } + const { uri: resolvedURI, isOnChain } = resolveURI(uri, options); if (isOnChain) { return resolvedURI; diff --git a/src/types.ts b/src/types.ts index 5c02d69..b74d764 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,12 +17,18 @@ export type MarketplaceAPIKey = Partial< } >; +export interface AxiosAgents { + httpAgent?: Function; + httpsAgent?: Function; +} + export interface AvatarResolverOpts { cache?: number; ipfs?: string; arweave?: string; apiKey?: MarketplaceAPIKey; urlDenyList?: string[]; + agents?: AxiosAgents; } export interface AvatarRequestOpts { diff --git a/src/utils/detectPlatform.ts b/src/utils/detectPlatform.ts new file mode 100644 index 0000000..cf9159c --- /dev/null +++ b/src/utils/detectPlatform.ts @@ -0,0 +1,4 @@ +const isBrowser: boolean = + typeof window !== 'undefined' && typeof window.document !== 'undefined'; + +export { isBrowser }; diff --git a/src/utils/fetch.ts b/src/utils/fetch.ts index cef615c..3724e84 100644 --- a/src/utils/fetch.ts +++ b/src/utils/fetch.ts @@ -1,4 +1,16 @@ import axios, { Axios } from 'axios'; +import { isBrowser } from './detectPlatform'; +import { AxiosAgents } from '../types'; + +export function createAgentAdapter(fetch: Axios, agents?: AxiosAgents) { + if (!isBrowser && agents && Object.values(agents || {}).length) { + fetch.interceptors.request.use(config => { + config.httpAgent = agents.httpAgent; + config.httpsAgent = agents.httpsAgent; + return config; + }); + } +} export function createCacheAdapter(fetch: Axios, ttl: number) { // creates cache adapter for axios @@ -8,11 +20,22 @@ export function createCacheAdapter(fetch: Axios, ttl: number) { }); } -function createFetcher({ ttl }: { ttl?: number }) { - const _fetch = axios.create({ proxy: false }); +function createFetcher({ + ttl, + agents, +}: { + ttl?: number; + agents?: AxiosAgents; +}) { + const _fetch = axios.create({ + proxy: false, + }); if (ttl && ttl > 0) { createCacheAdapter(_fetch, ttl); } + if (Object.values(agents || {}).length) { + createAgentAdapter(_fetch, agents); + } return _fetch; } diff --git a/src/utils/index.ts b/src/utils/index.ts index 29a00ce..a6ec7bc 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -4,7 +4,7 @@ import { parseNFT } from './parseNFT'; import { BaseError } from './error'; import { convertToRawSVG, getImageURI } from './getImageURI'; import { resolveURI } from './resolveURI'; -import { createCacheAdapter, fetch } from './fetch'; +import { createAgentAdapter, createCacheAdapter, fetch } from './fetch'; import { isCID } from './isCID'; import { isImageURI } from './isImageURI'; @@ -12,6 +12,7 @@ export { BaseError, assert, convertToRawSVG, + createAgentAdapter, createCacheAdapter, fetch, getImageURI,