Skip to content

Commit 618953f

Browse files
committed
feat: dual-wallet library, purchase choice, playback + file handler fixes
- Library shows assets owned by both EOA and Smart Account (merged, deduped, tagged) - Purchase flow lets user choose EOA or SA wallet with chain-switch to Base for EOA - Playback resolves correct owning wallet for Lit access (EOA/SA fallback) - Feed cards show "Owned" badge when user holds access token - Download/re-download from feed and library detail views - Chipotle mode skips SIWE signature prompts for standalone playback - Player handles IPFS thumbnail URLs and robust wallet resolution with timeout - open_item.js regex handles Puter duplicate naming for .edrm and .ddrm.json files Made-with: Cursor
1 parent e3ef5f0 commit 618953f

14 files changed

Lines changed: 453 additions & 116 deletions

File tree

docs/core/ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ These diagrams from Rong define the north star. Every work stream should move us
176176
- [x] **Bug fixes (Mar 18)** — Fixed duplicate wallet signatures (IPC.js + pc2-wallet-bridge.js dual handling), fixed "Network fee: Unavailable" (removed explicit gas estimation, let MetaMask handle), fixed duplicate chain switch popup (check current chain before switching), fixed duplicate SIWE login on account change, fixed media encode `dataToEncryptHash` propagation for correct minting contentId, fixed IPFS directory pinning for DASH packages (Helia `storeDirectory` + local directory detection in `pinRemoteCID`), fixed PSSH extraction (multi-pattern search), fixed PSSH ciphertext/hash/kid embedding, fixed authority address (`0x8fe6bf98...` AuthorityGateway on Base), fixed GUI IPC rebuild (bundle.min.js), **E2E verified: mint → buy → download → playback**
177177
- [x] **AV1 playback fix (Mar 18)** — Three critical fixes for encrypted AV1 video playback: (1) Rust WASM `strip.rs` updated to remove PSSH boxes nested inside `moov` (not just top-level), (2) `splitInitForTrack()` in `media.ts` splits multi-track init segments into per-track inits for MSE SourceBuffer compatibility (Bento4 produces shared init segments), (3) `hdlr` handler_type offset corrected from +8 to +12. MetaMask mint gas estimation fix with `sendTxWithRetry()` retry/skip buttons. Player MSE debug logging added.
178178
- [x] **WASM & I/O optimization (Mar 18)** — 5 quick wins: `wasm-opt -Oz` build pass in `build-wasm.sh`, WASM binary preload at startup, WASM cache key collision fix (SHA-256 fingerprint), async video thumbnail generation (no more event-loop blocking `execSync`), async HTML injection in `static.ts`. Plus: AES-GCM encrypt moved to WASM (`encrypt_only` mode in ddrm-renderer) — non-media file encryption no longer uses Node.js `crypto.createCipheriv`, plaintext never touches Node.js memory.
179-
- [x] **WASM/Rust optimization pass (Mar 20)** — Speed-tuned crypto: `cenc-decrypt` and `cenc-encrypt` changed from `opt-level = "s"` to `opt-level = 3` for ~20-40% faster AES operations. `panic = "abort"` on all 5 WASM crates (ddrm-renderer reduced 482 KB / 8.3%). Smart build pipeline: per-crate wasm-opt levels (`-O3` for crypto, `-Oz` for utility), `--enable-simd` and `--enable-nontrapping-float-to-int` flags. Hot-path log reduction: 20 WASMRuntime.ts `info` logs downgraded to `debug`.
179+
- [x] **WASM/Rust optimization pass (Mar 20)** — Speed-tuned crypto: `cenc-decrypt` and `cenc-encrypt` changed from `opt-level = "s"` to `opt-level = 3` for ~20-40% faster AES operations. `panic = "abort"` on all 5 WASM crates (ddrm-renderer reduced 482 KB / 8.3%). Smart build pipeline: per-crate wasm-opt levels (`-O3` for crypto, `-Oz` for utility), `--enable-simd` and `--enable-nontrapping-float-to-int` flags. Hot-path log reduction: 20 WASMRuntime.ts `info` logs downgraded to `debug`. Security hardening: CEK buffer zeroing in `unwrapECDHEnvelope` (media.ts), derived key zeroing in mnemonic encrypt/decrypt (encryption.ts). IPFS WASM assemble threshold lowered from 10MB to 5MB for reduced V8 heap pressure.
180180
- [x] **dDRM Viewer native windowing** — launches as UIWindow via IPC `postMessage``launch_app()` (not browser popup), integrated with taskbar *(completed Mar 15)*
181181
- [x] **.ddrm.json capsule format** — descriptor files for non-media assets with CID, Lit params, mimeType. MIME: `application/x-ddrm+json`. Saved to Documents *(completed Mar 15)*
182182
- [x] **GUI capsule integration** — custom shield icon, MIME registration, double-click opens dDRM Viewer, content_type_to_icon mapping *(completed Mar 15)*

