{"version":3,"file":"advanced-permissions.mjs","names":[],"sources":["../../../src/services/advanced-permissions.ts"],"sourcesContent":["/**\n * Advanced Permissions Service — MetaMask ERC-7715 integration.\n *\n * For MetaMask WalletConnect users, delegation is handled via Advanced\n * Permissions: the dapp requests scoped permissions from MetaMask, which\n * signs the delegation internally. The session account (our agent) then\n * redeems via the standard DelegationManager.\n *\n * This is a parallel path to the raw viem delegation in delegation-service.ts.\n * The policy gate routes based on wallet type:\n *   - MetaMask → Advanced Permissions (this service)\n *   - Private key / other wallets → raw delegation (delegation-service.ts)\n *\n * Uses @metamask/smart-accounts-kit SDK.\n */\n\nimport {\n  createDelegation,\n  createExecution,\n  getSmartAccountsEnvironment,\n  ExecutionMode,\n  ROOT_AUTHORITY,\n} from '@metamask/smart-accounts-kit';\nimport { DelegationManager } from '@metamask/smart-accounts-kit/contracts';\nimport type { Address, Hex } from 'viem';\nimport type { ExecutionAction } from './delegation-types.js';\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport interface GrantedPermission {\n  context: Hex;\n  signerMeta: {\n    delegationManager: Address;\n    [key: string]: unknown;\n  };\n  [key: string]: unknown;\n}\n\nexport interface PermissionRequest {\n  chainId: number;\n  expiry: number;\n  sessionAccountAddress: Address;\n  permission: NativeTokenPermission | Erc20TokenPermission;\n}\n\ninterface NativeTokenPermission {\n  type: 'native-token-transfer';\n  data: {\n    maxAmount: bigint;\n  };\n}\n\ninterface Erc20TokenPermission {\n  type: 'erc20-token-periodic';\n  data: {\n    tokenAddress: Address;\n    periodAmount: bigint;\n    periodDuration: number;\n    justification?: string;\n  };\n}\n\n// ─── Permission Storage ─────────────────────────────────────────────────\n// In-memory cache of granted permissions per policy ID.\n// Persists for the session lifetime. For cross-session persistence,\n// could be extended to disk (similar to delegation-store.ts).\n\nconst _grantedPermissions = new Map<string, GrantedPermission[]>();\n\nexport function storeGrantedPermissions(policyId: string, permissions: GrantedPermission[]): void {\n  _grantedPermissions.set(policyId, permissions);\n}\n\nexport function getGrantedPermissions(policyId: string): GrantedPermission[] | null {\n  return _grantedPermissions.get(policyId) ?? null;\n}\n\nexport function clearGrantedPermissions(policyId: string): void {\n  _grantedPermissions.delete(policyId);\n}\n\n// ─── Environment ────────────────────────────────────────────────────────\n\n/** Get the DelegationManager address for a chain from the SDK. */\nexport function getSdkDelegationManager(chainId: number): Address {\n  const env = getSmartAccountsEnvironment(chainId);\n  return env.DelegationManager as Address;\n}\n\n// ─── Redeem via SDK ─────────────────────────────────────────────────────\n\n/**\n * Build the redeemDelegations calldata using the SDK.\n * This encodes the permissionsContext + execution into the correct\n * format for the DelegationManager.\n *\n * The caller sends this as a raw transaction (to: DelegationManager, data: calldata).\n */\nexport function buildRedeemCalldata(\n  permissionsContext: Hex,\n  action: ExecutionAction,\n): Hex {\n  const execution = createExecution({\n    target: action.target,\n    value: action.value,\n    callData: action.callData,\n  });\n\n  return DelegationManager.encode.redeemDelegations({\n    delegations: [[]], // permissionsContext replaces inline delegations\n    modes: [ExecutionMode.SingleDefault],\n    executions: [[execution]],\n  }) as Hex;\n}\n\n/**\n * Check if Advanced Permissions are available for a wallet.\n * Returns true if:\n * 1. The wallet is connected via WalletConnect or MetaMask provider\n * 2. The wallet has an EIP-7702 designation (smart account)\n * 3. There are stored granted permissions\n */\nexport function hasAdvancedPermissions(policyId: string): boolean {\n  return _grantedPermissions.has(policyId);\n}\n\n/**\n * Get the permission context + DelegationManager address for a policy.\n * Returns null if no permissions are stored.\n */\nexport function getPermissionContext(policyId: string): {\n  context: Hex;\n  delegationManager: Address;\n} | null {\n  const perms = _grantedPermissions.get(policyId);\n  if (!perms || perms.length === 0) return null;\n\n  const first = perms[0];\n  if (!first) return null;\n\n  return {\n    context: first.context,\n    delegationManager: first.signerMeta.delegationManager,\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmEA,MAAM,sCAAsB,IAAI,KAAkC;AAElE,SAAgB,wBAAwB,UAAkB,aAAwC;AAChG,qBAAoB,IAAI,UAAU,YAAY;;AAGhD,SAAgB,sBAAsB,UAA8C;AAClF,QAAO,oBAAoB,IAAI,SAAS,IAAI;;AAG9C,SAAgB,wBAAwB,UAAwB;AAC9D,qBAAoB,OAAO,SAAS;;;AAMtC,SAAgB,wBAAwB,SAA0B;AAEhE,QADY,4BAA4B,QAAQ,CACrC;;;;;;;;;AAYb,SAAgB,oBACd,oBACA,QACK;CACL,MAAM,YAAY,gBAAgB;EAChC,QAAQ,OAAO;EACf,OAAO,OAAO;EACd,UAAU,OAAO;EAClB,CAAC;AAEF,QAAO,kBAAkB,OAAO,kBAAkB;EAChD,aAAa,CAAC,EAAE,CAAC;EACjB,OAAO,CAAC,cAAc,cAAc;EACpC,YAAY,CAAC,CAAC,UAAU,CAAC;EAC1B,CAAC;;;;;;;;;AAUJ,SAAgB,uBAAuB,UAA2B;AAChE,QAAO,oBAAoB,IAAI,SAAS;;;;;;AAO1C,SAAgB,qBAAqB,UAG5B;CACP,MAAM,QAAQ,oBAAoB,IAAI,SAAS;AAC/C,KAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;CAEzC,MAAM,QAAQ,MAAM;AACpB,KAAI,CAAC,MAAO,QAAO;AAEnB,QAAO;EACL,SAAS,MAAM;EACf,mBAAmB,MAAM,WAAW;EACrC"}