From 66429aec3e95988daba081421701d491c6ac8cfe Mon Sep 17 00:00:00 2001 From: Vitor Date: Thu, 5 Dec 2024 18:25:21 -0300 Subject: [PATCH] refactor: delegation types --- apps/api-delegations/drizzle.config.ts | 7 +- .../actions/delegations/get-delegation-db.ts | 1 - .../actions/delegations/get-delegations-db.ts | 6 +- .../delegations/insert-delegation-db.ts | 7 +- .../delegations/invalidate-delegation-db.ts | 1 + .../src/db/migrations/0006_flimsy_harpoon.sql | 3 + .../src/db/migrations/meta/0006_snapshot.json | 156 +++++ .../src/db/migrations/meta/_journal.json | 7 + apps/api-delegations/src/db/schema.ts | 7 +- .../api-delegations/src/routes/delegations.ts | 12 +- apps/api-delegations/src/validation.ts | 2 +- apps/api-universal/package.json | 1 + .../src/routes/credit-lines/index.ts | 10 +- ...ansfer-amount-enforcer-collection-total.ts | 8 +- .../generated/schema.graphql | 55 +- apps/delegations-indexer/package.json | 1 + apps/delegations-indexer/ponder.config.ts | 4 +- apps/delegations-indexer/ponder.schema.ts | 6 +- .../src/api/credit-lines/index.ts | 4 +- .../src/event-handlers/delegationManager.ts | 32 +- .../src/utils/delegation/constants.ts | 27 - .../erc20-transfer-amount-enforcer.ts | 6 +- .../utils/delegation/get-delegation-hash.ts | 53 -- .../components/card-payment-basic.tsx | 2 +- .../delegation-default-parsed-view.tsx | 2 +- .../sign/eth-sign-typed-data-v-4/page.tsx | 2 +- apps/popup/package.json | 1 + .../components/delegation-details-sheet.tsx | 10 +- .../delegations-management-sheet.tsx | 30 +- .../account-adapters/to-universal-account.ts | 6 +- .../src/lib/delegation-framework/abis.ts | 629 ------------------ .../src/lib/delegation-framework/constants.ts | 26 - .../delegation/encode-delegations.ts | 49 -- .../format-erc20-transfer-enforcer-calls.ts | 26 +- .../execution-lib/encode-batch-execution.ts | 29 - .../src/lib/delegation-framework/types.ts | 26 - packages/universal-data/package.json | 3 +- ... => erc20-transfer-amount-enforcer-abi.ts} | 2 +- packages/universal-data/src/exports/index.ts | 4 +- packages/universal-data/src/types.ts | 29 +- .../universal-delegations-sdk/package.json | 3 +- .../actions/core/use-delegation-execute.ts | 20 +- .../src/actions/core/use-delegation-status.ts | 16 +- .../actions/core/use-disable-delegation.ts | 33 +- .../src/actions/core/use-enable-delegation.ts | 34 +- .../use-erc20-transfer-amount-enforcer.ts | 16 +- .../src/actions/use-sign-erc20-transfer.ts | 62 +- .../src/constants.ts | 28 - .../src/delegation/encode-delegations.ts | 7 +- .../src/delegation/get-delegation-hash.ts | 11 +- .../delegation/hooks/use-redeem-delegation.ts | 6 +- .../delegation/hooks/use-sign-delegation.ts | 17 +- ...sform-delegation-db-to-delegation-types.ts | 25 - .../src/execution/encode-batch-execution.ts | 4 +- .../src/execution/encode-single-execution.ts | 4 +- .../src/exports/index.ts | 12 - .../universal-delegations-sdk/src/types.ts | 28 - .../universal-types/src/delegations/index.ts | 22 +- packages/universal-types/src/exports/index.ts | 5 - pnpm-lock.yaml | 15 + 60 files changed, 450 insertions(+), 1210 deletions(-) create mode 100644 apps/api-delegations/src/db/migrations/0006_flimsy_harpoon.sql create mode 100644 apps/api-delegations/src/db/migrations/meta/0006_snapshot.json delete mode 100644 apps/delegations-indexer/src/utils/delegation/constants.ts delete mode 100644 apps/delegations-indexer/src/utils/delegation/get-delegation-hash.ts delete mode 100644 apps/popup/src/lib/delegation-framework/abis.ts delete mode 100644 apps/popup/src/lib/delegation-framework/constants.ts delete mode 100644 apps/popup/src/lib/delegation-framework/delegation/encode-delegations.ts delete mode 100644 apps/popup/src/lib/delegation-framework/execution-lib/encode-batch-execution.ts delete mode 100644 apps/popup/src/lib/delegation-framework/types.ts rename packages/universal-data/src/abis/{erc20-transfer-amount-abi.ts => erc20-transfer-amount-enforcer-abi.ts} (98%) delete mode 100644 packages/universal-delegations-sdk/src/constants.ts delete mode 100644 packages/universal-delegations-sdk/src/delegation/transform-delegation-db-to-delegation-types.ts delete mode 100644 packages/universal-delegations-sdk/src/types.ts diff --git a/apps/api-delegations/drizzle.config.ts b/apps/api-delegations/drizzle.config.ts index 94e3726b..d723d163 100644 --- a/apps/api-delegations/drizzle.config.ts +++ b/apps/api-delegations/drizzle.config.ts @@ -1,11 +1,14 @@ import type { Config } from 'drizzle-kit'; -import { env } from './src/env.js'; + +if (!process.env.DELEGATIONS_DATABASE_URL) { + throw new Error('DELEGATIONS_DATABASE_URL is not set'); +} export default { schema: './src/db/schema.ts', out: './src/db/migrations', dialect: 'postgresql', dbCredentials: { - url: env.DELEGATIONS_DATABASE_URL, + url: process.env.DELEGATIONS_DATABASE_URL, }, } satisfies Config; diff --git a/apps/api-delegations/src/db/actions/delegations/get-delegation-db.ts b/apps/api-delegations/src/db/actions/delegations/get-delegation-db.ts index 64f21d9d..f5f40c50 100644 --- a/apps/api-delegations/src/db/actions/delegations/get-delegation-db.ts +++ b/apps/api-delegations/src/db/actions/delegations/get-delegation-db.ts @@ -4,7 +4,6 @@ import { db } from '../../index.js'; export function getDelegationDb({ hash }: GetDelegationParams) { return db.query.delegations.findFirst({ where: (delegations, { eq }) => eq(delegations.hash, hash), - with: { caveats: true, }, diff --git a/apps/api-delegations/src/db/actions/delegations/get-delegations-db.ts b/apps/api-delegations/src/db/actions/delegations/get-delegations-db.ts index 33aba5eb..b706886e 100644 --- a/apps/api-delegations/src/db/actions/delegations/get-delegations-db.ts +++ b/apps/api-delegations/src/db/actions/delegations/get-delegations-db.ts @@ -3,11 +3,9 @@ import type { GetDelegationsParams } from '../../../validation.js'; import { db } from '../../index.js'; import { delegations } from '../../schema.js'; import { sqlLower } from '../../utils.js'; -import type { DelegationWithChainIdMetadata } from 'universal-types'; +import type { DelegationWithMetadata } from 'universal-types'; -export type GetDelegationsDbReturnType = - | DelegationWithChainIdMetadata[] - | undefined; +export type GetDelegationsDbReturnType = DelegationWithMetadata[] | undefined; export function getDelegationsDb({ chainId, 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 b006252d..dc158b50 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 @@ -1,11 +1,14 @@ -import type { DelegationWithChainIdMetadataHash } from 'universal-types'; import { db } from '../../index.js'; import { caveats as caveatsDb, delegations as delegationsDb, + type InsertDelegationDb, + type InsertCaveatDb, } from '../../schema.js'; -type InsertDelegationDbParams = DelegationWithChainIdMetadataHash; +type InsertDelegationDbParams = InsertDelegationDb & { + caveats: InsertCaveatDb[]; +}; export function insertDelegationDb({ caveats, diff --git a/apps/api-delegations/src/db/actions/delegations/invalidate-delegation-db.ts b/apps/api-delegations/src/db/actions/delegations/invalidate-delegation-db.ts index 04ffe7e5..97c86ed5 100644 --- a/apps/api-delegations/src/db/actions/delegations/invalidate-delegation-db.ts +++ b/apps/api-delegations/src/db/actions/delegations/invalidate-delegation-db.ts @@ -6,6 +6,7 @@ import { sqlLower } from '../../utils.js'; export function invalidateDelegationDb({ hash }: { hash: Hash }) { return db + .update(delegationsDb) .set({ isValid: false }) .where(eq(sqlLower(delegationsDb.hash), hash.toLowerCase())) diff --git a/apps/api-delegations/src/db/migrations/0006_flimsy_harpoon.sql b/apps/api-delegations/src/db/migrations/0006_flimsy_harpoon.sql new file mode 100644 index 00000000..e35797e2 --- /dev/null +++ b/apps/api-delegations/src/db/migrations/0006_flimsy_harpoon.sql @@ -0,0 +1,3 @@ +ALTER TABLE "caveats" ALTER COLUMN "type" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "delegations" ALTER COLUMN "type" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "delegations" ADD COLUMN "verifyingContract" varchar(42) NOT NULL; \ No newline at end of file diff --git a/apps/api-delegations/src/db/migrations/meta/0006_snapshot.json b/apps/api-delegations/src/db/migrations/meta/0006_snapshot.json new file mode 100644 index 00000000..3510db14 --- /dev/null +++ b/apps/api-delegations/src/db/migrations/meta/0006_snapshot.json @@ -0,0 +1,156 @@ +{ + "id": "329f48a4-b96c-4cdf-99d6-6a84a14dd24c", + "prevId": "1f0dc50b-abed-4990-b8a2-435e9ee80874", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.caveats": { + "name": "caveats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(256)", + "primaryKey": false, + "notNull": false + }, + "enforcer": { + "name": "enforcer", + "type": "varchar(42)", + "primaryKey": false, + "notNull": true + }, + "terms": { + "name": "terms", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "args": { + "name": "args", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "delegationHash": { + "name": "delegationHash", + "type": "varchar(66)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "caveats_delegationHash_delegations_hash_fk": { + "name": "caveats_delegationHash_delegations_hash_fk", + "tableFrom": "caveats", + "tableTo": "delegations", + "columnsFrom": [ + "delegationHash" + ], + "columnsTo": [ + "hash" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.delegations": { + "name": "delegations", + "schema": "", + "columns": { + "hash": { + "name": "hash", + "type": "varchar(66)", + "primaryKey": true, + "notNull": true + }, + "chainId": { + "name": "chainId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "verifyingContract": { + "name": "verifyingContract", + "type": "varchar(42)", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(256)", + "primaryKey": false, + "notNull": false + }, + "delegator": { + "name": "delegator", + "type": "varchar(42)", + "primaryKey": false, + "notNull": true + }, + "delegate": { + "name": "delegate", + "type": "varchar(42)", + "primaryKey": false, + "notNull": true + }, + "authority": { + "name": "authority", + "type": "varchar(66)", + "primaryKey": false, + "notNull": true + }, + "salt": { + "name": "salt", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "signature": { + "name": "signature", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isValid": { + "name": "isValid", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/api-delegations/src/db/migrations/meta/_journal.json b/apps/api-delegations/src/db/migrations/meta/_journal.json index 551a3902..6fd5f74f 100644 --- a/apps/api-delegations/src/db/migrations/meta/_journal.json +++ b/apps/api-delegations/src/db/migrations/meta/_journal.json @@ -43,6 +43,13 @@ "when": 1733323390653, "tag": "0005_lean_rhino", "breakpoints": true + }, + { + "idx": 6, + "version": "7", + "when": 1733419629547, + "tag": "0006_flimsy_harpoon", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/api-delegations/src/db/schema.ts b/apps/api-delegations/src/db/schema.ts index 48979800..75ebfeee 100644 --- a/apps/api-delegations/src/db/schema.ts +++ b/apps/api-delegations/src/db/schema.ts @@ -23,9 +23,10 @@ const bigIntColumn = () => bigint({ mode: 'number' }).$type(); // Table export const delegations = pgTable('delegations', { hash: bytes32Column().primaryKey(), - type: varchar({ length: 256 }).notNull(), - delegator: addressColumn().notNull(), chainId: integer().notNull(), + verifyingContract: addressColumn().notNull(), + type: varchar({ length: 256 }), + delegator: addressColumn().notNull(), delegate: addressColumn().notNull(), authority: bytes32Column().notNull(), salt: bigIntColumn().notNull(), @@ -45,7 +46,7 @@ export const delegationsRelations = relations(delegations, ({ many }) => ({ // Table export const caveats = pgTable('caveats', { id: serial('id').primaryKey(), - type: varchar({ length: 256 }).notNull(), + type: varchar({ length: 256 }), enforcer: addressColumn().notNull(), terms: bytesColumn().notNull(), args: bytesColumn().notNull(), diff --git a/apps/api-delegations/src/routes/delegations.ts b/apps/api-delegations/src/routes/delegations.ts index 45908217..fb31eeb2 100644 --- a/apps/api-delegations/src/routes/delegations.ts +++ b/apps/api-delegations/src/routes/delegations.ts @@ -4,22 +4,18 @@ import { getDelegationDb } from '../db/actions/delegations/get-delegation-db.js' import { getDelegationsDb } from '../db/actions/delegations/get-delegations-db.js'; import { insertDelegationDb } from '../db/actions/delegations/insert-delegation-db.js'; import { invalidateDelegationDb } from '../db/actions/delegations/invalidate-delegation-db.js'; -import type { SelectDelegationDb } from '../db/schema.js'; import { getDelegationSchema, getDelegationsSchema, postDelegationSchema, } from '../validation.js'; -import type { - DelegationWithChainIdMetadata, - DelegationWithChainIdMetadataHash, -} from 'universal-types'; +import type { DelegationWithMetadata } from 'universal-types'; const delegationsRouter = new Hono() // Get a delegation by its hash .get('/:hash', zValidator('param', getDelegationSchema), async (c) => { const { hash } = c.req.valid('param'); - const delegation: DelegationWithChainIdMetadataHash | undefined = + const delegation: DelegationWithMetadata | undefined = await getDelegationDb({ hash, }); @@ -34,7 +30,7 @@ const delegationsRouter = new Hono() // Get a delegations by multiple parameters .post('/get', zValidator('json', getDelegationsSchema), async (c) => { const params = c.req.valid('json'); - const delegations: DelegationWithChainIdMetadata[] | undefined = + const delegations: DelegationWithMetadata[] | undefined = await getDelegationsDb(params); if (delegations) { @@ -73,7 +69,7 @@ const delegationsRouter = new Hono() // TODO: Expect a signature from the delegator to invalidate the delegation async (c) => { const { hash } = c.req.valid('param'); - const delegation: SelectDelegationDb[] | undefined = + const delegation: Omit[] | undefined = await invalidateDelegationDb({ hash, }); diff --git a/apps/api-delegations/src/validation.ts b/apps/api-delegations/src/validation.ts index 46e39bcc..bbbba45d 100644 --- a/apps/api-delegations/src/validation.ts +++ b/apps/api-delegations/src/validation.ts @@ -63,7 +63,7 @@ export const postDelegationSchema = z.object({ signature: hexSchema, caveats: z.array( z.object({ - enforcerType: typeSchema, + type: typeSchema, enforcer: addressSchema, terms: hexSchema, args: hexSchema, diff --git a/apps/api-universal/package.json b/apps/api-universal/package.json index 4447b0c1..1a12fc4d 100644 --- a/apps/api-universal/package.json +++ b/apps/api-universal/package.json @@ -30,6 +30,7 @@ "delegations-indexer": "workspace:*", "universal-credential-sdk": "workspace:*", "universal-data": "workspace:*", + "universal-types": "workspace:*", "universal-delegations-sdk": "workspace:*", "universal-identity-sdk": "workspace:*", "viem": "^2.21.41", diff --git a/apps/api-universal/src/routes/credit-lines/index.ts b/apps/api-universal/src/routes/credit-lines/index.ts index f1a8f948..60a8e761 100644 --- a/apps/api-universal/src/routes/credit-lines/index.ts +++ b/apps/api-universal/src/routes/credit-lines/index.ts @@ -1,22 +1,20 @@ import { zValidator } from '@hono/zod-validator'; import { Hono } from 'hono'; import { type TokenItem, findToken, getDefaultTokenList } from 'universal-data'; -import { - type DelegationDb, - decodeEnforcerERC20TransferAmount, -} from 'universal-delegations-sdk'; +import { decodeEnforcerERC20TransferAmount } from 'universal-delegations-sdk'; import { type Address, formatUnits } from 'viem'; import { getCredentialsByAddresses } from './utils/get-credentials-by-addresses.js'; import { getIssuedDelegations } from './utils/get-issued-delegations.js'; import { getRedeemedCreditLines } from './utils/get-redeemed-credit-Lines.js'; import { getCreditLineSchema } from './utils/validation.js'; +import type { DelegationWithMetadata } from 'universal-types'; -type DelegationDbWithOnchainData = DelegationDb & { +type DelegationWithOnchainData = DelegationWithMetadata & { isRevoked: boolean; }; type DelegationMetadata = { - data: DelegationDbWithOnchainData; + data: DelegationWithOnchainData; metadata: { available: { amount: string; diff --git a/apps/api-universal/src/utils/calculate-erc20-transfer-amount-enforcer-collection-total.ts b/apps/api-universal/src/utils/calculate-erc20-transfer-amount-enforcer-collection-total.ts index 2d4bf538..25a941f0 100644 --- a/apps/api-universal/src/utils/calculate-erc20-transfer-amount-enforcer-collection-total.ts +++ b/apps/api-universal/src/utils/calculate-erc20-transfer-amount-enforcer-collection-total.ts @@ -1,11 +1,9 @@ -import { - type DelegationDb, - decodeEnforcerERC20TransferAmount, -} from 'universal-delegations-sdk'; +import { decodeEnforcerERC20TransferAmount } from 'universal-delegations-sdk'; +import type { Delegation } from 'universal-types'; import type { Address } from 'viem'; export function calculateERC20TransferAmountEnforcerCollectionTotal( - delegations: DelegationDb[], + delegations: Delegation[], token: Address, ): bigint { return delegations.reduce((acc, delegation) => { diff --git a/apps/delegations-indexer/generated/schema.graphql b/apps/delegations-indexer/generated/schema.graphql index 8461a6c6..c8e0e85a 100644 --- a/apps/delegations-indexer/generated/schema.graphql +++ b/apps/delegations-indexer/generated/schema.graphql @@ -29,7 +29,8 @@ type Query { type delegations { hash: String! chainId: Int! - delegationType: String! + type: String + verifyingContract: String! delegate: String! delegator: String! authority: String! @@ -47,7 +48,7 @@ type caveatsPage { type caveats { index: Int! - enforcerType: String! + type: String enforcer: String! terms: String! args: String! @@ -66,16 +67,16 @@ input caveatsFilter { index_lt: Int index_gte: Int index_lte: Int - enforcerType: String - enforcerType_not: String - enforcerType_in: [String] - enforcerType_not_in: [String] - enforcerType_contains: String - enforcerType_not_contains: String - enforcerType_starts_with: String - enforcerType_ends_with: String - enforcerType_not_starts_with: String - enforcerType_not_ends_with: String + type: String + type_not: String + type_in: [String] + type_not_in: [String] + type_contains: String + type_not_contains: String + type_starts_with: String + type_ends_with: String + type_not_starts_with: String + type_not_ends_with: String enforcer: String enforcer_not: String enforcer_in: [String] @@ -275,16 +276,26 @@ input delegationsFilter { chainId_lt: Int chainId_gte: Int chainId_lte: Int - delegationType: String - delegationType_not: String - delegationType_in: [String] - delegationType_not_in: [String] - delegationType_contains: String - delegationType_not_contains: String - delegationType_starts_with: String - delegationType_ends_with: String - delegationType_not_starts_with: String - delegationType_not_ends_with: String + type: String + type_not: String + type_in: [String] + type_not_in: [String] + type_contains: String + type_not_contains: String + type_starts_with: String + type_ends_with: String + type_not_starts_with: String + type_not_ends_with: String + verifyingContract: String + verifyingContract_not: String + verifyingContract_in: [String] + verifyingContract_not_in: [String] + verifyingContract_contains: String + verifyingContract_not_contains: String + verifyingContract_starts_with: String + verifyingContract_ends_with: String + verifyingContract_not_starts_with: String + verifyingContract_not_ends_with: String delegate: String delegate_not: String delegate_in: [String] diff --git a/apps/delegations-indexer/package.json b/apps/delegations-indexer/package.json index b0af1cee..934eab94 100644 --- a/apps/delegations-indexer/package.json +++ b/apps/delegations-indexer/package.json @@ -22,6 +22,7 @@ "@ponder/core": "^0.7.11", "hono": "^4.5.0", "universal-data": "workspace:*", + "universal-delegations-sdk": "workspace:*", "universal-types": "workspace:*", "viem": "^2.21.3", "zod": "^3.23.8" diff --git a/apps/delegations-indexer/ponder.config.ts b/apps/delegations-indexer/ponder.config.ts index 412c63bd..c47de46f 100644 --- a/apps/delegations-indexer/ponder.config.ts +++ b/apps/delegations-indexer/ponder.config.ts @@ -3,7 +3,7 @@ import { http } from 'viem'; import { delegationManagerAbi, - erc20TransferAmountAbi, + erc20TransferAmountEnforcerAbi, universalDeployments, } from 'universal-data'; import { base, baseSepolia } from 'viem/chains'; @@ -37,7 +37,7 @@ export default createConfig({ }, }, ERC20TransferAmountEnforcer: { - abi: erc20TransferAmountAbi, + abi: erc20TransferAmountEnforcerAbi, network: { base: { address: universalDeployments.ERC20TransferAmountEnforcer, diff --git a/apps/delegations-indexer/ponder.schema.ts b/apps/delegations-indexer/ponder.schema.ts index 9b6b7f88..371688e6 100644 --- a/apps/delegations-indexer/ponder.schema.ts +++ b/apps/delegations-indexer/ponder.schema.ts @@ -1,6 +1,5 @@ import { onchainTable, primaryKey, relations } from '@ponder/core'; import { generateUUID } from './src/utils/uuid'; - // ---------------------------------------------- // Delegations // ---------------------------------------------- @@ -9,7 +8,8 @@ import { generateUUID } from './src/utils/uuid'; export const delegations = onchainTable('delegations', (t) => ({ hash: t.hex().notNull().primaryKey(), chainId: t.integer().notNull(), - delegationType: t.text().notNull(), + type: t.text(), + verifyingContract: t.hex().notNull(), delegate: t.hex().notNull(), delegator: t.hex().notNull(), authority: t.hex().notNull(), @@ -37,7 +37,7 @@ export const caveats = onchainTable( (t) => ({ // index of the caveat in the caveats array of the delegation index: t.integer().notNull(), - enforcerType: t.text().notNull(), + type: t.text(), enforcer: t.hex().notNull(), terms: t.hex().notNull(), args: t.hex().notNull(), diff --git a/apps/delegations-indexer/src/api/credit-lines/index.ts b/apps/delegations-indexer/src/api/credit-lines/index.ts index b47d113e..f6b3a17b 100644 --- a/apps/delegations-indexer/src/api/credit-lines/index.ts +++ b/apps/delegations-indexer/src/api/credit-lines/index.ts @@ -45,10 +45,10 @@ ponder.get( }); const creditLines = redeemerDelegations - .filter((delegation) => delegation.delegationType === 'CreditLine') + .filter((delegation) => delegation?.type === 'CreditLine') .map((delegation) => { const erc20TransferFromCaveat = delegation.caveats.find( - (caveat) => caveat.enforcerType === 'ERC20TransferAmountEnforcer', + (caveat) => caveat.type === 'ERC20TransferAmountEnforcer', ); if (!erc20TransferFromCaveat) { throw new Error('ERC20TransferAmountEnforcer not found'); diff --git a/apps/delegations-indexer/src/event-handlers/delegationManager.ts b/apps/delegations-indexer/src/event-handlers/delegationManager.ts index b904d221..2cba6d48 100644 --- a/apps/delegations-indexer/src/event-handlers/delegationManager.ts +++ b/apps/delegations-indexer/src/event-handlers/delegationManager.ts @@ -2,7 +2,7 @@ import { type Context, ponder } from '@/generated'; import { universalDeployments } from 'universal-data'; import type { Address } from 'viem'; import { type InsertCaveat, caveats, delegations } from '../../ponder.schema'; -import { getDelegationHash } from '../utils/delegation/get-delegation-hash'; +import { getDelegationHash } from 'universal-delegations-sdk'; import type { Delegation, DelegationCaveatWithMetadata } from 'universal-types'; function getEnforcerType(enforcer: Address): string { @@ -15,15 +15,15 @@ function getEnforcerType(enforcer: Address): string { return 'unknown'; } -function getDelegationType(caveats: DelegationCaveatWithMetadata[]): string { +function getDelegationType( + caveats: DelegationCaveatWithMetadata[], +): string | null { if ( - caveats.some( - (caveat) => caveat.enforcerType === 'ERC20TransferAmountEnforcer', - ) + caveats.some((caveat) => caveat?.type === 'ERC20TransferAmountEnforcer') ) { return 'CreditLine'; } - return 'unknown'; + return null; } async function updateDelegation({ @@ -37,18 +37,15 @@ async function updateDelegation({ }) { const delegationHash = getDelegationHash({ ...delegation, - chainId: context.network.chainId, caveats: delegation.caveats.slice(), }); - const formattedCaveats: InsertCaveat[] = delegation.caveats.map( - (caveat, index) => ({ - ...caveat, - index, - enforcerType: getEnforcerType(caveat.enforcer), - delegationHash, - }), - ); + const formattedCaveats = delegation.caveats.map((caveat, index) => ({ + ...caveat, + index, + type: getEnforcerType(caveat.enforcer), + delegationHash, + })) satisfies InsertCaveat[]; // Insert delegation if not already present await context.db @@ -56,14 +53,15 @@ async function updateDelegation({ .values({ hash: delegationHash, enabled, + verifyingContract: universalDeployments.DelegationManager, chainId: context.network.chainId, - delegationType: getDelegationType(formattedCaveats), + type: getDelegationType(formattedCaveats), ...delegation, }) .onConflictDoUpdate({ enabled, chainId: context.network.chainId, - delegationType: getDelegationType(formattedCaveats), + type: getDelegationType(formattedCaveats), ...delegation, }); diff --git a/apps/delegations-indexer/src/utils/delegation/constants.ts b/apps/delegations-indexer/src/utils/delegation/constants.ts deleted file mode 100644 index d8f5c9cf..00000000 --- a/apps/delegations-indexer/src/utils/delegation/constants.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { type Hex, keccak256, toHex } from 'viem'; - -// Delegation constants -export const ANY_DELEGATE = '0x0000000000000000000000000000000000000a11'; -export const ROOT_AUTHORITY = - '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; - -// Execution Modes -export const BATCH_EXECUTION_MODE = [ - '0x0100000000000000000000000000000000000000000000000000000000000000' as Hex, -]; -export const SINGLE_EXECUTION_MODE = [ - '0x0000000000000000000000000000000000000000000000000000000000000000' as Hex, -]; -export const EMPTY_ARGS = '0x'; -export const EMPTY_SIGNATURE = '0x'; -export const SALT = BigInt(0); - -export const CAVEAT_TYPEHASH = keccak256( - toHex('Caveat(address enforcer,bytes terms)'), -); - -export const DELEGATION_TYPEHASH = keccak256( - toHex( - 'Delegation(address delegate,address delegator,bytes32 authority,Caveat[] caveats,uint256 salt)Caveat(address enforcer,bytes terms)', - ), -); diff --git a/apps/delegations-indexer/src/utils/delegation/enforcers/erc20-transfer-amount-enforcer.ts b/apps/delegations-indexer/src/utils/delegation/enforcers/erc20-transfer-amount-enforcer.ts index 0ebba9cf..60133eb5 100644 --- a/apps/delegations-indexer/src/utils/delegation/enforcers/erc20-transfer-amount-enforcer.ts +++ b/apps/delegations-indexer/src/utils/delegation/enforcers/erc20-transfer-amount-enforcer.ts @@ -1,4 +1,4 @@ -import { erc20TransferAmountAbi } from 'universal-data'; +import { erc20TransferAmountEnforcerAbi } from 'universal-data'; import { type Address, type Hex, @@ -31,7 +31,7 @@ export function encodeErc20TransferAmountEvent({ }: EncodeErc20TransferAmountEventParams): EncodeErc20TransferAmountEventReturnType { return encodeAbiParameters( getAbiItem({ - abi: erc20TransferAmountAbi, + abi: erc20TransferAmountEnforcerAbi, name: 'IncreasedSpentMap', }).inputs, [sender, redeemer, delegationHash, limit, spent], @@ -47,7 +47,7 @@ export function decodeErc20TransferAmountEvent( ): DecodeErc20TransferAmountEventReturnType { const [sender, redeemer, delegationHash, limit, spent] = decodeAbiParameters( getAbiItem({ - abi: erc20TransferAmountAbi, + abi: erc20TransferAmountEnforcerAbi, name: 'IncreasedSpentMap', }).inputs, encoded, diff --git a/apps/delegations-indexer/src/utils/delegation/get-delegation-hash.ts b/apps/delegations-indexer/src/utils/delegation/get-delegation-hash.ts deleted file mode 100644 index 2bfbe1e0..00000000 --- a/apps/delegations-indexer/src/utils/delegation/get-delegation-hash.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { concatHex, encodeAbiParameters, keccak256 } from 'viem'; - -import { CAVEAT_TYPEHASH, DELEGATION_TYPEHASH } from './constants.js'; -import type { Delegation, DelegationCaveat } from 'universal-types'; - -// Implementation of: https://github.com/MetaMask/delegation-framework/blob/main/src/libraries/EncoderLib.sol#L18 -export function getDelegationHash(delegation: Delegation) { - const encodedCaveatArrayPacketHash = getCaveatArrayPacketHash( - delegation.caveats, - ); - const encoded = encodeAbiParameters( - [ - { name: 'delegationTypeHash', type: 'bytes32' }, - { name: 'delegate', type: 'address' }, - { name: 'delegator', type: 'address' }, - { name: 'authority', type: 'bytes32' }, - { name: 'encodedCaveatArrayPacketHash', type: 'bytes32' }, - { name: 'salt', type: 'uint256' }, - ], - [ - DELEGATION_TYPEHASH, - delegation.delegate, - delegation.delegator, - delegation.authority, - encodedCaveatArrayPacketHash, - BigInt(delegation.salt), - ], - ); - - return keccak256(encoded); -} - -export function getCaveatArrayPacketHash(caveats: DelegationCaveat[]) { - const caveatPacketHashes = caveats.map((caveat) => - getCaveatPacketHash(caveat), - ); - // Concatenate the bytes32 hashes directly - const concatenatedHashes = concatHex(caveatPacketHashes); - return keccak256(concatenatedHashes); -} - -export function getCaveatPacketHash(caveat: DelegationCaveat) { - const encoded = encodeAbiParameters( - [ - { name: 'caveatTypeHash', type: 'bytes32' }, - { name: 'enforcer', type: 'address' }, - { name: 'terms', type: 'bytes32' }, - ], - [CAVEAT_TYPEHASH, caveat.enforcer, keccak256(caveat.terms)], - ); - - return keccak256(encoded); -} diff --git a/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/card-payment-basic.tsx b/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/card-payment-basic.tsx index 7145935e..762a33b4 100644 --- a/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/card-payment-basic.tsx +++ b/apps/popup/app/(site)/sign/eth-sign-typed-data-v-4/components/card-payment-basic.tsx @@ -1,5 +1,5 @@ import { RowBasic } from '@/components/row-basic'; -import type { Delegation } from '@/lib/delegation-framework/types'; +import type { Delegation } from 'universal-types'; import { cn } from '@/lib/utils'; import { useMemo } from 'react'; import { findToken, getDefaultTokenList } from 'universal-data'; 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 382de631..0fe084fa 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,4 +1,4 @@ -import type { Delegation } from '@/lib/delegation-framework/types'; +import type { Delegation } from 'universal-types'; import { cn } from '@/lib/utils'; import { useMemo } from 'react'; import { universalDeployments } from 'universal-data'; 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 be16adac..9dae601b 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,7 +2,7 @@ import { RowBasic } from '@/components/row-basic'; import { Toggle } from '@/components/toggle'; import { Button } from '@/components/ui/button'; -import type { Delegation } from '@/lib/delegation-framework/types'; +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'; diff --git a/apps/popup/package.json b/apps/popup/package.json index d49a486e..43d51b24 100644 --- a/apps/popup/package.json +++ b/apps/popup/package.json @@ -53,6 +53,7 @@ "universal-wallet-connector": "workspace:*", "universal-wallet-sdk": "workspace:*", "universal-sdk": "workspace:*", + "universal-types": "workspace:*", "universal-wallet-ui": "workspace:*", "usehooks-ts": "^3.1.0", "viem": "^2.21.6", diff --git a/apps/popup/src/components/delegation-details-sheet.tsx b/apps/popup/src/components/delegation-details-sheet.tsx index eab2da73..9242d29c 100644 --- a/apps/popup/src/components/delegation-details-sheet.tsx +++ b/apps/popup/src/components/delegation-details-sheet.tsx @@ -10,7 +10,7 @@ import { import { formatNumber } from '@/lib/utils'; import type * as React from 'react'; import { useState } from 'react'; -import type { DelegationWithMetadata, SocialCredential } from 'universal-data'; +import type { CreditLineWithMetadata, SocialCredential } from 'universal-data'; import { DebitCard } from 'universal-wallet-ui'; import { AccountSocialCredentialBadge } from './identity/account-social-credential-badge'; import { Address } from './onchain/address'; @@ -20,7 +20,7 @@ import { Card } from './ui/card'; type DelegationDetailsSheet = React.HTMLAttributes & { credentials: SocialCredential[]; - delegation: DelegationWithMetadata; + delegation: CreditLineWithMetadata; }; export const DelegationDetailsSheet = ({ @@ -98,11 +98,11 @@ export const DelegationDetailsSheet = ({

Technical Details

- {delegation.data.caveats.map((caveat) => { + {delegation.data.caveats.map((caveat, index) => { return ( ); diff --git a/apps/popup/src/components/delegations-management-sheet.tsx b/apps/popup/src/components/delegations-management-sheet.tsx index 296a86cf..ca51c2a2 100644 --- a/apps/popup/src/components/delegations-management-sheet.tsx +++ b/apps/popup/src/components/delegations-management-sheet.tsx @@ -12,18 +12,18 @@ import Image from 'next/image'; import { useEffect, useMemo, useState } from 'react'; import type { DelegationExecutions, - DelegationWithMetadata, + CreditLineWithMetadata, SocialCredential, } from 'universal-data'; -import type { DelegationDb } from 'universal-delegations-sdk'; import { useGetCreditLines } from 'universal-sdk'; -import { type Address, parseUnits } from 'viem'; +import { type Address, type Hex, parseUnits } from 'viem'; import { DelegationDetailsSheet } from './delegation-details-sheet'; import { AccountSocialCredentialWeightedBadge } from './identity/account-social-credential-weighted-badge'; import { Toggle } from './toggle'; import { Button } from './ui/button'; import { Card, CardFooter, CardHeader } from './ui/card'; import { Input } from './ui/input'; +import type { DelegationWithMetadata } from 'universal-types'; export type DelegationsManagementSheet = Omit< React.HTMLAttributes, @@ -67,9 +67,7 @@ export const DelegationsManagementSheet = ({ } }, [isOpen]); - const handleDisableDelegation = ( - hash: DelegationWithMetadata['data']['hash'], - ) => { + const handleDisableDelegation = (hash: Hex) => { setDelegationExecutions( delegationExecutions.filter( (delegationExecution) => delegationExecution.delegation.hash !== hash, @@ -77,10 +75,7 @@ export const DelegationsManagementSheet = ({ ); }; - const handleDelegationAmountUpdate = ( - hash: DelegationWithMetadata['data']['hash'], - amountFormatted: string, - ) => { + const handleDelegationAmountUpdate = (hash: Hex, amountFormatted: string) => { setDelegationExecutions( delegationExecutions.map((delegationExecution) => { if (delegationExecution.delegation.hash === hash) { @@ -102,7 +97,7 @@ export const DelegationsManagementSheet = ({ }; const handleEnableDelegation = ( - delegationExecution: DelegationWithMetadata, + delegationExecution: CreditLineWithMetadata, ) => { setDelegationExecutions([ ...delegationExecutions, @@ -199,14 +194,11 @@ type CreditDelegationCard = Omit< 'handleEnableDelegation' > & { delegatorAccountSocialCredentials: SocialCredential[]; - delegation: DelegationDb; - delegationWithMetadata: DelegationWithMetadata; - handleEnableDelegation: (delegation: DelegationWithMetadata) => void; - handleDisableDelegation: (hash: DelegationDb['hash']) => void; - handleDelegationAmountUpdate: ( - hash: DelegationDb['hash'], - amountFormatted: string, - ) => void; + delegation: DelegationWithMetadata; + delegationWithMetadata: CreditLineWithMetadata; + handleEnableDelegation: (delegation: CreditLineWithMetadata) => void; + handleDisableDelegation: (hash: Hex) => void; + handleDelegationAmountUpdate: (hash: Hex, amountFormatted: string) => void; toggleIsOpen: (isOpen: boolean) => void; }; diff --git a/apps/popup/src/lib/account-abstraction/account-adapters/to-universal-account.ts b/apps/popup/src/lib/account-abstraction/account-adapters/to-universal-account.ts index aebc9d68..f6091d9a 100644 --- a/apps/popup/src/lib/account-abstraction/account-adapters/to-universal-account.ts +++ b/apps/popup/src/lib/account-abstraction/account-adapters/to-universal-account.ts @@ -35,8 +35,8 @@ import { type WebAuthnData, parseSignature as parseP256Signature, } from 'webauthn-p256'; -import { BATCH_EXECUTION_MODE } from '../../delegation-framework/constants'; -import { encodeBatchExecution } from '../../delegation-framework/execution-lib/encode-batch-execution'; +import { BATCH_EXECUTION_MODE } from 'universal-data'; +import { encodeBatchExecution } from 'universal-delegations-sdk'; import { getPackedUserOperationTypedDataHash, getUserOperationHash, @@ -165,7 +165,7 @@ export async function toUniversalAccount( return encodeFunctionData({ abi: universalWalletAbi, functionName: 'execute', - args: [BATCH_EXECUTION_MODE, batchExecutionCalldata], + args: [BATCH_EXECUTION_MODE[0], batchExecutionCalldata], }); } diff --git a/apps/popup/src/lib/delegation-framework/abis.ts b/apps/popup/src/lib/delegation-framework/abis.ts deleted file mode 100644 index 242fa7da..00000000 --- a/apps/popup/src/lib/delegation-framework/abis.ts +++ /dev/null @@ -1,629 +0,0 @@ -export const delegationManagerAbi = [ - { - type: 'constructor', - inputs: [{ name: '_owner', type: 'address', internalType: 'address' }], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'ANY_DELEGATE', - inputs: [], - outputs: [{ name: '', type: 'address', internalType: 'address' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'DOMAIN_VERSION', - inputs: [], - outputs: [{ name: '', type: 'string', internalType: 'string' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'NAME', - inputs: [], - outputs: [{ name: '', type: 'string', internalType: 'string' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'ROOT_AUTHORITY', - inputs: [], - outputs: [{ name: '', type: 'bytes32', internalType: 'bytes32' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'VERSION', - inputs: [], - outputs: [{ name: '', type: 'string', internalType: 'string' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'acceptOwnership', - inputs: [], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'disableDelegation', - inputs: [ - { - 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' }, - ], - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'disabledDelegations', - inputs: [ - { - name: 'delegationHash', - type: 'bytes32', - internalType: 'bytes32', - }, - ], - outputs: [{ name: 'isDisabled', type: 'bool', internalType: 'bool' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'eip712Domain', - inputs: [], - outputs: [ - { name: 'fields', type: 'bytes1', internalType: 'bytes1' }, - { name: 'name', type: 'string', internalType: 'string' }, - { name: 'version', type: 'string', internalType: 'string' }, - { name: 'chainId', type: 'uint256', internalType: 'uint256' }, - { - name: 'verifyingContract', - type: 'address', - internalType: 'address', - }, - { name: 'salt', type: 'bytes32', internalType: 'bytes32' }, - { - name: 'extensions', - type: 'uint256[]', - internalType: 'uint256[]', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'enableDelegation', - inputs: [ - { - 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' }, - ], - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'getDelegationHash', - inputs: [ - { - name: '_input', - 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' }, - ], - }, - ], - outputs: [{ name: '', type: 'bytes32', internalType: 'bytes32' }], - stateMutability: 'pure', - }, - { - type: 'function', - name: 'getDomainHash', - inputs: [], - outputs: [{ name: '', type: 'bytes32', internalType: 'bytes32' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'owner', - inputs: [], - outputs: [{ name: '', type: 'address', internalType: 'address' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'pause', - inputs: [], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'paused', - inputs: [], - outputs: [{ name: '', type: 'bool', internalType: 'bool' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'pendingOwner', - inputs: [], - outputs: [{ name: '', type: 'address', internalType: 'address' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'redeemDelegations', - inputs: [ - { - name: '_permissionContexts', - type: 'bytes[]', - internalType: 'bytes[]', - }, - { name: '_modes', type: 'bytes32[]', internalType: 'ModeCode[]' }, - { - name: '_executionCallDatas', - type: 'bytes[]', - internalType: 'bytes[]', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'renounceOwnership', - inputs: [], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'transferOwnership', - inputs: [{ name: 'newOwner', type: 'address', internalType: 'address' }], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'unpause', - inputs: [], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'event', - name: 'DisabledDelegation', - inputs: [ - { - name: 'delegationHash', - type: 'bytes32', - indexed: true, - internalType: 'bytes32', - }, - { - name: 'delegator', - type: 'address', - indexed: true, - internalType: 'address', - }, - { - name: 'delegate', - type: 'address', - indexed: true, - internalType: 'address', - }, - { - name: 'delegation', - type: 'tuple', - indexed: false, - 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' }, - ], - }, - ], - anonymous: false, - }, - { - type: 'event', - name: 'EIP712DomainChanged', - inputs: [], - anonymous: false, - }, - { - type: 'event', - name: 'EnabledDelegation', - inputs: [ - { - name: 'delegationHash', - type: 'bytes32', - indexed: true, - internalType: 'bytes32', - }, - { - name: 'delegator', - type: 'address', - indexed: true, - internalType: 'address', - }, - { - name: 'delegate', - type: 'address', - indexed: true, - internalType: 'address', - }, - { - name: 'delegation', - type: 'tuple', - indexed: false, - 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' }, - ], - }, - ], - anonymous: false, - }, - { - type: 'event', - name: 'OwnershipTransferStarted', - inputs: [ - { - name: 'previousOwner', - type: 'address', - indexed: true, - internalType: 'address', - }, - { - name: 'newOwner', - type: 'address', - indexed: true, - internalType: 'address', - }, - ], - anonymous: false, - }, - { - type: 'event', - name: 'OwnershipTransferred', - inputs: [ - { - name: 'previousOwner', - type: 'address', - indexed: true, - internalType: 'address', - }, - { - name: 'newOwner', - type: 'address', - indexed: true, - internalType: 'address', - }, - ], - anonymous: false, - }, - { - type: 'event', - name: 'Paused', - inputs: [ - { - name: 'account', - type: 'address', - indexed: false, - internalType: 'address', - }, - ], - anonymous: false, - }, - { - type: 'event', - name: 'RedeemedDelegation', - inputs: [ - { - name: 'rootDelegator', - type: 'address', - indexed: true, - internalType: 'address', - }, - { - name: 'redeemer', - type: 'address', - indexed: true, - internalType: 'address', - }, - { - name: 'delegation', - type: 'tuple', - indexed: false, - 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' }, - ], - }, - ], - anonymous: false, - }, - { - type: 'event', - name: 'SetDomain', - inputs: [ - { - name: 'domainHash', - type: 'bytes32', - indexed: true, - internalType: 'bytes32', - }, - { - name: 'name', - type: 'string', - indexed: false, - internalType: 'string', - }, - { - name: 'domainVersion', - type: 'string', - indexed: false, - internalType: 'string', - }, - { - name: 'chainId', - type: 'uint256', - indexed: false, - internalType: 'uint256', - }, - { - name: 'contractAddress', - type: 'address', - indexed: true, - internalType: 'address', - }, - ], - anonymous: false, - }, - { - type: 'event', - name: 'Unpaused', - inputs: [ - { - name: 'account', - type: 'address', - indexed: false, - internalType: 'address', - }, - ], - anonymous: false, - }, - { type: 'error', name: 'AlreadyDisabled', inputs: [] }, - { type: 'error', name: 'AlreadyEnabled', inputs: [] }, - { type: 'error', name: 'BatchDataLengthMismatch', inputs: [] }, - { type: 'error', name: 'CannotUseADisabledDelegation', inputs: [] }, - { type: 'error', name: 'ECDSAInvalidSignature', inputs: [] }, - { - type: 'error', - name: 'ECDSAInvalidSignatureLength', - inputs: [{ name: 'length', type: 'uint256', internalType: 'uint256' }], - }, - { - type: 'error', - name: 'ECDSAInvalidSignatureS', - inputs: [{ name: 's', type: 'bytes32', internalType: 'bytes32' }], - }, - { type: 'error', name: 'EmptySignature', inputs: [] }, - { type: 'error', name: 'EnforcedPause', inputs: [] }, - { type: 'error', name: 'ExpectedPause', inputs: [] }, - { type: 'error', name: 'InvalidAuthority', inputs: [] }, - { type: 'error', name: 'InvalidDelegate', inputs: [] }, - { type: 'error', name: 'InvalidDelegator', inputs: [] }, - { type: 'error', name: 'InvalidShortString', inputs: [] }, - { type: 'error', name: 'InvalidSignature', inputs: [] }, - { - type: 'error', - name: 'OwnableInvalidOwner', - inputs: [{ name: 'owner', type: 'address', internalType: 'address' }], - }, - { - type: 'error', - name: 'OwnableUnauthorizedAccount', - inputs: [{ name: 'account', type: 'address', internalType: 'address' }], - }, - { - type: 'error', - name: 'StringTooLong', - inputs: [{ name: 'str', type: 'string', internalType: 'string' }], - }, -] as const; diff --git a/apps/popup/src/lib/delegation-framework/constants.ts b/apps/popup/src/lib/delegation-framework/constants.ts deleted file mode 100644 index 0787dedc..00000000 --- a/apps/popup/src/lib/delegation-framework/constants.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { keccak256, toHex } from 'viem'; - -// Delegation constants -export const ANY_DELEGATE = '0x0000000000000000000000000000000000000a11'; -export const ROOT_AUTHORITY = - '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; - -// Execution Modes -export const BATCH_EXECUTION_MODE = - '0x0100000000000000000000000000000000000000000000000000000000000000'; -export const SINGLE_EXECUTION_MODE = - '0x0000000000000000000000000000000000000000000000000000000000000000'; - -export const EMPTY_ARGS = '0x'; -export const EMPTY_SIGNATURE = '0x'; -export const SALT = BigInt(0); - -export const CAVEAT_TYPEHASH = keccak256( - toHex('Caveat(address enforcer,bytes terms)'), -); - -export const DELEGATION_TYPEHASH = keccak256( - toHex( - 'Delegation(address delegate,address delegator,bytes32 authority,Caveat[] caveats,uint256 salt)Caveat(address enforcer,bytes terms)', - ), -); diff --git a/apps/popup/src/lib/delegation-framework/delegation/encode-delegations.ts b/apps/popup/src/lib/delegation-framework/delegation/encode-delegations.ts deleted file mode 100644 index b6810b2a..00000000 --- a/apps/popup/src/lib/delegation-framework/delegation/encode-delegations.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { type Hex, encodeAbiParameters } from 'viem'; - -import type { Delegation } from '../types'; - -export function encodeDelegations(delegations: 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' }, - ], - }, - ], - [delegations], - ); -} diff --git a/apps/popup/src/lib/delegation-framework/enforcers/erc20-transfer-amount/format-erc20-transfer-enforcer-calls.ts b/apps/popup/src/lib/delegation-framework/enforcers/erc20-transfer-amount/format-erc20-transfer-enforcer-calls.ts index c92091b4..f94ae5bc 100644 --- a/apps/popup/src/lib/delegation-framework/enforcers/erc20-transfer-amount/format-erc20-transfer-enforcer-calls.ts +++ b/apps/popup/src/lib/delegation-framework/enforcers/erc20-transfer-amount/format-erc20-transfer-enforcer-calls.ts @@ -1,24 +1,24 @@ -import { universalDeployments } from 'universal-data'; import { - type Delegation, - type Execution, + universalDeployments, + delegationManagerAbi, SINGLE_EXECUTION_MODE, +} from 'universal-data'; +import { decodeEnforcerERC20TransferAmount, - delegationManagerAbi, encodeDelegations, encodeSingleExecution, } from 'universal-delegations-sdk'; -import { - type CallParameters, - type Hex, - encodeFunctionData, - erc20Abi, -} from 'viem'; +import type { + DelegationWithMetadata, + Delegation, + DelegationExecution, +} from 'universal-types'; + +import { type CallParameters, encodeFunctionData, erc20Abi } from 'viem'; -export type DelegationWithHash = Delegation & { hash: Hex }; export type DelegationWithAmount = Delegation & { amount: bigint }; export type Erc20TransferEnforcerRedemption = { - delegation: DelegationWithHash; + delegation: DelegationWithMetadata; amount: bigint; }; @@ -31,7 +31,7 @@ function encodeErc20TransferEnforcerCalldata(delegation: DelegationWithAmount) { const [token] = decodeEnforcerERC20TransferAmount(caveat.terms); const permissionContexts = [encodeDelegations([delegation])]; - const execution: Execution = { + const execution: DelegationExecution = { value: 0n, target: token, calldata: encodeFunctionData({ diff --git a/apps/popup/src/lib/delegation-framework/execution-lib/encode-batch-execution.ts b/apps/popup/src/lib/delegation-framework/execution-lib/encode-batch-execution.ts deleted file mode 100644 index 092a84cc..00000000 --- a/apps/popup/src/lib/delegation-framework/execution-lib/encode-batch-execution.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { type Hex, encodeAbiParameters } from 'viem'; - -import type { Execution } from '../types'; - -// Typescript implementation of: https://github.com/erc7579/erc7579-implementation/blob/main/src/lib/ExecutionLib.sol#L33-L39 -export function encodeBatchExecution(executions: Execution[]): Hex { - return encodeAbiParameters( - [ - { - type: 'tuple[]', - components: [ - { - type: 'address', - name: 'target', - }, - { - type: 'uint256', - name: 'value', - }, - { - type: 'bytes', - name: 'calldata', - }, - ], - }, - ], - [executions], - ); -} diff --git a/apps/popup/src/lib/delegation-framework/types.ts b/apps/popup/src/lib/delegation-framework/types.ts deleted file mode 100644 index 16dcda06..00000000 --- a/apps/popup/src/lib/delegation-framework/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { Address, Hex } from 'viem'; - -// From https://github.com/erc7579/erc7579-implementation/blob/main/src/interfaces/IERC7579Account.sol#L6-L10 -export type Execution = { - target: Address; - value: bigint; - calldata: Hex; -}; - -// From https://github.com/MetaMask/delegation-framework/blob/main/src/utils/Types.sol#L38-L42 -export type Caveat = { - enforcer: Address; - // Terms and args are bytes with different encodings by enforcer - terms: Hex; - args: Hex; -}; - -// From https://github.com/MetaMask/delegation-framework/blob/main/src/utils/Types.sol#L24-L31 -export type Delegation = { - delegate: Address; - delegator: Address; - authority: Hex; - caveats: Caveat[]; - salt: bigint; - signature: Hex; -}; diff --git a/packages/universal-data/package.json b/packages/universal-data/package.json index d495303c..826b2f32 100644 --- a/packages/universal-data/package.json +++ b/packages/universal-data/package.json @@ -42,6 +42,7 @@ } }, "dependencies": { - "universal-wallet-sdk": "workspace:*" + "universal-wallet-sdk": "workspace:*", + "universal-types": "workspace:*" } } diff --git a/packages/universal-data/src/abis/erc20-transfer-amount-abi.ts b/packages/universal-data/src/abis/erc20-transfer-amount-enforcer-abi.ts similarity index 98% rename from packages/universal-data/src/abis/erc20-transfer-amount-abi.ts rename to packages/universal-data/src/abis/erc20-transfer-amount-enforcer-abi.ts index 680cb6f8..00ca32a4 100644 --- a/packages/universal-data/src/abis/erc20-transfer-amount-abi.ts +++ b/packages/universal-data/src/abis/erc20-transfer-amount-enforcer-abi.ts @@ -1,4 +1,4 @@ -export const erc20TransferAmountAbi = [ +export const erc20TransferAmountEnforcerAbi = [ { type: 'function', name: 'afterAllHook', diff --git a/packages/universal-data/src/exports/index.ts b/packages/universal-data/src/exports/index.ts index 6324c135..51778abb 100644 --- a/packages/universal-data/src/exports/index.ts +++ b/packages/universal-data/src/exports/index.ts @@ -1,5 +1,5 @@ export { delegationManagerAbi } from '../abis/delegation-manager-abi.js'; -export { erc20TransferAmountAbi } from '../abis/erc20-transfer-amount-abi.js'; +export { erc20TransferAmountEnforcerAbi } from '../abis/erc20-transfer-amount-enforcer-abi.js'; export { universalDocumentAbi } from '../abis/universal-document-abi.js'; export { universalResolverAbi } from '../abis/universal-resolver-abi.js'; export { universalDeployments } from '../deployments.js'; @@ -28,7 +28,7 @@ export { } from '../chains.js'; export type { DelegationExecutions, - DelegationWithMetadata, + CreditLineWithMetadata, SocialCredential, Token, TokenItem, diff --git a/packages/universal-data/src/types.ts b/packages/universal-data/src/types.ts index 1d2eda75..7a2d7f91 100644 --- a/packages/universal-data/src/types.ts +++ b/packages/universal-data/src/types.ts @@ -1,25 +1,4 @@ -import type { Address, Hex } from 'viem'; - -type DelegationDb = { - hash: Hex; - verifyingContract: Address; - type: string; - delegator: Address; - chainId: number; - delegate: Address; - authority: Hex; - salt: bigint; - signature: Hex; - isValid: boolean; - caveats: { - id: number; - enforcerType: string; - enforcer: Address; - terms: Hex; - args: Hex; - delegationHash: Hex; - }[]; -}; +import type { DelegationWithMetadata } from 'universal-types'; export type Token = { address: string; @@ -91,7 +70,7 @@ export type SocialCredential = { }; export type DelegationExecutions = { - delegation: DelegationDb; + delegation: DelegationWithMetadata; execution: { hash: string; amount: bigint; @@ -108,8 +87,8 @@ export type DelegationExecutions = { }; }; -export type DelegationWithMetadata = { - data: DelegationDb; +export type CreditLineWithMetadata = { + data: DelegationWithMetadata; metadata: { available: { amount: string; diff --git a/packages/universal-delegations-sdk/package.json b/packages/universal-delegations-sdk/package.json index 8957937f..04c73f69 100644 --- a/packages/universal-delegations-sdk/package.json +++ b/packages/universal-delegations-sdk/package.json @@ -39,6 +39,7 @@ "dependencies": { "api-delegations": "workspace:*", "hono": "^4.6.8", - "universal-data": "workspace:*" + "universal-data": "workspace:*", + "universal-types": "workspace:*" } } diff --git a/packages/universal-delegations-sdk/src/actions/core/use-delegation-execute.ts b/packages/universal-delegations-sdk/src/actions/core/use-delegation-execute.ts index cd6e3b93..cd5961a4 100644 --- a/packages/universal-delegations-sdk/src/actions/core/use-delegation-execute.ts +++ b/packages/universal-delegations-sdk/src/actions/core/use-delegation-execute.ts @@ -1,31 +1,29 @@ 'use client'; import { useWriteContract } from 'wagmi'; -import { delegationManagerAbi } from '../../abis/delegation-manager-abi.js'; -import { encodeDelegations } from '../../delegation/encode-delegations.js'; +import { delegationManagerAbi, SINGLE_EXECUTION_MODE } from 'universal-data'; +import type { + DelegationWithMetadata, + DelegationExecution, +} from 'universal-types'; -import type { DelegationDb } from 'api-delegations'; -import type { Address } from 'viem'; -import { SINGLE_EXECUTION_MODE } from '../../constants.js'; +import { encodeDelegations } from '../../delegation/encode-delegations.js'; import { encodeSingleExecution } from '../../execution/encode-single-execution.js'; -import type { Delegation, Execution } from '../../types.js'; export function useDelegationExecute() { const { writeContract } = useWriteContract(); return ({ - delegationManager, delegation, executions, }: { - delegationManager: Address; - delegation: Delegation | DelegationDb; - executions: Execution; + delegation: DelegationWithMetadata; + executions: DelegationExecution; }) => { const permissionContext = [encodeDelegations([delegation])]; const executionCallData = [encodeSingleExecution(executions)]; writeContract({ abi: delegationManagerAbi, - address: delegationManager, + address: delegation.verifyingContract, functionName: 'redeemDelegations', args: [permissionContext, SINGLE_EXECUTION_MODE, executionCallData], }); diff --git a/packages/universal-delegations-sdk/src/actions/core/use-delegation-status.ts b/packages/universal-delegations-sdk/src/actions/core/use-delegation-status.ts index 086603bf..7fa39f93 100644 --- a/packages/universal-delegations-sdk/src/actions/core/use-delegation-status.ts +++ b/packages/universal-delegations-sdk/src/actions/core/use-delegation-status.ts @@ -1,26 +1,24 @@ 'use client'; -import type { DelegationDb } from 'api-delegations'; -import type { Address } from 'viem'; + import { useReadContract } from 'wagmi'; -import { delegationManagerAbi } from '../../abis/delegation-manager-abi.js'; +import { delegationManagerAbi } from 'universal-data'; import { getDelegationHash } from '../../delegation/get-delegation-hash.js'; -import type { Delegation } from '../../types.js'; + +import type { DelegationWithMetadata } from 'universal-types'; export function useDelegationStatus({ - delegationManager, delegation, }: { - delegationManager: Address; - delegation: Delegation | DelegationDb; + delegation: DelegationWithMetadata; }) { const hash = getDelegationHash(delegation); return useReadContract({ abi: delegationManagerAbi, - address: delegationManager, + address: delegation.verifyingContract, functionName: 'disabledDelegations', args: [hash], query: { - enabled: !!delegationManager && !!hash, + enabled: !!delegation && !!hash, refetchInterval: 3000, }, }); diff --git a/packages/universal-delegations-sdk/src/actions/core/use-disable-delegation.ts b/packages/universal-delegations-sdk/src/actions/core/use-disable-delegation.ts index f82c4898..d38fd7a5 100644 --- a/packages/universal-delegations-sdk/src/actions/core/use-disable-delegation.ts +++ b/packages/universal-delegations-sdk/src/actions/core/use-disable-delegation.ts @@ -1,26 +1,39 @@ 'use client'; -import type { DelegationDb } from 'api-delegations'; -import type { Address } from 'viem'; + import { useWriteContract } from 'wagmi'; -import { delegationManagerAbi } from '../../abis/delegation-manager-abi.js'; -import type { Delegation } from '../../types.js'; +import { delegationManagerAbi } from 'universal-data'; +import type { DelegationWithMetadata } from 'universal-types'; export function useDisableDelegation({ - delegationManager, delegation, }: { - delegationManager: Address; - delegation: Delegation | DelegationDb; + delegation: DelegationWithMetadata; }) { const { writeContract, ...rest } = useWriteContract(); const disable = () => { - if (!delegationManager || !delegation) return; + if (!delegation) return; + + const { authority, caveats, delegate, delegator, salt, signature } = + delegation; writeContract({ abi: delegationManagerAbi, - address: delegationManager, + address: delegation.verifyingContract, functionName: 'disableDelegation', - args: [delegation as Delegation], + args: [ + { + authority, + delegate, + delegator, + salt, + signature, + caveats: caveats.map(({ enforcer, terms, args }) => ({ + enforcer, + terms, + args, + })), + }, + ], }); }; diff --git a/packages/universal-delegations-sdk/src/actions/core/use-enable-delegation.ts b/packages/universal-delegations-sdk/src/actions/core/use-enable-delegation.ts index 89adea52..5d409bdf 100644 --- a/packages/universal-delegations-sdk/src/actions/core/use-enable-delegation.ts +++ b/packages/universal-delegations-sdk/src/actions/core/use-enable-delegation.ts @@ -1,26 +1,40 @@ 'use client'; -import type { DelegationDb } from 'api-delegations'; -import type { Address } from 'viem'; + import { useWriteContract } from 'wagmi'; -import { delegationManagerAbi } from '../../abis/delegation-manager-abi.js'; -import type { Delegation } from '../../types.js'; +import { delegationManagerAbi } from 'universal-data'; + +import type { DelegationWithMetadata } from 'universal-types'; export function useEnableDelegation({ - delegationManager, delegation, }: { - delegationManager: Address; - delegation: Delegation | DelegationDb; + delegation: DelegationWithMetadata; }) { const { writeContract, ...rest } = useWriteContract(); + const { authority, caveats, delegate, delegator, salt, signature } = + delegation; + const enable = () => { - if (!delegationManager || !delegation) return; + if (!delegation) return; writeContract({ abi: delegationManagerAbi, - address: delegationManager, + address: delegation.verifyingContract, functionName: 'enableDelegation', - args: [delegation as Delegation], + args: [ + { + authority, + delegate, + delegator, + salt, + signature, + caveats: caveats.map(({ enforcer, terms, args }) => ({ + enforcer, + terms, + args, + })), + }, + ], }); }; diff --git a/packages/universal-delegations-sdk/src/actions/enforcers/use-erc20-transfer-amount-enforcer.ts b/packages/universal-delegations-sdk/src/actions/enforcers/use-erc20-transfer-amount-enforcer.ts index d2c676b8..966c2b1f 100644 --- a/packages/universal-delegations-sdk/src/actions/enforcers/use-erc20-transfer-amount-enforcer.ts +++ b/packages/universal-delegations-sdk/src/actions/enforcers/use-erc20-transfer-amount-enforcer.ts @@ -1,21 +1,23 @@ 'use client'; -import type { DelegationDb } from 'api-delegations'; + import { useMemo } from 'react'; -import { findToken, getDefaultTokenList } from 'universal-data'; +import { + findToken, + getDefaultTokenList, + erc20TransferAmountEnforcerAbi, +} from 'universal-data'; import { type Address, erc20Abi, formatUnits } from 'viem'; import { usePublicClient, useReadContract } from 'wagmi'; -import { erc20TransferAmountEnforcerAbi } from '../../abis/erc20-transfer-amount-enforcer-abi.js'; import { getDelegationHash } from '../../delegation/get-delegation-hash.js'; import { decodeEnforcerERC20TransferAmount } from '../../enforcers/enforcer-erc20-transfer-amount.js'; +import type { DelegationWithMetadata } from 'universal-types'; export function useErc20TransferAmountEnforcer({ - delegationManager, address, delegation, }: { - delegationManager: Address; address: Address; - delegation: DelegationDb; + delegation: DelegationWithMetadata; }) { const client = usePublicClient(); const hash = getDelegationHash(delegation); @@ -23,7 +25,7 @@ export function useErc20TransferAmountEnforcer({ abi: erc20TransferAmountEnforcerAbi, address: address, functionName: 'spentMap', - args: [delegationManager, hash], + args: [delegation.verifyingContract, hash], query: { refetchInterval: 7000, }, diff --git a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-transfer.ts b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-transfer.ts index d0530f3a..284ec8e0 100644 --- a/packages/universal-delegations-sdk/src/actions/use-sign-erc20-transfer.ts +++ b/packages/universal-delegations-sdk/src/actions/use-sign-erc20-transfer.ts @@ -1,14 +1,13 @@ 'use client'; import { useEffect, useState } from 'react'; -import { universalDeployments } from 'universal-data'; -import type { Address, Hex } from 'viem'; +import { universalDeployments, ROOT_AUTHORITY, SALT } from 'universal-data'; +import type { Address } from 'viem'; import { useChainId, useSignTypedData } from 'wagmi'; import { useInsertDelegation } from '../api/actions/insert-delegation.js'; -import { ROOT_AUTHORITY, SALT } from '../constants.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 type { Delegation } from '../types.js'; +import type { Delegation, DelegationWithMetadata } from 'universal-types'; type SignDelegationParams = { chainId: number; @@ -25,7 +24,7 @@ export function useSignErc20TransferDelegation() { useSignTypedData(); const chainId = useChainId(); const { mutate, ...insertRest } = useInsertDelegation(); - const [delegation, setDelegation] = useState(); + const [delegation, setDelegation] = useState(); function signAndSaveDelegation({ chainId, @@ -36,16 +35,14 @@ export function useSignErc20TransferDelegation() { decimals = 18, amount = '0', }: SignDelegationParams) { - setDelegation({ - chainId: chainId, + const coreDelegation: Delegation = { + authority: ROOT_AUTHORITY, delegate: delegate, delegator: delegator, - authority: ROOT_AUTHORITY, - salt: salt, + salt, signature: '0x', caveats: [ { - enforcerType: 'ERC20TransferAmount', enforcer: universalDeployments.ERC20TransferAmountEnforcer, terms: encodeEnforcerERC20TransferAmount({ token: erc20, @@ -55,6 +52,17 @@ export function useSignErc20TransferDelegation() { args: '0x', }, ], + }; + setDelegation({ + hash: getDelegationHash(coreDelegation), + chainId: chainId, + type: 'DebitAuthorization', + verifyingContract: universalDeployments.DelegationManager, + ...coreDelegation, + caveats: coreDelegation.caveats.map((caveat) => ({ + ...caveat, + type: 'ERC20TransferAmount', + })), }); signTypedData({ @@ -139,38 +147,42 @@ export function useSignErc20TransferDelegation() { ], }, }); - const _delegation = { - signature, - chainId, - delegate, - delegator, + + const _coreDelegation: Delegation = { authority: ROOT_AUTHORITY, - salt: salt, + delegate: delegate, + delegator: delegator, + salt, + signature, caveats: [ { - enforcerType: 'ERC20TransferAmount', enforcer: universalDeployments.ERC20TransferAmountEnforcer, terms: encodeEnforcerERC20TransferAmount({ token: erc20, amount: amount, decimals: decimals, }), - args: '0x' as Hex, + args: '0x', }, ], }; + const _delegation = { + hash: getDelegationHash(_coreDelegation), + chainId: chainId, + type: 'DebitAuthorization', + verifyingContract: universalDeployments.DelegationManager, + ..._coreDelegation, + caveats: _coreDelegation.caveats.map((caveat) => ({ + ...caveat, + type: 'ERC20TransferAmount', + })), + } satisfies DelegationWithMetadata; + setDelegation(_delegation); mutate({ ..._delegation, - verifyingContract: universalDeployments.DelegationManager, - type: 'DebitAuthorization', - signature: signature, salt: salt.toString(), - hash: getDelegationHash({ - ..._delegation, - salt, - }), }); } diff --git a/packages/universal-delegations-sdk/src/constants.ts b/packages/universal-delegations-sdk/src/constants.ts deleted file mode 100644 index 82447c76..00000000 --- a/packages/universal-delegations-sdk/src/constants.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { type Address, type Hex, keccak256, toHex } from 'viem'; - -// Delegation constants -export const ANY_DELEGATE = - '0x0000000000000000000000000000000000000a11' as Address; -export const ROOT_AUTHORITY = - '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' as Hex; - -// Execution Modes -export const BATCH_EXECUTION_MODE = [ - '0x0100000000000000000000000000000000000000000000000000000000000000' as Hex, -]; -export const SINGLE_EXECUTION_MODE = [ - '0x0000000000000000000000000000000000000000000000000000000000000000' as Hex, -]; -export const EMPTY_ARGS = '0x'; -export const EMPTY_SIGNATURE = '0x'; -export const SALT = BigInt(0); - -export const CAVEAT_TYPEHASH = keccak256( - toHex('Caveat(address enforcer,bytes terms)'), -); - -export const DELEGATION_TYPEHASH = keccak256( - toHex( - 'Delegation(address delegate,address delegator,bytes32 authority,Caveat[] caveats,uint256 salt)Caveat(address enforcer,bytes terms)', - ), -); diff --git a/packages/universal-delegations-sdk/src/delegation/encode-delegations.ts b/packages/universal-delegations-sdk/src/delegation/encode-delegations.ts index 0429e49e..7241a204 100644 --- a/packages/universal-delegations-sdk/src/delegation/encode-delegations.ts +++ b/packages/universal-delegations-sdk/src/delegation/encode-delegations.ts @@ -1,11 +1,8 @@ import { type Hex, encodeAbiParameters } from 'viem'; -import type { DelegationDb } from 'api-delegations'; -import type { Delegation } from '../types.js'; +import type { Delegation } from 'universal-types'; -export function encodeDelegations( - delegations: Delegation[] | DelegationDb[], -): Hex { +export function encodeDelegations(delegations: Delegation[]): Hex { return encodeAbiParameters( [ { diff --git a/packages/universal-delegations-sdk/src/delegation/get-delegation-hash.ts b/packages/universal-delegations-sdk/src/delegation/get-delegation-hash.ts index ca3686a4..4f7d895e 100644 --- a/packages/universal-delegations-sdk/src/delegation/get-delegation-hash.ts +++ b/packages/universal-delegations-sdk/src/delegation/get-delegation-hash.ts @@ -1,11 +1,10 @@ import { concatHex, encodeAbiParameters, keccak256 } from 'viem'; -import type { DelegationDb } from 'api-delegations'; -import { CAVEAT_TYPEHASH, DELEGATION_TYPEHASH } from '../constants.js'; -import type { Caveat, Delegation } from '../types.js'; +import { CAVEAT_TYPEHASH, DELEGATION_TYPEHASH } from 'universal-data'; +import type { DelegationCaveat, Delegation } from 'universal-types'; // Implementation of: https://github.com/MetaMask/delegation-framework/blob/main/src/libraries/EncoderLib.sol#L18 -export function getDelegationHash(delegation: Delegation | DelegationDb) { +export function getDelegationHash(delegation: Delegation) { const encodedCaveatArrayPacketHash = getCaveatArrayPacketHash( delegation.caveats, ); @@ -31,7 +30,7 @@ export function getDelegationHash(delegation: Delegation | DelegationDb) { return keccak256(encoded); } -export function getCaveatArrayPacketHash(caveats: Caveat[]) { +export function getCaveatArrayPacketHash(caveats: DelegationCaveat[]) { const caveatPacketHashes = caveats.map((caveat) => getCaveatPacketHash(caveat), ); @@ -40,7 +39,7 @@ export function getCaveatArrayPacketHash(caveats: Caveat[]) { return keccak256(concatenatedHashes); } -export function getCaveatPacketHash(caveat: Caveat) { +export function getCaveatPacketHash(caveat: DelegationCaveat) { const encoded = encodeAbiParameters( [ { name: 'caveatTypeHash', type: 'bytes32' }, diff --git a/packages/universal-delegations-sdk/src/delegation/hooks/use-redeem-delegation.ts b/packages/universal-delegations-sdk/src/delegation/hooks/use-redeem-delegation.ts index 3c44251c..8362a878 100644 --- a/packages/universal-delegations-sdk/src/delegation/hooks/use-redeem-delegation.ts +++ b/packages/universal-delegations-sdk/src/delegation/hooks/use-redeem-delegation.ts @@ -1,8 +1,8 @@ import type { Address, Hex } from 'viem'; import { useWaitForTransactionReceipt, useWriteContract } from 'wagmi'; -import { delegationManagerAbi } from '../../abis/delegation-manager-abi.js'; -import type { Delegation, Execution } from '../../types.js'; +import { delegationManagerAbi } from 'universal-data'; +import type { Delegation, DelegationExecution } from 'universal-types'; import { encodeBatchExecution } from '../../execution/encode-batch-execution.js'; import { encodeDelegations } from '../encode-delegations.js'; @@ -19,7 +19,7 @@ export function useRedeemDelegation(address: Address) { executionModes, }: { delegations: Delegation[]; - executions: Execution[]; + executions: DelegationExecution[]; executionModes: Hex[]; }) { const permissionContexts = [encodeDelegations(delegations)]; diff --git a/packages/universal-delegations-sdk/src/delegation/hooks/use-sign-delegation.ts b/packages/universal-delegations-sdk/src/delegation/hooks/use-sign-delegation.ts index 09ebdb51..e6232dff 100644 --- a/packages/universal-delegations-sdk/src/delegation/hooks/use-sign-delegation.ts +++ b/packages/universal-delegations-sdk/src/delegation/hooks/use-sign-delegation.ts @@ -1,30 +1,23 @@ -import type { Address } from 'viem'; import { useSignTypedData } from 'wagmi'; -import type { Delegation } from '../../types.js'; import { eip712DelegationTypes } from '../eip712-delegation-type.js'; +import type { DelegationWithMetadata } from 'universal-types'; -export function useSignDelegation({ - chainId, - address, -}: { - chainId: number; - address: Address; -}) { +export function useSignDelegation() { const { data: delegationSignature, signTypedData, ...signTypedDataParams } = useSignTypedData(); - function signDelegation(delegation: Delegation) { + function signDelegation(delegation: DelegationWithMetadata) { signTypedData({ types: eip712DelegationTypes, primaryType: 'Delegation', domain: { name: 'DelegationManager', version: '1', - chainId: chainId, - verifyingContract: address, + chainId: delegation.chainId, + verifyingContract: delegation.verifyingContract, }, message: delegation, }); diff --git a/packages/universal-delegations-sdk/src/delegation/transform-delegation-db-to-delegation-types.ts b/packages/universal-delegations-sdk/src/delegation/transform-delegation-db-to-delegation-types.ts deleted file mode 100644 index 677316bf..00000000 --- a/packages/universal-delegations-sdk/src/delegation/transform-delegation-db-to-delegation-types.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { Address, Hex } from 'viem'; - -import type { DelegationDb } from 'api-delegations'; - -export function transformDelegationDbToDelegationTypes( - delegation: DelegationDb, -) { - return { - chainId: delegation.chainId, - verifyingContract: delegation.verifyingContract as Address, - delegator: delegation.delegator as Address, - delegate: delegation.delegate as Address, - authority: delegation.authority as Hex, - salt: BigInt(delegation.salt), - signature: delegation.signature as Hex, - caveats: delegation.caveats.map((caveat) => { - return { - enforcerType: caveat.enforcerType, - enforcer: caveat.enforcer as Address, - terms: caveat.terms as Hex, - args: caveat.args as Hex, - }; - }), - }; -} diff --git a/packages/universal-delegations-sdk/src/execution/encode-batch-execution.ts b/packages/universal-delegations-sdk/src/execution/encode-batch-execution.ts index 50babc5a..ab9f9f7c 100644 --- a/packages/universal-delegations-sdk/src/execution/encode-batch-execution.ts +++ b/packages/universal-delegations-sdk/src/execution/encode-batch-execution.ts @@ -1,9 +1,9 @@ import { type Hex, encodeAbiParameters } from 'viem'; -import type { Execution } from '../types.js'; +import type { DelegationExecution } from 'universal-types'; // Typescript implementation of: https://github.com/erc7579/erc7579-implementation/blob/main/src/lib/ExecutionLib.sol#L33-L39 -export function encodeBatchExecution(executions: Execution[]): Hex { +export function encodeBatchExecution(executions: DelegationExecution[]): Hex { return encodeAbiParameters( [ { diff --git a/packages/universal-delegations-sdk/src/execution/encode-single-execution.ts b/packages/universal-delegations-sdk/src/execution/encode-single-execution.ts index a76435d5..e082b5bc 100644 --- a/packages/universal-delegations-sdk/src/execution/encode-single-execution.ts +++ b/packages/universal-delegations-sdk/src/execution/encode-single-execution.ts @@ -1,13 +1,13 @@ import { type Hex, encodePacked } from 'viem'; -import type { Execution } from '../types.js'; +import type { DelegationExecution } from 'universal-types'; // Typescript implementation of: https://github.com/erc7579/erc7579-implementation/blob/main/src/lib/ExecutionLib.sol#L51-L62 export function encodeSingleExecution({ calldata, target, value, -}: Execution): Hex { +}: DelegationExecution): Hex { return encodePacked( ['address', 'uint256', 'bytes'], [target, value, calldata], diff --git a/packages/universal-delegations-sdk/src/exports/index.ts b/packages/universal-delegations-sdk/src/exports/index.ts index ee93acb7..7214ce7e 100644 --- a/packages/universal-delegations-sdk/src/exports/index.ts +++ b/packages/universal-delegations-sdk/src/exports/index.ts @@ -28,7 +28,6 @@ export { useErc20TransferAmountEnforcer } from '../actions/enforcers/use-erc20-t export { useSignErc20TransferDelegation } from '../actions/use-sign-erc20-transfer.js'; export { eip712DelegationTypes } from '../delegation/eip712-delegation-type.js'; export { encodeDelegations } from '../delegation/encode-delegations.js'; -export { transformDelegationDbToDelegationTypes } from '../delegation/transform-delegation-db-to-delegation-types.js'; export { getCaveatArrayPacketHash, getCaveatPacketHash, @@ -36,15 +35,4 @@ export { } from '../delegation/get-delegation-hash.js'; export { encodeBatchExecution } from '../execution/encode-batch-execution.js'; export { encodeSingleExecution } from '../execution/encode-single-execution.js'; -export { - ANY_DELEGATE, - BATCH_EXECUTION_MODE, - CAVEAT_TYPEHASH, - DELEGATION_TYPEHASH, - EMPTY_ARGS, - EMPTY_SIGNATURE, - ROOT_AUTHORITY, - SALT, - SINGLE_EXECUTION_MODE, -} from '../constants.js'; export type { DelegationsApi } from 'api-delegations'; diff --git a/packages/universal-delegations-sdk/src/types.ts b/packages/universal-delegations-sdk/src/types.ts deleted file mode 100644 index 9087cde3..00000000 --- a/packages/universal-delegations-sdk/src/types.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { Address, Hex } from 'viem'; - -// From https://github.com/erc7579/erc7579-implementation/blob/main/src/interfaces/IERC7579Account.sol#L6-L10 -export type Execution = { - target: Address; - value: bigint; - calldata: Hex; -}; - -// From https://github.com/MetaMask/delegation-framework/blob/main/src/utils/Types.sol#L38-L42 -export type Caveat = { - enforcerType?: string; - enforcer: Address; - // Terms and args are bytes with different encodings by enforcer - terms: Hex; - args: Hex; -}; - -// From https://github.com/MetaMask/delegation-framework/blob/main/src/utils/Types.sol#L24-L31 -export type Delegation = { - chainId: number; - delegate: Address; - delegator: Address; - authority: Hex; - caveats: Caveat[]; - salt: bigint; - signature: Hex; -}; diff --git a/packages/universal-types/src/delegations/index.ts b/packages/universal-types/src/delegations/index.ts index 3ff4ae5a..a566a8a9 100644 --- a/packages/universal-types/src/delegations/index.ts +++ b/packages/universal-types/src/delegations/index.ts @@ -15,7 +15,6 @@ export type DelegationCaveat = { }; export type Delegation = { - chainId: number; delegate: Address; delegator: Address; authority: Hex; @@ -29,26 +28,15 @@ export type DelegationBatch = Delegation[]; // Variations with extra metadata // export type DelegationCaveatWithMetadata = DelegationCaveat & { - type: string; + type: string | null; }; export type DelegationWithMetadata = Omit & { - type: string; - caveats: DelegationCaveatWithMetadata[]; -}; - -export type DelegationWithChainId = Delegation & { - chainId: number; -}; -export type DelegationWithChainIdMetadata = DelegationWithMetadata & { + hash: Hex; chainId: number; + type: string | null; + verifyingContract: Address; + caveats: DelegationCaveatWithMetadata[]; }; -export type DelegationWithChainIdMetadataHash = - DelegationWithChainIdMetadata & { - hash: Hex; - }; export type DelegationBatchWithMetadata = DelegationWithMetadata[]; -export type DelegationBatchWithChainId = DelegationWithChainId[]; -export type DelegationBatchWithChainIdMetadata = - DelegationWithChainIdMetadata[]; diff --git a/packages/universal-types/src/exports/index.ts b/packages/universal-types/src/exports/index.ts index 4be06d59..41048d79 100644 --- a/packages/universal-types/src/exports/index.ts +++ b/packages/universal-types/src/exports/index.ts @@ -6,9 +6,4 @@ export type { DelegationCaveatWithMetadata, DelegationExecution, DelegationWithMetadata, - DelegationWithChainId, - DelegationBatchWithChainId, - DelegationBatchWithChainIdMetadata, - DelegationWithChainIdMetadata, - DelegationWithChainIdMetadataHash, } from '../delegations/index.js'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 72d0dca7..5d0fccb5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -248,6 +248,9 @@ importers: universal-identity-sdk: specifier: workspace:* version: link:../../packages/universal-identity-sdk + universal-types: + specifier: workspace:* + version: link:../../packages/universal-types viem: specifier: ^2.21.41 version: 2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.5)(zod@3.23.8) @@ -285,6 +288,9 @@ importers: universal-data: specifier: workspace:* version: link:../../packages/universal-data + universal-delegations-sdk: + specifier: workspace:* + version: link:../../packages/universal-delegations-sdk universal-types: specifier: workspace:* version: link:../../packages/universal-types @@ -521,6 +527,9 @@ importers: universal-sdk: specifier: workspace:* version: link:../../packages/universal-sdk + universal-types: + specifier: workspace:* + version: link:../../packages/universal-types universal-wallet-connector: specifier: workspace:* version: link:../../packages/universal-wallet-connector @@ -821,6 +830,9 @@ importers: typescript: specifier: '>=5.0.4' version: 5.6.3 + universal-types: + specifier: workspace:* + version: link:../universal-types universal-wallet-sdk: specifier: workspace:* version: link:../universal-wallet-sdk @@ -845,6 +857,9 @@ importers: universal-data: specifier: workspace:* version: link:../universal-data + universal-types: + specifier: workspace:* + version: link:../universal-types viem: specifier: ^2.21.6 version: 2.21.45(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8)