From 56797dddd3009461f6f3c02545cc0de730ed7082 Mon Sep 17 00:00:00 2001 From: Vitor Date: Wed, 11 Dec 2024 15:53:58 -0300 Subject: [PATCH 01/10] chore: add deployments and abi --- .../src/processing/process-delegation.ts | 11 ++++ .../process-limit-order-delegation.ts | 5 ++ .../processing/utils/get-delegation-type.ts | 21 +++++++ .../api-delegations/src/routes/delegations.ts | 17 +++-- .../src/abis/caveat-enforcer-abi.ts | 62 +++++++++++++++++++ packages/universal-data/src/deployments.ts | 2 + 6 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 apps/api-delegations/src/processing/process-delegation.ts create mode 100644 apps/api-delegations/src/processing/process-limit-order-delegation.ts create mode 100644 apps/api-delegations/src/processing/utils/get-delegation-type.ts create mode 100644 packages/universal-data/src/abis/caveat-enforcer-abi.ts diff --git a/apps/api-delegations/src/processing/process-delegation.ts b/apps/api-delegations/src/processing/process-delegation.ts new file mode 100644 index 00000000..9a23ae32 --- /dev/null +++ b/apps/api-delegations/src/processing/process-delegation.ts @@ -0,0 +1,11 @@ +import type { Delegation } from 'universal-types'; +import { getDelegationType } from './utils/get-delegation-type.js'; +import { processLimitOrderDelegation } from './process-limit-order-delegation.js'; + +export async function processDelegation(delegation: Delegation) { + const delegationType = getDelegationType(delegation); + + if (delegationType === 'LimitOrder') { + return processLimitOrderDelegation(delegation); + } +} diff --git a/apps/api-delegations/src/processing/process-limit-order-delegation.ts b/apps/api-delegations/src/processing/process-limit-order-delegation.ts new file mode 100644 index 00000000..4a1d57cb --- /dev/null +++ b/apps/api-delegations/src/processing/process-limit-order-delegation.ts @@ -0,0 +1,5 @@ +import type { Delegation } from 'universal-types'; + +export async function processLimitOrderDelegation(delegation: Delegation) { + console.log('Processing Limit Order Delegation:', delegation); +} diff --git a/apps/api-delegations/src/processing/utils/get-delegation-type.ts b/apps/api-delegations/src/processing/utils/get-delegation-type.ts new file mode 100644 index 00000000..4123c946 --- /dev/null +++ b/apps/api-delegations/src/processing/utils/get-delegation-type.ts @@ -0,0 +1,21 @@ +import type { Delegation } from 'universal-types'; +import { universalDeployments } from 'universal-data'; + +// TODO: Extract type/function and make it globally available +export type DelegationType = 'LimitOrder'; + +export function getDelegationType( + delegation: Delegation, +): DelegationType | null { + // TODO: Add more robust logic to determine delegation type + if ( + delegation.caveats.some( + ({ enforcer }) => + enforcer.toLowerCase() === + universalDeployments.ExternalHookEnforcer.toLowerCase(), + ) + ) { + return 'LimitOrder'; + } + return null; +} diff --git a/apps/api-delegations/src/routes/delegations.ts b/apps/api-delegations/src/routes/delegations.ts index bb8b96b1..72ff2edb 100644 --- a/apps/api-delegations/src/routes/delegations.ts +++ b/apps/api-delegations/src/routes/delegations.ts @@ -10,6 +10,7 @@ import { postDelegationSchema, } from '../validation.js'; import type { DelegationWithMetadata } from 'universal-types'; +import { processDelegation } from '../processing/process-delegation.js'; const delegationsRouter = new Hono() // Get a delegation by its hash @@ -51,23 +52,27 @@ const delegationsRouter = new Hono() zValidator('json', postDelegationSchema), // TODO: validate the signature of the delegation async (c) => { - const delegation = c.req.valid('json'); + const rawDelegation = c.req.valid('json'); - const format = JSON.parse( - JSON.stringify(delegation, (_key, value) => + const delegation = JSON.parse( + JSON.stringify(rawDelegation, (_key, value) => typeof value === 'bigint' ? value.toString() : value, ), ); - // Save the delegation to the database try { - await insertDelegationDb(format); + await Promise.all([ + // Process any necessary delegation side effects + processDelegation(delegation), + // Save the delegation to the database + insertDelegationDb(delegation), + ]); } catch (error) { console.error(error); return c.json({ error: 'failed to save delegation' }, 500); } - return c.json({ delegation: format }, 200); + return c.json({ delegation }, 200); }, ) .patch( diff --git a/packages/universal-data/src/abis/caveat-enforcer-abi.ts b/packages/universal-data/src/abis/caveat-enforcer-abi.ts new file mode 100644 index 00000000..c0189b0a --- /dev/null +++ b/packages/universal-data/src/abis/caveat-enforcer-abi.ts @@ -0,0 +1,62 @@ +export const caveatEnforcerAbi = [ + { + type: 'function', + name: 'afterAllHook', + inputs: [ + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'ModeCode' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'bytes32' }, + { name: '', type: 'address', internalType: 'address' }, + { name: '', type: 'address', internalType: 'address' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'afterHook', + inputs: [ + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'ModeCode' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'bytes32' }, + { name: '', type: 'address', internalType: 'address' }, + { name: '', type: 'address', internalType: 'address' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'beforeAllHook', + inputs: [ + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'ModeCode' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'bytes32' }, + { name: '', type: 'address', internalType: 'address' }, + { name: '', type: 'address', internalType: 'address' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'beforeHook', + inputs: [ + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'ModeCode' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'bytes32' }, + { name: '', type: 'address', internalType: 'address' }, + { name: '', type: 'address', internalType: 'address' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, +] as const; diff --git a/packages/universal-data/src/deployments.ts b/packages/universal-data/src/deployments.ts index 8c8c7432..f96cb6dc 100644 --- a/packages/universal-data/src/deployments.ts +++ b/packages/universal-data/src/deployments.ts @@ -30,4 +30,6 @@ export const universalDeployments = { RedeemerEnforcer: '0xbD848E5861825754c809F5b813A72B50691A86A6', TimestampEnforcer: '0x675b4844E388e329354185cAcBC30E3F93456559', ValueLteEnforcer: '0x1f7EE6330cc76Bb26Cc490166CcAbf451234A578', + ERC20BalanceGteAfterAllEnforcer: '0x2AB6fed8C074D4Bf4668E46f78a97cCD1FC23686', + ExternalHookEnforcer: '0xF1dF0e6d2d6D307814A086cCdeBdcD1250C53df3', } as const; From 4792158d9128dfa10a8f59e14c8ce549003f6a32 Mon Sep 17 00:00:00 2001 From: Vitor Date: Wed, 11 Dec 2024 18:17:10 -0300 Subject: [PATCH 02/10] feat: initial resolver processing --- apps/api-delegations/src/env.ts | 4 + .../src/processing/limit-order/index.ts | 108 ++ .../src/processing/limit-order/utils.ts | 140 ++ .../src/processing/process-delegation.ts | 10 +- .../process-limit-order-delegation.ts | 5 - .../src/resolver/resolver-wallet-client.ts | 30 + .../src/abis/aave-v3-pool-abi.ts | 1369 +++++++++++++++++ .../universal-data/src/abis/multicall-abi.ts | 28 + packages/universal-data/src/deployments.ts | 2 + packages/universal-data/src/exports/index.ts | 2 + .../src/enforcers/enforcer-external-hook.ts | 13 + .../src/exports/index.ts | 1 + pnpm-lock.yaml | 154 +- 13 files changed, 1824 insertions(+), 42 deletions(-) create mode 100644 apps/api-delegations/src/processing/limit-order/index.ts create mode 100644 apps/api-delegations/src/processing/limit-order/utils.ts delete mode 100644 apps/api-delegations/src/processing/process-limit-order-delegation.ts create mode 100644 apps/api-delegations/src/resolver/resolver-wallet-client.ts create mode 100644 packages/universal-data/src/abis/aave-v3-pool-abi.ts create mode 100644 packages/universal-data/src/abis/multicall-abi.ts create mode 100644 packages/universal-delegations-sdk/src/enforcers/enforcer-external-hook.ts diff --git a/apps/api-delegations/src/env.ts b/apps/api-delegations/src/env.ts index a468e53a..c7f5de81 100644 --- a/apps/api-delegations/src/env.ts +++ b/apps/api-delegations/src/env.ts @@ -1,10 +1,14 @@ import { createEnv } from '@t3-oss/env-core'; import { z } from 'zod'; import 'dotenv/config'; +import { isHex } from 'viem'; export const env = createEnv({ server: { DELEGATIONS_DATABASE_URL: z.string().url(), + RESOLVER_PRIVATE_KEY: z.string().refine(isHex), + RPC_URL_BASE: z.string().url(), + RPC_URL_BASE_SEPOLIA: z.string().url(), }, runtimeEnv: process.env, emptyStringAsUndefined: true, diff --git a/apps/api-delegations/src/processing/limit-order/index.ts b/apps/api-delegations/src/processing/limit-order/index.ts new file mode 100644 index 00000000..c9ee2115 --- /dev/null +++ b/apps/api-delegations/src/processing/limit-order/index.ts @@ -0,0 +1,108 @@ +import type { Delegation, DelegationExecution } from 'universal-types'; +import { + decodeEnforcerERC20TransferAmount, + encodeDelegation, + encodeSingleExecution, + getErc20TransferAmountEnforcerFromDelegation, + getExternalHookEnforcerFromDelegation, +} from './utils.js'; +import { getResolverWalletClient } from '../../resolver/resolver-wallet-client.js'; +import type { ValidChain } from 'universal-data'; +import { + SINGLE_EXECUTION_MODE, + aaveV3PoolAbi, + delegationManagerAbi, + universalDeployments, +} from 'universal-data'; +import { encodeFunctionData, type Address, type Hex, erc20Abi } from 'viem'; +import { multicallAbi } from 'universal-data'; + +const AAVE_V3_POOL_BASE = '0xA238Dd80C259a72e81d7e4664a9801593F98d1c5'; + +function getDepositAaveV3HookData({ + amount, + delegator, + token, +}: { amount: bigint; delegator: Address; token: Address }): Hex { + return encodeFunctionData({ + abi: multicallAbi, + + functionName: 'multicall', + args: [ + [ + // Approves the token to the Aave Pool + { + target: token, + value: 0n, + callData: encodeFunctionData({ + abi: erc20Abi, + functionName: 'approve', + args: [AAVE_V3_POOL_BASE, amount], + }), + }, + // Deposits the token to the Aave Pool on behalf of the delegator + { + target: AAVE_V3_POOL_BASE, + value: 0n, + callData: encodeFunctionData({ + abi: aaveV3PoolAbi, + functionName: 'supply', + args: [token, amount, delegator, 0], + }), + }, + ], + ], + }); +} + +export async function processLimitOrderDelegation({ + chainId, + delegation, +}: { chainId: ValidChain['id']; delegation: Delegation }) { + const { erc20TransferAmountEnforcer } = + getErc20TransferAmountEnforcerFromDelegation(delegation); + const { token, amount } = decodeEnforcerERC20TransferAmount( + erc20TransferAmountEnforcer.terms, + ); + + const { externalHookEnforcer, index: externalHookEnforcerIndex } = + getExternalHookEnforcerFromDelegation(delegation); + + delegation.caveats[externalHookEnforcerIndex] = { + ...externalHookEnforcer, + // Update the args of the external hook enforcer to include the data for the Aave V3 deposit + args: getDepositAaveV3HookData({ + amount, + token, + delegator: delegation.delegator, + }), + }; + + // Get resolver wallet client + const resolverWalletClient = getResolverWalletClient(chainId); + + // Set the delegation execution to transfer the delegator tokens to the multicall contract + const execution: DelegationExecution = { + value: 0n, + target: token, + calldata: encodeFunctionData({ + abi: erc20Abi, + functionName: 'transfer', + args: [universalDeployments.Multicall, amount], + }), + }; + + const permissionContexts = [encodeDelegation(delegation)]; + const executionCallData = [encodeSingleExecution(execution)]; + const executionModes = SINGLE_EXECUTION_MODE; + + // Redeem the delegation + const txHash = await resolverWalletClient.writeContract({ + address: universalDeployments.DelegationManager, + abi: delegationManagerAbi, + functionName: 'redeemDelegations', + args: [permissionContexts, executionModes, executionCallData], + }); + + return txHash; +} diff --git a/apps/api-delegations/src/processing/limit-order/utils.ts b/apps/api-delegations/src/processing/limit-order/utils.ts new file mode 100644 index 00000000..0b7c845a --- /dev/null +++ b/apps/api-delegations/src/processing/limit-order/utils.ts @@ -0,0 +1,140 @@ +import { universalDeployments } from 'universal-data'; +import type { Delegation, DelegationExecution } from 'universal-types'; +import { + type Address, + type Hex, + encodePacked, + hexToBigInt, + parseUnits, + sliceHex, + encodeAbiParameters, +} from 'viem'; + +export function encodeEnforcerERC20TransferAmount(data: { + token: Address; + amount: string; + decimals: number; +}) { + return encodePacked( + ['address', 'uint256'], + [data.token, parseUnits(data.amount, data.decimals)], + ); +} + +const NoEnforcerFoundError = new Error('No ERC20TransferAmountEnforcer found'); + +export function decodeEnforcerERC20TransferAmount(data: Hex) { + // Addresses are 20 bytes, uint256 is 32 bytes + const addressSize = 20; + const uint256Size = 32; + + // Decode `token` (first 20 bytes) + const token = sliceHex(data, 0, addressSize) as Address; + + // Decode `amount` (next 32 bytes) + const amountHex = sliceHex(data, addressSize, addressSize + uint256Size); + const amount = hexToBigInt(amountHex); + + return { + token, + amount, + }; +} + +export function getErc20TransferAmountEnforcerFromDelegation( + delegation: Delegation, +) { + const index = delegation.caveats.findIndex( + ({ enforcer }) => + enforcer.toLowerCase() === + universalDeployments.ERC20TransferAmountEnforcer.toLowerCase(), + ); + if (index === -1) { + throw NoEnforcerFoundError; + } + + const erc20TransferAmountEnforcer = delegation.caveats[index]; + + if (!erc20TransferAmountEnforcer) { + throw NoEnforcerFoundError; + } + + return { erc20TransferAmountEnforcer, index }; +} + +export function getExternalHookEnforcerFromDelegation(delegation: Delegation) { + const index = delegation.caveats.findIndex( + ({ enforcer }) => + enforcer.toLowerCase() === + universalDeployments.ExternalHookEnforcer.toLowerCase(), + ); + if (index === -1) { + throw NoEnforcerFoundError; + } + + const externalHookEnforcer = delegation.caveats[index]; + + if (!externalHookEnforcer) { + throw NoEnforcerFoundError; + } + + return { externalHookEnforcer, index }; +} + +// Typescript implementation of: https://github.com/erc7579/erc7579-implementation/blob/main/src/lib/ExecutionLib.sol#L51-L62 +export function encodeSingleExecution({ + calldata, + target, + value, +}: DelegationExecution): Hex { + return encodePacked( + ['address', 'uint256', 'bytes'], + [target, value, calldata], + ); +} + +export function encodeDelegation(delegation: Delegation): Hex { + return encodeAbiParameters( + [ + { + name: '_delegation', + type: 'tuple[]', + internalType: 'struct Delegation', + components: [ + { + name: 'delegate', + type: 'address', + internalType: 'address', + }, + { + name: 'delegator', + type: 'address', + internalType: 'address', + }, + { + name: 'authority', + type: 'bytes32', + internalType: 'bytes32', + }, + { + name: 'caveats', + type: 'tuple[]', + internalType: 'struct Caveat[]', + components: [ + { + name: 'enforcer', + type: 'address', + internalType: 'address', + }, + { name: 'terms', type: 'bytes', internalType: 'bytes' }, + { name: 'args', type: 'bytes', internalType: 'bytes' }, + ], + }, + { name: 'salt', type: 'uint256', internalType: 'uint256' }, + { name: 'signature', type: 'bytes', internalType: 'bytes' }, + ], + }, + ], + [[delegation]], + ); +} diff --git a/apps/api-delegations/src/processing/process-delegation.ts b/apps/api-delegations/src/processing/process-delegation.ts index 9a23ae32..02c9a62b 100644 --- a/apps/api-delegations/src/processing/process-delegation.ts +++ b/apps/api-delegations/src/processing/process-delegation.ts @@ -1,11 +1,15 @@ import type { Delegation } from 'universal-types'; import { getDelegationType } from './utils/get-delegation-type.js'; -import { processLimitOrderDelegation } from './process-limit-order-delegation.js'; +import { processLimitOrderDelegation } from './limit-order/index.js'; +import type { ValidChain } from 'universal-data'; -export async function processDelegation(delegation: Delegation) { +export async function processDelegation({ + chainId, + delegation, +}: { chainId: ValidChain['id']; delegation: Delegation }) { const delegationType = getDelegationType(delegation); if (delegationType === 'LimitOrder') { - return processLimitOrderDelegation(delegation); + await processLimitOrderDelegation({ chainId, delegation }); } } diff --git a/apps/api-delegations/src/processing/process-limit-order-delegation.ts b/apps/api-delegations/src/processing/process-limit-order-delegation.ts deleted file mode 100644 index 4a1d57cb..00000000 --- a/apps/api-delegations/src/processing/process-limit-order-delegation.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { Delegation } from 'universal-types'; - -export async function processLimitOrderDelegation(delegation: Delegation) { - console.log('Processing Limit Order Delegation:', delegation); -} diff --git a/apps/api-delegations/src/resolver/resolver-wallet-client.ts b/apps/api-delegations/src/resolver/resolver-wallet-client.ts new file mode 100644 index 00000000..93f6d7af --- /dev/null +++ b/apps/api-delegations/src/resolver/resolver-wallet-client.ts @@ -0,0 +1,30 @@ +import type { ValidChain } from 'universal-data'; +import { createWalletClient, http } from 'viem'; +import { base, baseSepolia } from 'viem/chains'; +import { env } from '../env.js'; +import { privateKeyToAccount } from 'viem/accounts'; + +const account = privateKeyToAccount(env.RESOLVER_PRIVATE_KEY); + +const resolverWalletClientBase = createWalletClient({ + account, + chain: base, + transport: http(env.RPC_URL_BASE), +}); + +const resolverWalletClientBaseSepolia = createWalletClient({ + account, + chain: baseSepolia, + transport: http(env.RPC_URL_BASE_SEPOLIA), +}); + +export function getResolverWalletClient(chainId: ValidChain['id']) { + switch (chainId) { + case base.id: + return resolverWalletClientBase; + case baseSepolia.id: + return resolverWalletClientBaseSepolia; + default: + throw new Error(`Invalid chainId: ${chainId}`); + } +} diff --git a/packages/universal-data/src/abis/aave-v3-pool-abi.ts b/packages/universal-data/src/abis/aave-v3-pool-abi.ts new file mode 100644 index 00000000..080a6eb3 --- /dev/null +++ b/packages/universal-data/src/abis/aave-v3-pool-abi.ts @@ -0,0 +1,1369 @@ +export const aaveV3PoolAbi = [ + { + inputs: [ + { + internalType: 'contract IPoolAddressesProvider', + name: 'provider', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'backer', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { indexed: false, internalType: 'uint256', name: 'fee', type: 'uint256' }, + ], + name: 'BackUnbacked', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'user', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'onBehalfOf', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { + indexed: false, + internalType: 'enum DataTypes.InterestRateMode', + name: 'interestRateMode', + type: 'uint8', + }, + { + indexed: false, + internalType: 'uint256', + name: 'borrowRate', + type: 'uint256', + }, + { + indexed: true, + internalType: 'uint16', + name: 'referralCode', + type: 'uint16', + }, + ], + name: 'Borrow', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'target', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'initiator', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'asset', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { + indexed: false, + internalType: 'enum DataTypes.InterestRateMode', + name: 'interestRateMode', + type: 'uint8', + }, + { + indexed: false, + internalType: 'uint256', + name: 'premium', + type: 'uint256', + }, + { + indexed: true, + internalType: 'uint16', + name: 'referralCode', + type: 'uint16', + }, + ], + name: 'FlashLoan', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'asset', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'totalDebt', + type: 'uint256', + }, + ], + name: 'IsolationModeTotalDebtUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'collateralAsset', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'debtAsset', + type: 'address', + }, + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'debtToCover', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'liquidatedCollateralAmount', + type: 'uint256', + }, + { + indexed: false, + internalType: 'address', + name: 'liquidator', + type: 'address', + }, + { + indexed: false, + internalType: 'bool', + name: 'receiveAToken', + type: 'bool', + }, + ], + name: 'LiquidationCall', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'user', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'onBehalfOf', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { + indexed: true, + internalType: 'uint16', + name: 'referralCode', + type: 'uint16', + }, + ], + name: 'MintUnbacked', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amountMinted', + type: 'uint256', + }, + ], + name: 'MintedToTreasury', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { + indexed: true, + internalType: 'address', + name: 'repayer', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { + indexed: false, + internalType: 'bool', + name: 'useATokens', + type: 'bool', + }, + ], + name: 'Repay', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'liquidityRate', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'stableBorrowRate', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'variableBorrowRate', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'liquidityIndex', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'variableBorrowIndex', + type: 'uint256', + }, + ], + name: 'ReserveDataUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'liquidityRate', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'stableBorrowRate', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'variableBorrowRate', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'liquidityIndex', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'variableBorrowIndex', + type: 'uint256', + }, + ], + name: 'ReserveDataUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + ], + name: 'ReserveUsedAsCollateralDisabled', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + ], + name: 'ReserveUsedAsCollateralEnabled', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'user', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'onBehalfOf', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { + indexed: true, + internalType: 'uint16', + name: 'referralCode', + type: 'uint16', + }, + ], + name: 'Supply', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { + indexed: false, + internalType: 'uint8', + name: 'categoryId', + type: 'uint8', + }, + ], + name: 'UserEModeSet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reserve', + type: 'address', + }, + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Withdraw', + type: 'event', + }, + { + inputs: [], + name: 'ADDRESSES_PROVIDER', + outputs: [ + { + internalType: 'contract IPoolAddressesProvider', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'BRIDGE_PROTOCOL_FEE', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'FLASHLOAN_PREMIUM_TOTAL', + outputs: [{ internalType: 'uint128', name: '', type: 'uint128' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'FLASHLOAN_PREMIUM_TO_PROTOCOL', + outputs: [{ internalType: 'uint128', name: '', type: 'uint128' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MAX_NUMBER_RESERVES', + outputs: [{ internalType: 'uint16', name: '', type: 'uint16' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'POOL_REVISION', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'uint256', name: 'fee', type: 'uint256' }, + ], + name: 'backUnbacked', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'uint256', name: 'interestRateMode', type: 'uint256' }, + { internalType: 'uint16', name: 'referralCode', type: 'uint16' }, + { internalType: 'address', name: 'onBehalfOf', type: 'address' }, + ], + name: 'borrow', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'args', type: 'bytes32' }], + name: 'borrow', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint8', name: 'id', type: 'uint8' }, + { + components: [ + { internalType: 'uint16', name: 'ltv', type: 'uint16' }, + { + internalType: 'uint16', + name: 'liquidationThreshold', + type: 'uint16', + }, + { internalType: 'uint16', name: 'liquidationBonus', type: 'uint16' }, + { internalType: 'string', name: 'label', type: 'string' }, + ], + internalType: 'struct DataTypes.EModeCategoryBaseConfiguration', + name: 'category', + type: 'tuple', + }, + ], + name: 'configureEModeCategory', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint8', name: 'id', type: 'uint8' }, + { internalType: 'uint128', name: 'borrowableBitmap', type: 'uint128' }, + ], + name: 'configureEModeCategoryBorrowableBitmap', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint8', name: 'id', type: 'uint8' }, + { internalType: 'uint128', name: 'collateralBitmap', type: 'uint128' }, + ], + name: 'configureEModeCategoryCollateralBitmap', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'address', name: 'onBehalfOf', type: 'address' }, + { internalType: 'uint16', name: 'referralCode', type: 'uint16' }, + ], + name: 'deposit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'dropReserve', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'from', type: 'address' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'uint256', name: 'balanceFromBefore', type: 'uint256' }, + { internalType: 'uint256', name: 'balanceToBefore', type: 'uint256' }, + ], + name: 'finalizeTransfer', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'receiverAddress', type: 'address' }, + { internalType: 'address[]', name: 'assets', type: 'address[]' }, + { internalType: 'uint256[]', name: 'amounts', type: 'uint256[]' }, + { + internalType: 'uint256[]', + name: 'interestRateModes', + type: 'uint256[]', + }, + { internalType: 'address', name: 'onBehalfOf', type: 'address' }, + { internalType: 'bytes', name: 'params', type: 'bytes' }, + { internalType: 'uint16', name: 'referralCode', type: 'uint16' }, + ], + name: 'flashLoan', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'receiverAddress', type: 'address' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'bytes', name: 'params', type: 'bytes' }, + { internalType: 'uint16', name: 'referralCode', type: 'uint16' }, + ], + name: 'flashLoanSimple', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'getBorrowLogic', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [], + name: 'getBridgeLogic', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getConfiguration', + outputs: [ + { + components: [ + { internalType: 'uint256', name: 'data', type: 'uint256' }, + ], + internalType: 'struct DataTypes.ReserveConfigurationMap', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint8', name: 'id', type: 'uint8' }], + name: 'getEModeCategoryBorrowableBitmap', + outputs: [{ internalType: 'uint128', name: '', type: 'uint128' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint8', name: 'id', type: 'uint8' }], + name: 'getEModeCategoryCollateralBitmap', + outputs: [{ internalType: 'uint128', name: '', type: 'uint128' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint8', name: 'id', type: 'uint8' }], + name: 'getEModeCategoryCollateralConfig', + outputs: [ + { + components: [ + { internalType: 'uint16', name: 'ltv', type: 'uint16' }, + { + internalType: 'uint16', + name: 'liquidationThreshold', + type: 'uint16', + }, + { internalType: 'uint16', name: 'liquidationBonus', type: 'uint16' }, + ], + internalType: 'struct DataTypes.CollateralConfig', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint8', name: 'id', type: 'uint8' }], + name: 'getEModeCategoryData', + outputs: [ + { + components: [ + { internalType: 'uint16', name: 'ltv', type: 'uint16' }, + { + internalType: 'uint16', + name: 'liquidationThreshold', + type: 'uint16', + }, + { internalType: 'uint16', name: 'liquidationBonus', type: 'uint16' }, + { internalType: 'address', name: 'priceSource', type: 'address' }, + { internalType: 'string', name: 'label', type: 'string' }, + ], + internalType: 'struct DataTypes.EModeCategoryLegacy', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint8', name: 'id', type: 'uint8' }], + name: 'getEModeCategoryLabel', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getEModeLogic', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [], + name: 'getFlashLoanLogic', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getLiquidationGracePeriod', + outputs: [{ internalType: 'uint40', name: '', type: 'uint40' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'getLiquidationLogic', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [], + name: 'getPoolLogic', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [{ internalType: 'uint16', name: 'id', type: 'uint16' }], + name: 'getReserveAddressById', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getReserveData', + outputs: [ + { + components: [ + { + components: [ + { internalType: 'uint256', name: 'data', type: 'uint256' }, + ], + internalType: 'struct DataTypes.ReserveConfigurationMap', + name: 'configuration', + type: 'tuple', + }, + { internalType: 'uint128', name: 'liquidityIndex', type: 'uint128' }, + { + internalType: 'uint128', + name: 'currentLiquidityRate', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'variableBorrowIndex', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'currentVariableBorrowRate', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'currentStableBorrowRate', + type: 'uint128', + }, + { + internalType: 'uint40', + name: 'lastUpdateTimestamp', + type: 'uint40', + }, + { internalType: 'uint16', name: 'id', type: 'uint16' }, + { internalType: 'address', name: 'aTokenAddress', type: 'address' }, + { + internalType: 'address', + name: 'stableDebtTokenAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'variableDebtTokenAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'interestRateStrategyAddress', + type: 'address', + }, + { + internalType: 'uint128', + name: 'accruedToTreasury', + type: 'uint128', + }, + { internalType: 'uint128', name: 'unbacked', type: 'uint128' }, + { + internalType: 'uint128', + name: 'isolationModeTotalDebt', + type: 'uint128', + }, + ], + internalType: 'struct DataTypes.ReserveDataLegacy', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getReserveDataExtended', + outputs: [ + { + components: [ + { + components: [ + { internalType: 'uint256', name: 'data', type: 'uint256' }, + ], + internalType: 'struct DataTypes.ReserveConfigurationMap', + name: 'configuration', + type: 'tuple', + }, + { internalType: 'uint128', name: 'liquidityIndex', type: 'uint128' }, + { + internalType: 'uint128', + name: 'currentLiquidityRate', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'variableBorrowIndex', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'currentVariableBorrowRate', + type: 'uint128', + }, + { + internalType: 'uint128', + name: '__deprecatedStableBorrowRate', + type: 'uint128', + }, + { + internalType: 'uint40', + name: 'lastUpdateTimestamp', + type: 'uint40', + }, + { internalType: 'uint16', name: 'id', type: 'uint16' }, + { + internalType: 'uint40', + name: 'liquidationGracePeriodUntil', + type: 'uint40', + }, + { internalType: 'address', name: 'aTokenAddress', type: 'address' }, + { + internalType: 'address', + name: '__deprecatedStableDebtTokenAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'variableDebtTokenAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'interestRateStrategyAddress', + type: 'address', + }, + { + internalType: 'uint128', + name: 'accruedToTreasury', + type: 'uint128', + }, + { internalType: 'uint128', name: 'unbacked', type: 'uint128' }, + { + internalType: 'uint128', + name: 'isolationModeTotalDebt', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'virtualUnderlyingBalance', + type: 'uint128', + }, + ], + internalType: 'struct DataTypes.ReserveData', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getReserveNormalizedIncome', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getReserveNormalizedVariableDebt', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getReservesCount', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getReservesList', + outputs: [{ internalType: 'address[]', name: '', type: 'address[]' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getSupplyLogic', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'user', type: 'address' }], + name: 'getUserAccountData', + outputs: [ + { internalType: 'uint256', name: 'totalCollateralBase', type: 'uint256' }, + { internalType: 'uint256', name: 'totalDebtBase', type: 'uint256' }, + { + internalType: 'uint256', + name: 'availableBorrowsBase', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'currentLiquidationThreshold', + type: 'uint256', + }, + { internalType: 'uint256', name: 'ltv', type: 'uint256' }, + { internalType: 'uint256', name: 'healthFactor', type: 'uint256' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'user', type: 'address' }], + name: 'getUserConfiguration', + outputs: [ + { + components: [ + { internalType: 'uint256', name: 'data', type: 'uint256' }, + ], + internalType: 'struct DataTypes.UserConfigurationMap', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'user', type: 'address' }], + name: 'getUserEMode', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getVirtualUnderlyingBalance', + outputs: [{ internalType: 'uint128', name: '', type: 'uint128' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'aTokenAddress', type: 'address' }, + { internalType: 'address', name: 'variableDebtAddress', type: 'address' }, + { + internalType: 'address', + name: 'interestRateStrategyAddress', + type: 'address', + }, + ], + name: 'initReserve', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IPoolAddressesProvider', + name: 'provider', + type: 'address', + }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'collateralAsset', type: 'address' }, + { internalType: 'address', name: 'debtAsset', type: 'address' }, + { internalType: 'address', name: 'user', type: 'address' }, + { internalType: 'uint256', name: 'debtToCover', type: 'uint256' }, + { internalType: 'bool', name: 'receiveAToken', type: 'bool' }, + ], + name: 'liquidationCall', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'args1', type: 'bytes32' }, + { internalType: 'bytes32', name: 'args2', type: 'bytes32' }, + ], + name: 'liquidationCall', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address[]', name: 'assets', type: 'address[]' }], + name: 'mintToTreasury', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'address', name: 'onBehalfOf', type: 'address' }, + { internalType: 'uint16', name: 'referralCode', type: 'uint16' }, + ], + name: 'mintUnbacked', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'args', type: 'bytes32' }], + name: 'repay', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'uint256', name: 'interestRateMode', type: 'uint256' }, + { internalType: 'address', name: 'onBehalfOf', type: 'address' }, + ], + name: 'repay', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'uint256', name: 'interestRateMode', type: 'uint256' }, + ], + name: 'repayWithATokens', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'args', type: 'bytes32' }], + name: 'repayWithATokens', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'args', type: 'bytes32' }, + { internalType: 'bytes32', name: 'r', type: 'bytes32' }, + { internalType: 'bytes32', name: 's', type: 'bytes32' }, + ], + name: 'repayWithPermit', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'uint256', name: 'interestRateMode', type: 'uint256' }, + { internalType: 'address', name: 'onBehalfOf', type: 'address' }, + { internalType: 'uint256', name: 'deadline', type: 'uint256' }, + { internalType: 'uint8', name: 'permitV', type: 'uint8' }, + { internalType: 'bytes32', name: 'permitR', type: 'bytes32' }, + { internalType: 'bytes32', name: 'permitS', type: 'bytes32' }, + ], + name: 'repayWithPermit', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'token', type: 'address' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'rescueTokens', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'resetIsolationModeTotalDebt', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { + components: [ + { internalType: 'uint256', name: 'data', type: 'uint256' }, + ], + internalType: 'struct DataTypes.ReserveConfigurationMap', + name: 'configuration', + type: 'tuple', + }, + ], + name: 'setConfiguration', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint40', name: 'until', type: 'uint40' }, + ], + name: 'setLiquidationGracePeriod', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'rateStrategyAddress', type: 'address' }, + ], + name: 'setReserveInterestRateStrategyAddress', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint8', name: 'categoryId', type: 'uint8' }], + name: 'setUserEMode', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'args', type: 'bytes32' }], + name: 'setUserUseReserveAsCollateral', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'bool', name: 'useAsCollateral', type: 'bool' }, + ], + name: 'setUserUseReserveAsCollateral', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'address', name: 'onBehalfOf', type: 'address' }, + { internalType: 'uint16', name: 'referralCode', type: 'uint16' }, + ], + name: 'supply', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'args', type: 'bytes32' }], + name: 'supply', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'address', name: 'onBehalfOf', type: 'address' }, + { internalType: 'uint16', name: 'referralCode', type: 'uint16' }, + { internalType: 'uint256', name: 'deadline', type: 'uint256' }, + { internalType: 'uint8', name: 'permitV', type: 'uint8' }, + { internalType: 'bytes32', name: 'permitR', type: 'bytes32' }, + { internalType: 'bytes32', name: 'permitS', type: 'bytes32' }, + ], + name: 'supplyWithPermit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'args', type: 'bytes32' }, + { internalType: 'bytes32', name: 'r', type: 'bytes32' }, + { internalType: 'bytes32', name: 's', type: 'bytes32' }, + ], + name: 'supplyWithPermit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'syncIndexesState', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'syncRatesState', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'protocolFee', type: 'uint256' }], + name: 'updateBridgeProtocolFee', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint128', + name: 'flashLoanPremiumTotal', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'flashLoanPremiumToProtocol', + type: 'uint128', + }, + ], + name: 'updateFlashloanPremiums', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'address', name: 'to', type: 'address' }, + ], + name: 'withdraw', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'args', type: 'bytes32' }], + name: 'withdraw', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, +] as const; diff --git a/packages/universal-data/src/abis/multicall-abi.ts b/packages/universal-data/src/abis/multicall-abi.ts new file mode 100644 index 00000000..fd4f9d1e --- /dev/null +++ b/packages/universal-data/src/abis/multicall-abi.ts @@ -0,0 +1,28 @@ +export const multicallAbi = [ + { + type: 'function', + name: 'multicall', + inputs: [ + { + name: '_executions', + type: 'tuple[]', + internalType: 'struct Execution[]', + components: [ + { name: 'target', type: 'address', internalType: 'address' }, + { name: 'value', type: 'uint256', internalType: 'uint256' }, + { name: 'callData', type: 'bytes', internalType: 'bytes' }, + ], + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'error', + name: 'CallReverted', + inputs: [ + { name: 'index', type: 'uint256', internalType: 'uint256' }, + { name: 'data', type: 'bytes', internalType: 'bytes' }, + ], + }, +] as const; diff --git a/packages/universal-data/src/deployments.ts b/packages/universal-data/src/deployments.ts index f96cb6dc..f31ea4d6 100644 --- a/packages/universal-data/src/deployments.ts +++ b/packages/universal-data/src/deployments.ts @@ -1,6 +1,8 @@ export const universalDeployments = { // Test Erc20Mintable: '0x4C8Be898BdE148aE6f9B0AF86e7D2b5a0558A7d0', + // Periphery + Multicall: '0x7063f9cB3623B872f75B54E5bFAECf1FEe1699fc', // Universal Identity Resolver: '0xc675eE8dA6B4183f977a7e9F1C4589B20982b8C3', // Delegation Framework Core diff --git a/packages/universal-data/src/exports/index.ts b/packages/universal-data/src/exports/index.ts index 8ed75b4b..9c134480 100644 --- a/packages/universal-data/src/exports/index.ts +++ b/packages/universal-data/src/exports/index.ts @@ -1,3 +1,5 @@ +export { aaveV3PoolAbi } from '../abis/aave-v3-pool-abi.js'; +export { multicallAbi } from '../abis/multicall-abi.js'; export { delegationManagerAbi } from '../abis/delegation-manager-abi.js'; export { erc20TransferAmountEnforcerAbi } from '../abis/erc20-transfer-amount-enforcer-abi.js'; export { universalDocumentAbi } from '../abis/universal-document-abi.js'; diff --git a/packages/universal-delegations-sdk/src/enforcers/enforcer-external-hook.ts b/packages/universal-delegations-sdk/src/enforcers/enforcer-external-hook.ts new file mode 100644 index 00000000..bdc75422 --- /dev/null +++ b/packages/universal-delegations-sdk/src/enforcers/enforcer-external-hook.ts @@ -0,0 +1,13 @@ +import { encodePacked, type Hex, type Address } from 'viem'; + +export type EncodeExternalHookArgsParams = { + target: Address; + callData: Hex; +}; + +export function encodeExternalHookArgs({ + target, + callData, +}: EncodeExternalHookArgsParams) { + return encodePacked(['address', 'bytes'], [target, callData]); +} diff --git a/packages/universal-delegations-sdk/src/exports/index.ts b/packages/universal-delegations-sdk/src/exports/index.ts index 55e8d70b..82eb7b90 100644 --- a/packages/universal-delegations-sdk/src/exports/index.ts +++ b/packages/universal-delegations-sdk/src/exports/index.ts @@ -21,6 +21,7 @@ export { encodeEnforcerERC20TransferAmount, getErc20TransferAmountEnforcerFromDelegation, } from '../enforcers/enforcer-erc20-transfer-amount.js'; +export { encodeExternalHookArgs } from '../enforcers/enforcer-external-hook.js'; export { useDelegationExecute } from '../actions/core/use-delegation-execute.js'; export { useDelegationStatus } from '../actions/core/use-delegation-status.js'; export { useDisableDelegation } from '../actions/core/use-disable-delegation.js'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ef0bc41b..f9ce7db3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -819,7 +819,7 @@ importers: version: 2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: specifier: 2.12.11 - version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) devDependencies: '@biomejs/biome': specifier: 1.9.4 @@ -844,7 +844,7 @@ importers: version: 2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: specifier: 2.12.11 - version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) packages/universal-delegations-sdk: dependencies: @@ -868,7 +868,7 @@ importers: version: 2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: specifier: 2.12.11 - version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) packages/universal-identity-sdk: dependencies: @@ -883,7 +883,7 @@ importers: version: 2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: specifier: 2.12.11 - version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) devDependencies: '@biomejs/biome': specifier: 1.9.4 @@ -914,7 +914,7 @@ importers: version: 2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: specifier: 2.12.11 - version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) packages/universal-types: dependencies: @@ -926,7 +926,7 @@ importers: version: 2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: specifier: 2.12.11 - version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) packages/universal-wallet-connector: dependencies: @@ -941,7 +941,7 @@ importers: version: 2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: specifier: 2.12.11 - version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + version: 2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) packages/universal-wallet-sdk: dependencies: @@ -13557,7 +13557,7 @@ snapshots: '@metamask/safe-event-emitter@3.1.2': {} - '@metamask/sdk-communication-layer@0.28.2(cross-fetch@4.0.0(encoding@0.1.13))(eciesjs@0.3.21)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))': + '@metamask/sdk-communication-layer@0.28.2(cross-fetch@4.0.0(encoding@0.1.13))(eciesjs@0.3.21)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.8)(utf-8-validate@6.0.5))': dependencies: bufferutil: 4.0.8 cross-fetch: 4.0.0(encoding@0.1.13) @@ -13566,13 +13566,13 @@ snapshots: eciesjs: 0.3.21 eventemitter2: 6.4.9 readable-stream: 3.6.2 - socket.io-client: 4.8.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + socket.io-client: 4.8.1(bufferutil@4.0.8)(utf-8-validate@6.0.5) utf-8-validate: 5.0.10 uuid: 8.3.2 transitivePeerDependencies: - supports-color - '@metamask/sdk-communication-layer@0.28.2(cross-fetch@4.0.0(encoding@0.1.13))(eciesjs@0.3.21)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.8)(utf-8-validate@6.0.5))': + '@metamask/sdk-communication-layer@0.28.2(cross-fetch@4.0.0)(eciesjs@0.3.21)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))': dependencies: bufferutil: 4.0.8 cross-fetch: 4.0.0(encoding@0.1.13) @@ -13581,7 +13581,7 @@ snapshots: eciesjs: 0.3.21 eventemitter2: 6.4.9 readable-stream: 3.6.2 - socket.io-client: 4.8.1(bufferutil@4.0.8)(utf-8-validate@6.0.5) + socket.io-client: 4.8.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) utf-8-validate: 5.0.10 uuid: 8.3.2 transitivePeerDependencies: @@ -13596,13 +13596,13 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-native: 0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@6.0.5) - '@metamask/sdk-install-modal-web@0.28.1(i18next@23.11.5)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)': + '@metamask/sdk-install-modal-web@0.28.1(i18next@23.11.5)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)': dependencies: i18next: 23.11.5 qr-code-styling: 1.8.4 optionalDependencies: react: 18.3.1 - react-native: 0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) + react-native: 0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10) '@metamask/sdk@0.28.2(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@6.0.5))(react@18.3.1)(rollup@3.29.5)(utf-8-validate@6.0.5)': dependencies: @@ -13676,12 +13676,12 @@ snapshots: - supports-color - utf-8-validate - '@metamask/sdk@0.28.2(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(utf-8-validate@5.0.10)': + '@metamask/sdk@0.28.2(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(utf-8-validate@5.0.10)': dependencies: '@metamask/onboarding': 1.0.1 '@metamask/providers': 16.1.0 - '@metamask/sdk-communication-layer': 0.28.2(cross-fetch@4.0.0(encoding@0.1.13))(eciesjs@0.3.21)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - '@metamask/sdk-install-modal-web': 0.28.1(i18next@23.11.5)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) + '@metamask/sdk-communication-layer': 0.28.2(cross-fetch@4.0.0)(eciesjs@0.3.21)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@metamask/sdk-install-modal-web': 0.28.1(i18next@23.11.5)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) '@types/dom-screen-wake-lock': 1.0.3 '@types/uuid': 10.0.0 bowser: 2.11.0 @@ -13695,7 +13695,7 @@ snapshots: obj-multiplex: 1.0.0 pump: 3.0.2 qrcode-terminal-nooctal: 0.12.1 - react-native-webview: 11.26.1(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) + react-native-webview: 11.26.1(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) readable-stream: 3.6.2 rollup-plugin-visualizer: 5.12.0(rollup@4.27.4) socket.io-client: 4.8.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -15012,7 +15012,7 @@ snapshots: execa: 5.1.1 invariant: 2.2.4 metro: 0.81.0(bufferutil@4.0.8)(utf-8-validate@6.0.5) - metro-config: 0.81.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + metro-config: 0.81.0(bufferutil@4.0.8)(utf-8-validate@6.0.5) metro-core: 0.81.0 node-fetch: 2.7.0(encoding@0.1.13) readline: 1.3.0 @@ -15086,6 +15086,7 @@ snapshots: react-native: 0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) optionalDependencies: '@types/react': 18.3.12 + optional: true '@react-native/virtualized-lists@0.76.1(@types/react@18.3.12)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@6.0.5))(react@18.3.1)': dependencies: @@ -15096,6 +15097,15 @@ snapshots: optionalDependencies: '@types/react': 18.3.12 + '@react-native/virtualized-lists@0.76.1(@types/react@18.3.12)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)': + dependencies: + invariant: 2.2.4 + nullthrows: 1.1.1 + react: 18.3.1 + react-native: 0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10) + optionalDependencies: + '@types/react': 18.3.12 + '@reown/walletkit@1.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.5)': dependencies: '@walletconnect/core': 2.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.5) @@ -16242,14 +16252,14 @@ snapshots: - supports-color - utf-8-validate - '@wagmi/connectors@5.1.10(@types/react@18.3.12)(@wagmi/core@2.13.5(@tanstack/query-core@5.59.20)(@types/react@18.3.12)(react@18.3.1)(typescript@5.6.3)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)': + '@wagmi/connectors@5.1.10(@types/react@18.3.12)(@wagmi/core@2.13.5(@tanstack/query-core@5.59.20)(@types/react@18.3.12)(react@18.3.1)(typescript@5.6.3)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)': dependencies: '@coinbase/wallet-sdk': 4.0.4 - '@metamask/sdk': 0.28.2(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(utf-8-validate@5.0.10) + '@metamask/sdk': 0.28.2(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.3(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) '@wagmi/core': 2.13.5(@tanstack/query-core@5.59.20)(@types/react@18.3.12)(react@18.3.1)(typescript@5.6.3)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8)) - '@walletconnect/ethereum-provider': 2.16.1(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) + '@walletconnect/ethereum-provider': 2.16.1(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10) '@walletconnect/modal': 2.6.2(@types/react@18.3.12)(react@18.3.1) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' viem: 2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) @@ -16545,16 +16555,16 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/ethereum-provider@2.16.1(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)': + '@walletconnect/ethereum-provider@2.16.1(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@6.0.5)': dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/modal': 2.6.2(@types/react@18.3.12)(react@18.3.1) - '@walletconnect/sign-client': 2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@walletconnect/sign-client': 2.16.1(bufferutil@4.0.8)(utf-8-validate@6.0.5) '@walletconnect/types': 2.16.1 - '@walletconnect/universal-provider': 2.16.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + '@walletconnect/universal-provider': 2.16.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@6.0.5) '@walletconnect/utils': 2.16.1 events: 3.3.0 transitivePeerDependencies: @@ -16577,16 +16587,16 @@ snapshots: - react - utf-8-validate - '@walletconnect/ethereum-provider@2.16.1(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@6.0.5)': + '@walletconnect/ethereum-provider@2.16.1(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10)': dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/modal': 2.6.2(@types/react@18.3.12)(react@18.3.1) - '@walletconnect/sign-client': 2.16.1(bufferutil@4.0.8)(utf-8-validate@6.0.5) + '@walletconnect/sign-client': 2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@walletconnect/types': 2.16.1 - '@walletconnect/universal-provider': 2.16.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@6.0.5) + '@walletconnect/universal-provider': 2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@walletconnect/utils': 2.16.1 events: 3.3.0 transitivePeerDependencies: @@ -16889,14 +16899,14 @@ snapshots: - '@vercel/kv' - ioredis - '@walletconnect/universal-provider@2.16.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)': + '@walletconnect/universal-provider@2.16.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@6.0.5)': dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@walletconnect/sign-client': 2.16.1(bufferutil@4.0.8)(utf-8-validate@6.0.5) '@walletconnect/types': 2.16.1 '@walletconnect/utils': 2.16.1 events: 3.3.0 @@ -16918,14 +16928,14 @@ snapshots: - ioredis - utf-8-validate - '@walletconnect/universal-provider@2.16.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@6.0.5)': + '@walletconnect/universal-provider@2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.16.1(bufferutil@4.0.8)(utf-8-validate@6.0.5) + '@walletconnect/sign-client': 2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@walletconnect/types': 2.16.1 '@walletconnect/utils': 2.16.1 events: 3.3.0 @@ -21046,6 +21056,21 @@ snapshots: - supports-color - utf-8-validate + metro-config@0.81.0(bufferutil@4.0.8)(utf-8-validate@6.0.5): + dependencies: + connect: 3.7.0 + cosmiconfig: 5.2.1 + flow-enums-runtime: 0.0.6 + jest-validate: 29.7.0 + metro: 0.81.0(bufferutil@4.0.8)(utf-8-validate@6.0.5) + metro-cache: 0.81.0 + metro-core: 0.81.0 + metro-runtime: 0.81.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + metro-core@0.81.0: dependencies: flow-enums-runtime: 0.0.6 @@ -21238,7 +21263,7 @@ snapshots: metro-babel-transformer: 0.81.0 metro-cache: 0.81.0 metro-cache-key: 0.81.0 - metro-config: 0.81.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + metro-config: 0.81.0(bufferutil@4.0.8)(utf-8-validate@6.0.5) metro-core: 0.81.0 metro-file-map: 0.81.0 metro-resolver: 0.81.0 @@ -22263,6 +22288,7 @@ snapshots: invariant: 2.2.4 react: 18.3.1 react-native: 0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10) + optional: true react-native-webview@11.26.1(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@6.0.5))(react@18.3.1): dependencies: @@ -22271,6 +22297,13 @@ snapshots: react: 18.3.1 react-native: 0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@6.0.5) + react-native-webview@11.26.1(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1): + dependencies: + escape-string-regexp: 2.0.0 + invariant: 2.2.4 + react: 18.3.1 + react-native: 0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10) + react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10): dependencies: '@jest/create-cache-key-function': 29.7.0 @@ -22322,6 +22355,7 @@ snapshots: - encoding - supports-color - utf-8-validate + optional: true react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@6.0.5): dependencies: @@ -22375,6 +22409,58 @@ snapshots: - supports-color - utf-8-validate + react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10): + dependencies: + '@jest/create-cache-key-function': 29.7.0 + '@react-native/assets-registry': 0.76.1 + '@react-native/codegen': 0.76.1(@babel/preset-env@7.26.0(@babel/core@7.26.0)) + '@react-native/community-cli-plugin': 0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + '@react-native/gradle-plugin': 0.76.1 + '@react-native/js-polyfills': 0.76.1 + '@react-native/normalize-colors': 0.76.1 + '@react-native/virtualized-lists': 0.76.1(@types/react@18.3.12)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1) + abort-controller: 3.0.0 + anser: 1.4.10 + ansi-regex: 5.0.1 + babel-jest: 29.7.0(@babel/core@7.26.0) + babel-plugin-syntax-hermes-parser: 0.23.1 + base64-js: 1.5.1 + chalk: 4.1.2 + commander: 12.1.0 + event-target-shim: 5.0.1 + flow-enums-runtime: 0.0.6 + glob: 7.2.3 + invariant: 2.2.4 + jest-environment-node: 29.7.0 + jsc-android: 250231.0.0 + memoize-one: 5.2.1 + metro-runtime: 0.81.0 + metro-source-map: 0.81.0 + mkdirp: 0.5.6 + nullthrows: 1.1.1 + pretty-format: 29.7.0 + promise: 8.3.0 + react: 18.3.1 + react-devtools-core: 5.3.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + react-refresh: 0.14.2 + regenerator-runtime: 0.13.11 + scheduler: 0.24.0-canary-efb381bbf-20230505 + semver: 7.6.3 + stacktrace-parser: 0.1.10 + whatwg-fetch: 3.6.20 + ws: 6.2.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + yargs: 17.7.2 + optionalDependencies: + '@types/react': 18.3.12 + transitivePeerDependencies: + - '@babel/core' + - '@babel/preset-env' + - '@react-native-community/cli-server-api' + - bufferutil + - encoding + - supports-color + - utf-8-validate + react-qr-reader-es6@2.2.1-2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: jsqr-es6: 1.4.0-1 @@ -23950,10 +24036,10 @@ snapshots: - utf-8-validate - zod - wagmi@2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8): + wagmi@2.12.11(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.12)(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8): dependencies: '@tanstack/react-query': 5.59.20(react@18.3.1) - '@wagmi/connectors': 5.1.10(@types/react@18.3.12)(@wagmi/core@2.13.5(@tanstack/query-core@5.59.20)(@types/react@18.3.12)(react@18.3.1)(typescript@5.6.3)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + '@wagmi/connectors': 5.1.10(@types/react@18.3.12)(@wagmi/core@2.13.5(@tanstack/query-core@5.59.20)(@types/react@18.3.12)(react@18.3.1)(typescript@5.6.3)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(react-native@0.76.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.12)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.27.4)(typescript@5.6.3)(utf-8-validate@5.0.10)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) '@wagmi/core': 2.13.5(@tanstack/query-core@5.59.20)(@types/react@18.3.12)(react@18.3.1)(typescript@5.6.3)(viem@2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8)) react: 18.3.1 use-sync-external-store: 1.2.0(react@18.3.1) From 2d91555e490d22507200d9dfe2b475eb37031cfd Mon Sep 17 00:00:00 2001 From: Kames Date: Wed, 11 Dec 2024 17:34:04 -0800 Subject: [PATCH 03/10] wip: erc20 swap --- apps/wallet/app/(site)/finance/swap/page.tsx | 14 ++ .../app/(site)/finance/transfer/page.tsx | 4 +- .../core/account-transfer-dialog.tsx | 4 +- .../fields/erc20-select-and-amount.tsx | 97 ++++++++++-- .../src/components/fields/erc20-selector.tsx | 37 +++-- .../src/components/forms/form-erc20-swap.tsx | 147 ++++++++++++++++++ .../components/forms/form-erc20-transfer.tsx | 8 +- .../layout/app-sidebar-menu-items.ts | 6 + ...rc20-balance-gte-after-all-enforcer-abi.ts | 97 ++++++++++++ packages/universal-data/src/deployments.ts | 4 + .../src/token-list/stablecoin-token-list.ts | 17 ++ .../src/actions/use-sign-erc20-swap.ts | 143 +++++++++++++++++ .../erc20-balance-gte-wrap-enforcer.ts | 34 ++++ .../src/enforcers/external-call-enforcer.ts | 13 ++ .../src/exports/index.ts | 38 +++-- 15 files changed, 609 insertions(+), 54 deletions(-) create mode 100644 apps/wallet/app/(site)/finance/swap/page.tsx create mode 100644 apps/wallet/src/components/forms/form-erc20-swap.tsx create mode 100644 packages/universal-data/src/abis/erc20-balance-gte-after-all-enforcer-abi.ts create mode 100644 packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts create mode 100644 packages/universal-delegations-sdk/src/enforcers/erc20-balance-gte-wrap-enforcer.ts create mode 100644 packages/universal-delegations-sdk/src/enforcers/external-call-enforcer.ts diff --git a/apps/wallet/app/(site)/finance/swap/page.tsx b/apps/wallet/app/(site)/finance/swap/page.tsx new file mode 100644 index 00000000..0f18169b --- /dev/null +++ b/apps/wallet/app/(site)/finance/swap/page.tsx @@ -0,0 +1,14 @@ +'use client'; +import { FormErc20Swap } from '@/components/forms/form-erc20-swap'; + +export default function FinanceSwapPage() { + return ( + <> +
+
+ +
+
+ + ); +} diff --git a/apps/wallet/app/(site)/finance/transfer/page.tsx b/apps/wallet/app/(site)/finance/transfer/page.tsx index cea668c8..3e8ba5b9 100644 --- a/apps/wallet/app/(site)/finance/transfer/page.tsx +++ b/apps/wallet/app/(site)/finance/transfer/page.tsx @@ -1,12 +1,12 @@ 'use client'; -import { FormerErc20Transfer } from '@/components/forms/form-erc20-transfer'; +import { FormErc20Transfer } from '@/components/forms/form-erc20-transfer'; export default function FinanceTransferPage() { return ( <>
- +
diff --git a/apps/wallet/src/components/core/account-transfer-dialog.tsx b/apps/wallet/src/components/core/account-transfer-dialog.tsx index 0fa997b7..8ad93dbf 100644 --- a/apps/wallet/src/components/core/account-transfer-dialog.tsx +++ b/apps/wallet/src/components/core/account-transfer-dialog.tsx @@ -8,7 +8,7 @@ import { } from '@/components/ui/dialog'; import type * as React from 'react'; import type { Address } from 'viem'; -import { FormerErc20Transfer } from '../forms/form-erc20-transfer'; +import { FormErc20Transfer } from '../forms/form-erc20-transfer'; type AccountTransferDialogProps = React.HTMLAttributes & { address: Address; @@ -32,7 +32,7 @@ export const AccountTransferDialog = ({ Transfer assets to another address. - void; } export function Erc20SelectAndAmount({ disabled, tokenList, + label = 'Asset', + amountName = 'amount', + tokenName = 'token', + setMaxAmount, }: Erc20SelectAndAmount) { const { control } = useFormContext(); + return (
- Asset + {label}
( @@ -44,9 +51,9 @@ export function Erc20SelectAndAmount({ /> ( - + name={tokenName} + render={({ field, ...rest }) => ( + + )} />
- + {/* Select the asset and amount you want to transfer. - + */}
); } + +type BalanceAndMaxInputProps = React.HTMLAttributes & { + token: TokenItem; + setMaxAmount?: (value: string) => void; +}; + +const BalanceAndMaxInput = ({ + className, + token, + setMaxAmount, +}: BalanceAndMaxInputProps) => { + const { address: account } = useAccount(); + const { data } = useReadContract({ + abi: erc20Abi, + address: token?.address as Address, + functionName: 'balanceOf', + args: [account as Address], + query: { + enabled: !!account && !!token, + refetchInterval: 5000, + }, + }); + + if (!token) { + return null; + } + + if (!data) { + return ( +
+ 0.00 {token?.symbol} +
+ ); + } + + return ( +
+ + {formatNumber(formatUnits(data, token.decimals))} + {token?.symbol} + + {setMaxAmount && ( + setMaxAmount?.(formatUnits(data, token.decimals))} + variant={'outline'} + className="cursor-pointer text-xs transition-shadow hover:shadow-md" + > + Max + + )} +
+ ); +}; diff --git a/apps/wallet/src/components/fields/erc20-selector.tsx b/apps/wallet/src/components/fields/erc20-selector.tsx index 129680c2..d48c90b0 100644 --- a/apps/wallet/src/components/fields/erc20-selector.tsx +++ b/apps/wallet/src/components/fields/erc20-selector.tsx @@ -10,6 +10,8 @@ import { import { cn } from '@/lib/utils'; import { useCallback, useMemo, useState } from 'react'; import type { TokenItem, TokenList } from 'universal-types'; +import type { Address } from 'viem'; +import { ERC20Balance } from '../onchain/erc20-balance'; import { Button } from '../ui/button'; import { DialogDescription, DialogTitle } from '../ui/dialog'; @@ -62,7 +64,7 @@ export function TokenSelector({ type="button" variant={'outline'} className={cn( - 'flex w-fit items-center gap-x-2 rounded-full py-2', + 'flex w-fit items-center gap-x-2 rounded-full px-6 py-2', // className, )} onClick={() => (disabled ? undefined : setOpen(true))} @@ -104,20 +106,27 @@ export function TokenSelector({ className="flex cursor-pointer" onSelect={() => handleSelect(token)} > -
- {`${token.name} -
-

{token.name}

-

- {token.symbol} -

+
+
+ {`${token.name} +
+

{token.name}

+

+ {token.symbol} +

+
+
))} diff --git a/apps/wallet/src/components/forms/form-erc20-swap.tsx b/apps/wallet/src/components/forms/form-erc20-swap.tsx new file mode 100644 index 00000000..a5a7bff4 --- /dev/null +++ b/apps/wallet/src/components/forms/form-erc20-swap.tsx @@ -0,0 +1,147 @@ +'use client'; +import { Erc20SelectAndAmount } from '@/components/fields/erc20-select-and-amount'; +import { ConnectUniversalWalletButton } from '@/components/onchain/connect-universal-wallet'; +import { Button } from '@/components/ui/button'; +import { Card } from '@/components/ui/card'; +import { Form } from '@/components/ui/form'; +import { defaultTokenList, useIsValidChain } from '@/lib/chains'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useForm } from 'react-hook-form'; +import { ANY_DELEGATE, findToken, getDefaultTokenList } from 'universal-data'; +import { useSignErc20SwapDelegation } from 'universal-delegations-sdk'; +import type { TokenItem } from 'universal-types'; +import type { Address } from 'viem'; +import { useAccount, useSwitchChain } from 'wagmi'; +import { useWriteContracts } from 'wagmi/experimental'; +import { z } from 'zod'; + +const formSchema = z.object({ + tokenOut: z.custom().refine((value) => !!value?.address, { + message: 'Token is required', + }), + amountOut: z.string(), + tokenIn: z.custom().refine((value) => !!value?.address, { + message: 'Token is required', + }), + amountIn: z.string(), +}); + +export type FormData = { + tokenOut?: Address; + amountOut?: string; + tokenIn?: Address; + amountIn?: string; +}; + +type FormErc20SwapProps = { + defaultValues?: FormData; +}; + +function FormErc20Swap({ defaultValues }: FormErc20SwapProps) { + const { address } = useAccount(); + const { switchChain, isPending: isPendingSwitchChain } = useSwitchChain(); + const { signAndSaveDelegationAsync, isSuccess } = + useSignErc20SwapDelegation(); + const { writeContracts } = useWriteContracts(); + + const { isValidChain, chainId, defaultChain } = useIsValidChain(); + + const tokenList = getDefaultTokenList({ chainId }); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + tokenOut: defaultValues?.tokenOut + ? findToken({ address: defaultValues?.tokenOut, tokenList }) + : undefined, + amountOut: defaultValues?.amountOut || undefined, + tokenIn: defaultValues?.tokenIn + ? findToken({ address: defaultValues?.tokenIn, tokenList }) + : undefined, + amountIn: defaultValues?.amountIn || undefined, + }, + }); + + async function onSubmit(data: z.infer) { + if (!isValidChain) { + switchChain({ + chainId: defaultChain.id, + }); + return; + } + await signAndSaveDelegationAsync({ + chainId: chainId, + delegate: ANY_DELEGATE, + delegator: address as Address, + tokenOut: data.tokenOut.address as Address, + decimalsOut: data.tokenOut.decimals, + amountOut: data?.amountOut?.toString(), + tokenIn: data.tokenIn.address as Address, + decimalsIn: data.tokenIn.decimals, + amountIn: data?.amountIn?.toString(), + }); + form.reset({ + tokenIn: undefined, + amountIn: undefined, + tokenOut: undefined, + amountOut: undefined, + }); + } + + return ( +
+ + + form.setValue('amountOut', value)} + /> + + + + + {address && isValidChain && ( + <> + + + )} + {address && !isValidChain && ( + + )} + {!address && ( + + Connect Universal Wallet + + )} +
+ + ); +} + +export { FormErc20Swap }; diff --git a/apps/wallet/src/components/forms/form-erc20-transfer.tsx b/apps/wallet/src/components/forms/form-erc20-transfer.tsx index a26478da..4e411ee1 100644 --- a/apps/wallet/src/components/forms/form-erc20-transfer.tsx +++ b/apps/wallet/src/components/forms/form-erc20-transfer.tsx @@ -13,8 +13,8 @@ import { Erc20SelectAndAmount } from '@/components/fields/erc20-select-and-amoun import { ConnectUniversalWalletButton } from '@/components/onchain/connect-universal-wallet'; import { Card } from '@/components/ui/card'; import { defaultTokenList, useIsValidChain } from '@/lib/chains'; -import type { TokenItem } from 'universal-types'; import { findToken, getDefaultTokenList } from 'universal-data'; +import type { TokenItem } from 'universal-types'; import { useWriteContracts } from 'wagmi/experimental'; const formSchema = z.object({ @@ -31,11 +31,11 @@ export type FormData = { amount?: string; }; -type FormerErc20TransferProps = { +type FormErc20TransferProps = { defaultValues?: FormData; }; -function FormerErc20Transfer({ defaultValues }: FormerErc20TransferProps) { +function FormErc20Transfer({ defaultValues }: FormErc20TransferProps) { const { address } = useAccount(); const { switchChain, isPending: isPendingSwitchChain } = useSwitchChain(); const { writeContracts } = useWriteContracts(); @@ -127,4 +127,4 @@ function FormerErc20Transfer({ defaultValues }: FormerErc20TransferProps) { ); } -export { FormerErc20Transfer }; +export { FormErc20Transfer }; diff --git a/apps/wallet/src/components/layout/app-sidebar-menu-items.ts b/apps/wallet/src/components/layout/app-sidebar-menu-items.ts index 77ac9674..6ed9cc80 100644 --- a/apps/wallet/src/components/layout/app-sidebar-menu-items.ts +++ b/apps/wallet/src/components/layout/app-sidebar-menu-items.ts @@ -7,6 +7,7 @@ import { KeySquare, LayoutList, Orbit, + Rotate3D, Search, } from 'lucide-react'; @@ -34,6 +35,11 @@ export const itemsCore = [ ]; export const itemsFinance = [ + { + title: 'Swap', + url: '/finance/swap', + icon: Rotate3D, + }, { title: 'Transfer', url: '/finance/transfer', diff --git a/packages/universal-data/src/abis/erc20-balance-gte-after-all-enforcer-abi.ts b/packages/universal-data/src/abis/erc20-balance-gte-after-all-enforcer-abi.ts new file mode 100644 index 00000000..f60dedfe --- /dev/null +++ b/packages/universal-data/src/abis/erc20-balance-gte-after-all-enforcer-abi.ts @@ -0,0 +1,97 @@ +export const erc20TransferAmountEnforcerAbi = [ + { + type: 'function', + name: 'afterAllHook', + inputs: [ + { name: '_terms', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'ModeCode' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '_delegationHash', type: 'bytes32', internalType: 'bytes32' }, + { name: '_delegator', type: 'address', internalType: 'address' }, + { name: '', type: 'address', internalType: 'address' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'afterHook', + inputs: [ + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'ModeCode' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'bytes32' }, + { name: '', type: 'address', internalType: 'address' }, + { name: '', type: 'address', internalType: 'address' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'balanceCache', + inputs: [{ name: 'hashKey', type: 'bytes32', internalType: 'bytes32' }], + outputs: [{ name: 'balance', type: 'uint256', internalType: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + name: 'beforeAllHook', + inputs: [ + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'ModeCode' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'bytes32' }, + { name: '', type: 'address', internalType: 'address' }, + { name: '', type: 'address', internalType: 'address' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'beforeHook', + inputs: [ + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'ModeCode' }, + { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '', type: 'bytes32', internalType: 'bytes32' }, + { name: '', type: 'address', internalType: 'address' }, + { name: '', type: 'address', internalType: 'address' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'getHashKey', + inputs: [ + { name: '_caller', type: 'address', internalType: 'address' }, + { name: '_token', type: 'address', internalType: 'address' }, + { name: '_delegationHash', type: 'bytes32', internalType: 'bytes32' }, + ], + outputs: [{ name: '', type: 'bytes32', internalType: 'bytes32' }], + stateMutability: 'pure', + }, + { + type: 'function', + name: 'getTermsInfo', + inputs: [{ name: '_terms', type: 'bytes', internalType: 'bytes' }], + outputs: [ + { name: 'token_', type: 'address', internalType: 'address' }, + { name: 'amount_', type: 'uint256', internalType: 'uint256' }, + ], + stateMutability: 'pure', + }, + { + type: 'function', + name: 'isLocked', + inputs: [{ name: 'hashKey', type: 'bytes32', internalType: 'bytes32' }], + outputs: [{ name: 'lock', type: 'bool', internalType: 'bool' }], + stateMutability: 'view', + }, +] as const; diff --git a/packages/universal-data/src/deployments.ts b/packages/universal-data/src/deployments.ts index 8c8c7432..b27a7c19 100644 --- a/packages/universal-data/src/deployments.ts +++ b/packages/universal-data/src/deployments.ts @@ -1,3 +1,5 @@ +import { zeroAddress } from 'viem'; + export const universalDeployments = { // Test Erc20Mintable: '0x4C8Be898BdE148aE6f9B0AF86e7D2b5a0558A7d0', @@ -15,10 +17,12 @@ export const universalDeployments = { BlockNumberEnforcer: '0x32c454A3a7E54bAf6793995fF1F1b6b996c16519', DeployedEnforcer: '0x19B8BdF3354Af17a8cD9F35Db3E079Ce9864a10a', ERC20BalanceGteEnforcer: '0xA1AF62Da13E025E7E0bDc9294F98cD0fB907fC56', + ERC20BalanceGteWrapEnforcer: zeroAddress, ERC20TransferAmountEnforcer: '0x9Ec6bA1D261F32bA7D11935Af7014455414D32BA', ERC721BalanceGteEnforcer: '0xbdB11E994668e879e9dae7BddeaE757828CDBF41', ERC721TransferEnforcer: '0x1Abd29e4A8769Ee581aef8a0cFa688F20a5c355D', ERC1155BalanceGteEnforcer: '0x8aE8462A3cc592A0Bd96a8E14a9780B3C554F430', + ExternalCallEnforcer: zeroAddress, IdEnforcer: '0x1D14da69A0d3C7C65dbCA7001cAFf267384375F4', LimitedCallsEnforcer: '0xA10A29F7A15595d238875E18DE629964ca745119', NativeBalanceGteEnforcer: '0x029f9d80B228695611aD14d0665B2f5576E493E5', diff --git a/packages/universal-data/src/token-list/stablecoin-token-list.ts b/packages/universal-data/src/token-list/stablecoin-token-list.ts index f0b6b6a3..ff983048 100644 --- a/packages/universal-data/src/token-list/stablecoin-token-list.ts +++ b/packages/universal-data/src/token-list/stablecoin-token-list.ts @@ -27,6 +27,23 @@ export const stablecoinTokenList: TokenList = { }, }, }, + { + chainId: 8453, + name: 'Prize USDC (Savings Account)', + symbol: 'przUSDC', + logoURI: 'https://app.cabana.fi/icons/przUSDC.svg', + address: '0x7f5C2b379b88499aC2B997Db583f8079503f25b9', + decimals: 6, + }, + { + chainId: 8453, + name: 'Aave USDC (Yield Bearing)', + symbol: 'aUSDC', + logoURI: + 'https://assets.coingecko.com/coins/images/14318/standard/aUSDC.e260d492.png?1696514006', + address: '0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB', + decimals: 6, + }, { name: 'Dai Stablecoin', address: '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', diff --git a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts new file mode 100644 index 00000000..a850dc08 --- /dev/null +++ b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts @@ -0,0 +1,143 @@ +'use client'; +import { useState } from 'react'; +import { ROOT_AUTHORITY, SALT, universalDeployments } from 'universal-data'; +import type { Delegation, DelegationWithMetadata } from 'universal-types'; +import { type Address, zeroAddress } from 'viem'; +import { useSignTypedData } from 'wagmi'; +import { useInsertDelegation } from '../api/actions/insert-delegation.js'; +import { eip712DelegationTypes } from '../delegation/eip712-delegation-type.js'; +import { getDelegationHash } from '../delegation/get-delegation-hash.js'; +import { encodeEnforcerERC20TransferAmount } from '../enforcers/enforcer-erc20-transfer-amount.js'; +import { encodeERC20BalanceGteWrapEnforcerTerms } from '../enforcers/erc20-balance-gte-wrap-enforcer.js'; + +type SignDelegationParams = { + chainId: number; + delegator: Address; + delegate: Address; + salt?: bigint; + tokenOut: Address; + decimalsOut: number; + amountOut: string; + tokenIn: Address; + decimalsIn: number; + amountIn: string; +}; + +export function useSignErc20SwapDelegation() { + const { data, signTypedData, signTypedDataAsync, ...rest } = + useSignTypedData(); + const { mutate, ...insertRest } = useInsertDelegation(); + const [delegation, setDelegation] = useState(); + + async function signAndSaveDelegationAsync({ + chainId, + delegator, + delegate, + salt = SALT, + tokenOut = zeroAddress, + decimalsOut = 18, + amountOut = '0', + tokenIn = zeroAddress, + decimalsIn = 18, + amountIn = '0', + }: SignDelegationParams) { + const signature = await signTypedDataAsync({ + types: eip712DelegationTypes, + primaryType: 'Delegation', + domain: { + name: 'DelegationManager', + version: '1', + chainId: chainId, + verifyingContract: universalDeployments.DelegationManager, + }, + message: { + delegate: delegate, + delegator: delegator, + authority: ROOT_AUTHORITY, + salt: salt, + caveats: [ + { + enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, + terms: encodeERC20BalanceGteWrapEnforcerTerms({ + token: tokenIn, + amount: amountIn, + decimals: decimalsIn, + }), + }, + { + enforcer: universalDeployments.ERC20TransferAmountEnforcer, + terms: encodeEnforcerERC20TransferAmount({ + token: tokenOut, + amount: amountOut, + decimals: decimalsOut, + }), + }, + { + enforcer: universalDeployments.ExternalCallEnforcer, + terms: '0x', + }, + ], + }, + }); + + const _coreDelegation: Delegation = { + authority: ROOT_AUTHORITY, + delegate: delegate, + delegator: delegator, + salt, + signature, + caveats: [ + { + enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, + terms: encodeERC20BalanceGteWrapEnforcerTerms({ + token: tokenIn, + amount: amountIn, + decimals: decimalsIn, + }), + args: '0x', + }, + { + enforcer: universalDeployments.ERC20TransferAmountEnforcer, + terms: encodeEnforcerERC20TransferAmount({ + token: tokenOut, + amount: amountOut, + decimals: decimalsOut, + }), + args: '0x', + }, + { + enforcer: universalDeployments.ExternalCallEnforcer, + terms: '0x', + args: '0x', + }, + ], + }; + + const _delegation = { + hash: getDelegationHash(_coreDelegation), + chainId: chainId, + type: 'DebitAuthorization', + verifyingContract: universalDeployments.DelegationManager, + authorityDelegation: null, + ..._coreDelegation, + caveats: _coreDelegation.caveats.map((caveat) => ({ + ...caveat, + type: 'ERC20TransferAmount', + })), + } satisfies DelegationWithMetadata; + + setDelegation(_delegation); + mutate({ + ..._delegation, + salt: salt.toString(), + }); + } + + return { + delegation, + signAndSaveDelegationAsync, + data, + mutation: insertRest, + ...rest, + }; +} diff --git a/packages/universal-delegations-sdk/src/enforcers/erc20-balance-gte-wrap-enforcer.ts b/packages/universal-delegations-sdk/src/enforcers/erc20-balance-gte-wrap-enforcer.ts new file mode 100644 index 00000000..b3a322e2 --- /dev/null +++ b/packages/universal-delegations-sdk/src/enforcers/erc20-balance-gte-wrap-enforcer.ts @@ -0,0 +1,34 @@ +import { + type Address, + type Hex, + encodePacked, + hexToBigInt, + parseUnits, + sliceHex, +} from 'viem'; + +export function encodeERC20BalanceGteWrapEnforcerTerms(data: { + token: Address; + amount: string; + decimals: number; +}) { + return encodePacked( + ['address', 'uint256'], + [data.token, parseUnits(data.amount, data.decimals)], + ); +} + +export function decodeERC20BalanceGteWrapEnforcerTerms(data: Hex) { + // Addresses are 20 bytes, uint256 is 32 bytes + const addressSize = 20; + const uint256Size = 32; + + // Decode `token` (first 20 bytes) + const token = sliceHex(data, 0, addressSize) as Address; + + // Decode `amount` (next 32 bytes) + const amountHex = sliceHex(data, addressSize, addressSize + uint256Size); + const amount = hexToBigInt(amountHex); + + return [token, BigInt(amount)] as const; +} diff --git a/packages/universal-delegations-sdk/src/enforcers/external-call-enforcer.ts b/packages/universal-delegations-sdk/src/enforcers/external-call-enforcer.ts new file mode 100644 index 00000000..2a9ff9d1 --- /dev/null +++ b/packages/universal-delegations-sdk/src/enforcers/external-call-enforcer.ts @@ -0,0 +1,13 @@ +import { type Address, type Hex, encodePacked } from 'viem'; + +export type EncodeExternalHookEnforcerArgsParams = { + target: Address; + callData: Hex; +}; + +export function encodeExternalHookEnforcerArgs({ + target, + callData, +}: EncodeExternalHookEnforcerArgsParams) { + return encodePacked(['address', 'bytes'], [target, callData]); +} diff --git a/packages/universal-delegations-sdk/src/exports/index.ts b/packages/universal-delegations-sdk/src/exports/index.ts index 5c226d9d..76651c41 100644 --- a/packages/universal-delegations-sdk/src/exports/index.ts +++ b/packages/universal-delegations-sdk/src/exports/index.ts @@ -1,31 +1,29 @@ -export { - getDelegations, - useGetDelegations, -} from '../api/actions/get-delegations.js'; +export type { DelegationsApi } from 'api-delegations'; +export { useDelegationExecute } from '../actions/core/use-delegation-execute.js'; +export { useDelegationStatus } from '../actions/core/use-delegation-status.js'; +export { useDisableDelegation } from '../actions/core/use-disable-delegation.js'; +export { useEnableDelegation } from '../actions/core/use-enable-delegation.js'; +export { useErc20TransferAmountEnforcer } from '../actions/enforcers/use-erc20-transfer-amount-enforcer.js'; +export { useSignErc20SwapDelegation } from '../actions/use-sign-erc20-swap.js'; +export { useSignErc20TransferDelegation } from '../actions/use-sign-erc20-transfer.js'; export { getDelegation, useGetDelegation, } from '../api/actions/get-delegation.js'; +export { + getDelegations, + useGetDelegations, +} from '../api/actions/get-delegations.js'; export { insertDelegation, useInsertDelegation, } from '../api/actions/insert-delegation.js'; export { invalidateDelegation } from '../api/actions/invalidate-delegation.js'; export { - type DelegationsApiClient, DelegationsApiClientProvider, useDelegationsApiClient, + type DelegationsApiClient, } from '../api/client.js'; -export { - decodeEnforcerERC20TransferAmount, - encodeEnforcerERC20TransferAmount, -} from '../enforcers/enforcer-erc20-transfer-amount.js'; -export { useDelegationExecute } from '../actions/core/use-delegation-execute.js'; -export { useDelegationStatus } from '../actions/core/use-delegation-status.js'; -export { useDisableDelegation } from '../actions/core/use-disable-delegation.js'; -export { useEnableDelegation } from '../actions/core/use-enable-delegation.js'; -export { useErc20TransferAmountEnforcer } from '../actions/enforcers/use-erc20-transfer-amount-enforcer.js'; -export { useSignErc20TransferDelegation } from '../actions/use-sign-erc20-transfer.js'; export { eip712DelegationTypes } from '../delegation/eip712-delegation-type.js'; export { encodeDelegation } from '../delegation/encode-delegation.js'; export { @@ -33,6 +31,14 @@ export { getCaveatPacketHash, getDelegationHash, } from '../delegation/get-delegation-hash.js'; +export { + decodeEnforcerERC20TransferAmount, + encodeEnforcerERC20TransferAmount, +} from '../enforcers/enforcer-erc20-transfer-amount.js'; +export { + decodeERC20BalanceGteWrapEnforcerTerms, + encodeERC20BalanceGteWrapEnforcerTerms, +} from '../enforcers/erc20-balance-gte-wrap-enforcer.js'; +export { encodeExternalHookEnforcerArgs } from '../enforcers/external-call-enforcer.js'; export { encodeBatchExecution } from '../execution/encode-batch-execution.js'; export { encodeSingleExecution } from '../execution/encode-single-execution.js'; -export type { DelegationsApi } from 'api-delegations'; From e34d1754f96cd4273163b2bfc49a6a6c9bbc6c0a Mon Sep 17 00:00:00 2001 From: Vitor Date: Thu, 12 Dec 2024 10:49:53 -0300 Subject: [PATCH 04/10] chore: update deployment addresses --- packages/universal-data/src/deployments.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/universal-data/src/deployments.ts b/packages/universal-data/src/deployments.ts index f31ea4d6..e5cc206e 100644 --- a/packages/universal-data/src/deployments.ts +++ b/packages/universal-data/src/deployments.ts @@ -32,6 +32,6 @@ export const universalDeployments = { RedeemerEnforcer: '0xbD848E5861825754c809F5b813A72B50691A86A6', TimestampEnforcer: '0x675b4844E388e329354185cAcBC30E3F93456559', ValueLteEnforcer: '0x1f7EE6330cc76Bb26Cc490166CcAbf451234A578', - ERC20BalanceGteAfterAllEnforcer: '0x2AB6fed8C074D4Bf4668E46f78a97cCD1FC23686', - ExternalHookEnforcer: '0xF1dF0e6d2d6D307814A086cCdeBdcD1250C53df3', + ERC20BalanceGteAfterAllEnforcer: '0xCb9950cC1D78876BCf76bF0accAF3b092245A8B4', + ExternalHookEnforcer: '0xeE186Ed1b94700B8a92E3FEf4200dED7668E969A', } as const; From 1c3c14a07fc230eb20f0d5df7fba05922853f364 Mon Sep 17 00:00:00 2001 From: Vitor Date: Thu, 12 Dec 2024 14:41:28 -0300 Subject: [PATCH 05/10] fix: limit order redemption --- .../delegations/insert-delegation-db.ts | 12 +++++- .../src/processing/limit-order/index.ts | 13 +++--- .../src/processing/limit-order/utils.ts | 12 ++++++ .../api-delegations/src/routes/delegations.ts | 5 ++- .../src/components/forms/form-erc20-swap.tsx | 5 +-- .../src/actions/use-sign-erc20-swap.ts | 40 +++++++++---------- ...rnal-hook.ts => enforcer-external-call.ts} | 2 +- .../erc20-balance-gte-wrap-enforcer.ts | 14 +++---- .../src/enforcers/external-call-enforcer.ts | 13 ------ .../src/exports/index.ts | 3 +- 10 files changed, 62 insertions(+), 57 deletions(-) rename packages/universal-delegations-sdk/src/enforcers/{enforcer-external-hook.ts => enforcer-external-call.ts} (84%) delete mode 100644 packages/universal-delegations-sdk/src/enforcers/external-call-enforcer.ts diff --git a/apps/api-delegations/src/db/actions/delegations/insert-delegation-db.ts b/apps/api-delegations/src/db/actions/delegations/insert-delegation-db.ts index dc158b50..d2ce1789 100644 --- a/apps/api-delegations/src/db/actions/delegations/insert-delegation-db.ts +++ b/apps/api-delegations/src/db/actions/delegations/insert-delegation-db.ts @@ -16,7 +16,11 @@ export function insertDelegationDb({ }: InsertDelegationDbParams) { return db.transaction(async (tx) => { // Insert the delegation - await tx.insert(delegationsDb).values(delegation).returning(); + await tx + .insert(delegationsDb) + .values(delegation) + .returning() + .onConflictDoNothing(); if (caveats.length > 0) { const caveatsWithDelegationHash = caveats.map((caveat) => ({ @@ -25,7 +29,11 @@ export function insertDelegationDb({ })); // Insert the caveats - await tx.insert(caveatsDb).values(caveatsWithDelegationHash).returning(); + await tx + .insert(caveatsDb) + .values(caveatsWithDelegationHash) + .returning() + .onConflictDoNothing(); } }); } diff --git a/apps/api-delegations/src/processing/limit-order/index.ts b/apps/api-delegations/src/processing/limit-order/index.ts index c9ee2115..265ca419 100644 --- a/apps/api-delegations/src/processing/limit-order/index.ts +++ b/apps/api-delegations/src/processing/limit-order/index.ts @@ -2,6 +2,7 @@ import type { Delegation, DelegationExecution } from 'universal-types'; import { decodeEnforcerERC20TransferAmount, encodeDelegation, + encodeExternalCallEnforcerArgs, encodeSingleExecution, getErc20TransferAmountEnforcerFromDelegation, getExternalHookEnforcerFromDelegation, @@ -26,7 +27,6 @@ function getDepositAaveV3HookData({ }: { amount: bigint; delegator: Address; token: Address }): Hex { return encodeFunctionData({ abi: multicallAbi, - functionName: 'multicall', args: [ [ @@ -71,10 +71,13 @@ export async function processLimitOrderDelegation({ delegation.caveats[externalHookEnforcerIndex] = { ...externalHookEnforcer, // Update the args of the external hook enforcer to include the data for the Aave V3 deposit - args: getDepositAaveV3HookData({ - amount, - token, - delegator: delegation.delegator, + args: encodeExternalCallEnforcerArgs({ + target: universalDeployments.Multicall, + callData: getDepositAaveV3HookData({ + amount, + token, + delegator: delegation.delegator, + }), }), }; diff --git a/apps/api-delegations/src/processing/limit-order/utils.ts b/apps/api-delegations/src/processing/limit-order/utils.ts index 5c82c1bb..5fa0670d 100644 --- a/apps/api-delegations/src/processing/limit-order/utils.ts +++ b/apps/api-delegations/src/processing/limit-order/utils.ts @@ -138,3 +138,15 @@ export function encodeDelegation(delegation: Delegation): Hex { [[delegation]], ); } + +export type EncodeExternalHookArgsParams = { + target: Address; + callData: Hex; +}; + +export function encodeExternalCallEnforcerArgs({ + target, + callData, +}: EncodeExternalHookArgsParams) { + return encodePacked(['address', 'bytes'], [target, callData]); +} diff --git a/apps/api-delegations/src/routes/delegations.ts b/apps/api-delegations/src/routes/delegations.ts index 72ff2edb..def4e9ac 100644 --- a/apps/api-delegations/src/routes/delegations.ts +++ b/apps/api-delegations/src/routes/delegations.ts @@ -63,7 +63,10 @@ const delegationsRouter = new Hono() try { await Promise.all([ // Process any necessary delegation side effects - processDelegation(delegation), + processDelegation({ + chainId: delegation.chainId, + delegation, + }), // Save the delegation to the database insertDelegationDb(delegation), ]); diff --git a/apps/wallet/src/components/forms/form-erc20-swap.tsx b/apps/wallet/src/components/forms/form-erc20-swap.tsx index a5a7bff4..0acf4d75 100644 --- a/apps/wallet/src/components/forms/form-erc20-swap.tsx +++ b/apps/wallet/src/components/forms/form-erc20-swap.tsx @@ -12,7 +12,6 @@ import { useSignErc20SwapDelegation } from 'universal-delegations-sdk'; import type { TokenItem } from 'universal-types'; import type { Address } from 'viem'; import { useAccount, useSwitchChain } from 'wagmi'; -import { useWriteContracts } from 'wagmi/experimental'; import { z } from 'zod'; const formSchema = z.object({ @@ -40,9 +39,7 @@ type FormErc20SwapProps = { function FormErc20Swap({ defaultValues }: FormErc20SwapProps) { const { address } = useAccount(); const { switchChain, isPending: isPendingSwitchChain } = useSwitchChain(); - const { signAndSaveDelegationAsync, isSuccess } = - useSignErc20SwapDelegation(); - const { writeContracts } = useWriteContracts(); + const { signAndSaveDelegationAsync } = useSignErc20SwapDelegation(); const { isValidChain, chainId, defaultChain } = useIsValidChain(); diff --git a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts index a850dc08..3baa643f 100644 --- a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts +++ b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts @@ -8,7 +8,7 @@ import { useInsertDelegation } from '../api/actions/insert-delegation.js'; import { eip712DelegationTypes } from '../delegation/eip712-delegation-type.js'; import { getDelegationHash } from '../delegation/get-delegation-hash.js'; import { encodeEnforcerERC20TransferAmount } from '../enforcers/enforcer-erc20-transfer-amount.js'; -import { encodeERC20BalanceGteWrapEnforcerTerms } from '../enforcers/erc20-balance-gte-wrap-enforcer.js'; +// import { encodeERC20BalanceGteWrapEnforcerTerms } from '../enforcers/erc20-balance-gte-wrap-enforcer.js'; type SignDelegationParams = { chainId: number; @@ -37,9 +37,9 @@ export function useSignErc20SwapDelegation() { tokenOut = zeroAddress, decimalsOut = 18, amountOut = '0', - tokenIn = zeroAddress, - decimalsIn = 18, - amountIn = '0', + // tokenIn = zeroAddress, + // decimalsIn = 18, + // amountIn = '0', }: SignDelegationParams) { const signature = await signTypedDataAsync({ types: eip712DelegationTypes, @@ -56,14 +56,13 @@ export function useSignErc20SwapDelegation() { authority: ROOT_AUTHORITY, salt: salt, caveats: [ - { - enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, - terms: encodeERC20BalanceGteWrapEnforcerTerms({ - token: tokenIn, - amount: amountIn, - decimals: decimalsIn, - }), - }, + // { + // enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, + // terms: encodeERC20BalanceGteWrapEnforcerTerms({ + // token: tokenIn, + // amount: parseUnits(amountIn, decimalsIn), + // }), + // }, { enforcer: universalDeployments.ERC20TransferAmountEnforcer, terms: encodeEnforcerERC20TransferAmount({ @@ -87,15 +86,14 @@ export function useSignErc20SwapDelegation() { salt, signature, caveats: [ - { - enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, - terms: encodeERC20BalanceGteWrapEnforcerTerms({ - token: tokenIn, - amount: amountIn, - decimals: decimalsIn, - }), - args: '0x', - }, + // { + // enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, + // terms: encodeERC20BalanceGteWrapEnforcerTerms({ + // token: tokenIn, + // amount: parseUnits(amountIn, decimalsIn), + // }), + // args: '0x', + // }, { enforcer: universalDeployments.ERC20TransferAmountEnforcer, terms: encodeEnforcerERC20TransferAmount({ diff --git a/packages/universal-delegations-sdk/src/enforcers/enforcer-external-hook.ts b/packages/universal-delegations-sdk/src/enforcers/enforcer-external-call.ts similarity index 84% rename from packages/universal-delegations-sdk/src/enforcers/enforcer-external-hook.ts rename to packages/universal-delegations-sdk/src/enforcers/enforcer-external-call.ts index bdc75422..0bd83ea6 100644 --- a/packages/universal-delegations-sdk/src/enforcers/enforcer-external-hook.ts +++ b/packages/universal-delegations-sdk/src/enforcers/enforcer-external-call.ts @@ -5,7 +5,7 @@ export type EncodeExternalHookArgsParams = { callData: Hex; }; -export function encodeExternalHookArgs({ +export function encodeExternalCallEnforcerArgs({ target, callData, }: EncodeExternalHookArgsParams) { diff --git a/packages/universal-delegations-sdk/src/enforcers/erc20-balance-gte-wrap-enforcer.ts b/packages/universal-delegations-sdk/src/enforcers/erc20-balance-gte-wrap-enforcer.ts index b3a322e2..29141975 100644 --- a/packages/universal-delegations-sdk/src/enforcers/erc20-balance-gte-wrap-enforcer.ts +++ b/packages/universal-delegations-sdk/src/enforcers/erc20-balance-gte-wrap-enforcer.ts @@ -3,19 +3,17 @@ import { type Hex, encodePacked, hexToBigInt, - parseUnits, sliceHex, } from 'viem'; -export function encodeERC20BalanceGteWrapEnforcerTerms(data: { +export function encodeERC20BalanceGteWrapEnforcerTerms({ + amount, + token, +}: { + amount: bigint; token: Address; - amount: string; - decimals: number; }) { - return encodePacked( - ['address', 'uint256'], - [data.token, parseUnits(data.amount, data.decimals)], - ); + return encodePacked(['address', 'uint256'], [token, amount]); } export function decodeERC20BalanceGteWrapEnforcerTerms(data: Hex) { diff --git a/packages/universal-delegations-sdk/src/enforcers/external-call-enforcer.ts b/packages/universal-delegations-sdk/src/enforcers/external-call-enforcer.ts deleted file mode 100644 index 2a9ff9d1..00000000 --- a/packages/universal-delegations-sdk/src/enforcers/external-call-enforcer.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { type Address, type Hex, encodePacked } from 'viem'; - -export type EncodeExternalHookEnforcerArgsParams = { - target: Address; - callData: Hex; -}; - -export function encodeExternalHookEnforcerArgs({ - target, - callData, -}: EncodeExternalHookEnforcerArgsParams) { - return encodePacked(['address', 'bytes'], [target, callData]); -} diff --git a/packages/universal-delegations-sdk/src/exports/index.ts b/packages/universal-delegations-sdk/src/exports/index.ts index f3f096c2..3dfebecb 100644 --- a/packages/universal-delegations-sdk/src/exports/index.ts +++ b/packages/universal-delegations-sdk/src/exports/index.ts @@ -29,7 +29,7 @@ export { encodeEnforcerERC20TransferAmount, getErc20TransferAmountEnforcerFromDelegation, } from '../enforcers/enforcer-erc20-transfer-amount.js'; -export { encodeExternalHookArgs } from '../enforcers/enforcer-external-hook.js'; +export { encodeExternalCallEnforcerArgs } from '../enforcers/enforcer-external-call.js'; export { eip712DelegationTypes } from '../delegation/eip712-delegation-type.js'; export { encodeDelegation } from '../delegation/encode-delegation.js'; export { @@ -41,6 +41,5 @@ export { decodeERC20BalanceGteWrapEnforcerTerms, encodeERC20BalanceGteWrapEnforcerTerms, } from '../enforcers/erc20-balance-gte-wrap-enforcer.js'; -export { encodeExternalHookEnforcerArgs } from '../enforcers/external-call-enforcer.js'; export { encodeBatchExecution } from '../execution/encode-batch-execution.js'; export { encodeSingleExecution } from '../execution/encode-single-execution.js'; From 7587f98b08ff64f6ab8e3c9f0871b6f9757aebc1 Mon Sep 17 00:00:00 2001 From: Vitor Date: Thu, 12 Dec 2024 21:16:43 -0300 Subject: [PATCH 06/10] fix: withdraw and deposit actions --- .../src/processing/limit-order/get-actions.ts | 92 ++ .../src/processing/limit-order/index.ts | 76 +- .../limit-order/protocols/aave-v3.ts | 65 + .../limit-order/protocols/compound-v3.ts | 44 + .../limit-order/protocols/pool-together-v5.ts | 73 ++ .../limit-order/protocols/underlying-asset.ts | 30 + .../src/processing/limit-order/utils.ts | 46 + .../src/abis/compound-v3-abi.ts | 1003 ++++++++++++++++ .../src/abis/delegation-manager-abi.ts | 17 + ...rc20-balance-gte-after-all-enforcer-abi.ts | 25 +- .../src/abis/pool-together-v5-abi.ts | 1056 +++++++++++++++++ packages/universal-data/src/exports/index.ts | 3 + .../src/token-list/stablecoin-token-list.ts | 44 +- .../src/actions/use-sign-erc20-swap.ts | 50 +- 14 files changed, 2520 insertions(+), 104 deletions(-) create mode 100644 apps/api-delegations/src/processing/limit-order/get-actions.ts create mode 100644 apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts create mode 100644 apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts create mode 100644 apps/api-delegations/src/processing/limit-order/protocols/pool-together-v5.ts create mode 100644 apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts create mode 100644 packages/universal-data/src/abis/compound-v3-abi.ts create mode 100644 packages/universal-data/src/abis/pool-together-v5-abi.ts diff --git a/apps/api-delegations/src/processing/limit-order/get-actions.ts b/apps/api-delegations/src/processing/limit-order/get-actions.ts new file mode 100644 index 00000000..4c00a64b --- /dev/null +++ b/apps/api-delegations/src/processing/limit-order/get-actions.ts @@ -0,0 +1,92 @@ +import { stablecoinTokenList } from 'universal-data'; +import type { Address, Hex } from 'viem'; +import { + getDepositAaveV3HookData, + getWithdrawAaveV3HookData, +} from './protocols/aave-v3.js'; +import { + getDepositPoolTogetherV5HookData, + getWithdrawPoolTogetherV5HookData, +} from './protocols/pool-together-v5.js'; +import { getDepositUnderlyingAssetHookData } from './protocols/underlying-asset.js'; + +type HookActions = { + target: Address; + value: bigint; + callData: Hex; +}[]; + +type GetHookActionsParams = { + tokenIn: Address; + tokenOut: Address; + amountIn: bigint; + amountOut: bigint; + delegator: Address; +}; + +type GetHookActionsReturnType = { + withdrawActions: HookActions; + depositActions: HookActions; +}; + +export function getHookActions({ + tokenIn, + tokenOut, + amountIn, + amountOut, + delegator, +}: GetHookActionsParams): GetHookActionsReturnType { + let withdrawActions: HookActions = []; + let depositActions: HookActions = []; + + const tokenInData = stablecoinTokenList.tokens.find( + (token) => token.address.toLowerCase() === tokenIn.toLowerCase(), + ); + const tokenOutData = stablecoinTokenList.tokens.find( + (token) => token.address.toLowerCase() === tokenOut.toLowerCase(), + ); + + if (!tokenInData || !tokenOutData) { + throw new Error('Token not found'); + } + + // Withdraw actions + if (tokenOutData.extensions?.protocol === 'aave-v3') { + withdrawActions = getWithdrawAaveV3HookData({ + amountIn, + tokenIn, + }); + } else if (tokenOutData.extensions?.protocol === 'pool-together-v5') { + withdrawActions = getWithdrawPoolTogetherV5HookData({ + amountOut, + tokenOut, + }); + } + + // Deposit actions + if (tokenInData.extensions?.protocol === 'aave-v3') { + depositActions = getDepositAaveV3HookData({ + amountIn, + delegator, + tokenOut, + }); + } else if (tokenInData.extensions?.protocol === 'pool-together-v5') { + depositActions = getDepositPoolTogetherV5HookData({ + amountIn, + delegator, + tokenIn, + tokenOut, + }); + } else if (!tokenInData.extensions?.protocol) { + depositActions = getDepositUnderlyingAssetHookData({ + amountIn, + delegator, + tokenIn, + }); + } + + return { + withdrawActions, + depositActions, + }; +} diff --git a/apps/api-delegations/src/processing/limit-order/index.ts b/apps/api-delegations/src/processing/limit-order/index.ts index 265ca419..f70197ac 100644 --- a/apps/api-delegations/src/processing/limit-order/index.ts +++ b/apps/api-delegations/src/processing/limit-order/index.ts @@ -1,9 +1,11 @@ import type { Delegation, DelegationExecution } from 'universal-types'; import { + decodeERC20BalanceGteWrapEnforcerTerms, decodeEnforcerERC20TransferAmount, encodeDelegation, encodeExternalCallEnforcerArgs, encodeSingleExecution, + getERC20BalanceGteWrapEnforcerFromDelegation, getErc20TransferAmountEnforcerFromDelegation, getExternalHookEnforcerFromDelegation, } from './utils.js'; @@ -11,49 +13,12 @@ import { getResolverWalletClient } from '../../resolver/resolver-wallet-client.j import type { ValidChain } from 'universal-data'; import { SINGLE_EXECUTION_MODE, - aaveV3PoolAbi, delegationManagerAbi, + multicallAbi, universalDeployments, } from 'universal-data'; -import { encodeFunctionData, type Address, type Hex, erc20Abi } from 'viem'; -import { multicallAbi } from 'universal-data'; - -const AAVE_V3_POOL_BASE = '0xA238Dd80C259a72e81d7e4664a9801593F98d1c5'; - -function getDepositAaveV3HookData({ - amount, - delegator, - token, -}: { amount: bigint; delegator: Address; token: Address }): Hex { - return encodeFunctionData({ - abi: multicallAbi, - functionName: 'multicall', - args: [ - [ - // Approves the token to the Aave Pool - { - target: token, - value: 0n, - callData: encodeFunctionData({ - abi: erc20Abi, - functionName: 'approve', - args: [AAVE_V3_POOL_BASE, amount], - }), - }, - // Deposits the token to the Aave Pool on behalf of the delegator - { - target: AAVE_V3_POOL_BASE, - value: 0n, - callData: encodeFunctionData({ - abi: aaveV3PoolAbi, - functionName: 'supply', - args: [token, amount, delegator, 0], - }), - }, - ], - ], - }); -} +import { encodeFunctionData, erc20Abi } from 'viem'; +import { getHookActions } from './get-actions.js'; export async function processLimitOrderDelegation({ chainId, @@ -61,22 +26,35 @@ export async function processLimitOrderDelegation({ }: { chainId: ValidChain['id']; delegation: Delegation }) { const { erc20TransferAmountEnforcer } = getErc20TransferAmountEnforcerFromDelegation(delegation); - const { token, amount } = decodeEnforcerERC20TransferAmount( - erc20TransferAmountEnforcer.terms, - ); + const { token: tokenOut, amount: amountOut } = + decodeEnforcerERC20TransferAmount(erc20TransferAmountEnforcer.terms); + + const { erc20BalanceGteWrapEnforcer } = + getERC20BalanceGteWrapEnforcerFromDelegation(delegation); + + const { token: tokenIn, amount: amountIn } = + decodeERC20BalanceGteWrapEnforcerTerms(erc20BalanceGteWrapEnforcer.terms); const { externalHookEnforcer, index: externalHookEnforcerIndex } = getExternalHookEnforcerFromDelegation(delegation); + const { withdrawActions, depositActions } = getHookActions({ + amountIn, + amountOut, + delegator: delegation.delegator, + tokenIn, + tokenOut, + }); + delegation.caveats[externalHookEnforcerIndex] = { ...externalHookEnforcer, // Update the args of the external hook enforcer to include the data for the Aave V3 deposit args: encodeExternalCallEnforcerArgs({ target: universalDeployments.Multicall, - callData: getDepositAaveV3HookData({ - amount, - token, - delegator: delegation.delegator, + callData: encodeFunctionData({ + abi: multicallAbi, + functionName: 'multicall', + args: [[...withdrawActions, ...depositActions]], }), }), }; @@ -87,11 +65,11 @@ export async function processLimitOrderDelegation({ // Set the delegation execution to transfer the delegator tokens to the multicall contract const execution: DelegationExecution = { value: 0n, - target: token, + target: tokenOut, calldata: encodeFunctionData({ abi: erc20Abi, functionName: 'transfer', - args: [universalDeployments.Multicall, amount], + args: [universalDeployments.Multicall, amountOut], }), }; diff --git a/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts b/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts new file mode 100644 index 00000000..939d180c --- /dev/null +++ b/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts @@ -0,0 +1,65 @@ +import { encodeFunctionData, erc20Abi, type Address, type Hex } from 'viem'; +import { aaveV3PoolAbi, universalDeployments } from 'universal-data'; + +const AAVE_V3_POOL_BASE = '0xA238Dd80C259a72e81d7e4664a9801593F98d1c5'; + +type GetDepositAaveV3HookDataReturnType = { + target: Address; + value: bigint; + callData: Hex; +}[]; + +export function getDepositAaveV3HookData({ + amountIn, + delegator, + tokenOut, +}: { + amountIn: bigint; + delegator: Address; + tokenOut: Address; +}): GetDepositAaveV3HookDataReturnType { + return [ + // Approves the token to the Aave Pool + { + target: tokenOut, + value: 0n, + callData: encodeFunctionData({ + abi: erc20Abi, + functionName: 'approve', + args: [AAVE_V3_POOL_BASE, amountIn], + }), + }, + // Deposits the token to the Aave Pool on behalf of the delegator + { + target: AAVE_V3_POOL_BASE, + value: 0n, + callData: encodeFunctionData({ + abi: aaveV3PoolAbi, + functionName: 'supply', + args: [tokenOut, amountIn, delegator, 0], + }), + }, + ]; +} + +type GetWithdrawAaveV3HookDataReturnType = GetDepositAaveV3HookDataReturnType; +export function getWithdrawAaveV3HookData({ + amountIn, + tokenIn, +}: { + amountIn: bigint; + tokenIn: Address; +}): GetWithdrawAaveV3HookDataReturnType { + return [ + // Withdraws the token from the Aave Pool on behalf of the delegator + { + target: AAVE_V3_POOL_BASE, + value: 0n, + callData: encodeFunctionData({ + abi: aaveV3PoolAbi, + functionName: 'withdraw', + args: [tokenIn, amountIn, universalDeployments.Multicall], + }), + }, + ]; +} diff --git a/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts b/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts new file mode 100644 index 00000000..2fcf6bb0 --- /dev/null +++ b/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts @@ -0,0 +1,44 @@ +import { encodeFunctionData, erc20Abi, type Address, type Hex } from 'viem'; +import { multicallAbi } from 'universal-data'; +import { compoundV3Abi } from 'universal-data'; + +export function getDepositCompoundV3HookData({ + amountIn, + delegator, + tokenOut, + tokenIn, +}: { + amountIn: bigint; + delegator: Address; + tokenIn: Address; + tokenOut: Address; +}): Hex { + return encodeFunctionData({ + abi: multicallAbi, + functionName: 'multicall', + args: [ + [ + // Approves the token to the Compound Pool + { + target: tokenOut, + value: 0n, + callData: encodeFunctionData({ + abi: erc20Abi, + functionName: 'approve', + args: [tokenIn, amountIn], + }), + }, + // Deposits the token to the Compound Pool on behalf of the delegator + { + target: tokenIn, + value: 0n, + callData: encodeFunctionData({ + abi: compoundV3Abi, + functionName: 'supplyTo', + args: [delegator, tokenOut, amountIn], + }), + }, + ], + ], + }); +} diff --git a/apps/api-delegations/src/processing/limit-order/protocols/pool-together-v5.ts b/apps/api-delegations/src/processing/limit-order/protocols/pool-together-v5.ts new file mode 100644 index 00000000..60e6c2f6 --- /dev/null +++ b/apps/api-delegations/src/processing/limit-order/protocols/pool-together-v5.ts @@ -0,0 +1,73 @@ +import { encodeFunctionData, erc20Abi, type Address, type Hex } from 'viem'; +import { poolTogetherV5Abi, universalDeployments } from 'universal-data'; + +type GetDepositPoolTogetherV5HookDataReturnType = { + target: Address; + value: bigint; + callData: Hex; +}[]; + +export function getDepositPoolTogetherV5HookData({ + amountIn, + delegator, + tokenOut, + tokenIn, +}: { + amountIn: bigint; + delegator: Address; + tokenIn: Address; + tokenOut: Address; +}): GetDepositPoolTogetherV5HookDataReturnType { + return [ + // Approves the token to the Prize vault + { + target: tokenOut, + value: 0n, + callData: encodeFunctionData({ + abi: erc20Abi, + functionName: 'approve', + args: [tokenIn, amountIn], + }), + }, + // Deposits the token to the Prize vault on behalf of the delegator + { + target: tokenIn, + value: 0n, + callData: encodeFunctionData({ + abi: poolTogetherV5Abi, + functionName: 'deposit', + args: [amountIn, delegator], + }), + }, + ]; +} + +type GetWithdrawPoolTogetherV5HookDataReturnType = + GetDepositPoolTogetherV5HookDataReturnType; + +export function getWithdrawPoolTogetherV5HookData({ + amountOut, + + tokenOut, +}: { + amountOut: bigint; + + tokenOut: Address; +}): GetWithdrawPoolTogetherV5HookDataReturnType { + return [ + // Deposits the token to the Prize vault on behalf of the delegator + { + target: tokenOut, + value: 0n, + callData: encodeFunctionData({ + abi: poolTogetherV5Abi, + functionName: 'redeem', + args: [ + amountOut, + universalDeployments.Multicall, + universalDeployments.Multicall, + ], + }), + }, + ]; +} diff --git a/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts b/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts new file mode 100644 index 00000000..0420d617 --- /dev/null +++ b/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts @@ -0,0 +1,30 @@ +import { encodeFunctionData, erc20Abi, type Address, type Hex } from 'viem'; + +type GetDepositUnderlyingAssetHookDataReturnType = { + target: Address; + value: bigint; + callData: Hex; +}[]; + +export function getDepositUnderlyingAssetHookData({ + amountIn, + delegator, + tokenIn, +}: { + amountIn: bigint; + delegator: Address; + tokenIn: Address; +}): GetDepositUnderlyingAssetHookDataReturnType { + return [ + // Approves the token to the Aave Pool + { + target: tokenIn, + value: 0n, + callData: encodeFunctionData({ + abi: erc20Abi, + functionName: 'transfer', + args: [delegator, amountIn], + }), + }, + ]; +} diff --git a/apps/api-delegations/src/processing/limit-order/utils.ts b/apps/api-delegations/src/processing/limit-order/utils.ts index 5fa0670d..0710010b 100644 --- a/apps/api-delegations/src/processing/limit-order/utils.ts +++ b/apps/api-delegations/src/processing/limit-order/utils.ts @@ -62,6 +62,27 @@ export function getErc20TransferAmountEnforcerFromDelegation( return { erc20TransferAmountEnforcer, index }; } +export function getERC20BalanceGteWrapEnforcerFromDelegation( + delegation: Delegation, +) { + const index = delegation.caveats.findIndex( + ({ enforcer }) => + enforcer.toLowerCase() === + universalDeployments.ERC20BalanceGteWrapEnforcer.toLowerCase(), + ); + if (index === -1) { + throw NoEnforcerFoundError; + } + + const erc20BalanceGteWrapEnforcer = delegation.caveats[index]; + + if (!erc20BalanceGteWrapEnforcer) { + throw NoEnforcerFoundError; + } + + return { erc20BalanceGteWrapEnforcer, index }; +} + export function getExternalHookEnforcerFromDelegation(delegation: Delegation) { const index = delegation.caveats.findIndex( ({ enforcer }) => @@ -150,3 +171,28 @@ export function encodeExternalCallEnforcerArgs({ }: EncodeExternalHookArgsParams) { return encodePacked(['address', 'bytes'], [target, callData]); } + +export function encodeERC20BalanceGteWrapEnforcerTerms({ + amount, + token, +}: { + amount: bigint; + token: Address; +}) { + return encodePacked(['address', 'uint256'], [token, amount]); +} + +export function decodeERC20BalanceGteWrapEnforcerTerms(data: Hex) { + // Addresses are 20 bytes, uint256 is 32 bytes + const addressSize = 20; + const uint256Size = 32; + + // Decode `token` (first 20 bytes) + const token = sliceHex(data, 0, addressSize) as Address; + + // Decode `amount` (next 32 bytes) + const amountHex = sliceHex(data, addressSize, addressSize + uint256Size); + const amount = hexToBigInt(amountHex); + + return { token, amount }; +} diff --git a/packages/universal-data/src/abis/compound-v3-abi.ts b/packages/universal-data/src/abis/compound-v3-abi.ts new file mode 100644 index 00000000..ac292b66 --- /dev/null +++ b/packages/universal-data/src/abis/compound-v3-abi.ts @@ -0,0 +1,1003 @@ +export const compoundV3Abi = [ + { + inputs: [ + { + components: [ + { internalType: 'address', name: 'governor', type: 'address' }, + { internalType: 'address', name: 'pauseGuardian', type: 'address' }, + { internalType: 'address', name: 'baseToken', type: 'address' }, + { + internalType: 'address', + name: 'baseTokenPriceFeed', + type: 'address', + }, + { + internalType: 'address', + name: 'extensionDelegate', + type: 'address', + }, + { internalType: 'uint64', name: 'supplyKink', type: 'uint64' }, + { + internalType: 'uint64', + name: 'supplyPerYearInterestRateSlopeLow', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'supplyPerYearInterestRateSlopeHigh', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'supplyPerYearInterestRateBase', + type: 'uint64', + }, + { internalType: 'uint64', name: 'borrowKink', type: 'uint64' }, + { + internalType: 'uint64', + name: 'borrowPerYearInterestRateSlopeLow', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'borrowPerYearInterestRateSlopeHigh', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'borrowPerYearInterestRateBase', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'storeFrontPriceFactor', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'trackingIndexScale', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'baseTrackingSupplySpeed', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'baseTrackingBorrowSpeed', + type: 'uint64', + }, + { + internalType: 'uint104', + name: 'baseMinForRewards', + type: 'uint104', + }, + { internalType: 'uint104', name: 'baseBorrowMin', type: 'uint104' }, + { internalType: 'uint104', name: 'targetReserves', type: 'uint104' }, + { + components: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'priceFeed', type: 'address' }, + { internalType: 'uint8', name: 'decimals', type: 'uint8' }, + { + internalType: 'uint64', + name: 'borrowCollateralFactor', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'liquidateCollateralFactor', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'liquidationFactor', + type: 'uint64', + }, + { internalType: 'uint128', name: 'supplyCap', type: 'uint128' }, + ], + internalType: 'struct CometConfiguration.AssetConfig[]', + name: 'assetConfigs', + type: 'tuple[]', + }, + ], + internalType: 'struct CometConfiguration.Configuration', + name: 'config', + type: 'tuple', + }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { inputs: [], name: 'Absurd', type: 'error' }, + { inputs: [], name: 'AlreadyInitialized', type: 'error' }, + { inputs: [], name: 'BadAsset', type: 'error' }, + { inputs: [], name: 'BadDecimals', type: 'error' }, + { inputs: [], name: 'BadDiscount', type: 'error' }, + { inputs: [], name: 'BadMinimum', type: 'error' }, + { inputs: [], name: 'BadPrice', type: 'error' }, + { inputs: [], name: 'BorrowCFTooLarge', type: 'error' }, + { inputs: [], name: 'BorrowTooSmall', type: 'error' }, + { inputs: [], name: 'InsufficientReserves', type: 'error' }, + { inputs: [], name: 'InvalidInt104', type: 'error' }, + { inputs: [], name: 'InvalidInt256', type: 'error' }, + { inputs: [], name: 'InvalidUInt104', type: 'error' }, + { inputs: [], name: 'InvalidUInt128', type: 'error' }, + { inputs: [], name: 'InvalidUInt64', type: 'error' }, + { inputs: [], name: 'LiquidateCFTooLarge', type: 'error' }, + { inputs: [], name: 'NegativeNumber', type: 'error' }, + { inputs: [], name: 'NoSelfTransfer', type: 'error' }, + { inputs: [], name: 'NotCollateralized', type: 'error' }, + { inputs: [], name: 'NotForSale', type: 'error' }, + { inputs: [], name: 'NotLiquidatable', type: 'error' }, + { inputs: [], name: 'Paused', type: 'error' }, + { inputs: [], name: 'SupplyCapExceeded', type: 'error' }, + { inputs: [], name: 'TimestampTooLarge', type: 'error' }, + { inputs: [], name: 'TooManyAssets', type: 'error' }, + { inputs: [], name: 'TooMuchSlippage', type: 'error' }, + { inputs: [], name: 'TransferInFailed', type: 'error' }, + { inputs: [], name: 'TransferOutFailed', type: 'error' }, + { inputs: [], name: 'Unauthorized', type: 'error' }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'absorber', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'borrower', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'asset', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'collateralAbsorbed', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'usdValue', + type: 'uint256', + }, + ], + name: 'AbsorbCollateral', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'absorber', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'borrower', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'basePaidOut', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'usdValue', + type: 'uint256', + }, + ], + name: 'AbsorbDebt', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'buyer', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'asset', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'baseAmount', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'collateralAmount', + type: 'uint256', + }, + ], + name: 'BuyCollateral', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'bool', + name: 'supplyPaused', + type: 'bool', + }, + { + indexed: false, + internalType: 'bool', + name: 'transferPaused', + type: 'bool', + }, + { + indexed: false, + internalType: 'bool', + name: 'withdrawPaused', + type: 'bool', + }, + { + indexed: false, + internalType: 'bool', + name: 'absorbPaused', + type: 'bool', + }, + { indexed: false, internalType: 'bool', name: 'buyPaused', type: 'bool' }, + ], + name: 'PauseAction', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'dst', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Supply', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'dst', type: 'address' }, + { + indexed: true, + internalType: 'address', + name: 'asset', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'SupplyCollateral', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Transfer', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: true, + internalType: 'address', + name: 'asset', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'TransferCollateral', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'src', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Withdraw', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'src', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: true, + internalType: 'address', + name: 'asset', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'WithdrawCollateral', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'WithdrawReserves', + type: 'event', + }, + { stateMutability: 'payable', type: 'fallback' }, + { + inputs: [ + { internalType: 'address', name: 'absorber', type: 'address' }, + { internalType: 'address[]', name: 'accounts', type: 'address[]' }, + ], + name: 'absorb', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'accrueAccount', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'manager', type: 'address' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'approveThis', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'balanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'baseBorrowMin', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'baseMinForRewards', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'baseScale', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'baseToken', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'baseTokenPriceFeed', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'baseTrackingBorrowSpeed', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'baseTrackingSupplySpeed', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'borrowBalanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'borrowKink', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'borrowPerSecondInterestRateBase', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'borrowPerSecondInterestRateSlopeHigh', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'borrowPerSecondInterestRateSlopeLow', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'minAmount', type: 'uint256' }, + { internalType: 'uint256', name: 'baseAmount', type: 'uint256' }, + { internalType: 'address', name: 'recipient', type: 'address' }, + ], + name: 'buyCollateral', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'decimals', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'extensionDelegate', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint8', name: 'i', type: 'uint8' }], + name: 'getAssetInfo', + outputs: [ + { + components: [ + { internalType: 'uint8', name: 'offset', type: 'uint8' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'priceFeed', type: 'address' }, + { internalType: 'uint64', name: 'scale', type: 'uint64' }, + { + internalType: 'uint64', + name: 'borrowCollateralFactor', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'liquidateCollateralFactor', + type: 'uint64', + }, + { internalType: 'uint64', name: 'liquidationFactor', type: 'uint64' }, + { internalType: 'uint128', name: 'supplyCap', type: 'uint128' }, + ], + internalType: 'struct CometCore.AssetInfo', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getAssetInfoByAddress', + outputs: [ + { + components: [ + { internalType: 'uint8', name: 'offset', type: 'uint8' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'priceFeed', type: 'address' }, + { internalType: 'uint64', name: 'scale', type: 'uint64' }, + { + internalType: 'uint64', + name: 'borrowCollateralFactor', + type: 'uint64', + }, + { + internalType: 'uint64', + name: 'liquidateCollateralFactor', + type: 'uint64', + }, + { internalType: 'uint64', name: 'liquidationFactor', type: 'uint64' }, + { internalType: 'uint128', name: 'supplyCap', type: 'uint128' }, + ], + internalType: 'struct CometCore.AssetInfo', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'utilization', type: 'uint256' }], + name: 'getBorrowRate', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getCollateralReserves', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'priceFeed', type: 'address' }], + name: 'getPrice', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getReserves', + outputs: [{ internalType: 'int256', name: '', type: 'int256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'utilization', type: 'uint256' }], + name: 'getSupplyRate', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getUtilization', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'governor', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'manager', type: 'address' }, + ], + name: 'hasPermission', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'initializeStorage', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'isAbsorbPaused', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'address', name: '', type: 'address' }, + ], + name: 'isAllowed', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'isBorrowCollateralized', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'isBuyPaused', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'isLiquidatable', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'isSupplyPaused', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'isTransferPaused', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'isWithdrawPaused', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'liquidatorPoints', + outputs: [ + { internalType: 'uint32', name: 'numAbsorbs', type: 'uint32' }, + { internalType: 'uint64', name: 'numAbsorbed', type: 'uint64' }, + { internalType: 'uint128', name: 'approxSpend', type: 'uint128' }, + { internalType: 'uint32', name: '_reserved', type: 'uint32' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'numAssets', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'bool', name: 'supplyPaused', type: 'bool' }, + { internalType: 'bool', name: 'transferPaused', type: 'bool' }, + { internalType: 'bool', name: 'withdrawPaused', type: 'bool' }, + { internalType: 'bool', name: 'absorbPaused', type: 'bool' }, + { internalType: 'bool', name: 'buyPaused', type: 'bool' }, + ], + name: 'pause', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'pauseGuardian', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'baseAmount', type: 'uint256' }, + ], + name: 'quoteCollateral', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'storeFrontPriceFactor', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'supply', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'from', type: 'address' }, + { internalType: 'address', name: 'dst', type: 'address' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'supplyFrom', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'supplyKink', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'supplyPerSecondInterestRateBase', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'supplyPerSecondInterestRateSlopeHigh', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'supplyPerSecondInterestRateSlopeLow', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'dst', type: 'address' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'supplyTo', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'targetReserves', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalBorrow', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalSupply', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'totalsCollateral', + outputs: [ + { internalType: 'uint128', name: 'totalSupplyAsset', type: 'uint128' }, + { internalType: 'uint128', name: '_reserved', type: 'uint128' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'trackingIndexScale', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'dst', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'transfer', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'dst', type: 'address' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'transferAsset', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'src', type: 'address' }, + { internalType: 'address', name: 'dst', type: 'address' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'transferAssetFrom', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'src', type: 'address' }, + { internalType: 'address', name: 'dst', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'transferFrom', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'userBasic', + outputs: [ + { internalType: 'int104', name: 'principal', type: 'int104' }, + { internalType: 'uint64', name: 'baseTrackingIndex', type: 'uint64' }, + { internalType: 'uint64', name: 'baseTrackingAccrued', type: 'uint64' }, + { internalType: 'uint16', name: 'assetsIn', type: 'uint16' }, + { internalType: 'uint8', name: '_reserved', type: 'uint8' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'address', name: '', type: 'address' }, + ], + name: 'userCollateral', + outputs: [ + { internalType: 'uint128', name: 'balance', type: 'uint128' }, + { internalType: 'uint128', name: '_reserved', type: 'uint128' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'userNonce', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'withdraw', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'src', type: 'address' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'withdrawFrom', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'withdrawReserves', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'withdrawTo', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, +] as const; diff --git a/packages/universal-data/src/abis/delegation-manager-abi.ts b/packages/universal-data/src/abis/delegation-manager-abi.ts index 242fa7da..437462c4 100644 --- a/packages/universal-data/src/abis/delegation-manager-abi.ts +++ b/packages/universal-data/src/abis/delegation-manager-abi.ts @@ -603,6 +603,23 @@ export const delegationManagerAbi = [ name: 'ECDSAInvalidSignatureS', inputs: [{ name: 's', type: 'bytes32', internalType: 'bytes32' }], }, + { + type: 'error', + name: 'BalanceNotGreaterOrEqualThan', + inputs: [ + { name: 'balance', type: 'uint256', internalType: 'uint256' }, + { name: 'expected', type: 'uint256', internalType: 'uint256' }, + ], + }, + { type: 'error', name: 'EnforcerIsLocked', inputs: [] }, + { + type: 'error', + name: 'InvalidTermsLength', + inputs: [ + { name: 'length', type: 'uint256', internalType: 'uint256' }, + { name: 'expected', type: 'uint256', internalType: 'uint256' }, + ], + }, { type: 'error', name: 'EmptySignature', inputs: [] }, { type: 'error', name: 'EnforcedPause', inputs: [] }, { type: 'error', name: 'ExpectedPause', inputs: [] }, diff --git a/packages/universal-data/src/abis/erc20-balance-gte-after-all-enforcer-abi.ts b/packages/universal-data/src/abis/erc20-balance-gte-after-all-enforcer-abi.ts index f60dedfe..6ea1282b 100644 --- a/packages/universal-data/src/abis/erc20-balance-gte-after-all-enforcer-abi.ts +++ b/packages/universal-data/src/abis/erc20-balance-gte-after-all-enforcer-abi.ts @@ -1,4 +1,4 @@ -export const erc20TransferAmountEnforcerAbi = [ +export const erc20BalanceGteWrapEnforcerAbi = [ { type: 'function', name: 'afterAllHook', @@ -40,12 +40,12 @@ export const erc20TransferAmountEnforcerAbi = [ type: 'function', name: 'beforeAllHook', inputs: [ - { name: '', type: 'bytes', internalType: 'bytes' }, + { name: '_terms', type: 'bytes', internalType: 'bytes' }, { name: '', type: 'bytes', internalType: 'bytes' }, { name: '', type: 'bytes32', internalType: 'ModeCode' }, { name: '', type: 'bytes', internalType: 'bytes' }, - { name: '', type: 'bytes32', internalType: 'bytes32' }, - { name: '', type: 'address', internalType: 'address' }, + { name: '_delegationHash', type: 'bytes32', internalType: 'bytes32' }, + { name: '_delegator', type: 'address', internalType: 'address' }, { name: '', type: 'address', internalType: 'address' }, ], outputs: [], @@ -94,4 +94,21 @@ export const erc20TransferAmountEnforcerAbi = [ outputs: [{ name: 'lock', type: 'bool', internalType: 'bool' }], stateMutability: 'view', }, + { + type: 'error', + name: 'BalanceNotGreaterOrEqualThan', + inputs: [ + { name: 'balance', type: 'uint256', internalType: 'uint256' }, + { name: 'expected', type: 'uint256', internalType: 'uint256' }, + ], + }, + { type: 'error', name: 'EnforcerIsLocked', inputs: [] }, + { + type: 'error', + name: 'InvalidTermsLength', + inputs: [ + { name: 'length', type: 'uint256', internalType: 'uint256' }, + { name: 'expected', type: 'uint256', internalType: 'uint256' }, + ], + }, ] as const; diff --git a/packages/universal-data/src/abis/pool-together-v5-abi.ts b/packages/universal-data/src/abis/pool-together-v5-abi.ts new file mode 100644 index 00000000..6d7aef4c --- /dev/null +++ b/packages/universal-data/src/abis/pool-together-v5-abi.ts @@ -0,0 +1,1056 @@ +export const poolTogetherV5Abi = [ + { + inputs: [ + { internalType: 'string', name: 'name_', type: 'string' }, + { internalType: 'string', name: 'symbol_', type: 'string' }, + { + internalType: 'contract IERC4626', + name: 'yieldVault_', + type: 'address', + }, + { + internalType: 'contract PrizePool', + name: 'prizePool_', + type: 'address', + }, + { internalType: 'address', name: 'claimer_', type: 'address' }, + { internalType: 'address', name: 'yieldFeeRecipient_', type: 'address' }, + { internalType: 'uint32', name: 'yieldFeePercentage_', type: 'uint32' }, + { internalType: 'uint256', name: 'yieldBuffer_', type: 'uint256' }, + { internalType: 'address', name: 'owner_', type: 'address' }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { inputs: [], name: 'BurnZeroShares', type: 'error' }, + { + inputs: [ + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'claimer', type: 'address' }, + ], + name: 'CallerNotClaimer', + type: 'error', + }, + { + inputs: [ + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'liquidationPair', type: 'address' }, + ], + name: 'CallerNotLP', + type: 'error', + }, + { + inputs: [ + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'yieldFeeRecipient', type: 'address' }, + ], + name: 'CallerNotYieldFeeRecipient', + type: 'error', + }, + { inputs: [], name: 'ClaimRecipientZeroAddress', type: 'error' }, + { inputs: [], name: 'ClaimerZeroAddress', type: 'error' }, + { inputs: [], name: 'DepositZeroAssets', type: 'error' }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'FailedToGetAssetDecimals', + type: 'error', + }, + { inputs: [], name: 'InvalidShortString', type: 'error' }, + { inputs: [], name: 'LPZeroAddress', type: 'error' }, + { inputs: [], name: 'LiquidationAmountOutZero', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'totalToWithdraw', type: 'uint256' }, + { internalType: 'uint256', name: 'availableYield', type: 'uint256' }, + ], + name: 'LiquidationExceedsAvailable', + type: 'error', + }, + { + inputs: [ + { internalType: 'address', name: 'tokenIn', type: 'address' }, + { internalType: 'address', name: 'prizeToken', type: 'address' }, + ], + name: 'LiquidationTokenInNotPrizeToken', + type: 'error', + }, + { + inputs: [{ internalType: 'address', name: 'tokenOut', type: 'address' }], + name: 'LiquidationTokenOutNotSupported', + type: 'error', + }, + { + inputs: [ + { internalType: 'uint256', name: 'totalAssets', type: 'uint256' }, + { internalType: 'uint256', name: 'totalSupply', type: 'uint256' }, + ], + name: 'LossyDeposit', + type: 'error', + }, + { + inputs: [ + { internalType: 'uint256', name: 'shares', type: 'uint256' }, + { internalType: 'uint256', name: 'maxShares', type: 'uint256' }, + ], + name: 'MaxSharesExceeded', + type: 'error', + }, + { + inputs: [ + { internalType: 'uint256', name: 'assets', type: 'uint256' }, + { internalType: 'uint256', name: 'minAssets', type: 'uint256' }, + ], + name: 'MinAssetsNotReached', + type: 'error', + }, + { + inputs: [{ internalType: 'uint256', name: 'excess', type: 'uint256' }], + name: 'MintLimitExceeded', + type: 'error', + }, + { inputs: [], name: 'MintZeroShares', type: 'error' }, + { inputs: [], name: 'OwnerZeroAddress', type: 'error' }, + { + inputs: [ + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'owner', type: 'address' }, + ], + name: 'PermitCallerNotOwner', + type: 'error', + }, + { inputs: [], name: 'PrizePoolZeroAddress', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'returnDataSize', type: 'uint256' }, + { internalType: 'uint256', name: 'hookDataLimit', type: 'uint256' }, + ], + name: 'ReturnDataOverLimit', + type: 'error', + }, + { + inputs: [ + { internalType: 'uint256', name: 'shares', type: 'uint256' }, + { internalType: 'uint256', name: 'yieldFeeBalance', type: 'uint256' }, + ], + name: 'SharesExceedsYieldFeeBalance', + type: 'error', + }, + { + inputs: [{ internalType: 'string', name: 'str', type: 'string' }], + name: 'StringTooLong', + type: 'error', + }, + { inputs: [], name: 'TwabControllerZeroAddress', type: 'error' }, + { inputs: [], name: 'WithdrawZeroAssets', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'yieldFeePercentage', type: 'uint256' }, + { + internalType: 'uint256', + name: 'maxYieldFeePercentage', + type: 'uint256', + }, + ], + name: 'YieldFeePercentageExceedsMax', + type: 'error', + }, + { inputs: [], name: 'YieldVaultZeroAddress', type: 'error' }, + { inputs: [], name: 'ZeroTotalAssets', type: 'error' }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Approval', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'recipient', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'shares', + type: 'uint256', + }, + ], + name: 'ClaimYieldFeeShares', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'claimer', + type: 'address', + }, + ], + name: 'ClaimerSet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'assets', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'shares', + type: 'uint256', + }, + ], + name: 'Deposit', + type: 'event', + }, + { anonymous: false, inputs: [], name: 'EIP712DomainChanged', type: 'event' }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'tokenOut', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'liquidationPair', + type: 'address', + }, + ], + name: 'LiquidationPairSet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'pendingOwner', + type: 'address', + }, + ], + name: 'OwnershipOffered', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'previousOwner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'newOwner', + type: 'address', + }, + ], + name: 'OwnershipTransferred', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + components: [ + { internalType: 'bool', name: 'useBeforeClaimPrize', type: 'bool' }, + { internalType: 'bool', name: 'useAfterClaimPrize', type: 'bool' }, + { + internalType: 'contract IPrizeHooks', + name: 'implementation', + type: 'address', + }, + ], + indexed: false, + internalType: 'struct PrizeHooks', + name: 'hooks', + type: 'tuple', + }, + ], + name: 'SetHooks', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Transfer', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'liquidationPair', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'tokenOut', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'recipient', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amountOut', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'yieldFee', + type: 'uint256', + }, + ], + name: 'TransferYieldOut', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'receiver', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'assets', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'shares', + type: 'uint256', + }, + ], + name: 'Withdraw', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'uint256', + name: 'yieldFeePercentage', + type: 'uint256', + }, + ], + name: 'YieldFeePercentageSet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'yieldFeeRecipient', + type: 'address', + }, + ], + name: 'YieldFeeRecipientSet', + type: 'event', + }, + { + inputs: [], + name: 'DOMAIN_SEPARATOR', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'FEE_PRECISION', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'HOOK_GAS', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'HOOK_RETURN_DATA_LIMIT', + outputs: [{ internalType: 'uint16', name: '', type: 'uint16' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MAX_YIELD_FEE', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'spender', type: 'address' }, + ], + name: 'allowance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'spender', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'approve', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'asset', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'availableYieldBalance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_account', type: 'address' }], + name: 'balanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'claimOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_winner', type: 'address' }, + { internalType: 'uint8', name: '_tier', type: 'uint8' }, + { internalType: 'uint32', name: '_prizeIndex', type: 'uint32' }, + { internalType: 'uint96', name: '_reward', type: 'uint96' }, + { internalType: 'address', name: '_rewardRecipient', type: 'address' }, + ], + name: 'claimPrize', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_shares', type: 'uint256' }], + name: 'claimYieldFeeShares', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'claimer', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_shares', type: 'uint256' }], + name: 'convertToAssets', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_assets', type: 'uint256' }], + name: 'convertToShares', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'currentYieldBuffer', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'decimals', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'spender', type: 'address' }, + { internalType: 'uint256', name: 'subtractedValue', type: 'uint256' }, + ], + name: 'decreaseAllowance', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: '_assets', type: 'uint256' }, + { internalType: 'address', name: '_receiver', type: 'address' }, + ], + name: 'deposit', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: '_assets', type: 'uint256' }, + { internalType: 'address', name: '_owner', type: 'address' }, + { 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: 'depositWithPermit', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'eip712Domain', + outputs: [ + { internalType: 'bytes1', name: 'fields', type: 'bytes1' }, + { internalType: 'string', name: 'name', type: 'string' }, + { internalType: 'string', name: 'version', type: 'string' }, + { internalType: 'uint256', name: 'chainId', type: 'uint256' }, + { internalType: 'address', name: 'verifyingContract', type: 'address' }, + { internalType: 'bytes32', name: 'salt', type: 'bytes32' }, + { internalType: 'uint256[]', name: 'extensions', type: 'uint256[]' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'getHooks', + outputs: [ + { + components: [ + { internalType: 'bool', name: 'useBeforeClaimPrize', type: 'bool' }, + { internalType: 'bool', name: 'useAfterClaimPrize', type: 'bool' }, + { + internalType: 'contract IPrizeHooks', + name: 'implementation', + type: 'address', + }, + ], + internalType: 'struct PrizeHooks', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'spender', type: 'address' }, + { internalType: 'uint256', name: 'addedValue', type: 'uint256' }, + ], + name: 'increaseAllowance', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_tokenOut', type: 'address' }, + { internalType: 'address', name: '_liquidationPair', type: 'address' }, + ], + name: 'isLiquidationPair', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_tokenOut', type: 'address' }], + name: 'liquidatableBalanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'liquidationPair', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'maxDeposit', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_owner', type: 'address' }], + name: 'maxMint', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_owner', type: 'address' }], + name: 'maxRedeem', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_owner', type: 'address' }], + name: 'maxWithdraw', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: '_shares', type: 'uint256' }, + { internalType: 'address', name: '_receiver', type: 'address' }, + ], + name: 'mint', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'name', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'owner', type: 'address' }], + name: 'nonces', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'owner', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'pendingOwner', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'spender', type: 'address' }, + { internalType: 'uint256', name: 'value', 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: 'permit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_assets', type: 'uint256' }], + name: 'previewDeposit', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_shares', type: 'uint256' }], + name: 'previewMint', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_shares', type: 'uint256' }], + name: 'previewRedeem', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_assets', type: 'uint256' }], + name: 'previewWithdraw', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'prizePool', + outputs: [ + { internalType: 'contract PrizePool', name: '', type: 'address' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: '_shares', type: 'uint256' }, + { internalType: 'address', name: '_receiver', type: 'address' }, + { internalType: 'address', name: '_owner', type: 'address' }, + { internalType: 'uint256', name: '_minAssets', type: 'uint256' }, + ], + name: 'redeem', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: '_shares', type: 'uint256' }, + { internalType: 'address', name: '_receiver', type: 'address' }, + { internalType: 'address', name: '_owner', type: 'address' }, + ], + name: 'redeem', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'renounceOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_claimer', type: 'address' }], + name: 'setClaimer', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + components: [ + { internalType: 'bool', name: 'useBeforeClaimPrize', type: 'bool' }, + { internalType: 'bool', name: 'useAfterClaimPrize', type: 'bool' }, + { + internalType: 'contract IPrizeHooks', + name: 'implementation', + type: 'address', + }, + ], + internalType: 'struct PrizeHooks', + name: 'hooks', + type: 'tuple', + }, + ], + name: 'setHooks', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_liquidationPair', type: 'address' }, + ], + name: 'setLiquidationPair', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint32', name: '_yieldFeePercentage', type: 'uint32' }, + ], + name: 'setYieldFeePercentage', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_yieldFeeRecipient', type: 'address' }, + ], + name: 'setYieldFeeRecipient', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'symbol', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'targetOf', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalAssets', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalDebt', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalPreciseAssets', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalSupply', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalYieldBalance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'transfer', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'from', type: 'address' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'transferFrom', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_newOwner', type: 'address' }], + name: 'transferOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'address', name: '_receiver', type: 'address' }, + { internalType: 'address', name: '_tokenOut', type: 'address' }, + { internalType: 'uint256', name: '_amountOut', type: 'uint256' }, + ], + name: 'transferTokensOut', + outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'twabController', + outputs: [ + { internalType: 'contract TwabController', name: '', type: 'address' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_tokenIn', type: 'address' }, + { internalType: 'uint256', name: '_amountIn', type: 'uint256' }, + { internalType: 'bytes', name: '', type: 'bytes' }, + ], + name: 'verifyTokensIn', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: '_assets', type: 'uint256' }, + { internalType: 'address', name: '_receiver', type: 'address' }, + { internalType: 'address', name: '_owner', type: 'address' }, + { internalType: 'uint256', name: '_maxShares', type: 'uint256' }, + ], + name: 'withdraw', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: '_assets', type: 'uint256' }, + { internalType: 'address', name: '_receiver', type: 'address' }, + { internalType: 'address', name: '_owner', type: 'address' }, + ], + name: 'withdraw', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'yieldBuffer', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'yieldFeeBalance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'yieldFeePercentage', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'yieldFeeRecipient', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'yieldVault', + outputs: [{ internalType: 'contract IERC4626', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, +] as const; diff --git a/packages/universal-data/src/exports/index.ts b/packages/universal-data/src/exports/index.ts index 9c134480..26e1e917 100644 --- a/packages/universal-data/src/exports/index.ts +++ b/packages/universal-data/src/exports/index.ts @@ -1,4 +1,7 @@ export { aaveV3PoolAbi } from '../abis/aave-v3-pool-abi.js'; +export { compoundV3Abi } from '../abis/compound-v3-abi.js'; +export { poolTogetherV5Abi } from '../abis/pool-together-v5-abi.js'; +export { erc20BalanceGteWrapEnforcerAbi } from '../abis/erc20-balance-gte-after-all-enforcer-abi.js'; export { multicallAbi } from '../abis/multicall-abi.js'; export { delegationManagerAbi } from '../abis/delegation-manager-abi.js'; export { erc20TransferAmountEnforcerAbi } from '../abis/erc20-transfer-amount-enforcer-abi.js'; diff --git a/packages/universal-data/src/token-list/stablecoin-token-list.ts b/packages/universal-data/src/token-list/stablecoin-token-list.ts index ff983048..7dd84964 100644 --- a/packages/universal-data/src/token-list/stablecoin-token-list.ts +++ b/packages/universal-data/src/token-list/stablecoin-token-list.ts @@ -34,6 +34,9 @@ export const stablecoinTokenList: TokenList = { logoURI: 'https://app.cabana.fi/icons/przUSDC.svg', address: '0x7f5C2b379b88499aC2B997Db583f8079503f25b9', decimals: 6, + extensions: { + protocol: 'pool-together-v5', + }, }, { chainId: 8453, @@ -43,37 +46,20 @@ export const stablecoinTokenList: TokenList = { 'https://assets.coingecko.com/coins/images/14318/standard/aUSDC.e260d492.png?1696514006', address: '0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB', decimals: 6, - }, - { - name: 'Dai Stablecoin', - address: '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', - symbol: 'DAI', - decimals: 18, - chainId: 8453, - logoURI: 'https://ethereum-optimism.github.io/data/DAI/logo.svg', extensions: { - bridgeInfo: { - '1': { - tokenAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - }, - }, - }, - }, - { - chainId: 8453, - name: 'Liquity USD', - symbol: 'LUSD', - logoURI: - 'https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327', - address: '0x368181499736d0c0CC614DBB145E2EC1AC86b8c6', - decimals: 18, - extensions: { - bridgeInfo: { - '1': { - tokenAddress: '0x5f98805A4E8be255a32880FDeC7F6728C6568bA0', - }, - }, + protocol: 'aave-v3', }, }, + // { + // chainId: 8453, + // name: 'Compound USDC', + // symbol: 'cUSDCv3', + // logoURI: 'https://ethereum-optimism.github.io/data/USDC/logo.png', + // address: '0xb125e6687d4313864e53df431d5425969c15eb2f', + // decimals: 6, + // extensions: { + // protocol: 'compound-v3', + // }, + // }, ], }; diff --git a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts index 3baa643f..22633c58 100644 --- a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts +++ b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts @@ -2,12 +2,18 @@ import { useState } from 'react'; import { ROOT_AUTHORITY, SALT, universalDeployments } from 'universal-data'; import type { Delegation, DelegationWithMetadata } from 'universal-types'; -import { type Address, zeroAddress } from 'viem'; +import { + type Address, + parseUnits, + // , + // parseUnits +} from 'viem'; import { useSignTypedData } from 'wagmi'; import { useInsertDelegation } from '../api/actions/insert-delegation.js'; import { eip712DelegationTypes } from '../delegation/eip712-delegation-type.js'; import { getDelegationHash } from '../delegation/get-delegation-hash.js'; import { encodeEnforcerERC20TransferAmount } from '../enforcers/enforcer-erc20-transfer-amount.js'; +import { encodeERC20BalanceGteWrapEnforcerTerms } from '../enforcers/erc20-balance-gte-wrap-enforcer.js'; // import { encodeERC20BalanceGteWrapEnforcerTerms } from '../enforcers/erc20-balance-gte-wrap-enforcer.js'; type SignDelegationParams = { @@ -34,12 +40,12 @@ export function useSignErc20SwapDelegation() { delegator, delegate, salt = SALT, - tokenOut = zeroAddress, - decimalsOut = 18, - amountOut = '0', - // tokenIn = zeroAddress, - // decimalsIn = 18, - // amountIn = '0', + tokenOut, + decimalsOut, + amountOut, + tokenIn, + decimalsIn, + amountIn, }: SignDelegationParams) { const signature = await signTypedDataAsync({ types: eip712DelegationTypes, @@ -56,13 +62,13 @@ export function useSignErc20SwapDelegation() { authority: ROOT_AUTHORITY, salt: salt, caveats: [ - // { - // enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, - // terms: encodeERC20BalanceGteWrapEnforcerTerms({ - // token: tokenIn, - // amount: parseUnits(amountIn, decimalsIn), - // }), - // }, + { + enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, + terms: encodeERC20BalanceGteWrapEnforcerTerms({ + token: tokenIn, + amount: parseUnits(amountIn, decimalsIn), + }), + }, { enforcer: universalDeployments.ERC20TransferAmountEnforcer, terms: encodeEnforcerERC20TransferAmount({ @@ -86,14 +92,14 @@ export function useSignErc20SwapDelegation() { salt, signature, caveats: [ - // { - // enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, - // terms: encodeERC20BalanceGteWrapEnforcerTerms({ - // token: tokenIn, - // amount: parseUnits(amountIn, decimalsIn), - // }), - // args: '0x', - // }, + { + enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, + terms: encodeERC20BalanceGteWrapEnforcerTerms({ + token: tokenIn, + amount: parseUnits(amountIn, decimalsIn), + }), + args: '0x', + }, { enforcer: universalDeployments.ERC20TransferAmountEnforcer, terms: encodeEnforcerERC20TransferAmount({ From 480c261564eed7755c30eb86d760d66c503c8748 Mon Sep 17 00:00:00 2001 From: Kames Geraghty Date: Thu, 12 Dec 2024 17:05:19 -0800 Subject: [PATCH 07/10] Feat: Swap Page UI (#65) * feat: swap page * feat: mobile --- apps/wallet/app/(site)/finance/swap/page.tsx | 104 +++++++++++++- apps/wallet/app/globals.css | 5 +- .../fields/erc20-select-and-amount.tsx | 10 +- .../src/components/forms/form-erc20-swap.tsx | 13 +- .../onchain/account-explorer-link.tsx | 2 +- .../onchain/etherscan-address-link.tsx | 31 ++++ .../src/components/views/assets-list-view.tsx | 134 ++++++++++++++++++ .../src/token-list/stablecoin-token-list.ts | 65 --------- .../src/token-list/stablecoin-token-list.tsx | 87 ++++++++++++ 9 files changed, 376 insertions(+), 75 deletions(-) create mode 100644 apps/wallet/src/components/onchain/etherscan-address-link.tsx create mode 100644 apps/wallet/src/components/views/assets-list-view.tsx delete mode 100644 packages/universal-data/src/token-list/stablecoin-token-list.ts create mode 100644 packages/universal-data/src/token-list/stablecoin-token-list.tsx diff --git a/apps/wallet/app/(site)/finance/swap/page.tsx b/apps/wallet/app/(site)/finance/swap/page.tsx index 0f18169b..79d0eeaa 100644 --- a/apps/wallet/app/(site)/finance/swap/page.tsx +++ b/apps/wallet/app/(site)/finance/swap/page.tsx @@ -1,12 +1,110 @@ 'use client'; import { FormErc20Swap } from '@/components/forms/form-erc20-swap'; +import { Badge } from '@/components/ui/badge'; +import { AssetsListView } from '@/components/views/assets-list-view'; +import { cn } from '@/lib/utils'; +import { ArrowLeftFromLine, ArrowRightFromLine, Coins } from 'lucide-react'; +import Image from 'next/image'; +import { useState } from 'react'; export default function FinanceSwapPage() { + const [isMinimized, setIsMinimized] = useState(false); + return ( <> -
-
- +
+
+ +
+
+ +
+
diff --git a/apps/wallet/app/globals.css b/apps/wallet/app/globals.css index 03cd49c5..cfa183e6 100644 --- a/apps/wallet/app/globals.css +++ b/apps/wallet/app/globals.css @@ -156,8 +156,9 @@ @apply mb-3; } - .content a { - @apply text-blue-600 dark:text-blue-300 font-bold; + .content a, + .link { + @apply text-blue-600 hover:text-blue-700 dark:text-blue-300; } .smart-wallet-connect { diff --git a/apps/wallet/src/components/fields/erc20-select-and-amount.tsx b/apps/wallet/src/components/fields/erc20-select-and-amount.tsx index cc8d26af..08f6af15 100644 --- a/apps/wallet/src/components/fields/erc20-select-and-amount.tsx +++ b/apps/wallet/src/components/fields/erc20-select-and-amount.tsx @@ -14,6 +14,8 @@ interface Erc20SelectAndAmount { amountName?: string; tokenName?: string; disabled?: boolean; + amountDisabled?: boolean; + tokenSelectorDisabled?: boolean; setMaxAmount?: (value: string) => void; } @@ -23,6 +25,8 @@ export function Erc20SelectAndAmount({ label = 'Asset', amountName = 'amount', tokenName = 'token', + amountDisabled, + tokenSelectorDisabled, setMaxAmount, }: Erc20SelectAndAmount) { const { control } = useFormContext(); @@ -38,7 +42,7 @@ export function Erc20SelectAndAmount({ ( + render={({ field }) => ( >({ resolver: zodResolver(formSchema), defaultValues: { @@ -59,6 +59,16 @@ function FormErc20Swap({ defaultValues }: FormErc20SwapProps) { }, }); + const formValues = form.watch(); + + useEffect(() => { + if (formValues.tokenOut && formValues.tokenIn && formValues.amountOut) { + form.setValue('amountIn', formValues.amountOut); + } else { + form.setValue('amountIn', undefined); + } + }, [form, formValues.amountOut, formValues.tokenOut, formValues.tokenIn]); + async function onSubmit(data: z.infer) { if (!isValidChain) { switchChain({ @@ -103,6 +113,7 @@ function FormErc20Swap({ defaultValues }: FormErc20SwapProps) { amountName="amountIn" tokenName="tokenIn" tokenList={defaultTokenList} + amountDisabled={true} /> {address && isValidChain && ( diff --git a/apps/wallet/src/components/onchain/account-explorer-link.tsx b/apps/wallet/src/components/onchain/account-explorer-link.tsx index 9979a718..663ff5f6 100644 --- a/apps/wallet/src/components/onchain/account-explorer-link.tsx +++ b/apps/wallet/src/components/onchain/account-explorer-link.tsx @@ -6,7 +6,7 @@ import { LinkComponent } from '../ui/link-component'; interface AccountExplorerLinkAddressProps extends Omit, 'children'> { - address?: AddressType; + address?: AddressType | string; chain?: Chain; } diff --git a/apps/wallet/src/components/onchain/etherscan-address-link.tsx b/apps/wallet/src/components/onchain/etherscan-address-link.tsx new file mode 100644 index 00000000..625764f2 --- /dev/null +++ b/apps/wallet/src/components/onchain/etherscan-address-link.tsx @@ -0,0 +1,31 @@ +import { defaultChain } from '@/lib/chains'; +import type { Address as AddressType, Chain } from 'viem'; +import { LinkComponent } from '../ui/link-component'; + +type ExplorerAddressLinkProps = React.HTMLAttributes & { + address?: AddressType | string; + chain?: Chain; +}; + +export const ExplorerAddressLink = ({ + children, + address, + className, + chain = defaultChain, +}: ExplorerAddressLinkProps) => { + const blockExplorerUrl = chain.blockExplorers?.default.url; + + if (blockExplorerUrl) { + return ( + + {children} + + ); + } + + return null; +}; diff --git a/apps/wallet/src/components/views/assets-list-view.tsx b/apps/wallet/src/components/views/assets-list-view.tsx new file mode 100644 index 00000000..0ed3b898 --- /dev/null +++ b/apps/wallet/src/components/views/assets-list-view.tsx @@ -0,0 +1,134 @@ +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@/components/ui/dialog'; +import { cn } from '@/lib/utils'; +import type * as React from 'react'; + +import { defaultTokenList } from '@/lib/chains'; +import Image from 'next/image'; +import type { TokenItem } from 'universal-types'; +import type { Address } from 'viem'; +import { ERC20Balance } from '../onchain/erc20-balance'; +import { ExplorerAddressLink } from '../onchain/etherscan-address-link'; +import { LinkComponent } from '../ui/link-component'; + +type AssetsListView = React.HTMLAttributes & { + isMinimized?: boolean; +}; + +const AssetsListView = ({ className, isMinimized }: AssetsListView) => { + return ( +
+ {defaultTokenList.tokens.map((token) => { + return ( + + ); + })} +
+ ); +}; + +export { AssetsListView }; + +type AssetCard = React.HTMLAttributes & { + token: TokenItem; + isMinimized?: boolean; +}; + +const AssetCard = ({ className, token, isMinimized }: AssetCard) => { + return ( + + + {isMinimized ? ( +
+ + {token.name} +
+ ) : ( +
+
+ {token.name} +
+ + {token.symbol}{' '} + {token?.extensions?.metadata?.type ? ( + + ({token?.extensions?.metadata?.type}) + + ) : null} + + {token.name} +
+
+ +
+ )} +
+ + + {token.name} + + {token.name} ({token.symbol}) + +
+ + Website + + | + + Explorer + +
+
+
+ {token?.extensions?.metadata?.description} +
+
+ {token.address} +
+
+
+ ); +}; diff --git a/packages/universal-data/src/token-list/stablecoin-token-list.ts b/packages/universal-data/src/token-list/stablecoin-token-list.ts deleted file mode 100644 index 7dd84964..00000000 --- a/packages/universal-data/src/token-list/stablecoin-token-list.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { TokenList } from 'universal-types'; - -export const stablecoinTokenList: TokenList = { - name: 'Universal Stablecoin Token List', - timestamp: '2023-09-08T19:28:15.497Z', - version: { - major: 1, - minor: 0, - patch: 0, - }, - tags: {}, - logoURI: '', - keywords: ['universal', 'stablecoin'], - tokens: [ - { - name: 'USD Coin', - address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', - symbol: 'USDC', - decimals: 6, - chainId: 8453, - logoURI: 'https://ethereum-optimism.github.io/data/USDC/logo.png', - extensions: { - bridgeInfo: { - '1': { - tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - }, - }, - }, - }, - { - chainId: 8453, - name: 'Prize USDC (Savings Account)', - symbol: 'przUSDC', - logoURI: 'https://app.cabana.fi/icons/przUSDC.svg', - address: '0x7f5C2b379b88499aC2B997Db583f8079503f25b9', - decimals: 6, - extensions: { - protocol: 'pool-together-v5', - }, - }, - { - chainId: 8453, - name: 'Aave USDC (Yield Bearing)', - symbol: 'aUSDC', - logoURI: - 'https://assets.coingecko.com/coins/images/14318/standard/aUSDC.e260d492.png?1696514006', - address: '0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB', - decimals: 6, - extensions: { - protocol: 'aave-v3', - }, - }, - // { - // chainId: 8453, - // name: 'Compound USDC', - // symbol: 'cUSDCv3', - // logoURI: 'https://ethereum-optimism.github.io/data/USDC/logo.png', - // address: '0xb125e6687d4313864e53df431d5425969c15eb2f', - // decimals: 6, - // extensions: { - // protocol: 'compound-v3', - // }, - // }, - ], -}; diff --git a/packages/universal-data/src/token-list/stablecoin-token-list.tsx b/packages/universal-data/src/token-list/stablecoin-token-list.tsx new file mode 100644 index 00000000..0b702292 --- /dev/null +++ b/packages/universal-data/src/token-list/stablecoin-token-list.tsx @@ -0,0 +1,87 @@ +import type { TokenList } from 'universal-types'; + +export const stablecoinTokenList: TokenList = { + name: 'Universal Stablecoin Token List', + timestamp: '2023-09-08T19:28:15.497Z', + version: { + major: 1, + minor: 0, + patch: 0, + }, + tags: {}, + logoURI: '', + keywords: ['universal', 'stablecoin'], + tokens: [ + { + name: 'USD Coin', + address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', + symbol: 'USDC', + decimals: 6, + chainId: 8453, + logoURI: 'https://ethereum-optimism.github.io/data/USDC/logo.png', + extensions: { + bridgeInfo: { + '1': { + tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + }, + }, + metadata: { + protocol: 'Circle', + url: 'https://www.usdc.com', + description: + 'USDC is a digital dollar, always tied to the value of the US Dollar. Managed by Circle, it’s fully backed by real assets, making it a reliable and stable currency for digital transactions.', + }, + }, + }, + { + chainId: 8453, + name: 'Prize USDC', + symbol: 'przUSDC', + logoURI: 'https://app.cabana.fi/icons/przUSDC.svg', + address: '0x7f5C2b379b88499aC2B997Db583f8079503f25b9', + decimals: 6, + extensions: { + protocol: 'pool-together-v5', + metadata: { + protocol: 'PoolTogether', + type: 'Prize Savings', + url: 'https://pooltogether.com', + description: ( + <> +

+ Prize USDC is a derivative of USDC, created after depositing + into the PoolTogether protocol. When you deposit USDC into + PoolTogether, it gets added to a lending protocol like Aave or + Compound. +

+

+ The interest earned from lending USDC is used to generate prizes + for the daily lottery. People who hold Prize USDC are entered + into the lottery, and can win prizes in ETH every day. +

+ + ), + }, + }, + }, + { + chainId: 8453, + name: 'Aave USDC', + symbol: 'aUSDC', + logoURI: + 'https://assets.coingecko.com/coins/images/14318/standard/aUSDC.e260d492.png?1696514006', + address: '0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB', + decimals: 6, + extensions: { + protocol: 'aave-v3', + metadata: { + protocol: 'Aave', + type: 'Yield Bearing', + url: 'https://aave.com', + description: + 'Aave USDC is a derivative of USDC, created after depositing into the Aave protocol. When you deposit your USDC into Aave, it gets lent out to others, and you earn fees paid by borrowers.', + }, + }, + }, + ], +}; From 00583243e69392c5a517f560dd786558af2550f5 Mon Sep 17 00:00:00 2001 From: Vitor Date: Thu, 12 Dec 2024 22:16:54 -0300 Subject: [PATCH 08/10] fix: withdraw and deposit actions --- .../src/processing/limit-order/get-actions.ts | 20 +++++++++++++------ .../limit-order/protocols/aave-v3.ts | 8 ++++---- .../limit-order/protocols/compound-v3.ts | 8 ++++---- .../limit-order/protocols/pool-together-v5.ts | 8 ++++---- .../limit-order/protocols/underlying-asset.ts | 6 +++--- .../src/abis/delegation-manager-abi.ts | 10 ++++++++++ .../src/actions/use-sign-erc20-swap.ts | 7 +++++-- 7 files changed, 44 insertions(+), 23 deletions(-) diff --git a/apps/api-delegations/src/processing/limit-order/get-actions.ts b/apps/api-delegations/src/processing/limit-order/get-actions.ts index 4c00a64b..b005b9c7 100644 --- a/apps/api-delegations/src/processing/limit-order/get-actions.ts +++ b/apps/api-delegations/src/processing/limit-order/get-actions.ts @@ -45,8 +45,11 @@ export function getHookActions({ const tokenOutData = stablecoinTokenList.tokens.find( (token) => token.address.toLowerCase() === tokenOut.toLowerCase(), ); + const underlyingAssetData = stablecoinTokenList.tokens.find( + (token) => !token.extensions?.protocol, + ); - if (!tokenInData || !tokenOutData) { + if (!tokenInData || !tokenOutData || !underlyingAssetData) { throw new Error('Token not found'); } @@ -63,23 +66,28 @@ export function getHookActions({ }); } + // If there are withdraw calls, the tokenOut should be replaced with the underlying asset + const updatedTokenOut = withdrawActions.length + ? (underlyingAssetData.address as Address) + : tokenOut; + // Deposit actions if (tokenInData.extensions?.protocol === 'aave-v3') { depositActions = getDepositAaveV3HookData({ - amountIn, + amountOut, delegator, - tokenOut, + tokenOut: updatedTokenOut, }); } else if (tokenInData.extensions?.protocol === 'pool-together-v5') { depositActions = getDepositPoolTogetherV5HookData({ - amountIn, + amountOut, delegator, tokenIn, - tokenOut, + tokenOut: updatedTokenOut, }); } else if (!tokenInData.extensions?.protocol) { depositActions = getDepositUnderlyingAssetHookData({ - amountIn, + amountOut, delegator, tokenIn, }); diff --git a/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts b/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts index 939d180c..be37a464 100644 --- a/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts +++ b/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts @@ -10,11 +10,11 @@ type GetDepositAaveV3HookDataReturnType = { }[]; export function getDepositAaveV3HookData({ - amountIn, + amountOut, delegator, tokenOut, }: { - amountIn: bigint; + amountOut: bigint; delegator: Address; tokenOut: Address; }): GetDepositAaveV3HookDataReturnType { @@ -26,7 +26,7 @@ export function getDepositAaveV3HookData({ callData: encodeFunctionData({ abi: erc20Abi, functionName: 'approve', - args: [AAVE_V3_POOL_BASE, amountIn], + args: [AAVE_V3_POOL_BASE, amountOut], }), }, // Deposits the token to the Aave Pool on behalf of the delegator @@ -36,7 +36,7 @@ export function getDepositAaveV3HookData({ callData: encodeFunctionData({ abi: aaveV3PoolAbi, functionName: 'supply', - args: [tokenOut, amountIn, delegator, 0], + args: [tokenOut, amountOut, delegator, 0], }), }, ]; diff --git a/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts b/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts index 2fcf6bb0..7243fd96 100644 --- a/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts +++ b/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts @@ -3,12 +3,12 @@ import { multicallAbi } from 'universal-data'; import { compoundV3Abi } from 'universal-data'; export function getDepositCompoundV3HookData({ - amountIn, + amountOut, delegator, tokenOut, tokenIn, }: { - amountIn: bigint; + amountOut: bigint; delegator: Address; tokenIn: Address; tokenOut: Address; @@ -25,7 +25,7 @@ export function getDepositCompoundV3HookData({ callData: encodeFunctionData({ abi: erc20Abi, functionName: 'approve', - args: [tokenIn, amountIn], + args: [tokenIn, amountOut], }), }, // Deposits the token to the Compound Pool on behalf of the delegator @@ -35,7 +35,7 @@ export function getDepositCompoundV3HookData({ callData: encodeFunctionData({ abi: compoundV3Abi, functionName: 'supplyTo', - args: [delegator, tokenOut, amountIn], + args: [delegator, tokenOut, amountOut], }), }, ], diff --git a/apps/api-delegations/src/processing/limit-order/protocols/pool-together-v5.ts b/apps/api-delegations/src/processing/limit-order/protocols/pool-together-v5.ts index 60e6c2f6..98125788 100644 --- a/apps/api-delegations/src/processing/limit-order/protocols/pool-together-v5.ts +++ b/apps/api-delegations/src/processing/limit-order/protocols/pool-together-v5.ts @@ -8,12 +8,12 @@ type GetDepositPoolTogetherV5HookDataReturnType = { }[]; export function getDepositPoolTogetherV5HookData({ - amountIn, + amountOut, delegator, tokenOut, tokenIn, }: { - amountIn: bigint; + amountOut: bigint; delegator: Address; tokenIn: Address; tokenOut: Address; @@ -26,7 +26,7 @@ export function getDepositPoolTogetherV5HookData({ callData: encodeFunctionData({ abi: erc20Abi, functionName: 'approve', - args: [tokenIn, amountIn], + args: [tokenIn, amountOut], }), }, // Deposits the token to the Prize vault on behalf of the delegator @@ -36,7 +36,7 @@ export function getDepositPoolTogetherV5HookData({ callData: encodeFunctionData({ abi: poolTogetherV5Abi, functionName: 'deposit', - args: [amountIn, delegator], + args: [amountOut, delegator], }), }, ]; diff --git a/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts b/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts index 0420d617..b4367655 100644 --- a/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts +++ b/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts @@ -7,11 +7,11 @@ type GetDepositUnderlyingAssetHookDataReturnType = { }[]; export function getDepositUnderlyingAssetHookData({ - amountIn, + amountOut, delegator, tokenIn, }: { - amountIn: bigint; + amountOut: bigint; delegator: Address; tokenIn: Address; }): GetDepositUnderlyingAssetHookDataReturnType { @@ -23,7 +23,7 @@ export function getDepositUnderlyingAssetHookData({ callData: encodeFunctionData({ abi: erc20Abi, functionName: 'transfer', - args: [delegator, amountIn], + args: [delegator, amountOut], }), }, ]; diff --git a/packages/universal-data/src/abis/delegation-manager-abi.ts b/packages/universal-data/src/abis/delegation-manager-abi.ts index 437462c4..aebebe3c 100644 --- a/packages/universal-data/src/abis/delegation-manager-abi.ts +++ b/packages/universal-data/src/abis/delegation-manager-abi.ts @@ -643,4 +643,14 @@ export const delegationManagerAbi = [ name: 'StringTooLong', inputs: [{ name: 'str', type: 'string', internalType: 'string' }], }, + { + type: 'error', + name: 'ExternalHookExecutionFailed', + inputs: [{ name: 'revertData', type: 'bytes', internalType: 'bytes' }], + }, + { + type: 'error', + name: 'InvalidArgsLength', + inputs: [{ name: 'length', type: 'uint256', internalType: 'uint256' }], + }, ] as const; diff --git a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts index 22633c58..bdb9b804 100644 --- a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts +++ b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts @@ -47,6 +47,9 @@ export function useSignErc20SwapDelegation() { decimalsIn, amountIn, }: SignDelegationParams) { + const amountInBigInt = parseUnits(amountIn, decimalsIn); + // The amountInMin is the amount in less 1 decimal place to avoid rounding errors + const amountInMin = amountInBigInt - 1n; const signature = await signTypedDataAsync({ types: eip712DelegationTypes, primaryType: 'Delegation', @@ -66,7 +69,7 @@ export function useSignErc20SwapDelegation() { enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, terms: encodeERC20BalanceGteWrapEnforcerTerms({ token: tokenIn, - amount: parseUnits(amountIn, decimalsIn), + amount: amountInMin, }), }, { @@ -96,7 +99,7 @@ export function useSignErc20SwapDelegation() { enforcer: universalDeployments.ERC20BalanceGteWrapEnforcer, terms: encodeERC20BalanceGteWrapEnforcerTerms({ token: tokenIn, - amount: parseUnits(amountIn, decimalsIn), + amount: amountInMin, }), args: '0x', }, From d00bbb8635920f58a3390cb837297c6e21c2104d Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 13 Dec 2024 11:07:02 -0300 Subject: [PATCH 09/10] fix: protocol to procol swaps --- .../src/processing/limit-order/get-actions.ts | 89 ++++++++++++------ .../limit-order/protocols/aave-v3.ts | 6 +- .../limit-order/protocols/compound-v3.ts | 90 ++++++++++++------- .../limit-order/protocols/underlying-asset.ts | 6 +- .../src/components/forms/form-erc20-swap.tsx | 2 +- .../src/token-list/stablecoin-token-list.tsx | 11 +++ .../src/actions/use-sign-erc20-swap.ts | 8 +- 7 files changed, 138 insertions(+), 74 deletions(-) diff --git a/apps/api-delegations/src/processing/limit-order/get-actions.ts b/apps/api-delegations/src/processing/limit-order/get-actions.ts index b005b9c7..84da50eb 100644 --- a/apps/api-delegations/src/processing/limit-order/get-actions.ts +++ b/apps/api-delegations/src/processing/limit-order/get-actions.ts @@ -9,6 +9,10 @@ import { getWithdrawPoolTogetherV5HookData, } from './protocols/pool-together-v5.js'; import { getDepositUnderlyingAssetHookData } from './protocols/underlying-asset.js'; +import { + getDepositCompoundV3HookData, + getWithdrawCompoundV3HookData, +} from './protocols/compound-v3.js'; type HookActions = { target: Address; @@ -53,17 +57,31 @@ export function getHookActions({ throw new Error('Token not found'); } + const tokenOutProtocol = tokenOutData.extensions?.protocol; + // Withdraw actions - if (tokenOutData.extensions?.protocol === 'aave-v3') { - withdrawActions = getWithdrawAaveV3HookData({ - amountIn, - tokenIn, - }); - } else if (tokenOutData.extensions?.protocol === 'pool-together-v5') { - withdrawActions = getWithdrawPoolTogetherV5HookData({ - amountOut, - tokenOut, - }); + switch (tokenOutProtocol) { + case 'aave-v3': + withdrawActions = getWithdrawAaveV3HookData({ + // Always use the underlying asset as the tokenIn for compound + tokenIn: underlyingAssetData.address as Address, + amountOut, + }); + break; + case 'pool-together-v5': + withdrawActions = getWithdrawPoolTogetherV5HookData({ + amountOut, + tokenOut, + }); + break; + case 'compound-v3': + withdrawActions = getWithdrawCompoundV3HookData({ + // Always use the underlying asset as the tokenIn for compound + tokenIn: underlyingAssetData.address as Address, + + tokenOut, + }); + break; } // If there are withdraw calls, the tokenOut should be replaced with the underlying asset @@ -71,26 +89,39 @@ export function getHookActions({ ? (underlyingAssetData.address as Address) : tokenOut; + const tokenInProtocol = tokenInData.extensions?.protocol; // Deposit actions - if (tokenInData.extensions?.protocol === 'aave-v3') { - depositActions = getDepositAaveV3HookData({ - amountOut, - delegator, - tokenOut: updatedTokenOut, - }); - } else if (tokenInData.extensions?.protocol === 'pool-together-v5') { - depositActions = getDepositPoolTogetherV5HookData({ - amountOut, - delegator, - tokenIn, - tokenOut: updatedTokenOut, - }); - } else if (!tokenInData.extensions?.protocol) { - depositActions = getDepositUnderlyingAssetHookData({ - amountOut, - delegator, - tokenIn, - }); + switch (tokenInProtocol) { + case 'aave-v3': + depositActions = getDepositAaveV3HookData({ + amountOut, + delegator, + tokenOut: updatedTokenOut, + }); + break; + case 'pool-together-v5': + depositActions = getDepositPoolTogetherV5HookData({ + amountOut, + delegator, + tokenIn, + tokenOut: updatedTokenOut, + }); + break; + case 'compound-v3': + depositActions = getDepositCompoundV3HookData({ + amountOut, + delegator, + tokenIn, + tokenOut: updatedTokenOut, + }); + break; + case undefined: + depositActions = getDepositUnderlyingAssetHookData({ + amountIn, + delegator, + tokenIn, + }); + break; } return { diff --git a/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts b/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts index be37a464..5667f0bf 100644 --- a/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts +++ b/apps/api-delegations/src/processing/limit-order/protocols/aave-v3.ts @@ -44,10 +44,10 @@ export function getDepositAaveV3HookData({ type GetWithdrawAaveV3HookDataReturnType = GetDepositAaveV3HookDataReturnType; export function getWithdrawAaveV3HookData({ - amountIn, + amountOut, tokenIn, }: { - amountIn: bigint; + amountOut: bigint; tokenIn: Address; }): GetWithdrawAaveV3HookDataReturnType { return [ @@ -58,7 +58,7 @@ export function getWithdrawAaveV3HookData({ callData: encodeFunctionData({ abi: aaveV3PoolAbi, functionName: 'withdraw', - args: [tokenIn, amountIn, universalDeployments.Multicall], + args: [tokenIn, amountOut, universalDeployments.Multicall], }), }, ]; diff --git a/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts b/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts index 7243fd96..f153e108 100644 --- a/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts +++ b/apps/api-delegations/src/processing/limit-order/protocols/compound-v3.ts @@ -1,7 +1,18 @@ -import { encodeFunctionData, erc20Abi, type Address, type Hex } from 'viem'; -import { multicallAbi } from 'universal-data'; +import { + encodeFunctionData, + erc20Abi, + type Address, + type Hex, + maxUint256, +} from 'viem'; import { compoundV3Abi } from 'universal-data'; +type GetDepositCompoundV3HookDataReturnType = { + target: Address; + value: bigint; + callData: Hex; +}[]; + export function getDepositCompoundV3HookData({ amountOut, delegator, @@ -12,33 +23,50 @@ export function getDepositCompoundV3HookData({ delegator: Address; tokenIn: Address; tokenOut: Address; -}): Hex { - return encodeFunctionData({ - abi: multicallAbi, - functionName: 'multicall', - args: [ - [ - // Approves the token to the Compound Pool - { - target: tokenOut, - value: 0n, - callData: encodeFunctionData({ - abi: erc20Abi, - functionName: 'approve', - args: [tokenIn, amountOut], - }), - }, - // Deposits the token to the Compound Pool on behalf of the delegator - { - target: tokenIn, - value: 0n, - callData: encodeFunctionData({ - abi: compoundV3Abi, - functionName: 'supplyTo', - args: [delegator, tokenOut, amountOut], - }), - }, - ], - ], - }); +}): GetDepositCompoundV3HookDataReturnType { + return [ + // Approves the token to the Compound Pool + { + target: tokenOut, + value: 0n, + callData: encodeFunctionData({ + abi: erc20Abi, + functionName: 'approve', + args: [tokenIn, amountOut], + }), + }, + // Deposits the token to the Compound Pool on behalf of the delegator + { + target: tokenIn, + value: 0n, + callData: encodeFunctionData({ + abi: compoundV3Abi, + functionName: 'supplyTo', + args: [delegator, tokenOut, amountOut], + }), + }, + ]; +} + +type GetWithdrawCompoundV3HookDataReturnType = + GetDepositCompoundV3HookDataReturnType; +export function getWithdrawCompoundV3HookData({ + tokenOut, + tokenIn, +}: { + tokenIn: Address; + tokenOut: Address; +}): GetWithdrawCompoundV3HookDataReturnType { + return [ + // Approves the token to the Compound Pool + { + target: tokenOut, + value: 0n, + callData: encodeFunctionData({ + abi: compoundV3Abi, + functionName: 'withdraw', + args: [tokenIn, maxUint256], + }), + }, + ]; } diff --git a/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts b/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts index b4367655..0420d617 100644 --- a/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts +++ b/apps/api-delegations/src/processing/limit-order/protocols/underlying-asset.ts @@ -7,11 +7,11 @@ type GetDepositUnderlyingAssetHookDataReturnType = { }[]; export function getDepositUnderlyingAssetHookData({ - amountOut, + amountIn, delegator, tokenIn, }: { - amountOut: bigint; + amountIn: bigint; delegator: Address; tokenIn: Address; }): GetDepositUnderlyingAssetHookDataReturnType { @@ -23,7 +23,7 @@ export function getDepositUnderlyingAssetHookData({ callData: encodeFunctionData({ abi: erc20Abi, functionName: 'transfer', - args: [delegator, amountOut], + args: [delegator, amountIn], }), }, ]; diff --git a/apps/wallet/src/components/forms/form-erc20-swap.tsx b/apps/wallet/src/components/forms/form-erc20-swap.tsx index 02e17d48..6d24062c 100644 --- a/apps/wallet/src/components/forms/form-erc20-swap.tsx +++ b/apps/wallet/src/components/forms/form-erc20-swap.tsx @@ -65,7 +65,7 @@ function FormErc20Swap({ defaultValues }: FormErc20SwapProps) { if (formValues.tokenOut && formValues.tokenIn && formValues.amountOut) { form.setValue('amountIn', formValues.amountOut); } else { - form.setValue('amountIn', undefined); + form.setValue('amountIn', ''); } }, [form, formValues.amountOut, formValues.tokenOut, formValues.tokenIn]); diff --git a/packages/universal-data/src/token-list/stablecoin-token-list.tsx b/packages/universal-data/src/token-list/stablecoin-token-list.tsx index 0b702292..e7171aa2 100644 --- a/packages/universal-data/src/token-list/stablecoin-token-list.tsx +++ b/packages/universal-data/src/token-list/stablecoin-token-list.tsx @@ -83,5 +83,16 @@ export const stablecoinTokenList: TokenList = { }, }, }, + { + chainId: 8453, + name: 'Compound USDC', + symbol: 'cUSDCv3', + logoURI: 'https://ethereum-optimism.github.io/data/USDC/logo.png', + address: '0xb125e6687d4313864e53df431d5425969c15eb2f', + decimals: 6, + extensions: { + protocol: 'compound-v3', + }, + }, ], }; diff --git a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts index bdb9b804..21999caf 100644 --- a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts +++ b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-swap.ts @@ -2,19 +2,13 @@ import { useState } from 'react'; import { ROOT_AUTHORITY, SALT, universalDeployments } from 'universal-data'; import type { Delegation, DelegationWithMetadata } from 'universal-types'; -import { - type Address, - parseUnits, - // , - // parseUnits -} from 'viem'; +import { type Address, parseUnits } from 'viem'; import { useSignTypedData } from 'wagmi'; import { useInsertDelegation } from '../api/actions/insert-delegation.js'; import { eip712DelegationTypes } from '../delegation/eip712-delegation-type.js'; import { getDelegationHash } from '../delegation/get-delegation-hash.js'; import { encodeEnforcerERC20TransferAmount } from '../enforcers/enforcer-erc20-transfer-amount.js'; import { encodeERC20BalanceGteWrapEnforcerTerms } from '../enforcers/erc20-balance-gte-wrap-enforcer.js'; -// import { encodeERC20BalanceGteWrapEnforcerTerms } from '../enforcers/erc20-balance-gte-wrap-enforcer.js'; type SignDelegationParams = { chainId: number; From 20e2adb1e9652852d51a84b12894a35fc29dd442 Mon Sep 17 00:00:00 2001 From: Kames Date: Fri, 13 Dec 2024 17:31:12 -0800 Subject: [PATCH 10/10] wip: popup ui --- .../delegation-default-parsed-view.tsx | 23 +++- .../components/erc20-swap-authorization.tsx | 109 ++++++++++++++++++ .../sign/eth-sign-typed-data-v-4/page.tsx | 4 +- .../src/token-list/stablecoin-token-list.tsx | 10 +- .../erc20-balance-gte-wrap-enforcer.ts | 17 +++ .../src/exports/index.ts | 13 ++- 6 files changed, 166 insertions(+), 10 deletions(-) create mode 100644 apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/erc20-swap-authorization.tsx diff --git a/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/delegation-default-parsed-view.tsx b/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/delegation-default-parsed-view.tsx index 0fe084fa..a582a02f 100644 --- a/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/delegation-default-parsed-view.tsx +++ b/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/delegation-default-parsed-view.tsx @@ -1,9 +1,10 @@ -import type { Delegation } from 'universal-types'; import { cn } from '@/lib/utils'; import { useMemo } from 'react'; import { universalDeployments } from 'universal-data'; +import type { Delegation } from 'universal-types'; import type { Chain } from 'viem'; import { CardPaymentBasic } from './card-payment-basic'; +import { ERC20SwapAuthorization } from './erc20-swap-authorization'; export type DelegationDefaultParsedView = React.HTMLAttributes & { chainId: Chain['id']; @@ -17,6 +18,7 @@ export const DelegationDefaultParsedView = ({ chainId, }: DelegationDefaultParsedView) => { const delegationType = useMemo(() => { + console.log(typedData.caveats[0], 'typedData.caveats[0]'); if (!typedData) { return; } @@ -28,6 +30,16 @@ export const DelegationDefaultParsedView = ({ case universalDeployments.ERC20TransferAmountEnforcer: case universalDeployments.NativeTokenPaymentEnforcer: return 'CardPayment'; + case universalDeployments.ERC20BalanceGteWrapEnforcer: + return 'ERC20Swap'; + default: + return 'Default'; + } + } + if (typedData.caveats.length === 3) { + switch (typedData.caveats[0].enforcer) { + case universalDeployments.ERC20BalanceGteWrapEnforcer: + return 'ERC20Swap'; default: return 'Default'; } @@ -45,5 +57,14 @@ export const DelegationDefaultParsedView = ({
); } + + if (delegationType === 'ERC20Swap') { + return ( +
+ +
+ ); + } + return
{children}
; }; diff --git a/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/erc20-swap-authorization.tsx b/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/erc20-swap-authorization.tsx new file mode 100644 index 00000000..adf47bac --- /dev/null +++ b/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/erc20-swap-authorization.tsx @@ -0,0 +1,109 @@ +import { cn } from '@/lib/utils'; +import { ArrowDown } from 'lucide-react'; +import Image from 'next/image'; +import { useMemo } from 'react'; +import { findToken, getDefaultTokenList } from 'universal-data'; +import { + decodeERC20BalanceGteWrapEnforcerTerms, + decodeEnforcerERC20TransferAmount, + getERC20BalanceGteWrapEnforcerFromDelegation, + getErc20TransferAmountEnforcerFromDelegation, +} from 'universal-delegations-sdk'; +import type { Delegation } from 'universal-types'; +import { type Address, formatUnits } from 'viem'; + +export type ERC20SwapAuthorization = React.HTMLAttributes & { + typedData: Delegation; + chainId: number; +}; + +export const ERC20SwapAuthorization = ({ + className, + typedData, + chainId, +}: ERC20SwapAuthorization) => { + const data = useMemo(() => { + const { terms: erc20BalanceGteWrapEnforcerTerms } = + getERC20BalanceGteWrapEnforcerFromDelegation(typedData); + const { terms: erc20TransferAmountEnforceTerms } = + getErc20TransferAmountEnforcerFromDelegation(typedData); + const erc20TransferAmountEnforcerFormattedTerms = + decodeEnforcerERC20TransferAmount(erc20TransferAmountEnforceTerms); + const erc20BalanceGteWrapEnforcerFormattedTerms = + decodeERC20BalanceGteWrapEnforcerTerms(erc20BalanceGteWrapEnforcerTerms); + + const addressOut = erc20TransferAmountEnforcerFormattedTerms[0] as Address; + const addressIn = erc20BalanceGteWrapEnforcerFormattedTerms[0] as Address; + const tokenList = getDefaultTokenList({ chainId }); + const tokenOut = findToken({ tokenList, address: addressOut }); + const tokenIn = findToken({ tokenList, address: addressIn }); + if (!tokenOut || !tokenIn) { + throw new Error(`Token not found: ${addressIn}`); + } + return { + to: typedData.delegate, + amountOutFormatted: erc20TransferAmountEnforcerFormattedTerms[1], + amountInFormatted: erc20BalanceGteWrapEnforcerFormattedTerms[1], + tokenIn: tokenIn, + tokenOut: tokenOut, + }; + }, [typedData, chainId]); + + return ( +
+
+
+
+ Token Out +
+ + {data.tokenOut.symbol} + + + {data.tokenOut.name} + +
+
+ + {formatUnits( + BigInt(data.amountOutFormatted), + data.tokenOut.decimals, + ).toString()} + +
+ +
+
+ Token In +
+ + {data.tokenIn.symbol} + + + {data.tokenIn.name} + +
+
+ + {formatUnits( + BigInt(data.amountInFormatted), + data.tokenIn.decimals, + ).toString()} + +
+
+
+ ); +}; diff --git a/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/page.tsx b/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/page.tsx index 9dae601b..e80614fc 100644 --- a/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/page.tsx +++ b/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/page.tsx @@ -2,10 +2,10 @@ import { RowBasic } from '@/components/row-basic'; import { Toggle } from '@/components/toggle'; import { Button } from '@/components/ui/button'; -import type { Delegation } from 'universal-types'; import { useGetMessageChainId } from '@/lib/pop-up/hooks/use-get-message-chain-id'; import { useMemo, useState } from 'react'; import type { UniversalDID, VerificationRequest } from 'universal-identity-sdk'; +import type { Delegation } from 'universal-types'; import type { TypedDataDefinition } from 'viem'; import { ActionRequestFooter } from '../components/action-request-footer'; import { ActionRequestHeader } from '../components/action-request-header'; @@ -65,7 +65,7 @@ export default function EthSignTypedDataV4Page() { /> - + {viewModeAdvanced === false && ( + enforcer.toLowerCase() === + universalDeployments.ERC20BalanceGteWrapEnforcer.toLowerCase(), + ); + if (!erc20TransferAmountEnforcer) { + throw new Error('No ERC20TransferAmountEnforcer found'); + } + + return erc20TransferAmountEnforcer; +} diff --git a/packages/universal-delegations-sdk/src/exports/index.ts b/packages/universal-delegations-sdk/src/exports/index.ts index 3dfebecb..034def30 100644 --- a/packages/universal-delegations-sdk/src/exports/index.ts +++ b/packages/universal-delegations-sdk/src/exports/index.ts @@ -24,12 +24,6 @@ export { useDelegationsApiClient, type DelegationsApiClient, } from '../api/client.js'; -export { - decodeEnforcerERC20TransferAmount, - encodeEnforcerERC20TransferAmount, - getErc20TransferAmountEnforcerFromDelegation, -} from '../enforcers/enforcer-erc20-transfer-amount.js'; -export { encodeExternalCallEnforcerArgs } from '../enforcers/enforcer-external-call.js'; export { eip712DelegationTypes } from '../delegation/eip712-delegation-type.js'; export { encodeDelegation } from '../delegation/encode-delegation.js'; export { @@ -37,9 +31,16 @@ export { getCaveatPacketHash, getDelegationHash, } from '../delegation/get-delegation-hash.js'; +export { + decodeEnforcerERC20TransferAmount, + encodeEnforcerERC20TransferAmount, + getErc20TransferAmountEnforcerFromDelegation, +} from '../enforcers/enforcer-erc20-transfer-amount.js'; +export { encodeExternalCallEnforcerArgs } from '../enforcers/enforcer-external-call.js'; export { decodeERC20BalanceGteWrapEnforcerTerms, encodeERC20BalanceGteWrapEnforcerTerms, + getERC20BalanceGteWrapEnforcerFromDelegation, } from '../enforcers/erc20-balance-gte-wrap-enforcer.js'; export { encodeBatchExecution } from '../execution/encode-batch-execution.js'; export { encodeSingleExecution } from '../execution/encode-single-execution.js';