Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/sdk/account/utils/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,20 @@ export const MOCK_MULTI_MODULE_ADDRESS =
export const MODULE_TYPE_MULTI = 0

export const NEXUS_DOMAIN_NAME = "Nexus"

/**
* Legacy fallback for the Nexus EIP-712 domain version. Only correct for MEE
* versions backed by Nexus 1.2.0 (e.g. V2_0_0, V2_1_0). For MEE ≥ V2_2_0 the
* domain version moved to the 1.3.x line and this constant produces signatures
* that the on-chain Nexus contract rejects.
*
* Prefer `getNexusDomainVersion(meeVersion)` from `../../constants` whenever
* the MEE version is known — or `getEip712Domain()` to query the deployed
* contract directly. This constant is kept only as a back-compat default and
* may be removed in a future major release.
*
* @deprecated Use `getNexusDomainVersion(meeVersionOrConfig)` instead.
*/
export const NEXUS_DOMAIN_VERSION = "1.2.0"
export const NEXUS_DOMAIN_TYPEHASH =
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
Expand Down
30 changes: 25 additions & 5 deletions src/sdk/account/utils/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ import {
NEXUS_DOMAIN_TYPEHASH,
NEXUS_DOMAIN_VERSION
} from "../../account/utils/Constants"
import { MEEVersion } from "../../constants"
import { MEEVersion, getNexusDomainVersion } from "../../constants"
import type { MEEVersionConfig } from "./getVersion"
import { EIP1271Abi } from "../../constants/abi"
import {
type AnyData,
Expand Down Expand Up @@ -286,8 +287,12 @@ export function convertToFactor(percentage: number | undefined): number {
*
* @param accountOwner - The account owner address
* @param modules - Array of modules with their types and configurations
* @param domainName - Optional domain name
* @param domainVersion - Optional domain version
* @param domainName - Optional domain name. Defaults to `NEXUS_DOMAIN_NAME`.
* @param domainVersion - Optional domain version. **Defaults to the legacy
* `NEXUS_DOMAIN_VERSION` ("1.2.0"), which is wrong for any MEE ≥ V2_2_0.**
* Callers should pass `getNexusDomainVersion(meeVersionOrConfig)` whenever
* the MEE version is known so the install-mode signature is verifiable on
* the Nexus 1.3.x line.
* @returns Tuple of [installData, hash]
*/
export function makeInstallDataAndHash(
Expand Down Expand Up @@ -382,13 +387,26 @@ export function getTypesForEIP712Domain({
/**
* Retrieves account metadata including name, version, and chain ID.
*
* Tries `eip712Domain()` on-chain first. If the SCA is not yet deployed
* (counterfactual) or the call fails for any reason, falls back to the static
* domain name + version. When `meeVersionOrConfig` is supplied, the fallback
* version is derived from that config's `accountId` (e.g. MEE v2.2.2 →
* `"1.3.2"`); otherwise it falls back to the legacy `NEXUS_DOMAIN_VERSION`
* constant, which only reflects Nexus 1.2.0 and is wrong for any MEE ≥ 2.2.x.
* Pass `meeVersionOrConfig` whenever you know which MEE version the account
* is being used with.
*
* @param client - The viem Client instance
* @param accountAddress - The account address to query
* @param meeVersionOrConfig - Optional MEE version (or resolved config) used
* to derive the correct fallback domain version. Strongly recommended when
* the account may not yet be deployed.
* @returns Promise resolving to account metadata
*/
export const getAccountMeta = async (
client: Client,
accountAddress: Address
accountAddress: Address,
meeVersionOrConfig?: MEEVersion | MEEVersionConfig
): Promise<AccountMetadata> => {
try {
const domain = await client.request({
Expand Down Expand Up @@ -420,7 +438,9 @@ export const getAccountMeta = async (
} catch (error) {}
return {
name: NEXUS_DOMAIN_NAME,
version: NEXUS_DOMAIN_VERSION,
version: meeVersionOrConfig
? getNexusDomainVersion(meeVersionOrConfig)
: NEXUS_DOMAIN_VERSION,
chainId: client.chain
? BigInt(client.chain.id)
: BigInt(await client.extend(publicActions).getChainId())
Expand Down
38 changes: 38 additions & 0 deletions src/sdk/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,44 @@ export const DEFAULT_CONFIGURATIONS_BY_MEE_VERSION: Record<
}
}

/**
* The Nexus EIP-712 domain version string for a given MEE version (or its
* already-resolved config).
*
* Each `MEEVersionConfig.accountId` is formatted as `biconomy.nexus.<X.Y.Z>` —
* the same string the on-chain Nexus contract returns from
* `_domainNameAndVersion()`. This helper strips the prefix and returns the
* version suffix, giving callers a reliable fallback when an on-chain
* `eip712Domain()` query is unavailable (e.g. for a counterfactual SCA whose
* factory hasn't been deployed yet).
*
* @example
* getNexusDomainVersion(MEEVersion.V2_2_2) // → "1.3.2"
* getNexusDomainVersion(getMEEVersion(MEEVersion.V2_1_0)) // → "1.2.0"
*/
export const getNexusDomainVersion = (
meeVersionOrConfig: MEEVersion | MEEVersionConfig
): string => {
const config =
typeof meeVersionOrConfig === "string"
? DEFAULT_CONFIGURATIONS_BY_MEE_VERSION[meeVersionOrConfig]
: meeVersionOrConfig
if (!config) {
throw new Error(
`Unsupported MEE version: ${String(meeVersionOrConfig)}. ` +
`Expected one of: ${Object.keys(DEFAULT_CONFIGURATIONS_BY_MEE_VERSION).join(", ")}`
)
}
const prefix = "biconomy.nexus."
if (!config.accountId.startsWith(prefix)) {
throw new Error(
`Unexpected accountId format: "${config.accountId}". ` +
`Expected "${prefix}<X.Y.Z>".`
)
}
return config.accountId.slice(prefix.length)
}

// Rhinestone constants
export {
SMART_SESSIONS_ADDRESS,
Expand Down
Loading