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: browser → BrowserSigner; aws → KmsSigner; privatekey → LocalAccountSigner. 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.