diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 01e9557..aa36a26 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 registry-url: https://registry.npmjs.org/ - run: yarn - run: yarn build diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml index 6af0c60..7a12dae 100644 --- a/.github/workflows/lint-and-test.yml +++ b/.github/workflows/lint-and-test.yml @@ -14,7 +14,7 @@ jobs: # https://github.com/actions/setup-node - uses: actions/setup-node@v2-beta with: - node-version: '16' + node-version: 18 cache: 'yarn' - run: yarn install diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 073f849..b5e2ed8 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 registry-url: https://registry.npmjs.org/ - run: yarn - run: yarn build diff --git a/__tests__/unit/transactions.spec.ts b/__tests__/unit/transactions.spec.ts index 436b3bf..95b0b5f 100644 --- a/__tests__/unit/transactions.spec.ts +++ b/__tests__/unit/transactions.spec.ts @@ -37,17 +37,17 @@ describe('transactions', () => { const expectedError = new Error('Missing property baseFeePerGas on block'); try { - gasModule.getMainnetGasType2Parameters({ block: emptyBlock, burstSize: 2, priorityFeeInWei }); + gasModule.getMainnetGasType2Parameters({ block: emptyBlock, blocksAhead: 2, priorityFeeInWei }); } catch (err) { expect(err).toStrictEqual(expectedError); } }); it('should call getBaseFeeInNextBlock when blocksAhead is 0', async () => { - const burstSize = 0; + const blocksAhead = 0; when(FlashbotsBundleProvider.getBaseFeeInNextBlock).mockReturnValue(mockFlashbotsResponse); - gasModule.getMainnetGasType2Parameters({ block: FAKE_BLOCK, burstSize, priorityFeeInWei }); + gasModule.getMainnetGasType2Parameters({ block: FAKE_BLOCK, blocksAhead, priorityFeeInWei }); expect(FlashbotsBundleProvider.getBaseFeeInNextBlock).toHaveBeenCalledWith( FAKE_BLOCK.baseFeePerGas, @@ -57,10 +57,10 @@ describe('transactions', () => { }); it('should call getBaseFeeInNextBlock when blocksAhead is 1', async () => { - const burstSize = 1; + const blocksAhead = 1; when(FlashbotsBundleProvider.getBaseFeeInNextBlock).mockReturnValue(mockFlashbotsResponse); - gasModule.getMainnetGasType2Parameters({ block: FAKE_BLOCK, burstSize, priorityFeeInWei }); + gasModule.getMainnetGasType2Parameters({ block: FAKE_BLOCK, blocksAhead, priorityFeeInWei }); expect(FlashbotsBundleProvider.getBaseFeeInNextBlock).toHaveBeenCalledWith( FAKE_BLOCK.baseFeePerGas, @@ -70,12 +70,12 @@ describe('transactions', () => { }); it('should call getMaxBaseFeeInFutureBlock when blocksAhead is more than 1', async () => { - const burstSize = 2; + const blocksAhead = 2; when(FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock).mockReturnValue(mockFlashbotsResponse); - gasModule.getMainnetGasType2Parameters({ block: FAKE_BLOCK, burstSize, priorityFeeInWei }); + gasModule.getMainnetGasType2Parameters({ block: FAKE_BLOCK, blocksAhead, priorityFeeInWei }); - expect(FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock).toHaveBeenCalledWith(FAKE_BLOCK.baseFeePerGas, burstSize); + expect(FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock).toHaveBeenCalledWith(FAKE_BLOCK.baseFeePerGas, blocksAhead); }); it('should return the right maxFeePerGas', async () => { @@ -85,7 +85,7 @@ describe('transactions', () => { const maxFeePerGas = BigNumber.from(priorityFeeInWei).add(mockFlashbotsResponse); - const fnCall = gasModule.getMainnetGasType2Parameters({ block: FAKE_BLOCK, burstSize: 2, priorityFeeInWei }); + const fnCall = gasModule.getMainnetGasType2Parameters({ block: FAKE_BLOCK, blocksAhead: 2, priorityFeeInWei }); expect(fnCall.maxFeePerGas).toEqual(maxFeePerGas); }); @@ -95,7 +95,7 @@ describe('transactions', () => { when(FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock).mockReturnValue(mockFlashbotsResponse); const maxFeePerGas = BigNumber.from(priorityFeeInWei).add(mockFlashbotsResponse); - expect(gasModule.getMainnetGasType2Parameters({ block: FAKE_BLOCK, burstSize: 2, priorityFeeInWei })).toEqual({ + expect(gasModule.getMainnetGasType2Parameters({ block: FAKE_BLOCK, blocksAhead: 2, priorityFeeInWei })).toEqual({ priorityFee: BigNumber.from(priorityFeeInWei), maxFeePerGas, }); diff --git a/package.json b/package.json index f48de89..8593812 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ }, "dependencies": { "@flashbots/ethers-provider-bundle": "0.6.1", + "axios": "1.6.7", "chalk": "4.1.1", "dotenv": "16.0.1", "ethers": "5.6.9", diff --git a/src/broadcastors/flashbotsBroadcastor.ts b/src/broadcastors/flashbotsBroadcastor.ts deleted file mode 100644 index 06fb2c7..0000000 --- a/src/broadcastors/flashbotsBroadcastor.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { getGasParametersNextBlock, populateTx, sendAndHandleResponse } from '../transactions'; -import type { TransactionRequest } from '@ethersproject/abstract-provider'; -import type { FlashbotsBundleTransaction, FlashbotsBundleProvider } from '@flashbots/ethers-provider-bundle'; -import type { Wallet, Overrides } from 'ethers'; -import { BroadcastorProps } from 'types'; - -/** - * @notice Creates and populate a transaction for work in a determinated job using flashbots - * - * @param flashbotsProvider The flashbot provider that will send the bundle - * @param priorityFeeInWei The priority fee in wei - * @param gasLimit The gas limit determines the maximum gas that can be spent in the transaction - * @param doStaticCall Flag to determinate whether to perform a callStatic to work or not. Defaults to true. - * - */ -export class FlashbotsBroadcastor { - public chainId: number; - - constructor( - public flashbotsProvider: FlashbotsBundleProvider, - public priorityFeeInWei: number, - public gasLimit: number, - public doStaticCall = true - ) { - this.chainId = flashbotsProvider.network.chainId; - } - - async tryToWorkOnFlashbots(props: BroadcastorProps): Promise { - const { jobContract, workMethod, workArguments, block } = props; - - if (this.doStaticCall) { - try { - await jobContract.callStatic[workMethod](...workArguments); - } catch (error: unknown) { - if (error instanceof Error) { - console.log(`Static call failed with ${error.message}`); - } - return; - } - } - - const { priorityFee, maxFeePerGas } = getGasParametersNextBlock({ block, priorityFeeInWei: this.priorityFeeInWei }); - - const txSigner = jobContract.signer as Wallet; - - const currentNonce = await txSigner.getTransactionCount(); - - const options: Overrides = { - gasLimit: this.gasLimit, - nonce: currentNonce, - maxFeePerGas, - maxPriorityFeePerGas: priorityFee, - type: 2, - }; - - const tx: TransactionRequest = await populateTx({ - contract: jobContract, - functionName: workMethod, - functionArgs: [...workArguments], - options, - chainId: this.chainId, - }); - - const privateTx: FlashbotsBundleTransaction = { - transaction: tx, - signer: txSigner, - }; - - console.log('Transaction populated successfully. Sending bundle...'); - - await sendAndHandleResponse({ flashbotsProvider: this.flashbotsProvider, privateTx }); - } -} diff --git a/src/broadcastors/index.ts b/src/broadcastors/index.ts index 218689d..936f9b2 100644 --- a/src/broadcastors/index.ts +++ b/src/broadcastors/index.ts @@ -1,3 +1,3 @@ -export * from './flashbotsBroadcastor'; +export * from './privateBroadcastor'; export * from './mempoolBroadcastor'; export * from './stealthBroadcastor'; diff --git a/src/broadcastors/mempoolBroadcastor.ts b/src/broadcastors/mempoolBroadcastor.ts index 2093068..31f3e4c 100644 --- a/src/broadcastors/mempoolBroadcastor.ts +++ b/src/broadcastors/mempoolBroadcastor.ts @@ -20,7 +20,7 @@ export class MempoolBroadcastor { public doStaticCall = true ) {} - tryToWorkOnMempool = async (props: BroadcastorProps): Promise => { + tryToWork = async (props: BroadcastorProps): Promise => { const { jobContract, workMethod, workArguments, block } = props; const txSigner = jobContract.signer as Wallet; @@ -58,7 +58,11 @@ export class MempoolBroadcastor { await jobContract.callStatic[workMethod](...workArguments); } catch (error: unknown) { if (error instanceof Error) { - console.log(`Static call failed with ${error.message}`); + console.log( + `Static call failed. Job contract: ${jobContract.address}. Work method: ${workMethod}. Work arguments: ${[ + ...workArguments, + ].join(', ')}. Error message: ${error.message}` + ); } return; } diff --git a/src/broadcastors/privateBroadcastor.ts b/src/broadcastors/privateBroadcastor.ts new file mode 100644 index 0000000..5545143 --- /dev/null +++ b/src/broadcastors/privateBroadcastor.ts @@ -0,0 +1,81 @@ +import { getMainnetGasType2Parameters, populateTx, sendBundle } from '../transactions'; +import type { TransactionRequest } from '@ethersproject/abstract-provider'; +import { Wallet, Overrides, ethers } from 'ethers'; +import { BroadcastorProps } from 'types'; + +/** + * @notice Creates and populate a private transaction to work a specific job + * + * @param endpoints The endpoint urls + * @param priorityFeeInWei The priority fee in wei + * @param gasLimit The gas limit determines the maximum gas that can be spent in the transaction + * @param doStaticCall Flag to determinate whether to perform a callStatic to work or not. Defaults to true. + * @param chainId The chainId. + * + */ +export class PrivateBroadcastor { + constructor( + public endpoints: string[], + public priorityFeeInWei: number, + public gasLimit: number, + public doStaticCall = true, + public chainId: number + ) {} + + async tryToWork(props: BroadcastorProps): Promise { + const { jobContract, workMethod, workArguments, block } = props; + + if (this.doStaticCall) { + try { + await jobContract.callStatic[workMethod](...workArguments); + } catch (error: unknown) { + if (error instanceof Error) { + console.log( + `Static call failed. Job contract: ${jobContract.address}. Work method: ${workMethod}. Work arguments: ${[ + ...workArguments, + ].join(', ')}. Error message: ${error.message}` + ); + } + return; + } + } + + const blocksAhead = 2; + const targetBlock = block.number + blocksAhead; + + const { priorityFee, maxFeePerGas } = getMainnetGasType2Parameters({ + block, + priorityFeeInWei: this.priorityFeeInWei, + blocksAhead, + }); + + const txSigner = jobContract.signer as Wallet; + + const currentNonce = await txSigner.getTransactionCount(); + + const options: Overrides = { + gasLimit: this.gasLimit, + nonce: currentNonce, + maxFeePerGas, + maxPriorityFeePerGas: priorityFee, + type: 2, + }; + + const tx: TransactionRequest = await populateTx({ + contract: jobContract, + functionName: workMethod, + functionArgs: [...workArguments], + options, + chainId: this.chainId, + }); + + const privateTx = await txSigner.signTransaction(tx); + console.log(`Bundle populated successfully. Sending private bundle: ${workArguments}`); + + await sendBundle({ + endpoints: this.endpoints, + privateTx, + targetBlock: ethers.utils.hexlify(targetBlock).toString(), + }); + } +} diff --git a/src/broadcastors/stealthBroadcastor.ts b/src/broadcastors/stealthBroadcastor.ts index 2ae6cce..75c7cc3 100644 --- a/src/broadcastors/stealthBroadcastor.ts +++ b/src/broadcastors/stealthBroadcastor.ts @@ -1,36 +1,31 @@ -import { calculateTargetBlocks, getStealthHash } from '../flashbots'; -import { getMainnetGasType2Parameters, populateTx, sendAndHandleResponse } from '../transactions'; +import { getStealthHash } from '../flashbots'; +import { getMainnetGasType2Parameters, populateTx, sendBundle } from '../transactions'; import type { TransactionRequest } from '@ethersproject/abstract-provider'; -import type { FlashbotsBundleTransaction, FlashbotsBundleProvider } from '@flashbots/ethers-provider-bundle'; -import type { Wallet, Overrides, Contract } from 'ethers'; +import { Contract, Overrides, Wallet, ethers } from 'ethers'; import { BroadcastorProps } from 'types'; /** - * @notice Creates and populate a transaction for work in a determinated job using flashbots + * @notice Creates and populate a private transaction to work a specific job * - * @param flashbotsProvider The flashbots provider. It contains a JSON or WSS provider - * @param flashbots The flashbot that will send the bundle - * @param burstSize The amount of transactions for future blocks to be broadcast each time + * @param endpoints The endpoint urls + * @param stealthRelayer The address of the StealthRelayer contract. * @param priorityFeeInWei The priority fee in wei - * @param gasLimit The gas limit determines the maximum gas that can be spent in the transaction - * @param doStaticCall Flag to determinate whether to perform a callStatic to work or not. Defaults to true. + * @param gasLimit The gas limit determines the maximum gas that can be spent in the transaction + * @param doStaticCall Flag to determinate whether to perform a callStatic to work or not. Defaults to true. + * @param chainId The chainId. * */ export class StealthBroadcastor { - public chainId: number; - constructor( - public flashbotsProvider: FlashbotsBundleProvider, + public endpoints: string[], public stealthRelayer: Contract, public priorityFeeInWei: number, public gasLimit: number, - public burstSize: number, - public doStaticCall = true - ) { - this.chainId = flashbotsProvider.network.chainId; - } + public doStaticCall = true, + public chainId: number + ) {} - async tryToWorkOnStealthRelayer(props: BroadcastorProps): Promise { + async tryToWork(props: BroadcastorProps): Promise { const { jobContract, workMethod, workArguments, block } = props; const stealthHash = getStealthHash(); @@ -41,22 +36,25 @@ export class StealthBroadcastor { await this.stealthRelayer.callStatic.execute(jobContract.address, workData, stealthHash, block.number); } catch (error: unknown) { if (error instanceof Error) { - console.log(`Static call failed with ${error.message}`); + console.log( + `Static call failed. Job contract: ${jobContract.address}. Work method: ${workMethod}. Work arguments: ${[ + ...workArguments, + ].join(', ')}. Error message: ${error.message}` + ); } return; } } - console.log(`Attempting to work strategy statically succeeded. Preparing real transaction...`); - - const nextBlock = block.number; + console.log(`Attempting to work strategy statically succeeded. Preparing real bundle...`); - const targetBlocks = calculateTargetBlocks(this.burstSize, nextBlock); + const blocksAhead = 2; + const targetBlock = block.number + blocksAhead; const { priorityFee, maxFeePerGas } = getMainnetGasType2Parameters({ block, priorityFeeInWei: this.priorityFeeInWei, - burstSize: this.burstSize, + blocksAhead, }); const txSigner = jobContract.signer as Wallet; @@ -71,23 +69,22 @@ export class StealthBroadcastor { type: 2, }; - for (const targetBlock of targetBlocks) { - const tx: TransactionRequest = await populateTx({ - contract: this.stealthRelayer, - functionName: 'execute', - functionArgs: [jobContract.address, workData, stealthHash, targetBlock], - options, - chainId: this.chainId, - }); + const tx: TransactionRequest = await populateTx({ + contract: this.stealthRelayer, + functionName: 'execute', + functionArgs: [jobContract.address, workData, stealthHash, targetBlock], + options, + chainId: this.chainId, + }); - const privateTx: FlashbotsBundleTransaction = { - transaction: tx, - signer: txSigner, - }; + const privateTx = await txSigner.signTransaction(tx); - console.log('Transaction populated successfully. Sending bundle...'); + console.log(`Bundle populated successfully. Sending private bundle for strategy: ${workArguments}`); - sendAndHandleResponse({ flashbotsProvider: this.flashbotsProvider, privateTx, maxBlockNumber: targetBlock }); - } + await sendBundle({ + endpoints: this.endpoints, + privateTx, + targetBlock: ethers.utils.hexlify(targetBlock).toString(), + }); } } diff --git a/src/transactions/getMainnetGasType2Parameters.ts b/src/transactions/getMainnetGasType2Parameters.ts index 93807d3..1f9f1eb 100644 --- a/src/transactions/getMainnetGasType2Parameters.ts +++ b/src/transactions/getMainnetGasType2Parameters.ts @@ -14,17 +14,17 @@ import { BigNumber } from 'ethers'; * @return An object containing the provided priority fee in gwei and the calculated maxFeePerGas. */ export function getMainnetGasType2Parameters(props: GetMainnetGasType2ParametersProps): GasType2Parameters { - const { block, priorityFeeInWei, burstSize } = props; + const { block, priorityFeeInWei, blocksAhead } = props; if (!block.baseFeePerGas) { throw new Error('Missing property baseFeePerGas on block'); } - if (burstSize === 0 || burstSize === 1) { + if (blocksAhead === 0 || blocksAhead === 1) { return getGasParametersNextBlock({ block, priorityFeeInWei }); } - const maxBaseFee = FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock(block.baseFeePerGas, burstSize); + const maxBaseFee = FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock(block.baseFeePerGas, blocksAhead); const priorityFee = BigNumber.from(priorityFeeInWei); const maxFeePerGas = maxBaseFee.add(priorityFee); diff --git a/src/transactions/index.ts b/src/transactions/index.ts index f734bb5..96b87be 100644 --- a/src/transactions/index.ts +++ b/src/transactions/index.ts @@ -2,4 +2,6 @@ export * from './sendTx'; export * from './getMainnetGasType2Parameters'; export * from './populateTx'; export * from './sendAndHandleResponse'; +export * from './sendBundle'; +export * from './sendPrivateTransaction'; export * from './getGasParametersNextBlock'; diff --git a/src/transactions/sendAndHandleResponse.ts b/src/transactions/sendAndHandleResponse.ts index cd81c35..6998a5c 100644 --- a/src/transactions/sendAndHandleResponse.ts +++ b/src/transactions/sendAndHandleResponse.ts @@ -1,6 +1,6 @@ import { SendAndHandleResponseProps } from 'types'; -export async function sendAndHandleResponse(props: SendAndHandleResponseProps) { +export async function sendAndHandleResponse(props: SendAndHandleResponseProps): Promise { const { flashbotsProvider, privateTx, maxBlockNumber } = props; try { diff --git a/src/transactions/sendBundle.ts b/src/transactions/sendBundle.ts new file mode 100644 index 0000000..dcdc11e --- /dev/null +++ b/src/transactions/sendBundle.ts @@ -0,0 +1,40 @@ +import axios from 'axios'; +import { SendPrivateBundleProps } from 'types'; + +export async function sendBundle(props: SendPrivateBundleProps): Promise { + const { endpoints, privateTx, targetBlock } = props; + + const requestData = { + jsonrpc: '2.0', + method: 'eth_sendBundle', + params: [ + { + txs: [privateTx], + blockNumber: targetBlock, + }, + ], + id: '1', + }; + + const promises = endpoints.map(async (endpoint) => { + try { + const response = await axios.post(endpoint, requestData, { + headers: { + 'Content-Type': 'application/json', + }, + }); + console.log(response.data); + } catch (error) { + if (axios.isAxiosError(error)) { + console.error('Axios error message:', error.message); + if (error.response) { + console.log('Response data:', error.response.data); + } + } else { + console.error('Unexpected error:', error); + } + } + }); + + await Promise.all(promises); +} diff --git a/src/transactions/sendPrivateTransaction.ts b/src/transactions/sendPrivateTransaction.ts new file mode 100644 index 0000000..ee8c294 --- /dev/null +++ b/src/transactions/sendPrivateTransaction.ts @@ -0,0 +1,37 @@ +import axios from 'axios'; +import { SendPrivateTransactionProps } from 'types'; + +export async function sendPrivateTransaction(props: SendPrivateTransactionProps): Promise { + const { endpoint, privateTx, maxBlockNumber } = props; + + const requestData = { + jsonrpc: '2.0', + method: 'eth_sendPrivateTransaction', + params: [ + { + privateTx, + maxBlockNumber, + }, + ], + id: '1', + }; + + try { + const response = await axios.post(endpoint, requestData, { + headers: { + 'Content-Type': 'application/json', + }, + }); + + console.log(response.data); + } catch (error) { + if (axios.isAxiosError(error)) { + console.error('Axios error message:', error.message); + if (error.response) { + console.log('Response data:', error.response.data); + } + } else { + console.error('Unexpected error:', error); + } + } +} diff --git a/src/types/Transactions.ts b/src/types/Transactions.ts index 1269a66..4067adc 100644 --- a/src/types/Transactions.ts +++ b/src/types/Transactions.ts @@ -36,12 +36,12 @@ export interface SendTxProps { * * @param block The current block. * @param priorityFeeInWei The priority fee that will be used for the transaction being formatted. - * @param burstSize The number blocks to send the transaction to. Can also be interpreted as the number of blocks into the future to use when calculating the maximum base fee. + * @param blocksAhead The number blocks to send the transaction to. Can also be interpreted as the number of blocks into the future to use when calculating the maximum base fee. */ export interface GetMainnetGasType2ParametersProps { block: Block; priorityFeeInWei: number; - burstSize: number; + blocksAhead: number; } /** @@ -57,6 +57,32 @@ export interface SendAndHandleResponseProps { maxBlockNumber?: number; } +/** + * @notice sendPrivateTransaction includes all parameters required to call sendPrivateTransaction function + * + * @param endpoint The endpoint to hit. + * @param privateTx The private flashbots transaction to send serialized. + * @param maxBlockNumber The maximum block number at this transaction will try to be included as a hex string + */ +export interface SendPrivateTransactionProps { + endpoint: string; + privateTx: string; + maxBlockNumber?: string; +} + +/** + * @notice SendBundleProps includes all parameters required to call SendBundleProps function + * + * @param flashbotsProvider A flashbots provider. + * @param privateTx The private flashbots transactions to send. + * @param targetBlockNumber The block number at which flashbots will try to include the transaction. + */ +export interface SendBundleProps { + flashbotsProvider: FlashbotsBundleProvider; + privateTxs: FlashbotsBundleTransaction[]; + targetBlockNumber: number; +} + /** * @notice GetGasParametersNextBlockProps includes all base properties required to compute the maxFeePerGas property * in order to format a transaction to type 2. @@ -68,3 +94,16 @@ export interface GetGasParametersNextBlockProps { block: Block; priorityFeeInWei: number; } + +/** + * @notice sendPrivateBundle includes all parameters required to call sendPrivateBundle function + * + * @param endpoints The endpoints to hit. + * @param privateTx The private flashbots transaction to send serialized. + * @param targetBlock The block number where this bundle will be valid. + */ +export interface SendPrivateBundleProps { + endpoints: string[]; + privateTx: string; + targetBlock?: string; +} diff --git a/yarn.lock b/yarn.lock index 35f723e..b17b3f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1752,6 +1752,20 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" + integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA== + dependencies: + follow-redirects "^1.15.4" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + babel-jest@^29.0.3: version "29.0.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.0.3.tgz#64e156a47a77588db6a669a88dedff27ed6e260f" @@ -2024,6 +2038,13 @@ colorette@^2.0.16, colorette@^2.0.17: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^9.3.0: version "9.4.0" resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.0.tgz#bc4a40918fefe52e22450c111ecd6b7acce6f11c" @@ -2077,6 +2098,11 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -2494,6 +2520,20 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +follow-redirects@^1.15.4: + version "1.15.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" + integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -3407,6 +3447,18 @@ micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.2" picomatch "^2.3.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -3673,6 +3725,11 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"