From df35ef720b08ba18a1b8386bd98ce6c4f492ae2a Mon Sep 17 00:00:00 2001 From: Nicolas Chamo Date: Wed, 30 Jul 2025 15:12:49 -0300 Subject: [PATCH] chore: clean up --- README.md | 397 ---- hardhat.config.ts | 12 - package.json | 22 +- src/chains.ts | 9 +- src/sdk/builders/dca-builder.ts | 28 - src/sdk/builders/earn-builder.ts | 31 - src/sdk/builders/permit2-builder.ts | 8 - src/sdk/sdk-builder.ts | 18 - src/sdk/types.ts | 6 - .../balance-sources/rpc-balance-source.ts | 112 +- src/services/dca/config.ts | 15 - src/services/dca/dca-service.ts | 1274 ----------- src/services/dca/index.ts | 43 - src/services/dca/types.ts | 310 --- src/services/earn/config.ts | 14 - src/services/earn/earn-service.ts | 1727 --------------- src/services/earn/index.ts | 13 - src/services/earn/types.ts | 381 ---- src/services/index.ts | 2 - src/services/permit2/README.md | 188 -- src/services/permit2/index.ts | 15 - .../permit2/permit2-arbitrary-service.ts | 117 -- src/services/permit2/permit2-quote-service.ts | 308 --- src/services/permit2/permit2-service.ts | 143 -- src/services/permit2/types.ts | 180 -- src/services/permit2/utils/config.ts | 37 - src/services/permit2/utils/eip712-types.ts | 25 - .../price-sources/alchemy-price-source.ts | 6 +- .../quotes/quote-sources/oku-quote-source.ts | 280 --- src/services/quotes/source-registry.ts | 2 - src/shared/abis/companion.ts | 223 -- src/shared/abis/dca-hub.ts | 234 --- .../abis/earn-delayed-withdrawal-manager.ts | 33 - src/shared/abis/earn-strategy-router.ts | 24 - src/shared/abis/earn-strategy.ts | 28 - src/shared/abis/earn-vault-companion.ts | 210 -- src/shared/abis/earn-vault.ts | 126 -- src/shared/abis/erc721.ts | 21 - src/shared/abis/permit2-adapter.ts | 222 -- src/shared/abis/permit2.ts | 12 - .../permit2/permit2-arbitrary-service.spec.ts | 231 -- .../permit2/permit2-quote-service.spec.ts | 116 - .../services/quotes/quote-tests-config.ts | 1 - .../quotes/sources/quote-sources.spec.ts | 436 ---- test/integration/utils/erc20.ts | 425 ---- test/integration/utils/evm.ts | 28 - test/integration/utils/other.ts | 9 +- test/tsconfig.json | 3 +- yarn.lock | 1870 ++--------------- 49 files changed, 170 insertions(+), 9805 deletions(-) delete mode 100644 hardhat.config.ts delete mode 100644 src/sdk/builders/dca-builder.ts delete mode 100644 src/sdk/builders/earn-builder.ts delete mode 100644 src/sdk/builders/permit2-builder.ts delete mode 100644 src/services/dca/config.ts delete mode 100644 src/services/dca/dca-service.ts delete mode 100644 src/services/dca/index.ts delete mode 100644 src/services/dca/types.ts delete mode 100644 src/services/earn/config.ts delete mode 100644 src/services/earn/earn-service.ts delete mode 100644 src/services/earn/index.ts delete mode 100644 src/services/earn/types.ts delete mode 100644 src/services/permit2/README.md delete mode 100644 src/services/permit2/index.ts delete mode 100644 src/services/permit2/permit2-arbitrary-service.ts delete mode 100644 src/services/permit2/permit2-quote-service.ts delete mode 100644 src/services/permit2/permit2-service.ts delete mode 100644 src/services/permit2/types.ts delete mode 100644 src/services/permit2/utils/config.ts delete mode 100644 src/services/permit2/utils/eip712-types.ts delete mode 100644 src/services/quotes/quote-sources/oku-quote-source.ts delete mode 100644 src/shared/abis/companion.ts delete mode 100644 src/shared/abis/dca-hub.ts delete mode 100644 src/shared/abis/earn-delayed-withdrawal-manager.ts delete mode 100644 src/shared/abis/earn-strategy-router.ts delete mode 100644 src/shared/abis/earn-strategy.ts delete mode 100644 src/shared/abis/earn-vault-companion.ts delete mode 100644 src/shared/abis/earn-vault.ts delete mode 100644 src/shared/abis/erc721.ts delete mode 100644 src/shared/abis/permit2-adapter.ts delete mode 100644 src/shared/abis/permit2.ts delete mode 100644 test/integration/services/permit2/permit2-arbitrary-service.spec.ts delete mode 100644 test/integration/services/permit2/permit2-quote-service.spec.ts delete mode 100644 test/integration/services/quotes/sources/quote-sources.spec.ts delete mode 100644 test/integration/utils/erc20.ts delete mode 100644 test/integration/utils/evm.ts diff --git a/README.md b/README.md index 662a8cd9..2fd894ba 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,6 @@ The SDK is divided into the following services: - **[Gas Service](#gas-service)**: Optimize transaction costs and estimate gas prices - **[Prices Service](#prices-service)**: Retrieve token price information across multiple chains - **[Metadata Service](#metadata-service)**: Access token metadata and information -- **[Permit2 Service](#permit2-service)**: Manage token approvals using the Permit2 protocol -- **[DCA Service](#dca-service)**: Set up and manage Dollar Cost Averaging positions -- **[Earn Service](#earn-service)**: Handle yield farming operations Each service provides a focused set of functionality while maintaining a consistent interface and error handling approach. This modular design allows developers to use only the services they need while ensuring a cohesive experience across the entire SDK. @@ -460,192 +457,6 @@ const allTxs = await sdk.quoteService.buildAllTxs({ }); ``` -### DCA Service - -The DCA (Dollar Cost Averaging) Service provides functionality for setting up and managing DCA positions. - -#### Objective and Potential - -- **Objective**: Enable automated dollar-cost averaging strategies for any token pair -- **Potential Use Cases**: - - Automated investment strategies - - Risk management through periodic investments - - Customizable DCA schedules - - Multi-chain DCA positions - - Permission management for shared positions - -#### Methods - -##### `getAllowanceTarget(params)` - -Gets the allowance target address for a DCA position. - -```typescript -const target = sdk.dcaService.getAllowanceTarget({ - chainId: Chains.ETHEREUM.chainId, - from: "0x...", // Token to sell - depositWith: "0x...", // Token to deposit with - usePermit2: boolean, -}); -``` - -##### `preparePermitData(params)` - -Prepares permit data for token approvals. - -```typescript -const permitData = await sdk.dcaService.preparePermitData({ - // Permit2 parameters -}); -``` - -##### `buildCreatePositionTx(params)` - -Builds a transaction to create a new DCA position. - -```typescript -const tx = await sdk.dcaService.buildCreatePositionTx({ - chainId: Chains.ETHEREUM.chainId, - from: { address: "0x...", variantId: "..." }, - to: { address: "0x...", variantId: "..." }, - swapInterval: DCASwapInterval.ONE_DAY, - amountOfSwaps: 30, - owner: "0x...", - permissions: [{ operator: "0x...", permissions: [DCAPermission.INCREASE] }], - deposit: { token: "0x...", amount: BigInt("1000000") }, -}); -``` - -##### `buildIncreasePositionTx(params)` - -Builds a transaction to increase an existing DCA position. - -```typescript -const tx = await sdk.dcaService.buildIncreasePositionTx({ - chainId: Chains.ETHEREUM.chainId, - positionId: "123", - increase: { token: "0x...", amount: BigInt("1000000") }, - amountOfSwaps: 30, -}); -``` - -##### `buildReducePositionTx(params)` - -Builds a transaction to reduce an existing DCA position. - -```typescript -const tx = await sdk.dcaService.buildReducePositionTx({ - chainId: Chains.ETHEREUM.chainId, - positionId: "123", - amountOfSwaps: 15, - reduce: { amount: BigInt("500000") }, - recipient: "0x...", -}); -``` - -##### `buildReduceToBuyPositionTx(params)` - -Builds a transaction to reduce a position to buy a specific amount. - -```typescript -const tx = await sdk.dcaService.buildReduceToBuyPositionTx({ - chainId: Chains.ETHEREUM.chainId, - positionId: "123", - amountOfSwaps: 15, - reduce: { amountToBuy: BigInt("500000") }, - recipient: "0x...", -}); -``` - -##### `buildWithdrawPositionTx(params)` - -Builds a transaction to withdraw from a DCA position. - -```typescript -const tx = await sdk.dcaService.buildWithdrawPositionTx({ - chainId: Chains.ETHEREUM.chainId, - positionId: "123", - withdraw: {}, - recipient: "0x...", -}); -``` - -##### `buildTerminatePositionTx(params)` - -Builds a transaction to terminate a DCA position. - -```typescript -const tx = await sdk.dcaService.buildTerminatePositionTx({ - chainId: Chains.ETHEREUM.chainId, - positionId: "123", - withdraw: {}, - recipient: "0x...", -}); -``` - -##### `buildMigratePositionTx(params)` - -Builds a transaction to migrate a DCA position to a new hub. - -```typescript -const tx = await sdk.dcaService.buildMigratePositionTx({ - chainId: Chains.ETHEREUM.chainId, - sourceHub: "0x...", - targetHub: "0x...", - positionId: "123", - migration: { useFundsFrom: "swapped", sendUnusedFundsTo: "0x..." }, -}); -``` - -##### `getSupportedPairs(params)` - -Gets supported token pairs for DCA positions. - -```typescript -const pairs = await sdk.dcaService.getSupportedPairs({ - chains: [Chains.ETHEREUM.chainId], - config: { timeout: "30s" }, -}); -``` - -##### `getPositionsByAccount(params)` - -Gets DCA positions for specific accounts. - -```typescript -const positions = await sdk.dcaService.getPositionsByAccount({ - accounts: ["0x..."], - chains: [Chains.ETHEREUM.chainId], - includeHistory: true, - config: { timeout: "30s" }, -}); -``` - -##### `getPositionsById(params)` - -Gets DCA positions by their IDs. - -```typescript -const positions = await sdk.dcaService.getPositionsById({ - ids: [{ chainId: Chains.ETHEREUM.chainId, hub: "0x...", positionId: 123 }], - includeHistory: true, - config: { timeout: "30s" }, -}); -``` - -##### `getPairSwaps(params)` - -Gets swap history for a token pair. - -```typescript -const swaps = await sdk.dcaService.getPairSwaps({ - chainId: Chains.ETHEREUM.chainId, - variantTokenA: "...", - variantTokenB: "...", - config: { timeout: "30s" }, -}); -``` - ### Gas Service The Gas Service provides gas price estimation and optimization across different chains. @@ -948,214 +759,6 @@ const metadata = await sdk.metadataService.getMetadata({ }); ``` -### Permit2 Service - -The Permit2 Service provides functionality for managing token approvals using the Permit2 protocol. - -#### Objective and Potential - -- **Objective**: Enable efficient and secure token approvals using the Permit2 standard -- **Potential Use Cases**: - - Gas-optimized token approvals - - Batch approvals - - Cross-protocol permission management - - Automated approval systems - - Security-focused approval workflows - -```typescript -// Get permit2 allowance -const allowance = await sdk.permit2Service.getAllowance({ - chainId: Chains.ETHEREUM.chainId, - token: "0x...", - owner: "0x...", - spender: "0x...", -}); -``` - -### Earn Service - -The Earn Service provides functionality for yield farming and staking operations. - -#### Objective and Potential - -- **Objective**: Enable efficient yield farming and staking operations across multiple protocols -- **Potential Use Cases**: - - Yield farming strategy management - - Automated position management - - Cross-protocol yield optimization - - Permission-based position sharing - - Delayed withdrawal management - - Strategy migration and optimization - -#### Methods - -##### `getAllowanceTarget(params)` - -Gets the allowance target address for a strategy. - -```typescript -const target = await sdk.earnService.getAllowanceTarget({ - chainId: Chains.ETHEREUM.chainId, - strategyId: "1-0x1234567890123456789012345678901234567890-42", // Format: chainId-registryAddress-strategyNumber - depositWith: "0x...", // Token to deposit with - usePermit2: boolean, -}); -``` - -##### `preparePermitData(params)` - -Prepares permit data for token approvals. - -```typescript -const permitData = await sdk.earnService.preparePermitData({ - chainId: Chains.ETHEREUM.chainId, - token: "0x...", - amount: "1000000", - spender: "0x...", -}); -``` - -##### `preparePermissionData(params)` - -Prepares permission data for position management. - -```typescript -const permissionData = await sdk.earnService.preparePermissionData({ - chainId: Chains.ETHEREUM.chainId, - positionId: "1-0xabcdef1234567890123456789012345678901234-1337", // Format: chainId-vaultAddress-positionNumber - permissions: [{ operator: "0x...", permissions: [EarnPermission.INCREASE] }], - signerAddress: "0x...", - signatureValidFor: "1w", -}); -``` - -##### `buildCreatePositionTx(params)` - -Builds a transaction to create a new earn position. - -```typescript -const tx = await sdk.earnService.buildCreatePositionTx({ - chainId: Chains.ETHEREUM.chainId, - strategyId: "1-0x1234567890123456789012345678901234567890-42", // Format: chainId-registryAddress-strategyNumber - owner: "0x...", - permissions: [{ operator: "0x...", permissions: [EarnPermission.INCREASE] }], - deposit: { token: "0x...", amount: "1000000" }, -}); -``` - -##### `buildIncreasePositionTx(params)` - -Builds a transaction to increase an existing position. - -```typescript -const tx = await sdk.earnService.buildIncreasePositionTx({ - chainId: Chains.ETHEREUM.chainId, - positionId: "1-0xabcdef1234567890123456789012345678901234-1337", // Format: chainId-vaultAddress-positionNumber - increase: { token: "0x...", amount: "1000000" }, -}); -``` - -##### `buildWithdrawPositionTx(params)` - -Builds a transaction to withdraw from a position. - -```typescript -const tx = await sdk.earnService.buildWithdrawPositionTx({ - chainId: Chains.ETHEREUM.chainId, - positionId: "1-0xabcdef1234567890123456789012345678901234-1337", // Format: chainId-vaultAddress-positionNumber - withdraw: { type: "market", token: "0x...", amount: "1000000" }, -}); -``` - -##### `buildClaimDelayedWithdrawPositionTx(params)` - -Builds a transaction to claim a delayed withdrawal. - -```typescript -const tx = await sdk.earnService.buildClaimDelayedWithdrawPositionTx({ - chainId: Chains.ETHEREUM.chainId, - positionId: "1-0xabcdef1234567890123456789012345678901234-1337", // Format: chainId-vaultAddress-positionNumber -}); -``` - -##### `estimateMarketWithdraw(params)` - -Estimates the amount of tokens that would be received from a market withdrawal. - -```typescript -const estimation = await sdk.earnService.estimateMarketWithdraw({ - chainId: Chains.ETHEREUM.chainId, - positionId: "1-0xabcdef1234567890123456789012345678901234-1337", // Format: chainId-vaultAddress-positionNumber - token: "0x...", - amount: "1000000", - swapConfig: { - slippagePercentage: 1, - txValidFor: "1w", - }, -}); -``` - -##### `getSupportedStrategies(params)` - -Gets supported strategies for yield farming. - -```typescript -const strategies = await sdk.earnService.getSupportedStrategies({ - chains: [Chains.ETHEREUM.chainId], - config: { timeout: "30s" }, -}); -``` - -##### `getStrategy(params)` - -Gets detailed information about a specific strategy. - -```typescript -const strategy = await sdk.earnService.getStrategy({ - strategy: "1-0x1234567890123456789012345678901234567890-42", // Format: chainId-registryAddress-strategyNumber - config: { timeout: "30s" }, -}); -``` - -##### `getPositionsByAccount(params)` - -Gets earn positions for specific accounts. - -```typescript -const positions = await sdk.earnService.getPositionsByAccount({ - accounts: ["0x..."], - chains: [Chains.ETHEREUM.chainId], - includeHistory: true, - includeHistoricalBalancesFrom: 1672531200, - config: { timeout: "30s" }, -}); -``` - -##### `getPositionsById(params)` - -Gets earn positions by their IDs. - -```typescript -const positions = await sdk.earnService.getPositionsById({ - ids: ["1-0xabcdef1234567890123456789012345678901234-1337"], // Format: chainId-vaultAddress-positionNumber - includeHistory: true, - includeHistoricalBalancesFrom: 1672531200, - config: { timeout: "30s" }, -}); -``` - -##### `getStrategyAsset(params)` - -Gets the asset token for a strategy or position. - -```typescript -const asset = await sdk.earnService.getStrategyAsset({ - chainId: Chains.ETHEREUM.chainId, - strategyId: "1-0x1234567890123456789012345678901234567890-42", // Format: chainId-registryAddress-strategyNumber - // or positionId: "1-0xabcdef1234567890123456789012345678901234-1337" // Format: chainId-vaultAddress-positionNumber -}); -``` - ## Advanced Usage ### Error Handling diff --git a/hardhat.config.ts b/hardhat.config.ts deleted file mode 100644 index be495a2c..00000000 --- a/hardhat.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { HardhatUserConfig } from 'hardhat/types'; -import '@nomiclabs/hardhat-ethers'; -import '@nomicfoundation/hardhat-chai-matchers'; -import 'tsconfig-paths/register'; -import dotenv from 'dotenv'; -dotenv.config(); - -const config: HardhatUserConfig = { - defaultNetwork: 'hardhat', -}; - -export default config; diff --git a/package.json b/package.json index 266bc9d7..45c84f7e 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { - "name": "@balmy/sdk", - "version": "0.9.0", + "name": "@nchamo/sdk", + "version": "0.0.1", "contributors": [ { - "name": "Nicolás Chamo", - "email": "nchamo@balmy.xyz", + "name": "Nicolas Chamo", + "email": "nicolas@chamo.com.ar", "url": "https://github.com/nchamo" }, { @@ -34,8 +34,7 @@ "prepare": "husky install", "script": "ts-node -r tsconfig-paths/register", "test": "jest --forceExit --detectOpenHandles --verbose", - "test:integration": "jest --forceExit --detectOpenHandles --verbose --testPathPattern=test/integration -t \"^(?!.*\\[External Quotes\\]).*$\"", - "test:integration:quotes": "jest --forceExit --detectOpenHandles --verbose -t \".*\\[External Quotes\\].*\"", + "test:integration": "jest --forceExit --detectOpenHandles --verbose --testPathPattern=test/integration", "test:unit": "jest --forceExit --detectOpenHandles --verbose --testPathPattern=test/unit" }, "lint-staged": { @@ -49,24 +48,21 @@ "lru-cache": "9.0.3", "ms": "3.0.0-canary.1", "qs": "6.11.2", - "viem": "2.28.0" + "viem": "2.33.1" }, "devDependencies": { "@commitlint/cli": "17.8.0", "@commitlint/config-conventional": "17.8.0", - "@nomicfoundation/hardhat-chai-matchers": "1.0.6", - "@nomicfoundation/hardhat-network-helpers": "1.0.8", - "@nomicfoundation/hardhat-toolbox": "2.0.2", - "@nomiclabs/hardhat-ethers": "2.2.3", + "@types/chai": "5.2.2", + "@types/chai-as-promised": "7", "@types/crypto-js": "4.1.2", "@types/jest": "29.5.6", "@types/node": "18.16.3", "@types/qs": "6.9.10", "@types/ws": "8.5.10", "chai": "4.3.7", + "chai-as-promised": "7", "dotenv": "16.3.1", - "ethers": "5.7.2", - "hardhat": "2.23.0", "husky": "8.0.3", "jest": "29.7.0", "lint-staged": "13.2.2", diff --git a/src/chains.ts b/src/chains.ts index 9a2ef769..0f039a1d 100644 --- a/src/chains.ts +++ b/src/chains.ts @@ -99,7 +99,6 @@ export const Chains = { 'https://polygon-mainnet.public.blastapi.io', 'https://rpc.ankr.com/polygon', 'https://rpc-mainnet.matic.quiknode.pro', - 'https://matic-mainnet.chainstacklabs.com', 'https://polygon-pokt.nodies.app', ], explorer: 'https://polygonscan.com/', @@ -486,7 +485,13 @@ export const Chains = { ids: ['scroll'], nativeCurrency: { symbol: 'ETH', name: 'Ethereum' }, wToken: '0x5300000000000000000000000000000000000004', - publicRPCs: ['https://scroll-mainnet.chainstacklabs.com', 'https://rpc.ankr.com/scroll', 'https://rpc.scroll.io', 'https://1rpc.io/scroll'], + publicRPCs: [ + 'https://rpc.ankr.com/scroll', + 'https://rpc.scroll.io', + 'https://1rpc.io/scroll', + 'https://scroll.therpc.io', + 'https://scroll-rpc.publicnode.com', + ], explorer: 'https://scrollscan.com/', }, MANTLE: { diff --git a/src/sdk/builders/dca-builder.ts b/src/sdk/builders/dca-builder.ts deleted file mode 100644 index cfc98250..00000000 --- a/src/sdk/builders/dca-builder.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { DCAService } from '@services/dca/dca-service'; -import { IFetchService } from '@services/fetch'; -import { IPermit2Service } from '@services/permit2'; -import { IPriceService } from '@services/prices'; -import { IProviderService } from '@services/providers'; -import { IQuoteService } from '@services/quotes'; - -export type BuildDCAParams = { customAPIUrl?: string }; -type Dependencies = { - providerService: IProviderService; - permit2Service: IPermit2Service; - quoteService: IQuoteService; - fetchService: IFetchService; - priceService: IPriceService; -}; -export function buildDCAService( - params: BuildDCAParams | undefined, - { providerService, permit2Service, quoteService, fetchService, priceService }: Dependencies -) { - return new DCAService( - params?.customAPIUrl ?? 'https://api.balmy.xyz', - providerService, - permit2Service, - quoteService, - fetchService, - priceService - ); -} diff --git a/src/sdk/builders/earn-builder.ts b/src/sdk/builders/earn-builder.ts deleted file mode 100644 index dec44229..00000000 --- a/src/sdk/builders/earn-builder.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { IAllowanceService } from '@services/allowances'; -import { IBalanceService } from '@services/balances'; -import { EarnService } from '@services/earn/earn-service'; -import { IFetchService } from '@services/fetch'; -import { IPermit2Service } from '@services/permit2'; -import { IProviderService } from '@services/providers'; -import { IQuoteService } from '@services/quotes'; - -export type BuildEarnParams = { customAPIUrl?: string }; -type Dependencies = { - permit2Service: IPermit2Service; - quoteService: IQuoteService; - providerService: IProviderService; - allowanceService: IAllowanceService; - fetchService: IFetchService; - balanceService: IBalanceService; -}; -export function buildEarnService( - params: BuildEarnParams | undefined, - { permit2Service, quoteService, providerService, allowanceService, fetchService, balanceService }: Dependencies -) { - return new EarnService( - params?.customAPIUrl ?? 'https://api.balmy.xyz', - permit2Service, - quoteService, - providerService, - allowanceService, - fetchService, - balanceService - ); -} diff --git a/src/sdk/builders/permit2-builder.ts b/src/sdk/builders/permit2-builder.ts deleted file mode 100644 index eae2cbf8..00000000 --- a/src/sdk/builders/permit2-builder.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { IGasService } from '@services/gas'; -import { Permit2Service } from '@services/permit2/permit2-service'; -import { IProviderService } from '@services/providers'; -import { IQuoteService } from '@services/quotes'; - -export function buildPermit2Service(quoteService: IQuoteService, providerService: IProviderService, gasService: IGasService) { - return new Permit2Service(providerService, quoteService, gasService); -} diff --git a/src/sdk/sdk-builder.ts b/src/sdk/sdk-builder.ts index c547a7e6..20117241 100644 --- a/src/sdk/sdk-builder.ts +++ b/src/sdk/sdk-builder.ts @@ -8,10 +8,7 @@ import { buildBalanceService, BuildBalancesParams } from './builders/balance-bui import { buildAllowanceService, BuildAllowanceParams } from './builders/allowance-builder'; import { ISDK } from './types'; import { BuildPriceParams, buildPriceService } from './builders/price-builder'; -import { buildPermit2Service } from './builders/permit2-builder'; -import { BuildDCAParams, buildDCAService } from './builders/dca-builder'; import { BuildBlocksParams, buildBlocksService } from './builders/blocks-builder'; -import { BuildEarnParams, buildEarnService } from './builders/earn-builder'; export function buildSDK( params?: Params @@ -26,16 +23,6 @@ export function buildSDK( const metadataService = buildMetadataService(params?.metadata, fetchService, providerService); const priceService = buildPriceService(params?.price, fetchService); const quoteService = buildQuoteService(params?.quotes, providerService, fetchService, gasService as any, metadataService as any, priceService); - const permit2Service = buildPermit2Service(quoteService, providerService, gasService as any); - const dcaService = buildDCAService(params?.dca, { providerService, permit2Service, quoteService, fetchService, priceService }); - const earnService = buildEarnService(params?.earn, { - permit2Service, - quoteService, - providerService, - allowanceService, - fetchService, - balanceService, - }); return { providerService, @@ -47,9 +34,6 @@ export function buildSDK( priceService, quoteService, logsService, - permit2Service, - dcaService, - earnService, blocksService, }; } @@ -60,8 +44,6 @@ export type BuildParams = { balances?: BuildBalancesParams; allowances?: BuildAllowanceParams; gas?: BuildGasParams; - dca?: BuildDCAParams; - earn?: BuildEarnParams; metadata?: BuildMetadataParams; price?: BuildPriceParams; quotes?: BuildQuoteParams; diff --git a/src/sdk/types.ts b/src/sdk/types.ts index 1e3417bf..78688963 100644 --- a/src/sdk/types.ts +++ b/src/sdk/types.ts @@ -9,10 +9,7 @@ import { IMetadataService } from '@services/metadata/types'; import { CalculateMetadataFromSourceParams } from './builders/metadata-builder'; import { CalculateGasValuesFromSourceParams } from './builders/gas-builder'; import { ILogsService } from '@services/logs'; -import { IPermit2Service } from '@services/permit2'; -import { IDCAService } from '@services/dca'; import { IBlocksService } from '@services/blocks'; -import { IEarnService } from '@services/earn'; export type ISDK< TokenMetadata extends object = CalculateMetadataFromSourceParams, @@ -27,8 +24,5 @@ export type ISDK< priceService: IPriceService; logsService: ILogsService; metadataService: IMetadataService; - permit2Service: IPermit2Service; - dcaService: IDCAService; - earnService: IEarnService; blocksService: IBlocksService; }; diff --git a/src/services/balances/balance-sources/rpc-balance-source.ts b/src/services/balances/balance-sources/rpc-balance-source.ts index e36190e6..4da4f93d 100644 --- a/src/services/balances/balance-sources/rpc-balance-source.ts +++ b/src/services/balances/balance-sources/rpc-balance-source.ts @@ -1,4 +1,4 @@ -import { Hex, parseAbi, Address as ViemAddress } from 'viem'; +import { parseAbi, Address as ViemAddress } from 'viem'; import { Address, ChainId, TimeString, TokenAddress } from '@types'; import { BalanceInput, IBalanceSource } from '../types'; import { IProviderService } from '@services/providers/types'; @@ -51,62 +51,31 @@ export class RPCBalanceSource implements IBalanceSource { tokens: Omit[], config?: { timeout?: TimeString } ): Promise>> { - const accountsToFetchNativeToken: Address[] = []; - const nonNativeTokens: Omit[] = []; - - for (const { account, token } of tokens) { - if (isSameAddress(token, Addresses.NATIVE_TOKEN)) { - accountsToFetchNativeToken.push(account); - } else { - nonNativeTokens.push({ account, token }); - } - } - - const erc20Promise = - Object.keys(nonNativeTokens).length > 0 - ? this.fetchERC20BalancesInChain(chainId, nonNativeTokens, config) - : Promise.resolve>>({}); - - const nativePromise = - accountsToFetchNativeToken.length > 0 - ? this.fetchNativeBalancesInChain(chainId, accountsToFetchNativeToken, config) - : Promise.resolve>({}); + if (tokens.length === 0) return {}; + + const contracts = tokens.map(({ account, token }) => + isSameAddress(token, Addresses.NATIVE_TOKEN) + ? { + abi: MULTICALL_ABI, + functionName: 'getEthBalance' as const, + args: [account], + address: MULTICALL_CONTRACT.address(chainId), + } + : { + address: token as ViemAddress, + abi: ERC20_ABI, + functionName: 'balanceOf' as const, + args: [account], + } + ); - const [erc20Result, nativeResult] = await Promise.all([erc20Promise, nativePromise]); + const multicallResults = await this.providerService.getViemPublicClient({ chainId }).multicall({ + contracts, + multicallAddress: MULTICALL_CONTRACT.address(chainId), + batchSize: this.config?.batching?.maxSizeInBytes ?? 0, + }); const result: Record> = {}; - - for (const { account, token } of tokens) { - const balance = isSameAddress(token, Addresses.NATIVE_TOKEN) ? nativeResult[account] : erc20Result[account]?.[token]; - - if (balance !== undefined) { - if (!(account in result)) result[account] = {}; - result[account][token] = balance; - } - } - - return result; - } - - private async fetchERC20BalancesInChain( - chainId: ChainId, - tokens: Omit[], - config?: { timeout?: TimeString } - ): Promise>> { - const contracts = tokens.map(({ account, token }) => ({ - address: token as ViemAddress, - abi: ERC20_ABI, - functionName: 'balanceOf', - args: [account], - })); - const multicallResults = contracts.length - ? await this.providerService.getViemPublicClient({ chainId }).multicall({ - contracts, - multicallAddress: MULTICALL_CONTRACT.address(chainId), - batchSize: this.config?.batching?.maxSizeInBytes ?? 0, - }) - : []; - const result: Record> = {}; for (let i = 0; i < tokens.length; i++) { const multicallResult = multicallResults[i]; if (multicallResult.status === 'failure') continue; @@ -116,38 +85,7 @@ export class RPCBalanceSource implements IBalanceSource { } return result; } - - private async fetchNativeBalancesInChain( - chainId: ChainId, - accounts: Address[], - config?: { timeout?: TimeString } - ): Promise> { - if (accounts.length === 0) return {}; - - let balances: Readonly; - - try { - // We are using deployless reads to perform a sort of multicall and fetch all native balances in one call - balances = await this.providerService.getViemPublicClient({ chainId }).readContract({ - code: BYTECODE, - abi: ABI, - functionName: 'getNativeBalances', - args: [accounts as ViemAddress[]], - blockTag: 'latest', - }); - } catch { - // Some chains don't support deployless reads, so we fallback to fetching each balance individually - balances = await Promise.all(accounts.map((account) => this.fetchNativeBalanceInChain(chainId, account))); - } - - return Object.fromEntries(accounts.map((account, i) => [account, balances[i]])); - } - - private fetchNativeBalanceInChain(chainId: ChainId, account: Address, config?: { timeout?: TimeString }) { - return this.providerService.getViemPublicClient({ chainId }).getBalance({ address: account as ViemAddress, blockTag: 'latest' }); - } } -const BYTECODE: Hex = - '0x608060405234801561001057600080fd5b506102ed806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80634c04bf9914610030575b600080fd5b61004361003e3660046101cf565b610059565b604051610050919061023e565b60405180910390f35b60608167ffffffffffffffff81111561009b577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156100c4578160200160208202803683370190505b50905060005b8281101561018d5783838281811061010b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020160208101906101209190610194565b73ffffffffffffffffffffffffffffffffffffffff1631828281518110610170577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60209081029190910101528061018581610282565b9150506100ca565b5092915050565b6000602082840312156101a5578081fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146101c8578182fd5b9392505050565b600080602083850312156101e1578081fd5b823567ffffffffffffffff808211156101f8578283fd5b818501915085601f83011261020b578283fd5b813581811115610219578384fd5b866020808302850101111561022c578384fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b818110156102765783518352928401929184019160010161025a565b50909695505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156102d9577f4e487b710000000000000000000000000000000000000000000000000000000081526011600452602481fd5b506001019056fea164736f6c6343000800000a'; -const ABI = parseAbi(['function getNativeBalances(address[] addresses) external view returns (uint256[] balances)']); +// The Multicall3 contract has this function that we can use to fetch all native balances in one call +const MULTICALL_ABI = parseAbi(['function getEthBalance(address addr) external view returns (uint256 balance)']); diff --git a/src/services/dca/config.ts b/src/services/dca/config.ts deleted file mode 100644 index d5a860eb..00000000 --- a/src/services/dca/config.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Chains } from '@chains'; -import { PERMIT2_ADAPTER_CONTRACT } from '@services/permit2/utils/config'; -import { Contract } from '@shared/contracts'; - -export const DCA_HUB_CONTRACT = Contract.with({ defaultAddress: '0xA5AdC5484f9997fBF7D405b9AA62A7d88883C345' }) - .and({ address: '0x8CC0Df843610cefF7f4AFa01100B6abf6756Bdf2', onChain: Chains.ROOTSTOCK.chainId }) - .build(); -export const DCA_PERMISSION_MANAGER_CONTRACT = Contract.with({ defaultAddress: '0x20bdAE1413659f47416f769a4B27044946bc9923' }) - .and({ address: '0x1EE410Fc840cC13C4e1b17DC6f93E245a918c19e', onChain: Chains.ROOTSTOCK.chainId }) - .build(); -export const COMPANION_CONTRACT = Contract.with({ defaultAddress: '0x6C615481E96806edBd9987B6E522A4Ea85d13659' }) - .and({ address: '0x5872E8D5Ec9Dbf67949FdD4B5e05707644D60876', onChain: Chains.ROOTSTOCK.chainId }) - .and({ address: '0x73376120621b243bC59c988cf172d23D5093e9F9', onChain: Chains.AVALANCHE.chainId }) - .build(); -export const COMPANION_SWAPPER_CONTRACT = PERMIT2_ADAPTER_CONTRACT; diff --git a/src/services/dca/dca-service.ts b/src/services/dca/dca-service.ts deleted file mode 100644 index 86f48468..00000000 --- a/src/services/dca/dca-service.ts +++ /dev/null @@ -1,1274 +0,0 @@ -import qs from 'qs'; -import { encodeFunctionData, Hex, Address as ViemAddress } from 'viem'; -import { Address, BigIntish, ChainId, TokenAddress, BuiltTransaction, TimeString, Timestamp } from '@types'; -import companionAbi from '@shared/abis/companion'; -import dcaHubAbi from '@shared/abis/dca-hub'; -import { SinglePermitParams, PermitData, IPermit2Service } from '@services/permit2'; -import { PERMIT2_CONTRACT } from '@services/permit2/utils/config'; -import { isSameAddress, toAmountsOfToken } from '@shared/utils'; -import { Addresses } from '@shared/constants'; -import { IQuoteService, QuoteRequest } from '@services/quotes'; -import { - CreateDCAPositionParams, - DCAActionSwapConfig, - DCAPermissionPermit, - DCASwapInterval, - SupportedDCAToken, - IDCAService, - IncreaseDCAPositionParams, - MigrateDCAPositionParams, - PairInChain, - ReduceDCAPositionParams, - ReduceToBuyDCAPositionParams, - SupportedPair, - SwapIntervalData, - TerminateDCAPositionParams, - TokenVariant, - TokenVariantPair, - WithdrawDCAPositionParams, - PositionId, - PlatformMessage, - PositionSummary, - DCAPermission, - TransferredAction, - PermissionsModifiedAction, - DCAPositionAction, - TokenVariantId, - ActionTypeAction, -} from './types'; -import { COMPANION_CONTRACT, COMPANION_SWAPPER_CONTRACT, DCA_HUB_CONTRACT, DCA_PERMISSION_MANAGER_CONTRACT } from './config'; -import ERC721_ABI from '@shared/abis/erc721'; -import { IFetchService } from '@services/fetch'; -import { IPriceService, PriceResult } from '@services/prices'; -import { IProviderService } from '..'; -import { MULTICALL_CONTRACT } from '@services/providers/utils'; -import { Chains } from '@chains'; - -export class DCAService implements IDCAService { - constructor( - private readonly apiUrl: string, - private readonly providerService: IProviderService, - private readonly permit2Service: IPermit2Service, - private readonly quoteService: IQuoteService, - private readonly fetchService: IFetchService, - private readonly priceService: IPriceService - ) {} - - getAllowanceTarget({ - chainId, - from, - depositWith, - usePermit2, - }: { - chainId: ChainId; - from: TokenAddress; - depositWith: TokenAddress; - usePermit2?: boolean; - }): Address { - if (usePermit2) { - return PERMIT2_CONTRACT.address(chainId); - } else if (isSameAddress(from, depositWith)) { - return DCA_HUB_CONTRACT.address(chainId); - } else { - return COMPANION_CONTRACT.address(chainId); - } - } - - preparePermitData(args: SinglePermitParams): Promise { - return this.permit2Service.preparePermitData({ ...args, spender: COMPANION_CONTRACT.address(args.chainId) }); - } - - async buildCreatePositionTx({ - chainId, - from, - to, - swapInterval, - amountOfSwaps, - owner, - permissions, - deposit, - }: CreateDCAPositionParams): Promise { - let depositInfo: { token: Address; amount: bigint; value: bigint }; - if ('token' in deposit) { - const amount = BigInt(deposit.amount); - depositInfo = { token: deposit.token, amount, value: isSameAddress(deposit.token, Addresses.NATIVE_TOKEN) ? amount : 0n }; - } else { - depositInfo = { token: deposit.permitData.token, amount: BigInt(deposit.permitData.amount), value: 0n }; - } - - const needsSwap = !isSameAddress(depositInfo.token, from.variantId); - if ('token' in deposit && !needsSwap) { - // If don't need to use Permit2, then just call the hub - return { - to: DCA_HUB_CONTRACT.address(chainId), - data: encodeFunctionData({ - abi: dcaHubAbi, - functionName: 'deposit', - args: [ - from.variantId as ViemAddress, - to.variantId as ViemAddress, - depositInfo.amount, - amountOfSwaps, - swapInterval, - owner as ViemAddress, - permissions.map(({ operator, permissions }) => ({ - operator: operator as ViemAddress, - permissions: permissions.map(mapPermission), - })), - ], - }), - }; - } - - // If we get to this point, then we'll use the Companion for the deposit - const calls: Call[] = []; - - // Handle take from caller (if necessary) - const recipient = needsSwap ? COMPANION_SWAPPER_CONTRACT.address(chainId) : COMPANION_CONTRACT.address(chainId); - if ('permitData' in deposit) { - calls.push(buildTakeFromCallerWithPermit(deposit.permitData, deposit.signature, recipient)); - } else if (!isSameAddress(depositInfo.token, Addresses.NATIVE_TOKEN)) { - calls.push(buildTakeFromCaller(depositInfo.token, depositInfo.amount, recipient)); - } - - // Handle swap - if (needsSwap) { - const { swapData } = await this.getSwapData({ - request: { - chainId, - sellToken: depositInfo.token, - buyToken: from.variantId, - order: { type: 'sell', sellAmount: depositInfo.amount }, - }, - leftoverRecipient: owner, - swapConfig: deposit?.swapConfig, - }); - calls.push(swapData); - } - - // Handle deposit - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'depositWithBalanceOnContract', - args: [ - DCA_HUB_CONTRACT.address(chainId), - from.variantId as ViemAddress, - to.variantId as ViemAddress, - amountOfSwaps, - swapInterval, - owner as ViemAddress, - permissions.map(({ operator, permissions }) => ({ - operator: operator as ViemAddress, - permissions: permissions.map(mapPermission), - })), - '0x', - ], - }) - ); - - // Build multicall and return tx - return buildCompanionMulticall({ chainId, calls, value: depositInfo.value }); - } - - async buildIncreasePositionTx({ - chainId, - positionId, - increase, - amountOfSwaps, - permissionPermit, - dcaHub, - }: IncreaseDCAPositionParams): Promise { - const hubAddress = dcaHub ?? DCA_HUB_CONTRACT.address(chainId); - let increaseInfo: { token: Address; amount: bigint; value: bigint }; - if (!increase) { - increaseInfo = { token: Addresses.ZERO_ADDRESS, amount: 0n, value: 0n }; - } else if ('token' in increase) { - const amount = BigInt(increase.amount); - increaseInfo = { token: increase.token, amount, value: isSameAddress(increase.token, Addresses.NATIVE_TOKEN) ? amount : 0n }; - } else { - increaseInfo = { token: increase.permitData.token, amount: BigInt(increase.permitData.amount), value: 0n }; - } - - const bigIntPositionId = BigInt(positionId); - const [positionOwner, position] = await this.providerService.getViemPublicClient({ chainId }).multicall({ - contracts: [ - { abi: ERC721_ABI, address: DCA_PERMISSION_MANAGER_CONTRACT.address(chainId), functionName: 'ownerOf', args: [bigIntPositionId] }, - { abi: dcaHubAbi, address: hubAddress as ViemAddress, functionName: 'userPosition', args: [bigIntPositionId] }, - ], - allowFailure: false, - multicallAddress: MULTICALL_CONTRACT.address(chainId), - batchSize: 0, - }); - - const needsSwap = !isSameAddress(increaseInfo.token, position.from); - const callHubDirectly = !increase || increaseInfo.amount === 0n || amountOfSwaps === 0 || ('token' in increase && !needsSwap); - - if (callHubDirectly) { - // If don't need to use Permit2, then just call the hub - return { - to: hubAddress, - data: encodeFunctionData({ - abi: dcaHubAbi, - functionName: 'increasePosition', - args: [BigInt(positionId), BigInt(increaseInfo.amount), amountOfSwaps], - }), - }; - } - - // If we get to this point, then we'll use the Companion for the increase - const calls: Call[] = []; - - const recipient = needsSwap ? COMPANION_SWAPPER_CONTRACT.address(chainId) : COMPANION_CONTRACT.address(chainId); - if ('permitData' in increase!) { - // Handle take from caller (if necessary) - calls.push(buildTakeFromCallerWithPermit(increase.permitData, increase.signature, recipient)); - } else if (!isSameAddress(increaseInfo.token, Addresses.NATIVE_TOKEN)) { - calls.push(buildTakeFromCaller(increaseInfo.token, increaseInfo.amount, recipient)); - } - - if (needsSwap) { - const { swapData } = await this.getSwapData({ - request: { - chainId, - sellToken: increaseInfo.token, - buyToken: position.from, - order: { type: 'sell', sellAmount: increaseInfo.amount }, - }, - leftoverRecipient: positionOwner, - swapConfig: increase?.swapConfig, - }); - calls.push(swapData); - } - - // Handle permission permit - if (permissionPermit) { - calls.push(buildPermissionPermit(permissionPermit, hubAddress)); - } - - // Handle increase - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'increasePositionWithBalanceOnContract', - args: [hubAddress as ViemAddress, bigIntPositionId, amountOfSwaps], - }) - ); - - // Build multicall and return tx - return buildCompanionMulticall({ chainId, calls, value: increaseInfo?.value }); - } - - async buildReducePositionTx({ - chainId, - positionId, - amountOfSwaps, - reduce, - recipient, - permissionPermit, - dcaHub, - }: ReduceDCAPositionParams): Promise { - const hubAddress = dcaHub ?? DCA_HUB_CONTRACT.address(chainId); - const position = await this.getUserPosition(chainId, hubAddress, positionId); - const shouldConvert = reduce.convertTo && !isSameAddress(position.from, reduce.convertTo); - - if (!shouldConvert) { - // If don't need to convert anything, then just call the hub - return { - to: hubAddress, - data: encodeFunctionData({ - abi: dcaHubAbi, - functionName: 'reducePosition', - args: [BigInt(positionId), BigInt(reduce.amount), amountOfSwaps, recipient as ViemAddress], - }), - }; - } - - // If we get to this point, then we'll use the Companion for swap & transfer - const calls: Call[] = []; - - // Handle permission permit - if (permissionPermit) { - calls.push(buildPermissionPermit(permissionPermit, hubAddress)); - } - - // Handle reduce - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'reducePosition', - args: [hubAddress as ViemAddress, BigInt(positionId), BigInt(reduce.amount), amountOfSwaps, COMPANION_SWAPPER_CONTRACT.address(chainId)], - }) - ); - - // Handle swap - const outToken = reduce.convertTo!; - const { swapData } = await this.getSwapData({ - request: { - chainId, - sellToken: position.from, - buyToken: outToken, - order: { type: 'sell', sellAmount: reduce.amount }, - }, - leftoverRecipient: recipient, - swapConfig: reduce?.swapConfig, - }); - calls.push(swapData); - - // Handle transfer - calls.push(buildSendAllBalance(outToken, recipient)); - - // Build multicall and return tx - return buildCompanionMulticall({ chainId, calls }); - } - - async buildReduceToBuyPositionTx({ - chainId, - positionId, - amountOfSwaps, - reduce, - recipient, - permissionPermit, - dcaHub, - }: ReduceToBuyDCAPositionParams): Promise { - const hubAddress = dcaHub ?? DCA_HUB_CONTRACT.address(chainId); - const calls: Call[] = []; - - const position = await this.getUserPosition(chainId, hubAddress, positionId); - const shouldConvert = reduce.convertTo && !isSameAddress(position.from, reduce.convertTo); - if (amountOfSwaps === 0 || !shouldConvert) { - // In these two scenarios, we can use the normal reduce - const amount = - amountOfSwaps === 0 - ? position.remaining // Withdraw everything - : reduce.amountToBuy; // Withdraw the specified amount - return this.buildReducePositionTx({ - chainId, - positionId, - amountOfSwaps, - reduce: { amount, convertTo: reduce.convertTo, swapConfig: reduce.swapConfig }, - recipient, - permissionPermit, - dcaHub, - }); - } - - // Handle permission permit - if (permissionPermit) { - calls.push(buildPermissionPermit(permissionPermit, hubAddress)); - } - - // Calculate swap (we know we need to swap if we got to this point) - const outToken = reduce.convertTo!; - const { bestQuote: buyQuote, swapData } = await this.getSwapData({ - request: { - chainId, - sellToken: position.from, - buyToken: outToken, - order: { type: 'buy', buyAmount: reduce.amountToBuy }, - }, - leftoverRecipient: recipient, - swapConfig: reduce?.swapConfig, - }); - - // If we are asking for more than available, then fail - if (BigInt(buyQuote.maxSellAmount.amount) > position.remaining) { - throw new Error('Trying to withdraw more than available'); - } - - // Handle reduce - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'reducePosition', - args: [ - hubAddress as ViemAddress, - BigInt(positionId), - BigInt(buyQuote.maxSellAmount.amount), - amountOfSwaps, - COMPANION_SWAPPER_CONTRACT.address(chainId), - ], - }) - ); - - // Add swap to calls list (needs to go after reduce) - calls.push(swapData); - - // Handle transfer - calls.push(buildSendAllBalance(outToken, recipient)); - - // Build multicall and return tx - return buildCompanionMulticall({ chainId, calls }); - } - - async buildWithdrawPositionTx({ - chainId, - positionId, - withdraw, - recipient, - permissionPermit, - dcaHub, - }: WithdrawDCAPositionParams): Promise { - const hubAddress = dcaHub ?? DCA_HUB_CONTRACT.address(chainId); - const position = await this.getUserPosition(chainId, hubAddress, positionId); - const shouldConvert = withdraw.convertTo && !isSameAddress(position.to, withdraw.convertTo); - - if (!shouldConvert) { - // If don't need to convert anything, then just call the hub - return { - to: hubAddress, - data: encodeFunctionData({ - abi: dcaHubAbi, - functionName: 'withdrawSwapped', - args: [BigInt(positionId), recipient as ViemAddress], - }), - }; - } - - // If we get to this point, then we'll use the Companion for swap & transfer - const calls: Call[] = []; - - // Handle permission permit - if (permissionPermit) { - calls.push(buildPermissionPermit(permissionPermit, hubAddress)); - } - - // Handle withdraw - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'withdrawSwapped', - args: [hubAddress as ViemAddress, BigInt(positionId), COMPANION_SWAPPER_CONTRACT.address(chainId)], - }) - ); - - // Handle swap - const outToken = withdraw.convertTo!; - const { swapData } = await this.getSwapData({ - request: { - chainId, - sellToken: position.to, - buyToken: outToken, - order: { type: 'sell', sellAmount: position.swapped }, - }, - leftoverRecipient: recipient, - swapConfig: withdraw?.swapConfig, - }); - calls.push(swapData); - - // Handle transfer - calls.push(buildSendAllBalance(outToken, recipient)); - - // Build multicall and return tx - return buildCompanionMulticall({ chainId, calls }); - } - - async buildTerminatePositionTx({ - chainId, - positionId, - withdraw, - recipient, - permissionPermit, - dcaHub, - }: TerminateDCAPositionParams): Promise { - const hubAddress = dcaHub ?? DCA_HUB_CONTRACT.address(chainId); - const position = await this.getUserPosition(chainId, hubAddress, positionId); - const shouldConvertUnswapped = - position.remaining > 0 && !!withdraw.unswappedConvertTo && !isSameAddress(position.from, withdraw.unswappedConvertTo); - const shouldConvertSwapped = position.swapped > 0 && !!withdraw.swappedConvertTo && !isSameAddress(position.to, withdraw.swappedConvertTo); - - if (!shouldConvertUnswapped && !shouldConvertSwapped) { - // If don't need to convert anything, then just call the hub - return { - to: hubAddress, - data: encodeFunctionData({ - abi: dcaHubAbi, - functionName: 'terminate', - args: [BigInt(positionId), recipient as ViemAddress, recipient as ViemAddress], - }), - }; - } - - // If we get to this point, then we'll use the Companion for swap & transfer - const calls: Call[] = []; - - // Handle permission permit - if (permissionPermit) { - calls.push(buildPermissionPermit(permissionPermit, hubAddress)); - } - - // Handle terminate - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'terminate', - args: [ - hubAddress as ViemAddress, - BigInt(positionId), - shouldConvertUnswapped ? COMPANION_SWAPPER_CONTRACT.address(chainId) : (recipient as ViemAddress), - shouldConvertSwapped ? COMPANION_SWAPPER_CONTRACT.address(chainId) : (recipient as ViemAddress), - ], - }) - ); - - // Handle swaps - let unswappedPromise: Promise, swappedPromise: Promise; - if (shouldConvertUnswapped) { - const convertTo = withdraw.unswappedConvertTo!; - unswappedPromise = this.getSwapData({ - request: { - chainId, - sellToken: position.from, - buyToken: convertTo, - order: { type: 'sell', sellAmount: position.remaining }, - }, - leftoverRecipient: recipient, - swapConfig: withdraw.swapConfig, - }).then(({ swapData }) => - calls.push( - swapData, // Swap - buildSendAllBalance(convertTo, recipient) // Transfer - ) - ); - } else { - unswappedPromise = Promise.resolve(); - } - if (shouldConvertSwapped) { - const convertTo = withdraw.swappedConvertTo!; - swappedPromise = this.getSwapData({ - request: { - chainId, - sellToken: position.to, - buyToken: convertTo, - order: { type: 'sell', sellAmount: position.swapped }, - }, - leftoverRecipient: recipient, - swapConfig: withdraw.swapConfig, - }).then(({ swapData }) => - calls.push( - swapData, // Swap - buildSendAllBalance(convertTo, recipient) // Transfer - ) - ); - } else { - swappedPromise = Promise.resolve(); - } - await Promise.all([unswappedPromise, swappedPromise]); - - // Build multicall and return tx - return buildCompanionMulticall({ chainId, calls }); - } - - async buildMigratePositionTx({ - chainId, - sourceHub, - targetHub, - positionId, - migration, - permissionPermit, - }: MigrateDCAPositionParams): Promise { - const bigIntPositionId = BigInt(positionId); - const [positionOwner, position] = await this.providerService.getViemPublicClient({ chainId }).multicall({ - contracts: [ - { abi: ERC721_ABI, address: DCA_PERMISSION_MANAGER_CONTRACT.address(chainId), functionName: 'ownerOf', args: [bigIntPositionId] }, - { abi: dcaHubAbi, address: sourceHub as ViemAddress, functionName: 'userPosition', args: [bigIntPositionId] }, - ], - allowFailure: false, - multicallAddress: MULTICALL_CONTRACT.address(chainId), - batchSize: 0, - }); - - const newFrom = migration.newFrom?.variantId ?? position.from; - const shouldConvertUnswapped = migration.useFundsFrom !== 'swapped' && position.remaining > 0 && !isSameAddress(position.from, newFrom); - const shouldConvertSwapped = migration.useFundsFrom !== 'unswapped' && position.swapped > 0 && !isSameAddress(position.to, newFrom); - const calls: Call[] = []; - - // Handle permission permit - if (permissionPermit) { - calls.push(buildPermissionPermit(permissionPermit, sourceHub)); - } - - // Handle terminate - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'terminate', - args: [ - sourceHub as ViemAddress, - bigIntPositionId, - shouldConvertUnswapped - ? COMPANION_SWAPPER_CONTRACT.address(chainId) - : migration.useFundsFrom !== 'swapped' - ? COMPANION_CONTRACT.address(chainId) - : (migration.sendUnusedFundsTo as ViemAddress), - shouldConvertSwapped - ? COMPANION_SWAPPER_CONTRACT.address(chainId) - : migration.useFundsFrom !== 'unswapped' - ? COMPANION_CONTRACT.address(chainId) - : (migration.sendUnusedFundsTo as ViemAddress), - ], - }) - ); - - // Handle swaps - let unswappedPromise: Promise, swappedPromise: Promise; - if (shouldConvertUnswapped) { - unswappedPromise = this.getSwapData({ - request: { - chainId, - sellToken: position.from, - buyToken: newFrom, - order: { type: 'sell', sellAmount: position.remaining }, - }, - leftoverRecipient: positionOwner, - swapConfig: migration?.swapConfig, - }).then(({ swapData }) => calls.push(swapData)); - } else { - unswappedPromise = Promise.resolve(); - } - if (shouldConvertSwapped) { - swappedPromise = this.getSwapData({ - request: { - chainId, - sellToken: position.to, - buyToken: newFrom, - order: { type: 'sell', sellAmount: position.swapped }, - }, - leftoverRecipient: positionOwner, - swapConfig: migration?.swapConfig, - }).then(({ swapData }) => calls.push(swapData)); - } else { - swappedPromise = Promise.resolve(); - } - - await Promise.all([unswappedPromise, swappedPromise]); - - // Handle re-deposit - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'depositWithBalanceOnContract', - args: [ - targetHub as ViemAddress, - newFrom as ViemAddress, - (migration.newTo?.variantId ?? position.to) as ViemAddress, - position.swapsLeft, - position.swapInterval, - positionOwner, - [], - '0x', - ], - }) - ); - - // Build multicall and return tx - return buildCompanionMulticall({ chainId, calls }); - } - - async getSupportedPairs(args?: { chains?: ChainId[]; config?: { timeout?: TimeString } }) { - const params = qs.stringify({ chains: args?.chains }, { arrayFormat: 'comma', skipNulls: true }); - const url = `${this.apiUrl}/v2/dca/pairs/supported?${params}`; - const response = await this.fetchService.fetch(url, { timeout: args?.config?.timeout }); - const body: SupportedPairsResponse = await response.json(); - const result: Record }> = {}; - for (const chainId in body.pairsByNetwork) { - const { pairs, tokens } = body.pairsByNetwork[chainId]; - result[Number(chainId)] = { - pairs: pairs.map((pair) => buildPair(Number(chainId), pair, tokens)), - tokens, - }; - } - return result; - } - - async getPositionsByAccount({ - accounts, - chains, - includeHistory, - config, - }: { - accounts: Address[]; - chains?: ChainId[]; - includeHistory?: boolean; - config?: { timeout?: TimeString }; - }) { - const params = qs.stringify({ users: accounts, chains, includeHistory }, { arrayFormat: 'comma', skipNulls: true }); - return this.fetchPositions(params, config?.timeout); - } - - async getPositionsById({ - ids, - includeHistory, - config, - }: { - ids: { chainId: ChainId; hub: Address; positionId: number }[]; - includeHistory?: boolean; - config?: { timeout: TimeString }; - }): Promise> { - const encodedIds = ids.map(({ chainId, hub, positionId }) => `${chainId}-${hub}-${positionId}`); - const params = qs.stringify({ ids: encodedIds, includeHistory }, { arrayFormat: 'comma', skipNulls: true }); - return this.fetchPositions(params, config?.timeout); - } - - async getPairSwaps({ - chainId, - variantTokenA, - variantTokenB, - config, - }: { - chainId: ChainId; - variantTokenA: TokenVariantId; - variantTokenB: TokenVariantId; - config?: { timeout: TimeString }; - }) { - const url = `${this.apiUrl}/v2/dca/pairs/${chainId}-${variantTokenA}-${variantTokenB}/swaps`; - const response = await this.fetchService.fetch(url, { timeout: config?.timeout }); - const { tokenA, tokenB, swaps }: PairSwapsResponse = await response.json(); - return { - tokenA, - tokenB, - swaps: swaps.map((swap) => ({ - ...swap, - ratioAToB: toBigInt(swap.ratioAToB), - ratioBToA: toBigInt(swap.ratioBToA), - ratioAToBWithFee: toBigInt(swap.ratioAToBWithFee), - ratioBToAWithFee: toBigInt(swap.ratioBToAWithFee), - intervalsInSwap: swap.intervalsInSwap.map(({ seconds }) => seconds), - })), - }; - } - - private async fetchPositions(params: string, timeout: TimeString | undefined) { - const url = `${this.apiUrl}/v2/dca/positions?${params}`; - const response = await this.fetchService.fetch(url, { timeout }); - const body: PositionsResponse = await response.json(); - const tokensToFetch = calculateMissingPrices(body); - const prices = - tokensToFetch.length === 0 ? {} : await this.priceService.getBulkHistoricalPrices({ tokens: tokensToFetch, config: { timeout: timeout } }); - - const result: Record = {}; - for (const chainId in body.positionsByNetwork) { - const { positions, tokens } = body.positionsByNetwork[chainId]; - result[Number(chainId)] = positions.map((position) => buildPosition(position, tokens, prices[Number(chainId)] ?? {})); - } - return result; - } - - private async getSwapData({ - request, - leftoverRecipient, - swapConfig, - }: { - request: Pick; - leftoverRecipient: Address; - swapConfig: DCAActionSwapConfig | undefined; - }) { - const txValidFor = swapConfig?.txValidFor ?? '1w'; - const bestQuote = await this.quoteService.getBestQuote({ - request: { - ...request, - slippagePercentage: swapConfig?.slippagePercentage ?? 0.3, - takerAddress: COMPANION_SWAPPER_CONTRACT.address(request.chainId), - recipient: COMPANION_SWAPPER_CONTRACT.address(request.chainId), - txValidFor, - filters: { includeSources: ['balmy'] }, // TODO: allow more sources and simulate to find the best one - sourceConfig: { custom: { balmy: { leftoverRecipient } } }, - }, - config: { - timeout: '5s', - }, - }); - const { [bestQuote.source.id]: tx } = await this.quoteService.buildAllTxs({ - config: { timeout: '5s' }, - quotes: { [bestQuote.source.id]: bestQuote }, - sourceConfig: { custom: { balmy: { leftoverRecipient } } }, - }); - - const allowanceTargets = isSameAddress(bestQuote.source.allowanceTarget, Addresses.ZERO_ADDRESS) - ? [] - : [{ token: bestQuote.sellToken.address, target: bestQuote.source.allowanceTarget }]; - - // Swap adapter uses the zero address as the native token - const tokenOutDistribution = isSameAddress(bestQuote.buyToken.address, Addresses.NATIVE_TOKEN) - ? Addresses.ZERO_ADDRESS - : bestQuote.buyToken.address; - - const arbitraryCall = this.permit2Service.arbitrary.buildArbitraryCallWithoutPermit({ - allowanceTargets, - calls: [{ to: tx.to, data: tx.data, value: tx.value ?? 0n }], - distribution: { [tokenOutDistribution]: [{ recipient: COMPANION_CONTRACT.address(request.chainId), shareBps: 0 }] }, - txValidFor, - chainId: request.chainId, - }); - - const swapData = encodeFunctionData({ - abi: companionAbi, - functionName: 'runSwap', - args: [ - Addresses.ZERO_ADDRESS, // No need to set it because we are already transferring the funds to the swapper - tx.value ?? 0n, - arbitraryCall.data as Hex, - bestQuote.buyToken.address as ViemAddress, - ], - }); - - return { bestQuote, swapData }; - } - - private async getUserPosition( - chainId: ChainId, - hubAddress: Address, - positionId: BigIntish - ): Promise<{ from: TokenAddress; to: TokenAddress; remaining: bigint; swapped: bigint }> { - const [position] = await this.providerService.getViemPublicClient({ chainId }).multicall({ - contracts: [{ abi: dcaHubAbi, address: hubAddress as ViemAddress, functionName: 'userPosition', args: [BigInt(positionId)] }], - allowFailure: false, - multicallAddress: MULTICALL_CONTRACT.address(chainId), - batchSize: 0, - }); - return { ...position, remaining: BigInt(position.remaining), swapped: BigInt(position.swapped) }; - } -} - -function buildTakeFromCallerWithPermit( - { token, amount, nonce, deadline }: PermitData['permitData'], - signature: string, - recipient: Address -): Hex { - return encodeFunctionData({ - abi: companionAbi, - functionName: 'permitTakeFromCaller', - args: [token as ViemAddress, BigInt(amount), BigInt(nonce), BigInt(deadline), signature as Hex, recipient as ViemAddress], - }); -} - -function buildTakeFromCaller(token: TokenAddress, amount: BigIntish, recipient: Address): Hex { - return encodeFunctionData({ - abi: companionAbi, - functionName: 'takeFromCaller', - args: [token as ViemAddress, BigInt(amount), recipient as ViemAddress], - }); -} - -function buildPermissionPermit(permit: DCAPermissionPermit, hub: Address): Hex { - const permissionManager = PERMISSION_MANAGER_FOR_HUB[hub.toLowerCase() as Lowercase
]; - return encodeFunctionData({ - abi: companionAbi, - functionName: 'permissionPermit', - args: [ - permissionManager as ViemAddress, - permit.permissions.map(({ operator, permissions }) => ({ - operator: operator as ViemAddress, - permissions: permissions.map(mapPermission), - })), - BigInt(permit.tokenId), - BigInt(permit.deadline), - parseInt(permit.v.toString()), - permit.r as Hex, - permit.s as Hex, - ], - }); -} - -function mapPermission(permission: DCAPermission) { - switch (permission) { - case DCAPermission.INCREASE: - return 0; - case DCAPermission.REDUCE: - return 1; - case DCAPermission.WITHDRAW: - return 2; - case DCAPermission.TERMINATE: - return 3; - } -} - -function buildSendAllBalance(token: TokenAddress, recipient: Address): Hex { - return encodeFunctionData({ - abi: companionAbi, - functionName: 'sendBalanceOnContractToRecipient', - args: [token as ViemAddress, recipient as ViemAddress], - }); -} - -async function buildCompanionMulticall({ chainId, calls, value }: { chainId: ChainId; calls: Call[]; value?: bigint }) { - const data = encodeFunctionData({ - abi: companionAbi, - functionName: 'multicall', - args: [calls], - }); - return { to: COMPANION_CONTRACT.address(chainId), data, value }; -} - -type Call = Hex; - -function buildPair(chainId: ChainId, pair: SupportedPairWithIntervals, tokens: Record): SupportedPair { - const tokenA = tokens[pair.tokenA]; - const tokenB = tokens[pair.tokenB]; - return { - chainId: Number(chainId), - ...pair, - swapIntervals: buildSwapIntervals(pair.swapIntervals, tokenA, tokenB), - }; -} - -function buildSwapIntervals( - swapIntervals: Record, - tokenA: TokenData, - tokenB: TokenData -): Record { - const tokenAVariantIds = tokenA.variants.map(({ id }) => id); - const tokenBVariantIds = tokenB.variants.map(({ id }) => id); - const variantCombinations = tokenAVariantIds.flatMap((tokenAVariantId) => - tokenBVariantIds.map((tokenBVariantId) => `${tokenAVariantId}-${tokenBVariantId}`) - ); - - const result: Record = {}; - const allIntervals = Object.keys(DCASwapInterval).slice(0, 8); - for (const seconds of allIntervals) { - const intervalName = DCASwapInterval[Number(seconds)]; - const nextSwapAvailableAt: Record = {}; - const isStale: Record = {}; - for (const combination of variantCombinations) { - isStale[combination] = swapIntervals[intervalName]?.stale?.includes(combination) ?? false; - nextSwapAvailableAt[combination] = swapIntervals[intervalName]?.nextSwapBlockedUntil[combination] ?? 0; - } - result[intervalName] = { seconds: Number(seconds), nextSwapAvailableAt, isStale }; - } - - return result; -} - -function buildPosition( - position: PositionSummaryResponse, - tokens: Record, - prices: Record> -): PositionSummary { - const { variants: fromVariants, ...fromToken } = tokens[position.from.address]; - const { variants: toVariants, ...toToken } = tokens[position.to.address]; - const fromVariant = fromVariants.find(({ id }) => id == position.from.variant.id) ?? position.from.variant; - const toVariant = toVariants.find(({ id }) => id === position.to.variant.id) ?? position.to.variant; - const [chainId, hub, tokenId] = position.id.split('-'); - return { - chainId: Number(chainId), - hub, - pair: { - pairId: toPairId(position.from.address, position.to.address), - variantPairId: toPairId(position.from.variant.id, position.to.variant.id), - }, - tokenId: BigInt(tokenId), - ...position, - from: { - ...position.from, - ...fromToken, - variant: fromVariant, - }, - to: { - ...position.to, - ...toToken, - variant: toVariant, - }, - swapInterval: position.swapInterval.seconds, - rate: toAmountsOfToken({ ...fromToken, amount: position.rate }), - funds: { - swapped: toAmountsOfToken({ ...toToken, amount: position.funds.swapped }), - remaining: toAmountsOfToken({ ...fromToken, amount: position.funds.remaining }), - toWithdraw: toAmountsOfToken({ ...toToken, amount: position.funds.toWithdraw }), - }, - generatedByYield: position.yield - ? { - swapped: position.yield.swapped === undefined ? undefined : toAmountsOfToken({ ...toToken, amount: position.yield.swapped }), - remaining: position.yield.remaining === undefined ? undefined : toAmountsOfToken({ ...fromToken, amount: position.yield.remaining }), - toWithdraw: position.yield.toWithdraw === undefined ? undefined : toAmountsOfToken({ ...toToken, amount: position.yield.toWithdraw }), - } - : undefined, - history: position.history?.map((action) => mapAction(action, position, prices)) ?? [], - }; -} - -function toPairId(address1: string, address2: string): `${Address}-${Address}` { - const lower1 = address1.toLowerCase(); - const lower2 = address2.toLowerCase(); - const [tokenA, tokenB] = lower1 < lower2 ? [lower1, lower2] : [lower2, lower1]; - return `${tokenA}-${tokenB}`; -} - -function mapAction( - action: DCAPositionActionResponse, - position: PositionSummaryResponse, - prices: Record> -): DCAPositionAction { - switch (action.action) { - case ActionTypeAction.CREATED: - return { - ...action, - fromPrice: action.fromPrice ?? prices[position.from.address]?.[action.tx.timestamp]?.price, - rate: toBigInt(action.rate), - tx: mapActionTx(action.tx), - }; - case ActionTypeAction.MODIFIED: - return { - ...action, - fromPrice: action.fromPrice ?? prices[position.from.address]?.[action.tx.timestamp]?.price, - rate: toBigInt(action.rate), - oldRate: toBigInt(action.oldRate), - tx: mapActionTx(action.tx), - }; - case ActionTypeAction.WITHDRAWN: - return { - ...action, - toPrice: action.toPrice ?? prices[position.to.address]?.[action.tx.timestamp]?.price, - withdrawn: toBigInt(action.withdrawn), - generatedByYield: action.yield && { withdrawn: toBigInt(action.yield.withdrawn) }, - tx: mapActionTx(action.tx), - }; - case ActionTypeAction.TERMINATED: - return { - ...action, - fromPrice: action.fromPrice ?? prices[position.from.address]?.[action.tx.timestamp]?.price, - toPrice: action.toPrice ?? prices[position.to.address]?.[action.tx.timestamp]?.price, - withdrawnRemaining: toBigInt(action.withdrawnRemaining), - withdrawnSwapped: toBigInt(action.withdrawnSwapped), - generatedByYield: action.yield && { - withdrawnRemaining: toBigInt(action.yield.withdrawnRemaining), - withdrawnSwapped: toBigInt(action.yield.withdrawnSwapped), - }, - tx: mapActionTx(action.tx), - }; - case ActionTypeAction.SWAPPED: - return { - ...action, - tokenA: { - address: action.tokenA.address, - price: action.tokenA.price ?? prices[action.tokenA.address]?.[action.tx.timestamp]?.price, - }, - tokenB: { - address: action.tokenB.address, - price: action.tokenB.price ?? prices[action.tokenB.address]?.[action.tx.timestamp]?.price, - }, - rate: toBigInt(action.rate), - swapped: toBigInt(action.swapped), - ratioAToB: toBigInt(action.ratioAToB), - ratioBToA: toBigInt(action.ratioBToA), - ratioAToBWithFee: toBigInt(action.ratioAToBWithFee), - ratioBToAWithFee: toBigInt(action.ratioBToAWithFee), - generatedByYield: action.yield && { rate: toBigInt(action.yield.rate) }, - tx: mapActionTx(action.tx), - }; - case ActionTypeAction.TRANSFERRED: - case ActionTypeAction.MODIFIED_PERMISSIONS: - return { ...action, tx: mapActionTx(action.tx) }; - } -} - -function mapActionTx(tx: DCAPositionActionResponse['tx']): DCAPositionAction['tx'] { - return { - ...tx, - gasPrice: toBigInt(tx.gasPrice), - l1GasPrice: toBigInt(tx.l1GasPrice), - overhead: toBigInt(tx.overhead), - }; -} - -function calculateMissingPrices(response: PositionsResponse) { - const toFetch: { chainId: ChainId; token: TokenAddress; timestamp: Timestamp }[] = []; - for (const chainIdString in response.positionsByNetwork) { - const chainId = Number(chainIdString); - for (const position of response.positionsByNetwork[chainId].positions) { - for (const action of position.history ?? []) { - switch (action.action) { - case ActionTypeAction.CREATED: - case ActionTypeAction.MODIFIED: - if (!action.fromPrice) { - toFetch.push({ chainId, token: position.from.address, timestamp: action.tx.timestamp }); - } - break; - case ActionTypeAction.WITHDRAWN: - if (!action.toPrice) { - toFetch.push({ chainId, token: position.to.address, timestamp: action.tx.timestamp }); - } - break; - case ActionTypeAction.TERMINATED: - if (!action.fromPrice) { - toFetch.push({ chainId, token: position.from.address, timestamp: action.tx.timestamp }); - } - if (!action.toPrice) { - toFetch.push({ chainId, token: position.to.address, timestamp: action.tx.timestamp }); - } - break; - case ActionTypeAction.SWAPPED: { - if (!action.tokenA.price) { - toFetch.push({ chainId, token: action.tokenA.address, timestamp: action.tx.timestamp }); - } - if (!action.tokenB.price) { - toFetch.push({ chainId, token: action.tokenB.address, timestamp: action.tx.timestamp }); - } - } - } - } - } - } - return toFetch; -} - -type SupportedPairsResponse = { - pairsByNetwork: Record< - string, // chainId as string - { - pairs: SupportedPairWithIntervals[]; - tokens: Record; - } - >; -}; -type SupportedPairWithIntervals = { - id: PairInChain; - tokenA: TokenAddress; - tokenB: TokenAddress; - swapIntervals: Record; -}; - -type SwapIntervalDataResponse = { - seconds: number; - nextSwapBlockedUntil: Record; - stale: TokenVariantPair[]; -}; - -type TokenData = { - symbol: string; - decimals: number; - name: string; - variants: TokenVariant[]; - price?: number; -}; - -type PositionsResponse = { - positionsByNetwork: Record }>; -}; -type PositionSummaryResponse = { - id: PositionId; - createdAt: Timestamp; - from: PositionToken; - to: PositionToken; - swapInterval: { seconds: DCASwapInterval }; - owner: Address; - remainingSwaps: number; - totalSwaps: number; - executedSwaps: number; - isStale: boolean; - status: 'ongoing' | 'empty' | 'terminated' | 'finished'; - nextSwapAvailableAt: Timestamp; - permissions: Record; - rate: BigIntish; - funds: PositionFunds; - yield?: Partial; - platformMessages: PlatformMessage[]; - history?: DCAPositionActionResponse[]; -}; -type PositionFunds = { - swapped: BigIntish; - remaining: BigIntish; - toWithdraw: BigIntish; -}; -type PositionToken = { - address: TokenAddress; - variant: TokenVariant; -}; -type DCAPositionActionResponse = { tx: DCATransaction } & ActionTypeResponse; -type ActionTypeResponse = - | CreatedActionResponse - | ModifiedActionResponse - | WithdrawnActionResponse - | TerminatedActionResponse - | TransferredAction - | PermissionsModifiedAction - | SwappedActionResponse; -type CreatedActionResponse = { - action: ActionTypeAction.CREATED; - rate: BigIntish; - swaps: number; - owner: Address; - permissions: Record; - fromPrice?: number; -}; -type ModifiedActionResponse = { - action: ActionTypeAction.MODIFIED; - rate: BigIntish; - remainingSwaps: number; - oldRate: BigIntish; - oldRemainingSwaps: number; - fromPrice?: number; -}; -type WithdrawnActionResponse = { - action: ActionTypeAction.WITHDRAWN; - withdrawn: BigIntish; - yield?: { withdrawn: BigIntish }; - toPrice?: number; -}; -type TerminatedActionResponse = { - action: ActionTypeAction.TERMINATED; - withdrawnRemaining: BigIntish; - withdrawnSwapped: BigIntish; - yield?: { - withdrawnRemaining?: BigIntish; - withdrawnSwapped?: BigIntish; - }; - fromPrice?: number; - toPrice?: number; -}; -type SwappedActionResponse = { - action: ActionTypeAction.SWAPPED; - rate: BigIntish; - swapped: BigIntish; - ratioAToB: BigIntish; - ratioBToA: BigIntish; - ratioAToBWithFee: BigIntish; - ratioBToAWithFee: BigIntish; - yield?: { rate: BigIntish }; - tokenA: { address: TokenAddress; price?: number }; - tokenB: { address: TokenAddress; price?: number }; -}; -type DCATransaction = { - hash: string; - timestamp: Timestamp; - gasPrice?: BigIntish; - l1GasPrice?: BigIntish; - overhead?: BigIntish; -}; - -type PairSwapsResponse = { - tokenA: TokenInPair; - tokenB: TokenInPair; - swaps: { - executedAt: Timestamp; - ratioAToB: string; - ratioBToA: string; - ratioAToBWithFee: string; - ratioBToAWithFee: string; - intervalsInSwap: { seconds: DCASwapInterval }[]; - }[]; -}; -type TokenInPair = { - address: TokenAddress; - symbol: string; - decimals: number; - name: string; - price?: number; - variant: TokenVariant; -}; - -function toBigInt(text: T): T extends BigIntish ? bigint : undefined { - return (text === undefined ? undefined : BigInt(text)) as T extends BigIntish ? bigint : undefined; -} - -const PERMISSION_MANAGER_FOR_HUB: Record, Address> = { - // Yield - '0xa5adc5484f9997fbf7d405b9aa62a7d88883c345': '0x20bdAE1413659f47416f769a4B27044946bc9923', - // Stable - '0x059d306a25c4ce8d7437d25743a8b94520536bd5': '0x6f54391fe0386d506b51d69deeb8b04e0544e088', - // Vuln - '0x230c63702d1b5034461ab2ca889a30e343d81349': '0xb4edfb45446c6a207643ea846bfa42021ce5ae11', - // Beta - '0x24f85583faa9f8bd0b8aa7b1d1f4f53f0f450038': '0x09AdE44D2E60fCa2270fF32Af5a189f40D29837b', - // Yield (RSK) - [DCA_HUB_CONTRACT.address(Chains.ROOTSTOCK.chainId)]: DCA_PERMISSION_MANAGER_CONTRACT.address(Chains.ROOTSTOCK.chainId), -}; diff --git a/src/services/dca/index.ts b/src/services/dca/index.ts deleted file mode 100644 index 87337315..00000000 --- a/src/services/dca/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -export { - IDCAService, - DCAPermission, - DCASwapInterval, - DCAPermissionSet, - CreateDCAPositionParams, - IncreaseDCAPositionParams, - ReduceDCAPositionParams, - ReduceToBuyDCAPositionParams, - WithdrawDCAPositionParams, - TerminateDCAPositionParams, - DCAActionSwapConfig, - DCAPermissionPermit, - AddFunds, - SupportedPair, - PairInChain, - SwapIntervalData, - TokenVariantPair, - SupportedDCAToken, - TokenVariant, - TokenVariantOriginal, - TokenVariantWrapper, - TokenVariantYield, - TokenVariantId, - PositionId, - PositionSummary, - ActionTypeAction, - PositionFunds, - DCAPositionToken, - PlatformMessage, - DCAPositionAction, - ActionType, - CreatedAction, - ModifiedAction, - WithdrawnAction, - TerminatedAction, - TransferredAction, - PermissionsModifiedAction, - SwappedAction, - DCATransaction, - TokenInPair, - DCASwap, -} from './types'; diff --git a/src/services/dca/types.ts b/src/services/dca/types.ts deleted file mode 100644 index 9601bfce..00000000 --- a/src/services/dca/types.ts +++ /dev/null @@ -1,310 +0,0 @@ -import { PermitData, SinglePermitParams } from '@services/permit2'; -import { Address, BigIntish, ChainId, TimeString, TokenAddress, BuiltTransaction, Timestamp, AmountsOfToken } from '@types'; -import { ArrayOneOrMore } from '@utility-types'; - -export type IDCAService = { - getAllowanceTarget(_: { chainId: ChainId; from: TokenAddress; depositWith: TokenAddress; usePermit2?: boolean }): Address; - preparePermitData(_: SinglePermitParams): Promise; - buildCreatePositionTx(_: CreateDCAPositionParams): Promise; - buildIncreasePositionTx(_: IncreaseDCAPositionParams): Promise; - buildReducePositionTx(_: ReduceDCAPositionParams): Promise; - buildReduceToBuyPositionTx(_: ReduceToBuyDCAPositionParams): Promise; - buildWithdrawPositionTx(_: WithdrawDCAPositionParams): Promise; - buildTerminatePositionTx(_: TerminateDCAPositionParams): Promise; - buildMigratePositionTx(_: MigrateDCAPositionParams): Promise; - - getSupportedPairs(_?: { - chains?: ChainId[]; - config?: { timeout: TimeString }; - }): Promise }>>; - getPositionsByAccount(_: { - accounts: ArrayOneOrMore
; - chains?: ChainId[]; - includeHistory?: boolean; - config?: { timeout: TimeString }; - }): Promise>; - getPositionsById(_: { - ids: ArrayOneOrMore<{ chainId: ChainId; hub: Address; positionId: number }>; - includeHistory?: boolean; - config?: { timeout: TimeString }; - }): Promise>; - getPairSwaps(_: { - chainId: ChainId; - variantTokenA: TokenVariantId; - variantTokenB: TokenVariantId; - config?: { timeout: TimeString }; - }): Promise<{ tokenA: TokenInPair; tokenB: TokenInPair; swaps: DCASwap[] }>; -}; - -export type PairInChain = `${ChainId}-${TokenAddress}-${TokenAddress}`; -export type PositionId = `${ChainId}-${Address}-${bigint}`; -export type PositionSummary = { - id: PositionId; - createdAt: Timestamp; - chainId: ChainId; - hub: Address; - tokenId: bigint; - pair: { - pairId: string; - variantPairId: TokenVariantPair; - }; - from: DCAPositionToken; - to: DCAPositionToken; - swapInterval: DCASwapInterval; - owner: Address; - remainingSwaps: number; - totalSwaps: number; - executedSwaps: number; - isStale: boolean; - status: 'ongoing' | 'empty' | 'terminated' | 'finished'; - nextSwapAvailableAt: Timestamp; - permissions: Record; - rate: AmountsOfToken; - funds: PositionFunds; - generatedByYield?: Partial; - history: DCAPositionAction[]; -}; -export type DCAPositionAction = { tx: DCATransaction } & ActionType; -export enum ActionTypeAction { - CREATED = 'created', - MODIFIED = 'modified', - WITHDRAWN = 'withdrawn', - TERMINATED = 'terminated', - TRANSFERRED = 'transferred', - MODIFIED_PERMISSIONS = 'modified permissions', - SWAPPED = 'swapped', -} -export type ActionType = - | CreatedAction - | ModifiedAction - | WithdrawnAction - | TerminatedAction - | TransferredAction - | PermissionsModifiedAction - | SwappedAction; -export type CreatedAction = { - action: ActionTypeAction.CREATED; - rate: bigint; - swaps: number; - owner: Address; - permissions: Record; - fromPrice?: number; -}; -export type ModifiedAction = { - action: ActionTypeAction.MODIFIED; - rate: bigint; - remainingSwaps: number; - oldRate: bigint; - oldRemainingSwaps: number; - fromPrice?: number; -}; -export type WithdrawnAction = { - action: ActionTypeAction.WITHDRAWN; - withdrawn: bigint; - generatedByYield?: { withdrawn: bigint }; - toPrice?: number; -}; -export type TerminatedAction = { - action: ActionTypeAction.TERMINATED; - withdrawnRemaining: bigint; - withdrawnSwapped: bigint; - generatedByYield?: { - withdrawnRemaining?: bigint; - withdrawnSwapped?: bigint; - }; - fromPrice?: number; - toPrice?: number; -}; -export type TransferredAction = { - action: ActionTypeAction.TRANSFERRED; - from: Address; - to: Address; -}; -export type PermissionsModifiedAction = { - action: ActionTypeAction.MODIFIED_PERMISSIONS; - permissions: Record; -}; -export type SwappedAction = { - action: ActionTypeAction.SWAPPED; - rate: bigint; - swapped: bigint; - ratioAToB: bigint; - ratioBToA: bigint; - ratioAToBWithFee: bigint; - ratioBToAWithFee: bigint; - generatedByYield?: { - rate: bigint; - }; - tokenA: { address: TokenAddress; price?: number }; - tokenB: { address: TokenAddress; price?: number }; -}; -export type DCATransaction = { - hash: string; - timestamp: Timestamp; - gasPrice?: bigint; - l1GasPrice?: bigint; - overhead?: bigint; -}; -export type PositionFunds = { - swapped: AmountsOfToken; - remaining: AmountsOfToken; - toWithdraw: AmountsOfToken; -}; -export type DCAPositionToken = { - address: TokenAddress; - symbol: string; - name: string; - decimals: number; - price?: number; - variant: TokenVariant; -}; -export type PlatformMessage = { - id: string; - generated: Timestamp; - message: string; -}; -export type SupportedPair = { - chainId: ChainId; - id: PairInChain; - tokenA: TokenAddress; - tokenB: TokenAddress; - swapIntervals: Record; -}; -export type SwapIntervalData = { - seconds: number; - nextSwapAvailableAt: Record; - isStale: Record; -}; -export type TokenVariantPair = `${TokenVariantId}-${TokenVariantId}`; -export type SupportedDCAToken = { - symbol: string; - decimals: number; - name: string; - variants: TokenVariant[]; - price?: number; -}; -export type TokenVariant = { id: TokenVariantId } & (TokenVariantOriginal | TokenVariantWrapper | TokenVariantYield); -export type TokenVariantOriginal = { type: 'original' }; -export type TokenVariantWrapper = { type: 'wrapper' }; -export type TokenVariantYield = { type: 'yield'; apy: number; platform: string; tvl: number }; -export type TokenVariantId = string; - -export enum DCAPermission { - INCREASE = 'INCREASE', - REDUCE = 'REDUCE', - WITHDRAW = 'WITHDRAW', - TERMINATE = 'TERMINATE', -} - -export enum DCASwapInterval { - ONE_MINUTE = 60, - FIVE_MINUTES = 300, - FIFTEEN_MINUTES = 900, - THIRTY_MINUTES = 1800, - ONE_HOUR = 3600, - FOUR_HOURS = 14400, - ONE_DAY = 86400, - ONE_WEEK = 604800, -} -export type TokenInPair = { - address: TokenAddress; - symbol: string; - decimals: number; - name: string; - price?: number; - variant: TokenVariant; -}; -export type DCASwap = { - executedAt: Timestamp; - ratioAToB: bigint; - ratioBToA: bigint; - ratioAToBWithFee: bigint; - ratioBToAWithFee: bigint; - intervalsInSwap: DCASwapInterval[]; -}; - -export type DCAPermissionSet = { operator: string; permissions: DCAPermission[] }; -export type CreateDCAPositionParams = { - chainId: ChainId; - from: PositionToken; - to: PositionToken; - swapInterval: DCASwapInterval; - amountOfSwaps: number; - owner: Address; - permissions: DCAPermissionSet[]; - deposit: AddFunds; -}; -export type IncreaseDCAPositionParams = { - chainId: ChainId; - positionId: BigIntish; - increase?: AddFunds; - amountOfSwaps: number; - permissionPermit?: DCAPermissionPermit; - dcaHub?: Address; -}; -export type ReduceDCAPositionParams = { - chainId: ChainId; - positionId: BigIntish; - amountOfSwaps: number; - reduce: { amount: BigIntish; convertTo?: TokenAddress; swapConfig?: DCAActionSwapConfig }; - recipient: Address; - permissionPermit?: DCAPermissionPermit; - dcaHub?: Address; -}; -export type ReduceToBuyDCAPositionParams = { - chainId: ChainId; - positionId: BigIntish; - amountOfSwaps: number; - reduce: { amountToBuy: BigIntish; convertTo?: TokenAddress; swapConfig?: DCAActionSwapConfig }; - recipient: Address; - permissionPermit?: DCAPermissionPermit; - dcaHub?: Address; -}; -export type WithdrawDCAPositionParams = { - chainId: ChainId; - positionId: BigIntish; - withdraw: { convertTo?: TokenAddress; swapConfig?: DCAActionSwapConfig }; - recipient: Address; - permissionPermit?: DCAPermissionPermit; - dcaHub?: Address; -}; -export type TerminateDCAPositionParams = { - chainId: ChainId; - positionId: BigIntish; - withdraw: { unswappedConvertTo?: TokenAddress; swappedConvertTo?: TokenAddress; swapConfig?: DCAActionSwapConfig }; - recipient: Address; - permissionPermit?: DCAPermissionPermit; - dcaHub?: Address; -}; -export type MigrateDCAPositionParams = { - chainId: ChainId; - sourceHub: Address; - targetHub: Address; - positionId: BigIntish; - permissionPermit?: DCAPermissionPermit; - migration: PositionMigration & { newFrom?: PositionToken; newTo?: PositionToken; swapConfig?: DCAActionSwapConfig }; -}; - -type PositionMigration = - | { useFundsFrom: 'swapped' | 'unswapped'; sendUnusedFundsTo: Address } - | { useFundsFrom: 'both'; sendUnusedFundsTo?: undefined }; - -export type DCAActionSwapConfig = { slippagePercentage?: number; txValidFor?: TimeString }; -export type DCAPermissionPermit = { - permissions: DCAPermissionSet[]; - tokenId: string; - deadline: BigIntish; - v: BigIntish; - r: string; - s: string; -}; - -export type AddFunds = { swapConfig?: DCAActionSwapConfig } & ( - | { permitData: PermitData['permitData']; signature: string } - | { token: TokenAddress; amount: BigIntish } -); - -type PositionToken = { - address: TokenAddress; - variantId: TokenVariantId; -}; diff --git a/src/services/earn/config.ts b/src/services/earn/config.ts deleted file mode 100644 index 02a553f5..00000000 --- a/src/services/earn/config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { PERMIT2_ADAPTER_CONTRACT } from '@services/permit2/utils/config'; -import { Contract } from '@shared/contracts'; - -export const EARN_VAULT = Contract.with({ defaultAddress: '0x0990a4a641636D437Af9aa214a1A580377eF1954' }).build(); - -export const EARN_VAULT_COMPANION = Contract.with({ defaultAddress: '0x5cb7667A29D2029aC2e38aA43F0608b620FAd087' }).build(); - -export const COMPANION_SWAPPER_CONTRACT = PERMIT2_ADAPTER_CONTRACT; - -export const DELAYED_WITHDRAWAL_MANAGER = Contract.with({ defaultAddress: '0x0ed7f185b12f8C5Cb91daA16edDb1778E404d5D0' }).build(); - -export const EARN_STRATEGY_ROUTER = Contract.with({ defaultAddress: '0xaA2e04112B149Dc415d3F29fc53dD97647ddeE30' }).build(); - -export const EXTERNAL_FIREWALL = Contract.with({ defaultAddress: '0xdcD1B12ab4941D1D2761119cd5f9B0C4a58e8eda' }).build(); diff --git a/src/services/earn/earn-service.ts b/src/services/earn/earn-service.ts deleted file mode 100644 index 231cff3f..00000000 --- a/src/services/earn/earn-service.ts +++ /dev/null @@ -1,1727 +0,0 @@ -import { Address, BigIntish, BuiltTransaction, ChainId, Timestamp, TimeString, TokenAddress } from '@types'; -import { - ClaimDelayedWithdrawPositionParams, - CreateEarnPositionParams, - DetailedStrategy, - EarnActionSwapConfig, - EarnDomain, - EarnPermission, - EarnPermissionData, - EarnPermissionDataMessage, - EarnPermissionPermit, - EarnPermissions, - EarnPermissionSet, - EarnPosition, - FarmId, - Fee, - Guardian, - GuardianId, - HistoricalData, - IEarnService, - IncreaseEarnPositionParams, - PositionId, - SpecialWithdrawalCode, - Strategy, - StrategyGuardian, - StrategyId, - StrategyRiskLevel, - EarnStrategyStatus, - StrategyYieldType, - Token, - TYPES, - WithdrawEarnPositionParams, - WithdrawType, - MigrateEarnType, - MigrateEarnPositionParams, - MigrationCode, -} from './types'; -import { - COMPANION_SWAPPER_CONTRACT, - DELAYED_WITHDRAWAL_MANAGER, - EARN_STRATEGY_ROUTER, - EARN_VAULT, - EARN_VAULT_COMPANION, - EXTERNAL_FIREWALL, -} from './config'; -import { - decodeAbiParameters, - decodeFunctionResult, - encodeFunctionData, - Hex, - parseAbiParameters, - toFunctionSelector, - toHex, - Address as ViemAddress, - encodeAbiParameters, -} from 'viem'; -import vaultAbi from '@shared/abis/earn-vault'; -import companionAbi from '@shared/abis/earn-vault-companion'; -import strategyRouterAbi from '@shared/abis/earn-strategy-router'; -import strategyAbi from '@shared/abis/earn-strategy'; -import delayerWithdrawalManagerAbi from '@shared/abis/earn-delayed-withdrawal-manager'; -import { calculateDeadline, isSameAddress, toAmountsOfToken, toLower } from '@shared/utils'; -import { Addresses, Uint } from '@shared/constants'; -import { IPermit2Service, PermitData, SinglePermitParams } from '@services/permit2'; -import { IQuoteService, QuoteRequest, QuoteResponseWithTx } from '@services/quotes'; -import { IProviderService } from '@services/providers'; -import { MULTICALL_CONTRACT } from '@services/providers/utils'; -import { IAllowanceService } from '@services/allowances'; -import { PERMIT2_CONTRACT } from '@services/permit2/utils/config'; -import qs from 'qs'; -import { IFetchService } from '@services/fetch'; -import { ArrayOneOrMore } from '@utility-types'; -import permit2AdapterAbi from '@shared/abis/permit2-adapter'; -import { IBalanceService } from '@services/balances'; -export class EarnService implements IEarnService { - constructor( - private readonly apiUrl: string, - private readonly permit2Service: IPermit2Service, - private readonly quoteService: IQuoteService, - private readonly providerService: IProviderService, - private readonly allowanceService: IAllowanceService, - private readonly fetchService: IFetchService, - private readonly balanceService: IBalanceService - ) {} - - async getPositionsByAccount({ - accounts, - chains, - includeHistory, - includeHistoricalBalancesFrom, - config, - }: { - accounts: ArrayOneOrMore
; - chains?: ChainId[]; - includeHistory?: boolean; - includeHistoricalBalancesFrom?: Timestamp; - config?: { timeout?: TimeString }; - }) { - return await this.getPositions({ accounts, chains, includeHistory, includeHistoricalBalancesFrom, config }); - } - - async getPositionsById({ - ids, - chains, - includeHistory, - includeHistoricalBalancesFrom, - config, - }: { - ids: ArrayOneOrMore; - chains?: ChainId[]; - includeHistory?: boolean; - includeHistoricalBalancesFrom?: Timestamp; - config?: { timeout?: TimeString }; - }) { - return await this.getPositions({ ids, chains, includeHistory, includeHistoricalBalancesFrom, config }); - } - - private async getPositions(args: GetPositionsParams) { - const { chains, includeHistory, includeHistoricalBalancesFrom, config } = args; - - const baseQueryParams = { - chains, - includeHistory, - includeHistoricalBalancesFrom, - }; - - let queryParams; - if ('accounts' in args) { - queryParams = { ...baseQueryParams, users: args.accounts }; - } else if ('ids' in args) { - queryParams = { ...baseQueryParams, ids: args.ids }; - } - - const params = qs.stringify(queryParams, { arrayFormat: 'comma', skipNulls: true }); - const url = `${this.apiUrl}/v1/earn/positions?${params}`; - const response = await this.fetchService.fetch(url, { timeout: config?.timeout }); - const body: GetPositionsResponse = await response.json(); - const result: Record = {}; - Object.entries(body.positionsByNetwork).forEach(([stringChainId, positionsInThisNetwork]) => { - const chainId = Number(stringChainId) as ChainId; - result[chainId] = positionsInThisNetwork.positions.map((position) => { - const { strategyId, balances, ...restPosition } = position; - const strategyResponse = positionsInThisNetwork.strategies[strategyId]; - return { - ...restPosition, - balances: fulfillBalance(balances, positionsInThisNetwork.tokens), - strategy: fulfillStrategy(strategyResponse, positionsInThisNetwork.tokens, body.guardians), - delayed: position.delayed?.map(({ token, pending, ready }) => ({ - token: { ...positionsInThisNetwork.tokens[token], address: token }, - pending: toAmountsOfToken({ - decimals: positionsInThisNetwork.tokens[token].decimals, - price: positionsInThisNetwork.tokens[token].price, - amount: pending, - }), - ready: toAmountsOfToken({ - decimals: positionsInThisNetwork.tokens[token].decimals, - price: positionsInThisNetwork.tokens[token].price, - amount: ready, - }), - })), - history: - includeHistory && position.history - ? position.history.map((history) => fulfillHistory(history, strategyResponse.farm.asset.address, positionsInThisNetwork.tokens)) - : undefined, - historicalBalances: - includeHistoricalBalancesFrom && position.historicalBalances - ? position.historicalBalances.map((historicalBalance) => - fulfillHistoricalBalance(historicalBalance, positionsInThisNetwork.tokens) - ) - : undefined, - lastUpdatedAt: position.lastUpdatedAt, - }; - }); - }); - return result; - } - - async getSupportedStrategies(args?: { chains?: ChainId[]; config?: { timeout: TimeString } }) { - const params = qs.stringify({ chains: args?.chains }, { arrayFormat: 'comma', skipNulls: true }); - const url = `${this.apiUrl}/v1/earn/strategies/supported?${params}`; - const response = await this.fetchService.fetch(url, { timeout: args?.config?.timeout }); - const body: GetSupportedStrategiesResponse = await response.json(); - const result: Record = {}; - Object.entries(body.strategiesByNetwork).forEach(([stringChainId, { strategies, tokens }]) => { - const chainId = Number(stringChainId) as ChainId; - result[chainId] = strategies.map((strategyResponse) => fulfillStrategy(strategyResponse, tokens, body.guardians)); - }); - return result; - } - - async getStrategy(args?: { strategy: StrategyId; config?: { timeout?: TimeString } }) { - const url = `${this.apiUrl}/v1/earn/strategies/${args?.strategy}`; - const response = await this.fetchService.fetch(url, { timeout: args?.config?.timeout }); - const body: GetStrategyResponse = await response.json(); - return fulfillStrategy(body.strategy, body.tokens, {}) as DetailedStrategy; - } - - preparePermitData(args: SinglePermitParams): Promise { - return this.permit2Service.preparePermitData({ ...args, spender: EARN_VAULT_COMPANION.address(args.chainId) }); - } - - async preparePermissionData({ - chainId, - positionId, - permissions, - signerAddress, - signatureValidFor, - }: { - chainId: ChainId; - positionId: PositionId; - permissions: EarnPermissionSet[]; - signerAddress: Address; - signatureValidFor: TimeString; - }): Promise { - const [, , stringPositionId] = positionId.split('-'); - const bigIntPositionId = BigInt(stringPositionId); - - const deadline = BigInt(calculateDeadline(signatureValidFor)); - const domain: EarnDomain = { - name: 'Balmy Earn NFT Position', - verifyingContract: EARN_VAULT.address(chainId), - chainId, - version: '1.0', - }; - - const nonce = await this.providerService.getViemPublicClient({ chainId }).readContract({ - address: EARN_VAULT.address(chainId), - abi: vaultAbi, - functionName: 'nextNonce', - args: [signerAddress as ViemAddress], - }); - - const message: EarnPermissionDataMessage = { - positions: [ - { - positionId: bigIntPositionId, - permissionSets: permissions.map(({ operator, permissions }) => ({ - operator: operator as ViemAddress, - permissions: permissions.map(mapPermission), - })), - }, - ], - nonce, - deadline, - }; - - return { - dataToSign: { - types: TYPES, - domain, - message, - primaryType: 'PermissionPermit', - }, - permitData: { - permissions, - tokenId: bigIntPositionId.toString(), - deadline, - }, - }; - } - - async getAllowanceTarget({ - chainId, - strategyId, - depositWith, - usePermit2, - }: { - chainId: ChainId; - strategyId: StrategyId; - depositWith: TokenAddress; - usePermit2?: boolean; - }): Promise { - if (isSameAddress(depositWith, Addresses.NATIVE_TOKEN)) { - return undefined; - } else if (usePermit2) { - return PERMIT2_CONTRACT.address(chainId); - } - const strategyRouter = EARN_STRATEGY_ROUTER.address(chainId); - const [, strategyRegistry, strategyIdString] = strategyId.split('-'); - const { result: supportedDepositTokensEncoded } = await this.providerService.getViemPublicClient({ chainId }).simulateContract({ - abi: strategyRouterAbi, - address: strategyRouter, - functionName: 'routeByStrategyId', - args: [strategyRegistry as ViemAddress, BigInt(strategyIdString), SUPPORTED_DEPOSIT_TOKENS_DATA], - }); - const supportedDepositTokens = decodeFunctionResult({ - abi: strategyAbi, - functionName: 'supportedDepositTokens', - data: supportedDepositTokensEncoded, - }); - const needsSwap = !supportedDepositTokens.map(toLower).includes(toLower(depositWith)); - if (needsSwap) { - return EARN_VAULT_COMPANION.address(chainId); - } else { - return EARN_VAULT.address(chainId); - } - } - - async buildCreatePositionTx({ - chainId, - strategyId, - owner, - permissions, - strategyValidationData, - deposit, - caller, - }: CreateEarnPositionParams): Promise { - const vault = EARN_VAULT.address(chainId); - const companion = EARN_VAULT_COMPANION.address(chainId); - const strategyRouter = EARN_STRATEGY_ROUTER.address(chainId); - let depositInfo: { token: Address; amount: bigint; value: bigint }; - if ('token' in deposit) { - const amount = BigInt(deposit.amount); - depositInfo = { token: deposit.token, amount, value: isSameAddress(deposit.token, Addresses.NATIVE_TOKEN) ? amount : 0n }; - } else { - depositInfo = { token: deposit.permitData.token, amount: BigInt(deposit.permitData.amount), value: 0n }; - } - const [, strategyRegistry, strategyIdString] = strategyId.split('-'); - const strategyIdBigInt = BigInt(strategyIdString); - - const [assetEncoded, supportedDepositTokensEncoded] = await this.providerService.getViemPublicClient({ chainId }).multicall({ - contracts: [ - { - abi: strategyRouterAbi, - address: strategyRouter, - functionName: 'routeByStrategyId', - args: [strategyRegistry as ViemAddress, strategyIdBigInt, ASSET_DATA], - }, - { - abi: strategyRouterAbi, - address: strategyRouter, - functionName: 'routeByStrategyId', - args: [strategyRegistry as ViemAddress, strategyIdBigInt, SUPPORTED_DEPOSIT_TOKENS_DATA], - }, - ], - allowFailure: false, - multicallAddress: MULTICALL_CONTRACT.address(chainId), - }); - const asset = decodeFunctionResult({ abi: strategyAbi, functionName: 'asset', data: assetEncoded }); - const supportedDepositTokens = decodeFunctionResult({ - abi: strategyAbi, - functionName: 'supportedDepositTokens', - data: supportedDepositTokensEncoded, - }); - const needsSwap = !supportedDepositTokens.map(toLower).includes(toLower(depositInfo.token)); - - if ('token' in deposit && !needsSwap) { - // If don't need to use Permit2, then just call the vault - const tx = { - to: vault, - data: encodeFunctionData({ - abi: vaultAbi, - functionName: 'createPosition', - args: [ - strategyIdBigInt, - depositInfo.token as ViemAddress, - depositInfo.amount, - owner as ViemAddress, - permissions.map(({ operator, permissions }) => ({ - operator: operator as ViemAddress, - permissions: permissions.map(mapPermission), - })), - strategyValidationData ?? '0x', - '0x', - ], - }), - value: depositInfo.value, - }; - return this.buildAttestedCallIfActivated(tx, caller, chainId, getSelectorFromAbi(vaultAbi, 'createPosition')); - } - // If we get to this point, then we'll use the Companion for the deposit - const calls: Hex[] = []; - - // Handle take from caller (if necessary) - const recipient = needsSwap ? COMPANION_SWAPPER_CONTRACT.address(chainId) : companion; - if ('permitData' in deposit) { - calls.push(buildTakeFromCallerWithPermit(deposit.permitData, deposit.signature, recipient)); - } else if (!isSameAddress(depositInfo.token, Addresses.NATIVE_TOKEN)) { - calls.push(buildTakeFromCaller(depositInfo.token, depositInfo.amount, recipient)); - } - - const depositToken = (needsSwap ? asset : depositInfo.token) as ViemAddress; - let maxApprove = false; - const promises = []; - - if (needsSwap) { - const swapPromise = this.getSwapData({ - request: { - chainId, - sellToken: depositInfo.token, - buyToken: asset, - order: { type: 'sell', sellAmount: depositInfo.amount }, - }, - leftoverRecipient: owner, - swapConfig: deposit?.swapConfig, - previousCalls: calls, - caller, - }).then((result) => calls.push(result.tx)); - promises.push(swapPromise); - } - - if (!isSameAddress(depositToken, Addresses.NATIVE_TOKEN)) { - const allowancePromise = this.allowanceService - .getAllowanceInChain({ - chainId, - owner: companion, - spender: vault, - token: depositToken, - }) - .then((allowance) => { - // Only if the allowance is 0 we need to max approve the vault - maxApprove = allowance === 0n; - }); - promises.push(allowancePromise); - } - - await Promise.all(promises); - - // Handle deposit - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'createPosition', - args: [ - vault, - strategyIdBigInt, - depositToken, - Uint.MAX_256, - owner as ViemAddress, - permissions.map(({ operator, permissions }) => ({ - operator: operator as ViemAddress, - permissions: permissions.map(mapPermission), - })), - strategyValidationData ?? '0x', - '0x', - maxApprove, - ], - }) - ); - - // Build multicall and return tx - return this.buildCompanionMulticall({ - chainId, - calls, - value: depositInfo.value, - caller, - needsAttestation: true, - method: getSelectorFromAbi(vaultAbi, 'createPosition'), - }); - } - - async buildIncreasePositionTx({ - chainId, - positionId, - increase, - permissionPermit, - caller, - }: IncreaseEarnPositionParams): Promise { - const vault = EARN_VAULT.address(chainId); - const companion = EARN_VAULT_COMPANION.address(chainId); - const strategyRouter = EARN_STRATEGY_ROUTER.address(chainId); - let increaseInfo: { token: Address; amount: bigint; value: bigint }; - if ('token' in increase) { - const amount = BigInt(increase.amount); - increaseInfo = { token: increase.token, amount, value: isSameAddress(increase.token, Addresses.NATIVE_TOKEN) ? amount : 0n }; - } else { - increaseInfo = { token: increase.permitData.token, amount: BigInt(increase.permitData.amount), value: 0n }; - } - - if (increaseInfo.amount === 0n) { - throw new Error('Amount cannot be 0'); - } - - const [, , tokenId] = positionId.split('-'); - const bigIntPositionId = BigInt(tokenId); - - const [assetEncoded, supportedDepositTokensEncoded, positionOwner] = await this.providerService.getViemPublicClient({ chainId }).multicall({ - contracts: [ - { abi: strategyRouterAbi, address: strategyRouter, functionName: 'routeByPositionId', args: [vault, bigIntPositionId, ASSET_DATA] }, - { - abi: strategyRouterAbi, - address: strategyRouter, - functionName: 'routeByPositionId', - args: [vault, bigIntPositionId, SUPPORTED_DEPOSIT_TOKENS_DATA], - }, - { abi: vaultAbi, address: vault, functionName: 'ownerOf', args: [bigIntPositionId] }, - ], - allowFailure: false, - multicallAddress: MULTICALL_CONTRACT.address(chainId), - }); - const asset = decodeFunctionResult({ abi: strategyAbi, functionName: 'asset', data: assetEncoded }); - const supportedDepositTokens = decodeFunctionResult({ - abi: strategyAbi, - functionName: 'supportedDepositTokens', - data: supportedDepositTokensEncoded, - }); - const needsSwap = !supportedDepositTokens.map(toLower).includes(toLower(increaseInfo.token)); - - if ('token' in increase && !needsSwap) { - // If don't need to use Permit2, then just call the vault - const tx = { - to: vault, - data: encodeFunctionData({ - abi: vaultAbi, - functionName: 'increasePosition', - args: [bigIntPositionId, increaseInfo.token as ViemAddress, increaseInfo.amount], - }), - value: increaseInfo.value, - }; - return this.buildAttestedCallIfActivated(tx, caller, chainId, getSelectorFromAbi(vaultAbi, 'increasePosition')); - } - - // If we get to this point, then we'll use the Companion for the increase - const calls: Hex[] = []; - - const recipient = needsSwap ? COMPANION_SWAPPER_CONTRACT.address(chainId) : companion; - if ('permitData' in increase) { - // Handle take from caller (if necessary) - calls.push(buildTakeFromCallerWithPermit(increase.permitData, increase.signature, recipient)); - } else if (!isSameAddress(increaseInfo.token, Addresses.NATIVE_TOKEN)) { - calls.push(buildTakeFromCaller(increaseInfo.token, increaseInfo.amount, recipient)); - } - - const depositToken = (needsSwap ? asset : increaseInfo.token) as ViemAddress; - let maxApprove = false; - const promises = []; - - if (needsSwap) { - const swapPromise = await this.getSwapData({ - request: { - chainId, - sellToken: increaseInfo.token, - buyToken: asset, - order: { type: 'sell', sellAmount: increaseInfo.amount }, - }, - leftoverRecipient: positionOwner, - swapConfig: increase?.swapConfig, - previousCalls: calls, - caller, - }).then((result) => calls.push(result.tx)); - promises.push(swapPromise); - } - - if (!isSameAddress(depositToken, Addresses.NATIVE_TOKEN)) { - const allowancePromise = this.allowanceService - .getAllowanceInChain({ - chainId, - owner: companion, - spender: vault, - token: depositToken, - }) - .then((allowance) => { - // Only if the allowance is 0 we need to max approve the vault - maxApprove = allowance === 0n; - }); - promises.push(allowancePromise); - } - - await Promise.all(promises); - - // Handle permission permit - if (permissionPermit) { - calls.push(buildPermissionPermit(bigIntPositionId, permissionPermit, vault)); - } - - // Handle increase - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'increasePosition', - args: [vault as ViemAddress, bigIntPositionId, depositToken, Uint.MAX_256, maxApprove], - }) - ); - - // Build multicall and return tx - return this.buildCompanionMulticall({ - chainId, - calls, - value: increaseInfo.value, - caller, - needsAttestation: true, - method: getSelectorFromAbi(vaultAbi, 'increasePosition'), - }); - } - - async buildClaimDelayedWithdrawPositionTx({ - chainId, - positionId, - recipient, - permissionPermit, - claim, - caller, - }: ClaimDelayedWithdrawPositionParams): Promise { - const vault = EARN_VAULT.address(chainId); - const manager = DELAYED_WITHDRAWAL_MANAGER.address(chainId); - const [, , tokenId] = positionId.split('-'); - const bigIntPositionId = BigInt(tokenId); - - // Get withdrawable funds for each token to convert - const withdrawableFunds = await this.providerService.getViemPublicClient({ chainId }).multicall({ - contracts: claim.tokens.map(({ token }) => ({ - address: manager as ViemAddress, - abi: delayerWithdrawalManagerAbi, - functionName: 'withdrawableFunds' as const, - args: [bigIntPositionId, token as ViemAddress], - })), - allowFailure: false, - }); - - const claimWithFunds = claim.tokens - .map((token, index) => ({ ...token, amount: withdrawableFunds[index] })) - .filter(({ amount }) => amount > 0n); - if (claimWithFunds.length == 0) { - throw new Error('No funds to claim'); - } - const claimsToConvert = claimWithFunds.filter(({ convertTo }) => !!convertTo); - - if (claimsToConvert.length == 0) { - // If don't need to convert anything, then just call the delayer withdrawal manager - const calls = claimWithFunds.map(({ token }) => - encodeFunctionData({ - abi: delayerWithdrawalManagerAbi, - functionName: 'withdraw', - args: [bigIntPositionId, token as ViemAddress, recipient as ViemAddress], - }) - ); - - return { - to: manager, - data: encodeFunctionData({ - abi: delayerWithdrawalManagerAbi, - functionName: 'multicall', - args: [calls], - }), - }; - } - - // If we get to this point, then we'll use the Companion for swap & transfer - const calls: Hex[] = []; - - // Handle permission permit - if (permissionPermit) { - calls.push(buildPermissionPermit(bigIntPositionId, permissionPermit, vault)); - } - - // Handle claim - calls.push( - ...claimWithFunds.map(({ token, convertTo }) => - encodeFunctionData({ - abi: companionAbi, - functionName: 'claimDelayedWithdraw', - args: [ - manager, - bigIntPositionId, - token as ViemAddress, - !!convertTo ? COMPANION_SWAPPER_CONTRACT.address(chainId) : (recipient as ViemAddress), - ], - }) - ) - ); - - const withdrawsToConvert = claimsToConvert.map(({ token, convertTo, amount }) => ({ - chainId, - sellToken: token, - buyToken: convertTo!, - order: { type: 'sell' as const, sellAmount: amount }, - recipient: caller, - })); - - // Handle swaps - const swapAndTransferData = await this.getSwapAndTransferData({ - chainId, - swaps: { - requests: withdrawsToConvert, - swapConfig: claim.swapConfig, - }, - recipient, - previousCalls: calls, - caller, - }); - - calls.push(...swapAndTransferData.calls); - - // Build multicall and return tx - return this.buildCompanionMulticall({ chainId, calls, needsAttestation: false }); - } - async estimateMarketWithdraw({ - chainId, - positionId, - token, - amount, - swapConfig, - }: { - chainId: ChainId; - positionId: PositionId; - token: TokenAddress; - amount: BigIntish; - swapConfig?: EarnActionSwapConfig; - }) { - const vault = EARN_VAULT.address(chainId); - const strategyRouter = EARN_STRATEGY_ROUTER.address(chainId); - const [, , tokenId] = positionId.split('-'); - const bigIntPositionId = BigInt(tokenId); - let amountToWithdraw = BigInt(amount); - if (amount == Uint.MAX_256) { - const [, balance] = await this.providerService.getViemPublicClient({ chainId }).readContract({ - address: vault, - abi: vaultAbi, - functionName: 'position', - args: [bigIntPositionId], - }); - amountToWithdraw = balance[0]; - } - const calldata = encodeFunctionData({ - abi: strategyAbi, - functionName: 'specialWithdraw', - args: [ - bigIntPositionId, - BigInt(SpecialWithdrawalCode.WITHDRAW_ASSET_FARM_TOKEN_BY_ASSET_AMOUNT), - [amountToWithdraw], - '0x', - COMPANION_SWAPPER_CONTRACT.address(chainId), - ], - }); - const [specialWithdrawEncoded, [, strategyAddress]] = await this.providerService.getViemPublicClient({ chainId }).multicall({ - contracts: [ - { - abi: strategyRouterAbi, - address: strategyRouter, - functionName: 'routeByPositionId', - args: [vault, bigIntPositionId, calldata], - }, - { - address: vault, - abi: vaultAbi, - functionName: 'positionsStrategy', - args: [bigIntPositionId], - }, - ], - allowFailure: false, - multicallAddress: MULTICALL_CONTRACT.address(chainId), - }); - const result = decodeFunctionResult({ abi: strategyAbi, functionName: 'specialWithdraw', data: specialWithdrawEncoded }); - - const [, actualWithdrawnTokens, actualWithdrawnAmounts] = result; - const estimateQuote = await this.quoteService.getBestQuote({ - request: { - chainId, - sellToken: actualWithdrawnTokens[0], // Farm token - buyToken: token, - order: { type: 'sell', sellAmount: actualWithdrawnAmounts[0] }, // Amount of farm token to convert - slippagePercentage: swapConfig?.slippagePercentage ?? 0.3, - takerAddress: strategyAddress, - }, - }); - return estimateQuote.buyAmount; - } - - async buildWithdrawPositionTx({ - chainId, - positionId, - withdraw, - migrate, - recipient, - caller, - permissionPermit, - }: WithdrawEarnPositionParams): Promise { - const vault = EARN_VAULT.address(chainId); - const [, , tokenId] = positionId.split('-'); - const bigIntPositionId = BigInt(tokenId); - const tokensToWithdraw = withdraw.amounts.map(({ token }) => token as ViemAddress); - const intendedWithdraw = Object.fromEntries(withdraw.amounts.map(({ token, amount }) => [toLower(token), BigInt(amount)])); - const tokensToMigrate = migrate?.amounts?.filter(({ amount }) => BigInt(amount) > 0n)?.map(({ token }) => token as ViemAddress) ?? []; - const intendedMigrate = migrate ? Object.fromEntries(migrate.amounts.map(({ token, amount }) => [toLower(token), BigInt(amount)])) : {}; - - if (withdraw.amounts.some(({ convertTo, type }) => !!convertTo && type == WithdrawType.DELAYED)) { - throw new Error('Can not convert delayed withdrawals'); - } - const shouldConvertAnyToken = withdraw.amounts.some(({ convertTo, amount }) => !!convertTo && BigInt(amount) > 0n); - const marketWithdrawalsTypes = withdraw.amounts.filter(({ type }) => type == WithdrawType.MARKET); - const shouldWithdrawFarmToken = marketWithdrawalsTypes.length > 0; - const shouldMigrate = tokensToMigrate.length > 0; - if (marketWithdrawalsTypes.length > 1 || (shouldWithdrawFarmToken && withdraw.amounts[0].type != WithdrawType.MARKET)) { - throw new Error('Only one withdraw type MARKET is allowed, and it should be the first one'); - } - if (!shouldConvertAnyToken && !shouldWithdrawFarmToken && !shouldMigrate) { - // If don't need to convert or migrate anything, then just call the vault - const tx = { - to: vault, - data: encodeFunctionData({ - abi: vaultAbi, - functionName: 'withdraw', - args: [BigInt(bigIntPositionId), tokensToWithdraw, Object.values(intendedWithdraw), recipient as ViemAddress], - }), - }; - - return this.buildAttestedCallIfActivated(tx, caller, chainId, getSelectorFromAbi(vaultAbi, 'withdraw')); - } - - // If we get to this point, then we'll use the Companion for swap & transfer - const calls: Hex[] = []; - - // Handle permission permit - if (permissionPermit) { - calls.push(buildPermissionPermit(bigIntPositionId, permissionPermit, vault)); - } - - const shouldCallWithdraw = - !shouldWithdrawFarmToken || withdraw.amounts.some(({ type, amount }) => type != WithdrawType.MARKET && BigInt(amount) >= 0n); - if (shouldCallWithdraw) { - // Handle withdraw - calls.push( - encodeFunctionData({ - abi: companionAbi, - functionName: 'withdraw', - args: [ - vault as ViemAddress, - bigIntPositionId, - tokensToWithdraw, - Object.values(intendedWithdraw).map((amount, index) => (withdraw.amounts[index].type != WithdrawType.MARKET ? amount : 0n)), - shouldMigrate ? EARN_VAULT_COMPANION.address(chainId) : COMPANION_SWAPPER_CONTRACT.address(chainId), - ], - }) - ); - } - - let balancesFromVault: Record = {}; - // If any token amount to convert is MAX_UINT256 or we are withdrawing the farm token, then we need to check vault balance - if ( - shouldWithdrawFarmToken || - withdraw.amounts.some(({ amount }) => amount == Uint.MAX_256) || - migrate?.amounts?.some(({ amount }) => amount == Uint.MAX_256) - ) { - const [positionTokens, positionBalances] = await this.providerService.getViemPublicClient({ chainId }).readContract({ - abi: vaultAbi, - address: vault, - functionName: 'position', - args: [bigIntPositionId], - }); - balancesFromVault = Object.fromEntries(positionTokens.map((token, index) => [toLower(token), positionBalances[index]])); - } - - // Calculate real amounts - const realWithdrawAmounts = Object.fromEntries( - withdraw.amounts.map(({ token, amount }) => [toLower(token), BigInt(amount != Uint.MAX_256 ? amount : balancesFromVault[token])]) - ); - const realMigrateAmounts = Object.fromEntries( - withdraw.amounts.map(({ token }) => [ - toLower(token), - intendedMigrate?.[token] ? BigInt(intendedMigrate[token] != Uint.MAX_256 ? intendedMigrate[token] : realWithdrawAmounts[token]) : 0n, - ]) - ); - const realConvertAmounts = withdraw.amounts.reduce((acc, { token, convertTo }) => { - const convertAmount = realWithdrawAmounts[token] - realMigrateAmounts[token]; - if (!!convertTo && convertAmount > 0n) { - acc[toLower(token)] = convertAmount; - } - return acc; - }, {} as Record); - const realTransferAmounts = withdraw.amounts.reduce((acc, { token, type, convertTo }) => { - const transferAmount = realWithdrawAmounts[token] - realMigrateAmounts[token]; - if (!convertTo && transferAmount > 0n && type != WithdrawType.MARKET) { - acc[toLower(token)] = transferAmount; - } - return acc; - }, {} as Record); - - // Handle swaps - const withdrawsToConvert = withdraw.amounts - .filter(({ token }) => realConvertAmounts[token] > 0n) - .map(({ token, convertTo }) => ({ - chainId, - sellToken: token as ViemAddress, - buyToken: convertTo! as ViemAddress, - order: { type: 'sell' as const, sellAmount: realConvertAmounts[token] }, - recipient: caller, - })); - - let migrationAsset: ViemAddress; - if (shouldMigrate) { - migrationAsset = await this.getStrategyAsset({ chainId, ...migrate! }); - withdrawsToConvert.push( - ...Object.entries(realMigrateAmounts) - .filter(([token]) => !isSameAddress(token, migrationAsset) && realMigrateAmounts[token] > 0n) - .map(([token, amount]) => ({ - chainId, - sellToken: token as ViemAddress, - buyToken: migrationAsset, - order: { type: 'sell' as const, sellAmount: amount }, - recipient: EARN_VAULT_COMPANION.address(chainId), - })) - ); - } - - // Check circular swaps - const convertToSet = new Set(withdrawsToConvert.map(({ buyToken }) => buyToken)); - const convertFromSet = new Set(withdrawsToConvert.map(({ sellToken }) => sellToken)); - const isCircularConversion = [...convertToSet].some((to) => convertFromSet.has(to)); - if (isCircularConversion) { - throw new Error('Cannot make a circular swap'); - } - - // Handle special withdraw - if (shouldWithdrawFarmToken) { - const token = toLower(tokensToWithdraw[0]); - const basicArgs = [ - bigIntPositionId, - BigInt(SpecialWithdrawalCode.WITHDRAW_ASSET_FARM_TOKEN_BY_ASSET_AMOUNT), - [realWithdrawAmounts[token]], - '0x', - COMPANION_SWAPPER_CONTRACT.address(chainId), - ] as const; - const specialWithdrawTx = { - abi: companionAbi, - functionName: 'specialWithdraw', - args: [vault as ViemAddress, ...basicArgs], - } as const; - - const { result } = await this.providerService.getViemPublicClient({ chainId }).simulateContract({ - abi: vaultAbi, - address: vault, - account: caller as ViemAddress, - functionName: 'specialWithdraw', - args: basicArgs, - }); - const [, , actualWithdrawnTokens, actualWithdrawnAmounts] = result; - calls.push(encodeFunctionData(specialWithdrawTx)); - // Convert farm token to asset or specified token - withdrawsToConvert.push({ - chainId, - sellToken: actualWithdrawnTokens[0], // Farm token - buyToken: (withdraw.amounts[0].convertTo ?? withdraw.amounts[0].token) as ViemAddress, // Asset or token to convert to - order: { type: 'sell' as const, sellAmount: actualWithdrawnAmounts[0] }, // Amount of farm token to convert - recipient: caller, - }); - } - - if (shouldMigrate) { - const tokensToRecipientWithoutMigrate = withdraw.amounts.filter(({ token }) => realTransferAmounts[token] > 0n).map(({ token }) => token); - if (tokensToRecipientWithoutMigrate.length > 0) { - calls.push( - ...tokensToRecipientWithoutMigrate.map((token) => - encodeFunctionData({ - abi: companionAbi, - functionName: 'sendToRecipient', - args: [token as ViemAddress, realTransferAmounts[token], recipient as ViemAddress], - }) - ) - ); - } - - calls.push( - ...withdrawsToConvert.map(({ sellToken, order }) => - encodeFunctionData({ - abi: companionAbi, - functionName: 'sendToRecipient', - args: [sellToken, order.sellAmount, COMPANION_SWAPPER_CONTRACT.address(chainId) as ViemAddress], - }) - ) - ); - } - - const tokensToTransfer = !shouldMigrate - ? withdraw.amounts.filter(({ token }) => realTransferAmounts[token] > 0n).map(({ token }) => token) - : []; - - if (tokensToTransfer.length > 0 || withdrawsToConvert.length > 0) { - const swapAndTransferData = await this.getSwapAndTransferData({ - chainId, - swaps: { requests: withdrawsToConvert, swapConfig: withdraw.swapConfig }, - transfers: tokensToTransfer, - recipient, - previousCalls: calls, - caller, - }); - - calls.push(...swapAndTransferData.calls); - } - - if (shouldMigrate) { - const migrateTx = this.buildMigrateTransaction({ - migrate: migrate!, - caller, - vault, - migrationAsset: migrationAsset!, - fromPositionId: positionId, - }); - calls.push(migrateTx); - } - - // Build multicall and return tx - return this.buildCompanionMulticall({ - chainId, - calls, - caller, - needsAttestation: true, - method: getSelectorFromAbi(vaultAbi, 'withdraw'), - }); - } - - private async getSwapData({ - request, - leftoverRecipient, - swapConfig, - previousCalls, - caller, - }: { - request: Pick; - leftoverRecipient: Address; - swapConfig: EarnActionSwapConfig | undefined; - previousCalls: Hex[]; - caller: Address; - }) { - const txValidFor = swapConfig?.txValidFor ?? '1w'; - const [quotes, balances] = await Promise.all([ - this.buildQuotes({ request, leftoverRecipient, swapConfig }), - this.balanceService.getBalancesForAccountInChain({ - account: caller, - chainId: request.chainId, - tokens: [Addresses.NATIVE_TOKEN], - }), - ]); - const nativeBalance = balances[Addresses.NATIVE_TOKEN] ?? 0n; - const bestQuote = await this.simulateSwaps({ - request, - txValidFor, - quotes, - nativeBalance, - previousCalls, - recipient: EARN_VAULT_COMPANION.address(request.chainId), - caller, - }); - return { quote: bestQuote.quote, tx: bestQuote.tx }; - } - - private buildMigrateTransaction(params: { - migrate: MigrateEarnPositionParams; - migrationAsset: ViemAddress; - caller: Address; - vault: ViemAddress; - fromPositionId: PositionId; - }) { - const { migrate, migrationAsset, caller, vault, fromPositionId } = params; - if (migrate?.type == MigrateEarnType.CREATE) { - const strategyIdBigInt = BigInt(migrate.strategyId.split('-')[2]); - const misc: Record = { - [MigrationCode.MIGRATE_FROM_POSITION_AND_CREATE]: encodeAbiParameters(parseAbiParameters('string'), [fromPositionId]), - }; - // Handle deposit - return encodeFunctionData({ - abi: companionAbi, - functionName: 'createPosition', - args: [ - vault, - strategyIdBigInt, - migrationAsset!, - Uint.MAX_256, - caller as ViemAddress, - migrate?.permissions.map(({ operator, permissions }) => ({ - operator: operator as ViemAddress, - permissions: permissions.map(mapPermission), - })), - migrate.strategyValidationData ?? '0x', - encodeAbiParameters(parseAbiParameters('(uint256, bytes)[]'), [ - Object.entries(misc).map(([key, value]) => [BigInt(key), value] as const), - ]), - false, - ], - }); - } else if (migrate?.type == MigrateEarnType.INCREASE) { - // Handle increase - const positionId = BigInt(migrate.positionId.split('-')[2]); - return encodeFunctionData({ - abi: companionAbi, - functionName: 'increasePosition', - args: [vault as ViemAddress, positionId, migrationAsset!, Uint.MAX_256, false], - }); - } - throw new Error('Invalid migration type'); - } - - private async getSwapAndTransferData({ - chainId, - swaps: { requests, swapConfig }, - transfers, - recipient, - previousCalls, - caller, - }: { - chainId: ChainId; - swaps: { - requests: (Pick & { recipient: Address })[]; - swapConfig?: EarnActionSwapConfig; - }; - transfers?: Address[]; - recipient: Address; - previousCalls: Hex[]; - caller: Address; - }) { - const distributions: Record = {}; - - const promises = requests.map(async (request) => { - const [quotes, balances] = await Promise.all([ - this.buildQuotes({ request, leftoverRecipient: recipient, swapConfig }), - this.balanceService.getBalancesForAccountInChain({ - account: caller, - chainId: request.chainId, - tokens: [Addresses.NATIVE_TOKEN], - }), - ]); - const nativeBalance = balances[Addresses.NATIVE_TOKEN] ?? 0n; - const bestQuote = await this.simulateSwaps({ - request, - txValidFor: swapConfig?.txValidFor ?? '1w', - quotes, - nativeBalance, - previousCalls, - recipient: request.recipient, - caller, - }); - return { quote: bestQuote.quote, tx: bestQuote.tx }; - }); - - const bestQuotes = await Promise.all(promises); - const calls = bestQuotes.map(({ tx }) => tx); - const value = bestQuotes.reduce((acc, { quote }) => acc + BigInt(quote.tx.value ?? 0), 0n); - // Handle transfers - if (transfers?.length) { - for (const transfer of transfers) { - const tokenOutTransfer = isSameAddress(transfer, Addresses.NATIVE_TOKEN) ? Addresses.ZERO_ADDRESS : transfer; - distributions[tokenOutTransfer] = [{ recipient, shareBps: 0 }]; - } - - const arbitraryCall = this.permit2Service.arbitrary.buildArbitraryCallWithoutPermit({ - calls: [], - distribution: distributions, - txValidFor: swapConfig?.txValidFor ?? '1w', - chainId, - }); - - const runSwapData = encodeFunctionData({ - abi: companionAbi, - functionName: 'runSwap', - args: [ - Addresses.ZERO_ADDRESS, // No need to set it because we are already transferring the funds to the swapper - value, - arbitraryCall.data as Hex, - ], - }); - calls.push(runSwapData); - } - - return { calls, quotes: bestQuotes }; - } - private async simulateSwaps({ - request, - txValidFor, - quotes, - nativeBalance, - previousCalls, - caller, - recipient, - }: { - request: Pick; - txValidFor: TimeString; - quotes: QuoteResponseWithTx>[]; - nativeBalance: bigint; - previousCalls: Hex[]; - caller: Address; - recipient: Address; - }) { - const swapsTx = quotes.map((quote) => { - // Swap adapter uses the zero address as the native token - const tokenInDistribution = isSameAddress(quote.sellToken.address, Addresses.NATIVE_TOKEN) - ? Addresses.ZERO_ADDRESS - : quote.sellToken.address; - const tokenOutDistribution = isSameAddress(quote.buyToken.address, Addresses.NATIVE_TOKEN) - ? Addresses.ZERO_ADDRESS - : quote.buyToken.address; - - const sellOrderSwapData = encodeFunctionData({ - abi: permit2AdapterAbi, - functionName: 'sellOrderSwap', - args: [ - { - deadline: BigInt(calculateDeadline(txValidFor) ?? calculateDeadline('1w')), - tokenIn: tokenInDistribution as ViemAddress, - amountIn: BigInt(quote.sellAmount.amount), - nonce: 0n, - signature: '0x' as Hex, - allowanceTarget: quote.source.allowanceTarget as ViemAddress, - swapper: quote.tx.to as ViemAddress, - swapData: quote.tx.data as Hex, - tokenOut: tokenOutDistribution as ViemAddress, - minAmountOut: BigInt(quote.minBuyAmount.amount), - transferOut: [{ recipient: recipient as ViemAddress, shareBps: 0n }], - misc: '0x', - }, - ], - }); - - return encodeFunctionData({ - abi: companionAbi, - functionName: 'runSwap', - args: [ - Addresses.ZERO_ADDRESS, // No need to set it because we are already transferring the funds to the swapper - quote.tx.value ?? 0n, - sellOrderSwapData, - ], - }); - }); - - const multicallsToSimulate = await Promise.all( - swapsTx.map( - async (tx, index) => - await this.buildCompanionMulticall({ - chainId: request.chainId, - calls: [...previousCalls, tx], - value: quotes[index].tx.value ?? 0n, - needsAttestation: false, - }).then(({ data }) => data as Hex) - ) - ); - - const value = quotes.sort((a, b) => Number(b.tx.value ?? 0n) - Number(a.tx.value ?? 0n))[0].tx.value ?? 0n; - const { result } = await this.providerService.getViemPublicClient({ chainId: request.chainId }).simulateContract({ - abi: companionAbi, - address: EARN_VAULT_COMPANION.address(request.chainId), - functionName: 'simulate', - args: [multicallsToSimulate], - value: value > nativeBalance ? nativeBalance : value, - account: caller as ViemAddress, - // We have to override this to avoid attest the call to the external firewall - stateOverride: [ - { - address: '0x0000000000000000000000000000000000f01274', - code: '0x10', // Random value, it needs to be a non-zero value - }, - ], - }); - - const decodedResults = result.map(({ success, result, gasSpent }, index) => { - const [amountIn, amountOut] = success ? decodeAbiParameters(parseAbiParameters('uint256 amountIn, uint256 amountOut'), result) : [0n, 0n]; - return { success, gasSpent, amountIn, amountOut, rawResult: result, tx: swapsTx[index], quote: quotes[index] }; - }); - - // DISCLAIMER: We only sort the quotes by amountOut because we don't have buy orders. In the future, if we add buy orders, we should change this. - const successfulQuotes = decodedResults.filter(({ success }) => success).sort((a, b) => Number(b.amountOut - a.amountOut)); - if (successfulQuotes.length === 0) { - throw new Error('No successful quotes'); - } - return { quote: successfulQuotes[0].quote, tx: successfulQuotes[0].tx }; - } - private async buildQuotes({ - request, - leftoverRecipient, - swapConfig, - }: { - request: Pick; - leftoverRecipient: Address; - swapConfig?: EarnActionSwapConfig; - }) { - const quotes = await this.quoteService.getAllQuotesWithTxs({ - request: { - ...request, - slippagePercentage: swapConfig?.slippagePercentage ?? 0.3, - takerAddress: COMPANION_SWAPPER_CONTRACT.address(request.chainId), - recipient: COMPANION_SWAPPER_CONTRACT.address(request.chainId), - txValidFor: swapConfig?.txValidFor ?? '1w', - sourceConfig: { custom: { balmy: { leftoverRecipient } } }, - filters: { includeSources: ['balmy'] }, - }, - config: { - timeout: '5s', - }, - }); - - return quotes; - } - - private async buildCompanionMulticall({ - chainId, - calls, - value, - ...rest - }: { chainId: ChainId; calls: Hex[]; value?: bigint } & ( - | { caller: Address; needsAttestation: true; method: Hex } - | { needsAttestation: false } - )) { - const data = encodeFunctionData({ - abi: companionAbi, - functionName: 'multicall', - args: [calls], - }); - - const tx = { to: EARN_VAULT_COMPANION.address(chainId), data, value }; - - if (rest.needsAttestation) { - return this.buildAttestedCallIfActivated(tx, rest.caller, chainId, rest.method); - } - - return tx; - } - - private async attestTx( - tx: BuiltTransaction, - caller: Address, - chainId: ChainId - ): Promise<{ attestation: { deadline: bigint; executionHashes: Hex[] }; signature: Hex }> { - const result = await this.fetchService.fetch(`https://attester-api.forta.network/attest`, { - method: 'POST', - body: JSON.stringify({ - from: caller, - to: tx.to, - input: tx.data, - value: toHex(tx.value ?? 0n), - chainId, - }), - headers: { 'Content-Type': 'application/json' }, - }); - if (!result.ok) { - throw new Error(`Failed to attest tx. Forta returned: ${await result.text()} (code: ${result.status})`); - } - return result.json(); - } - - private async buildAttestedCallIfActivated(tx: BuiltTransaction, caller: Address, chainId: ChainId, method: Hex): Promise { - const [, , , activationStatus] = await this.providerService.getViemPublicClient({ chainId }).readContract({ - abi: externalFirewallAbi, - address: EXTERNAL_FIREWALL.address(chainId), - functionName: 'getCheckpoint', - args: [method], - }); - - if (!activationStatus) { - return tx; - } - - const { attestation, signature } = await this.attestTx(tx, caller, chainId); - return { - to: tx.to, - value: tx.value, - data: encodeFunctionData({ - abi: vaultAbi, // same abi as companion for attestedCall - functionName: 'attestedCall', - args: [attestation, signature, tx.data as Hex], - }), - }; - } - - async getStrategyAsset(params: { chainId: ChainId } & ({ strategyId: StrategyId } | { positionId: PositionId })) { - const strategyRouter = EARN_STRATEGY_ROUTER.address(params.chainId); - let assetEncoded; - if ('strategyId' in params) { - const [, strategyRegistry, strategyIdString] = params.strategyId.split('-'); - const strategyIdBigInt = BigInt(strategyIdString); - assetEncoded = await this.providerService.getViemPublicClient({ chainId: params.chainId }).readContract({ - abi: strategyRouterAbi, - address: strategyRouter, - functionName: 'routeByStrategyId', - args: [strategyRegistry as ViemAddress, strategyIdBigInt, ASSET_DATA], - }); - } else { - const [, vault, positionIdString] = params.positionId.split('-'); - const positionIdBigInt = BigInt(positionIdString); - assetEncoded = await this.providerService.getViemPublicClient({ chainId: params.chainId }).readContract({ - abi: strategyRouterAbi, - address: strategyRouter, - functionName: 'routeByPositionId', - args: [vault as ViemAddress, positionIdBigInt, ASSET_DATA], - }); - } - return decodeFunctionResult({ abi: strategyAbi, functionName: 'asset', data: assetEncoded }); - } -} - -function buildPermissionPermit(positionId: bigint, permit: EarnPermissionPermit, vault: Address): Hex { - return encodeFunctionData({ - abi: companionAbi, - functionName: 'permissionPermit', - args: [ - vault as ViemAddress, - permit.permissions.map(({ operator, permissions }) => ({ - positionId, - permissionSets: [ - { - operator: operator as Hex, - permissions: permissions.map(mapPermission), - }, - ], - })), - BigInt(permit.deadline), - permit.signature, - ], - }); -} - -export function mapPermission(permission: EarnPermission) { - switch (permission) { - case EarnPermission.INCREASE: - return 0; - case EarnPermission.WITHDRAW: - return 1; - } -} - -function buildTakeFromCallerWithPermit( - { token, amount, nonce, deadline }: PermitData['permitData'], - signature: string, - recipient: Address -): Hex { - return encodeFunctionData({ - abi: companionAbi, - functionName: 'permitTakeFromCaller', - args: [token as ViemAddress, BigInt(amount), BigInt(nonce), BigInt(deadline), signature as Hex, recipient as ViemAddress], - }); -} - -function buildTakeFromCaller(token: TokenAddress, amount: BigIntish, recipient: Address): Hex { - return encodeFunctionData({ - abi: companionAbi, - functionName: 'takeFromCaller', - args: [token as ViemAddress, BigInt(amount), recipient as ViemAddress], - }); -} - -function fulfillStrategy( - strategyResponse: StrategyResponse | (StrategyResponse & HistoricalData), - tokens: Record, - guardians: Record -): Strategy { - const { - farm: { rewards, asset, ...restFarm }, - guardian, - depositTokens, - ...restStrategyResponse - } = strategyResponse; - return { - ...{ - ...restStrategyResponse, - depositTokens: depositTokens.map((token) => ({ - ...tokens[token], - address: token, - type: isSameAddress(token, asset.address) ? 'asset' : 'farm', - })), - farm: { - ...restFarm, - asset: { ...tokens[asset.address], address: asset.address, withdrawTypes: asset.withdrawTypes }, - rewards: rewards - ? { - tokens: rewards.tokens.map((token) => ({ - ...tokens[token.address], - address: token.address, - withdrawTypes: token.withdrawTypes, - apy: token.apy, - })), - apy: rewards.apy, - } - : undefined, - }, - guardian: guardian ? { ...guardians[guardian.id], ...guardian } : undefined, - }, - }; -} - -function fulfillHistory(action: EarnPositionAction, asset: TokenAddress, tokens: Record) { - switch (action.action) { - case 'created': - case 'increased': - return { - ...action, - deposited: toAmountsOfToken({ - price: action.assetPrice, - amount: action.deposited, - decimals: tokens[asset].decimals, - }), - }; - case 'withdrawn': - return { - ...action, - withdrawn: action.withdrawn.map(({ token, amount, tokenPrice, withdrawType }) => ({ - token: { ...tokens[token], address: token, price: tokenPrice }, - amount: toAmountsOfToken({ - price: tokenPrice, - amount, - decimals: tokens[token].decimals, - }), - withdrawType, - })), - }; - case 'withdrawn specially': - return { - ...action, - withdrawn: action.withdrawn.map(({ token, amount, tokenPrice }) => ({ - token: { ...tokens[token], address: token, price: tokenPrice }, - amount: toAmountsOfToken({ - price: tokenPrice, - amount, - decimals: tokens[token].decimals, - }), - })), - }; - case 'transferred': - case 'modified permissions': - return action; - case 'delayed withdrawal claimed': - return { - ...action, - token: { ...tokens[action.token], address: action.token }, - withdrawn: toAmountsOfToken({ - price: action.tokenPrice, - amount: action.withdrawn, - decimals: tokens[action.token].decimals, - }), - }; - } -} - -function fulfillHistoricalBalance({ timestamp, balances }: HistoricalBalance, tokens: Record) { - return { - timestamp, - balances: fulfillBalance(balances, tokens), - }; -} - -function fulfillBalance(balances: { token: TokenAddress; amount: bigint; profit: bigint }[], tokens: Record) { - return balances.map(({ token, amount, profit }) => ({ - token: { ...tokens[token], address: token }, - amount: toAmountsOfToken({ - price: tokens[token].price, - amount, - decimals: tokens[token].decimals, - }), - profit: toAmountsOfToken({ - price: tokens[token].price, - amount: profit, - decimals: tokens[token].decimals, - }), - })); -} - -type GetStrategyResponse = { - strategy: StrategyResponse & HistoricalData; - tokens: Record; -}; - -type GetSupportedStrategiesResponse = { - strategiesByNetwork: Record; - guardians: Record; -}; - -type StrategiesResponse = { - strategies: StrategyResponse[]; - tokens: Record; -}; - -type StrategyResponse = { - id: StrategyId; - farm: StrategyFarmResponse; - depositTokens: ViemAddress[]; - fees: Fee[]; - guardian?: StrategyGuardian; - tos?: string; - riskLevel?: StrategyRiskLevel; - needsTier?: number; - status: EarnStrategyStatus; -}; - -type StrategyFarmResponse = { - id: FarmId; - chainId: ChainId; - name: string; - protocol: string; - asset: { address: ViemAddress; withdrawTypes: WithdrawType[] }; - rewards?: { tokens: { address: ViemAddress; withdrawTypes: WithdrawType[]; apy?: number }[]; apy: number }; - tvl: number; - type: StrategyYieldType; - apy: number; -}; - -type GetPositionsResponse = { - positionsByNetwork: Record; - guardians: Record; -}; - -type PositionsResponse = { - positions: EarnPositionResponse[]; - tokens: Record; - strategies: Record; -}; - -type EarnPositionResponse = { - id: PositionId; - createdAt: Timestamp; - owner: ViemAddress; - permissions: EarnPermissions; - strategyId: StrategyId; - balances: { token: ViemAddress; amount: bigint; profit: bigint }[]; - delayed?: DelayedWithdrawalResponse[]; - history?: EarnPositionAction[]; - historicalBalances?: HistoricalBalance[]; - lastUpdatedAt: Timestamp; -}; -type DelayedWithdrawalResponse = { token: ViemAddress; pending: bigint; ready: bigint }; - -type HistoricalBalance = { - timestamp: Timestamp; - balances: { token: ViemAddress; amount: bigint; profit: bigint }[]; -}; - -type EarnPositionAction = { tx: Transaction } & ActionType; -type Transaction = { - hash: string; - timestamp: Timestamp; -}; - -type ActionType = - | CreatedAction - | IncreasedAction - | WithdrawnAction - | WithdrawnSpeciallyAction - | TransferredAction - | PermissionsModifiedAction - | DelayedWithdrawalClaimedAction; - -type CreatedAction = { - action: 'created'; - owner: ViemAddress; - strategyId: StrategyId; - permissions: EarnPermissions; - deposited: bigint; - assetPrice?: number; -}; - -type IncreasedAction = { - action: 'increased'; - deposited: bigint; - assetPrice?: number; -}; - -type WithdrawnAction = { - action: 'withdrawn'; - withdrawn: { - token: ViemAddress; - amount: bigint; - tokenPrice?: number; - withdrawType: WithdrawType; - }[]; - recipient: ViemAddress; -}; - -type WithdrawnSpeciallyAction = { - action: 'withdrawn specially'; - withdrawn: { - token: ViemAddress; - amount: bigint; - tokenPrice?: number; - }[]; - recipient: ViemAddress; -}; - -type TransferredAction = { - action: 'transferred'; - from: ViemAddress; - to: ViemAddress; -}; - -type PermissionsModifiedAction = { - action: 'modified permissions'; - permissions: EarnPermissions; -}; - -type DelayedWithdrawalClaimedAction = { - action: 'delayed withdrawal claimed'; - token: ViemAddress; - withdrawn: bigint; - tokenPrice?: number; - recipient: ViemAddress; -}; - -type BaseGetPositionsParams = { - chains?: ChainId[]; - includeHistory?: boolean; - includeHistoricalBalancesFrom?: Timestamp; - config?: { timeout?: TimeString }; -}; - -type GetPositionsParams = BaseGetPositionsParams & - ( - | { - ids: ArrayOneOrMore; - } - | { - accounts: ArrayOneOrMore
; - } - ); - -const externalFirewallAbi = [ - { - inputs: [{ internalType: 'bytes4', name: 'selector', type: 'bytes4' }], - name: 'getCheckpoint', - outputs: [ - { internalType: 'uint192', name: '', type: 'uint192' }, - { internalType: 'uint16', name: '', type: 'uint16' }, - { internalType: 'uint16', name: '', type: 'uint16' }, - { internalType: 'enum Activation', name: '', type: 'uint8' }, - { internalType: 'bool', name: '', type: 'bool' }, - ], - stateMutability: 'view', - type: 'function', - }, -] as const; - -function getSelectorFromAbi(abi: any, method: string) { - const abiFunction = abi.find((item: any) => item.name === method); - return toFunctionSelector(abiFunction); -} - -const ASSET_DATA = encodeFunctionData({ - abi: strategyAbi, - functionName: 'asset', -}); - -const SUPPORTED_DEPOSIT_TOKENS_DATA = encodeFunctionData({ - abi: strategyAbi, - functionName: 'supportedDepositTokens', -}); diff --git a/src/services/earn/index.ts b/src/services/earn/index.ts deleted file mode 100644 index 9d18b45a..00000000 --- a/src/services/earn/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export { - IEarnService, - CreateEarnPositionParams, - IncreaseEarnPositionParams, - WithdrawEarnPositionParams, - EarnPermission, - EarnPermissionSet, - EarnPermissionPermit, - AddFundsEarn, - EarnActionSwapConfig, - Token, - DepositToken, -} from './types'; diff --git a/src/services/earn/types.ts b/src/services/earn/types.ts deleted file mode 100644 index 9e36883a..00000000 --- a/src/services/earn/types.ts +++ /dev/null @@ -1,381 +0,0 @@ -import { PermitData, SinglePermitParams } from '@services/permit2'; -import { QuoteRequest } from '@services/quotes'; -import { Address, AmountsOfToken, BigIntish, BuiltTransaction, ChainId, Timestamp, TimeString, TokenAddress } from '@types'; -import { ArrayOneOrMore } from '@utility-types'; -import { Hex, Address as ViemAddress } from 'viem'; - -export type IEarnService = { - getAllowanceTarget(_: { - chainId: ChainId; - strategyId: StrategyId; - depositWith: TokenAddress; - usePermit2?: boolean; - }): Promise; - preparePermitData(_: SinglePermitParams): Promise; - preparePermissionData(_: { - chainId: ChainId; - positionId: PositionId; - permissions: EarnPermissionSet[]; - signerAddress: Address; - signatureValidFor: TimeString; - }): Promise; - buildCreatePositionTx(_: CreateEarnPositionParams): Promise; - buildIncreasePositionTx(_: IncreaseEarnPositionParams): Promise; - buildWithdrawPositionTx(_: WithdrawEarnPositionParams): Promise; - buildClaimDelayedWithdrawPositionTx(_: ClaimDelayedWithdrawPositionParams): Promise; - estimateMarketWithdraw(_: { - chainId: ChainId; - positionId: PositionId; - token: TokenAddress; - amount: BigIntish; - swapConfig?: EarnActionSwapConfig; - }): Promise; - getSupportedStrategies(_?: { chains?: ChainId[]; config?: { timeout?: TimeString } }): Promise>; - getStrategy(_?: { strategy: StrategyId; config?: { timeout?: TimeString } }): Promise; - getPositionsByAccount(_: { - accounts: ArrayOneOrMore
; - chains?: ChainId[]; - includeHistory?: boolean; - includeHistoricalBalancesFrom?: Timestamp; - config?: { timeout?: TimeString }; - }): Promise>; - getPositionsById(_: { - ids: ArrayOneOrMore; - includeHistory?: boolean; - includeHistoricalBalancesFrom?: Timestamp; - config?: { timeout?: TimeString }; - }): Promise>; -}; - -export type CreateEarnPositionParams = { - chainId: ChainId; - strategyId: StrategyId; - owner: Address; - permissions: EarnPermissionSet[]; - strategyValidationData?: Hex; - deposit: AddFundsEarn; - caller: Address; -}; - -export type IncreaseEarnPositionParams = { - chainId: ChainId; - positionId: PositionId; - increase: AddFundsEarn; - caller: Address; - permissionPermit?: EarnPermissionPermit; -}; - -export type WithdrawEarnPositionParams = { - chainId: ChainId; - positionId: PositionId; - withdraw: { - amounts: { token: TokenAddress; amount: BigIntish; convertTo?: TokenAddress; type: WithdrawType }[]; - swapConfig?: EarnActionSwapConfig; - }; - migrate?: MigrateEarnPositionParams; - recipient: Address; - caller: Address; - permissionPermit?: EarnPermissionPermit; -}; - -export type MigrateEarnPositionParams = { - amounts: { token: TokenAddress; amount: BigIntish }[]; -} & (MigrateEarnCreatePositionParams | MigrateEarnIncreasePositionParams); - -export type MigrateEarnCreatePositionParams = { - type: MigrateEarnType.CREATE; - strategyId: StrategyId; - strategyValidationData?: Hex; - permissions: EarnPermissionSet[]; -}; - -export type MigrateEarnIncreasePositionParams = { - type: MigrateEarnType.INCREASE; - positionId: PositionId; -}; - -export enum MigrateEarnType { - CREATE = 'CREATE', - INCREASE = 'INCREASE', -} - -export type SwapperRequestType = Pick; - -export type ClaimDelayedWithdrawPositionParams = { - chainId: ChainId; - positionId: PositionId; - recipient: Address; - permissionPermit?: EarnPermissionPermit; - claim: { tokens: { token: TokenAddress; convertTo?: TokenAddress }[]; swapConfig?: EarnActionSwapConfig }; - caller: Address; -}; - -export type EarnPermissionPermit = { - permissions: EarnPermissionSet[]; - tokenId: string; - deadline: BigIntish; - signature: Hex; -}; - -export type EarnPermissionSet = { operator: string; permissions: EarnPermission[] }; - -export enum EarnPermission { - INCREASE = 'INCREASE', - WITHDRAW = 'WITHDRAW', -} -export type EarnActionSwapConfig = { slippagePercentage?: number; txValidFor?: TimeString }; - -export type AddFundsEarn = { swapConfig?: EarnActionSwapConfig } & ( - | { permitData: PermitData['permitData']; signature: string } - | { token: TokenAddress; amount: BigIntish } -); - -export type DetailedStrategy = Strategy & HistoricalData; - -export type HistoricalData = { - historicalAPY: { - timestamp: Timestamp; - apy: number; - }[]; - - historicalTVL: { timestamp: Timestamp; tvl: number }[]; -}; - -export type DepositToken = Token & { - type: 'asset' | 'farm'; -}; - -export type Strategy = { - id: StrategyId; - depositTokens: DepositToken[]; - farm: StrategyFarm; - fees: Fee[]; - guardian?: StrategyGuardian; - tos?: string; - riskLevel?: StrategyRiskLevel; - needsTier?: number; - status: EarnStrategyStatus; -}; - -export type StrategyFarm = { - id: FarmId; - chainId: ChainId; - name: string; - protocol: string; - asset: TokenWithWithdrawTypes; - rewards?: { tokens: (TokenWithWithdrawTypes & { apy?: number })[]; apy: number }; - tvl: number; - type: StrategyYieldType; - apy: number; -}; - -export type StrategyGuardian = { - id: GuardianId; - fees: Fee[]; -} & Guardian; - -export type Guardian = { - name: string; - description: string; - logo: string; - links?: { - website?: string; - twitter?: string; - discord?: string; - }; -}; - -export type Token = { - address: TokenAddress; - symbol: string; - name: string; - decimals: number; - price?: number; -}; - -export type TokenWithWithdrawTypes = Token & { withdrawTypes: WithdrawType[] }; - -export type Fee = { - type: FeeType; - percentage: number; -}; - -export enum FeeType { - DEPOSIT = 'deposit', - WITHDRAW = 'withdraw', - PERFORMANCE = 'performance', - RESCUE = 'rescue', -} - -export type StrategyIdNumber = number; -export type StrategyRegistryAddress = Lowercase
; -export type StrategyId = `${ChainId}-${StrategyRegistryAddress}-${StrategyIdNumber}`; -export type FarmId = `${ChainId}-${Lowercase
}`; -export type GuardianId = string; - -export enum StrategyYieldType { - LENDING = 'LENDING', - STAKING = 'STAKING', - AGGREAGATOR = 'AGGREGATOR', -} -export enum StrategyRiskLevel { - LOW = 'LOW', - MEDIUM = 'MEDIUM', - HIGH = 'HIGH', -} - -export enum EarnStrategyStatus { - OK = 'ok', - RESCUE_NEEDS_CONFIRMATION = 'Rescue executed. Needs confirmation', - RESCUED = 'Rescued by guardian', -} - -export type EarnPosition = { - id: PositionId; - createdAt: Timestamp; - owner: ViemAddress; - permissions: EarnPermissions; - strategy: Strategy; - balances: { token: Token; amount: AmountsOfToken; profit: AmountsOfToken }[]; - delayed?: { token: Token; pending: AmountsOfToken; ready: AmountsOfToken }[]; - history?: EarnPositionAction[]; - historicalBalances?: HistoricalBalance[]; - lastUpdatedAt: Timestamp; -}; - -export type HistoricalBalance = { - timestamp: Timestamp; - balances: { token: Token; amount: AmountsOfToken; profit: AmountsOfToken }[]; -}; - -export type ActionType = - | CreatedAction - | IncreasedAction - | WithdrawnAction - | WithdrawnSpeciallyAction - | TransferredAction - | PermissionsModifiedAction - | DelayedWithdrawalClaimedAction; - -export type CreatedAction = { - action: 'created'; - owner: ViemAddress; - permissions: EarnPermissions; - deposited: AmountsOfToken; - assetPrice?: number; -}; - -export type IncreasedAction = { - action: 'increased'; - deposited: AmountsOfToken; - assetPrice?: number; -}; - -export type WithdrawnAction = { - action: 'withdrawn'; - withdrawn: { - token: Token; // With price - amount: AmountsOfToken; - withdrawType: WithdrawType; - }[]; - recipient: ViemAddress; -}; - -export type WithdrawnSpeciallyAction = { - action: 'withdrawn specially'; - withdrawn: { - token: Token; // With price - amount: AmountsOfToken; - }[]; - recipient: ViemAddress; -}; - -export type TransferredAction = { - action: 'transferred'; - from: ViemAddress; - to: ViemAddress; -}; - -export type PermissionsModifiedAction = { - action: 'modified permissions'; - permissions: EarnPermissions; -}; - -export type DelayedWithdrawalClaimedAction = { - action: 'delayed withdrawal claimed'; - token: Token; - withdrawn: AmountsOfToken; - recipient: ViemAddress; -}; - -export type EarnPositionAction = { tx: Transaction } & ActionType; -export type Transaction = { - hash: string; - timestamp: Timestamp; -}; - -export type Permission = 'WITHDRAW' | 'INCREASE'; -export type EarnPermissions = Record; - -export type PositionId = `${ChainId}-${VaultAddress}-${PositionIdNumber}`; -export type PositionIdNumber = number; -export type VaultAddress = Lowercase; - -export type EarnPermissionData = { - dataToSign: { - types: typeof TYPES; - domain: EarnDomain; - message: EarnPermissionDataMessage; - primaryType: 'PermissionPermit'; - }; - permitData: { - permissions: EarnPermissionSet[]; - tokenId: string; - deadline: bigint; - }; -}; -export type EarnDomain = { - name: 'Balmy Earn NFT Position'; - verifyingContract: ViemAddress; - chainId: ChainId; - version: '1.0'; -}; -export const TYPES = { - PermissionSet: [ - { name: 'operator', type: 'address' }, - { name: 'permissions', type: 'uint8[]' }, - ], - PositionPermissions: [ - { name: 'positionId', type: 'uint256' }, - { name: 'permissionSets', type: 'PermissionSet[]' }, - ], - PermissionPermit: [ - { name: 'positions', type: 'PositionPermissions[]' }, - { name: 'nonce', type: 'uint256' }, - { name: 'deadline', type: 'uint256' }, - ], -}; - -export type EarnPermissionDataMessage = { - positions: { - positionId: bigint; - permissionSets: { operator: string; permissions: number[] }[]; - }[]; - nonce: bigint; - deadline: bigint; -}; - -export enum WithdrawType { - IMMEDIATE = 'IMMEDIATE', - DELAYED = 'DELAYED', - MARKET = 'MARKET', -} - -export enum SpecialWithdrawalCode { - WITHDRAW_ASSET_FARM_TOKEN_BY_AMOUNT = 0, - WITHDRAW_ASSET_FARM_TOKEN_BY_ASSET_AMOUNT = 1, -} - -export enum MigrationCode { - MIGRATE_FROM_POSITION_AND_CREATE = 0, -} diff --git a/src/services/index.ts b/src/services/index.ts index cf365666..17b7679d 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -7,6 +7,4 @@ export * from './quotes'; export * from './metadata'; export * from './prices'; export * from './logs'; -export * from './permit2'; -export * from './dca'; export * from './blocks'; diff --git a/src/services/permit2/README.md b/src/services/permit2/README.md deleted file mode 100644 index 70542cb7..00000000 --- a/src/services/permit2/README.md +++ /dev/null @@ -1,188 +0,0 @@ -# Permit2 Service - -## Introduction - -From [Uniswap's blog post](https://blog.uniswap.org/permit2-and-universal-router): - -> Permit2 is a token approval contract that can safely share and manage token approvals across different smart contracts. As more projects integrate with Permit2, we can standardize token approvals across all applications. In turn, Permit2 will improve the user experience by reducing transaction costs while improving smart contract security. - -Basically, it would allow a user to grant your protocol authorization to use their tokens via signature, instead of the normal ERC20 approval flow. This has quite a few benefits: - -- No need for multiple transactions anymore -- Authorizations can be of the exact amount needed, reducing the risk to user funds -- Authorizations can have a deadline - -The normal workflow would require the user to grant the Permit2 contract "regular" ERC20 approval. It's recommended that this approval is the maximum possible so that it only has to be done once. Remember that it would be safe to do so, since funds can only be transferred with future signatures. - -Once the authorization to Permit2 is granted, next time the user wants to use your protocol they would only have to: - -1. Sign an authorization -1. Execute your contract - -While two operations are needed, only one transaction is required 🔥 - -## The Service - -This service can be used to interact with Permit2. It provides some helper methods that would make integration easier, while it also provides a way to give already deployed contracts Permit2 capabilities. - -### Permit2 Authorization - -Remember that before Permit2 can be used, you'll need to have the user authorize the Permit2 contract. - -```ts -import { Contract, constants } from "ethers"; -import { buildSDK } from "@balmy/sdk"; - -const sdk = buildSDK(); - -const TOKEN = "0x..."; // The address of the token that will be taken from the user - -const tokenContract = new Contract(TOKEN, ERC20_ABI, user); -await tokenContract.approve( - sdk.permit2Service.permit2ContractAddress, - constants.MaxUint256 -); -``` - -### Arbitrary Calls - -Re-deploying contracts can be difficult and time-consuming. Also, sometimes it's just impossible to migrate liquidity. This service will allow you to integrate your existing contract with Permit2, without having to re-deploy. - -#### Single Permit - -If you simply want to take one token from the user and do something with it, this is the way to go. This should be the usual case for most protocols. - -##### Example: take tokens and deposit into yield generating vault - -```ts -import { buildSDK } from "@balmy/sdk"; - -const sdk = buildSDK(); -const { arbitrary } = sdk.permit2Service; - -const TOKEN = "0x..."; // The address of the token that will be taken from the user -const AMOUNT_TO_DEPOSIT = 1e18; // The amount of tokens to deposit -const VAULT = "0x..."; // The vault to generate yield in - -// Prepare data to sign -const { - dataToSign: { domain, types, message }, - permitData, -} = await arbitrary.preparePermitData({ - appId: APP_ID, // A number that will identify your app - chainId: 1, // The chain's id - signerAddress: user.address, // The user's address - token: TOKEN, - amount: AMOUNT_TO_DEPOSIT, - signatureValidFor: "1d", // How long the signature will be valid for -}); - -// Have the user sign it -const signature = await user._signTypedData(domain, types, message); - -// Build tx -const tx = arbitrary.buildArbitraryCallWithPermit({ - // Set permit data - permitData: { ...permitData, signature }, - - // Provide allowance for vault - allowanceTargets: [{ token: TOKEN, target: VAULT }], - - // Deposit into vault - calls: [ - { - address: VAULT, - abi: { json: ABI }, - functionName: "deposit", - args: [AMOUNT_TO_DEPOSIT, arbitrary.contractAddress], - }, - ], - - // Distribute vault tokens to user - distribution: { - [VAULT]: [{ recipient: user.address, shareBps: 10_000 }], - }, -}); - -// Send tx -await user.sendTransaction(tx); -``` - -#### Batch Permit - -If you want to take more than one token from the user, you can do it also in one signature! - -##### Example: take multiple tokens and deposit into many yield generating vaults - -```ts -import { buildSDK } from "@balmy/sdk"; - -const sdk = buildSDK(); -const { arbitrary } = sdk.permit2Service; - -const TOKEN_1 = "0x..."; -const AMOUNT_TO_DEPOSIT_1 = 1e18; -const VAULT_1 = "0x..."; - -const TOKEN_2 = "0x..."; -const AMOUNT_TO_DEPOSIT_2 = 2e18; -const VAULT_2 = "0x..."; - -// Prepare data to sign -const { - dataToSign: { domain, types, message }, - permitData, -} = await arbitrary.prepareBatchPermitData({ - appId: APP_ID, // A number that will identify your app - chainId: 1, // The chain's id - signerAddress: user.address, // The user's address - tokens: { - // Tokens to take from the user - [TOKEN_1]: AMOUNT_TO_DEPOSIT_1, - [TOKEN_2]: AMOUNT_TO_DEPOSIT_2, - }, - signatureValidFor: "1d", // How long the signature will be valid for -}); - -// Have the user sign it -const signature = await user._signTypedData(domain, types, message); - -// Build tx -const tx = arbitrary.buildArbitraryCallWithBatchPermit({ - // Set permit data - permitData: { ...permitData, signature }, - - // Provide allowance for vaults - allowanceTargets: [ - { token: TOKEN_1, target: VAULT_1 }, - { token: TOKEN_2, target: VAULT_2 }, - ], - - calls: [ - // Deposit into first vault - { - address: VAULT_1, - abi: { json: ABI_1 }, - functionName: "deposit", - args: [AMOUNT_TO_DEPOSIT_1, arbitrary.contractAddress], - }, - - // Deposit into second vault - { - address: VAULT_2, - abi: { json: ABI_2 }, - functionName: "deposit", - args: [AMOUNT_TO_DEPOSIT_2, arbitrary.contractAddress], - }, - ], - - // Distribute vault tokens to user - distribution: { - [VAULT_1]: [{ recipient: user.address, shareBps: 10_000 }], - [VAULT_2]: [{ recipient: user.address, shareBps: 10_000 }], - }, -}); - -// Send tx -await user.sendTransaction(tx); -``` diff --git a/src/services/permit2/index.ts b/src/services/permit2/index.ts deleted file mode 100644 index 33fa5334..00000000 --- a/src/services/permit2/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export { - IPermit2Service, - IPermit2ArbitraryService, - IPermit2QuoteService, - SinglePermitParams, - BatchPermitParams, - PermitData, - BatchPermitData, - ArbitraryCallWithPermitParams, - ArbitraryCallWithBatchPermitParams, - ArbitraryCallWithoutPermitParams, - GenericContractCall, - DistributionTarget, - EstimatedQuoteResponseWithTx, -} from './types'; diff --git a/src/services/permit2/permit2-arbitrary-service.ts b/src/services/permit2/permit2-arbitrary-service.ts deleted file mode 100644 index 66c168a0..00000000 --- a/src/services/permit2/permit2-arbitrary-service.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { encodeFunctionData, parseAbi } from 'viem'; -import { calculateDeadline } from '@shared/utils'; -import permit2AdapterAbi from '@shared/abis/permit2-adapter'; -import { - ArbitraryCallWithBatchPermitParams, - ArbitraryCallWithoutPermitParams, - ArbitraryCallWithPermitParams, - BaseArbitraryCallParams, - BatchPermitData, - BatchPermitParams, - IPermit2ArbitraryService, - IPermit2Service, - PermitData, - SinglePermitParams, -} from './types'; -import { PERMIT2_ADAPTER_CONTRACT } from './utils/config'; -import { BuiltTransaction } from '@types'; - -export class Permit2ArbitraryService implements IPermit2ArbitraryService { - readonly permit2AdapterContract = PERMIT2_ADAPTER_CONTRACT; - - constructor(private readonly permit2Service: IPermit2Service) {} - - preparePermitData(args: SinglePermitParams): Promise { - return this.permit2Service.preparePermitData({ ...args, spender: this.permit2AdapterContract.address(args.chainId) }); - } - - prepareBatchPermitData(args: BatchPermitParams): Promise { - return this.permit2Service.prepareBatchPermitData({ ...args, spender: this.permit2AdapterContract.address(args.chainId) }); - } - - buildArbitraryCallWithPermit(params: ArbitraryCallWithPermitParams) { - return this.buildArbitraryCallInternal({ - ...params, - functionName: 'executeWithPermit', - }); - } - - buildArbitraryCallWithBatchPermit(params: ArbitraryCallWithBatchPermitParams): BuiltTransaction { - return this.buildArbitraryCallInternal({ - ...params, - functionName: 'executeWithBatchPermit', - }); - } - - buildArbitraryCallWithoutPermit(params: ArbitraryCallWithoutPermitParams): BuiltTransaction { - const permitData = { - tokens: [], - nonce: 0, - signature: '0x', - deadline: calculateDeadline(params.txValidFor), - }; - return this.buildArbitraryCallInternal({ - ...params, - permitData, - chainId: params.chainId, - functionName: 'executeWithBatchPermit', - }); - } - - private buildArbitraryCallInternal({ - permitData: { deadline, ...permitData }, - calls, - allowanceTargets, - distribution, - chainId, - functionName, - }: BaseArbitraryCallParams & { functionName: string }) { - const repeatedToken = findRepeatedKey(distribution ?? {}); - if (repeatedToken) throw new Error(`Found token '${repeatedToken}' more than once, with different casing`); - - const allowances = allowanceTargets?.map(({ token, target }) => ({ token, allowanceTarget: target })) ?? []; - const encodedCalls = calls.map((call) => - 'data' in call - ? { - target: call.to, - data: call.data, - value: call.value ?? 0, - } - : { - target: call.address, - data: encodeFunctionData({ - abi: 'json' in call.abi ? call.abi.json : parseAbi(call.abi.humanReadable), - functionName: call.functionName, - args: call.args ?? [], - }), - value: call.value ?? 0, - } - ); - const transferOut = Object.entries(distribution ?? {}).map(([token, distribution]) => ({ token, distribution })); - const totalValue = calls.reduce((sum, { value }) => sum + BigInt(value ?? 0), 0n); - - const data = encodeFunctionData({ - abi: permit2AdapterAbi as any, // We cast as any to avoid type checks - functionName, - args: [permitData, allowances, encodedCalls, transferOut, deadline], - }); - - return { - to: this.permit2AdapterContract.address(chainId), - data, - value: totalValue, - }; - } -} - -function findRepeatedKey(object: Record) { - const keys = new Set(); - for (const key in object) { - const lower = key.toLowerCase(); - if (keys.has(lower)) { - return key; - } - keys.add(lower); - } - return undefined; -} diff --git a/src/services/permit2/permit2-quote-service.ts b/src/services/permit2/permit2-quote-service.ts deleted file mode 100644 index ed6c96e4..00000000 --- a/src/services/permit2/permit2-quote-service.ts +++ /dev/null @@ -1,308 +0,0 @@ -import { EstimatedQuoteResponseWithTx, IPermit2QuoteService, IPermit2Service, PermitData, SinglePermitParams } from './types'; -import { PERMIT2_ADAPTER_CONTRACT, PERMIT2_SUPPORTED_CHAINS } from './utils/config'; -import { Address, ChainId, TimeString, TokenAddress } from '@types'; -import { CompareQuotesBy, CompareQuotesUsing, QuoteResponse, IQuoteService, sortQuotesBy } from '@services/quotes'; -import { calculateGasDetails, handleResponseFailure } from '@services/quotes/quote-service'; -import { - EstimatedQuoteRequest, - FailedResponse, - IgnoreFailedResponses, - QuoteResponseWithTx, - SourceId, - SourceMetadata, -} from '@services/quotes/types'; -import { calculateDeadline, isSameAddress, toAmountsOfToken } from '@shared/utils'; -import { encodeFunctionData, decodeAbiParameters, parseAbiParameters, Hex, Address as ViemAddress } from 'viem'; -import permit2AdapterAbi from '@shared/abis/permit2-adapter'; -import { Either } from '@utility-types'; -import { IGasService } from '@services/gas'; -import { Addresses } from '@shared/constants'; -import { IProviderService } from '..'; - -export class Permit2QuoteService implements IPermit2QuoteService { - readonly permit2AdapterContract = PERMIT2_ADAPTER_CONTRACT; - - constructor( - private readonly permit2Service: IPermit2Service, - private readonly quotesService: IQuoteService, - private readonly providerService: IProviderService, - private readonly gasService: IGasService - ) {} - - preparePermitData(args: SinglePermitParams): Promise { - return this.permit2Service.preparePermitData({ ...args, spender: this.permit2AdapterContract.address(args.chainId) }); - } - - supportedSources() { - const supportedChains = this.supportedChains(); - // Filter out unsupported chains - const sources: [SourceId, SourceMetadata][] = Object.entries(this.quotesService.supportedSources()).map(([sourceId, source]) => [ - sourceId, - { ...source, supports: { ...source.supports, chains: source.supports.chains.filter((chainId) => supportedChains.includes(chainId)) } }, - ]); - return Object.fromEntries(sources); - } - - supportedChains() { - return PERMIT2_SUPPORTED_CHAINS; - } - - supportedSourcesInChain({ chainId }: { chainId: ChainId }) { - const sourcesInChain = Object.entries(this.supportedSources()).filter(([, source]) => source.supports.chains.includes(chainId)); - return Object.fromEntries(sourcesInChain); - } - - supportedGasSpeeds() { - return this.quotesService.supportedGasSpeeds(); - } - - estimateQuotes({ request, config }: { request: EstimatedQuoteRequest; config?: { timeout?: TimeString } }) { - const quotes = this.quotesService.getQuotes({ - request: { ...request, takerAddress: this.permit2AdapterContract.address(request.chainId) }, - config: config, - }); - const txs = this.quotesService.buildTxs({ quotes, config }); - - const result: Record> = {}; - for (const sourceId in quotes) { - result[sourceId] = Promise.all([quotes[sourceId], txs[sourceId]]).then(([{ accounts, ...quote }, estimatedTx]) => ({ - ...quote, - customData: { - ...quote.customData, - estimatedTx, - }, - })); - } - return result; - } - - async estimateAllQuotes({ - request, - config, - }: { - request: EstimatedQuoteRequest; - config?: { - ignoredFailed?: IgnoreFailed; - sort?: { - by: CompareQuotesBy; - using?: CompareQuotesUsing; - }; - timeout?: TimeString; - }; - }) { - const metadata = this.supportedSources(); - const quotes = Object.entries(this.estimateQuotes({ request, config })).map(([sourceId, response]) => - handleResponseFailure(sourceId, response, metadata) - ); - - const responses = await Promise.all(quotes); - const successfulQuotes = responses.filter((response): response is EstimatedQuoteResponseWithTx => !('failed' in response)); - const failedQuotes = config?.ignoredFailed === false ? responses.filter((response): response is FailedResponse => 'failed' in response) : []; - - const sortedQuotes = sortQuotesBy(successfulQuotes, config?.sort?.by ?? 'most-swapped', config?.sort?.using ?? 'sell/buy amounts'); - - return [...sortedQuotes, ...failedQuotes] as IgnoreFailedResponses[]; - } - - async buildAndSimulateQuotes({ - chainId, - quotes: estimatedQuotes, - config, - ...quoteData - }: { - chainId: ChainId; - quotes: EstimatedQuoteResponseWithTx[]; - takerAddress: Address; - recipient?: Address; - config?: { - ignoredFailed?: IgnoreFailed; - sort?: { - by: CompareQuotesBy; - using?: CompareQuotesUsing; - }; - }; - } & Either<{ permitData?: PermitData['permitData'] & { signature: string } }, { txValidFor?: TimeString }>): Promise< - IgnoreFailedResponses[] - > { - const quotes = estimatedQuotes.map((estimatedQuote) => buildRealQuote(quoteData, estimatedQuote, chainId)); - const encoded = quotes.filter((response): response is QuoteResponseWithTx => !('failed' in response)); - const responses = await this.verifyAndCorrect(chainId, quoteData.takerAddress, encoded); - - if (config?.sort) { - const successfulQuotes = responses.filter((response): response is QuoteResponseWithTx => !('failed' in response)); - const failedQuotes = - config?.ignoredFailed === false - ? [ - ...quotes.filter((response): response is FailedResponse => 'failed' in response), - ...responses.filter((response): response is FailedResponse => 'failed' in response), - ] - : []; - - const sortedQuotes = sortQuotesBy(successfulQuotes, config.sort.by, config.sort.using ?? 'sell/buy amounts'); - return [...sortedQuotes, ...failedQuotes] as IgnoreFailedResponses[]; - } - - // Don't sort, but filter out failed if needed - const result = - config?.ignoredFailed === false ? responses : responses.filter((response): response is QuoteResponseWithTx => !('failed' in response)); - return result as IgnoreFailedResponses[]; - } - - private async verifyAndCorrect( - chainId: ChainId, - takerAddress: Address, - quotes: QuoteResponseWithTx[] - ): Promise<(QuoteResponseWithTx | FailedResponse)[]> { - const calls = quotes.map(({ tx }) => tx.data); - const maxValue = quotes.reduce((max, { tx: { value } }) => (value && max < (BigInt(value) ?? 0n) ? BigInt(value) : max), 0n); - const [gasCalculator, encodedResults] = await Promise.all([ - this.gasService.getQuickGasCalculator({ chainId, config: { timeout: '2s' } }), - this.simulate({ chainId, calls, account: takerAddress, value: maxValue }), - ]); - const decodedResults = encodedResults.map(({ success, result, gasSpent }) => { - const [amountIn, amountOut] = success ? decodeAbiParameters(parseAbiParameters('uint256 amountIn, uint256 amountOut'), result) : [0n, 0n]; - return { success, gasSpent, amountIn, amountOut, rawResult: result }; - }); - return quotes.map((quote, i) => { - const { success, amountIn, amountOut, gasSpent, rawResult } = decodedResults[i]; - if (!success) { - return { - failed: true, - source: { - id: quote.source.id, - name: quote.source.name, - logoURI: quote.source.logoURI, - }, - error: `Failed with ${rawResult}`, - }; - } - const sellAmount = toAmountsOfToken({ ...quote.sellToken, amount: amountIn }); - const buyAmount = toAmountsOfToken({ ...quote.buyToken, amount: amountOut }); - const gasCost = gasCalculator.calculateGasCost({ gasEstimation: gasSpent }); - let gas: QuoteResponse['gas'] = undefined; - if (quote.gas) { - gas = { - estimatedGas: gasSpent, - ...calculateGasDetails(quote.gas.gasTokenSymbol, gasCost['standard'].gasCostNativeToken, quote.gas.gasTokenPrice), - }; - } - return { ...quote, sellAmount, buyAmount, gas }; - }); - } - - private async simulate({ - chainId, - calls, - account, - value, - }: { - chainId: ChainId; - account: Address; - value?: bigint; - calls: string[]; - }): Promise> { - const { result } = await this.providerService.getViemPublicClient({ chainId }).simulateContract({ - address: this.permit2AdapterContract.address(chainId) as ViemAddress, - abi: permit2AdapterAbi, - functionName: 'simulate', - args: [calls as Hex[]], - account: account as ViemAddress, - value: value ?? 0n, - }); - return result; - } -} - -type SimulationResult = { - success: boolean; - result: Hex; - gasSpent: bigint; -}; - -function buildRealQuote( - { - takerAddress, - recipient, - permitData, - txValidFor, - }: { - takerAddress: Address; - recipient?: Address; - permitData?: PermitData['permitData'] & { signature: string }; // Not needed in case of native token - txValidFor?: TimeString; - }, - quote: EstimatedQuoteResponseWithTx, - chainId: ChainId -): QuoteResponseWithTx | FailedResponse { - try { - recipient = recipient ?? takerAddress; - const deadline = BigInt(permitData?.deadline ?? calculateDeadline(txValidFor) ?? calculateDeadline('1w')); - // Note: when selling native, we can end up with issues if maxSellAmount != value. So the idea would be to simply use the value - const maxSellAmount = isSameAddress(quote.sellToken.address, Addresses.NATIVE_TOKEN) - ? quote.customData.estimatedTx.value ?? 0n - : quote.maxSellAmount.amount; - const data = - quote.type === 'sell' - ? encodeFunctionData({ - abi: permit2AdapterAbi, - functionName: 'sellOrderSwap', - args: [ - { - deadline, - tokenIn: mapIfNative(quote.sellToken.address), - amountIn: maxSellAmount, - nonce: permitData ? permitData.nonce : 0n, - signature: (permitData?.signature as Hex) ?? '0x', - allowanceTarget: quote.source.allowanceTarget as ViemAddress, - swapper: quote.customData.estimatedTx.to as ViemAddress, - swapData: quote.customData.estimatedTx.data as Hex, - tokenOut: mapIfNative(quote.buyToken.address), - minAmountOut: quote.minBuyAmount.amount, - transferOut: [{ recipient: recipient as ViemAddress, shareBps: 0n }], - misc: '0x', - }, - ], - }) - : encodeFunctionData({ - abi: permit2AdapterAbi, - functionName: 'buyOrderSwap', - args: [ - { - deadline, - tokenIn: mapIfNative(quote.sellToken.address), - maxAmountIn: maxSellAmount, - nonce: permitData ? permitData.nonce : 0n, - signature: (permitData?.signature as Hex) ?? '0x', - allowanceTarget: quote.source.allowanceTarget as ViemAddress, - swapper: quote.customData.estimatedTx.to as ViemAddress, - swapData: quote.customData.estimatedTx.data as Hex, - tokenOut: mapIfNative(quote.buyToken.address), - amountOut: quote.minBuyAmount.amount, - transferOut: [{ recipient: recipient as ViemAddress, shareBps: 0n }], - unspentTokenInRecipient: takerAddress as ViemAddress, - misc: '0x', - }, - ], - }); - return { - ...quote, - accounts: { takerAddress, recipient }, - tx: { - ...quote.customData.estimatedTx, - from: takerAddress, - to: PERMIT2_ADAPTER_CONTRACT.address(chainId), - data, - }, - }; - } catch (e: any) { - return { - failed: true, - source: quote.source, - error: `Failed to encode params: ${e.message}`, - }; - } -} - -function mapIfNative(token: TokenAddress): ViemAddress { - return isSameAddress(token, Addresses.NATIVE_TOKEN) ? Addresses.ZERO_ADDRESS : (token as ViemAddress); -} diff --git a/src/services/permit2/permit2-service.ts b/src/services/permit2/permit2-service.ts deleted file mode 100644 index d3858116..00000000 --- a/src/services/permit2/permit2-service.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { Address, BigIntish, ChainId } from '@types'; -import { - BatchPermitData, - GenericBatchPermitParams, - GenericSinglePermitParams, - IPermit2ArbitraryService, - IPermit2QuoteService, - IPermit2Service, - PermitData, -} from './types'; -import { Permit2ArbitraryService } from './permit2-arbitrary-service'; -import { PERMIT2_CONTRACT, WORDS_FOR_NONCE_CALCULATION } from './utils/config'; -import { calculateDeadline } from '@shared/utils'; -import { PERMIT2_BATCH_TRANSFER_FROM_TYPES, PERMIT2_TRANSFER_FROM_TYPES } from './utils/eip712-types'; -import PERMIT2_ABI from '@shared/abis/permit2'; -import { Uint } from '@shared/constants'; -import { Permit2QuoteService } from './permit2-quote-service'; -import { IProviderService } from '@services/providers'; -import { IQuoteService } from '@services/quotes'; -import { IGasService } from '@services/gas'; -import { MULTICALL_CONTRACT } from '@services/providers/utils'; - -export class Permit2Service implements IPermit2Service { - readonly permit2Contract = PERMIT2_CONTRACT; - readonly arbitrary: IPermit2ArbitraryService; - readonly quotes: IPermit2QuoteService; - readonly providerService: IProviderService; - - constructor(providerService: IProviderService, quoteService: IQuoteService, gasService: IGasService) { - this.arbitrary = new Permit2ArbitraryService(this); - this.quotes = new Permit2QuoteService(this, quoteService, providerService, gasService); - this.providerService = providerService; - } - - async calculateNonce({ chainId, appId, user }: { chainId: ChainId; appId: BigIntish; user: Address }): Promise { - // Calculate words based on seed word - const words = new Array(WORDS_FOR_NONCE_CALCULATION).fill(0).map((_, i) => BigInt(appId) + BigInt(i)); - - // Fetch bitmaps for user's words - const contracts = words.map((word) => ({ - address: this.permit2Contract.address(chainId), - abi: PERMIT2_ABI, - functionName: 'nonceBitmap', - args: [user, word], - })); - - const results = contracts.length - ? await this.providerService - .getViemPublicClient({ chainId }) - .multicall({ contracts, allowFailure: false, multicallAddress: MULTICALL_CONTRACT.address(chainId), batchSize: 0 }) - : []; - - // Find nonce - for (let i = 0; i < results.length; i++) { - const result = BigInt(results[i] as bigint); - if (result < Uint.MAX_256) { - return (words[i] << 8n) + findUnusedBit(result); - } - } - - throw new Error('No nonce found'); - } - - async preparePermitData({ - appId, - chainId, - spender, - token, - amount, - signerAddress, - signatureValidFor, - }: GenericSinglePermitParams): Promise { - const nonce = await this.calculateNonce({ chainId, appId, user: signerAddress }); - const deadline = BigInt(calculateDeadline(signatureValidFor)); - return { - dataToSign: { - types: PERMIT2_TRANSFER_FROM_TYPES, - domain: { - name: 'Permit2', - chainId, - verifyingContract: this.permit2Contract.address(chainId), - }, - message: { - permitted: { token, amount: BigInt(amount) }, - spender, - nonce, - deadline, - }, - primaryType: 'PermitTransferFrom', - }, - permitData: { - token, - amount: BigInt(amount), - nonce, - deadline, - }, - }; - } - - async prepareBatchPermitData({ - appId, - chainId, - spender, - tokens, - signerAddress, - signatureValidFor, - }: GenericBatchPermitParams): Promise { - const nonce = await this.calculateNonce({ chainId, appId, user: signerAddress }); - const deadline = BigInt(calculateDeadline(signatureValidFor)); - return { - dataToSign: { - types: PERMIT2_BATCH_TRANSFER_FROM_TYPES, - domain: { - name: 'Permit2', - chainId, - verifyingContract: this.permit2Contract.address(chainId), - }, - message: { - permitted: Object.entries(tokens).map(([token, amount]) => ({ token, amount: BigInt(amount) })), - spender, - nonce, - deadline, - }, - primaryType: 'PermitBatchTransferFrom', - }, - permitData: { - nonce, - deadline, - tokens: Object.entries(tokens).map(([token, amount]) => ({ token, amount: BigInt(amount) })), - }, - }; - } -} - -function findUnusedBit(value: bigint) { - const binaryString = value.toString(2).padStart(256, '0'); - for (let i = 0; i < 256; i++) { - if (binaryString[binaryString.length - 1 - i] === '0') { - return BigInt(i); - } - } - throw new Error('Expected to find an unused bit'); -} diff --git a/src/services/permit2/types.ts b/src/services/permit2/types.ts deleted file mode 100644 index 6e8c58f3..00000000 --- a/src/services/permit2/types.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { Address, BigIntish, ChainId, ContractCall, SupportInChain, TimeString, TokenAddress, BuiltTransaction } from '@types'; -import { PERMIT2_BATCH_TRANSFER_FROM_TYPES, PERMIT2_TRANSFER_FROM_TYPES } from './utils/eip712-types'; -import { - CompareQuotesBy, - CompareQuotesUsing, - EstimatedQuoteRequest, - EstimatedQuoteResponse, - SourceId, - SourceMetadata, - QuoteTransaction, -} from '@services/quotes'; -import { SupportedGasValues } from '@services/gas/types'; -import { IgnoreFailedResponses, QuoteResponseWithTx } from '@services/quotes/types'; -import { Contract } from '@shared/contracts'; - -export type IPermit2Service = { - permit2Contract: Contract; - arbitrary: IPermit2ArbitraryService; - quotes: IPermit2QuoteService; - calculateNonce(params: { chainId: ChainId; appId: BigIntish; user: Address }): Promise; - preparePermitData(params: GenericSinglePermitParams): Promise; - prepareBatchPermitData(params: GenericBatchPermitParams): Promise; -}; - -export type IPermit2ArbitraryService = { - permit2AdapterContract: Contract; - preparePermitData(params: SinglePermitParams): Promise; - prepareBatchPermitData(params: BatchPermitParams): Promise; - buildArbitraryCallWithPermit(params: ArbitraryCallWithPermitParams): BuiltTransaction; - buildArbitraryCallWithBatchPermit(params: ArbitraryCallWithBatchPermitParams): BuiltTransaction; - buildArbitraryCallWithoutPermit(params: ArbitraryCallWithoutPermitParams): BuiltTransaction; -}; - -export type EstimatedQuoteResponseWithTx = EstimatedQuoteResponse<{ estimatedTx: QuoteTransaction }>; -export type IPermit2QuoteService = { - permit2AdapterContract: Contract; - preparePermitData(params: SinglePermitParams): Promise; - supportedSources(): Record; - supportedChains(): ChainId[]; - supportedSourcesInChain(_: { chainId: ChainId }): Record; - supportedGasSpeeds(): Record>; - estimateQuotes(_: { - request: EstimatedQuoteRequest; - config?: { timeout?: TimeString }; - }): Record>; - estimateAllQuotes(_: { - request: EstimatedQuoteRequest; - config?: { - ignoredFailed?: IgnoreFailed; - sort?: { - by: CompareQuotesBy; - using?: CompareQuotesUsing; - }; - timeout?: TimeString; - }; - }): Promise[]>; - buildAndSimulateQuotes( - _: { - chainId: ChainId; - quotes: EstimatedQuoteResponseWithTx[]; - takerAddress: Address; - recipient?: Address; - config?: { - ignoredFailed?: IgnoreFailed; - sort?: { - by: CompareQuotesBy; - using?: CompareQuotesUsing; - }; - }; - } & ( - | { permitData: PermitData['permitData'] & { signature: string }; txValidFor?: undefined } - | { txValidFor?: TimeString; permitData?: undefined } - ) - ): Promise[]>; -}; - -export type SinglePermitParams = { - appId: BigIntish; - chainId: ChainId; - signerAddress: Address; - token: TokenAddress; - amount: BigIntish; - signatureValidFor: TimeString; -}; -export type GenericSinglePermitParams = { spender: Address } & SinglePermitParams; - -export type BatchPermitParams = { - appId: BigIntish; - chainId: ChainId; - signerAddress: Address; - tokens: Record; - signatureValidFor: TimeString; -}; -export type GenericBatchPermitParams = { spender: Address } & BatchPermitParams; - -export type PermitData = { - dataToSign: { - types: typeof PERMIT2_TRANSFER_FROM_TYPES; - domain: Domain; - message: { - permitted: { - token: TokenAddress; - amount: bigint; - }; - spender: Address; - nonce: bigint; - deadline: bigint; - }; - primaryType: 'PermitTransferFrom'; - }; - permitData: { - token: Address; - amount: bigint; - nonce: bigint; - deadline: bigint; - }; -}; - -export type BatchPermitData = { - dataToSign: { - types: typeof PERMIT2_BATCH_TRANSFER_FROM_TYPES; - domain: Domain; - message: { - permitted: { - token: TokenAddress; - amount: bigint; - }[]; - spender: Address; - nonce: bigint; - deadline: bigint; - }; - primaryType: 'PermitBatchTransferFrom'; - }; - permitData: { - tokens: { token: TokenAddress; amount: bigint }[]; - nonce: bigint; - deadline: bigint; - }; -}; - -type Domain = { - name: 'Permit2'; - verifyingContract: Address; - chainId: ChainId; -}; - -export type ArbitraryCallWithPermitParams = BaseArbitraryCallParams & { - permitData: { - token: TokenAddress; - amount: BigIntish; - }; -}; - -export type ArbitraryCallWithBatchPermitParams = BaseArbitraryCallParams & { - permitData: { tokens: { token: TokenAddress; amount: BigIntish }[] }; -}; - -export type BaseArbitraryCallParams = { - permitData: { - nonce: BigIntish; - signature: string; - deadline: BigIntish; - }; - allowanceTargets?: { token: TokenAddress; target: Address }[]; - calls: GenericContractCall[]; - distribution?: Record; - chainId: ChainId; -}; - -export type ArbitraryCallWithoutPermitParams = { - calls: GenericContractCall[]; - txValidFor: TimeString; - allowanceTargets?: { token: TokenAddress; target: Address }[]; - distribution?: Record; - chainId: ChainId; -}; - -export type GenericContractCall = (EncodedContractCall | ContractCall) & { value?: BigIntish }; -export type DistributionTarget = { recipient: Address; shareBps: number }; -type EncodedContractCall = { to: Address; data: string }; diff --git a/src/services/permit2/utils/config.ts b/src/services/permit2/utils/config.ts deleted file mode 100644 index 5a757084..00000000 --- a/src/services/permit2/utils/config.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Chains } from '@chains'; -import { Contract } from '@shared/contracts'; - -export const PERMIT2_CONTRACT = Contract.with({ defaultAddress: '0x000000000022d473030f116ddee9f6b43ac78ba3' }).build(); -export const PERMIT2_ADAPTER_CONTRACT = Contract.with({ defaultAddress: '0xED306e38BB930ec9646FF3D917B2e513a97530b1' }) - .and({ address: '0xd4c28318bf51e823bAE1C4FEC562b80C53E66467', onChain: Chains.MANTLE }) - .and({ address: '0xd4c28318bf51e823bAE1C4FEC562b80C53E66467', onChain: Chains.CRONOS }) - .and({ address: '0xd4c28318bf51e823bAE1C4FEC562b80C53E66467', onChain: Chains.SONIC }) - .build(); -export const WORDS_FOR_NONCE_CALCULATION = 10; -export const PERMIT2_SUPPORTED_CHAINS = [ - Chains.ETHEREUM, - Chains.POLYGON, - Chains.BNB_CHAIN, - Chains.AVALANCHE, - Chains.FANTOM, - Chains.ARBITRUM, - Chains.OPTIMISM, - Chains.BASE, - Chains.MOONRIVER, - Chains.MOONBEAM, - Chains.FUSE, - Chains.EVMOS, - Chains.CELO, - Chains.GNOSIS, - Chains.KAVA, - Chains.POLYGON_ZKEVM, - Chains.OKC, - Chains.LINEA, - Chains.ROOTSTOCK, - Chains.BLAST, - Chains.SCROLL, - Chains.MODE, - Chains.MANTLE, - Chains.CRONOS, - Chains.SONIC, -].map(({ chainId }) => chainId); diff --git a/src/services/permit2/utils/eip712-types.ts b/src/services/permit2/utils/eip712-types.ts deleted file mode 100644 index ae31a6ba..00000000 --- a/src/services/permit2/utils/eip712-types.ts +++ /dev/null @@ -1,25 +0,0 @@ -export const PERMIT2_TRANSFER_FROM_TYPES = { - PermitTransferFrom: [ - { type: 'TokenPermissions', name: 'permitted' }, - { type: 'address', name: 'spender' }, - { type: 'uint256', name: 'nonce' }, - { type: 'uint256', name: 'deadline' }, - ], - TokenPermissions: [ - { type: 'address', name: 'token' }, - { type: 'uint256', name: 'amount' }, - ], -}; - -export const PERMIT2_BATCH_TRANSFER_FROM_TYPES = { - PermitBatchTransferFrom: [ - { type: 'TokenPermissions[]', name: 'permitted' }, - { type: 'address', name: 'spender' }, - { type: 'uint256', name: 'nonce' }, - { type: 'uint256', name: 'deadline' }, - ], - TokenPermissions: [ - { type: 'address', name: 'token' }, - { type: 'uint256', name: 'amount' }, - ], -}; diff --git a/src/services/prices/price-sources/alchemy-price-source.ts b/src/services/prices/price-sources/alchemy-price-source.ts index e956fe49..0c06cdce 100644 --- a/src/services/prices/price-sources/alchemy-price-source.ts +++ b/src/services/prices/price-sources/alchemy-price-source.ts @@ -103,11 +103,7 @@ export class AlchemyPriceSource implements IPriceSource { body: JSON.stringify({ addresses: chunk.map((address) => ({ network: ALCHEMY_NETWORKS[chainId].key, - // Alchemy doesn't support native tokens (only on Ethereum), so we use the wrapped native token - address: - isSameAddress(address, Addresses.NATIVE_TOKEN) && chainId !== Chains.ETHEREUM.chainId - ? getChainByKeyOrFail(chainId).wToken - : address, + address: isSameAddress(address, Addresses.NATIVE_TOKEN) ? Addresses.ZERO_ADDRESS : address, })), }), timeout, diff --git a/src/services/quotes/quote-sources/oku-quote-source.ts b/src/services/quotes/quote-sources/oku-quote-source.ts deleted file mode 100644 index 93939ee9..00000000 --- a/src/services/quotes/quote-sources/oku-quote-source.ts +++ /dev/null @@ -1,280 +0,0 @@ -import { Address as ViemAddress, encodeFunctionData, formatUnits, parseUnits } from 'viem'; -import { Address, ChainId, TimeString, TokenAddress } from '@types'; -import { Chains, getChainByKey } from '@chains'; -import { Addresses } from '@shared/constants'; -import { GasPrice } from '@services/gas'; -import { calculateDeadline, isSameAddress } from '@shared/utils'; -import { BuildTxParams, QuoteParams, QuoteSourceMetadata, SourceQuoteResponse, SourceQuoteTransaction } from './types'; -import { addQuoteSlippage, calculateAllowanceTarget, failed } from './utils'; -import { AlwaysValidConfigAndContextSource } from './base/always-valid-source'; -import { PERMIT2_ADAPTER_CONTRACT } from '@services/permit2/utils/config'; -import { Contract } from '@shared/contracts'; - -const SWAP_PROXY_CONTRACT = Contract.with({ defaultAddress: '0xaE382fb775c05130fED953DA2Ee00600470170Dc' }).build(); - -const CHAINS: Record = { - // [Chains.ARBITRUM.chainId]: 'arbitrum', - // [Chains.BASE.chainId]: 'base', - // [Chains.BOBA.chainId]: 'boba', - // [Chains.BNB_CHAIN.chainId]: 'bsc', - // [Chains.ETHEREUM.chainId]: 'ethereum', - // [Chains.MOONBEAM.chainId]: 'moonbeam', - [Chains.OPTIMISM.chainId]: 'optimism', - [Chains.POLYGON.chainId]: 'polygon', - // [Chains.POLYGON_ZKEVM.chainId]: 'polygon-zkevm', - [Chains.ROOTSTOCK.chainId]: 'rootstock', - // [Chains.ZKSYNC.chainId]: "zksync", - // [Chains.SCROLL.chainId]: "scroll", -}; - -const OKU_METADATA: QuoteSourceMetadata = { - name: 'Oku', - supports: { - chains: Object.keys(CHAINS).map(Number), - swapAndTransfer: false, - buyOrders: true, - }, - logoURI: 'ipfs://QmS2Kf7sZz7DrcwWU9nNG8eGt2126G2p2c9PTDFT774sW7', -}; -type OkuSupport = { buyOrders: true; swapAndTransfer: false }; -type OkuConfig = {}; -type OkuData = { - coupon: any; - signingRequest: any; - txValidFor: TimeString | undefined; - takeFrom: Address; -}; -// Note: Oku is actually an API that finds routes in Uniswap. The thing is that they have integrated with -// the Universal Router, which required Permit2 to work. Our quote sources can't work directly with Permit2 -// so we've built a new contract called SwapProxy, that can be used to provide ERC20 approval features to -// a contract. The way it works, the SwapProxy will take funds from the caller and send them to the -// Permit2Adapter, which will execute the swap. Take into consideration that we are using this contract because -// it allows arbitrary calls, not because we actually use anything related to Permit2. -export class OkuQuoteSource extends AlwaysValidConfigAndContextSource { - getMetadata() { - return OKU_METADATA; - } - - async quote({ - components: { fetchService }, - request: { - chainId, - sellToken, - buyToken, - order, - config: { slippagePercentage, timeout, txValidFor }, - accounts: { takeFrom }, - external, - }, - }: QuoteParams): Promise> { - const chain = getChainByKey(chainId); - if (chain && isSameAddress(chain.wToken, sellToken) && isSameAddress(Addresses.NATIVE_TOKEN, buyToken)) - throw new Error(`Native token unwrap not supported by this source`); - if (chain && isSameAddress(Addresses.NATIVE_TOKEN, sellToken) && isSameAddress(chain.wToken, buyToken)) - throw new Error(`Native token wrap not supported by this source`); - - const [gasPrice, tokenData] = await Promise.all([external.gasPrice.request(), external.tokenData.request()]); - const body = { - chain: CHAINS[chainId], - account: takeFrom, - gasPrice: Number(eip1159ToLegacy(gasPrice)), - isExactIn: order.type === 'sell', - inTokenAddress: mapToken(sellToken), - outTokenAddress: mapToken(buyToken), - slippage: slippagePercentage * 100, - ...(order.type === 'sell' - ? { inTokenAmount: formatUnits(order.sellAmount, tokenData.sellToken.decimals) } - : { outTokenAmount: formatUnits(order.buyAmount, tokenData.buyToken.decimals) }), - }; - const quoteResponse = await fetchService.fetch('https://canoe.icarus.tools/market/usor/swap_quote', { - method: 'POST', - body: JSON.stringify(body), - headers: { 'Content-Type': 'application/json' }, - timeout, - }); - if (!quoteResponse.ok) { - failed(OKU_METADATA, chainId, sellToken, buyToken, await quoteResponse.text()); - } - const { coupon, inAmount, outAmount, signingRequest } = await quoteResponse.json(); - const sellAmount = parseUnits(inAmount, tokenData.sellToken.decimals); - const buyAmount = parseUnits(outAmount, tokenData.buyToken.decimals); - const quote = { - sellAmount, - buyAmount, - type: order.type, - allowanceTarget: calculateAllowanceTarget(sellToken, SWAP_PROXY_CONTRACT.address(chainId)), - customData: { - coupon, - signingRequest, - txValidFor, - takeFrom, - }, - }; - return addQuoteSlippage(quote, order.type, slippagePercentage); - } - - async buildTx({ - components: { fetchService }, - request: { - chainId, - sellToken, - buyToken, - maxSellAmount, - type, - config: { timeout }, - customData: { txValidFor, coupon, signingRequest, takeFrom }, - }, - }: BuildTxParams): Promise { - const executionResponse = await fetchService.fetch('https://canoe.icarus.tools/market/usor/execution_information', { - method: 'POST', - body: JSON.stringify({ - coupon, - signingRequest: signingRequest - ? { - ...signingRequest, - permitSignature: [ - { - ...signingRequest.permitSignature[0], - signature: '0x0000000000000000000000000000000000000000000000000000000000000001', - }, - ], - } - : undefined, - }), - headers: { 'Content-Type': 'application/json' }, - timeout, - }); - if (!executionResponse.ok) { - failed(OKU_METADATA, chainId, sellToken, buyToken, await executionResponse.text()); - } - const { - trade: { data, to, value }, - approvals, - } = await executionResponse.json(); - - const deadline = BigInt(calculateDeadline(txValidFor) ?? calculateDeadline('1w')); - const tokenOut = - type === 'sell' || isSameAddress(takeFrom, PERMIT2_ADAPTER_CONTRACT.address(chainId)) - ? [] - : [{ token: mapToken(sellToken), distribution: [{ recipient: takeFrom as ViemAddress, shareBps: 0n }] }]; - const adapterData = encodeFunctionData({ - abi: PERMIT2_ADAPTER_ABI, - functionName: 'executeWithBatchPermit', - args: [ - { tokens: [], nonce: 0n, signature: '0x' }, // There is nothing to take from the caller, since the swap proxy will already send it to the contract - approvals?.map((approval: { address: Address; approvee: Address }) => ({ - token: approval.address, - allowanceTarget: approval.approvee, - })) ?? [], - [{ target: to, data, value: BigInt(value ?? 0) }], - tokenOut, - deadline, - ], - }); - const swapProxyData = encodeFunctionData({ - abi: SWAP_PROXY_ABI, - functionName: 'swap', - args: [mapToken(sellToken), maxSellAmount, adapterData], - }); - - return { - to: SWAP_PROXY_CONTRACT.address(chainId), - calldata: swapProxyData, - value: BigInt(value ?? 0), - }; - } -} - -function mapToken(address: TokenAddress) { - return isSameAddress(address, Addresses.NATIVE_TOKEN) ? Addresses.ZERO_ADDRESS : (address as ViemAddress); -} - -function eip1159ToLegacy(gasPrice: GasPrice): bigint { - if ('gasPrice' in gasPrice) { - return BigInt(gasPrice.gasPrice); - } - return BigInt(gasPrice.maxFeePerGas); -} - -const SWAP_PROXY_ABI = [ - { - inputs: [ - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'bytes', name: 'data', type: 'bytes' }, - ], - name: 'swap', - outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }], - stateMutability: 'payable', - type: 'function', - }, -] as const; - -const PERMIT2_ADAPTER_ABI = [ - { - inputs: [ - { - components: [ - { - components: [ - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - ], - internalType: 'struct IPermit2.TokenPermissions[]', - name: 'tokens', - type: 'tuple[]', - }, - { internalType: 'uint256', name: 'nonce', type: 'uint256' }, - { internalType: 'bytes', name: 'signature', type: 'bytes' }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.BatchPermit', - name: '_batchPermit', - type: 'tuple', - }, - { - components: [ - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'address', name: 'allowanceTarget', type: 'address' }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.AllowanceTarget[]', - name: '_allowanceTargets', - type: 'tuple[]', - }, - { - components: [ - { internalType: 'address', name: 'target', type: 'address' }, - { internalType: 'bytes', name: 'data', type: 'bytes' }, - { internalType: 'uint256', name: 'value', type: 'uint256' }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.ContractCall[]', - name: '_contractCalls', - type: 'tuple[]', - }, - { - components: [ - { internalType: 'address', name: 'token', type: 'address' }, - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'uint256', name: 'shareBps', type: 'uint256' }, - ], - internalType: 'struct Token.DistributionTarget[]', - name: 'distribution', - type: 'tuple[]', - }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.TransferOut[]', - name: '_transferOut', - type: 'tuple[]', - }, - { internalType: 'uint256', name: '_deadline', type: 'uint256' }, - ], - name: 'executeWithBatchPermit', - outputs: [ - { internalType: 'bytes[]', name: '_executionResults', type: 'bytes[]' }, - { internalType: 'uint256[]', name: '_tokenBalances', type: 'uint256[]' }, - ], - stateMutability: 'payable', - type: 'function', - }, -] as const; diff --git a/src/services/quotes/source-registry.ts b/src/services/quotes/source-registry.ts index 32ef8f72..1872f001 100644 --- a/src/services/quotes/source-registry.ts +++ b/src/services/quotes/source-registry.ts @@ -19,7 +19,6 @@ import { XYFinanceQuoteSource } from './quote-sources/xy-finance-quote-source'; import { FlyTradeQuoteSource } from './quote-sources/fly-trade-quote-source'; import { SquidQuoteSource } from './quote-sources/squid-quote-source'; import { ConveyorQuoteSource } from './quote-sources/conveyor-quote-source'; -import { OkuQuoteSource } from './quote-sources/oku-quote-source'; import { EnsoQuoteSource } from './quote-sources/enso-quote-source'; import { BrainDexQuoteSource } from './quote-sources/braindex-quote-source'; import { SovrynQuoteSource } from './quote-sources/sovryn-quote-source'; @@ -46,7 +45,6 @@ export const QUOTE_SOURCES = { rango: new RangoQuoteSource(), changelly: new ChangellyQuoteSource(), balmy: new BalmyQuoteSource(), - oku: new OkuQuoteSource(), ['fly-trade']: new FlyTradeQuoteSource(), squid: new SquidQuoteSource(), 'portals-fi': new PortalsFiQuoteSource(), diff --git a/src/shared/abis/companion.ts b/src/shared/abis/companion.ts deleted file mode 100644 index d6ebe9ff..00000000 --- a/src/shared/abis/companion.ts +++ /dev/null @@ -1,223 +0,0 @@ -export default [ - { - inputs: [ - { internalType: 'contract IDCAHub', name: '_hub', type: 'address' }, - { internalType: 'address', name: '_from', type: 'address' }, - { internalType: 'address', name: '_to', type: 'address' }, - { internalType: 'uint32', name: '_amountOfSwaps', type: 'uint32' }, - { internalType: 'uint32', name: '_swapInterval', type: 'uint32' }, - { internalType: 'address', name: '_owner', type: 'address' }, - { - components: [ - { internalType: 'address', name: 'operator', type: 'address' }, - { internalType: 'enum IDCAPermissionManager.Permission[]', name: 'permissions', type: 'uint8[]' }, - ], - internalType: 'struct IDCAPermissionManager.PermissionSet[]', - name: '_permissions', - type: 'tuple[]', - }, - { internalType: 'bytes', name: '_miscellaneous', type: 'bytes' }, - ], - name: 'depositWithBalanceOnContract', - outputs: [{ internalType: 'uint256', name: '_positionId', type: 'uint256' }], - stateMutability: 'payable', - type: 'function', - }, - - { - inputs: [ - { internalType: 'contract IDCAHub', name: '_hub', type: 'address' }, - { internalType: 'uint256', name: '_positionId', type: 'uint256' }, - { internalType: 'uint32', name: '_newSwaps', type: 'uint32' }, - ], - name: 'increasePositionWithBalanceOnContract', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [{ internalType: 'bytes[]', name: '_data', type: 'bytes[]' }], - name: 'multicall', - outputs: [{ internalType: 'bytes[]', name: '_results', type: 'bytes[]' }], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [], - name: 'pendingGovernor', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IDCAPermissionManager', name: '_permissionManager', type: 'address' }, - { - components: [ - { internalType: 'address', name: 'operator', type: 'address' }, - { internalType: 'enum IDCAPermissionManager.Permission[]', name: 'permissions', type: 'uint8[]' }, - ], - internalType: 'struct IDCAPermissionManager.PermissionSet[]', - name: '_permissions', - type: 'tuple[]', - }, - { internalType: 'uint256', name: '_tokenId', type: 'uint256' }, - { internalType: 'uint256', name: '_deadline', type: 'uint256' }, - { internalType: 'uint8', name: '_v', type: 'uint8' }, - { internalType: 'bytes32', name: '_r', type: 'bytes32' }, - { internalType: 'bytes32', name: '_s', type: 'bytes32' }, - ], - name: 'permissionPermit', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'address', name: '_token', type: 'address' }, - { internalType: 'uint256', name: '_amount', type: 'uint256' }, - { internalType: 'uint256', name: '_nonce', type: 'uint256' }, - { internalType: 'uint256', name: '_deadline', type: 'uint256' }, - { internalType: 'bytes', name: '_signature', type: 'bytes' }, - { internalType: 'address', name: '_recipient', type: 'address' }, - ], - name: 'permitTakeFromCaller', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IDCAHub', name: '_hub', type: 'address' }, - { internalType: 'uint256', name: '_positionId', type: 'uint256' }, - { internalType: 'uint256', name: '_amount', type: 'uint256' }, - { internalType: 'uint32', name: '_newSwaps', type: 'uint32' }, - { internalType: 'address', name: '_recipient', type: 'address' }, - ], - name: 'reducePosition', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'address', name: '_allowanceToken', type: 'address' }, - { internalType: 'uint256', name: '_value', type: 'uint256' }, - { internalType: 'bytes', name: '_swapData', type: 'bytes' }, - { internalType: 'address', name: '_tokenOut', type: 'address' }, - ], - name: 'runSwap', - outputs: [{ internalType: 'uint256', name: '_amountOut', type: 'uint256' }], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IDCAHub', name: '_hub', type: 'address' }, - { - components: [ - { internalType: 'address', name: 'tokenA', type: 'address' }, - { internalType: 'address', name: 'tokenB', type: 'address' }, - ], - internalType: 'struct Pair[]', - name: '_pairs', - type: 'tuple[]', - }, - { internalType: 'bool', name: '_calculatePrivilegedAvailability', type: 'bool' }, - ], - name: 'secondsUntilNextSwap', - outputs: [{ internalType: 'uint256[]', name: '', type: 'uint256[]' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { internalType: 'address', name: '_token', type: 'address' }, - { internalType: 'address', name: '_recipient', type: 'address' }, - ], - name: 'sendBalanceOnContractToRecipient', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'address', name: '_newSwapper', type: 'address' }, - { internalType: 'address', name: '_newAllowanceTarget', type: 'address' }, - ], - name: 'setSwapper', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [{ internalType: 'bytes[]', name: '_calls', type: 'bytes[]' }], - name: 'simulate', - outputs: [ - { - components: [ - { internalType: 'bool', name: 'success', type: 'bool' }, - { internalType: 'bytes', name: 'result', type: 'bytes' }, - { internalType: 'uint256', name: 'gasSpent', type: 'uint256' }, - ], - internalType: 'struct ISimulationAdapter.SimulationResult[]', - name: '_results', - type: 'tuple[]', - }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [{ internalType: 'bytes', name: '_call', type: 'bytes' }], - name: 'simulateAndRevert', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [{ internalType: 'bytes4', name: '_interfaceId', type: 'bytes4' }], - name: 'supportsInterface', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'view', - type: 'function', - }, - { inputs: [], name: 'swapper', outputs: [{ internalType: 'address', name: '', type: 'address' }], stateMutability: 'view', type: 'function' }, - { - inputs: [ - { internalType: 'contract IERC20', name: '_token', type: 'address' }, - { internalType: 'uint256', name: '_amount', type: 'uint256' }, - { internalType: 'address', name: '_recipient', type: 'address' }, - ], - name: 'takeFromCaller', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IDCAHub', name: '_hub', type: 'address' }, - { internalType: 'uint256', name: '_positionId', type: 'uint256' }, - { internalType: 'address', name: '_recipientUnswapped', type: 'address' }, - { internalType: 'address', name: '_recipientSwapped', type: 'address' }, - ], - name: 'terminate', - outputs: [ - { internalType: 'uint256', name: '_unswapped', type: 'uint256' }, - { internalType: 'uint256', name: '_swapped', type: 'uint256' }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IDCAHub', name: '_hub', type: 'address' }, - { internalType: 'uint256', name: '_positionId', type: 'uint256' }, - { internalType: 'address', name: '_recipient', type: 'address' }, - ], - name: 'withdrawSwapped', - outputs: [{ internalType: 'uint256', name: '_swapped', type: 'uint256' }], - stateMutability: 'payable', - type: 'function', - }, -] as const; diff --git a/src/shared/abis/dca-hub.ts b/src/shared/abis/dca-hub.ts deleted file mode 100644 index 128e62fb..00000000 --- a/src/shared/abis/dca-hub.ts +++ /dev/null @@ -1,234 +0,0 @@ -export default [ - { - inputs: [ - { - internalType: 'address', - name: '_from', - type: 'address', - }, - { - internalType: 'address', - name: '_to', - type: 'address', - }, - { - internalType: 'uint256', - name: '_amount', - type: 'uint256', - }, - { - internalType: 'uint32', - name: '_amountOfSwaps', - type: 'uint32', - }, - { - internalType: 'uint32', - name: '_swapInterval', - type: 'uint32', - }, - { - internalType: 'address', - name: '_owner', - type: 'address', - }, - { - components: [ - { - internalType: 'address', - name: 'operator', - type: 'address', - }, - { - internalType: 'enum IDCAPermissionManager.Permission[]', - name: 'permissions', - type: 'uint8[]', - }, - ], - internalType: 'struct IDCAPermissionManager.PermissionSet[]', - name: '_permissions', - type: 'tuple[]', - }, - ], - name: 'deposit', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, - - { - inputs: [ - { - internalType: 'uint256', - name: '_positionId', - type: 'uint256', - }, - { - internalType: 'uint256', - name: '_amount', - type: 'uint256', - }, - { - internalType: 'uint32', - name: '_newAmountOfSwaps', - type: 'uint32', - }, - ], - name: 'increasePosition', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint256', - name: '_positionId', - type: 'uint256', - }, - { - internalType: 'uint256', - name: '_amount', - type: 'uint256', - }, - { - internalType: 'uint32', - name: '_newAmountOfSwaps', - type: 'uint32', - }, - { - internalType: 'address', - name: '_recipient', - type: 'address', - }, - ], - name: 'reducePosition', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint256', - name: '_positionId', - type: 'uint256', - }, - { - internalType: 'address', - name: '_recipientUnswapped', - type: 'address', - }, - { - internalType: 'address', - name: '_recipientSwapped', - type: 'address', - }, - ], - name: 'terminate', - outputs: [ - { - internalType: 'uint256', - name: '_unswapped', - type: 'uint256', - }, - { - internalType: 'uint256', - name: '_swapped', - type: 'uint256', - }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint256', - name: '_positionId', - type: 'uint256', - }, - ], - name: 'userPosition', - outputs: [ - { - components: [ - { - internalType: 'contract IERC20Metadata', - name: 'from', - type: 'address', - }, - { - internalType: 'contract IERC20Metadata', - name: 'to', - type: 'address', - }, - { - internalType: 'uint32', - name: 'swapInterval', - type: 'uint32', - }, - { - internalType: 'uint32', - name: 'swapsExecuted', - type: 'uint32', - }, - { - internalType: 'uint256', - name: 'swapped', - type: 'uint256', - }, - { - internalType: 'uint32', - name: 'swapsLeft', - type: 'uint32', - }, - { - internalType: 'uint256', - name: 'remaining', - type: 'uint256', - }, - { - internalType: 'uint120', - name: 'rate', - type: 'uint120', - }, - ], - internalType: 'struct IDCAHubPositionHandler.UserPosition', - name: '_userPosition', - type: 'tuple', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint256', - name: '_positionId', - type: 'uint256', - }, - { - internalType: 'address', - name: '_recipient', - type: 'address', - }, - ], - name: 'withdrawSwapped', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, -] as const; diff --git a/src/shared/abis/earn-delayed-withdrawal-manager.ts b/src/shared/abis/earn-delayed-withdrawal-manager.ts deleted file mode 100644 index 89b3697e..00000000 --- a/src/shared/abis/earn-delayed-withdrawal-manager.ts +++ /dev/null @@ -1,33 +0,0 @@ -export default [ - { - inputs: [ - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'address', name: 'token', type: 'address' }, - ], - name: 'withdrawableFunds', - outputs: [{ internalType: 'uint256', name: 'funds', type: 'uint256' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'address', name: 'recipient', type: 'address' }, - ], - name: 'withdraw', - outputs: [ - { internalType: 'uint256', name: 'withdrawn', type: 'uint256' }, - { internalType: 'uint256', name: 'stillPending', type: 'uint256' }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [{ internalType: 'bytes[]', name: 'data', type: 'bytes[]' }], - name: 'multicall', - outputs: [{ internalType: 'bytes[]', name: 'results', type: 'bytes[]' }], - stateMutability: 'payable', - type: 'function', - }, -] as const; diff --git a/src/shared/abis/earn-strategy-router.ts b/src/shared/abis/earn-strategy-router.ts deleted file mode 100644 index fbd5f2dc..00000000 --- a/src/shared/abis/earn-strategy-router.ts +++ /dev/null @@ -1,24 +0,0 @@ -export default [ - { - inputs: [ - { internalType: 'contract IEarnVault', name: 'vault', type: 'address' }, - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'bytes', name: 'data', type: 'bytes' }, - ], - name: 'routeByPositionId', - outputs: [{ internalType: 'bytes', name: 'result', type: 'bytes' }], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IEarnStrategyRegistry', name: 'registry', type: 'address' }, - { internalType: 'StrategyId', name: 'strategyId', type: 'uint96' }, - { internalType: 'bytes', name: 'data', type: 'bytes' }, - ], - name: 'routeByStrategyId', - outputs: [{ internalType: 'bytes', name: 'result', type: 'bytes' }], - stateMutability: 'payable', - type: 'function', - }, -] as const; diff --git a/src/shared/abis/earn-strategy.ts b/src/shared/abis/earn-strategy.ts deleted file mode 100644 index bcfab83b..00000000 --- a/src/shared/abis/earn-strategy.ts +++ /dev/null @@ -1,28 +0,0 @@ -export default [ - { inputs: [], name: 'asset', outputs: [{ internalType: 'address', name: '', type: 'address' }], stateMutability: 'view', type: 'function' }, - { - inputs: [], - name: 'supportedDepositTokens', - outputs: [{ internalType: 'address[]', name: '', type: 'address[]' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'SpecialWithdrawalCode', name: 'withdrawalCode', type: 'uint256' }, - { internalType: 'uint256[]', name: 'toWithdraw', type: 'uint256[]' }, - { internalType: 'bytes', name: 'withdrawalData', type: 'bytes' }, - { internalType: 'address', name: 'recipient', type: 'address' }, - ], - name: 'specialWithdraw', - outputs: [ - { internalType: 'uint256[]', name: 'balanceChanges', type: 'uint256[]' }, - { internalType: 'address[]', name: 'actualWithdrawnTokens', type: 'address[]' }, - { internalType: 'uint256[]', name: 'actualWithdrawnAmounts', type: 'uint256[]' }, - { internalType: 'bytes', name: 'result', type: 'bytes' }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, -] as const; diff --git a/src/shared/abis/earn-vault-companion.ts b/src/shared/abis/earn-vault-companion.ts deleted file mode 100644 index 8c41d504..00000000 --- a/src/shared/abis/earn-vault-companion.ts +++ /dev/null @@ -1,210 +0,0 @@ -export default [ - { - inputs: [ - { internalType: 'contract IEarnVault', name: 'vault', type: 'address' }, - { internalType: 'StrategyId', name: 'strategyId', type: 'uint96' }, - { internalType: 'address', name: 'depositToken', type: 'address' }, - { internalType: 'uint256', name: 'depositAmount', type: 'uint256' }, - { internalType: 'address', name: 'owner_', type: 'address' }, - { - components: [ - { internalType: 'address', name: 'operator', type: 'address' }, - { internalType: 'INFTPermissions.Permission[]', name: 'permissions', type: 'uint8[]' }, - ], - internalType: 'struct INFTPermissions.PermissionSet[]', - name: 'permissions', - type: 'tuple[]', - }, - { internalType: 'bytes', name: 'strategyValidationData', type: 'bytes' }, - { internalType: 'bytes', name: 'misc', type: 'bytes' }, - { internalType: 'bool', name: 'maxApprove', type: 'bool' }, - ], - name: 'createPosition', - outputs: [ - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'uint256', name: 'assetsDeposited', type: 'uint256' }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'address', name: 'allowanceToken', type: 'address' }, - { internalType: 'uint256', name: 'value', type: 'uint256' }, - { internalType: 'bytes', name: 'swapData', type: 'bytes' }, - ], - name: 'runSwap', - outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'uint256', name: 'nonce', type: 'uint256' }, - { internalType: 'uint256', name: 'deadline', type: 'uint256' }, - { internalType: 'bytes', name: 'signature', type: 'bytes' }, - { internalType: 'address', name: 'recipient', type: 'address' }, - ], - name: 'permitTakeFromCaller', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IERC20', name: 'token', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'address', name: 'recipient', type: 'address' }, - ], - name: 'takeFromCaller', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [{ internalType: 'bytes[]', name: 'data', type: 'bytes[]' }], - name: 'multicall', - outputs: [{ internalType: 'bytes[]', name: 'results', type: 'bytes[]' }], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IEarnVault', name: 'vault', type: 'address' }, - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'address', name: 'depositToken', type: 'address' }, - { internalType: 'uint256', name: 'depositAmount', type: 'uint256' }, - { internalType: 'bool', name: 'maxApprove', type: 'bool' }, - ], - name: 'increasePosition', - outputs: [{ internalType: 'uint256', name: 'assetsDeposited', type: 'uint256' }], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IEarnVault', name: 'vault', type: 'address' }, - { - components: [ - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { - components: [ - { internalType: 'address', name: 'operator', type: 'address' }, - { internalType: 'INFTPermissions.Permission[]', name: 'permissions', type: 'uint8[]' }, - ], - internalType: 'struct INFTPermissions.PermissionSet[]', - name: 'permissionSets', - type: 'tuple[]', - }, - ], - internalType: 'struct INFTPermissions.PositionPermissions[]', - name: 'permissions', - type: 'tuple[]', - }, - { internalType: 'uint256', name: 'deadline', type: 'uint256' }, - { internalType: 'bytes', name: 'signature', type: 'bytes' }, - ], - name: 'permissionPermit', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IEarnVault', name: 'vault', type: 'address' }, - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'address[]', name: 'tokensToWithdraw', type: 'address[]' }, - { internalType: 'uint256[]', name: 'intendedWithdraw', type: 'uint256[]' }, - { internalType: 'address', name: 'recipient', type: 'address' }, - ], - name: 'withdraw', - outputs: [{ internalType: 'uint256[]', name: '', type: 'uint256[]' }], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IDelayedWithdrawalManager', name: 'manager', type: 'address' }, - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'address', name: 'recipient', type: 'address' }, - ], - name: 'claimDelayedWithdraw', - outputs: [ - { internalType: 'uint256', name: '', type: 'uint256' }, - { internalType: 'uint256', name: '', type: 'uint256' }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'contract IEarnVault', name: 'vault', type: 'address' }, - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'SpecialWithdrawalCode', name: 'withdrawalCode', type: 'uint256' }, - { internalType: 'uint256[]', name: 'toWithdraw', type: 'uint256[]' }, - { internalType: 'bytes', name: 'withdrawalData', type: 'bytes' }, - { internalType: 'address', name: 'recipient', type: 'address' }, - ], - name: 'specialWithdraw', - outputs: [ - { internalType: 'address[]', name: 'tokens', type: 'address[]' }, - { internalType: 'uint256[]', name: 'balanceChanges', type: 'uint256[]' }, - { internalType: 'address[]', name: 'actualWithdrawnTokens', type: 'address[]' }, - { internalType: 'uint256[]', name: 'actualWithdrawnAmounts', type: 'uint256[]' }, - { internalType: 'bytes', name: 'result', type: 'bytes' }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { - components: [ - { internalType: 'uint256', name: 'deadline', type: 'uint256' }, - { internalType: 'bytes32[]', name: 'executionHashes', type: 'bytes32[]' }, - ], - internalType: 'struct Attestation', - name: 'attestation', - type: 'tuple', - }, - { internalType: 'bytes', name: 'attestationSignature', type: 'bytes' }, - { internalType: 'bytes', name: 'data', type: 'bytes' }, - ], - name: 'attestedCall', - outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [{ internalType: 'bytes[]', name: '_calls', type: 'bytes[]' }], - name: 'simulate', - outputs: [ - { - components: [ - { internalType: 'bool', name: 'success', type: 'bool' }, - { internalType: 'bytes', name: 'result', type: 'bytes' }, - { internalType: 'uint256', name: 'gasSpent', type: 'uint256' }, - ], - internalType: 'struct ISimulationAdapter.SimulationResult[]', - name: '_results', - type: 'tuple[]', - }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'address', name: 'recipient', type: 'address' }, - ], - name: 'sendToRecipient', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, -] as const; diff --git a/src/shared/abis/earn-vault.ts b/src/shared/abis/earn-vault.ts deleted file mode 100644 index 12eacfea..00000000 --- a/src/shared/abis/earn-vault.ts +++ /dev/null @@ -1,126 +0,0 @@ -export default [ - { - inputs: [ - { internalType: 'StrategyId', name: 'strategyId', type: 'uint96' }, - { internalType: 'address', name: 'depositToken', type: 'address' }, - { internalType: 'uint256', name: 'depositAmount', type: 'uint256' }, - { internalType: 'address', name: 'owner', type: 'address' }, - { - components: [ - { internalType: 'address', name: 'operator', type: 'address' }, - { internalType: 'INFTPermissions.Permission[]', name: 'permissions', type: 'uint8[]' }, - ], - internalType: 'struct INFTPermissions.PermissionSet[]', - name: 'permissions', - type: 'tuple[]', - }, - { internalType: 'bytes', name: 'strategyValidationData', type: 'bytes' }, - { internalType: 'bytes', name: 'misc', type: 'bytes' }, - ], - name: 'createPosition', - outputs: [ - { internalType: 'uint256', name: '', type: 'uint256' }, - { internalType: 'uint256', name: '', type: 'uint256' }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'address', name: 'depositToken', type: 'address' }, - { internalType: 'uint256', name: 'depositAmount', type: 'uint256' }, - ], - name: 'increasePosition', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [{ internalType: 'uint256', name: 'tokenId', type: 'uint256' }], - name: 'ownerOf', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'address[]', name: 'tokensToWithdraw', type: 'address[]' }, - { internalType: 'uint256[]', name: 'intendedWithdraw', type: 'uint256[]' }, - { internalType: 'address', name: 'recipient', type: 'address' }, - ], - name: 'withdraw', - outputs: [{ internalType: 'uint256[]', name: 'withdrawn', type: 'uint256[]' }], - stateMutability: 'payable', - type: 'function', - }, - { stateMutability: 'payable', type: 'receive' }, - { - inputs: [{ internalType: 'uint256', name: 'positionId', type: 'uint256' }], - name: 'position', - outputs: [ - { internalType: 'address[]', name: '', type: 'address[]' }, - { internalType: 'uint256[]', name: '', type: 'uint256[]' }, - { internalType: 'StrategyId', name: '', type: 'uint96' }, - { internalType: 'contract IEarnStrategy', name: '', type: 'address' }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [{ internalType: 'uint256', name: 'positionId', type: 'uint256' }], - name: 'positionsStrategy', - outputs: [ - { internalType: 'StrategyId', name: 'strategyId', type: 'uint96' }, - { internalType: 'contract IEarnStrategy', name: 'strategy', type: 'address' }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [{ internalType: 'address', name: 'owner', type: 'address' }], - name: 'nextNonce', - outputs: [{ internalType: 'uint256', name: 'nextNonce', type: 'uint256' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { internalType: 'uint256', name: 'positionId', type: 'uint256' }, - { internalType: 'SpecialWithdrawalCode', name: 'withdrawalCode', type: 'uint256' }, - { internalType: 'uint256[]', name: 'toWithdraw', type: 'uint256[]' }, - { internalType: 'bytes', name: 'withdrawalData', type: 'bytes' }, - { internalType: 'address', name: 'recipient', type: 'address' }, - ], - name: 'specialWithdraw', - outputs: [ - { internalType: 'address[]', name: 'tokens', type: 'address[]' }, - { internalType: 'uint256[]', name: 'balanceChanges', type: 'uint256[]' }, - { internalType: 'address[]', name: 'actualWithdrawnTokens', type: 'address[]' }, - { internalType: 'uint256[]', name: 'actualWithdrawnAmounts', type: 'uint256[]' }, - { internalType: 'bytes', name: 'result', type: 'bytes' }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { - components: [ - { internalType: 'uint256', name: 'deadline', type: 'uint256' }, - { internalType: 'bytes32[]', name: 'executionHashes', type: 'bytes32[]' }, - ], - internalType: 'struct Attestation', - name: 'attestation', - type: 'tuple', - }, - { internalType: 'bytes', name: 'attestationSignature', type: 'bytes' }, - { internalType: 'bytes', name: 'data', type: 'bytes' }, - ], - name: 'attestedCall', - outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }], - stateMutability: 'nonpayable', - type: 'function', - }, -] as const; diff --git a/src/shared/abis/erc721.ts b/src/shared/abis/erc721.ts deleted file mode 100644 index fb9cc76d..00000000 --- a/src/shared/abis/erc721.ts +++ /dev/null @@ -1,21 +0,0 @@ -export default [ - { - inputs: [ - { - internalType: 'uint256', - name: 'tokenId', - type: 'uint256', - }, - ], - name: 'ownerOf', - outputs: [ - { - internalType: 'address', - name: 'owner', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, -] as const; diff --git a/src/shared/abis/permit2-adapter.ts b/src/shared/abis/permit2-adapter.ts deleted file mode 100644 index 444cba2e..00000000 --- a/src/shared/abis/permit2-adapter.ts +++ /dev/null @@ -1,222 +0,0 @@ -export default [ - { - inputs: [{ internalType: 'bytes[]', name: '_calls', type: 'bytes[]' }], - name: 'simulate', - outputs: [ - { - components: [ - { internalType: 'bool', name: 'success', type: 'bool' }, - { internalType: 'bytes', name: 'result', type: 'bytes' }, - { internalType: 'uint256', name: 'gasSpent', type: 'uint256' }, - ], - internalType: 'struct ISimulationAdapter.SimulationResult[]', - name: '_results', - type: 'tuple[]', - }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { - components: [ - { internalType: 'uint256', name: 'deadline', type: 'uint256' }, - { internalType: 'address', name: 'tokenIn', type: 'address' }, - { internalType: 'uint256', name: 'amountIn', type: 'uint256' }, - { internalType: 'uint256', name: 'nonce', type: 'uint256' }, - { internalType: 'bytes', name: 'signature', type: 'bytes' }, - { internalType: 'address', name: 'allowanceTarget', type: 'address' }, - { internalType: 'address', name: 'swapper', type: 'address' }, - { internalType: 'bytes', name: 'swapData', type: 'bytes' }, - { internalType: 'address', name: 'tokenOut', type: 'address' }, - { internalType: 'uint256', name: 'minAmountOut', type: 'uint256' }, - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'uint256', name: 'shareBps', type: 'uint256' }, - ], - internalType: 'struct Token.DistributionTarget[]', - name: 'transferOut', - type: 'tuple[]', - }, - { internalType: 'bytes', name: 'misc', type: 'bytes' }, - ], - internalType: 'struct ISwapPermit2Adapter.SellOrderSwapParams', - name: '_params', - type: 'tuple', - }, - ], - name: 'sellOrderSwap', - outputs: [ - { internalType: 'uint256', name: '_amountIn', type: 'uint256' }, - { internalType: 'uint256', name: '_amountOut', type: 'uint256' }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { - components: [ - { internalType: 'uint256', name: 'deadline', type: 'uint256' }, - { internalType: 'address', name: 'tokenIn', type: 'address' }, - { internalType: 'uint256', name: 'maxAmountIn', type: 'uint256' }, - { internalType: 'uint256', name: 'nonce', type: 'uint256' }, - { internalType: 'bytes', name: 'signature', type: 'bytes' }, - { internalType: 'address', name: 'allowanceTarget', type: 'address' }, - { internalType: 'address', name: 'swapper', type: 'address' }, - { internalType: 'bytes', name: 'swapData', type: 'bytes' }, - { internalType: 'address', name: 'tokenOut', type: 'address' }, - { internalType: 'uint256', name: 'amountOut', type: 'uint256' }, - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'uint256', name: 'shareBps', type: 'uint256' }, - ], - internalType: 'struct Token.DistributionTarget[]', - name: 'transferOut', - type: 'tuple[]', - }, - { internalType: 'address', name: 'unspentTokenInRecipient', type: 'address' }, - { internalType: 'bytes', name: 'misc', type: 'bytes' }, - ], - internalType: 'struct ISwapPermit2Adapter.BuyOrderSwapParams', - name: '_params', - type: 'tuple', - }, - ], - name: 'buyOrderSwap', - outputs: [ - { internalType: 'uint256', name: '_amountIn', type: 'uint256' }, - { internalType: 'uint256', name: '_amountOut', type: 'uint256' }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { - components: [ - { - components: [ - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - ], - internalType: 'struct IPermit2.TokenPermissions[]', - name: 'tokens', - type: 'tuple[]', - }, - { internalType: 'uint256', name: 'nonce', type: 'uint256' }, - { internalType: 'bytes', name: 'signature', type: 'bytes' }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.BatchPermit', - name: '_batchPermit', - type: 'tuple', - }, - { - components: [ - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'address', name: 'allowanceTarget', type: 'address' }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.AllowanceTarget[]', - name: '_allowanceTargets', - type: 'tuple[]', - }, - { - components: [ - { internalType: 'address', name: 'target', type: 'address' }, - { internalType: 'bytes', name: 'data', type: 'bytes' }, - { internalType: 'uint256', name: 'value', type: 'uint256' }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.ContractCall[]', - name: '_contractCalls', - type: 'tuple[]', - }, - { - components: [ - { internalType: 'address', name: 'token', type: 'address' }, - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'uint256', name: 'shareBps', type: 'uint256' }, - ], - internalType: 'struct Token.DistributionTarget[]', - name: 'distribution', - type: 'tuple[]', - }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.TransferOut[]', - name: '_transferOut', - type: 'tuple[]', - }, - { internalType: 'uint256', name: '_deadline', type: 'uint256' }, - ], - name: 'executeWithBatchPermit', - outputs: [ - { internalType: 'bytes[]', name: '_executionResults', type: 'bytes[]' }, - { internalType: 'uint256[]', name: '_tokenBalances', type: 'uint256[]' }, - ], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { - components: [ - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'uint256', name: 'nonce', type: 'uint256' }, - { internalType: 'bytes', name: 'signature', type: 'bytes' }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.SinglePermit', - name: '_permit', - type: 'tuple', - }, - { - components: [ - { internalType: 'address', name: 'token', type: 'address' }, - { internalType: 'address', name: 'allowanceTarget', type: 'address' }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.AllowanceTarget[]', - name: '_allowanceTargets', - type: 'tuple[]', - }, - { - components: [ - { internalType: 'address', name: 'target', type: 'address' }, - { internalType: 'bytes', name: 'data', type: 'bytes' }, - { internalType: 'uint256', name: 'value', type: 'uint256' }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.ContractCall[]', - name: '_contractCalls', - type: 'tuple[]', - }, - { - components: [ - { internalType: 'address', name: 'token', type: 'address' }, - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'uint256', name: 'shareBps', type: 'uint256' }, - ], - internalType: 'struct Token.DistributionTarget[]', - name: 'distribution', - type: 'tuple[]', - }, - ], - internalType: 'struct IArbitraryExecutionPermit2Adapter.TransferOut[]', - name: '_transferOut', - type: 'tuple[]', - }, - { internalType: 'uint256', name: '_deadline', type: 'uint256' }, - ], - name: 'executeWithPermit', - outputs: [ - { internalType: 'bytes[]', name: '_executionResults', type: 'bytes[]' }, - { internalType: 'uint256[]', name: '_tokenBalances', type: 'uint256[]' }, - ], - stateMutability: 'payable', - type: 'function', - }, -] as const; diff --git a/src/shared/abis/permit2.ts b/src/shared/abis/permit2.ts deleted file mode 100644 index 4fa408f0..00000000 --- a/src/shared/abis/permit2.ts +++ /dev/null @@ -1,12 +0,0 @@ -export default [ - { - inputs: [ - { internalType: 'address', name: '', type: 'address' }, - { internalType: 'uint256', name: '', type: 'uint256' }, - ], - name: 'nonceBitmap', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function', - }, -] as const; diff --git a/test/integration/services/permit2/permit2-arbitrary-service.spec.ts b/test/integration/services/permit2/permit2-arbitrary-service.spec.ts deleted file mode 100644 index 58b59037..00000000 --- a/test/integration/services/permit2/permit2-arbitrary-service.spec.ts +++ /dev/null @@ -1,231 +0,0 @@ -import ms from 'ms'; -import { expect } from 'chai'; -import { ethers } from 'hardhat'; -import { Chains } from '@chains'; -import { IPermit2ArbitraryService } from '@services/permit2/types'; -import { fork } from '@test-utils/evm'; -import { SnapshotRestorer, takeSnapshot } from '@nomicfoundation/hardhat-network-helpers'; -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; -import { TestToken, approve, balance, loadTokens, mint } from '@test-utils/erc20'; -import { PERMIT2_CONTRACT } from '@services/permit2/utils/config'; -import { Uint } from '@shared/constants'; -import { parseUnits } from 'viem'; -import { buildSDK } from '@builder'; - -jest.retryTimes(3).setTimeout(ms('2m')); - -const APP_ID = '0x000000012345678910'; -const CHAIN = Chains.OPTIMISM; -const VAULT_USDC = '0x81c9a7b55a4df39a9b7b5f781ec0e53539694873'; -const VAULT_WETH = '0xc4d4500326981eacd020e20a81b1c479c161c7ef'; -const AMOUNT_TO_DEPOSIT_USDC = parseUnits('500', 6); -const AMOUNT_TO_DEPOSIT_WETH = parseUnits('1', 18); -const ORIGINAL_AMOUNT_USDC = parseUnits('1000', 6); -const ORIGINAL_AMOUNT_ETH = parseUnits('20', 18); -const ORIGINAL_AMOUNT_WETH = parseUnits('20', 18); - -describe('Permit2 Arbitrary Service', () => { - let nativeToken: TestToken, STABLE_ERC20: TestToken, wToken: TestToken; - let chainId: number; - let arbitrary: IPermit2ArbitraryService; - let user: SignerWithAddress; - let snapshot: SnapshotRestorer; - - beforeAll(async () => { - await fork({ chain: CHAIN, blockNumber: 116816944 }); - chainId = await ethers.provider.getNetwork().then(({ chainId }) => chainId); - [user] = await ethers.getSigners(); - ({ nativeToken, STABLE_ERC20, wToken } = await loadTokens(CHAIN)); - await mint({ amount: ORIGINAL_AMOUNT_ETH, of: nativeToken, to: user }); - await mint({ amount: ORIGINAL_AMOUNT_WETH, of: wToken, to: user }); - await mint({ amount: ORIGINAL_AMOUNT_USDC, of: STABLE_ERC20, to: user }); - await approve({ amount: Uint.MAX_256, to: PERMIT2_CONTRACT.address(chainId), for: STABLE_ERC20, from: user }); - await approve({ amount: Uint.MAX_256, to: PERMIT2_CONTRACT.address(chainId), for: wToken, from: user }); - snapshot = await takeSnapshot(); - arbitrary = buildSDK().permit2Service.arbitrary; - }); - - afterEach(async () => { - await snapshot.restore(); - }); - - it('buildArbitraryCallWithPermit', async () => { - // Prepare data to sign - const { - dataToSign: { domain, types, message }, - permitData, - } = await arbitrary.preparePermitData({ - appId: APP_ID, - chainId: CHAIN.chainId, - signerAddress: user.address, - token: STABLE_ERC20.address, - amount: AMOUNT_TO_DEPOSIT_USDC, - signatureValidFor: '2y', - }); - - // We need to overwrite the chain id so that it matches the fork's id - const newDomain = { ...domain, chainId }; - - // Sign it - const signature = await user._signTypedData(newDomain, types, message); - - // Build tx - const tx = arbitrary.buildArbitraryCallWithPermit({ - // Set permit data - permitData: { ...permitData, signature }, - - // Provide allowance for vault - allowanceTargets: [{ token: STABLE_ERC20.address, target: VAULT_USDC }], - - // Deposit into vault - calls: [ - { - address: VAULT_USDC, - abi: { humanReadable: ERC4626_ABI }, - functionName: 'deposit', - args: [AMOUNT_TO_DEPOSIT_USDC, arbitrary.permit2AdapterContract.address(chainId)], - }, - ], - - chainId, - - // Distribute vault token to user - distribution: { - [VAULT_USDC]: [{ recipient: user.address, shareBps: 10_000 }], - }, - }); - - // Send tx - await user.sendTransaction(tx); - - // Assertions - const usdcBalance = await balance({ of: user.address, for: STABLE_ERC20 }); - const vaultBalance = await balance({ of: VAULT_USDC, for: STABLE_ERC20 }); - expect(usdcBalance).to.equal(ORIGINAL_AMOUNT_USDC - AMOUNT_TO_DEPOSIT_USDC); - expect(vaultBalance).to.be.gt(0); - }); - - it('buildArbitraryCallWithoutPermit', async () => { - const VAULT = '0xc4d4500326981eacd020e20a81b1c479c161c7ef'; - - // Build tx - const tx = arbitrary.buildArbitraryCallWithoutPermit({ - // Provide allowance for vault - allowanceTargets: [{ token: wToken.address, target: VAULT }], - - calls: [ - // Convert ETH to WETH - { - address: wToken.address, - abi: { humanReadable: ['function deposit() payable'] }, - functionName: 'deposit', - args: [], - value: AMOUNT_TO_DEPOSIT_WETH, - }, - - // Deposit into vault - { - address: VAULT, - abi: { humanReadable: ERC4626_ABI }, - functionName: 'deposit', - args: [AMOUNT_TO_DEPOSIT_WETH, arbitrary.permit2AdapterContract.address(chainId)], - }, - ], - - chainId, - - // Distribute vault token to user - distribution: { - [VAULT]: [{ recipient: user.address, shareBps: 10_000 }], - }, - - // Set special config - txValidFor: '2y', - }); - - // Send tx - await user.sendTransaction(tx); - - // Assertions - const nativeBalance = await balance({ of: user.address, for: STABLE_ERC20 }); - const vaultBalance = await balance({ of: VAULT_WETH, for: wToken }); - expect(nativeBalance).to.be.lte(ORIGINAL_AMOUNT_ETH - AMOUNT_TO_DEPOSIT_WETH); - expect(vaultBalance).to.be.gt(0); - }); - - it('buildArbitraryCallWithBatchPermit', async () => { - // Prepare data to sign - const { - dataToSign: { domain, types, message }, - permitData, - } = await arbitrary.prepareBatchPermitData({ - appId: APP_ID, - chainId: CHAIN.chainId, - signerAddress: user.address, - tokens: { - [STABLE_ERC20.address]: AMOUNT_TO_DEPOSIT_USDC, - [wToken.address]: AMOUNT_TO_DEPOSIT_WETH, - }, - signatureValidFor: '2y', - }); - - // We need to overwrite the chain id so that it matches the fork's id - const newDomain = { ...domain, chainId }; - - // Sign it - const signature = await user._signTypedData(newDomain, types, message); - - // Build tx - const tx = arbitrary.buildArbitraryCallWithBatchPermit({ - // Set permit data - permitData: { ...permitData, signature }, - - // Provide allowance for vaults - allowanceTargets: [ - { token: STABLE_ERC20.address, target: VAULT_USDC }, - { token: wToken.address, target: VAULT_WETH }, - ], - - calls: [ - // Deposit into USDC vault - { - address: VAULT_USDC, - abi: { humanReadable: ERC4626_ABI }, - functionName: 'deposit', - args: [AMOUNT_TO_DEPOSIT_USDC, arbitrary.permit2AdapterContract.address(chainId)], - }, - - // Deposit into WETH vault - { - address: VAULT_WETH, - abi: { humanReadable: ERC4626_ABI }, - functionName: 'deposit', - args: [AMOUNT_TO_DEPOSIT_WETH, arbitrary.permit2AdapterContract.address(chainId)], - }, - ], - - chainId, - - // Distribute vault token to user - distribution: { - [VAULT_USDC]: [{ recipient: user.address, shareBps: 10_000 }], - [VAULT_WETH]: [{ recipient: user.address, shareBps: 10_000 }], - }, - }); - - // Send tx - await user.sendTransaction(tx); - - // Assertions - const usdcBalance = await balance({ of: user.address, for: STABLE_ERC20 }); - const wTokenBalance = await balance({ of: user.address, for: wToken }); - const usdcVaultBalance = await balance({ of: VAULT_USDC, for: STABLE_ERC20 }); - const wethVaultBalance = await balance({ of: VAULT_WETH, for: wToken }); - expect(usdcBalance).to.equal(ORIGINAL_AMOUNT_USDC - AMOUNT_TO_DEPOSIT_USDC); - expect(wTokenBalance).to.equal(ORIGINAL_AMOUNT_WETH - AMOUNT_TO_DEPOSIT_WETH); - expect(usdcVaultBalance).to.be.gt(0); - expect(wethVaultBalance).to.be.gt(0); - }); -}); - -export const ERC4626_ABI = ['function deposit(uint256 assets, address receiver) returns (uint256 shares)']; diff --git a/test/integration/services/permit2/permit2-quote-service.spec.ts b/test/integration/services/permit2/permit2-quote-service.spec.ts deleted file mode 100644 index f7276606..00000000 --- a/test/integration/services/permit2/permit2-quote-service.spec.ts +++ /dev/null @@ -1,116 +0,0 @@ -import ms from 'ms'; -import { ethers } from 'hardhat'; -import { SnapshotRestorer, takeSnapshot } from '@nomicfoundation/hardhat-network-helpers'; -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; -import { given, then, when } from '@test-utils/bdd'; -import { fork } from '@test-utils/evm'; -import { TransactionResponse } from '@ethersproject/providers'; -import { Chains, getChainByKeyOrFail } from '@chains'; -import { TokenAddress, Address } from '@types'; -import { - assertRecipientsBalanceIsIncreasedAsExpected, - assertUsersBalanceIsReducedAsExpected, - calculateBalancesFor, - loadTokens, - mint, - TestToken, -} from '@test-utils/erc20'; -import { buildSDK } from '@builder'; -import { parseEther } from 'viem'; -import { CONFIG } from '../quotes/quote-tests-config'; -import { QuoteResponseWithTx } from '@services/quotes'; - -// Since trading tests can be a little bit flaky, we want to re-test before failing -jest.retryTimes(3); -jest.setTimeout(ms('5m')); - -const { - permit2Service: { quotes: permit2QuoteService }, -} = buildSDK({ quotes: { defaultConfig: CONFIG, sourceList: { type: 'local' } } }); - -// This test validates quotes, but the SDK can't connect to the local test network. So we need to use addresses that have enough -// balance, because we can't simulate it on the real chain -const NATIVE_WHALES = { - [Chains.POLYGON.chainId]: '0x06959153B974D0D5fDfd87D561db6d8d4FA0bb0B', - [Chains.ETHEREUM.chainId]: '0x00000000219ab540356cbb839cbe05303d7705fa', - [Chains.BNB_CHAIN.chainId]: '0xf977814e90da44bfa03b6295a0616a897441acec', -}; -const chains = Object.keys(NATIVE_WHALES).map(Number); - -describe('Permit2 Quote Service [External Quotes]', () => { - for (const chainId of chains) { - const chain = getChainByKeyOrFail(chainId); - describe(`${chain.name}`, () => { - const ONE_NATIVE_TOKEN = parseEther('1'); - let user: SignerWithAddress; - let nativeToken: TestToken, STABLE_ERC20: TestToken, wToken: TestToken; - let initialBalances: Record>; - let snapshot: SnapshotRestorer; - beforeAll(async () => { - await fork({ chain }); - const whale = NATIVE_WHALES[chainId]; - if (!whale) throw new Error('Whale not set'); - user = await ethers.getImpersonatedSigner(whale); - ({ nativeToken, STABLE_ERC20, wToken } = await loadTokens(chain)); - await mint({ amount: ONE_NATIVE_TOKEN * 3n, of: nativeToken, to: user }); - await mint({ amount: ONE_NATIVE_TOKEN * 3n, of: wToken, to: user }); - initialBalances = await calculateBalancesFor({ - tokens: [nativeToken, STABLE_ERC20, wToken], - addresses: [user], - }); - snapshot = await takeSnapshot(); - }); - afterEach(async () => { - await snapshot.restore(); - }); - when('swapping 1 native token to stables', () => { - let quote: QuoteResponseWithTx; - let response: TransactionResponse; - given(async () => { - const estimatedQuotes = await permit2QuoteService.estimateAllQuotes({ - request: { - chainId, - sellToken: nativeToken.address, - buyToken: STABLE_ERC20.address, - order: { - type: 'sell', - sellAmount: ONE_NATIVE_TOKEN.toString(), - }, - slippagePercentage: 5, - }, - config: { - timeout: '15s', - }, - }); - const quotes = await permit2QuoteService.buildAndSimulateQuotes({ - chainId, - quotes: estimatedQuotes, - takerAddress: user.address, - txValidFor: '1y', - config: { sort: { by: 'most-swapped' } }, - }); - quote = quotes[0]; - const { gasPrice, maxFeePerGas, maxPriorityFeePerGas, ...tx } = quote.tx; - response = await user.sendTransaction({ gasPrice, ...tx }); - }); - then('result is as expected', async () => { - await assertUsersBalanceIsReducedAsExpected({ - txs: [response], - sellToken: nativeToken, - quote, - tx: quote.tx, - user, - initialBalances, - }); - await assertRecipientsBalanceIsIncreasedAsExpected({ - txs: [response], - buyToken: STABLE_ERC20, - quote, - recipient: user, - initialBalances, - }); - }); - }); - }); - } -}); diff --git a/test/integration/services/quotes/quote-tests-config.ts b/test/integration/services/quotes/quote-tests-config.ts index 58fccfdb..6e123c9e 100644 --- a/test/integration/services/quotes/quote-tests-config.ts +++ b/test/integration/services/quotes/quote-tests-config.ts @@ -69,7 +69,6 @@ export const EXCEPTIONS: Partial> = { uniswap: [Test.WRAP_NATIVE_TOKEN, Test.UNWRAP_WTOKEN], kyberswap: [Test.WRAP_NATIVE_TOKEN, Test.UNWRAP_WTOKEN], sovryn: [Test.WRAP_NATIVE_TOKEN, Test.UNWRAP_WTOKEN], - oku: [Test.WRAP_NATIVE_TOKEN, Test.UNWRAP_WTOKEN], balmy: [ Test.SELL_RANDOM_ERC20_TO_STABLE, Test.SELL_STABLE_TO_NATIVE, diff --git a/test/integration/services/quotes/sources/quote-sources.spec.ts b/test/integration/services/quotes/sources/quote-sources.spec.ts deleted file mode 100644 index 8bddd159..00000000 --- a/test/integration/services/quotes/sources/quote-sources.spec.ts +++ /dev/null @@ -1,436 +0,0 @@ -import ms from 'ms'; -import { ethers } from 'hardhat'; -import { SnapshotRestorer, takeSnapshot } from '@nomicfoundation/hardhat-network-helpers'; -import { parseUnits, parseEther } from 'viem'; -import { expect } from 'chai'; -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; -import { given, then, when } from '@test-utils/bdd'; -import { fork } from '@test-utils/evm'; -import { TransactionResponse } from '@ethersproject/providers'; -import { Chains, getChainByKeyOrFail } from '@chains'; -import { Addresses } from '@shared/constants'; -import { addPercentage, isSameAddress, subtractPercentage } from '@shared/utils'; -import { Chain, TokenAddress, Address, ChainId } from '@types'; -import { - BuyOrder, - IQuoteSource, - QuoteSourceSupport, - SellOrder, - SourceQuoteResponse, - SourceQuoteTransaction, -} from '@services/quotes/quote-sources/types'; -import { RPCGasPriceSource } from '@services/gas/gas-price-sources/rpc-gas-price-source'; -import { FetchService } from '@services/fetch/fetch-service'; -import { GasPrice } from '@services/gas/types'; -import { Test, EXCEPTIONS, CONFIG } from '../quote-tests-config'; -import { - approve, - assertRecipientsBalanceIsIncreasedAsExpected, - assertUsersBalanceIsReducedAsExpected, - calculateBalancesFor, - chainsWithTestData, - loadTokens, - mintMany, - TestToken, -} from '@test-utils/erc20'; -import { QUOTE_SOURCES, SOURCES_METADATA, SourceWithConfigId } from '@services/quotes/source-registry'; -import { SourceId } from '@services/quotes/types'; -import { PublicRPCsProviderSource } from '@services/providers/provider-sources/public-rpcs-provider'; -import { Deferred } from '@shared/deferred'; -import { TriggerablePromise } from '@shared/triggerable-promise'; -import { ProviderService } from '@services/providers/provider-service'; -import { OpenOceanGasPriceSource } from '@services/gas/gas-price-sources/open-ocean-gas-price-source'; -import { PrioritizedGasPriceSourceCombinator } from '@services/gas/gas-price-sources/prioritized-gas-price-source-combinator'; -import { wait } from '@shared/wait'; - -// Note: this test is quite flaky, since sources can sometimes fail or rate limit us. So the idea is to run this test -// locally only for now, until we can come up with a solution. We will skip it until then - -// This is meant to be used for local testing. On the CI, we will do something different -const RUN_FOR: { source: keyof typeof SOURCES_METADATA; chains: Chain[] | 'all' } = { - source: 'balancer', - chains: [Chains.ETHEREUM], -}; -const ROUNDING_ISSUES: SourceId[] = ['rango', 'wido']; -const AVOID_DURING_CI: SourceId[] = [ - 'rango', // Fails, a lot -]; - -// Since trading tests can be a little bit flaky, we want to re-test before failing -jest.retryTimes(3); -jest.setTimeout(ms('5m')); - -describe('Quote Sources [External Quotes]', () => { - const sourcesPerChain = getSources(); - for (const chainId of Object.keys(sourcesPerChain)) { - const chain = getChainByKeyOrFail(chainId); - describe(`${chain.name}`, () => { - const ONE_NATIVE_TOKEN = parseEther('1'); - let user = new Deferred(), - recipient = new Deferred(), - nativeToken = new Deferred(), - wToken = new Deferred(), - STABLE_ERC20 = new Deferred(), - RANDOM_ERC20 = new Deferred(), - gasPrice = new Deferred(); - let initialBalances: Record>; - let snapshot: SnapshotRestorer; - - beforeAll(async () => { - await fork({ chain }); - const [, , , , , userSigner, recipientSigner] = await ethers.getSigners(); - const tokens = await loadTokens(chain); - - await mintMany({ - to: userSigner, - tokens: [ - { amount: parseUnits('10000', tokens.STABLE_ERC20.decimals), token: tokens.STABLE_ERC20 }, - { amount: parseUnits('1000', tokens.RANDOM_ERC20.decimals), token: tokens.RANDOM_ERC20 }, - { amount: ONE_NATIVE_TOKEN * 3n, token: tokens.nativeToken }, - { amount: ONE_NATIVE_TOKEN, token: tokens.wToken }, - ], - }); - initialBalances = await calculateBalancesFor({ - tokens: [tokens.nativeToken, tokens.wToken, tokens.STABLE_ERC20, tokens.RANDOM_ERC20], - addresses: [userSigner, recipientSigner], - }); - const gasPriceResult = await GAS_PRICE_SOURCE.getGasPrice(chain).then((gasPrices) => gasPrices['standard']); - - // Resolve all deferred - user.resolve(userSigner); - recipient.resolve(recipientSigner); - nativeToken.resolve(tokens.nativeToken); - wToken.resolve(tokens.wToken); - STABLE_ERC20.resolve(tokens.STABLE_ERC20); - RANDOM_ERC20.resolve(tokens.RANDOM_ERC20); - gasPrice.resolve(gasPriceResult); - snapshot = await takeSnapshot(); - }); - - afterEach(async () => { - await snapshot.restore(); - }); - - describe('Sell order', () => { - quoteTest({ - test: Test.SELL_RANDOM_ERC20_TO_STABLE, - when: 'swapping 1 random token to stable', - request: { - sellToken: RANDOM_ERC20, - buyToken: STABLE_ERC20, - unitsToSell: 1, - }, - }); - quoteTest({ - test: Test.SELL_STABLE_TO_NATIVE, - when: 'swapping 1000 of stables to native token', - request: { - sellToken: STABLE_ERC20, - buyToken: nativeToken, - unitsToSell: 1000, - }, - }); - quoteTest({ - test: Test.SELL_NATIVE_TO_RANDOM_ERC20, - when: 'swapping 1 native token to random token', - request: { - sellToken: nativeToken, - buyToken: RANDOM_ERC20, - unitsToSell: 1, - }, - }); - }); - describe('Swap and transfer', () => { - quoteTest({ - test: Test.SELL_NATIVE_TO_STABLE_AND_TRANSFER, - checkSupport: (support) => support.swapAndTransfer, - when: 'swapping 1 native token to stable', - request: { - sellToken: nativeToken, - buyToken: STABLE_ERC20, - unitsToSell: 1, - recipient, - }, - }); - }); - describe('Buy order', () => { - quoteTest({ - test: Test.BUY_NATIVE_WITH_STABLE, - checkSupport: (support) => support.buyOrders, - when: 'buying 1 native token with stables', - request: { - sellToken: STABLE_ERC20, - buyToken: nativeToken, - unitsToBuy: 1, - }, - }); - quoteTest({ - test: Test.BUY_RANDOM_ERC20_WITH_STABLE, - checkSupport: (support) => support.buyOrders, - when: 'buying 100 random token with stables', - request: { - sellToken: STABLE_ERC20, - buyToken: RANDOM_ERC20, - unitsToBuy: 100, - }, - }); - }); - describe('Wrap / Unwrap', () => { - quoteTest({ - test: Test.WRAP_NATIVE_TOKEN, - when: 'wrapping 1 native token', - request: { - sellToken: nativeToken, - buyToken: wToken, - unitsToSell: 1, - }, - }); - quoteTest({ - test: Test.UNWRAP_WTOKEN, - when: 'unwrapping 1 wtoken', - request: { - sellToken: wToken, - buyToken: nativeToken, - unitsToSell: 1, - }, - }); - }); - - function quoteTest({ - test, - when: title, - request, - checkSupport, - }: { - test: Test; - when: string; - checkSupport?: (support: QuoteSourceSupport) => boolean; - request: Quote; - }) { - when(title, () => { - for (const [sourceId, source] of Object.entries(sourcesPerChain[chain.chainId])) { - const config = getConfig(sourceId); - if ( - source.isConfigAndContextValidForQuoting(config) && - source.isConfigAndContextValidForTxBuilding(config) && - shouldExecute(sourceId, test) && - (!checkSupport || checkSupport(source.getMetadata().supports)) - ) { - const quotePromise = buildQuote(sourceId, source, request, test); - describe(`on ${source.getMetadata().name}`, () => { - let quote: SourceQuoteResponse; - let tx: SourceQuoteTransaction; - let sellToken: TestToken, buyToken: TestToken, recipient: SignerWithAddress | undefined, takeFrom: SignerWithAddress; - let txs: TransactionResponse[]; - given(async () => { - [sellToken, buyToken, recipient, takeFrom] = await Promise.all([request.sellToken, request.buyToken, request.recipient, user]); - ({ quote, tx } = await quotePromise); - const approveTx = isSameAddress(quote.allowanceTarget, Addresses.ZERO_ADDRESS) - ? [] - : [await approve({ amount: quote.maxSellAmount, to: quote.allowanceTarget, for: sellToken, from: takeFrom })]; - txs = [...approveTx, await execute({ tx, as: takeFrom })]; - }); - then('result is as expected', async () => { - await assertUsersBalanceIsReducedAsExpected({ - txs, - sellToken, - quote, - tx, - user: takeFrom, - initialBalances, - }); - await assertRecipientsBalanceIsIncreasedAsExpected({ - txs, - buyToken, - quote, - recipient: recipient ?? takeFrom, - initialBalances, - }); - const { sellToken: _, buyToken: __, ...rest } = request; - assertQuoteIsConsistent(quote, tx, { - sellToken, - buyToken, - ...rest, - sourceId, - }); - }); - }); - } - } - }); - } - - function assertQuoteIsConsistent( - quote: SourceQuoteResponse, - tx: SourceQuoteTransaction, - { - sellToken, - buyToken, - unitsToSell, - unitsToBuy, - sourceId, - }: { - sellToken: TestToken; - buyToken: TestToken; - sourceId: SourceId; - unitsToSell?: number; - unitsToBuy?: number; - } - ) { - const type = unitsToSell ? 'sell' : 'buy'; - const sellAmount = unitsToSell ? parseUnits(`${unitsToSell}`, sellToken.decimals) : undefined; - const buyAmount = unitsToBuy ? parseUnits(`${unitsToBuy}`, buyToken.decimals) : undefined; - expect(quote.type).to.equal(type); - if (type === 'sell') { - expect(quote.sellAmount).to.equal(sellAmount); - expect(quote.sellAmount).to.equal(quote.maxSellAmount); - if (buyAmount) { - expect(quote.buyAmount).to.be.gte(buyAmount); - } else { - validateQuote(sellToken, buyToken, sellAmount!, quote.buyAmount); - } - } else { - expect(quote.buyAmount).to.equal(buyAmount); - expect(quote.buyAmount).to.equal(quote.minBuyAmount); - if (sellAmount) { - expect(quote.sellAmount).to.be.lte(sellAmount); - } else { - validateQuote(buyToken, sellToken, buyAmount!, quote.sellAmount); - } - } - validateMinBuyMaxSell(sourceId, quote); - if (isSameAddress(sellToken.address, Addresses.NATIVE_TOKEN)) { - expect(quote.allowanceTarget).to.equal(Addresses.ZERO_ADDRESS); - expect(tx.value).to.equal(quote.maxSellAmount); - } else { - const isValueNotSet = (value?: bigint) => !value || value === 0n; - expect(isValueNotSet(tx.value)).to.be.true; - } - } - - function validateMinBuyMaxSell(sourceId: SourceId, quote: SourceQuoteResponse) { - let slippage = SLIPPAGE_PERCENTAGE; - if (ROUNDING_ISSUES.includes(sourceId)) slippage += 0.05; - if (quote.type === 'sell') { - expect(quote.minBuyAmount).to.be.gte(subtractPercentage(quote.buyAmount.toString(), slippage, 'up')); - } else { - expect(quote.maxSellAmount).to.be.lte(addPercentage(quote.sellAmount.toString(), slippage, 'up')); - } - } - - const TRESHOLD_PERCENTAGE = 5; // 5% - function validateQuote(from: TestToken, to: TestToken, fromAmount: bigint, toAmount: bigint) { - const fromPriceBN = parseEther(`${from.price!}`); - const toPriceBN = parseEther(`${to.price!}`); - const magnitudeFrom = parseUnits('1', from.decimals); - const magnitudeTo = parseUnits('1', to.decimals); - const expected = (fromAmount * fromPriceBN * magnitudeTo) / (toPriceBN * magnitudeFrom); - - const threshold = (expected * BigInt(TRESHOLD_PERCENTAGE * 10)) / BigInt(100 * 10); - const lowerThreshold = expected - threshold; - expect(toAmount).to.be.gte(lowerThreshold); - } - - type Quote = ({ unitsToSell: number } | { unitsToBuy: number }) & { - recipient?: Promise; - sellToken: Promise; - buyToken: Promise; - }; - async function buildQuote(sourceId: string, source: IQuoteSource, quote: Quote, test: Test) { - const [sellToken, buyToken, takeFrom, recipient] = await Promise.all([quote.sellToken, quote.buyToken, user, quote.recipient]); - // If we execute all requests at the same time, then we'll probably get rate-limited. So the idea is to wait a little for each test so requests are not executed concurrently - const millisToWait = ms('0.5s') * test; - await wait(millisToWait); - const order: SellOrder | BuyOrder = - 'unitsToSell' in quote - ? { type: 'sell', sellAmount: parseUnits(`${quote.unitsToSell}`, sellToken.decimals) } - : { type: 'buy', buyAmount: parseUnits(`${quote.unitsToBuy}`, buyToken.decimals) }; - const quoteResponse = await source.quote({ - components: { providerService: PROVIDER_SERVICE, fetchService: FETCH_SERVICE }, - request: { - ...quote, - order, - sellToken: sellToken.address, - buyToken: buyToken.address, - chainId: chain.chainId, - config: { - slippagePercentage: SLIPPAGE_PERCENTAGE, - txValidFor: '5m', - timeout: '15s', - }, - accounts: { takeFrom: takeFrom.address, recipient: recipient?.address }, - external: { - gasPrice: new TriggerablePromise(() => gasPrice), - tokenData: new TriggerablePromise(() => Promise.resolve({ sellToken, buyToken })), - }, - }, - config: getConfig(sourceId), - }); - const tx = await source.buildTx({ - components: { providerService: PROVIDER_SERVICE, fetchService: FETCH_SERVICE }, - config: getConfig(sourceId), - request: { - chainId: chain.chainId, - sellToken: sellToken.address, - buyToken: buyToken.address, - ...quoteResponse, - accounts: { takeFrom: takeFrom.address, recipient: recipient?.address ?? takeFrom.address }, - customData: quoteResponse.customData, - config: { timeout: '15s' }, - }, - }); - return { quote: quoteResponse, tx }; - } - - function execute({ as, tx: { value, calldata, to } }: { as: SignerWithAddress; tx: SourceQuoteTransaction }) { - return as.sendTransaction({ to, data: calldata, value }); - } - - function shouldExecute(sourceId: string, test: Test) { - return !EXCEPTIONS[sourceId]?.includes(test); - } - }); - - function getConfig(sourceId: SourceId) { - return { - ...CONFIG.global, - ...CONFIG.custom?.[sourceId as SourceWithConfigId], - }; - } - } -}); - -function getSources() { - const sources = QUOTE_SOURCES; - const result: Record>> = {}; - - if (process.env.CI_CONTEXT) { - // Will choose test on Ethereum or, if not supported, choose random chain - for (const [sourceId, source] of Object.entries(sources)) { - if (AVOID_DURING_CI.includes(sourceId)) continue; - const supportedChains = chainsWithTestData(source.getMetadata().supports.chains); - if (supportedChains.length === 0) continue; - const chainId = supportedChains.includes(Chains.ETHEREUM.chainId) - ? Chains.ETHEREUM.chainId - : supportedChains[Math.floor(Math.random() * supportedChains.length)]; - if (!(chainId in result)) result[chainId] = {} as any; - result[chainId][sourceId] = source; - } - } else { - const source = sources[RUN_FOR.source as keyof typeof sources]; - const chains = - RUN_FOR.chains === 'all' ? chainsWithTestData(source.getMetadata().supports.chains) : RUN_FOR.chains.map(({ chainId }) => chainId); - for (const chainId of chains) { - if (!(chainId in result)) result[chainId] = {} as any; - result[chainId][RUN_FOR.source] = source; - } - } - return result; -} - -const PROVIDER_SERVICE = new ProviderService({ source: new PublicRPCsProviderSource() }); -const FETCH_SERVICE = new FetchService(); -const OPEN_OCEAN_GAS_PRICE_SOURCE = new OpenOceanGasPriceSource(FETCH_SERVICE); -const RPC_GAS_PRICE_SOURCE = new RPCGasPriceSource(PROVIDER_SERVICE); -const GAS_PRICE_SOURCE = new PrioritizedGasPriceSourceCombinator([OPEN_OCEAN_GAS_PRICE_SOURCE, RPC_GAS_PRICE_SOURCE]); -const SLIPPAGE_PERCENTAGE = 5; // We set a high slippage so that the tests don't fail as much diff --git a/test/integration/utils/erc20.ts b/test/integration/utils/erc20.ts deleted file mode 100644 index e5c635a4..00000000 --- a/test/integration/utils/erc20.ts +++ /dev/null @@ -1,425 +0,0 @@ -import { setBalance, impersonateAccount, stopImpersonatingAccount } from '@nomicfoundation/hardhat-network-helpers'; -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; -import { Contract } from 'ethers'; -import { ethers } from 'hardhat'; -import { Addresses } from '@shared/constants'; -import { isSameAddress } from '@shared/utils'; -import { Address, BigIntish, Chain, ChainId, TokenAddress } from '@types'; -import { Chains } from '@chains'; -import { FetchService } from '@services/fetch/fetch-service'; -import { TransactionResponse } from '@ethersproject/providers'; -import { SourceQuoteResponse, SourceQuoteTransaction } from '@services/quotes/quote-sources/types'; -import { CHAINS_WITH_KNOWN_ISSUES, calculateGasSpent } from './other'; -import { expect } from 'chai'; -import { QuoteResponse, QuoteResponseWithTx, QuoteTransaction } from '@services/quotes/types'; -import { BaseTokenMetadata } from '@services/metadata/types'; -import { DefiLlamaClient } from '@shared/defi-llama'; -import { parseEther } from 'viem'; - -type TokenData = { address: TokenAddress; whale: Address }; -type ChainTokens = { RANDOM_ERC20: TokenData; STABLE_ERC20: TokenData; wToken: TokenData }; -export type TestToken = BaseTokenMetadata & { price: number } & IHasAddress & { whale?: Address }; - -export const TOKENS: Record> = { - [Chains.ETHEREUM.chainId]: { - STABLE_ERC20: { - address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - whale: '0x40ec5b33f54e0e8a33a975908c5ba1c14e5bbbdf', - }, - RANDOM_ERC20: { - address: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - whale: '0x9ff58f4fFB29fA2266Ab25e75e2A8b3503311656', - }, - wToken: { - address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - whale: '0x08638ef1a205be6762a8b935f5da9b700cf7322c', - }, - }, - [Chains.OPTIMISM.chainId]: { - STABLE_ERC20: { - address: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', - whale: '0xf390830df829cf22c53c8840554b98eafc5dcbc2', - }, - RANDOM_ERC20: { - address: '0x68f180fcCe6836688e9084f035309E29Bf0A2095', - whale: '0x338726dd694db9e2230ec2bb8624a2d7f566c96d', - }, - wToken: { - address: '0x4200000000000000000000000000000000000006', - whale: '0x68f5c0a2de713a54991e01858fd27a3832401849', - }, - }, - [Chains.BASE.chainId]: { - STABLE_ERC20: { - address: '0x50c5725949a6f0c72e6c4a641f24049a917db0cb', - whale: '0x6d3c5a4a7ac4b1428368310e4ec3bb1350d01455', - }, - RANDOM_ERC20: { - address: '0x8544fe9d190fd7ec52860abbf45088e81ee24a8c', - whale: '0x5f0a153a64fd734c111b770da11de2c385ca8042', - }, - wToken: { - address: '0x4200000000000000000000000000000000000006', - whale: '0x41d160033c222e6f3722ec97379867324567d883', - }, - }, - [Chains.POLYGON.chainId]: { - STABLE_ERC20: { - address: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', - whale: '0xe7804c37c13166ff0b37f5ae0bb07a3aebb6e245', - }, - RANDOM_ERC20: { - address: '0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6', - whale: '0x078f358208685046a11C85e8ad32895DED33A249', - }, - wToken: { - address: '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270', - whale: '0x8df3aad3a84da6b69a4da8aec3ea40d9091b2ac4', - }, - }, - [Chains.ARBITRUM.chainId]: { - STABLE_ERC20: { - address: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - whale: '0x489ee077994b6658eafa855c308275ead8097c4a', - }, - RANDOM_ERC20: { - address: '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f', - whale: '0x489ee077994b6658eafa855c308275ead8097c4a', - }, - wToken: { - address: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', - whale: '0x489ee077994b6658eafa855c308275ead8097c4a', - }, - }, - [Chains.GNOSIS.chainId]: { - STABLE_ERC20: { - address: '0xddafbb505ad214d7b80b1f830fccc89b60fb7a83', - whale: '0xc66825c5c04b3c2ccd536d626934e16248a63f68', - }, - RANDOM_ERC20: { - address: '0x8e5bbbb09ed1ebde8674cda39a0c169401db4252', - whale: '0x30887fc55cbfad3487cb55bfe1779f6d2ba1c118', - }, - wToken: { - address: '0xe91d153e0b41518a2ce8dd3d7944fa863463a97d', - whale: '0x7f90122bf0700f9e7e1f688fe926940e8839f353', - }, - }, - [Chains.FANTOM.chainId]: { - STABLE_ERC20: { - address: '0x04068da6c83afcfa0e13ba15a6696662335d5b75', - whale: '0x95bf7e307bc1ab0ba38ae10fc27084bc36fcd605', - }, - RANDOM_ERC20: { - address: '0xb3654dc3d10ea7645f8319668e8f54d2574fbdc8', - whale: '0x89d9bc2f2d091cfbfc31e333d6dc555ddbc2fd29', - }, - wToken: { - address: '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', - whale: '0x39b3bd37208cbade74d0fcbdbb12d606295b430a', - }, - }, - [Chains.BNB_CHAIN.chainId]: { - STABLE_ERC20: { - address: '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', - whale: '0x4f31fa980a675570939b737ebdde0471a4be40eb', - }, - RANDOM_ERC20: { - address: '0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82', - whale: '0x000000000000000000000000000000000000dead', - }, - wToken: { - address: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', - whale: '0xd7d069493685a581d27824fc46eda46b7efc0063', - }, - }, - [Chains.AVALANCHE.chainId]: { - STABLE_ERC20: { - address: '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e', - whale: '0x4aefa39caeadd662ae31ab0ce7c8c2c9c0a013e8', - }, - RANDOM_ERC20: { - address: '0x50b7545627a5162f82a992c33b87adc75187b218', - whale: '0x686bef2417b6dc32c50a3cbfbcc3bb60e1e9a15d', - }, - wToken: { - address: '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7', - whale: '0xc73eed4494382093c6a7c284426a9a00f6c79939', - }, - }, - [Chains.KAIA.chainId]: { - STABLE_ERC20: { - address: '0x6270b58be569a7c0b8f47594f191631ae5b2c86c', - whale: '0x7d274dce8e2467fc4cdb6e8e1755db5686daebbb', - }, - RANDOM_ERC20: { - address: '0x5fff3a6c16c2208103f318f4713d4d90601a7313', - whale: '0xfe8850c2d03f2e09283fd6b908aa201f5664b21b', - }, - wToken: { - address: '0xe4f05a66ec68b54a58b17c22107b02e0232cc817', - whale: '0x2f72278d8f8c4840a4d9e20d609fb0b6ef622904', - }, - }, - [Chains.ROOTSTOCK.chainId]: { - STABLE_ERC20: { - // DLLR - address: '0xc1411567d2670e24d9c4daaa7cda95686e1250aa', - whale: '0x1440d19436beeaf8517896bffb957a88ec95a00f', - }, - RANDOM_ERC20: { - // SOV - address: '0xefc78fc7d48b64958315949279ba181c2114abbd', - whale: '0x5684a06cab22db16d901fee2a5c081b4c91ea40e', - }, - wToken: { - address: '0x542fda317318ebf1d3deaf76e0b632741a7e677d', - whale: '0x5a0d867e0d70fcc6ade25c3f1b89d618b5b4eaa7', - }, - }, - [Chains.AURORA.chainId]: { - STABLE_ERC20: { - address: '0xB12BFcA5A55806AaF64E99521918A4bf0fC40802', - whale: '0x2fe064b6c7d274082aa5d2624709bc9ae7d16c77', - }, - RANDOM_ERC20: { - address: '0xc42c30ac6cc15fac9bd938618bcaa1a1fae8501d', - whale: '0x8c14ea853321028a7bb5e4fb0d0147f183d3b677', - }, - wToken: { - address: '0xC9BdeEd33CD01541e1eeD10f90519d2C06Fe3feB', - whale: '0x63da4db6ef4e7c62168ab03982399f9588fcd198', - }, - }, - [Chains.POLYGON_ZKEVM.chainId]: { - STABLE_ERC20: { - address: '0xa8ce8aee21bc2a48a5ef670afcc9274c7bbbc035', - whale: '0x99b31498b0a1dae01fc3433e3cb60f095340935c', - }, - RANDOM_ERC20: { - address: '0xea034fb02eb1808c2cc3adbc15f447b93cbe08e1', - whale: '0x99b31498b0a1dae01fc3433e3cb60f095340935c', - }, - wToken: { - address: '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9', - whale: '0x89715e5b0deb3dcf82ca6485ad2a496ca502223d', - }, - }, - [Chains.KAVA.chainId]: { - STABLE_ERC20: { - address: '0xdb0e1e86b01c4ad25241b1843e407efc4d615248', - whale: '0xcc35FD8B11e66aB413dc520c920F396c2c1096Eb', - }, - RANDOM_ERC20: { - address: '0xe1da44c0da55b075ae8e2e4b6986adc76ac77d73', - whale: '0x3a724E0082b0E833670cF762Ea6bd711bcBdFf37', - }, - wToken: { - address: '0xc86c7c0efbd6a49b35e8714c5f59d99de09a225b', - whale: '0xc35DADB65012eC5796536bD9864eD8773aBc74C4', - }, - }, - [Chains.SCROLL.chainId]: { - STABLE_ERC20: { - address: '0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4', - whale: '0x621df269d4dcb33012a089c00e79f92d2197ee5e', - }, - RANDOM_ERC20: { - address: '0xf610a9dfb7c89644979b4a0f27063e9e7d7cda32', - whale: '0x69caccbd8e434453faf0b92ec6655cadef086e5c', - }, - wToken: { - address: '0x5300000000000000000000000000000000000004', - whale: '0xa5832adc1e4487b635a483722e4fc34062467479', - }, - }, - // Note: hardhat + Celo + Moonbeam throws `Errors: Invalid value undefined supplied to : RpcBlockWithTransactions | null/sha3Uncles: HASH, Invalid value undefined supplied to : RpcBlockWithTransactions | null/difficulty` error. - // Ref.: https://github.com/NomicFoundation/hardhat/issues/3590 - // [Chains.CELO.chainId]: { - // STABLE_ERC20: { - // address: '0x765de816845861e75a25fca122bb6898b8b1282a', - // whale: '0x246f4599eFD3fA67AC44335Ed5e749E518Ffd8bB', - // }, - // RANDOM_ERC20: { - // address: '0xc668583dcbdc9ae6fa3ce46462758188adfdfc24', - // whale: '0x08baFb4400A102Dddc5e5d584abf0aA38E174c57', - // }, - // wToken: { - // address: '0x149d5bf28fbace2950b52d4aca1c79bfd9bbb6fc', - // whale: '0xA5c453BC33FD9C5C798Ac24F666fa2B49E0a87fe', - // }, - // }, - // Note: we are disabling EVMOS because tests fail to load quite often on that network - // [Chains.EVMOS.chainId]: { - // STABLE_ERC20: { - // address: '0x51e44ffad5c2b122c8b635671fcc8139dc636e82', - // whale: '0xa8d87759fc80e08d40c6ee7857652f38e5c39aa8', - // }, - // RANDOM_ERC20: { - // address: '0x3f75ceabcdfed1aca03257dc6bdc0408e2b4b026', - // whale: '0x8e000833c11e0643ab41264bd41547cb077a5003', - // }, - // wToken: { - // address: '0xD4949664cD82660AaE99bEdc034a0deA8A0bd517', - // whale: '0xfcd2ce20ef8ed3d43ab4f8c2da13bbf1c6d9512f', - // }, - // }, - // [Chains.MOONBEAM.chainId]: { - // STABLE_ERC20: { - // address: '0x931715FEE2d06333043d11F658C8CE934aC61D0c', - // whale: '0x744b1756e7651c6D57f5311767EAFE5E931D615b', - // }, - // RANDOM_ERC20: { - // address: '0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080', - // whale: '0xD22Da948c0aB3A27f5570b604f3ADef5F68211C3', - // }, - // wToken: { - // address: '0xAcc15dC74880C9944775448304B263D191c6077F', - // whale: '0x343e4f06BF240d22FbdFd4a2Fe5858BC66e79F12', - // }, - // }, - // Note: we are disabling Canto because tests fail to load quite often on that network - // [Chains.CANTO.chainId]: { - // STABLE_ERC20: { - // address: '0x80b5a32e4f032b2a058b4f29ec95eefeeb87adcd', - // whale: '0xdE59F060D7ee2b612E7360E6C1B97c4d8289Ca2e', - // }, - // RANDOM_ERC20: { - // address: '0x7264610a66eca758a8ce95cf11ff5741e1fd0455', - // whale: '0xF0e4e74Ce34738826477b9280776fc797506fE13', - // }, - // wToken: { - // address: '0x826551890Dc65655a0Aceca109aB11AbDbD7a07B', - // whale: '0x1D20635535307208919f0b67c3B2065965A85aA9', - // }, - // }, -} satisfies Record; - -export function chainsWithTestData(chainIds: ChainId[]) { - return chainIds.filter((chainId) => chainId in TOKENS).filter((chainId) => !CHAINS_WITH_KNOWN_ISSUES.includes(chainId)); -} - -export async function calculateBalancesFor({ tokens, addresses }: { tokens: IHasAddress[]; addresses: IHasAddress[] }) { - const promises = tokens.flatMap((token) => - addresses.map(async (hasAddress) => ({ token, hasAddress, balance: await balance({ of: hasAddress.address, for: token }) })) - ); - const balances: Record> = {}; - const results = await Promise.all(promises); - for (const { token, hasAddress, balance } of results) { - if (!(hasAddress.address in balances)) balances[hasAddress.address] = {}; - balances[hasAddress.address][token.address] = balance; - } - return balances; -} - -export async function balance({ of, for: token }: { of: Address; for: IHasAddress }): Promise { - if (isSameAddress(token.address, Addresses.NATIVE_TOKEN)) { - const balance = await ethers.provider.getBalance(of); - return BigInt(balance.toString()); - } else { - const balance = await new Contract(token.address, ERC20_ABI, ethers.provider).balanceOf(of); - return BigInt(balance.toString()); - } -} - -export function approve({ amount, to, for: token, from }: { amount: BigIntish; to: Address; for: IHasAddress; from: SignerWithAddress }) { - return new Contract(token.address, ERC20_ABI, from).approve(to, amount); -} - -export async function mintMany({ to, tokens }: { to: IHasAddress; tokens: { token: TestToken; amount: BigIntish }[] }) { - await Promise.all(tokens.map(({ token, amount }) => mint({ amount, of: token, to }))); -} - -export async function mint({ of: token, amount, to: user }: { amount: BigIntish; of: TestToken; to: IHasAddress }) { - if (isSameAddress(token.address, Addresses.NATIVE_TOKEN)) { - await setBalance(user.address, amount); - } else { - await impersonateAccount(token.whale!); - const whaleSigner = await ethers.getSigner(token.whale!); - await setBalance(whaleSigner.address, parseEther('1')); - const contract = new Contract(token.address, ERC20_ABI, whaleSigner); - await contract.transfer(user.address, amount); - await stopImpersonatingAccount(token.whale!); - } -} - -export async function loadTokens(chain: Chain) { - const address = (name: string) => TOKENS[chain.chainId][name].address; - const whale = (name: string) => TOKENS[chain.chainId][name].whale; - const tokenSource = new DefiLlamaClient(new FetchService()); - const input = [Addresses.NATIVE_TOKEN, chain.wToken, address('STABLE_ERC20'), address('RANDOM_ERC20')].map((token) => ({ - chainId: chain.chainId, - token, - })); - const tokens = await tokenSource.getCurrentTokenData({ tokens: input }); - if (!tokens[chain.chainId][Addresses.NATIVE_TOKEN]) { - tokens[chain.chainId][Addresses.NATIVE_TOKEN] = { - ...tokens[chain.chainId][chain.wToken], - symbol: chain.nativeCurrency.symbol, - }; - } - return { - nativeToken: { ...tokens[chain.chainId][Addresses.NATIVE_TOKEN], address: Addresses.NATIVE_TOKEN }, - wToken: { ...tokens[chain.chainId][chain.wToken], address: address('wToken'), whale: whale('wToken') }, - STABLE_ERC20: { ...tokens[chain.chainId][address('STABLE_ERC20')], address: address('STABLE_ERC20'), whale: whale('STABLE_ERC20') }, - RANDOM_ERC20: { ...tokens[chain.chainId][address('RANDOM_ERC20')], address: address('RANDOM_ERC20'), whale: whale('RANDOM_ERC20') }, - }; -} - -export async function assertUsersBalanceIsReducedAsExpected({ - txs, - sellToken, - quote, - user, - tx, - initialBalances, -}: { - txs?: TransactionResponse[]; - sellToken: IHasAddress; - quote: SourceQuoteResponse | QuoteResponse | QuoteResponseWithTx; - tx: SourceQuoteTransaction | QuoteTransaction; - user: IHasAddress; - initialBalances: Record>; -}) { - const initialBalance = initialBalances[user.address][sellToken.address]; - const bal = await balance({ of: user.address, for: sellToken }); - if (isSameAddress(sellToken.address, Addresses.NATIVE_TOKEN)) { - const gasSpent = await calculateGasSpent(...(txs ?? [])); - expect(bal).to.equal(initialBalance - gasSpent - (tx.value ?? 0n)); - } else { - const maxSellAmount = typeof quote.maxSellAmount === 'object' ? quote.maxSellAmount.amount : quote.maxSellAmount; - expect(bal).to.be.gte(initialBalance - maxSellAmount); - } -} - -export async function assertRecipientsBalanceIsIncreasedAsExpected({ - txs, - buyToken, - quote, - recipient, - initialBalances, -}: { - txs?: TransactionResponse[]; - buyToken: IHasAddress; - quote: SourceQuoteResponse | QuoteResponse | QuoteResponseWithTx; - recipient: IHasAddress; - initialBalances: Record>; -}) { - const initialBalance = initialBalances[recipient.address][buyToken.address]; - const bal = await balance({ of: recipient.address, for: buyToken }); - const minBuyAmount = typeof quote.minBuyAmount === 'object' ? BigInt(quote.minBuyAmount.amount) : quote.minBuyAmount; - if (isSameAddress(buyToken.address, Addresses.NATIVE_TOKEN)) { - const gasSpent = await calculateGasSpent(...(txs ?? [])); - expect(bal - initialBalance + gasSpent).to.be.gte(minBuyAmount); - } else { - expect(bal - initialBalance).to.be.gte(minBuyAmount); - } -} - -const ERC20_ABI = [ - 'function balanceOf(address owner) view returns (uint)', - 'function transfer(address to, uint amount)', - 'function approve(address to, uint amount)', -]; - -type IHasAddress = { address: Address }; diff --git a/test/integration/utils/evm.ts b/test/integration/utils/evm.ts deleted file mode 100644 index f88dfe29..00000000 --- a/test/integration/utils/evm.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { alchemySupportedChains, buildAlchemyRPCUrl } from '@services/providers'; -import { Chain } from '@types'; -import { network } from 'hardhat'; - -export const fork = async ({ chain, blockNumber }: { chain: Chain; blockNumber?: number }) => { - const params = [ - { - forking: { - jsonRpcUrl: getUrl(chain), - blockNumber, - }, - }, - ]; - await network.provider.request({ - method: 'hardhat_reset', - params, - }); -}; - -function getUrl(chain: Chain) { - const apiKey = process.env.ALCHEMY_API_KEY; - const paid = process.env.ALCHEMY_API_KEY_TYPE === 'paid'; - const alchemyChains = alchemySupportedChains({ onlyFree: !paid }); - if (apiKey && alchemyChains.includes(chain.chainId)) { - return buildAlchemyRPCUrl({ apiKey, chainId: chain.chainId, protocol: 'https' }); - } - return chain.publicRPCs[0]; -} diff --git a/test/integration/utils/other.ts b/test/integration/utils/other.ts index 45602632..a52dc7a6 100644 --- a/test/integration/utils/other.ts +++ b/test/integration/utils/other.ts @@ -1,12 +1,4 @@ import { Chains } from '@chains'; -import { TransactionResponse } from '@ethersproject/providers'; - -export async function calculateGasSpent(...txs: TransactionResponse[]): Promise { - const gasSpentEach = await Promise.all( - txs.map((tx) => tx.wait().then((receipt) => BigInt(receipt.gasUsed.mul(receipt.effectiveGasPrice).toString()))) - ); - return gasSpentEach.reduce((accum, curr) => accum + curr, 0n); -} export const CHAINS_WITH_KNOWN_ISSUES = [ Chains.AURORA, @@ -22,4 +14,5 @@ export const CHAINS_WITH_KNOWN_ISSUES = [ Chains.opBNB, Chains.HECO, Chains.EVMOS, + Chains.CANTO, ].map(({ chainId }) => chainId); diff --git a/test/tsconfig.json b/test/tsconfig.json index 422728db..cf0f1631 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -13,6 +13,5 @@ "resolveJsonModule": true }, "extends": "../tsconfig.json", - "include": ["./integration", ".", "./test"], - "files": ["../hardhat.config.ts"] + "include": ["./integration", ".", "./test"] } diff --git a/yarn.lock b/yarn.lock index 7a662218..370ca930 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@adraffy/ens-normalize@^1.10.1": +"@adraffy/ens-normalize@^1.11.0": version "1.11.0" resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33" integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg== @@ -543,366 +543,6 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@ethereumjs/rlp@^5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-5.0.2.tgz#c89bd82f2f3bec248ab2d517ae25f5bbc4aac842" - integrity sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA== - -"@ethereumjs/util@^9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-9.1.0.tgz#75e3898a3116d21c135fa9e29886565609129bce" - integrity sha512-XBEKsYqLGXLah9PNJbgdkigthkG7TAGvlD/sH12beMXEyHDyigfcbdvHhmLyDWgDyOJn4QwiQUaF7yeuhnjdog== - dependencies: - "@ethereumjs/rlp" "^5.0.2" - ethereum-cryptography "^2.2.1" - -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" - integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" - integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - -"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" - integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" - integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" - integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" - integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" - integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - bn.js "^5.2.1" - -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" - integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/contracts@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" - integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - -"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" - integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" - integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" - integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" - integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - js-sha3 "0.8.0" - -"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" - integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== - -"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" - integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" - integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - -"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" - integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/providers@5.7.2": - version "5.7.2" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" - integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" - integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" - integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" - integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - hash.js "1.1.7" - -"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" - integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - bn.js "^5.2.1" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/solidity@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" - integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" - integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" - integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/units@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" - integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/wallet@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" - integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/json-wallets" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" - integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" - integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@fastify/busboy@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8" - integrity sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ== - "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1185,52 +825,30 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@noble/curves@1.4.2", "@noble/curves@~1.4.0": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" - integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== - dependencies: - "@noble/hashes" "1.4.0" +"@noble/ciphers@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-1.3.0.tgz#f64b8ff886c240e644e5573c097f86e5b43676dc" + integrity sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw== -"@noble/curves@1.8.2", "@noble/curves@~1.8.1": - version "1.8.2" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.2.tgz#8f24c037795e22b90ae29e222a856294c1d9ffc7" - integrity sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g== +"@noble/curves@1.9.2": + version "1.9.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.2.tgz#73388356ce733922396214a933ff7c95afcef911" + integrity sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g== dependencies: - "@noble/hashes" "1.7.2" + "@noble/hashes" "1.8.0" -"@noble/curves@^1.6.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.0.tgz#13e0ca8be4a0ce66c113693a94514e5599f40cfc" - integrity sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg== +"@noble/curves@^1.9.1", "@noble/curves@~1.9.0": + version "1.9.6" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.6.tgz#b45ebedca85bb75782f6be7e7f120f0c423c99e0" + integrity sha512-GIKz/j99FRthB8icyJQA51E8Uk5hXmdyThjgQXRKiv9h0zeRlzSCLIzFw6K1LotZ3XuB7yzlf76qk7uBmTdFqA== dependencies: "@noble/hashes" "1.8.0" -"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" - integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== - -"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" - integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== - -"@noble/hashes@1.7.2", "@noble/hashes@~1.7.1": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.2.tgz#d53c65a21658fb02f3303e7ee3ba89d6754c64b4" - integrity sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ== - -"@noble/hashes@1.8.0", "@noble/hashes@^1.5.0": +"@noble/hashes@1.8.0", "@noble/hashes@^1.8.0", "@noble/hashes@~1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== -"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" - integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1252,281 +870,27 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nomicfoundation/edr-darwin-arm64@0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.10.0.tgz#3a6952bdf3e2825937cb1aad737b6851e4c6df30" - integrity sha512-n0N+CVM4LKN9QeGZ5irr94Q4vwSs4u7W6jfuhNLmx1cpUxwE9RpeW+ym93JXDv62iVsbekeI5VsUEBHy0hymtA== - -"@nomicfoundation/edr-darwin-x64@0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.10.0.tgz#e8e8a1b5e0e6df27d47dee38fbea7d1b77e92ee5" - integrity sha512-nmImWM/3qWopYzOmicMzK/MF3rFKpm2Biuc8GpQYTLjdXhmItpP9JwEPyjbAWv/1HI09C2pRzgNzKfTxoIgJ6w== - -"@nomicfoundation/edr-linux-arm64-gnu@0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.10.0.tgz#0442b934d801abf1e94de517203f6c7cb24022a6" - integrity sha512-B/N1IyrCU7J6H4QckkQ1cSWAq1jSrJcXpO8GzRaQD1bgOOvg8wrUOrCD+Mfw7MLa6+X9vdZoXtPZOaaOQ9LmhA== - -"@nomicfoundation/edr-linux-arm64-musl@0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.10.0.tgz#ece7f90113347b3c41ca9d0b27962cbc42e54a3d" - integrity sha512-NA9DFLB0LzcKy9mTCUzgnRDbmmSfW0CdO22ySwOy+MKt4Cr9eJi+XR5ZH933Rxpi6BWNkSPeS2ECETE25sJT3w== - -"@nomicfoundation/edr-linux-x64-gnu@0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.10.0.tgz#aa2b6587f2dc5da280c696aaf3c8021edce36e4f" - integrity sha512-bDrbRTA9qZ9wSw5mqa8VpLFbf6ue2Z4qmRd08404eKm8RyBEFxjdHflFzCx46gz/Td0e+GLXy6KTVDj5D29r8w== - -"@nomicfoundation/edr-linux-x64-musl@0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.10.0.tgz#fcb755e1f1926d713f3883856b5840e970ce9096" - integrity sha512-wx7yOlC/hx4N1xuIeh5cAebpzCTx8ZH8/z0IyYMf2t4v52KHERz4IyzBz5OLfd+0IqTRg8ZU5EnFBacIoPeP/g== - -"@nomicfoundation/edr-win32-x64-msvc@0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.10.0.tgz#eb411d5a855a82cc9859a8889069c887ca5dde4b" - integrity sha512-DpBdVMimb+BUEs0E+nLGQ5JFHdGHyxQQNA+nh9V1eKtgarsV21S6br/d1vlQBMLQqkIzwmc6n+/O9Zjk2KfB3g== - -"@nomicfoundation/edr@^0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.10.0.tgz#c0d3476b348ae396458369d1589913154d774192" - integrity sha512-ed9qHSNssgh+0hYUx4ilDoMxxgf/sNT8SjnzgmA5A/LSXHaq2ax68bkdQ8otLYTlxHCO9BS5Nhb8bfajV4FZeA== - dependencies: - "@nomicfoundation/edr-darwin-arm64" "0.10.0" - "@nomicfoundation/edr-darwin-x64" "0.10.0" - "@nomicfoundation/edr-linux-arm64-gnu" "0.10.0" - "@nomicfoundation/edr-linux-arm64-musl" "0.10.0" - "@nomicfoundation/edr-linux-x64-gnu" "0.10.0" - "@nomicfoundation/edr-linux-x64-musl" "0.10.0" - "@nomicfoundation/edr-win32-x64-msvc" "0.10.0" - -"@nomicfoundation/hardhat-chai-matchers@1.0.6": - version "1.0.6" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-1.0.6.tgz#72a2e312e1504ee5dd73fe302932736432ba96bc" - integrity sha512-f5ZMNmabZeZegEfuxn/0kW+mm7+yV7VNDxLpMOMGXWFJ2l/Ct3QShujzDRF9cOkK9Ui/hbDeOWGZqyQALDXVCQ== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@types/chai-as-promised" "^7.1.3" - chai-as-promised "^7.1.1" - deep-eql "^4.0.1" - ordinal "^1.0.3" +"@scure/base@~1.2.5": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" + integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== -"@nomicfoundation/hardhat-network-helpers@1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.8.tgz#e4fe1be93e8a65508c46d73c41fa26c7e9f84931" - integrity sha512-MNqQbzUJZnCMIYvlniC3U+kcavz/PhhQSsY90tbEtUyMj/IQqsLwIRZa4ctjABh3Bz0KCh9OXUZ7Yk/d9hr45Q== +"@scure/bip32@1.7.0", "@scure/bip32@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.7.0.tgz#b8683bab172369f988f1589640e53c4606984219" + integrity sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw== dependencies: - ethereumjs-util "^7.1.4" - -"@nomicfoundation/hardhat-toolbox@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-2.0.2.tgz#ec95f23b53cb4e71a1a7091380fa223aad18f156" - integrity sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg== - -"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.0.tgz#83a7367342bd053a76d04bbcf4f373fef07cf760" - integrity sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw== - -"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.0.tgz#1225f7da647ae1ad25a87125664704ecc0af6ccc" - integrity sha512-dlHeIg0pTL4dB1l9JDwbi/JG6dHQaU1xpDK+ugYO8eJ1kxx9Dh2isEUtA4d02cQAl22cjOHTvifAk96A+ItEHA== - -"@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.0.tgz#dbc052dcdfd50ae50fd5ae1788b69b4e0fa40040" - integrity sha512-WFCZYMv86WowDA4GiJKnebMQRt3kCcFqHeIomW6NMyqiKqhK1kIZCxSLDYsxqlx396kKLPN1713Q1S8tu68GKg== - -"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.0.tgz#e6b2eea633995b557e74e881d2a43eab4760903d" - integrity sha512-DTw6MNQWWlCgc71Pq7CEhEqkb7fZnS7oly13pujs4cMH1sR0JzNk90Mp1zpSCsCs4oKan2ClhMlLKtNat/XRKQ== - -"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.0.tgz#af81107f5afa794f19988a368647727806e18dc4" - integrity sha512-wUpUnR/3GV5Da88MhrxXh/lhb9kxh9V3Jya2NpBEhKDIRCDmtXMSqPMXHZmOR9DfCwCvG6vLFPr/+YrPCnUN0w== - -"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.0.tgz#6877e1da1a06a9f08446070ab6e0a5347109f868" - integrity sha512-lR0AxK1x/MeKQ/3Pt923kPvwigmGX3OxeU5qNtQ9pj9iucgk4PzhbS3ruUeSpYhUxG50jN4RkIGwUMoev5lguw== - -"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.0.tgz#bb6cd83a0c259eccef4183796b6329a66cf7ebd9" - integrity sha512-A1he/8gy/JeBD3FKvmI6WUJrGrI5uWJNr5Xb9WdV+DK0F8msuOqpEByLlnTdLkXMwW7nSl3awvLezOs9xBHJEg== - -"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.0.tgz#9d4bca1cc9a1333fde985675083b0b7d165f6076" - integrity sha512-7x5SXZ9R9H4SluJZZP8XPN+ju7Mx+XeUMWZw7ZAqkdhP5mK19I4vz3x0zIWygmfE8RT7uQ5xMap0/9NPsO+ykw== - -"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.0.tgz#0db5bfc6aa952bea4098d8d2c8947b4e5c4337ee" - integrity sha512-m7w3xf+hnE774YRXu+2mGV7RiF3QJtUoiYU61FascCkQhX3QMQavh7saH/vzb2jN5D24nT/jwvaHYX/MAM9zUw== + "@noble/curves" "~1.9.0" + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" -"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.0.tgz#2e0f39a2924dcd77db6b419828595e984fabcb33" - integrity sha512-xCuybjY0sLJQnJhupiFAXaek2EqF0AP0eBjgzaalPXSNvCEN6ZYHvUzdA50ENDVeSYFXcUsYf3+FsD3XKaeptA== - -"@nomicfoundation/solidity-analyzer@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.0.tgz#e5ddc43ad5c0aab96e5054520d8e16212e125f50" - integrity sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg== - optionalDependencies: - "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.0" - "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.0" - "@nomicfoundation/solidity-analyzer-freebsd-x64" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-arm64-msvc" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" - -"@nomiclabs/hardhat-ethers@2.2.3": - version "2.2.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" - integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== - -"@scure/base@~1.1.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" - integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== - -"@scure/base@~1.1.6": - version "1.1.7" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.7.tgz#fe973311a5c6267846aa131bc72e96c5d40d2b30" - integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g== - -"@scure/base@~1.2.2", "@scure/base@~1.2.4": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.4.tgz#002eb571a35d69bdb4c214d0995dff76a8dcd2a9" - integrity sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ== - -"@scure/bip32@1.1.5": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" - integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== +"@scure/bip39@1.6.0", "@scure/bip39@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.6.0.tgz#475970ace440d7be87a6086cbee77cb8f1a684f9" + integrity sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A== dependencies: - "@noble/hashes" "~1.2.0" - "@noble/secp256k1" "~1.7.0" - "@scure/base" "~1.1.0" - -"@scure/bip32@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" - integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== - dependencies: - "@noble/curves" "~1.4.0" - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" - -"@scure/bip32@1.6.2", "@scure/bip32@^1.5.0": - version "1.6.2" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.2.tgz#093caa94961619927659ed0e711a6e4bf35bffd0" - integrity sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw== - dependencies: - "@noble/curves" "~1.8.1" - "@noble/hashes" "~1.7.1" - "@scure/base" "~1.2.2" - -"@scure/bip39@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" - integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== - dependencies: - "@noble/hashes" "~1.2.0" - "@scure/base" "~1.1.0" - -"@scure/bip39@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" - integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== - dependencies: - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" - -"@scure/bip39@1.5.4", "@scure/bip39@^1.4.0": - version "1.5.4" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.4.tgz#07fd920423aa671be4540d59bdd344cc1461db51" - integrity sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA== - dependencies: - "@noble/hashes" "~1.7.1" - "@scure/base" "~1.2.4" - -"@sentry/core@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" - integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/hub@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" - integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== - dependencies: - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/minimal@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" - integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/types" "5.30.0" - tslib "^1.9.3" - -"@sentry/node@^5.18.1": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" - integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== - dependencies: - "@sentry/core" "5.30.0" - "@sentry/hub" "5.30.0" - "@sentry/tracing" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - cookie "^0.4.1" - https-proxy-agent "^5.0.0" - lru_map "^0.3.3" - tslib "^1.9.3" - -"@sentry/tracing@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" - integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/types@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" - integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== - -"@sentry/utils@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" - integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== - dependencies: - "@sentry/types" "5.30.0" - tslib "^1.9.3" + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" "@sinclair/typebox@^0.27.8": version "0.27.8" @@ -1600,30 +964,30 @@ dependencies: "@babel/types" "^7.3.0" -"@types/bn.js@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== - dependencies: - "@types/node" "*" - -"@types/chai-as-promised@^7.1.3": - version "7.1.5" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" - integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== +"@types/chai-as-promised@7": + version "7.1.8" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz#f2b3d82d53c59626b5d6bbc087667ccb4b677fe9" + integrity sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw== dependencies: "@types/chai" "*" -"@types/chai@*": - version "4.3.4" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" - integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== +"@types/chai@*", "@types/chai@5.2.2": + version "5.2.2" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.2.tgz#6f14cea18180ffc4416bc0fd12be05fdd73bdd6b" + integrity sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg== + dependencies: + "@types/deep-eql" "*" "@types/crypto-js@4.1.2": version "4.1.2" resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.1.2.tgz#fb56b34f397d9ae2335611e416f15e7d65e276e6" integrity sha512-t33RNmTu5ufG/sorROIafiCVJMx3jz95bXUMoPAZcUD14fxMXnuTzqzXZoxpR0tNx2xpw11Dlmem9vGCsrSOfA== +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + "@types/glob@^7.1.1": version "7.2.0" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" @@ -1666,11 +1030,6 @@ expect "^29.0.0" pretty-format "^29.0.0" -"@types/lru-cache@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" - integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== - "@types/minimatch@*": version "5.1.2" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" @@ -1696,25 +1055,11 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== -"@types/pbkdf2@^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" - integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== - dependencies: - "@types/node" "*" - "@types/qs@6.9.10": version "6.9.10" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.10.tgz#0af26845b5067e1c9a622658a51f60a3934d51e8" integrity sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw== -"@types/secp256k1@^4.0.1": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" - integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== - dependencies: - "@types/node" "*" - "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" @@ -1752,7 +1097,7 @@ JSONStream@^1.3.5: jsonparse "^1.2.0" through ">=2.2.7 <3" -abitype@1.0.8, abitype@^1.0.6: +abitype@1.0.8, abitype@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.8.tgz#3554f28b2e9d6e9f35eb59878193eabd1b9f46ba" integrity sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg== @@ -1767,23 +1112,6 @@ acorn@^8.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== -adm-zip@^0.4.16: - version "0.4.16" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" - integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== - -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== - -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1802,23 +1130,6 @@ ajv@^8.11.0: require-from-string "^2.0.2" uri-js "^4.2.2" -ansi-align@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" - integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== - dependencies: - string-width "^4.1.0" - -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-colors@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -1860,7 +1171,7 @@ ansi-styles@^6.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== -anymatch@^3.0.3, anymatch@~3.1.2: +anymatch@^3.0.3: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -1980,52 +1291,6 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base-x@^3.0.2: - version "3.0.9" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" - integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== - dependencies: - safe-buffer "^5.0.1" - -bech32@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" - integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -blakejs@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" - integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== - -bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - -boxen@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" - integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^6.2.0" - chalk "^4.1.0" - cli-boxes "^2.2.1" - string-width "^4.2.2" - type-fest "^0.20.2" - widest-line "^3.1.0" - wrap-ansi "^7.0.0" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2034,42 +1299,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.2, braces@~3.0.2: +braces@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: fill-range "^7.1.1" -brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -browserify-aes@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - browserslist@^4.21.3: version "4.21.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" @@ -2087,22 +1323,6 @@ bs-logger@0.x: dependencies: fast-json-stable-stringify "2.x" -bs58@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== - dependencies: - base-x "^3.0.2" - -bs58check@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== - dependencies: - bs58 "^4.0.0" - create-hash "^1.1.0" - safe-buffer "^5.1.2" - bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -2115,16 +1335,6 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - call-bind@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -2152,7 +1362,7 @@ camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0, camelcase@^6.2.0: +camelcase@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -2162,10 +1372,10 @@ caniuse-lite@^1.0.30001449: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001456.tgz#734ec1dbfa4f3abe6e435b78ecf40d68e8c32ce4" integrity sha512-XFHJY5dUgmpMV25UqaD4kVq2LsiaU5rS8fb0f17pCoXQiQslzmFgnfOxfvo1bTpTqf7dwG/N/05CnLCnOEKmzA== -chai-as-promised@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" - integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== +chai-as-promised@7: + version "7.1.2" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.2.tgz#70cd73b74afd519754161386421fb71832c6d041" + integrity sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw== dependencies: check-error "^1.0.2" @@ -2214,33 +1424,6 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== -chokidar@3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chokidar@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" - integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== - dependencies: - readdirp "^4.0.1" - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - ci-info@^3.2.0: version "3.8.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" @@ -2251,14 +1434,6 @@ ci-info@^3.7.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - cjs-module-lexer@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" @@ -2269,11 +1444,6 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-boxes@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" - integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== - cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -2297,15 +1467,6 @@ cli-truncate@^3.1.0: slice-ansi "^5.0.0" string-width "^5.0.0" -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -2354,11 +1515,6 @@ colorette@^2.0.19: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== -command-exists@^1.2.8: - version "1.2.9" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" - integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== - commander@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.0.tgz#71797971162cd3cf65f0b9d24eb28f8d303acdf1" @@ -2369,11 +1525,6 @@ commander@^3.0.2: resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== -commander@^8.1.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - compare-func@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" @@ -2421,11 +1572,6 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -cookie@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - cosmiconfig-typescript-loader@^4.0.0: version "4.3.0" resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz#c4259ce474c9df0f32274ed162c0447c951ef073" @@ -2441,29 +1587,6 @@ cosmiconfig@^8.0.0: parse-json "^5.0.0" path-type "^4.0.0" -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - create-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" @@ -2508,7 +1631,7 @@ dargs@^7.0.0: resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4: +debug@^4.1.0, debug@^4.1.1, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2528,17 +1651,12 @@ decamelize@^1.1.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - dedent@^1.0.0: version "1.5.1" resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== -deep-eql@^4.0.1, deep-eql@^4.1.2: +deep-eql@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== @@ -2555,11 +1673,6 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.0.tgz#65491893ec47756d44719ae520e0e2609233b59b" integrity sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og== -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - detect-indent@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.1.tgz#cbb060a12842b9c4d333f1cac4aa4da1bb66bc25" @@ -2580,11 +1693,6 @@ diff-sequences@^29.6.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== -diff@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -2619,32 +1727,6 @@ electron-to-chromium@^1.4.284: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.301.tgz#175d9fa1509a5b062752c6db321051e610fe2eae" integrity sha512-bz00ASIIDjcgszZKuEA1JEFhbDjqUNbQ/PEhNEl1wbixzYpeTp2H2QWjsQvAL2T1wJBdOwCF5hE896BoMwYKrA== -elliptic@6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -elliptic@^6.5.7: - version "6.5.7" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" - integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - emittery@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" @@ -2660,18 +1742,6 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -enquirer@^2.3.0: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - -env-paths@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -2684,11 +1754,6 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -2704,107 +1769,11 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -ethereum-cryptography@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" - integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== - dependencies: - "@types/pbkdf2" "^3.0.0" - "@types/secp256k1" "^4.0.1" - blakejs "^1.1.0" - browserify-aes "^1.2.0" - bs58check "^2.1.2" - create-hash "^1.2.0" - create-hmac "^1.1.7" - hash.js "^1.1.7" - keccak "^3.0.0" - pbkdf2 "^3.0.17" - randombytes "^2.1.0" - safe-buffer "^5.1.2" - scrypt-js "^3.0.0" - secp256k1 "^4.0.1" - setimmediate "^1.0.5" - -ethereum-cryptography@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" - integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== - dependencies: - "@noble/hashes" "1.2.0" - "@noble/secp256k1" "1.7.1" - "@scure/bip32" "1.1.5" - "@scure/bip39" "1.1.1" - -ethereum-cryptography@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" - integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== - dependencies: - "@noble/curves" "1.4.2" - "@noble/hashes" "1.4.0" - "@scure/bip32" "1.4.0" - "@scure/bip39" "1.3.0" - -ethereumjs-util@^7.1.4: - version "7.1.5" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" - integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethers@5.7.2: - version "5.7.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" - integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.2" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - eventemitter3@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== -evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -2886,11 +1855,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -fdir@^6.4.4: - version "6.4.4" - resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.4.tgz#1cfcf86f875a883e19a8fab53622cfe992e8d2f9" - integrity sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg== - fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -2898,14 +1862,6 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -find-up@5.0.0, find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -2914,6 +1870,14 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + find-yarn-workspace-root@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" @@ -2921,26 +1885,6 @@ find-yarn-workspace-root@^2.0.0: dependencies: micromatch "^4.0.2" -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -follow-redirects@^1.12.1: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== - -fp-ts@1.19.3: - version "1.19.3" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" - integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== - -fp-ts@^1.0.0: - version "1.19.5" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" - integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== - fs-extra@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.0.tgz#5784b102104433bb0e090f48bfc4a30742c357ed" @@ -2950,15 +1894,6 @@ fs-extra@^11.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^9.0.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -2974,7 +1909,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^2.3.2, fsevents@~2.3.2: +fsevents@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== @@ -3039,25 +1974,13 @@ git-raw-commits@^2.0.11: split2 "^3.0.0" through2 "^4.0.0" -glob-parent@^5.1.2, glob-parent@~5.1.2: +glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -3112,7 +2035,7 @@ graceful-fs@^4.1.11: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: +graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -3122,53 +2045,6 @@ hard-rejection@^2.1.0: resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== -hardhat@2.23.0: - version "2.23.0" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.23.0.tgz#c3b404410ea52c41f3200cc011f5b4cebd7d80bd" - integrity sha512-xnORx1LgX46TxylOFme96JmSAIjXuHUVpOlUnaCt8MKMGsgy0NGsfPo5rJI/ncCBPLFLURGfZUQ2Uc6ZYN4kYg== - dependencies: - "@ethereumjs/util" "^9.1.0" - "@ethersproject/abi" "^5.1.2" - "@nomicfoundation/edr" "^0.10.0" - "@nomicfoundation/solidity-analyzer" "^0.1.0" - "@sentry/node" "^5.18.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" - adm-zip "^0.4.16" - aggregate-error "^3.0.0" - ansi-escapes "^4.3.0" - boxen "^5.1.2" - chokidar "^4.0.0" - ci-info "^2.0.0" - debug "^4.1.1" - enquirer "^2.3.0" - env-paths "^2.2.0" - ethereum-cryptography "^1.0.3" - find-up "^5.0.0" - fp-ts "1.19.3" - fs-extra "^7.0.1" - immutable "^4.0.0-rc.12" - io-ts "1.10.4" - json-stream-stringify "^3.1.4" - keccak "^3.0.2" - lodash "^4.17.11" - micro-eth-signer "^0.14.0" - mnemonist "^0.38.0" - mocha "^10.0.0" - p-map "^4.0.0" - picocolors "^1.1.0" - raw-body "^2.4.1" - resolve "1.17.0" - semver "^6.3.0" - solc "0.8.26" - source-map-support "^0.5.13" - stacktrace-parser "^0.1.10" - tinyglobby "^0.2.6" - tsort "0.0.1" - undici "^5.14.0" - uuid "^8.3.2" - ws "^7.4.6" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -3191,37 +2067,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -3239,25 +2084,6 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -3273,23 +2099,11 @@ husky@8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - ignore@^5.1.1, ignore@^5.2.0: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== -immutable@^4.0.0-rc.12: - version "4.2.4" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.4.tgz#83260d50889526b4b531a5e293709a77f7c55a2a" - integrity sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w== - import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -3324,7 +2138,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: +inherits@2, inherits@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3334,25 +2148,11 @@ ini@^1.3.4: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -io-ts@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" - integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== - dependencies: - fp-ts "^1.0.0" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - is-core-module@^2.5.0, is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" @@ -3385,7 +2185,7 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-glob@^4.0.1, is-glob@~4.0.1: +is-glob@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -3407,11 +2207,6 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - is-plain-obj@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" @@ -3434,11 +2229,6 @@ is-text-path@^1.0.1: dependencies: text-extensions "^1.0.0" -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - is-wsl@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -3451,10 +2241,10 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isows@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.6.tgz#0da29d706fa51551c663c627ace42769850f86e7" - integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw== +isows@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.7.tgz#1c06400b7eed216fbba3bcbd68f12490fc342915" + integrity sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" @@ -3879,23 +2669,11 @@ jest@29.7.0: import-local "^3.0.2" jest-cli "^29.7.0" -js-sha3@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@4.1.0, js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -3904,6 +2682,13 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -3926,23 +2711,11 @@ json-stable-stringify@^1.0.2: dependencies: jsonify "^0.0.1" -json-stream-stringify@^3.1.4: - version "3.1.6" - resolved "https://registry.yarnpkg.com/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz#ebe32193876fb99d4ec9f612389a8d8e2b5d54d4" - integrity sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog== - json5@^2.2.0, json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== - optionalDependencies: - graceful-fs "^4.1.6" - jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -3962,15 +2735,6 @@ jsonparse@^1.2.0: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== -keccak@^3.0.0, keccak@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" - integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - readable-stream "^3.6.0" - kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -4105,19 +2869,11 @@ lodash.upperfirst@^4.3.1: resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== -lodash@^4.17.11, lodash@^4.17.15: +lodash@^4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - log-update@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" @@ -4154,11 +2910,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lru_map@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" - integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== - make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -4188,20 +2939,6 @@ map-obj@^4.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -memorystream@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== - meow@^8.0.0, meow@^8.1.2: version "8.1.2" resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897" @@ -4229,22 +2966,6 @@ merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micro-eth-signer@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/micro-eth-signer/-/micro-eth-signer-0.14.0.tgz#8aa1fe997d98d6bdf42f2071cef7eb01a66ecb22" - integrity sha512-5PLLzHiVYPWClEvZIXXFu5yutzpadb73rnQCpUqIHu3No3coFuWQNfE5tkBQJ7djuLYl6aRLaS0MgWJYGoqiBw== - dependencies: - "@noble/curves" "~1.8.1" - "@noble/hashes" "~1.7.1" - micro-packed "~0.7.2" - -micro-packed@~0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/micro-packed/-/micro-packed-0.7.2.tgz#7f9decd6c11fe2617bc85ad4ebc0ad48bf423f36" - integrity sha512-HJ/u8+tMzgrJVAl6P/4l8KGjJSA3SCZaRb1m4wpbovNScCSmVOGUYbkkcoPPcknCHWPpRAdjy+yqXqyQWf+k8g== - dependencies: - "@scure/base" "~1.2.2" - micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" @@ -4268,23 +2989,6 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - minimatch@^3.0.4, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -4306,75 +3010,21 @@ minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -mnemonist@^0.38.0: - version "0.38.5" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" - integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== - dependencies: - obliterator "^2.0.0" - -mocha@^10.0.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" - integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - nanoid "3.3.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - ms@3.0.0-canary.1: version "3.0.0-canary.1" resolved "https://registry.yarnpkg.com/ms/-/ms-3.0.0-canary.1.tgz#c7b34fbce381492fd0b345d1cf56e14d67b77b80" integrity sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g== -nanoid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -node-addon-api@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" - integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== - -node-addon-api@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" - integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== - node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -4382,11 +3032,6 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-gyp-build@^4.2.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" - integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== - node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -4417,7 +3062,7 @@ normalize-package-data@^3.0.0: semver "^7.3.4" validate-npm-package-license "^3.0.1" -normalize-path@^3.0.0, normalize-path@~3.0.0: +normalize-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -4441,11 +3086,6 @@ object-inspect@^1.12.3, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== -obliterator@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" - integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -4475,27 +3115,23 @@ open@^7.4.2: is-docker "^2.0.0" is-wsl "^2.1.1" -ordinal@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ordinal/-/ordinal-1.0.3.tgz#1a3c7726a61728112f50944ad7c35c06ae3a0d4d" - integrity sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ== - os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== -ox@0.6.9: - version "0.6.9" - resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.9.tgz#da1ee04fa10de30c8d04c15bfb80fe58b1f554bd" - integrity sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug== - dependencies: - "@adraffy/ens-normalize" "^1.10.1" - "@noble/curves" "^1.6.0" - "@noble/hashes" "^1.5.0" - "@scure/bip32" "^1.5.0" - "@scure/bip39" "^1.4.0" - abitype "^1.0.6" +ox@0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.8.1.tgz#c1328e4c890583b9c19d338126aef4b796d53543" + integrity sha512-e+z5epnzV+Zuz91YYujecW8cF01mzmrUtWotJ0oEPym/G82uccs7q0WDHTYL3eiONbTUEvcZrptAKLgTBD3u2A== + dependencies: + "@adraffy/ens-normalize" "^1.11.0" + "@noble/ciphers" "^1.3.0" + "@noble/curves" "^1.9.1" + "@noble/hashes" "^1.8.0" + "@scure/bip32" "^1.7.0" + "@scure/bip39" "^1.6.0" + abitype "^1.0.8" eventemitter3 "5.0.1" p-limit@^2.2.0: @@ -4596,7 +3232,7 @@ path-key@^4.0.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== -path-parse@^1.0.6, path-parse@^1.0.7: +path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -4611,37 +3247,16 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pbkdf2@^3.0.17: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picocolors@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== - pidtree@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" @@ -4708,23 +3323,6 @@ quick-lru@^4.0.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -raw-body@^2.4.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - react-is@^18.0.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" @@ -4749,7 +3347,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.6.0: +readable-stream@3, readable-stream@^3.0.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -4758,18 +3356,6 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdirp@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" - integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - redent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" @@ -4817,13 +3403,6 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.0.tgz#c1a0028c2d166ec2fbf7d0644584927e76e7400e" integrity sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg== -resolve@1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - resolve@^1.10.0, resolve@^1.20.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" @@ -4858,21 +3437,6 @@ rimraf@^2.6.3: dependencies: glob "^7.1.3" -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rlp@^2.2.4: - version "2.2.7" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" - integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== - dependencies: - bn.js "^5.2.0" - run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -4887,31 +3451,12 @@ rxjs@^7.8.0: dependencies: tslib "^2.1.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -scrypt-js@3.0.1, scrypt-js@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" - integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== - -secp256k1@^4.0.1: - version "4.0.4" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.4.tgz#58f0bfe1830fe777d9ca1ffc7574962a8189f8ab" - integrity sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw== - dependencies: - elliptic "^6.5.7" - node-addon-api "^5.0.0" - node-gyp-build "^4.2.0" - -"semver@2 || 3 || 4 || 5", semver@^5.5.0: +"semver@2 || 3 || 4 || 5": version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== @@ -4928,31 +3473,6 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -serialize-javascript@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -5025,19 +3545,6 @@ slice-ansi@^5.0.0: ansi-styles "^6.0.0" is-fullwidth-code-point "^4.0.0" -solc@0.8.26: - version "0.8.26" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" - integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== - dependencies: - command-exists "^1.2.8" - commander "^8.1.0" - follow-redirects "^1.12.1" - js-sha3 "0.8.0" - memorystream "^0.3.1" - semver "^5.5.0" - tmp "0.0.33" - sort-object-keys@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" @@ -5064,14 +3571,6 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.13: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -5122,18 +3621,6 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" -stacktrace-parser@^0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" - integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== - dependencies: - type-fest "^0.7.1" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - string-argv@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" @@ -5147,7 +3634,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5213,18 +3700,11 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@3.1.1, strip-json-comments@^3.1.1: +strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -supports-color@8.1.1, supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -5239,6 +3719,13 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -5270,15 +3757,7 @@ through2@^4.0.0: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== -tinyglobby@^0.2.6: - version "0.2.13" - resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.13.tgz#a0e46515ce6cbcd65331537e57484af5a7b2ff7e" - integrity sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw== - dependencies: - fdir "^6.4.4" - picomatch "^4.0.2" - -tmp@0.0.33, tmp@^0.0.33: +tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== @@ -5302,11 +3781,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -5368,21 +3842,11 @@ tsconfig-replace-paths@0.0.14: globby "^10.0.1" json5 "^2.2.0" -tslib@^1.9.3: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - tslib@^2.1.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== -tsort@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" - integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== - type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -5393,11 +3857,6 @@ type-fest@^0.18.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" @@ -5408,11 +3867,6 @@ type-fest@^0.6.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -5428,28 +3882,11 @@ typescript@5.4.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== -undici@^5.14.0: - version "5.28.4" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" - integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g== - dependencies: - "@fastify/busboy" "^2.0.0" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== -unpipe@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - update-browserslist-db@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" @@ -5470,11 +3907,6 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" @@ -5497,19 +3929,19 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -viem@2.28.0: - version "2.28.0" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.28.0.tgz#b04bea64f067d6bfdb8603b39561b732a1e64066" - integrity sha512-Z4W5O1pe+6pirYTFm451FcZmfGAUxUWt2L/eWC+YfTF28j/8rd7q6MBAi05lMN4KhLJjhN0s5YGIPB+kf1L20g== +viem@2.33.1: + version "2.33.1" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.33.1.tgz#47ae1de711a1052f03f0f585be224383de812b03" + integrity sha512-++Dkj8HvSOLPMKEs+ZBNNcWbBRlUHcXNWktjIU22hgr6YmbUldV1sPTGLZa6BYRm06WViMjXj6HIsHt8rD+ZKQ== dependencies: - "@noble/curves" "1.8.2" - "@noble/hashes" "1.7.2" - "@scure/bip32" "1.6.2" - "@scure/bip39" "1.5.4" + "@noble/curves" "1.9.2" + "@noble/hashes" "1.8.0" + "@scure/bip32" "1.7.0" + "@scure/bip39" "1.6.0" abitype "1.0.8" - isows "1.0.6" - ox "0.6.9" - ws "8.18.1" + isows "1.0.7" + ox "0.8.1" + ws "8.18.2" walker@^1.0.8: version "1.0.8" @@ -5538,18 +3970,6 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== - wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -5581,20 +4001,10 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@7.4.6: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== - -ws@8.18.1: - version "8.18.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb" - integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w== - -ws@^7.4.6: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== +ws@8.18.2: + version "8.18.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.2.tgz#42738b2be57ced85f46154320aabb51ab003705a" + integrity sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ== y18n@^5.0.5: version "5.0.8" @@ -5616,12 +4026,7 @@ yaml@^2.2.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.2.2.tgz#ec551ef37326e6d42872dad1970300f8eb83a073" integrity sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA== -yargs-parser@20.2.4: - version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" - integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== - -yargs-parser@^20.2.2, yargs-parser@^20.2.3: +yargs-parser@^20.2.3: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== @@ -5631,29 +4036,6 @@ yargs-parser@^21.0.1, yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs-unparser@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - yargs@^17.0.0, yargs@^17.3.1: version "17.7.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.0.tgz#b21e9af1e0a619a2a9c67b1133219b2975a07985"