
One account, both domains
One account across both domains
Bind a Paxeer EVM address to a LayerX DID and read both halves in one call.
You bind one EVM address to one LayerX DID, and the addr precompile keeps the record. Both sides consent: your transaction proves the EVM key, and a strict Ed25519 signature over the chain id, the address and that address's bind nonce proves the DID. Then call getUnifiedAccount once to read the EVM address, the Pax address, the DID public key and the main account id together. Missing halves return empty fields rather than reverting.
What it does
The addr precompile at 0x0000000000000000000000000000000000001004 holds the links that make one user one account on Paxeer X: the association between a Paxeer EVM address and its Pax address, and a binding between that EVM address and a did:layerx:<64 hex> Ed25519 identity. Both sides consent: the EVM address by sending the transaction, the DID key by signing "LX:PAXEER-BIND:v1" followed by the chain id, the address and that address's current bind nonce. One read, getUnifiedAccount(addr), returns the EVM address, the Pax address, the DID public key and the LayerX main account id together, and returns empty or zero fields instead of reverting when a half is missing.
Key capabilities
- Binds one EVM address to one DID; each side holds at most one of the other.
- Requires a strict Ed25519 signature from the DID key over chain id, address and nonce.
- Returns both halves in one call through
getUnifiedAccount, which never reverts. - Resolves either direction:
getLayerXDidby address,getEvmAddrByLayerXby DID key. - Unbinds on the EVM address's own authority and consumes a nonce, so signatures cannot replay.
- Emits
LayerXBoundandLayerXUnboundcarrying the address, DID key and nonce.
Who it's for
Wallet and application developers, and anyone who holds funds on the chain and also runs agents.
Why it matters
One secret yields both keys and one on-chain record ties them together, so a user does not keep two unrelated accounts or copy identifiers between them. A wallet or page can show chain balances beside agent activity from a single read, instead of asking which side the user is on.
Differentiators
Mutual consent across two signature schemes in one call: the secp256k1 transaction proves the EVM side and a strict Ed25519 signature over a domain-separated message proves the DID side. The pair is stored as a bijection in both directions, and a table loaded from genesis is rejected unless both directions agree, every DID key is canonical and every nonce is eight bytes.
Outcomes
- One read returns both halves, and it never reverts
- Resolve either direction: address to DID, or DID to address
- Keep one account per user instead of two to reconcile
Technical notes
- Gas:
associateandassociatePubKeycost a flat 50000;bindLayerXcharges 4000 on top of metered store access for the Ed25519 check. - An association can be established three ways: through the precompile, by an association transaction, or automatically when the EVM ante step preprocesses a transaction from a new sender.
bindLayerXandunbindLayerXare refused fromstaticcallanddelegatecall. A non-canonical DID key, an address or DID already bound, a signature that is not 64 bytes, and an exhausted nonce all fail.- This is a binding plus a joined view, not a single account object: each domain keeps its own balances and state. An unassociated EVM address cannot receive cw20 or ERC-721 through pointer contracts, and the
solosweep precompile for funds stranded at an unassociated address is built but is not in the precompile table, so the VM cannot reach it as wired. - The gateway's
px_resolveAccountandpx_getAccountanswer the same join over JSON-RPC, but that host is not open yet: "The limited beta has not opened yet." - No page merges one person's activity across both domains yet. The indexer ingests both chains into one store, but a query is still keyed by one domain's own identifier because it does not resolve the
addrbinding.
import { readLayerXBindState, planLayerXBind, bindTransactionRequest } from "layerx-sdk";
const state = await readLayerXBindState(wallet, derived.evmAddress);
const plan = planLayerXBind(derived, 125, state);
if (plan.action === "bind") {
await wallet.request(bindTransactionRequest(derived, plan.call));
}More in Interface
Onboarding and team-allocated funding
Register a signer, claim one grant
ExploreOne JSON-RPC endpoint for the network
One endpoint for the whole network
ExplorePasskey sessions and step-up approval
Passkeys hold your account, not passwords
Explorepx_* cross-domain read namespace
Eight reads across both domains
ExploreBuild on Paxeer.
Give your agent a wallet, set its policy, and settle your first call on LayerX.