Repository navigation
Conversation
Wallet create and import now encrypt private keys using the standard Ethereum keystore format (AES-128-CTR + scrypt), the same format used by MetaMask, Geth, and Foundry. Users are prompted for a password on key creation/import and when any command needs the key. The POLYMARKET_PASSWORD env var supports non-interactive use (CI/scripts). Use --no-password to opt into plaintext storage (not recommended). Adds wallet export subcommand to decrypt and display the key. Fixes Polymarket#18 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…xt path Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Addressed both cursor findings in d491d80:
|
…y-storage # Conflicts: # Cargo.lock # Cargo.toml
|
Merged current main into this branch in ae96342. The conflicts were in Cargo.toml and Cargo.lock from the move to
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
Reviewed by Cursor Bugbot for commit ae96342. Configure here.
Every resolve_key call decrypted the keystore and prompted for the password, so `approve set` asked about once per allowance and could leave partial approvals if the user stopped partway. Keep the decrypted key for the rest of the command. The shell drops it after each command, and writing the config drops it so a replaced wallet is never served from the old key. decrypt_keystore also took the first file in the keystore directory, which could be a leftover keystore or .DS_Store. Write the keystore under a fixed name and read only that file. The rename now replaces the old file directly, so a failed move can no longer leave the directory empty.
|
Both Bugbot findings were valid and are fixed in efcfbf3. Password prompted on every key resolve: the decrypted key is now kept for the rest of the command, so Keystore decrypt picks an arbitrary file: the keystore is now always written as I added a unit test for the single unlock and an integration test that overwrites a wallet, adds stray files and reads the address back. |

Summary
~/.config/polymarket/config.jsonwere stored as plaintext - any process running as the same user could read themwallet createandwallet importnow encrypt keys using the standard Ethereum keystore format (AES-128-CTR + scrypt), the same format used by MetaMask, Geth, and FoundryPOLYMARKET_PASSWORDenv var for CI/scripts)--no-passwordflag available for plaintext storage (not recommended)wallet exportsubcommand to decrypt and display the key for backupNew dependencies
rpassword- secure terminal password input (no echo)rand0.8 - RNG for keystore encryptionalloysigner-keystorefeature - standard keystore encrypt/decryptFixes #18
Supersedes #19 (pre-refactor, needs full rewrite after #13)
Test plan
cargo fmt --checkpassescargo clippy -- -D warningspassescargo testpasses (131 tests)polymarket wallet createprompts for password and stores encrypted keystorepolymarket wallet create --no-passwordstores plaintext (with warning)polymarket wallet import <key>prompts for passwordpolymarket wallet exportdecrypts and shows keyPOLYMARKET_PASSWORD=xxx polymarket wallet addressworks without interactive promptThis contribution was developed with AI assistance (Claude Code).
Note
High Risk
Changes how private keys are stored, decrypted, exported, and held in memory—core wallet security behavior that reviewers should scrutinize carefully.
Overview
Wallet create/import now default to password-protected storage using the standard Ethereum keystore format (
wallet.jsonunder the config keystore dir) via Alloy’ssigner-keystore, instead of writing the private key intoconfig.json.--no-passwordkeeps the old plaintext-on-disk behavior (with warnings), and config gains anencryptedflag so existing plaintext setups still load unchanged.Unlocking prompts interactively (or uses
POLYMARKET_PASSWORD) when commands need the key from an encrypted wallet; the decrypted key is cached for the rest of a single command and cleared after interactive shell lines.wallet exportdecrypts and prints the key for backup.Keystore writes use a temp directory and replace a fixed
wallet.jsonfilename so overwrites do not leave stale files that could be picked up by mistake. Dependencies addrpassword,rand, and the keystore crypto stack in the lockfile.Reviewed by Cursor Bugbot for commit efcfbf3. Bugbot is set up for automated code reviews on this repo. Configure here.