Skip to content

Commit

Permalink
Merge pull request #122 from zerodevapp/feat/fallback-provider
Browse files Browse the repository at this point in the history
feat: add fallback kernel account client
  • Loading branch information
adnpark authored Apr 25, 2024
2 parents d267467 + 0ce3c0c commit 83f9d7f
Show file tree
Hide file tree
Showing 7 changed files with 1,241 additions and 1 deletion.
10 changes: 9 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,12 @@ GREETER_ADDRESS=
ZERODEV_PROJECT_ID=
ZERODEV_PAYMASTER_RPC_HOST=
ZERODEV_BUNDLER_RPC_HOST=
ZERODEV_API_KEY=
ZERODEV_API_KEY=

# For fallback e2e tests
ZERODEV_RPC_URL=
PIMLICO_RPC_URL=
STACKUP_RPC_URL=
ZERODEV_PAYMASTER_RPC_URL=
PIMLICO_PAYMASTER_RPC_URL=
STACKUP_PAYMASTER_RPC_URL=
62 changes: 62 additions & 0 deletions packages/core/clients/fallbackKernelAccountClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { EntryPoint } from "permissionless/types"
import type { Chain, Transport } from "viem"
import type { KernelSmartAccount } from "../accounts/index.js"
import type { KernelAccountClient } from "./kernelAccountClient.js"

export const createFallbackKernelAccountClient = <
TEntryPoint extends EntryPoint,
TTransport extends Transport,
TChain extends Chain | undefined,
TSmartAccount extends KernelSmartAccount<TEntryPoint> | undefined
>(
clients: Array<
KernelAccountClient<TEntryPoint, TTransport, TChain, TSmartAccount>
>
): KernelAccountClient<TEntryPoint, TTransport, TChain, TSmartAccount> => {
const proxyClient = new Proxy(clients[0], {
get(_target, prop, receiver) {
for (const client of clients) {
const value = Reflect.get(client, prop, receiver)
if (value !== undefined) {
// If the property is a function, wrap it to add fallback logic
if (typeof value === "function") {
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
return async (...args: any[]) => {
for (let i = 0; i < clients.length; i++) {
try {
const method = Reflect.get(
clients[i],
prop,
receiver
)
if (typeof method === "function") {
// Attempt to call the function on the current client
return await method(...args)
}
} catch (error) {
console.error(
`Action ${String(
prop
)} failed with client ${
client.transport.url
}, trying next if available.`,
error
)
if (i === clients.length - 1) {
throw error
}
}
}
}
}
// For non-function properties, return the first defined value found
return value
}
}
// If no clients have a defined value for the property, return undefined
return undefined
}
})

return proxyClient
}
2 changes: 2 additions & 0 deletions packages/core/clients/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ export {
createKernelAccountClient,
type KernelAccountClient
} from "./kernelAccountClient.js"

export { createFallbackKernelAccountClient } from "./fallbackKernelAccountClient.js"
1 change: 1 addition & 0 deletions packages/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export {
createKernelAccountClient,
type KernelAccountClient
} from "./clients/kernelAccountClient.js"
export { createFallbackKernelAccountClient } from "./clients/fallbackKernelAccountClient.js"
export {
type KernelValidator,
type ZeroDevPaymasterRpcSchema,
Expand Down
Loading

0 comments on commit 83f9d7f

Please sign in to comment.