diff --git a/.changeset/khaki-dots-cry.md b/.changeset/khaki-dots-cry.md new file mode 100644 index 00000000000..278f3ed4cf3 --- /dev/null +++ b/.changeset/khaki-dots-cry.md @@ -0,0 +1,5 @@ +--- +"@thirdweb-dev/service-utils": patch +--- + +Options to check service policies diff --git a/.changeset/stale-moose-tan.md b/.changeset/stale-moose-tan.md new file mode 100644 index 00000000000..e5f484d5ea6 --- /dev/null +++ b/.changeset/stale-moose-tan.md @@ -0,0 +1,5 @@ +--- +"@thirdweb-dev/wallets": patch +--- + +Dont refetch paymaster if sponsorship rejected diff --git a/packages/service-utils/src/core/api.ts b/packages/service-utils/src/core/api.ts index 61dd622e8d4..f40cb87be9f 100644 --- a/packages/service-utils/src/core/api.ts +++ b/packages/service-utils/src/core/api.ts @@ -1,5 +1,17 @@ import type { ServiceName } from "./services"; +export type UserOpData = { + sender: string; + targets: string[]; + gasLimit: string; + gasPrice: string; +}; + +export type PolicyResult = { + isAllowed: boolean; + reason: string; +}; + export type CoreServiceConfig = { enforceAuth?: boolean; apiUrl: string; @@ -7,6 +19,11 @@ export type CoreServiceConfig = { serviceApiKey: string; serviceAction?: string; useWalletAuth?: boolean; + checkPolicy?: boolean; + policyMetadata?: { + chainId: number; + userOp: UserOpData; + }; }; type Usage = { @@ -38,6 +55,7 @@ export type ApiKeyMetadata = { usage?: Usage; limits: Partial>; rateLimits: Partial>; + policyResult?: PolicyResult; }; export type AccountMetadata = { @@ -71,8 +89,15 @@ export async function fetchKeyMetadataFromApi( clientId: string, config: CoreServiceConfig, ): Promise { - const { apiUrl, serviceScope, serviceApiKey } = config; - const url = `${apiUrl}/v1/keys/use?clientId=${clientId}&scope=${serviceScope}&includeUsage=true`; + const { apiUrl, serviceScope, serviceApiKey, checkPolicy, policyMetadata } = + config; + const policyQuery = + checkPolicy && policyMetadata + ? `&checkPolicy=true&policyMetadata=${encodeURIComponent( + JSON.stringify(policyMetadata), + )}` + : ""; + const url = `${apiUrl}/v1/keys/use?clientId=${clientId}&scope=${serviceScope}&includeUsage=true${policyQuery}`; const response = await fetch(url, { method: "GET", headers: { diff --git a/packages/wallets/src/evm/connectors/smart-wallet/lib/base-api.ts b/packages/wallets/src/evm/connectors/smart-wallet/lib/base-api.ts index 94a6febbf68..56881275f0f 100644 --- a/packages/wallets/src/evm/connectors/smart-wallet/lib/base-api.ts +++ b/packages/wallets/src/evm/connectors/smart-wallet/lib/base-api.ts @@ -231,9 +231,8 @@ export abstract class BaseAccountAPI { const gasless = options?.gasless !== undefined ? options.gasless : this.gasless; if (gasless) { - const paymasterResult = await this.paymasterAPI.getPaymasterAndData( - partialOp, - ); + const paymasterResult = + await this.paymasterAPI.getPaymasterAndData(partialOp); const paymasterAndData = paymasterResult.paymasterAndData; if (paymasterAndData && paymasterAndData !== "0x") { partialOp.paymasterAndData = paymasterAndData; @@ -267,14 +266,15 @@ export abstract class BaseAccountAPI { estimates.preVerificationGas, ); // need paymaster to re-sign after estimates - const paymasterResult2 = await this.paymasterAPI.getPaymasterAndData( - partialOp, - ); - if ( - paymasterResult2.paymasterAndData && - paymasterResult2.paymasterAndData !== "0x" - ) { - partialOp.paymasterAndData = paymasterResult2.paymasterAndData; + if (paymasterAndData && paymasterAndData !== "0x") { + const paymasterResult2 = + await this.paymasterAPI.getPaymasterAndData(partialOp); + if ( + paymasterResult2.paymasterAndData && + paymasterResult2.paymasterAndData !== "0x" + ) { + partialOp.paymasterAndData = paymasterResult2.paymasterAndData; + } } } } else {