{"version":3,"file":"kit.mjs","names":["presetFunction: FunctionPermission","allow: AllowKitMap"],"sources":["../src/kit/typings.ts"],"sourcesContent":["import * as ethSdk from \"@gnosis-guild/eth-sdk-client\"\nimport {\n  BaseContract,\n  ContractTransaction,\n  ContractTransactionResponse,\n  ethers,\n  FunctionFragment,\n  isError,\n  TransactionRequest,\n} from \"ethers\"\nimport { Condition, Operator, ParameterType } from \"../main/types\"\n// We import via alias to avoid double bundling of sdk functions\n// eslint does not know about our Typescript path alias\n// eslint-disable-next-line import/no-unresolved\nimport {\n  c,\n  ExecutionFlags,\n  TargetPermission,\n  FunctionPermission,\n  FunctionPermissionCoerced,\n} from \"zodiac-roles-sdk\"\n\n// For things that are not publicly exported we still use relative paths.\n// Since these are mainly types, this won't blow up bundles.\nimport { TupleScopings } from \"../main/target/authoring\"\nimport { coercePermission } from \"../main/permission\"\n\n// In this file, we derive the typed allow kit from the eth-sdk-client that has been generated based on the user-provided config json.\n\ntype PickByValue<T, Value> = {\n  [P in keyof T as T[P] extends Value\n    ? P extends string\n      ? P\n      : never\n    : never]: T[P]\n}\n\ntype Options = {\n  /** Allow sending an Ether value */\n  send?: boolean\n  /** Allow making delegate calls */\n  delegatecall?: boolean\n  /** Restrict the total Ether value sent using the specified allowance */\n  etherWithinAllowance?: `0x${string}`\n  /** Restrict the call rate using the specified allowance */\n  callWithinAllowance?: `0x${string}`\n}\n\n/** We need to skip over functions with \"view\" state mutability. We do this by matching the ethers ContractMethod type  */\ninterface StateMutatingContractMethod {\n  (): Promise<ContractTransactionResponse>\n\n  name: string\n  fragment: FunctionFragment\n  getFragment(): FunctionFragment\n  populateTransaction(): Promise<ContractTransaction>\n  staticCall(): Promise<any>\n  send(): Promise<ContractTransactionResponse>\n  estimateGas(): Promise<bigint>\n  staticCallResult(): Promise<any>\n}\n\ntype StateMutatingContractMethods<C extends BaseContract> = PickByValue<\n  C,\n  StateMutatingContractMethod\n>\n\n// These are copied over from what TypeChain generates\ntype BaseOverrides = Omit<TransactionRequest, \"to\" | \"data\">\ntype NonPayableOverrides = Omit<\n  BaseOverrides,\n  \"value\" | \"blockTag\" | \"enableCcipRead\"\n>\ntype PayableOverrides = Omit<BaseOverrides, \"blockTag\" | \"enableCcipRead\">\n\n// Maps the types of ethers method arguments to the ones we want to use in the allow function\ntype AllowFunctionParameters<MethodArgs extends [...any]> = MethodArgs extends [\n  ...any,\n  NonPayableOverrides | PayableOverrides,\n]\n  ? never\n  : [...TupleScopings<MethodArgs>, options?: Options]\n\ntype AllowFunctions<C extends BaseContract> = {\n  [key in keyof StateMutatingContractMethods<C>]: (\n    ...args: AllowFunctionParameters<\n      Parameters<C[key] extends (...args: any) => any ? C[key] : never>\n    >\n  ) => FunctionPermission\n}\n\ntype AllowContract<C extends BaseContract> = {\n  [EVERYTHING]: (options?: Options) => TargetPermission\n} & AllowFunctions<C>\n\nconst makeAllowFunction = <\n  C extends BaseContract,\n  N extends keyof StateMutatingContractMethods<C>,\n>(\n  contract: C,\n  name: N\n) => {\n  const functionFragment = contract.interface.getFunction(name as string)!\n  const functionInputs = functionFragment.inputs\n\n  if (\n    typeof contract.target !== \"string\" ||\n    !contract.target.startsWith(\"0x\")\n  ) {\n    throw new Error(\"Only addresses as contract targets are supported\")\n  }\n\n  return (...args: any[]): FunctionPermission => {\n    const scopings = args.slice(0, functionInputs.length) as any[]\n    const hasScopings = scopings.some((s) => !!s)\n    const options = (args[functionInputs.length] || {}) as Options\n    const presetFunction: FunctionPermission = {\n      targetAddress: contract.target as `0x${string}`,\n      signature: functionFragment.format(\"sighash\"),\n      condition: hasScopings\n        ? c.calldataMatches(scopings, functionInputs)()\n        : undefined,\n    }\n    return applyOptions(coercePermission(presetFunction), options)\n  }\n}\n\nconst emptyCalldataMatches = {\n  paramType: ParameterType.Calldata,\n  operator: Operator.Matches,\n  children: [],\n}\n\n/**\n * EthersWithinAllowance and CallWithinAllowance are global conditions that restrict the total Ether value sent or the call rate.\n * They must be appended as children of the root calldata matches node.\n */\nconst applyGlobalAllowance = (\n  condition: Condition = emptyCalldataMatches,\n  allowanceCondition: Condition\n) => {\n  if (\n    condition.paramType !== ParameterType.Calldata ||\n    condition.operator !== Operator.Matches\n  ) {\n    throw new Error(\n      \"Global allowance can only be applied to calldata matches nodes\"\n    )\n  }\n\n  return {\n    ...condition,\n    children: [...(condition.children || []), allowanceCondition],\n  }\n}\n\nconst applyOptions = (\n  entry: FunctionPermissionCoerced,\n  options: Options\n): FunctionPermissionCoerced => {\n  let condition = entry.condition\n\n  if (options.etherWithinAllowance) {\n    if (!options.send) {\n      throw new Error(\n        \"`etherWithinAllowance` can only be used if `send` is allowed\"\n      )\n    }\n\n    condition = applyGlobalAllowance(condition, {\n      paramType: ParameterType.None,\n      operator: Operator.EtherWithinAllowance,\n      compValue: options.etherWithinAllowance,\n    })\n  }\n\n  if (options.callWithinAllowance) {\n    condition = applyGlobalAllowance(condition, {\n      paramType: ParameterType.None,\n      operator: Operator.CallWithinAllowance,\n      compValue: options.callWithinAllowance,\n    })\n  }\n\n  return {\n    ...entry,\n    send: options.send,\n    delegatecall: options.delegatecall,\n    condition,\n  }\n}\n\nexport const EVERYTHING = Symbol(\"EVERYTHING\")\n\nconst makeAllowContract = <C extends BaseContract>(\n  contract: C\n): AllowContract<C> => {\n  const allowEverything = (options?: ExecutionFlags): TargetPermission => {\n    return {\n      targetAddress: contract.target as `0x${string}`,\n      ...options,\n    }\n  }\n\n  // TODO use Proxy just like ethers v6\n  // https://github.com/ethers-io/ethers.js/blob/main/src.ts/contract/contract.ts#L777\n\n  const contractHasFunction = (prop: string) => {\n    try {\n      contract.getFunction(prop)\n    } catch (error) {\n      if (!isError(error, \"INVALID_ARGUMENT\") || error.argument !== \"key\") {\n        throw error\n      }\n      return false\n    }\n    return true\n  }\n\n  return new Proxy(\n    {},\n    {\n      get: (target, prop) => {\n        if (prop === EVERYTHING) {\n          return allowEverything\n        }\n        if (typeof prop !== \"string\") {\n          return undefined\n        }\n\n        if (contractHasFunction(prop)) {\n          return makeAllowFunction(contract, prop as any)\n        }\n\n        return undefined\n      },\n      has: (target, prop) => {\n        if (typeof prop === \"symbol\") {\n          return prop === EVERYTHING\n        }\n\n        return contractHasFunction(prop)\n      },\n    }\n  ) as any\n}\n\ntype EthSdk = {\n  [key: string]: EthSdk | BaseContract\n}\n\ntype AllowKit<S extends EthSdk> = {\n  [Key in keyof S]: S[Key] extends BaseContract\n    ? AllowContract<S[Key]>\n    : S[Key] extends EthSdk // somehow it cannot infer that it cannot be a BaseContract here, so we use an extra conditional\n      ? AllowKit<S[Key]>\n      : never\n}\n\nconst mapSdk = <S extends EthSdk>(sdk: S): AllowKit<S> => {\n  return Object.keys(sdk).reduce((acc, key) => {\n    if (sdk[key].constructor.name === \"Contract\") {\n      acc[key] = makeAllowContract(sdk[key] as BaseContract)\n    } else {\n      acc[key] = mapSdk(sdk[key] as EthSdk)\n    }\n    return acc\n  }, {} as any)\n}\n\ntype SdkGetterName = Exclude<keyof typeof ethSdk, \"getContract\">\ntype NetworkName<S extends SdkGetterName> = S extends `get${infer N}Sdk`\n  ? Uncapitalize<N>\n  : never\n\ntype AllowKitMap = {\n  [Key in NetworkName<SdkGetterName>]: AllowKit<\n    ReturnType<(typeof ethSdk)[`get${Capitalize<Key>}Sdk`]>\n  >\n}\n\nconst uncapitalize = (s: string) => s.charAt(0).toLowerCase() + s.slice(1)\nexport const allow: AllowKitMap = Object.keys(ethSdk).reduce(\n  (acc, sdkGetterName) => {\n    if (\n      sdkGetterName === \"getContract\" ||\n      !sdkGetterName.startsWith(\"get\") ||\n      !sdkGetterName.endsWith(\"Sdk\")\n    ) {\n      return acc\n    }\n\n    const network = uncapitalize(sdkGetterName.slice(3, -3))\n    acc[network] = mapSdk(\n      ethSdk[sdkGetterName as SdkGetterName](ethers.getDefaultProvider())\n    )\n    return acc\n  },\n  {} as any\n)\n"],"mappings":"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"}