Standalone, client-side tool for signing Solana transactions and messages using a Para-exported MPC-Ed25519 Signing-Scalar Format v1 private key.
- Paste a Para-exported private key.
- Pick Mainnet or Devnet. The site fetches your SOL balance and SPL token holdings from the public RPC.
- Transfer SOL to any recipient — builds a
SystemProgram.transfer, signs it locally with the FROST scalar, and broadcasts. - Transfer SPL tokens — pick one of your held tokens, enter a recipient
and amount; the site resolves both ATAs (creating the recipient's if
needed) and signs+broadcasts a
transferCheckedinstruction. - Sign a UTF-8 message — sign and verify locally with
tweetnacl. Useful for proof-of-key without spending fees.
Note: a 32-byte string in base58 is ambiguous between a FROST scalar (Para's native format) and an RFC 8032 seed (Phantom /
solana-keygenformat). They derive different addresses. This site treats raw 32-byte input as a FROST scalar — if the displayed address doesn't match the wallet you exported from, your input is probably a seed, not a scalar.
yarn install
yarn devOpen http://localhost:5173.
To produce a production bundle, run yarn build — the output lands in
dist/, which is a static site you can serve with any static-file host.
The site needs a Solana RPC endpoint that allows browser-origin requests.
api.mainnet-beta.solana.com does not, so the self-hosted defaults are:
- mainnet →
https://solana-rpc.publicnode.com— free, no key, browser- friendly. BlocksgetParsedTokenAccountsByOwner(so the SPL token-select dropdown won't populate), butgetBalance,sendTransaction, etc. all work. - devnet →
https://api.devnet.solana.com— full method set, browser CORS open.
Override at build time via env vars (see .env.example):
VITE_SOLANA_MAINNET_RPC_URL=https://your-provider.example.com/...
VITE_SOLANA_DEVNET_RPC_URL=https://your-provider.example.com/...
Override at runtime via the Custom RPC field on the page — useful if the default RPC is rate-limited and you have an Alchemy/Helius/QuickNode account of your own.
- Treat any v1 string like a private key. Anyone who has it controls the funds.
- Verify the URL bar before pasting. When in doubt, self-host or run offline.
- The page sets a strict CSP and uses
noindex. There is no analytics, no third-party scripts, no telemetry. - The bundle uses
@noble/curvesandtweetnaclfor the cryptography.@noble/curvesis the same library Phantom and Solflare use under the hood.
src/
├── localSign.ts v1 + raw-scalar decoders, RFC-8032 Ed25519 signing
├── solana.ts RPC, balance/holdings, SOL + SPL transfer builders
├── polyfills.ts Buffer global (required by @solana/spl-token at module-eval)
├── main.tsx React root
├── App.tsx top-level shell + AccountProvider
├── global.css Tailwind v4 entry
├── theme.css Para design tokens
├── vite-env.d.ts VITE_SOLANA_*_RPC_URL types
├── lib/
│ └── utils.ts cn() class-name helper
├── state/
│ └── account.tsx AccountProvider — the only place the decoded key lives
└── components/
├── ImportForm.tsx pre-import paste-the-key screen
├── AccountHeader.tsx address, network toggle, custom RPC, key details
├── BalanceCard.tsx SOL + SPL balances
├── SendSolCard.tsx SOL transfer form
├── SendSplCard.tsx SPL transfer form
├── SignMessageCard.tsx arbitrary-message signing
├── TransactionsCard.tsx submitted-tx history
├── NetworkToggle.tsx mainnet / devnet switch
├── Footer.tsx repo + license links
└── base/ shadcn primitives (button, card, input, …)