From 28ea67240d431e01363b8b4bac2bf316d5582c92 Mon Sep 17 00:00:00 2001 From: Leandro Date: Fri, 27 Oct 2023 10:03:15 -0700 Subject: [PATCH] feat(permit): refactor permit-utils package (#3258) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add permit-utils lib Generated using `nx g @nx/js:lib` command * chore: remove default files * feat: add utils to permit-utils package * feat: remove utils from modules/permit in favor of permit-utils pkg * chore: move PermitProviderConnector to utils * chore: updated eslint rules similar to main app * chore: remove external dependency on DAI * chore: remove types that are not used in the lib * chore: remove dependency on GP_VAULT_RELAYER * chore: remove dependency on @cowprotocol/common-utils * refactor: sorting imports * chore: update project name * chore: add readme * refactor: move buildPermitCallData to utils * refactor: rename checkIsTokenPermittable to getTokenPermitInfo * chore: move IsTokenPermittableResult back to modules/permit * chore: set permit-utils pkg version to 0.0.1-RC.0 * refactor: export fns individually rather than everything from the file * fix: typo on project name 🤦 * chore: fix config with `nx repair` * fix: project name has to match path I think. Now it builds * chore: pick the version from package.json when publishing a package * chore: add otp arg to all projects * chore: copy README on publish to dist folder so it gets added to npm * chore: remove dependency on cow-sdk package * fix: must have macrosPlugin as part of vite.config * chore: change provider type to JsonRpcProvider * chore: expose GetTokenPermitIntoResult * chore: remove stuff added automatically which are not needed * fix: js code style * chore: remove commands which are not relevant in the NPM context * chore: add somewhat complete usage example * chore: remove another dep added automatically jest-environment-node * chore: import AbiInput from @1inch lib instead of directly from web3 * chore: remove @ethersproject/bignumber dep. Already part of ethers * refactor: removed extra comma * refactor: remove dependency on @uniswap/core * chore: exclude all external dependencies from the build * chore: change package type from commonjs to module * chore: add required dependencies to lib package.json * feat: set different entry points for different module styles * chore: update some package dependencies * fix: exclusions MUST not be the whole /node_modules/ as it breaks the generated bundle * fix: no longer using Token type on permit-utils * fix: uploaded local registry path by mistake --- .../src/modules/permit/const.ts | 30 -- .../hooks/useAccountAgnosticPermitHookData.ts | 8 +- .../hooks/useCheckHasValidPendingPermit.ts | 60 +--- .../permit/hooks/useGeneratePermitHook.ts | 11 +- .../permit/hooks/useIsTokenPermittable.ts | 9 +- .../src/modules/permit/types.ts | 60 +--- .../src/modules/permit/utils/handlePermit.ts | 4 +- .../modules/swap/services/swapFlow/index.ts | 4 +- apps/cowswap-frontend/tsconfig.json | 3 +- apps/widget-configurator/project.json | 2 +- jest.config.ts | 5 + libs/abis/project.json | 2 +- libs/permit-utils/.eslintrc.json | 81 +++++ libs/permit-utils/README.md | 153 +++++++++ libs/permit-utils/jest.config.ts | 11 + libs/permit-utils/package.json | 19 ++ libs/permit-utils/project.json | 41 +++ libs/permit-utils/src/const.ts | 28 ++ libs/permit-utils/src/index.ts | 13 + .../src/lib/checkIsCallDataAValidPermit.ts | 53 ++++ .../src/lib}/generatePermitHook.ts | 13 +- .../src/lib}/getPermitUtilsInstance.ts | 11 +- .../src/lib/getTokenPermitInfo.ts | 29 +- libs/permit-utils/src/types.ts | 59 ++++ .../src}/utils/PermitProviderConnector.ts | 20 +- .../src}/utils/buildPermitCallData.ts | 0 .../permit-utils/src}/utils/fixTokenName.ts | 0 .../src}/utils/getPermitDeadline.ts | 0 libs/permit-utils/tsconfig.json | 22 ++ libs/permit-utils/tsconfig.lib.json | 10 + libs/permit-utils/tsconfig.spec.json | 9 + libs/permit-utils/vite.config.ts | 52 ++++ libs/ui-utils/project.json | 2 +- libs/widget-lib/project.json | 3 +- libs/widget-react/project.json | 2 +- nx.json | 34 +- package.json | 7 +- tools/scripts/publish.mjs | 34 +- tsconfig.base.json | 1 + yarn.lock | 290 ++++++++++++++++-- 40 files changed, 937 insertions(+), 258 deletions(-) create mode 100644 jest.config.ts create mode 100644 libs/permit-utils/.eslintrc.json create mode 100644 libs/permit-utils/README.md create mode 100644 libs/permit-utils/jest.config.ts create mode 100644 libs/permit-utils/package.json create mode 100644 libs/permit-utils/project.json create mode 100644 libs/permit-utils/src/const.ts create mode 100644 libs/permit-utils/src/index.ts create mode 100644 libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts rename {apps/cowswap-frontend/src/modules/permit/utils => libs/permit-utils/src/lib}/generatePermitHook.ts (89%) rename {apps/cowswap-frontend/src/modules/permit/utils => libs/permit-utils/src/lib}/getPermitUtilsInstance.ts (84%) rename apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts => libs/permit-utils/src/lib/getTokenPermitInfo.ts (84%) create mode 100644 libs/permit-utils/src/types.ts rename {apps/cowswap-frontend/src/modules/wallet => libs/permit-utils/src}/utils/PermitProviderConnector.ts (80%) rename {apps/cowswap-frontend/src/modules/permit => libs/permit-utils/src}/utils/buildPermitCallData.ts (100%) rename {apps/cowswap-frontend/src/modules/permit => libs/permit-utils/src}/utils/fixTokenName.ts (100%) rename {apps/cowswap-frontend/src/modules/permit => libs/permit-utils/src}/utils/getPermitDeadline.ts (100%) create mode 100644 libs/permit-utils/tsconfig.json create mode 100644 libs/permit-utils/tsconfig.lib.json create mode 100644 libs/permit-utils/tsconfig.spec.json create mode 100644 libs/permit-utils/vite.config.ts diff --git a/apps/cowswap-frontend/src/modules/permit/const.ts b/apps/cowswap-frontend/src/modules/permit/const.ts index b6225c5134..877ced2cb4 100644 --- a/apps/cowswap-frontend/src/modules/permit/const.ts +++ b/apps/cowswap-frontend/src/modules/permit/const.ts @@ -1,30 +1,7 @@ -import { DAI } from '@cowprotocol/common-const' -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { MaxUint256 } from '@ethersproject/constants' -import { Wallet } from '@ethersproject/wallet' - import ms from 'ms.macro' import { TradeType } from '../trade' -// PK used only for signing permit requests for quoting and identifying token 'permittability' -// Do not use or try to send funds to it. Or do. It'll be your funds 🤷 -const PERMIT_PK = '0xc58a2a421ca71ca57ae698f1c32feeb0b0ccb434da0b8089d88d80fb918f3f9d' // address: 0xFf65D1DfCF256cf4A8D5F2fb8e70F936606B7474 - -export const PERMIT_SIGNER = new Wallet(PERMIT_PK) - -export const PERMIT_GAS_LIMIT_MIN: Record = { - 1: 55_000, - 100: 55_000, - 5: 36_000, -} - -export const DEFAULT_PERMIT_GAS_LIMIT = '80000' - -export const DEFAULT_PERMIT_VALUE = MaxUint256.toString() - -export const DEFAULT_PERMIT_DURATION = ms`5 years` - export const ORDER_TYPE_SUPPORTS_PERMIT: Record = { [TradeType.SWAP]: true, [TradeType.LIMIT_ORDER]: true, @@ -32,10 +9,3 @@ export const ORDER_TYPE_SUPPORTS_PERMIT: Record = { } export const PENDING_ORDER_PERMIT_CHECK_INTERVAL = ms`1min` - -// DAI's mainnet contract (https://etherscan.io/address/0x6b175474e89094c44da98b954eedeac495271d0f#readContract) returns -// `1` for the version, while when calling the contract method returns `2`. -// Also, if we use the version returned by the contract, it simply doesn't work -// Thus, do not call it for DAI. -// TODO: figure out whether more tokens behave the same way -export const TOKENS_TO_SKIP_VERSION = new Set([DAI.address.toLowerCase()]) diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts index 458cbe3e21..580e46f2ee 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' -import { Token } from '@uniswap/sdk-core' +import { PermitHookData } from '@cowprotocol/permit-utils' import { useDerivedTradeState } from 'modules/trade' @@ -9,7 +9,7 @@ import { useSafeMemo } from 'common/hooks/useSafeMemo' import { useGeneratePermitHook } from './useGeneratePermitHook' import { useIsTokenPermittable } from './useIsTokenPermittable' -import { GeneratePermitHookParams, PermitHookData } from '../types' +import { GeneratePermitHookParams } from '../types' /** * Returns PermitHookData using an account agnostic signer if inputCurrency is permittable @@ -44,10 +44,10 @@ function useGeneratePermitHookParams(): GeneratePermitHookParams | undefined { const permitInfo = useIsTokenPermittable(inputCurrency, tradeType) return useSafeMemo(() => { - if (!inputCurrency || !permitInfo) return undefined + if (!inputCurrency || !('address' in inputCurrency) || !permitInfo) return undefined return { - inputToken: inputCurrency as Token, + inputToken: { address: inputCurrency.address, name: inputCurrency.name }, permitInfo, } }, [inputCurrency, permitInfo]) diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts index 75144a1c9f..b32c0410ad 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts @@ -1,21 +1,18 @@ import { useCallback } from 'react' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { checkIsCallDataAValidPermit, getPermitUtilsInstance, PermitInfo } from '@cowprotocol/permit-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { Web3Provider } from '@ethersproject/providers' import { useWeb3React } from '@web3-react/core' -import { DAI_PERMIT_SELECTOR, Eip2612PermitUtils, EIP_2612_PERMIT_SELECTOR } from '@1inch/permit-signed-approvals-utils' - import { getAppDataHooks } from 'modules/appData' import { ParsedOrder } from 'utils/orderUtils/parseOrder' import { useGetPermitInfo } from './useGetPermitInfo' -import { CheckHasValidPendingPermit, PermitInfo, SupportedPermitInfo } from '../types' -import { fixTokenName } from '../utils/fixTokenName' -import { getPermitUtilsInstance } from '../utils/getPermitUtilsInstance' +import { CheckHasValidPendingPermit } from '../types' export function useCheckHasValidPendingPermit(): CheckHasValidPendingPermit { const { chainId } = useWalletInfo() @@ -38,7 +35,7 @@ export function useCheckHasValidPendingPermit(): CheckHasValidPendingPermit { return checkHasValidPendingPermit(order, provider, chainId, permitInfo) }, - [chainId, provider] + [chainId, getPermitInfo, provider] ) } @@ -71,7 +68,7 @@ async function checkHasValidPendingPermit( const checkedHooks = await Promise.all( preHooks.map(({ callData }) => - checkIsSingleCallDataAValidPermit(order, chainId, eip2162Utils, tokenAddress, tokenName, callData, permitInfo) + checkIsCallDataAValidPermit(order.owner, chainId, eip2162Utils, tokenAddress, tokenName, callData, permitInfo) ) ) @@ -85,52 +82,3 @@ async function checkHasValidPendingPermit( // Only when all permits are valid, then the order permits are still valid return validPermits.every(Boolean) } - -async function checkIsSingleCallDataAValidPermit( - order: ParsedOrder, - chainId: SupportedChainId, - eip2162Utils: Eip2612PermitUtils, - tokenAddress: string, - tokenName: string, - callData: string, - { version }: SupportedPermitInfo -): Promise { - const params = { chainId, tokenName: fixTokenName(tokenName), tokenAddress, callData, version } - - let recoverPermitOwnerPromise: Promise | undefined = undefined - - // If pre-hook doesn't start with either selector, it's not a permit - if (callData.startsWith(EIP_2612_PERMIT_SELECTOR)) { - recoverPermitOwnerPromise = eip2162Utils.recoverPermitOwnerFromCallData({ - ...params, - // I don't know why this was removed, ok? - // We added it back on buildPermitCallData.ts - // But it looks like this is needed 🤷 - // Check the test for this method https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.test.ts#L85-L106 - callData: callData.replace(EIP_2612_PERMIT_SELECTOR, '0x'), - }) - } else if (callData.startsWith(DAI_PERMIT_SELECTOR)) { - recoverPermitOwnerPromise = eip2162Utils.recoverDaiLikePermitOwnerFromCallData({ - ...params, - callData: callData.replace(DAI_PERMIT_SELECTOR, '0x'), - }) - } - - if (!recoverPermitOwnerPromise) { - // The callData doesn't match any known permit type - return undefined - } - - try { - const recoveredOwner = await recoverPermitOwnerPromise - - // Permit is valid when recovered owner matches order owner - return recoveredOwner.toLowerCase() === order.owner.toLowerCase() - } catch (e) { - console.debug( - `[checkHasValidPendingPermit] Failed to check permit validity for order ${order.id} with callData ${callData}`, - e - ) - return false - } -} diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts index 82edb237c0..2a821920e9 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts @@ -1,6 +1,8 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useCallback } from 'react' +import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' +import { generatePermitHook, getPermitUtilsInstance, PermitHookData } from '@cowprotocol/permit-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' @@ -10,9 +12,7 @@ import { storePermitCacheAtom, userPermitCacheAtom, } from '../state/permitCacheAtom' -import { GeneratePermitHook, GeneratePermitHookParams, PermitHookData } from '../types' -import { generatePermitHook } from '../utils/generatePermitHook' -import { getPermitUtilsInstance } from '../utils/getPermitUtilsInstance' +import { GeneratePermitHook, GeneratePermitHookParams } from '../types' /** * Hook that returns callback to generate permit hook data @@ -32,6 +32,8 @@ export function useGeneratePermitHook(): GeneratePermitHook { const { chainId } = useWalletInfo() const { provider } = useWeb3React() + const spender = GP_VAULT_RELAYER[chainId] + return useCallback( async (params: GeneratePermitHookParams): Promise => { const { inputToken, account, permitInfo } = params @@ -57,6 +59,7 @@ export function useGeneratePermitHook(): GeneratePermitHook { const hookData = await generatePermitHook({ chainId, inputToken, + spender, provider, permitInfo, eip2162Utils, @@ -68,6 +71,6 @@ export function useGeneratePermitHook(): GeneratePermitHook { return hookData }, - [storePermit, chainId, getCachedPermit, provider] + [provider, chainId, getCachedPermit, spender, storePermit] ) } diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts index e8019ce7ed..13328d0eab 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts @@ -1,8 +1,10 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useEffect, useMemo } from 'react' +import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' import { getIsNativeToken, getWrappedToken } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { getTokenPermitInfo } from '@cowprotocol/permit-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' @@ -16,7 +18,6 @@ import { useIsPermitEnabled } from 'common/hooks/featureFlags/useIsPermitEnabled import { ORDER_TYPE_SUPPORTS_PERMIT } from '../const' import { addPermitInfoForTokenAtom, permittableTokensAtom } from '../state/permittableTokensAtom' import { IsTokenPermittableResult } from '../types' -import { checkIsTokenPermittable } from '../utils/checkIsTokenPermittable' /** * Checks whether the token is permittable, and caches the result on localStorage @@ -45,12 +46,14 @@ export function useIsTokenPermittable( const addPermitInfo = useAddPermitInfo() const permitInfo = usePermitInfo(chainId, isPermitEnabled ? lowerCaseAddress : undefined) + const spender = GP_VAULT_RELAYER[chainId] + useEffect(() => { if (!chainId || !isPermitEnabled || !lowerCaseAddress || !provider || permitInfo !== undefined || isNative) { return } - checkIsTokenPermittable({ tokenAddress: lowerCaseAddress, tokenName, chainId, provider }).then((result) => { + getTokenPermitInfo({ spender, tokenAddress: lowerCaseAddress, tokenName, chainId, provider }).then((result) => { if (!result) { // When falsy, we know it doesn't support permit. Cache it. addPermitInfo({ chainId, tokenAddress: lowerCaseAddress, permitInfo: false }) @@ -64,7 +67,7 @@ export function useIsTokenPermittable( addPermitInfo({ chainId, tokenAddress: lowerCaseAddress, permitInfo: result }) } }) - }, [addPermitInfo, chainId, isNative, isPermitEnabled, lowerCaseAddress, permitInfo, provider, tokenName]) + }, [addPermitInfo, chainId, isNative, isPermitEnabled, lowerCaseAddress, permitInfo, provider, spender, tokenName]) if (isNative) { return false diff --git a/apps/cowswap-frontend/src/modules/permit/types.ts b/apps/cowswap-frontend/src/modules/permit/types.ts index 312b5442a9..f3c81b4318 100644 --- a/apps/cowswap-frontend/src/modules/permit/types.ts +++ b/apps/cowswap-frontend/src/modules/permit/types.ts @@ -1,80 +1,30 @@ -import { latest } from '@cowprotocol/app-data' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { Web3Provider } from '@ethersproject/providers' -import { Token } from '@uniswap/sdk-core' - -import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' +import { PermitHookData, PermitHookParams, PermitInfo } from '@cowprotocol/permit-utils' +import { Currency } from '@uniswap/sdk-core' import { AppDataInfo } from 'modules/appData' import { ParsedOrder } from 'utils/orderUtils/parseOrder' -export type PermitType = 'dai-like' | 'eip-2612' - -export type SupportedPermitInfo = { - type: PermitType - version: string | undefined // Some tokens have it different than `1`, and won't work without it -} -type UnsupportedPermitInfo = false -export type PermitInfo = SupportedPermitInfo | UnsupportedPermitInfo +export type IsTokenPermittableResult = PermitInfo | undefined export type PermittableTokens = Record> -export type IsTokenPermittableResult = PermitInfo | undefined - export type AddPermitTokenParams = { chainId: SupportedChainId tokenAddress: string permitInfo: PermitInfo } -export type PermitHookParams = { - inputToken: Token - chainId: SupportedChainId - permitInfo: SupportedPermitInfo - provider: Web3Provider - eip2162Utils: Eip2612PermitUtils - account?: string | undefined - nonce?: number | undefined -} - export type GeneratePermitHookParams = Pick export type GeneratePermitHook = (params: GeneratePermitHookParams) => Promise -export type HandlePermitParams = Omit & { +export type HandlePermitParams = Omit & { permitInfo: IsTokenPermittableResult appData: AppDataInfo generatePermitHook: GeneratePermitHook -} - -export type PermitHookData = latest.CoWHook - -type FailedToIdentify = { error: string } - -export type EstimatePermitResult = - // When it's a permittable token: - | SupportedPermitInfo - // When something failed: - | FailedToIdentify - // When it's not permittable: - | UnsupportedPermitInfo - -type BasePermitCallDataParams = { - eip2162Utils: Eip2612PermitUtils -} -export type BuildEip2162PermitCallDataParams = BasePermitCallDataParams & { - callDataParams: Parameters -} -export type BuildDaiLikePermitCallDataParams = BasePermitCallDataParams & { - callDataParams: Parameters -} - -export type CheckIsTokenPermittableParams = { - tokenAddress: string - tokenName: string - chainId: SupportedChainId - provider: Web3Provider + inputToken: Currency } export type PermitCache = Record diff --git a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts index 38bc18b9c3..ce63421a0e 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts @@ -15,11 +15,11 @@ import { HandlePermitParams } from '../types' export async function handlePermit(params: HandlePermitParams): Promise { const { permitInfo, inputToken, account, appData, generatePermitHook } = params - if (permitInfo) { + if (permitInfo && 'address' in inputToken) { // permitInfo will only be set if there's NOT enough allowance const permitData = await generatePermitHook({ - inputToken, + inputToken: { address: inputToken.address, name: inputToken.name }, account, permitInfo, }) diff --git a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts index ec49a936b3..48e61f8b67 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts @@ -1,4 +1,4 @@ -import { Percent, Token } from '@uniswap/sdk-core' +import { Percent } from '@uniswap/sdk-core' import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { partialOrderUpdate } from 'legacy/state/orders/utils' @@ -30,7 +30,7 @@ export async function swapFlow( input.orderParams.appData = await handlePermit({ appData: input.orderParams.appData, - inputToken: input.context.trade.inputAmount.currency as Token, + inputToken: input.context.trade.inputAmount.currency, account: input.orderParams.account, permitInfo: input.permitInfo, generatePermitHook: input.generatePermitHook, diff --git a/apps/cowswap-frontend/tsconfig.json b/apps/cowswap-frontend/tsconfig.json index 2dae219c87..06f8eb146a 100644 --- a/apps/cowswap-frontend/tsconfig.json +++ b/apps/cowswap-frontend/tsconfig.json @@ -23,7 +23,8 @@ "@cowprotocol/common-hooks": ["../../../libs/common-hooks/src/index.ts"], "@cowprotocol/ens": ["../../../libs/ens/src/index.ts"], "@cowprotocol/core": ["../../../libs/core/src/index.ts"], - "@cowprotocol/analytics": ["../../../libs/analytics/src/index.ts"] + "@cowprotocol/analytics": ["../../../libs/analytics/src/index.ts"], + "@cowprotocol/permit-utils": ["../../../libs/permit-utils/src/index.ts"] } }, "files": [], diff --git a/apps/widget-configurator/project.json b/apps/widget-configurator/project.json index 8d65c4e860..4932fe22c2 100644 --- a/apps/widget-configurator/project.json +++ b/apps/widget-configurator/project.json @@ -54,7 +54,7 @@ }, "test": { "executor": "@nx/vite:test", - "outputs": ["coverage/apps/widget-configurator"], + "outputs": ["{workspaceRoot}/coverage/apps/widget-configurator"], "options": { "passWithNoTests": true, "reportsDirectory": "../../coverage/apps/widget-configurator" diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000000..64f7210caf --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,5 @@ +import { getJestProjects } from '@nx/jest' + +export default { + projects: getJestProjects(), +} diff --git a/libs/abis/project.json b/libs/abis/project.json index c0bc448f2d..c874f941b7 100644 --- a/libs/abis/project.json +++ b/libs/abis/project.json @@ -34,7 +34,7 @@ } }, "publish": { - "command": "node tools/scripts/publish.mjs abis {args.ver} {args.tag}", + "command": "node tools/scripts/publish.mjs abis {args.tag} {args.otp}", "dependsOn": ["build"] }, "lint": { diff --git a/libs/permit-utils/.eslintrc.json b/libs/permit-utils/.eslintrc.json new file mode 100644 index 0000000000..60b6753f20 --- /dev/null +++ b/libs/permit-utils/.eslintrc.json @@ -0,0 +1,81 @@ +{ + "extends": [ + "../../.eslintrc.json" + ], + "ignorePatterns": [ + "!**/*" + ], + "plugins": [ + "unused-imports", + "eslint-plugin-import" + ], + "rules": { + "@typescript-eslint/no-unused-vars": "off", + "no-unused-vars": "off", + "unused-imports/no-unused-imports": "error", + "unused-imports/no-unused-vars": [ + "error", + { + "vars": "all", + "varsIgnorePattern": "^_", + "args": "after-used", + "argsIgnorePattern": "^_" + } + ], + "import/order": [ + "error", + { + "pathGroups": [ + { + "pattern": "{@cowprotocol,@uniswap,@safe-global,@ethersproject,@web3-react,@1inch}/**", + "group": "external", + "position": "before" + } + ], + "groups": [ + "external", + "builtin", + "internal", + "sibling", + "parent", + "object", + "index", + "type" + ], + "alphabetize": { + "order": "asc", + "caseInsensitive": true + }, + "newlines-between": "always" + } + ], + "prefer-const": "error", + "no-unneeded-ternary": "error", + "no-var": "error" + }, + "overrides": [ + { + "files": [ + "*.ts", + "*.tsx", + "*.js", + "*.jsx" + ], + "rules": {} + }, + { + "files": [ + "*.ts", + "*.tsx" + ], + "rules": {} + }, + { + "files": [ + "*.js", + "*.jsx" + ], + "rules": {} + } + ] +} diff --git a/libs/permit-utils/README.md b/libs/permit-utils/README.md new file mode 100644 index 0000000000..52176a084d --- /dev/null +++ b/libs/permit-utils/README.md @@ -0,0 +1,153 @@ +# @cowprotocol/permit-utils + +Collection of utils for handling token permits. + +## Installation + +```bash +yarn add @cowprotocol/permit-utils +``` + +## Usage + +### `getTokenPermitInfo` + +```typescript +import { getTokenPermitInfo } from "@cowprotocol/permit-utils" + +const permitInfo = await getTokenPermitInfo({ + spender, tokenAddress, tokenName, chainId, provider +}) +``` + +### `getPermitUtilsInstance` + +```typescript +import { getPermitUtilsInstance } from "@cowprotocol/permit-utils" + +// Using the a static account defined in the library +const staticEip2612PermitUtils = getPermitUtilsInstance(chainId, provider) + +// Using a provided account address +const accountEip2612PermitUtils = getPermitUtilsInstance(chainId, provider, account) +``` + +### `generatePermitHook` + +```typescript +import { generatePermitHook } from "@cowprotocol/permit-utils" + +const hookData = await generatePermitHook({ + chainId, + inputToken, + spender, + provider, + permitInfo, + eip2162Utils, + account, + nonce +}) +``` + +### `checkIsCallDataAValidPermit` + +```typescript +import { checkIsCallDataAValidPermit } from "@cowprotocol/permit-utils" + +const isCallDataAValidPermit = await checkIsCallDataAValidPermit( + account, + chainId, + eip2612Utils, + tokenAddress, + tokenName, + callData, + permitInfo +) +``` + +**Full flow example** + +To illustrate, we'll show the flow of placing an order with a permit hook using the utils in this lib. + +1. Check whether a given token is permittable +2. If it is, generate a permit hook +3. Add permit hook to order's appData +4. Periodically check whether the permit is still valid + +```typescript +import { checkIsCallDataAValidPermit, generatePermitHook, getPermitUtilsInstance, getTokenPermitInfo } from '@cowprotocol/permit-utils' +import { stringifyDeterministic } from '@cowprotocol/app-data' +import { OrderBookApi } from '@cowprotocol/cow-sdk' + + +// Check whether token is permittable. +// No account info is necessary. +// `spender` could in theory be any address +// `tokenName` must always match the contract +const permitInfo = await getTokenPermitInfo({ + spender, tokenAddress, tokenName, chainId, provider +}) + +// Not able to tell or not permittable +if (!permitInfo) { + return +} + +// Pass in an account address as we'll need the user to sign the actual permit +const eip2612Utils = getPermitUtilsInstance(chainId, provider, account) + +// Need to know what the current permit nonce is +const nonce = await eip2162Utils.getTokenNonce(inputToken.address, account) + +// Calling this fn should trigger the signature in the user's wallet +const hookData = await generatePermitHook({ + chainId, + inputToken, + spender, // Now `spender` must be the real one + provider, + permitInfo, + eip2612Utils, + account, // `account` should also be the user's + nonce +}) + +// Add the hookData to the order's appData +// See the full reference on https://github.com/cowprotocol/app-data/ +const appData = { version: '0.10.0', metadata: { hooks: { pre: [hookData] } } } + +// The order expects the stringified JSON doc +const fullAppData = await stringifyDeterministic(appData) + +// Build cow-sdk orderBookApi instance +const orderBookApi = new OrderBookApi() + +// Note: price quoting is a required step before placing the order but has been left out of this example for brevity + +// Place order +const orderId = await orderBookApi.sendOrder( + { + ...orderParameters, + quoteId, // Must be fetched before hand, and also include the appData in the params + appData: fullAppData // <-- The order will be placed with the permit info + }, + { chainId } +) + +// Now we check whether the permit included in the order is still valid +// It'll become invalid when another permit is executed +// This check does not consider whether the `address` has enough allowance, it purelly checks the permit validity. + +// CallData is part of the hookData +const callData = hookData.callData + +// All properties must match what was used when the hookData was generated +const isCallDataAValidPermit = await checkIsCallDataAValidPermit( + account, + chainId, + eip2612Utils, + tokenAddress, + tokenName, + callData, + permitInfo +) +``` diff --git a/libs/permit-utils/jest.config.ts b/libs/permit-utils/jest.config.ts new file mode 100644 index 0000000000..58793e30dd --- /dev/null +++ b/libs/permit-utils/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'permit-utils', + preset: '../../jest.preset.js', + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../coverage/libs/permit-utils', +} diff --git a/libs/permit-utils/package.json b/libs/permit-utils/package.json new file mode 100644 index 0000000000..d9616d2411 --- /dev/null +++ b/libs/permit-utils/package.json @@ -0,0 +1,19 @@ +{ + "name": "@cowprotocol/permit-utils", + "version": "0.0.1-RC.0", + "type": "module", + "dependencies": { + "ethers": "^5.7.2", + "@1inch/permit-signed-approvals-utils": "^1.4.10", + "@cowprotocol/app-data": "^1.1.0", + "tslib": "^2.6.1" + }, + "module": "./index.js", + "main": "./index.cjs", + "exports": { + ".": { + "import": "./index.js", + "require": "./index.cjs" + } + } +} diff --git a/libs/permit-utils/project.json b/libs/permit-utils/project.json new file mode 100644 index 0000000000..0c02d0157b --- /dev/null +++ b/libs/permit-utils/project.json @@ -0,0 +1,41 @@ +{ + "name": "permit-utils", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/permit-utils/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/libs/permit-utils" + } + }, + "publish": { + "command": "node tools/scripts/publish.mjs permit-utils {args.tag} {args.otp}", + "dependsOn": ["build"] + }, + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/permit-utils/**/*.ts"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/permit-utils/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + }, + "tags": [] +} diff --git a/libs/permit-utils/src/const.ts b/libs/permit-utils/src/const.ts new file mode 100644 index 0000000000..ee0215868a --- /dev/null +++ b/libs/permit-utils/src/const.ts @@ -0,0 +1,28 @@ +import { MaxUint256 } from '@ethersproject/constants' +import { Wallet } from '@ethersproject/wallet' +import ms from 'ms.macro' + +// PK used only for signing permit requests for quoting and identifying token 'permittability' +// Do not use or try to send funds to it. Or do. It'll be your funds 🤷 +const PERMIT_PK = '0xc58a2a421ca71ca57ae698f1c32feeb0b0ccb434da0b8089d88d80fb918f3f9d' // address: 0xFf65D1DfCF256cf4A8D5F2fb8e70F936606B7474 + +export const PERMIT_SIGNER = new Wallet(PERMIT_PK) + +export const PERMIT_GAS_LIMIT_MIN: Record = { + 1: 55_000, + 100: 55_000, + 5: 36_000, +} + +export const DEFAULT_PERMIT_GAS_LIMIT = '80000' + +export const DEFAULT_PERMIT_VALUE = MaxUint256.toString() + +export const DEFAULT_PERMIT_DURATION = ms`5 years` + +// DAI's mainnet contract (https://etherscan.io/address/0x6b175474e89094c44da98b954eedeac495271d0f#readContract) returns +// `1` for the version, while when calling the contract method returns `2`. +// Also, if we use the version returned by the contract, it simply doesn't work +// Thus, do not call it for DAI. +// TODO: figure out whether more tokens behave the same way +export const TOKENS_TO_SKIP_VERSION = new Set(['0x6b175474e89094c44da98b954eedeac495271d0f']) diff --git a/libs/permit-utils/src/index.ts b/libs/permit-utils/src/index.ts new file mode 100644 index 0000000000..3edad2af5e --- /dev/null +++ b/libs/permit-utils/src/index.ts @@ -0,0 +1,13 @@ +export { checkIsCallDataAValidPermit } from './lib/checkIsCallDataAValidPermit' +export { generatePermitHook } from './lib/generatePermitHook' +export { getPermitUtilsInstance } from './lib/getPermitUtilsInstance' +export { getTokenPermitInfo } from './lib/getTokenPermitInfo' + +export type { + PermitHookData, + PermitHookParams, + PermitInfo, + PermitType, + SupportedPermitInfo, + GetTokenPermitIntoResult, +} from './types' diff --git a/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts b/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts new file mode 100644 index 0000000000..7c9c4cd48c --- /dev/null +++ b/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts @@ -0,0 +1,53 @@ +import { DAI_PERMIT_SELECTOR, Eip2612PermitUtils, EIP_2612_PERMIT_SELECTOR } from '@1inch/permit-signed-approvals-utils' + +import { SupportedPermitInfo } from '../types' +import { fixTokenName } from '../utils/fixTokenName' + +export async function checkIsCallDataAValidPermit( + owner: string, + chainId: number, + eip2162Utils: Eip2612PermitUtils, + tokenAddress: string, + tokenName: string, + callData: string, + { version }: SupportedPermitInfo +): Promise { + const params = { chainId, tokenName: fixTokenName(tokenName), tokenAddress, callData, version } + + let recoverPermitOwnerPromise: Promise | undefined = undefined + + // If pre-hook doesn't start with either selector, it's not a permit + if (callData.startsWith(EIP_2612_PERMIT_SELECTOR)) { + recoverPermitOwnerPromise = eip2162Utils.recoverPermitOwnerFromCallData({ + ...params, + // I don't know why this was removed, ok? + // We added it back on buildPermitCallData.ts + // But it looks like this is needed 🤷 + // Check the test for this method https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.test.ts#L85-L106 + callData: callData.replace(EIP_2612_PERMIT_SELECTOR, '0x'), + }) + } else if (callData.startsWith(DAI_PERMIT_SELECTOR)) { + recoverPermitOwnerPromise = eip2162Utils.recoverDaiLikePermitOwnerFromCallData({ + ...params, + callData: callData.replace(DAI_PERMIT_SELECTOR, '0x'), + }) + } + + if (!recoverPermitOwnerPromise) { + // The callData doesn't match any known permit type + return undefined + } + + try { + const recoveredOwner = await recoverPermitOwnerPromise + + // Permit is valid when recovered owner matches order owner + return recoveredOwner.toLowerCase() === owner.toLowerCase() + } catch (e) { + console.debug( + `[checkHasValidPendingPermit] Failed to check permit validity for owner ${owner} with callData ${callData}`, + e + ) + return false + } +} diff --git a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts b/libs/permit-utils/src/lib/generatePermitHook.ts similarity index 89% rename from apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts rename to libs/permit-utils/src/lib/generatePermitHook.ts index ea9db1f713..4299748a92 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts +++ b/libs/permit-utils/src/lib/generatePermitHook.ts @@ -1,11 +1,9 @@ -import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' -import { Web3Provider } from '@ethersproject/providers' - -import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData' -import { getPermitDeadline } from './getPermitDeadline' +import { JsonRpcProvider } from '@ethersproject/providers' import { DEFAULT_PERMIT_GAS_LIMIT, DEFAULT_PERMIT_VALUE, PERMIT_SIGNER } from '../const' import { PermitHookData, PermitHookParams } from '../types' +import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from '../utils/buildPermitCallData' +import { getPermitDeadline } from '../utils/getPermitDeadline' const REQUESTS_CACHE: { [permitKey: string]: Promise } = {} @@ -36,7 +34,7 @@ export async function generatePermitHook(params: PermitHookParams): Promise { - const { inputToken, chainId, permitInfo, provider, account, eip2162Utils, nonce: preFetchedNonce } = params + const { inputToken, spender, chainId, permitInfo, provider, account, eip2162Utils, nonce: preFetchedNonce } = params const tokenAddress = inputToken.address const tokenName = inputToken.name || tokenAddress @@ -46,7 +44,6 @@ async function generatePermitHookRaw(params: PermitHookParams): Promise { try { diff --git a/apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts b/libs/permit-utils/src/lib/getPermitUtilsInstance.ts similarity index 84% rename from apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts rename to libs/permit-utils/src/lib/getPermitUtilsInstance.ts index daeba06d33..2f0d891525 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts +++ b/libs/permit-utils/src/lib/getPermitUtilsInstance.ts @@ -1,11 +1,9 @@ -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import type { Web3Provider } from '@ethersproject/providers' +import type { JsonRpcProvider } from '@ethersproject/providers' import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' -import { PermitProviderConnector } from 'modules/wallet/utils/PermitProviderConnector' - import { PERMIT_SIGNER } from '../const' +import { PermitProviderConnector } from '../utils/PermitProviderConnector' /** * Cache by network. Here we don't care about the provider as a static account will be used for the signature @@ -17,8 +15,8 @@ const CHAIN_UTILS_CACHE = new Map() const PROVIDER_UTILS_CACHE = new Map() export function getPermitUtilsInstance( - chainId: SupportedChainId, - provider: Web3Provider, + chainId: number, + provider: JsonRpcProvider, account?: string | undefined ): Eip2612PermitUtils { const chainCache = CHAIN_UTILS_CACHE.get(chainId) @@ -33,6 +31,7 @@ export function getPermitUtilsInstance( return providerCache } + // TODO: allow to receive the signer as a parameter const web3ProviderConnector = new PermitProviderConnector(provider, account ? undefined : PERMIT_SIGNER) const eip2612PermitUtils = new Eip2612PermitUtils(web3ProviderConnector) diff --git a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts b/libs/permit-utils/src/lib/getTokenPermitInfo.ts similarity index 84% rename from apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts rename to libs/permit-utils/src/lib/getTokenPermitInfo.ts index 3b4c5dd599..cb347da253 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts +++ b/libs/permit-utils/src/lib/getTokenPermitInfo.ts @@ -1,15 +1,14 @@ -import { GP_VAULT_RELAYER, NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import type { Web3Provider } from '@ethersproject/providers' +import type { JsonRpcProvider } from '@ethersproject/providers' import { DAI_LIKE_PERMIT_TYPEHASH, Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' +import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData' -import { getPermitDeadline } from './getPermitDeadline' import { getPermitUtilsInstance } from './getPermitUtilsInstance' import { DEFAULT_PERMIT_VALUE, PERMIT_GAS_LIMIT_MIN, PERMIT_SIGNER, TOKENS_TO_SKIP_VERSION } from '../const' -import { CheckIsTokenPermittableParams, EstimatePermitResult, PermitType } from '../types' +import { GetTokenPermitInfoParams, GetTokenPermitIntoResult, PermitType } from '../types' +import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from '../utils/buildPermitCallData' +import { getPermitDeadline } from '../utils/getPermitDeadline' const EIP_2162_PERMIT_PARAMS = { value: DEFAULT_PERMIT_VALUE, @@ -23,14 +22,10 @@ const DAI_LIKE_PERMIT_PARAMS = { expiry: getPermitDeadline(), } -const REQUESTS_CACHE: Record> = {} +const REQUESTS_CACHE: Record> = {} -export async function checkIsTokenPermittable(params: CheckIsTokenPermittableParams): Promise { +export async function getTokenPermitInfo(params: GetTokenPermitInfoParams): Promise { const { tokenAddress, chainId } = params - if (NATIVE_CURRENCY_BUY_ADDRESS.toLowerCase() === tokenAddress.toLowerCase()) { - // We shouldn't call this for the native token, but just in case - return false - } const key = `${chainId}-${tokenAddress.toLowerCase()}` @@ -47,10 +42,8 @@ export async function checkIsTokenPermittable(params: CheckIsTokenPermittablePar return request } -async function actuallyCheckTokenIsPermittable(params: CheckIsTokenPermittableParams): Promise { - const { tokenAddress, tokenName, chainId, provider } = params - - const spender = GP_VAULT_RELAYER[chainId] +async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams): Promise { + const { spender, tokenAddress, tokenName, chainId, provider } = params const eip2612PermitUtils = getPermitUtilsInstance(chainId, provider) @@ -130,10 +123,10 @@ type BaseParams = { type EstimateParams = BaseParams & { type: PermitType - provider: Web3Provider + provider: JsonRpcProvider } -async function estimateTokenPermit(params: EstimateParams): Promise { +async function estimateTokenPermit(params: EstimateParams): Promise { const { provider, chainId, walletAddress, tokenAddress, type, version } = params const getCallDataFn = type === 'eip-2612' ? getEip2612CallData : getDaiLikeCallData diff --git a/libs/permit-utils/src/types.ts b/libs/permit-utils/src/types.ts new file mode 100644 index 0000000000..054aa5cef4 --- /dev/null +++ b/libs/permit-utils/src/types.ts @@ -0,0 +1,59 @@ +import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' +import { latest } from '@cowprotocol/app-data' +import { JsonRpcProvider } from '@ethersproject/providers' + +export type PermitType = 'dai-like' | 'eip-2612' + +export type SupportedPermitInfo = { + type: PermitType + version: string | undefined // Some tokens have it different than `1`, and won't work without it +} +type UnsupportedPermitInfo = false +export type PermitInfo = SupportedPermitInfo | UnsupportedPermitInfo + +// Local TokenInfo definition to not depend on external libs just for this +type TokenInfo = { + address: string + name: string | undefined +} + +export type PermitHookParams = { + inputToken: TokenInfo + spender: string + chainId: number + permitInfo: SupportedPermitInfo + provider: JsonRpcProvider + eip2162Utils: Eip2612PermitUtils + account?: string | undefined + nonce?: number | undefined +} + +export type PermitHookData = latest.CoWHook + +type FailedToIdentify = { error: string } + +export type GetTokenPermitIntoResult = + // When it's a permittable token: + | SupportedPermitInfo + // When something failed: + | FailedToIdentify + // When it's not permittable: + | UnsupportedPermitInfo + +type BasePermitCallDataParams = { + eip2162Utils: Eip2612PermitUtils +} +export type BuildEip2162PermitCallDataParams = BasePermitCallDataParams & { + callDataParams: Parameters +} +export type BuildDaiLikePermitCallDataParams = BasePermitCallDataParams & { + callDataParams: Parameters +} + +export type GetTokenPermitInfoParams = { + spender: string + tokenAddress: string + tokenName: string + chainId: number + provider: JsonRpcProvider +} diff --git a/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts b/libs/permit-utils/src/utils/PermitProviderConnector.ts similarity index 80% rename from apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts rename to libs/permit-utils/src/utils/PermitProviderConnector.ts index 8a8f6c47c0..fa0715cb9e 100644 --- a/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts +++ b/libs/permit-utils/src/utils/PermitProviderConnector.ts @@ -1,18 +1,21 @@ -import { getContract } from '@cowprotocol/common-utils' +import type { JsonRpcProvider } from '@ethersproject/providers' + +import { AbiInput, AbiItem, EIP712TypedData, ProviderConnector } from '@1inch/permit-signed-approvals-utils' import { defaultAbiCoder, ParamType } from '@ethersproject/abi' import { TypedDataField } from '@ethersproject/abstract-signer' import { BigNumber } from '@ethersproject/bignumber' -import type { Web3Provider } from '@ethersproject/providers' +import { Contract, ContractInterface } from '@ethersproject/contracts' import { Wallet } from '@ethersproject/wallet' -import { AbiItem, EIP712TypedData, ProviderConnector } from '@1inch/permit-signed-approvals-utils' -import { AbiInput } from 'web3-utils' - export class PermitProviderConnector implements ProviderConnector { - constructor(private provider: Web3Provider, private walletSigner?: Wallet | undefined) {} + constructor(private provider: JsonRpcProvider, private walletSigner?: Wallet | undefined) {} + + private getContract(address: string, abi: ContractInterface, provider: JsonRpcProvider): Contract { + return new Contract(address, abi, provider) + } contractEncodeABI(abi: AbiItem[], address: string | null, methodName: string, methodParams: unknown[]): string { - const contract = getContract(address || '', abi, this.provider) + const contract = this.getContract(address || '', abi, this.provider) return contract.interface.encodeFunctionData(methodName, methodParams) } @@ -42,6 +45,7 @@ export class PermitProviderConnector implements ProviderConnector { decodeABIParameter(type: string, hex: string): T { return defaultAbiCoder.decode([type], hex)[0] } + decodeABIParameters(types: AbiInput[], hex: string): T { const decodedValues = defaultAbiCoder.decode(types as unknown as (ParamType | string)[], hex) as T @@ -50,7 +54,7 @@ export class PermitProviderConnector implements ProviderConnector { // so we need this mess to convert them to hex strings, which 1inch understands // TODO: Any way to make this typing mess any cleaner? if (decodedValues && typeof decodedValues === 'object') { - const copy: Record = {} + const copy: Record = {} Object.keys(decodedValues).forEach((key) => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts b/libs/permit-utils/src/utils/buildPermitCallData.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts rename to libs/permit-utils/src/utils/buildPermitCallData.ts diff --git a/apps/cowswap-frontend/src/modules/permit/utils/fixTokenName.ts b/libs/permit-utils/src/utils/fixTokenName.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/permit/utils/fixTokenName.ts rename to libs/permit-utils/src/utils/fixTokenName.ts diff --git a/apps/cowswap-frontend/src/modules/permit/utils/getPermitDeadline.ts b/libs/permit-utils/src/utils/getPermitDeadline.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/permit/utils/getPermitDeadline.ts rename to libs/permit-utils/src/utils/getPermitDeadline.ts diff --git a/libs/permit-utils/tsconfig.json b/libs/permit-utils/tsconfig.json new file mode 100644 index 0000000000..f5b85657a8 --- /dev/null +++ b/libs/permit-utils/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/permit-utils/tsconfig.lib.json b/libs/permit-utils/tsconfig.lib.json new file mode 100644 index 0000000000..4befa7f099 --- /dev/null +++ b/libs/permit-utils/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true, + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/libs/permit-utils/tsconfig.spec.json b/libs/permit-utils/tsconfig.spec.json new file mode 100644 index 0000000000..b2ee74a6b1 --- /dev/null +++ b/libs/permit-utils/tsconfig.spec.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"] +} diff --git a/libs/permit-utils/vite.config.ts b/libs/permit-utils/vite.config.ts new file mode 100644 index 0000000000..c59b77528b --- /dev/null +++ b/libs/permit-utils/vite.config.ts @@ -0,0 +1,52 @@ +/// +import { defineConfig } from 'vite' +import macrosPlugin from 'vite-plugin-babel-macros' +import dts from 'vite-plugin-dts' +import viteTsConfigPaths from 'vite-tsconfig-paths' + +import * as path from 'path' + +export default defineConfig({ + cacheDir: '../../../node_modules/.vite/permit-utils', + + plugins: [ + dts({ + entryRoot: 'src', + tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'), + skipDiagnostics: true, + }), + + macrosPlugin(), + + viteTsConfigPaths({ + root: '../../../', + }), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + lib: { + // Could also be a dictionary or array of multiple entry points. + entry: 'src/index.ts', + name: 'permit-utils', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es', 'cjs'], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: [/@1inch/, /@cowprotocol/, /@ethersproject/], + }, + }, +}) diff --git a/libs/ui-utils/project.json b/libs/ui-utils/project.json index 1baadf2019..d0caffbae5 100644 --- a/libs/ui-utils/project.json +++ b/libs/ui-utils/project.json @@ -12,7 +12,7 @@ } }, "publish": { - "command": "node tools/scripts/publish.mjs ui {args.ver} {args.tag}", + "command": "node tools/scripts/publish.mjs ui {args.tag} {args.otp}", "dependsOn": ["build"] }, "lint": { diff --git a/libs/widget-lib/project.json b/libs/widget-lib/project.json index 5ad2c18b96..8f1745dc9c 100644 --- a/libs/widget-lib/project.json +++ b/libs/widget-lib/project.json @@ -3,7 +3,6 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "libs/widget-lib/src", "projectType": "library", - "targets": { "build": { "executor": "@nx/vite:build", @@ -22,7 +21,7 @@ "configurations": {} }, "publish": { - "command": "node tools/scripts/publish.mjs widget-lib {args.ver} {args.tag}", + "command": "node tools/scripts/publish.mjs widget-lib {args.tag} {args.otp}", "dependsOn": ["build"] }, "lint": { diff --git a/libs/widget-react/project.json b/libs/widget-react/project.json index 0303ac0825..5e460c29d1 100644 --- a/libs/widget-react/project.json +++ b/libs/widget-react/project.json @@ -29,7 +29,7 @@ } }, "publish": { - "command": "node tools/scripts/publish.mjs widget-react {args.ver} {args.tag}", + "command": "node tools/scripts/publish.mjs widget-react {args.tag} {args.otp}", "dependsOn": ["build"] }, "test": { diff --git a/nx.json b/nx.json index b02e49fd75..50390ce55c 100644 --- a/nx.json +++ b/nx.json @@ -7,27 +7,49 @@ "default": { "runner": "nx-cloud", "options": { - "cacheableOperations": ["build", "lint", "test", "e2e"], + "cacheableOperations": [ + "build", + "lint", + "test", + "e2e" + ], "accessToken": "M2U1ZmI5MTEtZmY3MS00YzRjLTkxYmQtZDhkM2QzZTBkNTVhfHJlYWQ=" } } }, "targetDefaults": { "build": { - "inputs": ["default", "production", "^production"] + "inputs": [ + "default", + "production", + "^production" + ] }, "e2e": { - "inputs": ["default", "^production"] + "inputs": [ + "default", + "^production" + ] }, "test": { - "inputs": ["default", "^production"] + "inputs": [ + "default", + "^production" + ] }, "lint": { - "inputs": ["default", "{workspaceRoot}/.eslintrc.json", "{workspaceRoot}/.eslintignore"] + "inputs": [ + "default", + "{workspaceRoot}/.eslintrc.json", + "{workspaceRoot}/.eslintignore" + ] } }, "namedInputs": { - "default": ["{projectRoot}/**/*", "sharedGlobals"], + "default": [ + "{projectRoot}/**/*", + "sharedGlobals" + ], "production": [ "default", "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", diff --git a/package.json b/package.json index 435b9c8d72..d07472690c 100644 --- a/package.json +++ b/package.json @@ -49,11 +49,11 @@ ] }, "dependencies": { - "@1inch/permit-signed-approvals-utils": "^1.4.8", + "@1inch/permit-signed-approvals-utils": "^1.4.10", "@amplitude/analytics-browser": "^1.1.4", "@babel/runtime": "^7.17.0", "@coinbase/wallet-sdk": "^3.3.0", - "@cowprotocol/app-data": "^1.1.0-RC.0", + "@cowprotocol/app-data": "^1.1.0", "@cowprotocol/contracts": "^1.3.1", "@cowprotocol/cow-runner-game": "^0.2.9", "@cowprotocol/cow-sdk": "^3.0.0-rc.0", @@ -61,7 +61,6 @@ "@davatar/react": "1.8.1", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@ethersproject/bignumber": "^5.7.0", "@ethersproject/experimental": "^5.7.0", "@ethvault/iframe-provider": "^0.1.10", "@fontsource/ibm-plex-mono": "^4.5.1", @@ -118,7 +117,7 @@ "cross-env": "^7.0.3", "d3": "^7.8.1", "date-fns": "^2.29.3", - "ethers": "^5.1.4", + "ethers": "^5.7.2", "exponential-backoff": "^3.1.1", "fast-deep-equal": "^3.1.3", "fast-safe-stringify": "^2.0.8", diff --git a/tools/scripts/publish.mjs b/tools/scripts/publish.mjs index a6214556eb..f752940b93 100644 --- a/tools/scripts/publish.mjs +++ b/tools/scripts/publish.mjs @@ -11,8 +11,9 @@ import devkit from '@nx/devkit' import chalk from 'chalk' import { execSync } from 'child_process' -import { readFileSync, writeFileSync } from 'fs' +import { readFileSync } from 'fs' import path from 'path' + const { readCachedProjectGraph } = devkit function invariant(condition, message) { @@ -22,16 +23,19 @@ function invariant(condition, message) { } } -// Executing publish script: node path/to/publish.mjs {name} --version {version} --tag {tag} +// Executing publish script: node path/to/publish.mjs {name} --tag {tag} // Default "tag" to "next" so we won't publish the "latest" tag by accident. -const [, , name, version, tag] = process.argv +const [, , name, tag, otp] = process.argv -// A simple SemVer validation to validate the version -const validVersion = /^\d+\.\d+\.\d+(-\w+\.\d+)?/ -invariant( - version && validVersion.test(version), - `No version provided or version did not match Semantic Versioning, expected: #.#.#-tag.# or #.#.#, got ${version}.` -) +// Fetch the version from "package.json" before publishing +let version +try { + const json = JSON.parse(readFileSync(`package.json`).toString()) + version = json.version +} catch (e) { + console.error(chalk.bold.red(`Error reading package.json file from library build output.`)) + process.exit(1) +} const graph = readCachedProjectGraph() const project = graph.nodes[name] @@ -47,19 +51,11 @@ invariant( const rootLib = path.dirname(project.data.sourceRoot) const copyReadmeCommand = `cp ${rootLib}/README.md ${outputPath}` console.log(chalk.bold.greenBright(copyReadmeCommand)) +execSync(copyReadmeCommand) process.chdir(outputPath) -// Updating the version in "package.json" before publishing -try { - const json = JSON.parse(readFileSync(`package.json`).toString()) - json.version = version - writeFileSync(`package.json`, JSON.stringify(json, null, 2)) -} catch (e) { - console.error(chalk.bold.red(`Error reading package.json file from library build output.`)) -} - // Execute "npm publish" to publish -const publishCommand = `npm publish --access public --tag ${tag === 'undefined' ? 'next' : tag}` +const publishCommand = `npm publish --access public --tag ${tag === 'undefined' ? 'next' : tag} ${otp ? `--otp ${otp}` : ''}` console.log(chalk.bold.greenBright(publishCommand)) execSync(publishCommand) console.log('Published successfully 🎉') diff --git a/tsconfig.base.json b/tsconfig.base.json index acfb541c2c..6ba976d101 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -39,6 +39,7 @@ "@cowprotocol/common-utils": ["libs/common-utils/src/index.ts"], "@cowprotocol/core": ["libs/core/src/index.ts"], "@cowprotocol/ens": ["libs/ens/src/index.ts"], + "@cowprotocol/permit-utils": ["libs/permit-utils/src/index.ts"], "@cowprotocol/snackbars": ["libs/snackbars/src/index.ts"], "@cowprotocol/tokens": ["libs/tokens/src/index.ts"], "@cowprotocol/ui": ["libs/ui/src/index.ts"], diff --git a/yarn.lock b/yarn.lock index dc4b83f100..5ea6735760 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@1inch/permit-signed-approvals-utils@^1.4.8": - version "1.4.8" - resolved "https://registry.yarnpkg.com/@1inch/permit-signed-approvals-utils/-/permit-signed-approvals-utils-1.4.8.tgz#d5d20e9e8a763f2649945aef8b843034a9a92c52" - integrity sha512-1U9U/tdvZpp9ZXaNmiiehu6S2EIYV3A4c1pj48oPcObRaWxX0QSDCrEHh95eJ0ND9y7QgvdlOy8DSAWUmxZOhA== +"@1inch/permit-signed-approvals-utils@^1.4.10": + version "1.4.10" + resolved "https://registry.yarnpkg.com/@1inch/permit-signed-approvals-utils/-/permit-signed-approvals-utils-1.4.10.tgz#f5b869c50bdc40f54577ca2260440d31bf2c7dac" + integrity sha512-wWRO5h0a2rzQgIbbNrq1wtGhmDKsLq7DwuT3qfuXCrt6mfkEAem9EJnT8Q09mCGOY/mLUQhEorKbbcHOEGi/7A== dependencies: "@metamask/eth-sig-util" "^4.0.1" web3 "^1.5.1" @@ -1242,14 +1242,7 @@ dependencies: regenerator-runtime "^0.13.11" -"@babel/runtime@^7.18.3", "@babel/runtime@^7.23.1", "@babel/runtime@^7.8.7": - version "7.23.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.1.tgz#72741dc4d413338a91dcb044a86f3c0bc402646d" - integrity sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/runtime@^7.3.1": +"@babel/runtime@^7.18.3", "@babel/runtime@^7.23.1", "@babel/runtime@^7.3.1", "@babel/runtime@^7.8.7": version "7.23.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885" integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg== @@ -1516,10 +1509,10 @@ dependencies: chalk "^4.1.0" -"@cowprotocol/app-data@^1.1.0-RC.0": - version "1.1.0-RC.0" - resolved "https://registry.yarnpkg.com/@cowprotocol/app-data/-/app-data-1.1.0-RC.0.tgz#ac4e5d7a036c4033df431e07f7670e47be7662fd" - integrity sha512-tQrFTTXu2beVrPnHlB1YsRfYpmK9wvYpqJXsdHlXisuTm38EGPMSIAxV9NxYFbqlbslmYvBX7uSFPO70kMrN9g== +"@cowprotocol/app-data@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@cowprotocol/app-data/-/app-data-1.1.0.tgz#38d91a79388220bc1ff99d2b6d0d3e3cce38e8f9" + integrity sha512-r55wyVrVnyq32KcswGN+1q5jTIfkLq4NlhibLWpe8px05lqvHA/RXRLO8lTkK7WFtlbO4iSnQqkIs4wqLc80kg== dependencies: ajv "^8.11.0" cross-fetch "^3.1.5" @@ -2206,7 +2199,7 @@ crc-32 "^1.2.0" ethereumjs-util "^7.1.1" -"@ethereumjs/common@^2.5.0": +"@ethereumjs/common@2.6.5", "@ethereumjs/common@^2.5.0", "@ethereumjs/common@^2.6.4": version "2.6.5" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" integrity sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA== @@ -2227,7 +2220,15 @@ "@ethereumjs/common" "^2.5.0" ethereumjs-util "^7.1.2" -"@ethereumjs/util@^8.0.6": +"@ethereumjs/tx@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.2.tgz#197b9b6299582ad84f9527ca961466fce2296c1c" + integrity sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw== + dependencies: + "@ethereumjs/common" "^2.6.4" + ethereumjs-util "^7.1.5" + +"@ethereumjs/util@^8.0.6", "@ethereumjs/util@^8.1.0": version "8.1.0" resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== @@ -7864,7 +7865,7 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -abortcontroller-polyfill@^1.7.3: +abortcontroller-polyfill@^1.7.3, abortcontroller-polyfill@^1.7.5: version "1.7.5" resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== @@ -10156,6 +10157,13 @@ cross-fetch@^3.0.4, cross-fetch@^3.1.4, cross-fetch@^3.1.5, cross-fetch@^3.1.6: dependencies: node-fetch "^2.6.12" +cross-fetch@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" + integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== + dependencies: + node-fetch "^2.6.12" + cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -12278,7 +12286,7 @@ ethereum-cryptography@^1.1.2: "@scure/bip32" "1.1.5" "@scure/bip39" "1.1.1" -ethereum-cryptography@^2.0.0: +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug== @@ -12320,7 +12328,7 @@ ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereum ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethers@5.7.2, ethers@^5.1.4, ethers@^5.7.0: +ethers@5.7.2, ethers@^5.7.0, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -16286,9 +16294,9 @@ json-stable-stringify@^1.0.2: jsonify "^0.0.1" json-stringify-deterministic@^1.0.8: - version "1.0.10" - resolved "https://registry.yarnpkg.com/json-stringify-deterministic/-/json-stringify-deterministic-1.0.10.tgz#d56660b6e9c12f47dee4340ec2ce26745fa6ee64" - integrity sha512-hBLYMyCnoYh0rQ2ZyEegbLaFAS5KqOZ6HZ5fgq6lGWhtNRKw2JUp/hkfjQS1bjYZlHW9AjvXBWCJe9OwcugRNw== + version "1.0.12" + resolved "https://registry.yarnpkg.com/json-stringify-deterministic/-/json-stringify-deterministic-1.0.12.tgz#aaa3f907466ed01e3afd77b898d0a2b3b132820a" + integrity sha512-q3PN0lbUdv0pmurkBNdJH3pfFvOTL/Zp0lquqpvcjfKzt6Y0j49EPHAmVHCAS4Ceq/Y+PejWTzyiVpoY71+D6g== json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" @@ -23447,6 +23455,15 @@ web3-bzz@1.10.0: got "12.1.0" swarm-js "^0.1.40" +web3-bzz@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.10.3.tgz#13942b37757eb850f3500a8e08bf605448b67566" + integrity sha512-XDIRsTwekdBXtFytMpHBuun4cK4x0ZMIDXSoo1UVYp+oMyZj07c7gf7tNQY5qZ/sN+CJIas4ilhN25VJcjSijQ== + dependencies: + "@types/node" "^12.12.6" + got "12.1.0" + swarm-js "^0.1.40" + web3-core-helpers@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.10.0.tgz#1016534c51a5df77ed4f94d1fcce31de4af37fad" @@ -23455,6 +23472,14 @@ web3-core-helpers@1.10.0: web3-eth-iban "1.10.0" web3-utils "1.10.0" +web3-core-helpers@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.10.3.tgz#f2db40ea57e888795e46f229b06113b60bcd671c" + integrity sha512-Yv7dQC3B9ipOc5sWm3VAz1ys70Izfzb8n9rSiQYIPjpqtJM+3V4EeK6ghzNR6CO2es0+Yu9CtCkw0h8gQhrTxA== + dependencies: + web3-eth-iban "1.10.3" + web3-utils "1.10.3" + web3-core-method@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.10.0.tgz#82668197fa086e8cc8066742e35a9d72535e3412" @@ -23466,6 +23491,17 @@ web3-core-method@1.10.0: web3-core-subscriptions "1.10.0" web3-utils "1.10.0" +web3-core-method@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.10.3.tgz#63f16310ccab4eec8eca0a337d534565c2ba8d33" + integrity sha512-VZ/Dmml4NBmb0ep5PTSg9oqKoBtG0/YoMPei/bq/tUdlhB2dMB79sbeJPwx592uaV0Vpk7VltrrrBv5hTM1y4Q== + dependencies: + "@ethersproject/transactions" "^5.6.2" + web3-core-helpers "1.10.3" + web3-core-promievent "1.10.3" + web3-core-subscriptions "1.10.3" + web3-utils "1.10.3" + web3-core-promievent@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.10.0.tgz#cbb5b3a76b888df45ed3a8d4d8d4f54ccb66a37b" @@ -23473,6 +23509,13 @@ web3-core-promievent@1.10.0: dependencies: eventemitter3 "4.0.4" +web3-core-promievent@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.10.3.tgz#9765dd42ce6cf2dc0a08eaffee607b855644f290" + integrity sha512-HgjY+TkuLm5uTwUtaAfkTgRx/NzMxvVradCi02gy17NxDVdg/p6svBHcp037vcNpkuGeFznFJgULP+s2hdVgUQ== + dependencies: + eventemitter3 "4.0.4" + web3-core-requestmanager@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.10.0.tgz#4b34f6e05837e67c70ff6f6993652afc0d54c340" @@ -23484,6 +23527,17 @@ web3-core-requestmanager@1.10.0: web3-providers-ipc "1.10.0" web3-providers-ws "1.10.0" +web3-core-requestmanager@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.10.3.tgz#c34ca8e998a18d6ca3fa7f7a11d4391da401c987" + integrity sha512-VT9sKJfgM2yBOIxOXeXiDuFMP4pxzF6FT+y8KTLqhDFHkbG3XRe42Vm97mB/IvLQCJOmokEjl3ps8yP1kbggyw== + dependencies: + util "^0.12.5" + web3-core-helpers "1.10.3" + web3-providers-http "1.10.3" + web3-providers-ipc "1.10.3" + web3-providers-ws "1.10.3" + web3-core-subscriptions@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.10.0.tgz#b534592ee1611788fc0cb0b95963b9b9b6eacb7c" @@ -23492,6 +23546,14 @@ web3-core-subscriptions@1.10.0: eventemitter3 "4.0.4" web3-core-helpers "1.10.0" +web3-core-subscriptions@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.10.3.tgz#58768cd72a9313252ef05dc52c09536f009a9479" + integrity sha512-KW0Mc8sgn70WadZu7RjQ4H5sNDJ5Lx8JMI3BWos+f2rW0foegOCyWhRu33W1s6ntXnqeBUw5rRCXZRlA3z+HNA== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.10.3" + web3-core@1.10.0, web3-core@^1.8.1: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.10.0.tgz#9aa07c5deb478cf356c5d3b5b35afafa5fa8e633" @@ -23505,6 +23567,19 @@ web3-core@1.10.0, web3-core@^1.8.1: web3-core-requestmanager "1.10.0" web3-utils "1.10.0" +web3-core@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.10.3.tgz#4aeb8f4b0cb5775d9fa4edf1127864743f1c3ae3" + integrity sha512-Vbk0/vUNZxJlz3RFjAhNNt7qTpX8yE3dn3uFxfX5OHbuon5u65YEOd3civ/aQNW745N0vGUlHFNxxmn+sG9DIw== + dependencies: + "@types/bn.js" "^5.1.1" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.10.3" + web3-core-method "1.10.3" + web3-core-requestmanager "1.10.3" + web3-utils "1.10.3" + web3-eth-abi@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.10.0.tgz#53a7a2c95a571e205e27fd9e664df4919483cce1" @@ -23513,6 +23588,14 @@ web3-eth-abi@1.10.0: "@ethersproject/abi" "^5.6.3" web3-utils "1.10.0" +web3-eth-abi@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.10.3.tgz#7decfffa8fed26410f32cfefdc32d3e76f717ca2" + integrity sha512-O8EvV67uhq0OiCMekqYsDtb6FzfYzMXT7VMHowF8HV6qLZXCGTdB/NH4nJrEh2mFtEwVdS6AmLFJAQd2kVyoMQ== + dependencies: + "@ethersproject/abi" "^5.6.3" + web3-utils "1.10.3" + web3-eth-accounts@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.10.0.tgz#2942beca0a4291455f32cf09de10457a19a48117" @@ -23529,6 +23612,22 @@ web3-eth-accounts@1.10.0: web3-core-method "1.10.0" web3-utils "1.10.0" +web3-eth-accounts@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.10.3.tgz#9ecb816b81cd97333988bfcd0afaee5d13bbb198" + integrity sha512-8MipGgwusDVgn7NwKOmpeo3gxzzd+SmwcWeBdpXknuyDiZSQy9tXe+E9LeFGrmys/8mLLYP79n3jSbiTyv+6pQ== + dependencies: + "@ethereumjs/common" "2.6.5" + "@ethereumjs/tx" "3.5.2" + "@ethereumjs/util" "^8.1.0" + eth-lib "0.2.8" + scrypt-js "^3.0.1" + uuid "^9.0.0" + web3-core "1.10.3" + web3-core-helpers "1.10.3" + web3-core-method "1.10.3" + web3-utils "1.10.3" + web3-eth-contract@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.10.0.tgz#8e68c7654576773ec3c91903f08e49d0242c503a" @@ -23543,6 +23642,20 @@ web3-eth-contract@1.10.0: web3-eth-abi "1.10.0" web3-utils "1.10.0" +web3-eth-contract@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.10.3.tgz#8880468e2ba7d8a4791cf714f67d5e1ec1591275" + integrity sha512-Y2CW61dCCyY4IoUMD4JsEQWrILX4FJWDWC/Txx/pr3K/+fGsBGvS9kWQN5EsVXOp4g7HoFOfVh9Lf7BmVVSRmg== + dependencies: + "@types/bn.js" "^5.1.1" + web3-core "1.10.3" + web3-core-helpers "1.10.3" + web3-core-method "1.10.3" + web3-core-promievent "1.10.3" + web3-core-subscriptions "1.10.3" + web3-eth-abi "1.10.3" + web3-utils "1.10.3" + web3-eth-ens@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.10.0.tgz#96a676524e0b580c87913f557a13ed810cf91cd9" @@ -23557,6 +23670,20 @@ web3-eth-ens@1.10.0: web3-eth-contract "1.10.0" web3-utils "1.10.0" +web3-eth-ens@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.10.3.tgz#ae5b49bcb9823027e0b28aa6b1de58d726cbaafa" + integrity sha512-hR+odRDXGqKemw1GFniKBEXpjYwLgttTES+bc7BfTeoUyUZXbyDHe5ifC+h+vpzxh4oS0TnfcIoarK0Z9tFSiQ== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + web3-core "1.10.3" + web3-core-helpers "1.10.3" + web3-core-promievent "1.10.3" + web3-eth-abi "1.10.3" + web3-eth-contract "1.10.3" + web3-utils "1.10.3" + web3-eth-iban@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.10.0.tgz#5a46646401965b0f09a4f58e7248c8a8cd22538a" @@ -23565,6 +23692,14 @@ web3-eth-iban@1.10.0: bn.js "^5.2.1" web3-utils "1.10.0" +web3-eth-iban@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.10.3.tgz#91d458e5400195edc883a0d4383bf1cecd17240d" + integrity sha512-ZCfOjYKAjaX2TGI8uif5ah+J3BYFuo+47JOIV1RIz2l7kD9VfnxvRH5UiQDRyMALQC7KFd2hUqIEtHklapNyKA== + dependencies: + bn.js "^5.2.1" + web3-utils "1.10.3" + web3-eth-personal@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.10.0.tgz#94d525f7a29050a0c2a12032df150ac5ea633071" @@ -23577,6 +23712,18 @@ web3-eth-personal@1.10.0: web3-net "1.10.0" web3-utils "1.10.0" +web3-eth-personal@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.10.3.tgz#4e72008aa211327ccc3bfa7671c510e623368457" + integrity sha512-avrQ6yWdADIvuNQcFZXmGLCEzulQa76hUOuVywN7O3cklB4nFc/Gp3yTvD3bOAaE7DhjLQfhUTCzXL7WMxVTsw== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.10.3" + web3-core-helpers "1.10.3" + web3-core-method "1.10.3" + web3-net "1.10.3" + web3-utils "1.10.3" + web3-eth@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.10.0.tgz#38b905e2759697c9624ab080cfcf4e6c60b3a6cf" @@ -23595,6 +23742,24 @@ web3-eth@1.10.0: web3-net "1.10.0" web3-utils "1.10.0" +web3-eth@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.10.3.tgz#b8c6f37f1aac52422583a5a9c29130983a3fb3b1" + integrity sha512-Uk1U2qGiif2mIG8iKu23/EQJ2ksB1BQXy3wF3RvFuyxt8Ft9OEpmGlO7wOtAyJdoKzD5vcul19bJpPcWSAYZhA== + dependencies: + web3-core "1.10.3" + web3-core-helpers "1.10.3" + web3-core-method "1.10.3" + web3-core-subscriptions "1.10.3" + web3-eth-abi "1.10.3" + web3-eth-accounts "1.10.3" + web3-eth-contract "1.10.3" + web3-eth-ens "1.10.3" + web3-eth-iban "1.10.3" + web3-eth-personal "1.10.3" + web3-net "1.10.3" + web3-utils "1.10.3" + web3-net@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.10.0.tgz#be53e7f5dafd55e7c9013d49c505448b92c9c97b" @@ -23604,6 +23769,15 @@ web3-net@1.10.0: web3-core-method "1.10.0" web3-utils "1.10.0" +web3-net@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.10.3.tgz#9486c2fe51452cb958e11915db6f90bd6caa5482" + integrity sha512-IoSr33235qVoI1vtKssPUigJU9Fc/Ph0T9CgRi15sx+itysmvtlmXMNoyd6Xrgm9LuM4CIhxz7yDzH93B79IFg== + dependencies: + web3-core "1.10.3" + web3-core-method "1.10.3" + web3-utils "1.10.3" + web3-providers-http@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.10.0.tgz#864fa48675e7918c9a4374e5f664b32c09d0151b" @@ -23614,6 +23788,16 @@ web3-providers-http@1.10.0: es6-promise "^4.2.8" web3-core-helpers "1.10.0" +web3-providers-http@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.10.3.tgz#d8166ee89db82d37281ea9e15c5882a2d7928755" + integrity sha512-6dAgsHR3MxJ0Qyu3QLFlQEelTapVfWNTu5F45FYh8t7Y03T1/o+YAkVxsbY5AdmD+y5bXG/XPJ4q8tjL6MgZHw== + dependencies: + abortcontroller-polyfill "^1.7.5" + cross-fetch "^4.0.0" + es6-promise "^4.2.8" + web3-core-helpers "1.10.3" + web3-providers-ipc@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.10.0.tgz#9747c7a6aee96a51488e32fa7c636c3460b39889" @@ -23622,6 +23806,14 @@ web3-providers-ipc@1.10.0: oboe "2.1.5" web3-core-helpers "1.10.0" +web3-providers-ipc@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.10.3.tgz#a7e015957fc037d8a87bd4b6ae3561c1b1ad1f46" + integrity sha512-vP5WIGT8FLnGRfswTxNs9rMfS1vCbMezj/zHbBe/zB9GauBRTYVrUo2H/hVrhLg8Ut7AbsKZ+tCJ4mAwpKi2hA== + dependencies: + oboe "2.1.5" + web3-core-helpers "1.10.3" + web3-providers-ws@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.10.0.tgz#cb0b87b94c4df965cdf486af3a8cd26daf3975e5" @@ -23631,6 +23823,15 @@ web3-providers-ws@1.10.0: web3-core-helpers "1.10.0" websocket "^1.0.32" +web3-providers-ws@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.10.3.tgz#03c84958f9da251349cd26fd7a4ae567e3af6caa" + integrity sha512-/filBXRl48INxsh6AuCcsy4v5ndnTZ/p6bl67kmO9aK1wffv7CT++DrtclDtVMeDGCgB3van+hEf9xTAVXur7Q== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.10.3" + websocket "^1.0.32" + web3-shh@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.10.0.tgz#c2979b87e0f67a7fef2ce9ee853bd7bfbe9b79a8" @@ -23641,7 +23842,17 @@ web3-shh@1.10.0: web3-core-subscriptions "1.10.0" web3-net "1.10.0" -web3-utils@1.10.0, web3-utils@^1.5.1, web3-utils@^1.8.1: +web3-shh@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.10.3.tgz#ee44f760598a65a290d611c443838aac854ee858" + integrity sha512-cAZ60CPvs9azdwMSQ/PSUdyV4PEtaW5edAZhu3rCXf6XxQRliBboic+AvwUvB6j3eswY50VGa5FygfVmJ1JVng== + dependencies: + web3-core "1.10.3" + web3-core-method "1.10.3" + web3-core-subscriptions "1.10.3" + web3-net "1.10.3" + +web3-utils@1.10.0, web3-utils@^1.8.1: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578" integrity sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg== @@ -23654,7 +23865,34 @@ web3-utils@1.10.0, web3-utils@^1.5.1, web3-utils@^1.8.1: randombytes "^2.1.0" utf8 "3.0.0" -web3@^1.5.1, web3@^1.8.1: +web3-utils@1.10.3, web3-utils@^1.5.1: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.3.tgz#f1db99c82549c7d9f8348f04ffe4e0188b449714" + integrity sha512-OqcUrEE16fDBbGoQtZXWdavsPzbGIDc5v3VrRTZ0XrIpefC/viZ1ZU9bGEemazyS0catk/3rkOOxpzTfY+XsyQ== + dependencies: + "@ethereumjs/util" "^8.1.0" + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereum-cryptography "^2.1.2" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +web3@^1.5.1: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.10.3.tgz#5e80ac532dc432b09fde668d570b0ad4e6710897" + integrity sha512-DgUdOOqC/gTqW+VQl1EdPxrVRPB66xVNtuZ5KD4adVBtko87hkgM8BTZ0lZ8IbUfnQk6DyjcDujMiH3oszllAw== + dependencies: + web3-bzz "1.10.3" + web3-core "1.10.3" + web3-eth "1.10.3" + web3-eth-personal "1.10.3" + web3-net "1.10.3" + web3-shh "1.10.3" + web3-utils "1.10.3" + +web3@^1.8.1: version "1.10.0" resolved "https://registry.yarnpkg.com/web3/-/web3-1.10.0.tgz#2fde0009f59aa756c93e07ea2a7f3ab971091274" integrity sha512-YfKY9wSkGcM8seO+daR89oVTcbu18NsVfvOngzqMYGUU0pPSQmE57qQDvQzUeoIOHAnXEBNzrhjQJmm8ER0rng==