Skip to content

Commit

Permalink
feat: add multi-chain config (#10)
Browse files Browse the repository at this point in the history
* fix: update type of createClientEOA

* fix: update type of createClientPasskey

* fix: update type of set and disconnect kernelClient

* feat: update type of createSession

* fix: update type of send userop

* fix: update getbalance type

* fix: update getSession type

* feat: add config

* fix: create kernelAcount with config

* feat: add useChainId and useSwitchChain

* fix: reconstruct client after chain switch

* fix: get session from chainId

* feat: add useChains

* fix: nonceKey and paymaster config

* fix: switch chain when create account with eoa

* 0.1.11-alpha.0

* fix: disconnect params

* feat: add transport in config

* 0.1.11-alpha.1

* feat: switch chain with social login

* 0.1.11-alpha.2

* fix: remove appId and chain in provider

* feat: add sendTransactionWithSession

* 0.2.0
  • Loading branch information
jstinhw authored May 10, 2024
1 parent f6e3fd0 commit e624d9e
Show file tree
Hide file tree
Showing 76 changed files with 3,934 additions and 1,751 deletions.
3 changes: 2 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"rules": {
"recommended": true,
"suspicious": {
"noExplicitAny": "warn"
"noExplicitAny": "warn",
"noConfusingVoidType": "warn"
},
"style": {
"noUnusedTemplateLiteral": "warn",
Expand Down
Binary file modified bun.lockb
Binary file not shown.
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zerodev/waas",
"version": "0.1.10",
"version": "0.2.0",
"description": "",
"main": "dist/index.cjs",
"module": "dist/index.js",
Expand All @@ -23,12 +23,13 @@
"@zerodev/ecdsa-validator": "^5.2.3",
"@zerodev/passkey-validator": "^5.2.3",
"@zerodev/permissions": "^5.2.2",
"@zerodev/sdk": "^5.2.4",
"@zerodev/sdk": "^5.2.10",
"@zerodev/session-key": "^5.2.2",
"@zerodev/social-validator": "5.0.1",
"events": "^3.3.0",
"lodash": "^4.17.21",
"pino-pretty": "^11.0.0"
"pino-pretty": "^11.0.0",
"zustand": "4.4.1"
},
"devDependencies": {
"@biomejs/biome": "^1.7.1",
Expand Down
82 changes: 82 additions & 0 deletions src/actions/createBasicSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type { Evaluate } from "@wagmi/core/internal"
import type { KernelValidator } from "@zerodev/sdk"
import type { Permission } from "@zerodev/session-key"
import { ENTRYPOINT_ADDRESS_V06 } from "permissionless"
import type { EntryPoint } from "permissionless/types"
import { http, type Abi, createPublicClient } from "viem"
import { privateKeyToAccount } from "viem/accounts"
import type { Config } from "../createConfig"
import {
KernelClientNotConnectedError,
type KernelClientNotConnectedErrorType,
KernelClientNotSupportedError,
type KernelClientNotSupportedErrorType,
PermissionsEmptyError,
type PermissionsEmptyErrorType,
ZerodevNotConfiguredError,
type ZerodevNotConfiguredErrorType
} from "../errors"
import { ZERODEV_BUNDLER_URL } from "../utils/constants"
import { createSessionKernelAccount, createSessionKey } from "../utils/sessions"

export type CreateBasicSessionParameters = Evaluate<{
permissions: Permission<Abi>[]
}>

export type CreateBasicSessionReturnType = Evaluate<{
chainId: number
sessionKey: `0x${string}`
sessionId: `0x${string}`
smartAccount: `0x${string}`
enableSignature: `0x${string}`
permissions: Permission<Abi>[]
}>

export type CreateBasicSessionErrorType =
| ZerodevNotConfiguredErrorType
| KernelClientNotSupportedErrorType
| PermissionsEmptyErrorType
| KernelClientNotConnectedErrorType

export async function createBasicSession<TEntryPoint extends EntryPoint>(
entryPoint: TEntryPoint | null,
validator: KernelValidator<TEntryPoint> | null,
config: Config,
parameters: CreateBasicSessionParameters
): Promise<CreateBasicSessionReturnType> {
const { permissions } = parameters

const chainId = config.state.chainId
const selectedChain = config.chains.find((x) => x.id === chainId)
if (!selectedChain) {
throw new ZerodevNotConfiguredError()
}
const publicClient = config.getClient({ chainId })

if (!entryPoint || !validator) throw new KernelClientNotConnectedError()

if (entryPoint !== ENTRYPOINT_ADDRESS_V06) {
throw new KernelClientNotSupportedError("create basicSession", "v3")
}
if (!permissions || permissions.length === 0)
throw new PermissionsEmptyError()

const sessionKey = createSessionKey()
const sessionSigner = privateKeyToAccount(sessionKey)

const kernelAccount = await createSessionKernelAccount({
sessionSigner,
publicClient: publicClient,
sudoValidator: validator,
entryPoint: entryPoint,
permissions: permissions
})
return {
chainId,
sessionKey: sessionKey,
sessionId: kernelAccount.sessionId,
smartAccount: kernelAccount.smartAccount,
enableSignature: kernelAccount.enableSignature,
permissions: kernelAccount.permissions
}
}
103 changes: 103 additions & 0 deletions src/actions/createKernelClientEOA.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { connect, getAccount, getWalletClient, switchChain } from "@wagmi/core"
import type { Evaluate } from "@wagmi/core/internal"
import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator"
import {
type KernelSmartAccount,
type KernelValidator,
createKernelAccount
} from "@zerodev/sdk"
import { walletClientToSmartAccountSigner } from "permissionless"
import type { EntryPoint } from "permissionless/types"
import { http, createPublicClient } from "viem"
import type {
ResourceUnavailableRpcErrorType,
UserRejectedRequestErrorType
} from "viem"
import type { Config, Connector, CreateConnectorFn } from "wagmi"
import type { Config as ZdConfig } from "../createConfig"
import {
ZerodevNotConfiguredError,
type ZerodevNotConfiguredErrorType
} from "../errors"
import type { KernelVersionType } from "../types"
import { ZERODEV_BUNDLER_URL } from "../utils/constants"
import { getEntryPointFromVersion } from "../utils/entryPoint"

export type CreateKernelClientEOAParameters = Evaluate<{
connector: Connector | CreateConnectorFn
}>

export type CreateKernelClientEOAReturnType = {
validator: KernelValidator<EntryPoint>
kernelAccount: KernelSmartAccount<EntryPoint>
entryPoint: EntryPoint
}

export type CreateKernelClientEOAErrorType =
| ZerodevNotConfiguredErrorType
| ResourceUnavailableRpcErrorType
| UserRejectedRequestErrorType

export async function createKernelClientEOA(
wagmiConfig: Config,
zdConfig: ZdConfig,
version: KernelVersionType,
parameters: CreateKernelClientEOAParameters
) {
const { connector } = parameters

const chainId = zdConfig.state.chainId
const chain = zdConfig.chains.find((x) => x.id === chainId)
if (!chain) throw new ZerodevNotConfiguredError()

const client = zdConfig.getClient({ chainId })

const entryPoint = getEntryPointFromVersion(version)

const { status } = getAccount(wagmiConfig)

const isConnected =
"uid" in connector && connector.uid === wagmiConfig.state.current

if (status === "disconnected" && !isConnected) {
await connect(wagmiConfig, { connector, chainId: chainId })
} else {
if (wagmiConfig.state.chainId !== chainId) {
await switchChain(wagmiConfig, { chainId })
}
}
const walletClient = await getWalletClient(wagmiConfig)

const ecdsaValidator = await signerToEcdsaValidator(client, {
entryPoint: entryPoint,
signer: walletClientToSmartAccountSigner(walletClient)
})
const account = await createKernelAccount(client, {
entryPoint: entryPoint,
plugins: {
sudo: ecdsaValidator
}
})
const uid = `ecdsa:${account.address}`

zdConfig.setState((x) => {
const chainId = x.chainId
return {
...x,
connections: new Map(x.connections).set(uid, {
chainId,
accounts: [
{
client: null,
account: account,
entryPoint,
validator: ecdsaValidator
}
]
}),
current: uid
}
})

return { validator: ecdsaValidator, kernelAccount: account, entryPoint }
}
106 changes: 106 additions & 0 deletions src/actions/createKernelClientPasskey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import type { Evaluate } from "@wagmi/core/internal"
import {
createPasskeyValidator,
getPasskeyValidator
} from "@zerodev/passkey-validator"
import {
type KernelSmartAccount,
type KernelValidator,
createKernelAccount
} from "@zerodev/sdk"
import type { EntryPoint } from "permissionless/types"
import { http, createPublicClient } from "viem"
import type { Config } from "../createConfig"
import {
PasskeyRegisterNoUsernameError,
type PasskeyRegisterNoUsernameErrorType,
ZerodevNotConfiguredError,
type ZerodevNotConfiguredErrorType
} from "../errors"
import type { KernelVersionType } from "../types"
import { ZERODEV_PASSKEY_URL } from "../utils/constants"
import { ZERODEV_BUNDLER_URL } from "../utils/constants"
import { getEntryPointFromVersion } from "../utils/entryPoint"
import { getWeb3AuthNValidatorFromVersion } from "../utils/webauthn"

export type PasskeConnectType = "register" | "login"

export type CreateKernelClientPasskeyParameters = Evaluate<{
type: PasskeConnectType
username?: string | undefined
}>

export type CreateKernelClientPasskeyReturnType = {
validator: KernelValidator<EntryPoint>
kernelAccount: KernelSmartAccount<EntryPoint>
entryPoint: EntryPoint
}

export type CreateKernelClientPasskeyErrorType =
| ZerodevNotConfiguredErrorType
| PasskeyRegisterNoUsernameErrorType

export async function createKernelClientPasskey(
config: Config,
version: KernelVersionType,
parameters: CreateKernelClientPasskeyParameters
) {
const { type, username } = parameters

const chainId = config.state.chainId
const chain = config.chains.find((x) => x.id === chainId)
if (!chain) throw new ZerodevNotConfiguredError()
const projectId = config.projectIds[chainId]
const client = config.getClient({ chainId })

let passkeyValidator: KernelValidator<EntryPoint>
const entryPoint = getEntryPointFromVersion(version)
const webauthnValidator = getWeb3AuthNValidatorFromVersion(entryPoint)

if (type === "register") {
if (!username) {
throw new PasskeyRegisterNoUsernameError()
}
passkeyValidator = await createPasskeyValidator(client, {
passkeyName: username,
passkeyServerUrl: `${ZERODEV_PASSKEY_URL}/${projectId}`,
entryPoint: entryPoint,
validatorAddress: webauthnValidator
})
} else {
passkeyValidator = await getPasskeyValidator(client, {
passkeyServerUrl: `${ZERODEV_PASSKEY_URL}/${projectId}`,
entryPoint: entryPoint,
validatorAddress: webauthnValidator
})
}

const kernelAccount = await createKernelAccount(client, {
entryPoint: entryPoint,
plugins: {
sudo: passkeyValidator
}
})
const uid = `passkey:${kernelAccount.address}`

config.setState((x) => {
const chainId = x.chainId
return {
...x,
connections: new Map(x.connections).set(uid, {
chainId,
accounts: [
{
client: null,
account: kernelAccount,
entryPoint,
validator: passkeyValidator
}
]
}),
current: uid
}
})

return { validator: passkeyValidator, kernelAccount, entryPoint }
}
Loading

0 comments on commit e624d9e

Please sign in to comment.