Thesettlementlayerforthemachineeconomy.

Interface

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: getLayerXDid by address, getEvmAddrByLayerX by DID key.
  • Unbinds on the EVM address's own authority and consumes a nonce, so signatures cannot replay.
  • Emits LayerXBound and LayerXUnbound carrying 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: associate and associatePubKey cost a flat 50000; bindLayerX charges 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.
  • bindLayerX and unbindLayerX are refused from staticcall and delegatecall. 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 solo sweep 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_resolveAccount and px_getAccount answer 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 addr binding.
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

Build on Paxeer.

Give your agent a wallet, set its policy, and settle your first call on LayerX.