Skip to content

Signing modes

Every write in PrimeDelta is signed. The signer you give the client is the exact boundary of what the SDK — or an assistant driving it — can do on your behalf. PrimeDelta never holds your key; choose the weakest signer that still does the job.

You pass a signer to the client one of two ways:

from primedelta import PrimeDelta, KmsSigner

# a) a raw key, wrapped for you:
pd = PrimeDelta(private_key="0x…", web3_provider_url=RPC, network="testnet")

# b) an explicit signer:
pd = PrimeDelta(signer=KmsSigner(key_id="…", region_name="eu-central-1"),
                web3_provider_url=RPC, network="testnet")

Pass exactly one of private_key or signer.

The signers

Signer Custody Runs where Approvals
LocalAccountSigner Raw key on the machine Anywhere (headless) None — signs automatically
KmsSigner Key stays inside AWS KMS Anywhere (headless) None — signs automatically
BrowserSigner Your wallet Local desktop only You approve each action in your wallet
RemoteBrowserSigner Your wallet A hosted https:// surface You approve each action in your wallet
MockBrowserSigner Dev key Anywhere (dev/CI) None — stands in for a wallet in tests

Local key — LocalAccountSigner

Signs with a raw key you hold. Headless and simple, but the key lives wherever the process does — treat it as dev / sandbox custody and use a dedicated, limited-funds wallet.

from primedelta import LocalAccountSigner

signer = LocalAccountSigner.from_key("0x…")
# also: LocalAccountSigner.from_keystore(path, password)
#       LocalAccountSigner.from_mnemonic(phrase, index=0)

KMS — KmsSigner

The signing key never leaves AWS KMS; only 32-byte digests are sent to be signed. Headless, unattended, and the right choice for anything shared or real. Needs the [kms] extra and an asymmetric secp256k1 (ECC_SECG_P256K1, SIGN_VERIFY) key.

from primedelta import KmsSigner

signer = KmsSigner(key_id="arn:aws:kms:…", region_name="eu-central-1")

Full setup: AWS KMS.

Browser — BrowserSigner

Signs through your real browser wallet (MetaMask, Rabby, …) via a one-shot local loopback page. A human approves every action, so it's the most contained mode — but it only works on a local desktop with a browser. It cannot run headless, in Docker, in CI, or on a hosted server.

from primedelta import BrowserSigner

signer = BrowserSigner(timeout=180.0)   # opens 127.0.0.1:<port> for your wallet

Remote browser — RemoteBrowserSigner

The browser experience for a hosted deployment: your app serves a sign page at an https:// origin and the user's own wallet signs there. Non-custodial — no fund-moving key lives on the server — but you host the sign/result endpoints.

from primedelta import RemoteBrowserSigner

signer = RemoteBrowserSigner(base_url="https://app.example.com", deliver=send_link_to_user)

Craft-only

If you'd rather sign with your own tooling entirely, pd.craft(...) returns the unsigned transaction for you to sign and broadcast elsewhere. (A signer is still configured, to fill the from-address.)

In the Claude Desktop plugin

The plugin exposes the same choices as three words: browserBrowserSigner; awsKmsSigner; privatekeyLocalAccountSigner. See Configure the plugin.

Which one, where

Different surfaces support different signers — a browser wallet can't sign on a headless server. See the signing-modes matrix before you deploy.