원클릭으로
siwa-keyring-proxy
Self-hosted keyring proxy signer with optional 2FA for secure key isolation.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Self-hosted keyring proxy signer with optional 2FA for secure key isolation.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Magic server wallet integration for SIWA authentication.
SIWA (Sign-In With Agent) authentication for ERC-8004 registered agents.
Openfort backend wallet integration for SIWA authentication.
Use this skill to implement server-side SIWA verification. For backends and APIs that need to authenticate ERC-8004 agents without signing capabilities.
Bankr wallet integration for SIWA authentication.
Circle developer-controlled wallet integration for SIWA authentication.
| name | siwa-keyring-proxy |
| version | 0.2.0 |
| description | Self-hosted keyring proxy signer with optional 2FA for secure key isolation. |
Sign SIWA messages using a self-hosted keyring proxy. The private key is stored securely in the proxy — your agent never touches it.
One-click deploy to Railway:
Or run with Docker:
docker run -p 3100:3100 \
-e KEYRING_PROXY_SECRET=your-shared-secret \
-e KEYSTORE_PASSWORD=your-keystore-password \
ghcr.io/builders-garden/siwa-keyring-proxy
npm install @buildersgarden/siwa
import { createKeyringProxySigner } from "@buildersgarden/siwa/signer";
const signer = createKeyringProxySigner({
proxyUrl: process.env.KEYRING_PROXY_URL!,
proxySecret: process.env.KEYRING_PROXY_SECRET!,
});
If your agent doesn't have an ERC-8004 identity yet, register onchain first:
import { registerAgent } from "@buildersgarden/siwa/registry";
const result = await registerAgent({
agentURI: "data:application/json;base64,...", // or ipfs://...
chainId: 84532, // Base Sepolia
signer,
});
console.log("Agent ID:", result.agentId);
console.log("Registry:", result.agentRegistry);
console.log("Tx Hash:", result.txHash);
The agentURI contains your agent's metadata (name, description, capabilities). You can use a base64 data URI or IPFS.
The authentication flow consists of two steps:
Note: The URLs below (
api.example.com) are placeholders. Replace them with your own server that implements the SIWA verification endpoints. See the Server-Side Verification skill for implementation details.
/siwa/nonce endpoint/siwa/verifyconst nonceRes = await fetch("https://api.example.com/siwa/nonce", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
address: await signer.getAddress(),
agentId: 42,
agentRegistry: "eip155:84532:0x8004A818BFB912233c491871b3d84c89A494BD9e",
}),
});
const { nonce, nonceToken, issuedAt, expirationTime } = await nonceRes.json();
import { signSIWAMessage } from "@buildersgarden/siwa";
const { message, signature, address } = await signSIWAMessage({
domain: "api.example.com",
uri: "https://api.example.com/siwa",
agentId: 42,
agentRegistry: "eip155:84532:0x8004A818BFB912233c491871b3d84c89A494BD9e", //According to the chain
chainId: 84532,
nonce,
issuedAt,
expirationTime,
}, signer);
// Send to server for verification
const verifyRes = await fetch("https://api.example.com/siwa/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message, signature, nonceToken }),
});
const { receipt, agentId } = await verifyRes.json();
// Store the receipt for authenticated API calls
import { signAuthenticatedRequest } from "@buildersgarden/siwa/erc8128";
const request = new Request("https://api.example.com/action", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action: "execute" }),
});
const signedRequest = await signAuthenticatedRequest(
request,
receipt, // from SIWA sign-in
signer,
84532,
);
const response = await fetch(signedRequest);
Create and manage wallets via the keystore module:
import { createWallet, getAddress } from "@buildersgarden/siwa/keystore";
// Create a new wallet (stored encrypted in the proxy)
const address = await createWallet({
proxyUrl: process.env.KEYRING_PROXY_URL!,
proxySecret: process.env.KEYRING_PROXY_SECRET!,
});
// Get the wallet address
const addr = await getAddress({
proxyUrl: process.env.KEYRING_PROXY_URL!,
proxySecret: process.env.KEYRING_PROXY_SECRET!,
});
KEYRING_PROXY_URL=https://your-proxy.up.railway.app
KEYRING_PROXY_SECRET=your-shared-hmac-secret
Agent Keyring Proxy Target API
| | |
+-- signMessage() --------> | |
| (HMAC authenticated) | Signs with private key |
| | Returns signature only |
| | |
+-- fetch(signedRequest) ---|-----------------------> |
| | Verifies signature
KEYSTORE_PASSWORD