Skip to content

Wire getLocale, getAppIcon, ethers.Wallet.createRandom (closes #278)#299

Closed
proggeramlug wants to merge 1 commit intomainfrom
fix/issue-278
Closed

Wire getLocale, getAppIcon, ethers.Wallet.createRandom (closes #278)#299
proggeramlug wants to merge 1 commit intomainfrom
fix/issue-278

Conversation

@proggeramlug
Copy link
Copy Markdown
Contributor

Closes #278.

Summary

  • getLocale() / getAppIcon(path) (perry/system): both FFIs were already implemented in every platform crate but had no dispatch rows in PERRY_SYSTEM_TABLE. Added two rows to crates/perry-dispatch/src/lib.rs and type declarations to types/perry/system/index.d.ts.

  • ethers.Wallet.createRandom(): three-part fix:

    1. HIR lowering (crates/perry-hir/src/lower/expr_call.rs): the module.Class.staticMethod() double-member pattern was not recognized. Added a new handler (modelled after the existing process.hrtime.bigint() handler) that produces NativeMethodCall { module, class_name: Some(class_name), method, … }.
    2. Runtime FFI (crates/perry-stdlib/src/ethers.rs): new js_ethers_wallet_create_random() generates a cryptographically random 32-byte private key via rand::thread_rng, derives the 20-byte Ethereum address as keccak256(pk)[12..32], applies EIP-55 checksum, and returns a JS object with address and privateKey string fields.
    3. Dispatch table (crates/perry-codegen/src/lower_call.rs): added ethers rows to NATIVE_MODULE_TABLE including createRandom with class_filter: Some("Wallet"). Also added NativeRetKind::BigInt so parseEther/parseUnits NaN-box their *mut BigIntHeader returns with BIGINT_TAG (0x7FFA).
  • Docs: crypto.md "not yet wired" section replaced with verified {{#include}} extract; getLocale/getAppIcon anchor blocks added to system/snippets.ts.

Test plan

  • ethers.Wallet.createRandom() returns object with checksummed address (42 chars) and privateKey (length 66)
  • ethers.getAddress / parseEther / formatEther still work (existing ethers dispatch unchanged)
  • getLocale() IR emits declare i64 @perry_system_get_locale() + call
  • getAppIcon("") IR emits declare i64 @perry_system_get_app_icon(i64) + call
  • cargo build --release -p perry-hir -p perry-codegen -p perry-dispatch -p perry-stdlib -p perry clean
  • ./target/release/doc-tests --filter crypto passes (compile-only, run: false)
  • ./target/release/doc-tests --filter system passes (compile-only, run: false)

Generated by Claude Code

…n, ethers.Wallet.createRandom

Closes #278.

**getLocale / getAppIcon (perry/system)**
Both FFIs were already implemented in every platform crate but had no
dispatch rows in PERRY_SYSTEM_TABLE (perry-dispatch). Add two rows:
- `getLocale` → `perry_system_get_locale()` returns Str
- `getAppIcon(path)` → `perry_system_get_app_icon(i64)` returns Widget

**ethers.Wallet.createRandom()**
No codegen or runtime existed. Three-part fix:

1. *HIR lowering* (`perry-hir/src/lower/expr_call.rs`): the `module.Class.staticMethod()`
   double-member pattern (e.g. `ethers.Wallet.createRandom()`) was not recognized.
   Add a new handler matching outer Member → inner Member → Ident → native-module lookup,
   producing `NativeMethodCall { module, class_name: Some(class_name), method, ... }`.
   Modelled after the existing `process.hrtime.bigint()` handler.

2. *Runtime FFI* (`perry-stdlib/src/ethers.rs`): new `js_ethers_wallet_create_random()`
   generates a cryptographically random 32-byte private key via `rand::thread_rng`,
   derives the 20-byte Ethereum address as `keccak256(pk)[12..32]`, applies EIP-55
   checksum, and returns a JS object with `address` and `privateKey` string fields.

3. *Dispatch* (`perry-codegen/src/lower_call.rs`): add ethers dispatch rows to
   NATIVE_MODULE_TABLE including `createRandom` with `class_filter: Some("Wallet")`.
   Also add `NativeRetKind::BigInt` variant so `parseEther`/`parseUnits` can NaN-box
   their `*mut BigIntHeader` return values with BIGINT_TAG (0x7FFA).

**Docs**
- `docs/src/stdlib/crypto.md`: replace "not yet wired" section with verified
  `{{#include}}` extract from snippets.ts.
- `docs/examples/stdlib/crypto/snippets.ts`: add `ethers` anchor block.
- `docs/examples/system/snippets.ts`: add `locale` and `app-icon` anchor blocks.
- `types/perry/system/index.d.ts`: add `getLocale` and `getAppIcon` declarations.

Verified end-to-end:
- `ethers.Wallet.createRandom()` → `address: 0x...` (checksummed), `privateKey length: 66`
- `getLocale` / `getAppIcon` IR declares `perry_system_get_locale()` and
  `perry_system_get_app_icon(i64)` correctly; links on any platform with a UI crate.

https://claude.ai/code/session_018bS3B71M2Xx31vmBZwQRbL
proggeramlug pushed a commit that referenced this pull request Apr 29, 2026
…t.createRandom (v0.5.385) (#299)

Closes #278.

**getLocale / getAppIcon (perry/system)**
Both FFIs were already implemented in every platform crate but had no
dispatch rows in PERRY_SYSTEM_TABLE (perry-dispatch). Add two rows:
- `getLocale` → `perry_system_get_locale()` returns Str
- `getAppIcon(path)` → `perry_system_get_app_icon(i64)` returns Widget

**ethers.Wallet.createRandom()**
No codegen or runtime existed. Three-part fix:

1. *HIR lowering* (`perry-hir/src/lower/expr_call.rs`): the
   `module.Class.staticMethod()` double-member pattern (e.g.
   `ethers.Wallet.createRandom()`) was not recognized. Add a new
   handler matching outer Member → inner Member → Ident →
   native-module lookup, producing
   `NativeMethodCall { module, class_name: Some(class_name), method, ... }`.
   Modelled after the existing `process.hrtime.bigint()` handler.

2. *Runtime FFI* (`perry-stdlib/src/ethers.rs`): new
   `js_ethers_wallet_create_random()` generates a cryptographically
   random 32-byte private key via `rand::thread_rng`, derives the
   20-byte Ethereum address as `keccak256(pk)[12..32]`, applies
   EIP-55 checksum, and returns a JS object with `address` and
   `privateKey` string fields.

3. *Dispatch* (`perry-codegen/src/lower_call.rs`): add ethers
   dispatch rows to NATIVE_MODULE_TABLE including `createRandom`
   with `class_filter: Some("Wallet")`. Also add
   `NativeRetKind::BigInt` variant so `parseEther`/`parseUnits`
   can NaN-box their `*mut BigIntHeader` return values with
   BIGINT_TAG (0x7FFA).

**Docs**
- `docs/src/stdlib/crypto.md`: replace "not yet wired" section with
  verified `{{#include}}` extract from snippets.ts.
- `docs/examples/stdlib/crypto/snippets.ts`: add `ethers` anchor
  block.
- `docs/examples/system/snippets.ts`: add `locale` and `app-icon`
  anchor blocks.
- `types/perry/system/index.d.ts`: add `getLocale` and `getAppIcon`
  declarations.

Verified end-to-end:
- `ethers.Wallet.createRandom()` → `address: 0x...` (checksummed),
  `privateKey length: 66`
- `getLocale` / `getAppIcon` IR declares `perry_system_get_locale()`
  and `perry_system_get_app_icon(i64)` correctly; links on any
  platform with a UI crate.

PR #299 was opened against pre-v0.5.382 main; manually rebased onto
current main HEAD by maintainer with conflict resolution in 4 files
(dispatch table style alignment, NativeRetKind::BigInt arm
addition, expr_call.rs surgical insertion, ethers.rs use-stmt
union). PR author attribution preserved on the rebased commit.
@proggeramlug
Copy link
Copy Markdown
Contributor Author

Manually rebased onto current main and landed as c61296b (v0.5.385). PR was opened against pre-v0.5.382 main and conflicted with the v0.5.382 + v0.5.384 stack (lower_call.rs / dispatch / expr_call.rs / ethers.rs); resolved with style alignment + surgical insertion of the new module.Class.staticMethod() block. Author attribution preserved on the rebased commit. Thanks!

proggeramlug added a commit that referenced this pull request Apr 29, 2026
… merges

The lint job on c61296b caught rustfmt drift from the recent batch
of squash-merges:

- crates/perry-doc-tests/src/image_diff.rs (PR #298)
- crates/perry-hir/src/destructuring.rs (PR #301)
- crates/perry-hir/src/lower/expr_new.rs (PR #301)
- crates/perry-hir/src/lower_decl.rs (PR #301)
- crates/perry-stdlib/src/fetch.rs (PR #301)
- crates/perry-stdlib/src/streams.rs (PR #301)
- crates/perry-stdlib/src/ethers.rs (PR #299, my conflict resolution
  inserted a long line that needed wrapping)
- crates/perry-codegen/src/lower_call.rs +
  crates/perry-codegen/src/lower_call/builtin.rs +
  crates/perry-codegen/src/runtime_decls.rs (PR #301)

Plus Cargo.lock sync from 0.5.384 → 0.5.385 (my v0.5.385 commit
landed Cargo.toml's version bump but I forgot to stage Cargo.lock).

Pure `cargo fmt --all` output, no hand edits. Verified
`cargo build --release -p perry -p perry-runtime -p perry-stdlib`
clean post-fmt in 1m 31s.

No version bump — same precedent as ea95e85 (rustfmt baseline as
chore companion to #294).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wire codegen dispatch for the 3 #193 holdouts: ethers.Wallet.createRandom, perry/system getLocale + getAppIcon

2 participants