docs/core/SESSION_HANDOVER.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ Expanded the dDRM Viewer to support four new interactive content types beyond th
789789
- **`panic = "abort"` on all WASM crates** — Removes unwinding code from all 5 WASM binaries. `ddrm-renderer.wasm` reduced by 482 KB (5.83 MB → 5.35 MB, -8.3%).
790790
- **Smart build pipeline**`build-wasm.sh` now uses per-crate wasm-opt levels: `-O3` for crypto crates (speed), `-Oz` for utility crates (size). Added `--enable-nontrapping-float-to-int` and `--enable-simd` flags for Rust-generated WASM features.
791791
- **Hot-path log reduction** — 20 `logger.info` calls in `WASMRuntime.ts` downgraded to `logger.debug`. Eliminates 5-10 log writes per WASM invocation in production. First-time compilation, queue events, and errors remain at `info`.
792+
- **Security: CEK buffer zeroing**`unwrapECDHEnvelope()` in `media.ts` now zeroes the decrypted license buffer (`decrypted.fill(0)`) after CEK extraction, preventing sensitive key material from lingering in V8 heap.
793+
- **Security: derived key zeroing**`encryptMnemonicWithSignature()` and `decryptMnemonicWithSignature()` in `encryption.ts` now zero the derived AES key (`key.fill(0)`) in `finally` blocks, ensuring cleanup even on error paths.
794+
- **IPFS WASM threshold lowered**`WASM_ASSEMBLE_THRESHOLD` in `ipfs.ts` lowered from 10MB to 5MB. More files assembled in WASM linear memory (outside V8 heap), reducing GC pressure on constrained devices like Jetson.
792795

793796
**WASM binary size comparison (before → after):**
794797
| Binary | Before | After | Change |
@@ -809,6 +812,9 @@ Expanded the dDRM Viewer to support four new interactive content types beyond th
809812
| `pc2-node/wasm-renderer/Cargo.toml` | `panic = "abort"` |
810813
| `pc2-node/scripts/build-wasm.sh` | Per-crate wasm-opt levels, SIMD + nontrapping-float-to-int flags |
811814
| `pc2-node/src/services/wasm/WASMRuntime.ts` | 20 hot-path logs downgraded to debug |
815+
| `pc2-node/src/api/media.ts` | CEK buffer zeroing in `unwrapECDHEnvelope` (`decrypted.fill(0)` after extraction) |
816+
| `pc2-node/src/utils/encryption.ts` | Derived key zeroing in mnemonic encrypt/decrypt (`key.fill(0)` in `finally`) |
817+
| `pc2-node/src/storage/ipfs.ts` | WASM assemble threshold lowered from 10MB to 5MB |
812818
| `pc2-node/wasm-apps/*/` | All 5 WASM binaries rebuilt |
813819

814820
**Market & Player UX fixes (Mar 19 — session 2):**

pc2-node/data/test-apps/elacity-market/api.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,29 @@ var ElacityAPI = (function () {
596596
).then(function (data) { return data.assets; });
597597
}
598598

599+
function fetchAccessibleAssetsForAddress(address, offset, limit) {
600+
var headers = { 'Content-Type': 'application/json' };
601+
if (authToken) headers['Authorization'] = 'Bearer ' + authToken;
602+
if (address) headers['X-ETH-Signer'] = address.toLowerCase();
603+
604+
var body = { query: {}, filters: { offset: offset || 0, limit: limit || 20, sort: { createdAt: -1 } } };
605+
return fetch(GQL_ENDPOINT, {
606+
method: 'POST',
607+
headers: headers,
608+
body: JSON.stringify({ query: FETCH_ACCESSIBLE_ASSETS_QUERY, variables: body })
609+
})
610+
.then(function (res) {
611+
if (!res.ok) throw new Error('API request failed: ' + res.status);
612+
return res.json();
613+
})
614+
.then(function (json) {
615+
if (json.errors && json.errors.length > 0 && (!json.data || Object.values(json.data).every(function (v) { return v === null; }))) {
616+
throw new Error(json.errors[0].message || 'GraphQL error');
617+
}
618+
return json.data ? json.data.assets : { total: 0, data: [] };
619+
});
620+
}
621+
599622
function fetchWithPreset(presetName, offset, limit) {
600623
var preset = PRESETS[presetName];
601624
if (!preset) throw new Error('Unknown preset: ' + presetName);
@@ -756,6 +779,7 @@ var ElacityAPI = (function () {
756779
return {
757780
fetchItems: fetchItems,
758781
fetchAccessibleAssets: fetchAccessibleAssets,
782+
fetchAccessibleAssetsForAddress: fetchAccessibleAssetsForAddress,
759783
fetchWithPreset: fetchWithPreset,
760784
getAssetDetail: getAssetDetail,
761785
getNonce: getNonce,

0 commit comments

Comments
 (0)