From 5e8f082f12095ae46d45bc3cb58b8a2a7b65533a Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Tue, 25 Aug 2026 14:55:33 +0200 Subject: [PATCH 01/17] Add UniFFI browser authenticator POC --- Cargo.lock | 112 +- Cargo.toml | 5 +- crates/walletkit-core/Cargo.toml | 4 + .../walletkit-core/src/authenticator/mod.rs | 9 +- .../uniffi-web-authenticator-poc/.gitignore | 6 + .../uniffi-web-authenticator-poc/AGENTS.md | 9 + .../uniffi-web-authenticator-poc/CLAUDE.md | 1 + .../uniffi-web-authenticator-poc/README.md | 53 + .../next-env.d.ts | 7 + .../package-lock.json | 1063 +++++++++++++++++ .../uniffi-web-authenticator-poc/package.json | 33 + .../rust/Cargo.toml | 16 + .../rust/src/lib.rs | 12 + .../scripts/patch-generated-index.mjs | 20 + .../scripts/patch-ubrn-wasm-bindgen.mjs | 36 + .../src/app/globals.css | 106 ++ .../src/app/layout.tsx | 19 + .../src/app/page.tsx | 184 +++ .../tsconfig.json | 30 + .../ubrn.config.yaml | 6 + 20 files changed, 1674 insertions(+), 57 deletions(-) create mode 100644 examples/uniffi-web-authenticator-poc/.gitignore create mode 100644 examples/uniffi-web-authenticator-poc/AGENTS.md create mode 100644 examples/uniffi-web-authenticator-poc/CLAUDE.md create mode 100644 examples/uniffi-web-authenticator-poc/README.md create mode 100644 examples/uniffi-web-authenticator-poc/next-env.d.ts create mode 100644 examples/uniffi-web-authenticator-poc/package-lock.json create mode 100644 examples/uniffi-web-authenticator-poc/package.json create mode 100644 examples/uniffi-web-authenticator-poc/rust/Cargo.toml create mode 100644 examples/uniffi-web-authenticator-poc/rust/src/lib.rs create mode 100644 examples/uniffi-web-authenticator-poc/scripts/patch-generated-index.mjs create mode 100644 examples/uniffi-web-authenticator-poc/scripts/patch-ubrn-wasm-bindgen.mjs create mode 100644 examples/uniffi-web-authenticator-poc/src/app/globals.css create mode 100644 examples/uniffi-web-authenticator-poc/src/app/layout.tsx create mode 100644 examples/uniffi-web-authenticator-poc/src/app/page.tsx create mode 100644 examples/uniffi-web-authenticator-poc/tsconfig.json create mode 100644 examples/uniffi-web-authenticator-poc/ubrn.config.yaml diff --git a/Cargo.lock b/Cargo.lock index 4ceabacc0..6bd2e0a45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1479,11 +1479,11 @@ dependencies = [ [[package]] name = "askama" -version = "0.15.6" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b8246bcbf8eb97abef10c2d92166449680d41d55c0fc6978a91dec2e3619608" +checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4" dependencies = [ - "askama_macros 0.15.6", + "askama_derive 0.14.0", "itoa", "percent-encoding", "serde", @@ -1492,11 +1492,11 @@ dependencies = [ [[package]] name = "askama" -version = "0.16.0" +version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf825125edd887a019d0a3a837dcc5499a68b0d034cc3eb594070c3e18addc" +checksum = "9b8246bcbf8eb97abef10c2d92166449680d41d55c0fc6978a91dec2e3619608" dependencies = [ - "askama_macros 0.16.0", + "askama_macros", "itoa", "percent-encoding", "serde", @@ -1505,11 +1505,11 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.15.6" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f9670bc84a28bb3da91821ef74226949ab63f1265aff7c751634f1dd0e6f97c" +checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f" dependencies = [ - "askama_parser 0.15.6", + "askama_parser 0.14.0", "basic-toml", "memchr", "proc-macro2", @@ -1522,13 +1522,12 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.16.0" +version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c7065972a130eafa84215f21352ae15b4a7393da48c1f5e103904490736738" +checksum = "2f9670bc84a28bb3da91821ef74226949ab63f1265aff7c751634f1dd0e6f97c" dependencies = [ - "askama_parser 0.16.0", + "askama_parser 0.15.6", "basic-toml", - "glob", "memchr", "proc-macro2", "quote", @@ -1547,33 +1546,23 @@ dependencies = [ "askama_derive 0.15.6", ] -[[package]] -name = "askama_macros" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e23b1d2c4bd39a41971f6124cef4cc6fd0540913ecb90919b69ab3bbe44ae1a" -dependencies = [ - "askama_derive 0.16.0", -] - [[package]] name = "askama_parser" -version = "0.15.6" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0af3691ba3af77949c0b5a3925444b85cb58a0184cc7fec16c68ba2e7be868" +checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358" dependencies = [ - "rustc-hash", + "memchr", "serde", "serde_derive", - "unicode-ident", - "winnow 1.0.3", + "winnow 0.7.15", ] [[package]] name = "askama_parser" -version = "0.16.0" +version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db09fde9143e7ac4513358fb32ee32847125b63b18ea715afd487956da715da" +checksum = "5d0af3691ba3af77949c0b5a3925444b85cb58a0184cc7fec16c68ba2e7be868" dependencies = [ "rustc-hash", "serde", @@ -2073,19 +2062,18 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.3.3" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", - "serde_core", ] [[package]] name = "cargo_metadata" -version = "0.23.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", @@ -3379,9 +3367,9 @@ dependencies = [ [[package]] name = "fs-err" -version = "3.3.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91aa448ca50d7e79433bdf3ee8d99215430d2ec02ade5aefab2a073a1822e8a" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" dependencies = [ "autocfg", ] @@ -9023,9 +9011,9 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "uniffi" -version = "0.32.0" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a782a48d72cfd7a2d65cfc7c691dbf5375c43104b3c195f7eccc716dcc3540c8" +checksum = "46eefd5468602930da46b1f49d3448c6dfc2e81295f93120f23f8174fd70267f" dependencies = [ "anyhow", "camino", @@ -9044,14 +9032,20 @@ dependencies = [ "uniffi", ] +[[package]] +name = "uniffi-runtime-wasm" +version = "0.31.0-5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb05d9a7313e50a448bbf2e28804c3acf477c379f25199476a7fff231b67f2f1" + [[package]] name = "uniffi_bindgen" -version = "0.32.0" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533b0312c73e3b54eb78a4b257ceae390962dd4767995778309a74644643f9ac" +checksum = "c4a0c9b375d32e1365cdb2bdd7cb495eecf6fac851ddbad077412b4ee1888514" dependencies = [ "anyhow", - "askama 0.16.0", + "askama 0.14.0", "camino", "cargo_metadata", "fs-err", @@ -9072,9 +9066,9 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.32.0" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e32e261c5b0dfaba6488f536e71957dddd6b1a498ac7eb791bee56b60a086be" +checksum = "eec017b112701681f6fbbe5d92014b5c468eb0b177a94389de03ceec40665095" dependencies = [ "anyhow", "async-compat", @@ -9085,9 +9079,9 @@ dependencies = [ [[package]] name = "uniffi_internal_macros" -version = "0.32.0" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84ae78069a5e6772ef694fd5bdb628532c88d2c2f0e7142bf6a384636eadb1af" +checksum = "4641669b48fefbc5e80ff08c5004d9c7617fb91232131a6734ab6712779cb04c" dependencies = [ "anyhow", "indexmap 2.14.0", @@ -9098,9 +9092,9 @@ dependencies = [ [[package]] name = "uniffi_macros" -version = "0.32.0" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330be6770532e86320df31f54c70bb0be67588594e8e77fa56e9083a3fed5d0d" +checksum = "eeb8617ee814de22caf7417bf514715ba0b3f46bd9d5a5d794413fd8282cb737" dependencies = [ "camino", "fs-err", @@ -9115,9 +9109,9 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.32.0" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78de021f5547e56ab16c665a49d67d4fd3d31e77422f7739a2e9359d328cd9e7" +checksum = "58d5b94fc92803d21b2928bd15c6f06e57609b95caf98ea561c99cda1b6d2a25" dependencies = [ "anyhow", "siphasher", @@ -9127,9 +9121,9 @@ dependencies = [ [[package]] name = "uniffi_pipeline" -version = "0.32.0" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f8201bb1907ed8a42d80e11cbc25c8a033e7a31c3cff1d911f56eedb81d4948" +checksum = "032739b3ec725576914c15899dedaf080163ced86b6934566c20ec2b20ce90ca" dependencies = [ "anyhow", "heck 0.5.0", @@ -9140,9 +9134,9 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.32.0" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e57996bc58009cc29bf04845d627ae313c2547b87171c1c349d6c51a1656c0" +checksum = "fc0a1d0a0252ce1af9e8ce78ba67ac0d8937fb2bedaf10cbddd43d3614d06ec6" dependencies = [ "anyhow", "textwrap", @@ -9415,6 +9409,15 @@ dependencies = [ "world-id-core", ] +[[package]] +name = "walletkit-web-authenticator-poc" +version = "0.0.0" +dependencies = [ + "uniffi", + "uniffi-runtime-wasm", + "walletkit-core", +] + [[package]] name = "want" version = "0.3.1" @@ -9968,6 +9971,9 @@ name = "winnow" version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] [[package]] name = "winnow" diff --git a/Cargo.toml b/Cargo.toml index 771670d43..b2f5cc4a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "crates/walletkit-sqlite", "crates/walletkit-cli", "crates/walletkit-testkit", + "examples/uniffi-web-authenticator-poc/rust", "xtask", ] resolver = "2" @@ -75,7 +76,9 @@ tokio-test = "0.4" tracing = "0.1" tracing-log = "0.2" tracing-subscriber = "0.3" -uniffi = { version = "0.32.0", features = [ +# uniffi-bindgen-react-native 0.31.0-5 cannot parse UniFFI 0.32 metadata yet. +# Keep this aligned with the generator until its UniFFI 0.32 support is released. +uniffi = { version = "0.31.2", features = [ "tokio", "wasm-unstable-single-threaded", ] } diff --git a/crates/walletkit-core/Cargo.toml b/crates/walletkit-core/Cargo.toml index 074830429..7c739fe34 100644 --- a/crates/walletkit-core/Cargo.toml +++ b/crates/walletkit-core/Cargo.toml @@ -116,6 +116,10 @@ compress-zkeys = [ issuers = [] +# Exports authenticator futures without UniFFI's Tokio compatibility adapter. +# Browser WASM has no thread on which async-compat can host its fallback runtime. +uniffi-wasm = [] + # Embeds compiled zkeys into the binary at compile time for `EmbeddedZkArtifacts`. # On native targets, `CachingZkArtifacts` can cache the embedded material on disk. # Disable this feature for environments where binary size matters (e.g. WASM). diff --git a/crates/walletkit-core/src/authenticator/mod.rs b/crates/walletkit-core/src/authenticator/mod.rs index 94031a096..3c0baf0dc 100644 --- a/crates/walletkit-core/src/authenticator/mod.rs +++ b/crates/walletkit-core/src/authenticator/mod.rs @@ -100,7 +100,8 @@ fn parse_authenticator_pubkey( Ok(pubkey) } -#[uniffi::export(async_runtime = "tokio")] +#[cfg_attr(feature = "uniffi-wasm", uniffi::export)] +#[cfg_attr(not(feature = "uniffi-wasm"), uniffi::export(async_runtime = "tokio"))] impl Authenticator { /// Returns the packed account data for the holder's World ID. /// @@ -494,7 +495,8 @@ impl Authenticator { } } -#[uniffi::export(async_runtime = "tokio")] +#[cfg_attr(feature = "uniffi-wasm", uniffi::export)] +#[cfg_attr(not(feature = "uniffi-wasm"), uniffi::export(async_runtime = "tokio"))] impl Authenticator { /// Initializes a new Authenticator from a seed and with SDK defaults. /// @@ -842,7 +844,8 @@ impl From for RegistrationStatus { #[derive(uniffi::Object)] pub struct InitializingAuthenticator(CoreInitializingAuthenticator); -#[uniffi::export(async_runtime = "tokio")] +#[cfg_attr(feature = "uniffi-wasm", uniffi::export)] +#[cfg_attr(not(feature = "uniffi-wasm"), uniffi::export(async_runtime = "tokio"))] impl InitializingAuthenticator { /// Registers a new World ID with SDK defaults. /// diff --git a/examples/uniffi-web-authenticator-poc/.gitignore b/examples/uniffi-web-authenticator-poc/.gitignore new file mode 100644 index 000000000..434b431c5 --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/.gitignore @@ -0,0 +1,6 @@ +.next/ +dist/ +node_modules/ +public/wasm/ +rust/Cargo.lock +src/generated/ diff --git a/examples/uniffi-web-authenticator-poc/AGENTS.md b/examples/uniffi-web-authenticator-poc/AGENTS.md new file mode 100644 index 000000000..643577dfa --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/AGENTS.md @@ -0,0 +1,9 @@ + + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. + +This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. + + diff --git a/examples/uniffi-web-authenticator-poc/CLAUDE.md b/examples/uniffi-web-authenticator-poc/CLAUDE.md new file mode 100644 index 000000000..43c994c2d --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/examples/uniffi-web-authenticator-poc/README.md b/examples/uniffi-web-authenticator-poc/README.md new file mode 100644 index 000000000..7eb9abb55 --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/README.md @@ -0,0 +1,53 @@ +# WalletKit UniFFI browser authenticator POC + +> PROTOTYPE: throwaway feasibility probe, not production packaging. + +This example asks one question: can WalletKit's existing UniFFI authenticator +surface be generated, loaded, and called from a Next.js App Router application +through `uniffi-bindgen-react-native`'s WASM player? + +Run it with: + +```sh +npm install +npm run dev +``` + +`npm run dev` regenerates the bindings before starting Next.js. Use +`npm run build` to prove the production bundle as well. + +The Rust wrapper is deliberately local to this example so the WASM player's +runtime dependency does not leak into WalletKit's production crate graph. + +## What the POC proves + +- The generator can produce TypeScript for WalletKit records, errors, objects, + callbacks, and async authenticator methods. +- The generated WASM loads in a browser and calls WalletKit synchronously to + derive authenticator recovery material from secure browser randomness. +- Next.js can bundle the generated JavaScript glue in a Client Component while + serving the generated WASM as a static asset from `public/wasm`. +- An async authenticator constructor crosses the generated future/error bridge; + the smoke call uses invalid configuration and stops before any network request. +- The UI wires the generated async `InitializingAuthenticator` registration and + polling methods. Registration is an explicit, opt-in staging mutation. + +## Experimental compatibility pins + +The released generator (`0.31.0-5`) cannot parse UniFFI 0.32 metadata, so this +POC pins the worktree to UniFFI 0.31.2. Its internal wasm-bindgen processor is +also pinned to 0.2.100, while `sqlite-wasm-rs` requires a newer schema; the +postinstall script aligns the generator to WalletKit's 0.2.126 schema. + +WalletKit's native bindings ask UniFFI to adapt exported futures to Tokio. That +adapter creates a fallback thread when it is polled without a Tokio runtime, +which browser WASM cannot do. The POC enables `walletkit-core/uniffi-wasm` so +only the authenticator exports skip that adapter and are polled directly by the +generator's WASM player; native builds keep their existing Tokio behavior. + +The generated bindings are imported dynamically from a Client Component. This +keeps the WASM player and browser-only APIs out of Next.js server rendering. + +The generated WASM is around 6 MB in release mode before HTTP compression. No +attempt has been made to productionize storage, artifact loading, worker +placement, bundle splitting, or key persistence. diff --git a/examples/uniffi-web-authenticator-poc/next-env.d.ts b/examples/uniffi-web-authenticator-poc/next-env.d.ts new file mode 100644 index 000000000..ce4e94a6b --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/next-env.d.ts @@ -0,0 +1,7 @@ +/// +/// +import "./.next/types/routes.d.ts"; +import "./.next/types/root-params.d.ts"; + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/examples/uniffi-web-authenticator-poc/package-lock.json b/examples/uniffi-web-authenticator-poc/package-lock.json new file mode 100644 index 000000000..b4c991ec7 --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/package-lock.json @@ -0,0 +1,1063 @@ +{ + "name": "walletkit-uniffi-web-authenticator-poc", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "walletkit-uniffi-web-authenticator-poc", + "version": "0.0.0", + "hasInstallScript": true, + "dependencies": { + "@ubjs/core": "0.31.0-5", + "@ubjs/wasm": "0.31.0-5", + "next": "16.3.2", + "react": "19.2.8", + "react-dom": "19.2.8" + }, + "devDependencies": { + "@types/node": "25.0.3", + "@types/react": "19.2.14", + "@types/react-dom": "19.2.3", + "prettier": "3.6.2", + "typescript": "5.9.2", + "uniffi-bindgen-react-native": "0.31.0-5" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@next/env": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.2.tgz", + "integrity": "sha512-8k4YoG8cM7LWlkfzGNYCRBbFNlernLiMw4s0btVl+CmmWqn3VpYypA72/5Feb1UWdxe6tHqr5KHP4p4Y4m9luA==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.2.tgz", + "integrity": "sha512-ib5Llm93YCKoKWDh6ZaHq6QWTuOZ2bRkSnUwMmX8dsRIOkBNL1vVlSiUKSfixPL9SSh9pvukzqajk/klkn5vqg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.2.tgz", + "integrity": "sha512-qd98fX2+I5nYJDioW2o7nSjoxM5KvWdeDefM80igia4+C/qSIEhH4MhTE+hO/7qKM7W37/Mq+dOWp8UePSyLHw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.2.tgz", + "integrity": "sha512-vqsgb6FAOzcrCccsLXiKtAy5t8EzO+uOazuFaSkQxeY0tNONG3vpHYy8pyBafcI5SNFPTeyard6yTr6SzNGo2A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.2.tgz", + "integrity": "sha512-xIe1eujfHUB2XcxHGddxJyu6TJRPjC5NpIkQYB/32ESkt5VkQyIAjmLRS38c+s6QY+qjtY/4KarVDzXRuD7lZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.2.tgz", + "integrity": "sha512-Fe0SA2j8X0kmc3aveuHD7UktO3AE2+mH3LguP60vGbz7u0z+MrDXbeb5iZFYAwR7EzzzXJ2Yk966w9mGTFMqfA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.2.tgz", + "integrity": "sha512-TFBipb+gyesI/2Ve4zVu7kGltBWN/R466G5/1gtt2lECfc22G1pjkTxu68Q9aFcOaXiRGTQfvDbQQFe7mYgxiQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.2.tgz", + "integrity": "sha512-rVtmnNpBYIosDnKD/96dKxFsJnwnn1WRGG/HioSe8XCm2ksSHNrd2R6+hSjvTBxeMNhJ9pYeu/90cWB1nQLuNA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.2.tgz", + "integrity": "sha512-H4Y2o2/JcHu8LtwzD5CXfHhwxwz8gfsx2HXDEw46Mtev5xHnEmB7HNtZtmriw5ReUOjRtcDqo7XSbU01FT9NlA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@types/node": { + "version": "25.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz", + "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@ubjs/core": { + "version": "0.31.0-5", + "resolved": "https://registry.npmjs.org/@ubjs/core/-/core-0.31.0-5.tgz", + "integrity": "sha512-oRBRtyYOhaodiOY3rLMZFgAHGFMmD44XefMpsAx4Ja0/rO+45kVdQB1VZsblQMLYxP965i3IHm56eymgo3I5eQ==", + "license": "MPL-2.0" + }, + "node_modules/@ubjs/wasm": { + "version": "0.31.0-5", + "resolved": "https://registry.npmjs.org/@ubjs/wasm/-/wasm-0.31.0-5.tgz", + "integrity": "sha512-dO7i67DQ1UKBSegznLVjVrYowmxY7gaXXluBdtJXPYgcR5vzwYf2ZbxAUqj4qL1JkqxRmeTKgXtuesFI+D5dPg==", + "license": "MPL-2.0", + "peerDependencies": { + "@ubjs/core": "^0.31.0-5" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.19.tgz", + "integrity": "sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001810", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", + "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/next/-/next-16.3.2.tgz", + "integrity": "sha512-/ZCaubUy17Lld1SiPWxuPbCk2ihqAxF2QNQaPZeEaEb7t1I58qhsJN187D7AfpapHAqUPXH0f/thtdW9dWgWFg==", + "license": "MIT", + "dependencies": { + "@next/env": "16.3.2", + "@swc/helpers": "0.5.23", + "baseline-browser-mapping": "^2.9.19", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.5.23", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.3.2", + "@next/swc-darwin-x64": "16.3.2", + "@next/swc-linux-arm64-gnu": "16.3.2", + "@next/swc-linux-arm64-musl": "16.3.2", + "@next/swc-linux-x64-gnu": "16.3.2", + "@next/swc-linux-x64-musl": "16.3.2", + "@next/swc-win32-arm64-msvc": "16.3.2", + "@next/swc-win32-x64-msvc": "16.3.2", + "sharp": "^0.35.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.8" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uniffi-bindgen-react-native": { + "version": "0.31.0-5", + "resolved": "https://registry.npmjs.org/uniffi-bindgen-react-native/-/uniffi-bindgen-react-native-0.31.0-5.tgz", + "integrity": "sha512-YtL3gTe+RVXAQx/2P2Iuypic/CunRZC65Cs47v//YRfwWNYU4Ufd1jT3rqxSrH5b5QFCYblP89Nf/9ssZRvNgg==", + "dev": true, + "license": "MPL-2.0", + "bin": { + "ubrn": "bin/cli.cjs", + "uniffi-bindgen-react-native": "bin/cli.cjs" + } + } + } +} diff --git a/examples/uniffi-web-authenticator-poc/package.json b/examples/uniffi-web-authenticator-poc/package.json new file mode 100644 index 000000000..e6dcb0663 --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/package.json @@ -0,0 +1,33 @@ +{ + "name": "walletkit-uniffi-web-authenticator-poc", + "private": true, + "version": "0.0.0", + "type": "module", + "repository": { + "type": "git", + "url": "https://github.com/worldcoin/walletkit" + }, + "scripts": { + "postinstall": "node scripts/patch-ubrn-wasm-bindgen.mjs", + "bindings": "CC_wasm32_unknown_unknown=/opt/homebrew/opt/llvm/bin/clang ubrn build wasm2 --config ubrn.config.yaml --release && node scripts/patch-generated-index.mjs", + "predev": "npm run bindings", + "dev": "next dev", + "build": "npm run bindings && next build", + "start": "next start" + }, + "dependencies": { + "@ubjs/core": "0.31.0-5", + "@ubjs/wasm": "0.31.0-5", + "next": "16.3.2", + "react": "19.2.8", + "react-dom": "19.2.8" + }, + "devDependencies": { + "@types/node": "25.0.3", + "@types/react": "19.2.14", + "@types/react-dom": "19.2.3", + "prettier": "3.6.2", + "typescript": "5.9.2", + "uniffi-bindgen-react-native": "0.31.0-5" + } +} diff --git a/examples/uniffi-web-authenticator-poc/rust/Cargo.toml b/examples/uniffi-web-authenticator-poc/rust/Cargo.toml new file mode 100644 index 000000000..833f2d58d --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/rust/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "walletkit-web-authenticator-poc" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["lib", "cdylib"] +name = "walletkit_web_authenticator_poc" + +[dependencies] +uniffi = { version = "0.31.2", features = ["tokio", "wasm-unstable-single-threaded"] } +walletkit-core = { path = "../../../crates/walletkit-core", default-features = false, features = ["uniffi-wasm"] } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +uniffi-runtime-wasm = "0.31.0-5" diff --git a/examples/uniffi-web-authenticator-poc/rust/src/lib.rs b/examples/uniffi-web-authenticator-poc/rust/src/lib.rs new file mode 100644 index 000000000..a8b59bcde --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/rust/src/lib.rs @@ -0,0 +1,12 @@ +//! PROTOTYPE: browser bindings for WalletKit's existing UniFFI API. + +extern crate walletkit_core; + +#[cfg(target_arch = "wasm32")] +extern crate uniffi_runtime_wasm as _; + +walletkit_core::uniffi_reexport_scaffolding!(); + +pub use walletkit_core::*; + +uniffi::setup_scaffolding!("walletkit_web_authenticator_poc"); diff --git a/examples/uniffi-web-authenticator-poc/scripts/patch-generated-index.mjs b/examples/uniffi-web-authenticator-poc/scripts/patch-generated-index.mjs new file mode 100644 index 000000000..2a10544df --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/scripts/patch-generated-index.mjs @@ -0,0 +1,20 @@ +// PROTOTYPE workaround: ubrn 0.31.0-5 emits readonly player definitions that +// @ubjs/wasm 0.31.0-5 types as mutable, and omits a declaration for its +// generated wasm-bindgen glue module. Runtime shapes are compatible. +import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; + +const generatedIndex = new URL("../src/generated/index.ts", import.meta.url); +const source = readFileSync(generatedIndex, "utf8"); +if (!source.startsWith("// @ts-nocheck")) { + writeFileSync(generatedIndex, `// @ts-nocheck\n${source}`); +} + +const publicWasm = new URL("../public/wasm/", import.meta.url); +mkdirSync(publicWasm, { recursive: true }); +copyFileSync( + new URL( + "../src/generated/walletkit_web_authenticator_poc.wasm", + import.meta.url, + ), + new URL("walletkit_web_authenticator_poc.wasm", publicWasm), +); diff --git a/examples/uniffi-web-authenticator-poc/scripts/patch-ubrn-wasm-bindgen.mjs b/examples/uniffi-web-authenticator-poc/scripts/patch-ubrn-wasm-bindgen.mjs new file mode 100644 index 000000000..73aa1e34d --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/scripts/patch-ubrn-wasm-bindgen.mjs @@ -0,0 +1,36 @@ +// PROTOTYPE workaround: sqlite-wasm-rs requires wasm-bindgen >= 0.2.104, +// while ubrn 0.31.0-5 pins its post-processor to 0.2.100. Both sides must use +// the exact same schema, so align the installed generator with WalletKit. +import { execFileSync } from "node:child_process"; +import { readFileSync, writeFileSync } from "node:fs"; + +const root = new URL( + "../node_modules/uniffi-bindgen-react-native/", + import.meta.url, +); +const manifest = new URL("Cargo.toml", root); +const lockfile = new URL("Cargo.lock", root); +const oldDependency = 'wasm-bindgen-cli-support = "=0.2.100"'; +const newDependency = 'wasm-bindgen-cli-support = "=0.2.126"'; + +const source = readFileSync(manifest, "utf8"); +if (source.includes(oldDependency)) { + writeFileSync(manifest, source.replace(oldDependency, newDependency)); +} + +const lock = readFileSync(lockfile, "utf8"); +if (/name = "wasm-bindgen-cli-support"\nversion = "0\.2\.100"/.test(lock)) { + execFileSync( + "cargo", + [ + "update", + "--manifest-path", + manifest.pathname, + "-p", + "wasm-bindgen-cli-support@0.2.100", + "--precise", + "0.2.126", + ], + { stdio: "inherit" }, + ); +} diff --git a/examples/uniffi-web-authenticator-poc/src/app/globals.css b/examples/uniffi-web-authenticator-poc/src/app/globals.css new file mode 100644 index 000000000..cd80c060f --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/src/app/globals.css @@ -0,0 +1,106 @@ +:root { + color: #15261f; + background: #eaf1ec; + font-family: Inter, ui-sans-serif, system-ui, sans-serif; +} + +* { + box-sizing: border-box; +} + +body { + min-height: 100vh; + margin: 0; +} + +main { + min-height: 100vh; + display: grid; + place-items: center; + padding: 1.5rem; +} + +.card { + width: min(42rem, 100%); + padding: 2rem; + border: 1px solid #bdcbc3; + border-radius: 1rem; + background: #f9fbf9; + box-shadow: 0 1rem 3rem rgb(24 54 42 / 10%); +} + +.eyebrow { + color: #167552; + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +h1 { + margin: 0.5rem 0 1rem; +} + +pre { + overflow: auto; + margin: 1.5rem 0 0; + padding: 1rem; + border-radius: 0.5rem; + color: #d9f7e8; + background: #10231b; + white-space: pre-wrap; +} + +dl { + display: grid; + gap: 0.75rem; + margin: 1.5rem 0; +} + +dl div { + padding-bottom: 0.75rem; + border-bottom: 1px solid #dce5df; +} + +dt { + margin-bottom: 0.25rem; + color: #567064; + font-size: 0.75rem; + font-weight: 700; + text-transform: uppercase; +} + +dd { + overflow-wrap: anywhere; + margin: 0; + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 0.85rem; +} + +button { + margin: 0.5rem 0.5rem 0.5rem 0; + padding: 0.7rem 1rem; + border: 0; + border-radius: 0.5rem; + color: white; + background: #167552; + font-weight: 700; + cursor: pointer; +} + +button:disabled { + cursor: not-allowed; + opacity: 0.45; +} + +details { + margin-top: 1.25rem; + padding: 1rem; + border: 1px solid #d1ddd5; + border-radius: 0.5rem; +} + +summary { + cursor: pointer; + font-weight: 700; +} diff --git a/examples/uniffi-web-authenticator-poc/src/app/layout.tsx b/examples/uniffi-web-authenticator-poc/src/app/layout.tsx new file mode 100644 index 000000000..d3eb0d3c9 --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/src/app/layout.tsx @@ -0,0 +1,19 @@ +import type { Metadata } from "next"; +import type { ReactNode } from "react"; + +import "./globals.css"; + +export const metadata: Metadata = { + title: "WalletKit UniFFI browser POC", + description: "WalletKit authenticator running as browser WASM in Next.js", +}; + +export default function RootLayout({ + children, +}: Readonly<{ children: ReactNode }>) { + return ( + + {children} + + ); +} diff --git a/examples/uniffi-web-authenticator-poc/src/app/page.tsx b/examples/uniffi-web-authenticator-poc/src/app/page.tsx new file mode 100644 index 000000000..2351f1c51 --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/src/app/page.tsx @@ -0,0 +1,184 @@ +"use client"; + +import { useEffect, useRef, useState } from "react"; + +import type { InitializingAuthenticatorLike, RecoveryData } from "../generated"; + +type WalletKitBindings = typeof import("../generated"); + +const WASM_URL = "/wasm/walletkit_web_authenticator_poc.wasm"; + +function printableState(state: string) { + return JSON.stringify( + { + state, + environment: "staging", + region: "eu", + seed: "32 random bytes held only in memory", + }, + null, + 2, + ); +} + +export default function Home() { + const bindings = useRef(null); + const seed = useRef(new Uint8Array(32)); + const registration = useRef(undefined); + const initialized = useRef(false); + const [runtime, setRuntime] = useState("Loading…"); + const [asyncBridge, setAsyncBridge] = useState("Pending…"); + const [recovery, setRecovery] = useState(); + const [confirmed, setConfirmed] = useState(false); + const [registering, setRegistering] = useState(false); + const [canPoll, setCanPoll] = useState(false); + const [status, setStatus] = useState("Initializing generated bindings…"); + + function deriveAuthenticator(module = bindings.current) { + if (!module) return; + seed.current = crypto.getRandomValues(new Uint8Array(32)); + setRecovery( + module.recoveryDataFromSeed(new Uint8Array(seed.current).buffer), + ); + registration.current = undefined; + setCanPoll(false); + setStatus(printableState("authenticator-derived")); + } + + useEffect(() => { + if (initialized.current) return; + initialized.current = true; + + void (async () => { + try { + const module = await import("../generated"); + bindings.current = module; + await module.uniffiInitAsync(WASM_URL); + setRuntime("Ready"); + deriveAuthenticator(module); + + try { + await module.InitializingAuthenticator.register( + new Uint8Array(seed.current).buffer, + "invalid config used only to exercise async error lifting", + undefined, + ); + setAsyncBridge("Unexpected success"); + } catch { + setAsyncBridge("Ready (Rust rejected the invalid config)"); + } + } catch (error) { + setRuntime("Failed"); + setStatus(String(error)); + } + })(); + }, []); + + async function registerAuthenticator() { + const module = bindings.current; + if (!module) return; + setRegistering(true); + setStatus("Sending registration request to the staging gateway…"); + try { + registration.current = + await module.InitializingAuthenticator.registerWithDefaults( + new Uint8Array(seed.current).buffer, + undefined, + module.Environment.Staging, + module.Region.Eu, + undefined, + ); + setCanPoll(true); + setStatus(JSON.stringify({ state: "registration-requested" }, null, 2)); + } catch (error) { + setStatus(String(error)); + } finally { + setRegistering(false); + } + } + + async function pollRegistration() { + if (!registration.current) return; + setCanPoll(false); + try { + const result = await registration.current.pollStatus(); + setStatus( + JSON.stringify({ state: "registration-polled", result }, null, 2), + ); + } catch (error) { + setStatus(String(error)); + } finally { + setCanPoll(true); + } + } + + return ( +
+
+

Throwaway Next.js feasibility probe

+

WalletKit authenticator in browser WASM

+

+ This Client Component loads WalletKit's real UniFFI surface + through the generator's WASM player and derives fresh + authenticator material entirely inside the browser. +

+
+
+
WASM runtime
+
{runtime}
+
+
+
Async UniFFI bridge
+
{asyncBridge}
+
+
+
Authenticator address
+
{recovery?.authenticatorAddress ?? "—"}
+
+
+
Authenticator public key
+
{recovery?.authenticatorPubkey ?? "—"}
+
+
+
Signer commitment
+
{recovery?.offchainSignerCommitment ?? "—"}
+
+
+ +
+ Optional network proof: register on staging +

+ This sends a real account-registration request to WalletKit's + staging gateway. The seed remains in this tab and is discarded on + refresh. +

+ +
+ + +
+
+
{status}
+
+
+ ); +} diff --git a/examples/uniffi-web-authenticator-poc/tsconfig.json b/examples/uniffi-web-authenticator-poc/tsconfig.json new file mode 100644 index 000000000..470da820c --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "allowJs": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "skipLibCheck": true + }, + "include": [ + "next-env.d.ts", + "src/**/*.ts", + "src/**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": ["node_modules"] +} diff --git a/examples/uniffi-web-authenticator-poc/ubrn.config.yaml b/examples/uniffi-web-authenticator-poc/ubrn.config.yaml new file mode 100644 index 000000000..a9433e45d --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/ubrn.config.yaml @@ -0,0 +1,6 @@ +rust: + directory: ./rust + manifestPath: Cargo.toml + +wasm2: + ts: src/generated From f17a9956ac46300252efea46e90cbd3d41867527 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Tue, 25 Aug 2026 15:25:17 +0200 Subject: [PATCH 02/17] Link upstream UniFFI 0.32 upgrade --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b2f5cc4a5..e4740b907 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,7 +77,7 @@ tracing = "0.1" tracing-log = "0.2" tracing-subscriber = "0.3" # uniffi-bindgen-react-native 0.31.0-5 cannot parse UniFFI 0.32 metadata yet. -# Keep this aligned with the generator until its UniFFI 0.32 support is released. +# Remove this pin once https://github.com/jhugman/uniffi-bindgen-react-native/pull/409 lands. uniffi = { version = "0.31.2", features = [ "tokio", "wasm-unstable-single-threaded", From a3e8b1295357475bfd49418f5c7e402be8158b33 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Tue, 25 Aug 2026 17:10:02 +0200 Subject: [PATCH 03/17] Use Nix toolchain for browser WASM build --- .../uniffi-web-authenticator-poc/README.md | 17 ++++++++++------- .../uniffi-web-authenticator-poc/package.json | 2 +- .../scripts/optimize-wasm.mjs | 18 ++++++++++++++++++ nix/README.md | 2 +- nix/wasm.nix | 2 ++ 5 files changed, 32 insertions(+), 9 deletions(-) create mode 100644 examples/uniffi-web-authenticator-poc/scripts/optimize-wasm.mjs diff --git a/examples/uniffi-web-authenticator-poc/README.md b/examples/uniffi-web-authenticator-poc/README.md index 7eb9abb55..33c4ff0cd 100644 --- a/examples/uniffi-web-authenticator-poc/README.md +++ b/examples/uniffi-web-authenticator-poc/README.md @@ -6,15 +6,17 @@ This example asks one question: can WalletKit's existing UniFFI authenticator surface be generated, loaded, and called from a Next.js App Router application through `uniffi-bindgen-react-native`'s WASM player? -Run it with: +Run it from the repository root with the pinned WASM toolchain: ```sh -npm install -npm run dev +nix develop .#wasm --command npm --prefix examples/uniffi-web-authenticator-poc install +nix develop .#wasm --command npm --prefix examples/uniffi-web-authenticator-poc run dev ``` `npm run dev` regenerates the bindings before starting Next.js. Use -`npm run build` to prove the production bundle as well. +`npm run build` to prove the production bundle as well. These scripts expect to +run inside `nix develop .#wasm`, which supplies Node, Binaryen, and the +WASM-targeted Clang and LLVM tools. The Rust wrapper is deliberately local to this example so the WASM player's runtime dependency does not leak into WalletKit's production crate graph. @@ -48,6 +50,7 @@ generator's WASM player; native builds keep their existing Tokio behavior. The generated bindings are imported dynamically from a Client Component. This keeps the WASM player and browser-only APIs out of Next.js server rendering. -The generated WASM is around 6 MB in release mode before HTTP compression. No -attempt has been made to productionize storage, artifact loading, worker -placement, bundle splitting, or key persistence. +The generated WASM is optimized with Binaryen's `wasm-opt -Oz --converge` +before it is copied into the Next.js public assets. No attempt has been made to +productionize storage, artifact loading, worker placement, bundle splitting, +or key persistence. diff --git a/examples/uniffi-web-authenticator-poc/package.json b/examples/uniffi-web-authenticator-poc/package.json index e6dcb0663..0ecfef29a 100644 --- a/examples/uniffi-web-authenticator-poc/package.json +++ b/examples/uniffi-web-authenticator-poc/package.json @@ -9,7 +9,7 @@ }, "scripts": { "postinstall": "node scripts/patch-ubrn-wasm-bindgen.mjs", - "bindings": "CC_wasm32_unknown_unknown=/opt/homebrew/opt/llvm/bin/clang ubrn build wasm2 --config ubrn.config.yaml --release && node scripts/patch-generated-index.mjs", + "bindings": "ubrn build wasm2 --config ubrn.config.yaml --release && node scripts/optimize-wasm.mjs && node scripts/patch-generated-index.mjs", "predev": "npm run bindings", "dev": "next dev", "build": "npm run bindings && next build", diff --git a/examples/uniffi-web-authenticator-poc/scripts/optimize-wasm.mjs b/examples/uniffi-web-authenticator-poc/scripts/optimize-wasm.mjs new file mode 100644 index 000000000..aaf34e5b0 --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/scripts/optimize-wasm.mjs @@ -0,0 +1,18 @@ +// Optimize the generated module before it is copied into Next.js public assets. +// Binaryen is supplied by the repository's `nix develop .#wasm` shell. +import { execFileSync } from "node:child_process"; +import { renameSync } from "node:fs"; +import { fileURLToPath } from "node:url"; + +const wasm = fileURLToPath( + new URL( + "../src/generated/walletkit_web_authenticator_poc.wasm", + import.meta.url, + ), +); +const optimized = `${wasm}.optimized`; + +execFileSync("wasm-opt", [wasm, "-Oz", "--converge", "-o", optimized], { + stdio: "inherit", +}); +renameSync(optimized, wasm); diff --git a/nix/README.md b/nix/README.md index a384f27f3..e06ce9483 100644 --- a/nix/README.md +++ b/nix/README.md @@ -15,7 +15,7 @@ ordinary `cargo build` invocations run inside a shell. |---|---|---| | `default` | Host builds, uniffi-bindgen, nargo | all | | `android` | Cross-compile the 4 Android targets (NDK, linkers, API 23) | linux/darwin x86_64, darwin aarch64 | -| `wasm` | `wasm32-unknown-unknown` builds and headless browser tests | all | +| `wasm` | `wasm32-unknown-unknown` builds and headless browser tests with Node and Binaryen | all | ```bash nix develop .#android # enter a shell diff --git a/nix/wasm.nix b/nix/wasm.nix index c1993828e..9e5f69805 100644 --- a/nix/wasm.nix +++ b/nix/wasm.nix @@ -21,9 +21,11 @@ pkgs.mkShell { llvm.clang-unwrapped llvm.bintools-unwrapped wasmBindgenCli + pkgs.binaryen pkgs.curl pkgs.git pkgs.nargo + pkgs.nodejs ] ++ pkgs.lib.optionals firefoxAvailable [ pkgs.firefox From 659f3ce455407a71e09f01b1c5c6d165c0d6bb0e Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Tue, 25 Aug 2026 18:11:14 +0200 Subject: [PATCH 04/17] Package WalletKit browser bindings --- Cargo.lock | 10 +- Cargo.toml | 1 - README.md | 14 + crates/walletkit/Cargo.toml | 5 + crates/walletkit/src/lib.rs | 4 + .../uniffi-web-authenticator-poc/.gitignore | 3 - .../uniffi-web-authenticator-poc/README.md | 58 +- .../next.config.ts | 13 + .../package-lock.json | 45 +- .../uniffi-web-authenticator-poc/package.json | 13 +- .../rust/Cargo.toml | 16 - .../rust/src/lib.rs | 12 - .../src/app/page.tsx | 25 +- nix/README.md | 1 + web/walletkit/.gitignore | 3 + web/walletkit/README.md | 26 + web/walletkit/package-lock.json | 562 ++++++++++++++++++ web/walletkit/package.json | 42 ++ web/walletkit/scripts/clean.mjs | 3 + web/walletkit/scripts/copy-wasm.mjs | 8 + .../walletkit}/scripts/optimize-wasm.mjs | 7 +- .../scripts/patch-generated-index.mjs | 12 +- .../scripts/patch-ubrn-wasm-bindgen.mjs | 10 +- web/walletkit/src/index.ts | 19 + web/walletkit/tsconfig.build.json | 17 + .../walletkit}/ubrn.config.yaml | 3 +- 26 files changed, 795 insertions(+), 137 deletions(-) create mode 100644 examples/uniffi-web-authenticator-poc/next.config.ts delete mode 100644 examples/uniffi-web-authenticator-poc/rust/Cargo.toml delete mode 100644 examples/uniffi-web-authenticator-poc/rust/src/lib.rs create mode 100644 web/walletkit/.gitignore create mode 100644 web/walletkit/README.md create mode 100644 web/walletkit/package-lock.json create mode 100644 web/walletkit/package.json create mode 100644 web/walletkit/scripts/clean.mjs create mode 100644 web/walletkit/scripts/copy-wasm.mjs rename {examples/uniffi-web-authenticator-poc => web/walletkit}/scripts/optimize-wasm.mjs (69%) rename {examples/uniffi-web-authenticator-poc => web/walletkit}/scripts/patch-generated-index.mjs (55%) rename {examples/uniffi-web-authenticator-poc => web/walletkit}/scripts/patch-ubrn-wasm-bindgen.mjs (82%) create mode 100644 web/walletkit/src/index.ts create mode 100644 web/walletkit/tsconfig.build.json rename {examples/uniffi-web-authenticator-poc => web/walletkit}/ubrn.config.yaml (50%) diff --git a/Cargo.lock b/Cargo.lock index 6bd2e0a45..0630d9213 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9276,6 +9276,7 @@ name = "walletkit" version = "0.22.0" dependencies = [ "uniffi", + "uniffi-runtime-wasm", "walletkit-core", ] @@ -9409,15 +9410,6 @@ dependencies = [ "world-id-core", ] -[[package]] -name = "walletkit-web-authenticator-poc" -version = "0.0.0" -dependencies = [ - "uniffi", - "uniffi-runtime-wasm", - "walletkit-core", -] - [[package]] name = "want" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index e4740b907..8cf975bd4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ members = [ "crates/walletkit-sqlite", "crates/walletkit-cli", "crates/walletkit-testkit", - "examples/uniffi-web-authenticator-poc/rust", "xtask", ] resolver = "2" diff --git a/README.md b/README.md index 55cadeeaf..ec47eaddd 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,20 @@ binding tests with `cargo xtask swift test`. See [`swift/README.md`](swift/README.md) for package integration details. +## Local development (browser/WASM) + +The experimental `@worldcoin/walletkit-web` package builds directly from the +`walletkit` crate and contains the generated bindings, wasm-bindgen glue, and +optimized WASM module. Build it with the pinned WASM toolchain: + +```bash +nix develop .#wasm --command npm --prefix web/walletkit install +nix develop .#wasm --command npm --prefix web/walletkit run build +``` + +The Next.js integration probe under `examples/uniffi-web-authenticator-poc` +consumes the package through its public `initializeWalletKit()` interface. + ## Local development (Android/Kotlin) ### Prerequisites diff --git a/crates/walletkit/Cargo.toml b/crates/walletkit/Cargo.toml index 63c292b17..8170e32c1 100644 --- a/crates/walletkit/Cargo.toml +++ b/crates/walletkit/Cargo.toml @@ -23,6 +23,11 @@ name = "walletkit" walletkit-core = { workspace = true } uniffi = { workspace = true } +[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies] +# ubrn's browser player supplies the UniFFI runtime imports for the generated module. +uniffi-runtime-wasm = "0.31.0-5" +walletkit-core = { workspace = true, features = ["uniffi-wasm"] } + [features] default = ["issuers"] semaphore = ["walletkit-core/semaphore"] diff --git a/crates/walletkit/src/lib.rs b/crates/walletkit/src/lib.rs index 864eac6fb..3ea1cc11c 100644 --- a/crates/walletkit/src/lib.rs +++ b/crates/walletkit/src/lib.rs @@ -5,6 +5,10 @@ //! [`walletkit_core`]. extern crate walletkit_core; + +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +extern crate uniffi_runtime_wasm as _; + walletkit_core::uniffi_reexport_scaffolding!(); pub use walletkit_core::*; diff --git a/examples/uniffi-web-authenticator-poc/.gitignore b/examples/uniffi-web-authenticator-poc/.gitignore index 434b431c5..e0411220b 100644 --- a/examples/uniffi-web-authenticator-poc/.gitignore +++ b/examples/uniffi-web-authenticator-poc/.gitignore @@ -1,6 +1,3 @@ .next/ dist/ node_modules/ -public/wasm/ -rust/Cargo.lock -src/generated/ diff --git a/examples/uniffi-web-authenticator-poc/README.md b/examples/uniffi-web-authenticator-poc/README.md index 33c4ff0cd..d2372e89a 100644 --- a/examples/uniffi-web-authenticator-poc/README.md +++ b/examples/uniffi-web-authenticator-poc/README.md @@ -1,34 +1,35 @@ -# WalletKit UniFFI browser authenticator POC +# WalletKit web package Next.js example -> PROTOTYPE: throwaway feasibility probe, not production packaging. +> PROTOTYPE: integration probe for the private `@worldcoin/walletkit-web` +> package, not production packaging. -This example asks one question: can WalletKit's existing UniFFI authenticator -surface be generated, loaded, and called from a Next.js App Router application -through `uniffi-bindgen-react-native`'s WASM player? +This example verifies that a Next.js App Router application can consume +WalletKit as an ordinary package without owning its Rust wrapper, UniFFI +generation, WASM optimization, or asset staging. Run it from the repository root with the pinned WASM toolchain: ```sh +nix develop .#wasm --command npm --prefix web/walletkit install nix develop .#wasm --command npm --prefix examples/uniffi-web-authenticator-poc install nix develop .#wasm --command npm --prefix examples/uniffi-web-authenticator-poc run dev ``` -`npm run dev` regenerates the bindings before starting Next.js. Use -`npm run build` to prove the production bundle as well. These scripts expect to -run inside `nix develop .#wasm`, which supplies Node, Binaryen, and the -WASM-targeted Clang and LLVM tools. - -The Rust wrapper is deliberately local to this example so the WASM player's -runtime dependency does not leak into WalletKit's production crate graph. +`npm run dev` builds `@worldcoin/walletkit-web` before starting Next.js. Use +`npm run build` to prove the production bundle as well. The package build runs +inside `nix develop .#wasm`, which supplies Node, Binaryen, and the WASM-targeted +Clang and LLVM tools. ## What the POC proves -- The generator can produce TypeScript for WalletKit records, errors, objects, - callbacks, and async authenticator methods. +- `@worldcoin/walletkit-web` hides generation and WASM loading behind + `initializeWalletKit()`. +- The package exposes WalletKit records, errors, objects, callbacks, and async + authenticator methods. - The generated WASM loads in a browser and calls WalletKit synchronously to derive authenticator recovery material from secure browser randomness. -- Next.js can bundle the generated JavaScript glue in a Client Component while - serving the generated WASM as a static asset from `public/wasm`. +- Next.js can bundle the package's generated JavaScript glue and emit its WASM + asset from a Client Component. - An async authenticator constructor crosses the generated future/error bridge; the smoke call uses invalid configuration and stops before any network request. - The UI wires the generated async `InitializingAuthenticator` registration and @@ -39,18 +40,19 @@ runtime dependency does not leak into WalletKit's production crate graph. The released generator (`0.31.0-5`) cannot parse UniFFI 0.32 metadata, so this POC pins the worktree to UniFFI 0.31.2. Its internal wasm-bindgen processor is also pinned to 0.2.100, while `sqlite-wasm-rs` requires a newer schema; the -postinstall script aligns the generator to WalletKit's 0.2.126 schema. +package build aligns the generator to WalletKit's 0.2.126 schema. WalletKit's native bindings ask UniFFI to adapt exported futures to Tokio. That adapter creates a fallback thread when it is polled without a Tokio runtime, -which browser WASM cannot do. The POC enables `walletkit-core/uniffi-wasm` so -only the authenticator exports skip that adapter and are polled directly by the -generator's WASM player; native builds keep their existing Tokio behavior. - -The generated bindings are imported dynamically from a Client Component. This -keeps the WASM player and browser-only APIs out of Next.js server rendering. - -The generated WASM is optimized with Binaryen's `wasm-opt -Oz --converge` -before it is copied into the Next.js public assets. No attempt has been made to -productionize storage, artifact loading, worker placement, bundle splitting, -or key persistence. +which browser WASM cannot do. The `walletkit` crate enables +`walletkit-core/uniffi-wasm` only for `wasm32-unknown-unknown`, so the +authenticator exports are polled directly by the generator's WASM player while +native builds keep their existing Tokio behavior. + +The package is imported dynamically from a Client Component. This keeps the +WASM player and browser-only APIs out of Next.js server rendering. + +The package's WASM is optimized with Binaryen's `wasm-opt -Oz --converge` and +resolved from the package with `new URL(..., import.meta.url)`. No attempt has +been made to productionize storage, worker placement, bundle splitting, or key +persistence. diff --git a/examples/uniffi-web-authenticator-poc/next.config.ts b/examples/uniffi-web-authenticator-poc/next.config.ts new file mode 100644 index 000000000..78a721b64 --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/next.config.ts @@ -0,0 +1,13 @@ +import type { NextConfig } from "next"; +import { fileURLToPath } from "node:url"; + +const nextConfig: NextConfig = { + // The local file dependency is symlinked outside the example directory. + // Published consumers resolve the package from their own node_modules and + // do not need this development-only Turbopack root. + turbopack: { + root: fileURLToPath(new URL("../..", import.meta.url)), + }, +}; + +export default nextConfig; diff --git a/examples/uniffi-web-authenticator-poc/package-lock.json b/examples/uniffi-web-authenticator-poc/package-lock.json index b4c991ec7..182d809ae 100644 --- a/examples/uniffi-web-authenticator-poc/package-lock.json +++ b/examples/uniffi-web-authenticator-poc/package-lock.json @@ -7,10 +7,8 @@ "": { "name": "walletkit-uniffi-web-authenticator-poc", "version": "0.0.0", - "hasInstallScript": true, "dependencies": { - "@ubjs/core": "0.31.0-5", - "@ubjs/wasm": "0.31.0-5", + "@worldcoin/walletkit-web": "file:../../web/walletkit", "next": "16.3.2", "react": "19.2.8", "react-dom": "19.2.8" @@ -20,6 +18,19 @@ "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "prettier": "3.6.2", + "typescript": "5.9.2" + } + }, + "../../web/walletkit": { + "name": "@worldcoin/walletkit-web", + "version": "0.21.2", + "dependencies": { + "@ubjs/core": "0.31.0-5", + "@ubjs/wasm": "0.31.0-5" + }, + "devDependencies": { + "esbuild": "0.25.9", + "prettier": "3.6.2", "typescript": "5.9.2", "uniffi-bindgen-react-native": "0.31.0-5" } @@ -708,20 +719,9 @@ "@types/react": "^19.2.0" } }, - "node_modules/@ubjs/core": { - "version": "0.31.0-5", - "resolved": "https://registry.npmjs.org/@ubjs/core/-/core-0.31.0-5.tgz", - "integrity": "sha512-oRBRtyYOhaodiOY3rLMZFgAHGFMmD44XefMpsAx4Ja0/rO+45kVdQB1VZsblQMLYxP965i3IHm56eymgo3I5eQ==", - "license": "MPL-2.0" - }, - "node_modules/@ubjs/wasm": { - "version": "0.31.0-5", - "resolved": "https://registry.npmjs.org/@ubjs/wasm/-/wasm-0.31.0-5.tgz", - "integrity": "sha512-dO7i67DQ1UKBSegznLVjVrYowmxY7gaXXluBdtJXPYgcR5vzwYf2ZbxAUqj4qL1JkqxRmeTKgXtuesFI+D5dPg==", - "license": "MPL-2.0", - "peerDependencies": { - "@ubjs/core": "^0.31.0-5" - } + "node_modules/@worldcoin/walletkit-web": { + "resolved": "../../web/walletkit", + "link": true }, "node_modules/baseline-browser-mapping": { "version": "2.11.19", @@ -1047,17 +1047,6 @@ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true, "license": "MIT" - }, - "node_modules/uniffi-bindgen-react-native": { - "version": "0.31.0-5", - "resolved": "https://registry.npmjs.org/uniffi-bindgen-react-native/-/uniffi-bindgen-react-native-0.31.0-5.tgz", - "integrity": "sha512-YtL3gTe+RVXAQx/2P2Iuypic/CunRZC65Cs47v//YRfwWNYU4Ufd1jT3rqxSrH5b5QFCYblP89Nf/9ssZRvNgg==", - "dev": true, - "license": "MPL-2.0", - "bin": { - "ubrn": "bin/cli.cjs", - "uniffi-bindgen-react-native": "bin/cli.cjs" - } } } } diff --git a/examples/uniffi-web-authenticator-poc/package.json b/examples/uniffi-web-authenticator-poc/package.json index 0ecfef29a..daac7fc44 100644 --- a/examples/uniffi-web-authenticator-poc/package.json +++ b/examples/uniffi-web-authenticator-poc/package.json @@ -8,16 +8,14 @@ "url": "https://github.com/worldcoin/walletkit" }, "scripts": { - "postinstall": "node scripts/patch-ubrn-wasm-bindgen.mjs", - "bindings": "ubrn build wasm2 --config ubrn.config.yaml --release && node scripts/optimize-wasm.mjs && node scripts/patch-generated-index.mjs", - "predev": "npm run bindings", + "predev": "npm --prefix ../../web/walletkit run build", "dev": "next dev", - "build": "npm run bindings && next build", + "prebuild": "npm --prefix ../../web/walletkit run build", + "build": "next build", "start": "next start" }, "dependencies": { - "@ubjs/core": "0.31.0-5", - "@ubjs/wasm": "0.31.0-5", + "@worldcoin/walletkit-web": "file:../../web/walletkit", "next": "16.3.2", "react": "19.2.8", "react-dom": "19.2.8" @@ -27,7 +25,6 @@ "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "prettier": "3.6.2", - "typescript": "5.9.2", - "uniffi-bindgen-react-native": "0.31.0-5" + "typescript": "5.9.2" } } diff --git a/examples/uniffi-web-authenticator-poc/rust/Cargo.toml b/examples/uniffi-web-authenticator-poc/rust/Cargo.toml deleted file mode 100644 index 833f2d58d..000000000 --- a/examples/uniffi-web-authenticator-poc/rust/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "walletkit-web-authenticator-poc" -version = "0.0.0" -edition = "2021" -publish = false - -[lib] -crate-type = ["lib", "cdylib"] -name = "walletkit_web_authenticator_poc" - -[dependencies] -uniffi = { version = "0.31.2", features = ["tokio", "wasm-unstable-single-threaded"] } -walletkit-core = { path = "../../../crates/walletkit-core", default-features = false, features = ["uniffi-wasm"] } - -[target.'cfg(target_arch = "wasm32")'.dependencies] -uniffi-runtime-wasm = "0.31.0-5" diff --git a/examples/uniffi-web-authenticator-poc/rust/src/lib.rs b/examples/uniffi-web-authenticator-poc/rust/src/lib.rs deleted file mode 100644 index a8b59bcde..000000000 --- a/examples/uniffi-web-authenticator-poc/rust/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! PROTOTYPE: browser bindings for WalletKit's existing UniFFI API. - -extern crate walletkit_core; - -#[cfg(target_arch = "wasm32")] -extern crate uniffi_runtime_wasm as _; - -walletkit_core::uniffi_reexport_scaffolding!(); - -pub use walletkit_core::*; - -uniffi::setup_scaffolding!("walletkit_web_authenticator_poc"); diff --git a/examples/uniffi-web-authenticator-poc/src/app/page.tsx b/examples/uniffi-web-authenticator-poc/src/app/page.tsx index 2351f1c51..39a321d4f 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/page.tsx +++ b/examples/uniffi-web-authenticator-poc/src/app/page.tsx @@ -2,11 +2,11 @@ import { useEffect, useRef, useState } from "react"; -import type { InitializingAuthenticatorLike, RecoveryData } from "../generated"; - -type WalletKitBindings = typeof import("../generated"); - -const WASM_URL = "/wasm/walletkit_web_authenticator_poc.wasm"; +import type { + InitializingAuthenticatorLike, + RecoveryData, + WalletKit, +} from "@worldcoin/walletkit-web"; function printableState(state: string) { return JSON.stringify( @@ -22,7 +22,7 @@ function printableState(state: string) { } export default function Home() { - const bindings = useRef(null); + const bindings = useRef(null); const seed = useRef(new Uint8Array(32)); const registration = useRef(undefined); const initialized = useRef(false); @@ -51,9 +51,11 @@ export default function Home() { void (async () => { try { - const module = await import("../generated"); + const { initializeWalletKit } = await import( + "@worldcoin/walletkit-web" + ); + const module = await initializeWalletKit(); bindings.current = module; - await module.uniffiInitAsync(WASM_URL); setRuntime("Ready"); deriveAuthenticator(module); @@ -115,12 +117,11 @@ export default function Home() { return (
-

Throwaway Next.js feasibility probe

+

WalletKit web package integration probe

WalletKit authenticator in browser WASM

- This Client Component loads WalletKit's real UniFFI surface - through the generator's WASM player and derives fresh - authenticator material entirely inside the browser. + This Client Component initializes the WalletKit web package and + derives fresh authenticator material entirely inside the browser.

diff --git a/nix/README.md b/nix/README.md index e06ce9483..d8ac07a41 100644 --- a/nix/README.md +++ b/nix/README.md @@ -28,6 +28,7 @@ Convenience wrappers (they enter the right shell for you): nix/build-android.sh --target aarch64-linux-android nix/build-wasm.sh nix develop .#wasm --command cargo test -p walletkit-sqlite --target wasm32-unknown-unknown +nix develop .#wasm --command npm --prefix web/walletkit run build nix develop .#android --command cargo xtask kotlin build # full Android jniLibs + bindings nix develop .#android --command cargo xtask kotlin local 0.3.1 # publish to Maven Local ``` diff --git a/web/walletkit/.gitignore b/web/walletkit/.gitignore new file mode 100644 index 000000000..f816e0f8b --- /dev/null +++ b/web/walletkit/.gitignore @@ -0,0 +1,3 @@ +dist/ +node_modules/ +src/generated/ diff --git a/web/walletkit/README.md b/web/walletkit/README.md new file mode 100644 index 000000000..bdd29ce04 --- /dev/null +++ b/web/walletkit/README.md @@ -0,0 +1,26 @@ +# `@worldcoin/walletkit-web` + +Browser WebAssembly bindings for WalletKit. + +> PROTOTYPE: this package is private while its generation and publication +> workflow is being validated. + +The package owns the compiled WalletKit module, generated TypeScript bindings, +UniFFI player setup, and WASM asset resolution. Browser applications initialize +it through one interface: + +```ts +const { initializeWalletKit } = await import("@worldcoin/walletkit-web"); +const walletKit = await initializeWalletKit(); +``` + +Build it from the repository root with the pinned toolchain: + +```sh +nix develop .#wasm --command npm --prefix web/walletkit install +nix develop .#wasm --command npm --prefix web/walletkit run build +``` + +The release build uses `crates/walletkit` directly, disables its default +features, and optimizes the generated module with +`wasm-opt -Oz --converge`. diff --git a/web/walletkit/package-lock.json b/web/walletkit/package-lock.json new file mode 100644 index 000000000..a4773d0fb --- /dev/null +++ b/web/walletkit/package-lock.json @@ -0,0 +1,562 @@ +{ + "name": "@worldcoin/walletkit-web", + "version": "0.21.2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@worldcoin/walletkit-web", + "version": "0.21.2", + "dependencies": { + "@ubjs/core": "0.31.0-5", + "@ubjs/wasm": "0.31.0-5" + }, + "devDependencies": { + "esbuild": "0.25.9", + "prettier": "3.6.2", + "typescript": "5.9.2", + "uniffi-bindgen-react-native": "0.31.0-5" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@ubjs/core": { + "version": "0.31.0-5", + "resolved": "https://registry.npmjs.org/@ubjs/core/-/core-0.31.0-5.tgz", + "integrity": "sha512-oRBRtyYOhaodiOY3rLMZFgAHGFMmD44XefMpsAx4Ja0/rO+45kVdQB1VZsblQMLYxP965i3IHm56eymgo3I5eQ==", + "license": "MPL-2.0" + }, + "node_modules/@ubjs/wasm": { + "version": "0.31.0-5", + "resolved": "https://registry.npmjs.org/@ubjs/wasm/-/wasm-0.31.0-5.tgz", + "integrity": "sha512-dO7i67DQ1UKBSegznLVjVrYowmxY7gaXXluBdtJXPYgcR5vzwYf2ZbxAUqj4qL1JkqxRmeTKgXtuesFI+D5dPg==", + "license": "MPL-2.0", + "peerDependencies": { + "@ubjs/core": "^0.31.0-5" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uniffi-bindgen-react-native": { + "version": "0.31.0-5", + "resolved": "https://registry.npmjs.org/uniffi-bindgen-react-native/-/uniffi-bindgen-react-native-0.31.0-5.tgz", + "integrity": "sha512-YtL3gTe+RVXAQx/2P2Iuypic/CunRZC65Cs47v//YRfwWNYU4Ufd1jT3rqxSrH5b5QFCYblP89Nf/9ssZRvNgg==", + "dev": true, + "license": "MPL-2.0", + "bin": { + "ubrn": "bin/cli.cjs", + "uniffi-bindgen-react-native": "bin/cli.cjs" + } + } + } +} diff --git a/web/walletkit/package.json b/web/walletkit/package.json new file mode 100644 index 000000000..a2673556f --- /dev/null +++ b/web/walletkit/package.json @@ -0,0 +1,42 @@ +{ + "name": "@worldcoin/walletkit-web", + "version": "0.21.2", + "private": true, + "description": "Browser WebAssembly bindings for WalletKit.", + "type": "module", + "files": [ + "dist/", + "README.md" + ], + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "scripts": { + "clean": "node scripts/clean.mjs", + "patch:generator": "node scripts/patch-ubrn-wasm-bindgen.mjs", + "generate": "npm run patch:generator && ubrn build wasm2 --config ubrn.config.yaml --release && node scripts/optimize-wasm.mjs && node scripts/patch-generated-index.mjs", + "build": "npm run clean && npm run generate && tsc -p tsconfig.build.json && esbuild src/index.ts --bundle --format=esm --platform=browser --target=es2022 --outfile=dist/index.js --external:@ubjs/core --external:@ubjs/wasm && node scripts/copy-wasm.mjs", + "pack:check": "npm pack --dry-run" + }, + "dependencies": { + "@ubjs/core": "0.31.0-5", + "@ubjs/wasm": "0.31.0-5" + }, + "devDependencies": { + "esbuild": "0.25.9", + "prettier": "3.6.2", + "typescript": "5.9.2", + "uniffi-bindgen-react-native": "0.31.0-5" + }, + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/worldcoin/walletkit", + "directory": "web/walletkit" + } +} diff --git a/web/walletkit/scripts/clean.mjs b/web/walletkit/scripts/clean.mjs new file mode 100644 index 000000000..16ed422b5 --- /dev/null +++ b/web/walletkit/scripts/clean.mjs @@ -0,0 +1,3 @@ +import { rmSync } from "node:fs"; + +rmSync(new URL("../dist/", import.meta.url), { force: true, recursive: true }); diff --git a/web/walletkit/scripts/copy-wasm.mjs b/web/walletkit/scripts/copy-wasm.mjs new file mode 100644 index 000000000..6e5851db0 --- /dev/null +++ b/web/walletkit/scripts/copy-wasm.mjs @@ -0,0 +1,8 @@ +import { copyFileSync, mkdirSync } from "node:fs"; + +const output = new URL("../dist/generated/", import.meta.url); +mkdirSync(output, { recursive: true }); +copyFileSync( + new URL("../src/generated/walletkit.wasm", import.meta.url), + new URL("walletkit.wasm", output), +); diff --git a/examples/uniffi-web-authenticator-poc/scripts/optimize-wasm.mjs b/web/walletkit/scripts/optimize-wasm.mjs similarity index 69% rename from examples/uniffi-web-authenticator-poc/scripts/optimize-wasm.mjs rename to web/walletkit/scripts/optimize-wasm.mjs index aaf34e5b0..0b0cbe37f 100644 --- a/examples/uniffi-web-authenticator-poc/scripts/optimize-wasm.mjs +++ b/web/walletkit/scripts/optimize-wasm.mjs @@ -1,14 +1,11 @@ -// Optimize the generated module before it is copied into Next.js public assets. +// Optimize the generated module before it is included in the npm package. // Binaryen is supplied by the repository's `nix develop .#wasm` shell. import { execFileSync } from "node:child_process"; import { renameSync } from "node:fs"; import { fileURLToPath } from "node:url"; const wasm = fileURLToPath( - new URL( - "../src/generated/walletkit_web_authenticator_poc.wasm", - import.meta.url, - ), + new URL("../src/generated/walletkit.wasm", import.meta.url), ); const optimized = `${wasm}.optimized`; diff --git a/examples/uniffi-web-authenticator-poc/scripts/patch-generated-index.mjs b/web/walletkit/scripts/patch-generated-index.mjs similarity index 55% rename from examples/uniffi-web-authenticator-poc/scripts/patch-generated-index.mjs rename to web/walletkit/scripts/patch-generated-index.mjs index 2a10544df..7a2813a4c 100644 --- a/examples/uniffi-web-authenticator-poc/scripts/patch-generated-index.mjs +++ b/web/walletkit/scripts/patch-generated-index.mjs @@ -1,20 +1,10 @@ // PROTOTYPE workaround: ubrn 0.31.0-5 emits readonly player definitions that // @ubjs/wasm 0.31.0-5 types as mutable, and omits a declaration for its // generated wasm-bindgen glue module. Runtime shapes are compatible. -import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { readFileSync, writeFileSync } from "node:fs"; const generatedIndex = new URL("../src/generated/index.ts", import.meta.url); const source = readFileSync(generatedIndex, "utf8"); if (!source.startsWith("// @ts-nocheck")) { writeFileSync(generatedIndex, `// @ts-nocheck\n${source}`); } - -const publicWasm = new URL("../public/wasm/", import.meta.url); -mkdirSync(publicWasm, { recursive: true }); -copyFileSync( - new URL( - "../src/generated/walletkit_web_authenticator_poc.wasm", - import.meta.url, - ), - new URL("walletkit_web_authenticator_poc.wasm", publicWasm), -); diff --git a/examples/uniffi-web-authenticator-poc/scripts/patch-ubrn-wasm-bindgen.mjs b/web/walletkit/scripts/patch-ubrn-wasm-bindgen.mjs similarity index 82% rename from examples/uniffi-web-authenticator-poc/scripts/patch-ubrn-wasm-bindgen.mjs rename to web/walletkit/scripts/patch-ubrn-wasm-bindgen.mjs index 73aa1e34d..3a0224d53 100644 --- a/examples/uniffi-web-authenticator-poc/scripts/patch-ubrn-wasm-bindgen.mjs +++ b/web/walletkit/scripts/patch-ubrn-wasm-bindgen.mjs @@ -2,7 +2,7 @@ // while ubrn 0.31.0-5 pins its post-processor to 0.2.100. Both sides must use // the exact same schema, so align the installed generator with WalletKit. import { execFileSync } from "node:child_process"; -import { readFileSync, writeFileSync } from "node:fs"; +import { existsSync, readFileSync, writeFileSync } from "node:fs"; const root = new URL( "../node_modules/uniffi-bindgen-react-native/", @@ -18,8 +18,12 @@ if (source.includes(oldDependency)) { writeFileSync(manifest, source.replace(oldDependency, newDependency)); } -const lock = readFileSync(lockfile, "utf8"); -if (/name = "wasm-bindgen-cli-support"\nversion = "0\.2\.100"/.test(lock)) { +if ( + existsSync(lockfile) && + /name = "wasm-bindgen-cli-support"\nversion = "0\.2\.100"/.test( + readFileSync(lockfile, "utf8"), + ) +) { execFileSync( "cargo", [ diff --git a/web/walletkit/src/index.ts b/web/walletkit/src/index.ts new file mode 100644 index 000000000..ea4feef01 --- /dev/null +++ b/web/walletkit/src/index.ts @@ -0,0 +1,19 @@ +import * as generated from "./generated"; + +export type * from "./generated"; + +type GeneratedWalletKit = typeof generated; + +/** WalletKit's generated domain interface without its raw runtime hooks. */ +export type WalletKit = Omit; + +const wasm = new URL("./generated/walletkit.wasm", import.meta.url); + +/** + * Loads WalletKit's browser WASM module and returns its generated bindings. + * Repeated calls share the generated runtime's initialization promise. + */ +export async function initializeWalletKit(): Promise { + await generated.uniffiInitAsync(wasm); + return generated; +} diff --git a/web/walletkit/tsconfig.build.json b/web/walletkit/tsconfig.build.json new file mode 100644 index 000000000..34193e502 --- /dev/null +++ b/web/walletkit/tsconfig.build.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "allowJs": true, + "declaration": true, + "emitDeclarationOnly": true, + "esModuleInterop": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "Bundler", + "outDir": "dist", + "rootDir": "src", + "skipLibCheck": true, + "strict": true, + "target": "ES2022" + }, + "include": ["src/**/*.ts", "src/**/*.js"] +} diff --git a/examples/uniffi-web-authenticator-poc/ubrn.config.yaml b/web/walletkit/ubrn.config.yaml similarity index 50% rename from examples/uniffi-web-authenticator-poc/ubrn.config.yaml rename to web/walletkit/ubrn.config.yaml index a9433e45d..20e7c47b7 100644 --- a/examples/uniffi-web-authenticator-poc/ubrn.config.yaml +++ b/web/walletkit/ubrn.config.yaml @@ -1,6 +1,7 @@ rust: - directory: ./rust + directory: ../../crates/walletkit manifestPath: Cargo.toml wasm2: + defaultFeatures: false ts: src/generated From eea4dcb3075a5c2786e82a5968bda4e5e870194d Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Thu, 27 Aug 2026 11:42:19 +0200 Subject: [PATCH 05/17] remove the async bridge test thing --- .../src/app/page.tsx | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/examples/uniffi-web-authenticator-poc/src/app/page.tsx b/examples/uniffi-web-authenticator-poc/src/app/page.tsx index 39a321d4f..d06d7df2e 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/page.tsx +++ b/examples/uniffi-web-authenticator-poc/src/app/page.tsx @@ -27,7 +27,6 @@ export default function Home() { const registration = useRef(undefined); const initialized = useRef(false); const [runtime, setRuntime] = useState("Loading…"); - const [asyncBridge, setAsyncBridge] = useState("Pending…"); const [recovery, setRecovery] = useState(); const [confirmed, setConfirmed] = useState(false); const [registering, setRegistering] = useState(false); @@ -58,17 +57,6 @@ export default function Home() { bindings.current = module; setRuntime("Ready"); deriveAuthenticator(module); - - try { - await module.InitializingAuthenticator.register( - new Uint8Array(seed.current).buffer, - "invalid config used only to exercise async error lifting", - undefined, - ); - setAsyncBridge("Unexpected success"); - } catch { - setAsyncBridge("Ready (Rust rejected the invalid config)"); - } } catch (error) { setRuntime("Failed"); setStatus(String(error)); @@ -128,10 +116,6 @@ export default function Home() {
WASM runtime
{runtime}
-
-
Async UniFFI bridge
-
{asyncBridge}
-
Authenticator address
{recovery?.authenticatorAddress ?? "—"}
From 1318860301cc44d9b2e85e233674b5dcb0859272 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Thu, 27 Aug 2026 13:21:07 +0200 Subject: [PATCH 06/17] Add browser faux credential proof flow --- .../src/storage/credential_storage.rs | 20 ++ .../walletkit-core/src/storage/ephemeral.rs | 154 +++++++++++++ crates/walletkit-core/src/storage/mod.rs | 2 + .../uniffi-web-authenticator-poc/.gitignore | 1 + .../uniffi-web-authenticator-poc/README.md | 19 +- .../package-lock.json | 209 +++++++++++++++++- .../uniffi-web-authenticator-poc/package.json | 3 +- .../src/app/api/faux-credential/route.ts | 30 +++ .../src/app/globals.css | 6 +- .../src/app/page.tsx | 187 +++++++++++++--- .../src/app/staging.ts | 131 +++++++++++ web/walletkit/README.md | 6 +- web/walletkit/ubrn.config.yaml | 2 + 13 files changed, 725 insertions(+), 45 deletions(-) create mode 100644 crates/walletkit-core/src/storage/ephemeral.rs create mode 100644 examples/uniffi-web-authenticator-poc/src/app/api/faux-credential/route.ts create mode 100644 examples/uniffi-web-authenticator-poc/src/app/staging.ts diff --git a/crates/walletkit-core/src/storage/credential_storage.rs b/crates/walletkit-core/src/storage/credential_storage.rs index 34ca23fd9..cd98a13b1 100644 --- a/crates/walletkit-core/src/storage/credential_storage.rs +++ b/crates/walletkit-core/src/storage/credential_storage.rs @@ -346,6 +346,26 @@ impl CredentialStore { } } +#[cfg(all(target_arch = "wasm32", feature = "uniffi-wasm"))] +#[uniffi::export] +impl CredentialStore { + /// Creates process-local credential storage for browser demos and tests. + /// + /// The store is discarded when the page is refreshed. Its key envelope is + /// kept in memory without device-bound encryption, so callers must not use + /// this constructor for production credentials. + /// + /// # Errors + /// + /// Returns an error if the in-memory storage handle cannot be created. + #[uniffi::constructor] + pub fn new_ephemeral() -> StorageResult { + Self::from_provider_arc(Arc::new( + super::ephemeral::EphemeralStorageProvider::new(), + )) + } +} + #[uniffi::export] impl CredentialStore { /// Permanently destroys all credential storage data. diff --git a/crates/walletkit-core/src/storage/ephemeral.rs b/crates/walletkit-core/src/storage/ephemeral.rs new file mode 100644 index 000000000..1b7b492e8 --- /dev/null +++ b/crates/walletkit-core/src/storage/ephemeral.rs @@ -0,0 +1,154 @@ +//! Process-local storage components for browser demos and tests. + +#[cfg(all(target_arch = "wasm32", feature = "uniffi-wasm"))] +use std::sync::Arc; +use std::{collections::HashMap, sync::Mutex}; + +use sha2::{Digest as _, Sha256}; +use subtle::ConstantTimeEq as _; + +use super::{AtomicBlobStore, DeviceKeystore, StorageError, StorageResult}; +#[cfg(all(target_arch = "wasm32", feature = "uniffi-wasm"))] +use super::{StoragePaths, StorageProvider}; + +const ASSOCIATED_DATA_DIGEST_LENGTH: usize = 32; + +struct EphemeralKeystore; + +impl DeviceKeystore for EphemeralKeystore { + fn seal( + &self, + associated_data: Vec, + plaintext: Vec, + ) -> StorageResult> { + let mut sealed = + Vec::with_capacity(ASSOCIATED_DATA_DIGEST_LENGTH + plaintext.len()); + sealed.extend_from_slice(&Sha256::digest(associated_data)); + sealed.extend_from_slice(&plaintext); + Ok(sealed) + } + + fn open_sealed( + &self, + associated_data: Vec, + sealed: Vec, + ) -> StorageResult> { + let Some((stored_digest, plaintext)) = + sealed.split_at_checked(ASSOCIATED_DATA_DIGEST_LENGTH) + else { + return Err(StorageError::InvalidEnvelope( + "ephemeral keystore payload is too short".to_string(), + )); + }; + let expected_digest = Sha256::digest(associated_data); + if !bool::from(stored_digest.ct_eq(expected_digest.as_slice())) { + return Err(StorageError::InvalidEnvelope( + "ephemeral keystore associated data mismatch".to_string(), + )); + } + Ok(plaintext.to_vec()) + } +} + +#[derive(Default)] +struct EphemeralBlobStore { + blobs: Mutex>>, +} + +impl AtomicBlobStore for EphemeralBlobStore { + fn read(&self, path: String) -> StorageResult>> { + Ok(self + .blobs + .lock() + .map_err(|_| StorageError::BlobStore("mutex poisoned".to_string()))? + .get(&path) + .cloned()) + } + + fn write_atomic(&self, path: String, bytes: Vec) -> StorageResult<()> { + self.blobs + .lock() + .map_err(|_| StorageError::BlobStore("mutex poisoned".to_string()))? + .insert(path, bytes); + Ok(()) + } + + fn delete(&self, path: String) -> StorageResult<()> { + self.blobs + .lock() + .map_err(|_| StorageError::BlobStore("mutex poisoned".to_string()))? + .remove(&path); + Ok(()) + } +} + +#[cfg(all(target_arch = "wasm32", feature = "uniffi-wasm"))] +pub(super) struct EphemeralStorageProvider { + keystore: Arc, + blob_store: Arc, + paths: Arc, +} + +#[cfg(all(target_arch = "wasm32", feature = "uniffi-wasm"))] +impl EphemeralStorageProvider { + pub(super) fn new() -> Self { + Self { + keystore: Arc::new(EphemeralKeystore), + blob_store: Arc::new(EphemeralBlobStore::default()), + paths: Arc::new(StoragePaths::new(format!( + "walletkit-ephemeral-{}", + uuid::Uuid::new_v4() + ))), + } + } +} + +#[cfg(all(target_arch = "wasm32", feature = "uniffi-wasm"))] +impl StorageProvider for EphemeralStorageProvider { + fn keystore(&self) -> Arc { + self.keystore.clone() + } + + fn blob_store(&self) -> Arc { + self.blob_store.clone() + } + + fn paths(&self) -> Arc { + self.paths.clone() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn ephemeral_keystore_checks_associated_data() { + let keystore = EphemeralKeystore; + let sealed = keystore + .seal(b"expected".to_vec(), b"secret".to_vec()) + .expect("seal"); + + assert_eq!( + keystore + .open_sealed(b"expected".to_vec(), sealed.clone()) + .expect("open"), + b"secret" + ); + assert!(keystore.open_sealed(b"wrong".to_vec(), sealed).is_err()); + } + + #[test] + fn ephemeral_blob_store_roundtrips_and_deletes() { + let store = EphemeralBlobStore::default(); + store + .write_atomic("key".to_string(), b"value".to_vec()) + .expect("write"); + assert_eq!( + store.read("key".to_string()).expect("read"), + Some(b"value".to_vec()) + ); + store.delete("key".to_string()).expect("delete"); + assert_eq!(store.read("key".to_string()).expect("read"), None); + } +} diff --git a/crates/walletkit-core/src/storage/mod.rs b/crates/walletkit-core/src/storage/mod.rs index 529b5c64e..10c4ab018 100644 --- a/crates/walletkit-core/src/storage/mod.rs +++ b/crates/walletkit-core/src/storage/mod.rs @@ -46,6 +46,8 @@ pub mod cache; pub mod credential_storage; pub mod credential_vault; +#[cfg(any(test, all(target_arch = "wasm32", feature = "uniffi-wasm")))] +mod ephemeral; pub mod error; pub mod keys; pub mod paths; diff --git a/examples/uniffi-web-authenticator-poc/.gitignore b/examples/uniffi-web-authenticator-poc/.gitignore index e0411220b..230962c61 100644 --- a/examples/uniffi-web-authenticator-poc/.gitignore +++ b/examples/uniffi-web-authenticator-poc/.gitignore @@ -1,3 +1,4 @@ .next/ dist/ node_modules/ +tsconfig.tsbuildinfo diff --git a/examples/uniffi-web-authenticator-poc/README.md b/examples/uniffi-web-authenticator-poc/README.md index d2372e89a..ea2ef646b 100644 --- a/examples/uniffi-web-authenticator-poc/README.md +++ b/examples/uniffi-web-authenticator-poc/README.md @@ -30,10 +30,13 @@ Clang and LLVM tools. derive authenticator recovery material from secure browser randomness. - Next.js can bundle the package's generated JavaScript glue and emit its WASM asset from a Client Component. -- An async authenticator constructor crosses the generated future/error bridge; - the smoke call uses invalid configuration and stops before any network request. -- The UI wires the generated async `InitializingAuthenticator` registration and - polling methods. Registration is an explicit, opt-in staging mutation. +- The UI drives a real opt-in staging flow: account registration, ephemeral + credential-store initialization, faux credential issuance, and uniqueness + proof generation. +- A staging RP proof request is signed in the browser with the intentionally + public test key used by `walletkit-testkit`. +- A same-origin Next.js route forwards the issuance request because the hosted + staging faux issuer does not allow browser CORS preflights. ## Experimental compatibility pins @@ -53,6 +56,8 @@ The package is imported dynamically from a Client Component. This keeps the WASM player and browser-only APIs out of Next.js server rendering. The package's WASM is optimized with Binaryen's `wasm-opt -Oz --converge` and -resolved from the package with `new URL(..., import.meta.url)`. No attempt has -been made to productionize storage, worker placement, bundle splitting, or key -persistence. +resolved from the package with `new URL(..., import.meta.url)`. Proof generation +currently embeds the proving artifacts, making the optimized WASM roughly 40 MB. +The example uses a WASM-only ephemeral store whose data and key envelope are +discarded on refresh. No attempt has been made to productionize persistent +storage, worker placement, artifact delivery, or bundle splitting. diff --git a/examples/uniffi-web-authenticator-poc/package-lock.json b/examples/uniffi-web-authenticator-poc/package-lock.json index 182d809ae..b81183300 100644 --- a/examples/uniffi-web-authenticator-poc/package-lock.json +++ b/examples/uniffi-web-authenticator-poc/package-lock.json @@ -11,7 +11,8 @@ "@worldcoin/walletkit-web": "file:../../web/walletkit", "next": "16.3.2", "react": "19.2.8", - "react-dom": "19.2.8" + "react-dom": "19.2.8", + "viem": "^2.56.0" }, "devDependencies": { "@types/node": "25.0.3", @@ -35,6 +36,12 @@ "uniffi-bindgen-react-native": "0.31.0-5" } }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", + "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", + "license": "MIT" + }, "node_modules/@emnapi/runtime": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", @@ -680,6 +687,81 @@ "node": ">= 10" } }, + "node_modules/@noble/ciphers": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", + "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", + "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@swc/helpers": { "version": "0.5.23", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", @@ -723,6 +805,27 @@ "resolved": "../../web/walletkit", "link": true }, + "node_modules/abitype": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.3.tgz", + "integrity": "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3.22.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, "node_modules/baseline-browser-mapping": { "version": "2.11.19", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.19.tgz", @@ -778,6 +881,27 @@ "node": ">=8" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/isows": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", + "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, "node_modules/nanoid": { "version": "3.3.18", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", @@ -877,6 +1001,36 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/ox": { + "version": "0.14.34", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.34.tgz", + "integrity": "sha512-12seOIk7dv8eAoGQhcWaeKZxNz304IVcDvb9U5Y7JZAEVe21Nm1YMxLjhWah+su5BD4Omx4Zz0z5x3ij9M4GYQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.11.0", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "1.9.1", + "@noble/hashes": "^1.8.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "abitype": "^1.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -1031,7 +1185,7 @@ "version": "5.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -1047,6 +1201,57 @@ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true, "license": "MIT" + }, + "node_modules/viem": { + "version": "2.56.0", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.56.0.tgz", + "integrity": "sha512-JmkgIk4jN+im4oguLxwPv19pwSaGH9kcGSq25Ilm55106ULBBMNR3eWKKA0wZoeyLPSHIiOwZ4sGceEYEIq7LA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.9.1", + "@noble/hashes": "1.8.0", + "@scure/bip32": "1.7.0", + "@scure/bip39": "1.6.0", + "abitype": "1.2.3", + "isows": "1.0.7", + "ox": "0.14.34", + "ws": "8.21.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } } } } diff --git a/examples/uniffi-web-authenticator-poc/package.json b/examples/uniffi-web-authenticator-poc/package.json index daac7fc44..40ce55f8a 100644 --- a/examples/uniffi-web-authenticator-poc/package.json +++ b/examples/uniffi-web-authenticator-poc/package.json @@ -18,7 +18,8 @@ "@worldcoin/walletkit-web": "file:../../web/walletkit", "next": "16.3.2", "react": "19.2.8", - "react-dom": "19.2.8" + "react-dom": "19.2.8", + "viem": "^2.56.0" }, "devDependencies": { "@types/node": "25.0.3", diff --git a/examples/uniffi-web-authenticator-poc/src/app/api/faux-credential/route.ts b/examples/uniffi-web-authenticator-poc/src/app/api/faux-credential/route.ts new file mode 100644 index 000000000..48f0831a1 --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/src/app/api/faux-credential/route.ts @@ -0,0 +1,30 @@ +import { NextResponse } from "next/server"; + +const FAUX_ISSUER_URL = "https://faux-issuer.us.id-infra.worldcoin.dev/issue"; +const FIELD_ELEMENT_PATTERN = /^0x[0-9a-f]{64}$/; + +export async function POST(request: Request) { + const body = (await request.json()) as { sub?: unknown }; + if (typeof body.sub !== "string" || !FIELD_ELEMENT_PATTERN.test(body.sub)) { + return NextResponse.json( + { error: "sub must be a 32-byte lowercase hex field element" }, + { status: 400 }, + ); + } + + const response = await fetch(FAUX_ISSUER_URL, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ sub: body.sub }), + cache: "no-store", + }); + const responseBody = await response.text(); + + return new NextResponse(responseBody, { + status: response.status, + headers: { + "content-type": + response.headers.get("content-type") ?? "application/json", + }, + }); +} diff --git a/examples/uniffi-web-authenticator-poc/src/app/globals.css b/examples/uniffi-web-authenticator-poc/src/app/globals.css index cd80c060f..431798aa5 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/globals.css +++ b/examples/uniffi-web-authenticator-poc/src/app/globals.css @@ -21,7 +21,7 @@ main { } .card { - width: min(42rem, 100%); + width: min(48rem, 100%); padding: 2rem; border: 1px solid #bdcbc3; border-radius: 1rem; @@ -104,3 +104,7 @@ summary { cursor: pointer; font-weight: 700; } + +ol { + padding-left: 1.5rem; +} diff --git a/examples/uniffi-web-authenticator-poc/src/app/page.tsx b/examples/uniffi-web-authenticator-poc/src/app/page.tsx index d06d7df2e..3f346032e 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/page.tsx +++ b/examples/uniffi-web-authenticator-poc/src/app/page.tsx @@ -3,20 +3,24 @@ import { useEffect, useRef, useState } from "react"; import type { + AuthenticatorLike, + CredentialStoreLike, InitializingAuthenticatorLike, RecoveryData, WalletKit, } from "@worldcoin/walletkit-web"; -function printableState(state: string) { +import { createStagingProofRequest, issueFauxCredential } from "./staging"; + +function printableState(state: string, details = {}) { return JSON.stringify( { state, environment: "staging", region: "eu", - seed: "32 random bytes held only in memory", + ...details, }, - null, + (_, value) => (typeof value === "bigint" ? value.toString() : value), 2, ); } @@ -25,11 +29,16 @@ export default function Home() { const bindings = useRef(null); const seed = useRef(new Uint8Array(32)); const registration = useRef(undefined); + const authenticator = useRef(undefined); + const store = useRef(undefined); const initialized = useRef(false); const [runtime, setRuntime] = useState("Loading…"); const [recovery, setRecovery] = useState(); const [confirmed, setConfirmed] = useState(false); - const [registering, setRegistering] = useState(false); + const [registered, setRegistered] = useState(false); + const [authenticatorReady, setAuthenticatorReady] = useState(false); + const [credentialIssued, setCredentialIssued] = useState(false); + const [busy, setBusy] = useState(false); const [canPoll, setCanPoll] = useState(false); const [status, setStatus] = useState("Initializing generated bindings…"); @@ -40,8 +49,17 @@ export default function Home() { module.recoveryDataFromSeed(new Uint8Array(seed.current).buffer), ); registration.current = undefined; + authenticator.current = undefined; + store.current = undefined; setCanPoll(false); - setStatus(printableState("authenticator-derived")); + setRegistered(false); + setAuthenticatorReady(false); + setCredentialIssued(false); + setStatus( + printableState("authenticator-derived", { + seed: "32 random bytes held only in memory", + }), + ); } useEffect(() => { @@ -67,7 +85,7 @@ export default function Home() { async function registerAuthenticator() { const module = bindings.current; if (!module) return; - setRegistering(true); + setBusy(true); setStatus("Sending registration request to the staging gateway…"); try { registration.current = @@ -79,26 +97,106 @@ export default function Home() { undefined, ); setCanPoll(true); - setStatus(JSON.stringify({ state: "registration-requested" }, null, 2)); + setStatus(printableState("registration-requested")); } catch (error) { setStatus(String(error)); } finally { - setRegistering(false); + setBusy(false); } } async function pollRegistration() { - if (!registration.current) return; - setCanPoll(false); + const module = bindings.current; + if (!module || !registration.current) return; + setBusy(true); try { const result = await registration.current.pollStatus(); + const finalized = module.RegistrationStatus.Finalized.instanceOf(result); + setRegistered(finalized); + setCanPoll(!finalized); setStatus( - JSON.stringify({ state: "registration-polled", result }, null, 2), + printableState( + finalized ? "registration-finalized" : "registration-pending", + { status: result.constructor.name }, + ), ); } catch (error) { setStatus(String(error)); } finally { - setCanPoll(true); + setBusy(false); + } + } + + async function initializeRegisteredAuthenticator() { + const module = bindings.current; + if (!module) return; + setBusy(true); + setStatus("Initializing the registered authenticator and ephemeral store…"); + try { + const ephemeralStore = module.CredentialStore.newEphemeral(); + const artifacts = new module.EmbeddedZkArtifacts().asZkArtifactSource(); + const initializedAuthenticator = + await module.Authenticator.initWithDefaults( + new Uint8Array(seed.current).buffer, + undefined, + module.Environment.Staging, + module.Region.Eu, + artifacts, + ephemeralStore, + ); + initializedAuthenticator.initStorage( + BigInt(Math.floor(Date.now() / 1000)), + ); + store.current = ephemeralStore; + authenticator.current = initializedAuthenticator; + setAuthenticatorReady(true); + setStatus(printableState("authenticator-initialized")); + } catch (error) { + setStatus(String(error)); + } finally { + setBusy(false); + } + } + + async function issueCredential() { + const module = bindings.current; + if (!module || !authenticator.current || !store.current) return; + setBusy(true); + setStatus("Requesting a credential from the staging faux issuer…"); + try { + const issued = await issueFauxCredential( + module, + authenticator.current, + store.current, + ); + setCredentialIssued(true); + setStatus(printableState("credential-issued", issued)); + } catch (error) { + setStatus(String(error)); + } finally { + setBusy(false); + } + } + + async function generateProof() { + const module = bindings.current; + if (!module || !authenticator.current) return; + setBusy(true); + setStatus("Generating a uniqueness proof in browser WASM…"); + try { + const request = await createStagingProofRequest( + module, + "walletkit-web-example", + ); + const response = await authenticator.current.generateProof( + request, + BigInt(Math.floor(Date.now() / 1000)), + ); + setStatus(response.toJson()); + } catch (error) { + setStatus(String(error)); + } finally { + setBusy(false); } } @@ -106,10 +204,10 @@ export default function Home() {

WalletKit web package integration probe

-

WalletKit authenticator in browser WASM

+

WalletKit credential proof in browser WASM

- This Client Component initializes the WalletKit web package and - derives fresh authenticator material entirely inside the browser. + Derive and register a temporary staging authenticator, issue a faux + credential, then generate a proof for it entirely in the browser.

@@ -130,17 +228,16 @@ export default function Home() {
-
- Optional network proof: register on staging +
+ Staging credential proof

- This sends a real account-registration request to WalletKit's - staging gateway. The seed remains in this tab and is discarded on - refresh. + This creates a real temporary account and credential in staging. The + seed and credential store are discarded when this tab reloads.

-
- - -
+
    +
  1. + + +
  2. +
  3. + +
  4. +
  5. + +
  6. +
  7. + +
  8. +
{status}
diff --git a/examples/uniffi-web-authenticator-poc/src/app/staging.ts b/examples/uniffi-web-authenticator-poc/src/app/staging.ts new file mode 100644 index 000000000..5ffc3ea3b --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/src/app/staging.ts @@ -0,0 +1,131 @@ +import { privateKeyToAccount } from "viem/accounts"; + +import type { + AuthenticatorLike, + CredentialStoreLike, + WalletKit, +} from "@worldcoin/walletkit-web"; + +const FAUX_ISSUER_SCHEMA_ID = 128n; +const STAGING_RP_ID = 46n; +const STAGING_RP_PRIVATE_KEY = + "0x1111111111111111111111111111111111111111111111111111111111111111"; + +function fixedWidthBytes(value: bigint, width: number) { + const bytes = new Uint8Array(width); + for (let index = width - 1; index >= 0; index -= 1) { + bytes[index] = Number(value & 0xffn); + value >>= 8n; + } + return bytes; +} + +function hex(bytes: Uint8Array) { + return `0x${Array.from(bytes, (byte) => + byte.toString(16).padStart(2, "0"), + ).join("")}`; +} + +function concat(...chunks: Uint8Array[]) { + const result = new Uint8Array( + chunks.reduce((length, chunk) => length + chunk.length, 0), + ); + let offset = 0; + for (const chunk of chunks) { + result.set(chunk, offset); + offset += chunk.length; + } + return result; +} + +export async function issueFauxCredential( + module: WalletKit, + authenticator: AuthenticatorLike, + store: CredentialStoreLike, +) { + const blindingFactor = + await authenticator.generateCredentialBlindingFactorRemote( + FAUX_ISSUER_SCHEMA_ID, + ); + const sub = authenticator.computeCredentialSub(blindingFactor); + const response = await fetch("/api/faux-credential", { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ sub: sub.toHexString() }), + }); + if (!response.ok) { + throw new Error( + `Faux issuer returned ${response.status}: ${await response.text()}`, + ); + } + + const body = (await response.json()) as { credential?: unknown }; + if (body.credential === undefined) { + throw new Error("Faux issuer response did not contain a credential"); + } + + const credentialBytes = new TextEncoder().encode( + JSON.stringify(body.credential), + ); + const credential = module.Credential.fromBytes(credentialBytes.buffer); + const now = BigInt(Math.floor(Date.now() / 1000)); + const credentialId = store.storeCredential( + credential, + blindingFactor, + credential.expiresAt(), + undefined, + now, + ); + + return { + credentialId, + issuerSchemaId: credential.issuerSchemaId(), + sub: sub.toHexString(), + }; +} + +export async function createStagingProofRequest( + module: WalletKit, + signal: string, +) { + const nonce = crypto.getRandomValues(new Uint8Array(32)); + // A 31-byte random value is always within the BabyJubJub base field. + nonce[0] = 0; + const action = fixedWidthBytes(1n, 32); + const createdAt = BigInt(Math.floor(Date.now() / 1000)); + const expiresAt = createdAt + 300n; + const message = concat( + new Uint8Array([1]), + nonce, + fixedWidthBytes(createdAt, 8), + fixedWidthBytes(expiresAt, 8), + action, + ); + const account = privateKeyToAccount(STAGING_RP_PRIVATE_KEY); + const signature = await account.signMessage({ message: { raw: message } }); + + return module.ProofRequest.fromJson( + JSON.stringify({ + id: crypto.randomUUID(), + version: 1, + proof_type: "uniqueness", + created_at: Number(createdAt), + expires_at: Number(expiresAt), + rp_id: `rp_${STAGING_RP_ID.toString(16).padStart(16, "0")}`, + oprf_key_id: `0x${STAGING_RP_ID.toString(16)}`, + session_id: null, + action: hex(action), + signature, + nonce: hex(nonce), + proof_requests: [ + { + identifier: "faux-credential", + issuer_schema_id: Number(FAUX_ISSUER_SCHEMA_ID), + signal: hex(new TextEncoder().encode(signal)), + genesis_issued_at_min: null, + expires_at_min: null, + }, + ], + }), + ); +} diff --git a/web/walletkit/README.md b/web/walletkit/README.md index bdd29ce04..a575bb5f9 100644 --- a/web/walletkit/README.md +++ b/web/walletkit/README.md @@ -22,5 +22,7 @@ nix develop .#wasm --command npm --prefix web/walletkit run build ``` The release build uses `crates/walletkit` directly, disables its default -features, and optimizes the generated module with -`wasm-opt -Oz --converge`. +features except for `embed-zkeys`, and optimizes the generated module with +`wasm-opt -Oz --converge`. Embedding the proving artifacts currently makes the +optimized WASM roughly 40 MB; lazy artifact delivery and worker placement are +still future production work. diff --git a/web/walletkit/ubrn.config.yaml b/web/walletkit/ubrn.config.yaml index 20e7c47b7..5a1b5ec83 100644 --- a/web/walletkit/ubrn.config.yaml +++ b/web/walletkit/ubrn.config.yaml @@ -4,4 +4,6 @@ rust: wasm2: defaultFeatures: false + features: + - embed-zkeys ts: src/generated From 7f3ae9e67a7277a4ff4c3f9a03ec48033878a22b Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Thu, 27 Aug 2026 14:29:53 +0200 Subject: [PATCH 07/17] Fix browser credential proof generation --- crates/walletkit-core/src/credential.rs | 44 +++++++++++++++++++ .../src/app/page.tsx | 26 +++++++---- .../src/app/staging.ts | 10 +---- 3 files changed, 63 insertions(+), 17 deletions(-) diff --git a/crates/walletkit-core/src/credential.rs b/crates/walletkit-core/src/credential.rs index 6d51cc8a7..36123647b 100644 --- a/crates/walletkit-core/src/credential.rs +++ b/crates/walletkit-core/src/credential.rs @@ -7,6 +7,11 @@ use world_id_core::Credential as CoreCredential; use crate::error::WalletKitError; use crate::FieldElement; +#[derive(serde::Deserialize)] +struct IssuanceResponse { + credential: CoreCredential, +} + /// A wrapper around [`CoreCredential`] to enable FFI interoperability. /// /// Encapsulates the credential and exposes accessors for fields that FFI @@ -34,6 +39,33 @@ impl Credential { Ok(Self(credential)) } + /// Deserializes a `Credential` from an issuer response shaped as + /// `{ "credential": ... }`. + /// + /// Accepting the complete response lets JavaScript callers pass its raw + /// bytes to Rust without parsing signed `u64` fields as lossy JS numbers. + /// + /// # Errors + /// + /// Returns an error if the response or its credential cannot be deserialized. + #[uniffi::constructor] + #[expect( + clippy::needless_pass_by_value, + reason = "UniFFI constructors take owned byte buffers" + )] + pub fn from_issuance_response_bytes( + bytes: Vec, + ) -> Result { + let response: IssuanceResponse = + serde_json::from_slice(&bytes).map_err(|e| { + WalletKitError::InvalidInput { + attribute: "issuance_response_bytes".to_string(), + reason: format!("Failed to deserialize issuance response: {e}"), + } + })?; + Ok(Self(response.credential)) + } + /// Returns the credential's `sub` field element. #[must_use] pub fn sub(&self) -> FieldElement { @@ -174,4 +206,16 @@ mod tests { assert!(hex[2..].iter().all(|claim| claim == "0x0000000000000000000000000000000000000000000000000000000000000000")); } + + #[test] + fn issuance_response_preserves_u64_fields_above_javascript_safe_integer() { + let credential_id = 9_007_199_254_740_993; + let credential = CoreCredential::new().id(credential_id); + let response = serde_json::json!({ "credential": credential }); + let bytes = serde_json::to_vec(&response).unwrap(); + + let parsed = Credential::from_issuance_response_bytes(bytes).unwrap(); + + assert_eq!(parsed.0.id, credential_id); + } } diff --git a/examples/uniffi-web-authenticator-poc/src/app/page.tsx b/examples/uniffi-web-authenticator-poc/src/app/page.tsx index 3f346032e..9c27e0eca 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/page.tsx +++ b/examples/uniffi-web-authenticator-poc/src/app/page.tsx @@ -17,7 +17,7 @@ function printableState(state: string, details = {}) { { state, environment: "staging", - region: "eu", + region: "us", ...details, }, (_, value) => (typeof value === "bigint" ? value.toString() : value), @@ -25,6 +25,14 @@ function printableState(state: string, details = {}) { ); } +function printableError(error: unknown) { + if (error instanceof Error && "inner" in error) { + return `${error.message}: ${JSON.stringify(error.inner)}`; + } + + return String(error); +} + export default function Home() { const bindings = useRef(null); const seed = useRef(new Uint8Array(32)); @@ -77,7 +85,7 @@ export default function Home() { deriveAuthenticator(module); } catch (error) { setRuntime("Failed"); - setStatus(String(error)); + setStatus(printableError(error)); } })(); }, []); @@ -93,13 +101,13 @@ export default function Home() { new Uint8Array(seed.current).buffer, undefined, module.Environment.Staging, - module.Region.Eu, + module.Region.Us, undefined, ); setCanPoll(true); setStatus(printableState("registration-requested")); } catch (error) { - setStatus(String(error)); + setStatus(printableError(error)); } finally { setBusy(false); } @@ -121,7 +129,7 @@ export default function Home() { ), ); } catch (error) { - setStatus(String(error)); + setStatus(printableError(error)); } finally { setBusy(false); } @@ -140,7 +148,7 @@ export default function Home() { new Uint8Array(seed.current).buffer, undefined, module.Environment.Staging, - module.Region.Eu, + module.Region.Us, artifacts, ephemeralStore, ); @@ -152,7 +160,7 @@ export default function Home() { setAuthenticatorReady(true); setStatus(printableState("authenticator-initialized")); } catch (error) { - setStatus(String(error)); + setStatus(printableError(error)); } finally { setBusy(false); } @@ -172,7 +180,7 @@ export default function Home() { setCredentialIssued(true); setStatus(printableState("credential-issued", issued)); } catch (error) { - setStatus(String(error)); + setStatus(printableError(error)); } finally { setBusy(false); } @@ -194,7 +202,7 @@ export default function Home() { ); setStatus(response.toJson()); } catch (error) { - setStatus(String(error)); + setStatus(printableError(error)); } finally { setBusy(false); } diff --git a/examples/uniffi-web-authenticator-poc/src/app/staging.ts b/examples/uniffi-web-authenticator-poc/src/app/staging.ts index 5ffc3ea3b..d5d2af7d3 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/staging.ts +++ b/examples/uniffi-web-authenticator-poc/src/app/staging.ts @@ -59,15 +59,9 @@ export async function issueFauxCredential( ); } - const body = (await response.json()) as { credential?: unknown }; - if (body.credential === undefined) { - throw new Error("Faux issuer response did not contain a credential"); - } - - const credentialBytes = new TextEncoder().encode( - JSON.stringify(body.credential), + const credential = module.Credential.fromIssuanceResponseBytes( + await response.arrayBuffer(), ); - const credential = module.Credential.fromBytes(credentialBytes.buffer); const now = BigInt(Math.floor(Date.now() / 1000)); const credentialId = store.storeCredential( credential, From e7cfeb844984d72c1883cfc86defecfd6699f9e0 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Mon, 31 Aug 2026 13:26:03 +0200 Subject: [PATCH 08/17] fix css issues --- examples/uniffi-web-authenticator-poc/src/app/globals.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/uniffi-web-authenticator-poc/src/app/globals.css b/examples/uniffi-web-authenticator-poc/src/app/globals.css index 431798aa5..132ad75d7 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/globals.css +++ b/examples/uniffi-web-authenticator-poc/src/app/globals.css @@ -16,12 +16,15 @@ body { main { min-height: 100vh; display: grid; + grid-template-columns: minmax(0, 1fr); place-items: center; padding: 1.5rem; } .card { - width: min(48rem, 100%); + width: 100%; + max-width: 48rem; + min-width: 0; padding: 2rem; border: 1px solid #bdcbc3; border-radius: 1rem; @@ -43,6 +46,7 @@ h1 { pre { overflow: auto; + overflow-wrap: anywhere; margin: 1.5rem 0 0; padding: 1rem; border-radius: 0.5rem; From 848480ee0dbd6380bdfc4f2291581c5e7d52cd34 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Mon, 31 Aug 2026 13:26:12 +0200 Subject: [PATCH 09/17] bump version + change package name --- web/walletkit/package-lock.json | 4 ++-- web/walletkit/package.json | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/web/walletkit/package-lock.json b/web/walletkit/package-lock.json index a4773d0fb..1b67dddc2 100644 --- a/web/walletkit/package-lock.json +++ b/web/walletkit/package-lock.json @@ -1,12 +1,12 @@ { "name": "@worldcoin/walletkit-web", - "version": "0.21.2", + "version": "0.21.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@worldcoin/walletkit-web", - "version": "0.21.2", + "version": "0.21.3", "dependencies": { "@ubjs/core": "0.31.0-5", "@ubjs/wasm": "0.31.0-5" diff --git a/web/walletkit/package.json b/web/walletkit/package.json index a2673556f..dcdf894e0 100644 --- a/web/walletkit/package.json +++ b/web/walletkit/package.json @@ -1,7 +1,6 @@ { - "name": "@worldcoin/walletkit-web", - "version": "0.21.2", - "private": true, + "name": "walletkit-web", + "version": "0.21.3", "description": "Browser WebAssembly bindings for WalletKit.", "type": "module", "files": [ From e42cc2444f5f517d0d3b40f4bd460c8ba13c369d Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Mon, 31 Aug 2026 13:51:56 +0200 Subject: [PATCH 10/17] Use published walletkit-web package in POC --- README.md | 5 ++- .../uniffi-web-authenticator-poc/README.md | 28 ++++++------ .../package-lock.json | 44 +++++++++++-------- .../uniffi-web-authenticator-poc/package.json | 6 +-- .../src/app/page.tsx | 6 +-- .../src/app/staging.ts | 2 +- web/walletkit/README.md | 8 ++-- web/walletkit/package-lock.json | 4 +- 8 files changed, 52 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index ec47eaddd..1818551c0 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ See [`swift/README.md`](swift/README.md) for package integration details. ## Local development (browser/WASM) -The experimental `@worldcoin/walletkit-web` package builds directly from the +The experimental `walletkit-web` package builds directly from the `walletkit` crate and contains the generated bindings, wasm-bindgen glue, and optimized WASM module. Build it with the pinned WASM toolchain: @@ -63,7 +63,8 @@ nix develop .#wasm --command npm --prefix web/walletkit run build ``` The Next.js integration probe under `examples/uniffi-web-authenticator-poc` -consumes the package through its public `initializeWalletKit()` interface. +installs the published package and consumes its public `initializeWalletKit()` +interface. ## Local development (Android/Kotlin) diff --git a/examples/uniffi-web-authenticator-poc/README.md b/examples/uniffi-web-authenticator-poc/README.md index ea2ef646b..93bb31aca 100644 --- a/examples/uniffi-web-authenticator-poc/README.md +++ b/examples/uniffi-web-authenticator-poc/README.md @@ -1,28 +1,25 @@ # WalletKit web package Next.js example -> PROTOTYPE: integration probe for the private `@worldcoin/walletkit-web` -> package, not production packaging. +> PROTOTYPE: integration probe for the published `walletkit-web` package. This example verifies that a Next.js App Router application can consume WalletKit as an ordinary package without owning its Rust wrapper, UniFFI generation, WASM optimization, or asset staging. -Run it from the repository root with the pinned WASM toolchain: +Run it from the repository root: ```sh -nix develop .#wasm --command npm --prefix web/walletkit install -nix develop .#wasm --command npm --prefix examples/uniffi-web-authenticator-poc install -nix develop .#wasm --command npm --prefix examples/uniffi-web-authenticator-poc run dev +npm --prefix examples/uniffi-web-authenticator-poc install +npm --prefix examples/uniffi-web-authenticator-poc run dev ``` -`npm run dev` builds `@worldcoin/walletkit-web` before starting Next.js. Use -`npm run build` to prove the production bundle as well. The package build runs -inside `nix develop .#wasm`, which supplies Node, Binaryen, and the WASM-targeted -Clang and LLVM tools. +The example installs `walletkit-web` from npm and does not build the package's +Rust, generated bindings, or WASM locally. Use `npm run build` to prove the +production bundle as well. ## What the POC proves -- `@worldcoin/walletkit-web` hides generation and WASM loading behind +- `walletkit-web` hides generation and WASM loading behind `initializeWalletKit()`. - The package exposes WalletKit records, errors, objects, callbacks, and async authenticator methods. @@ -40,10 +37,11 @@ Clang and LLVM tools. ## Experimental compatibility pins -The released generator (`0.31.0-5`) cannot parse UniFFI 0.32 metadata, so this -POC pins the worktree to UniFFI 0.31.2. Its internal wasm-bindgen processor is -also pinned to 0.2.100, while `sqlite-wasm-rs` requires a newer schema; the -package build aligns the generator to WalletKit's 0.2.126 schema. +The published `walletkit-web` 0.21.3 package was generated with UniFFI 0.31.2 +because the released generator (`0.31.0-5`) cannot parse UniFFI 0.32 metadata. +Its internal wasm-bindgen processor is pinned to 0.2.100, while +`sqlite-wasm-rs` requires a newer schema; the package build aligns the +generator to WalletKit's 0.2.126 schema. WalletKit's native bindings ask UniFFI to adapt exported futures to Tokio. That adapter creates a fallback thread when it is polled without a Tokio runtime, diff --git a/examples/uniffi-web-authenticator-poc/package-lock.json b/examples/uniffi-web-authenticator-poc/package-lock.json index b81183300..025f6042b 100644 --- a/examples/uniffi-web-authenticator-poc/package-lock.json +++ b/examples/uniffi-web-authenticator-poc/package-lock.json @@ -8,11 +8,11 @@ "name": "walletkit-uniffi-web-authenticator-poc", "version": "0.0.0", "dependencies": { - "@worldcoin/walletkit-web": "file:../../web/walletkit", "next": "16.3.2", "react": "19.2.8", "react-dom": "19.2.8", - "viem": "^2.56.0" + "viem": "^2.56.0", + "walletkit-web": "0.21.3" }, "devDependencies": { "@types/node": "25.0.3", @@ -22,20 +22,6 @@ "typescript": "5.9.2" } }, - "../../web/walletkit": { - "name": "@worldcoin/walletkit-web", - "version": "0.21.2", - "dependencies": { - "@ubjs/core": "0.31.0-5", - "@ubjs/wasm": "0.31.0-5" - }, - "devDependencies": { - "esbuild": "0.25.9", - "prettier": "3.6.2", - "typescript": "5.9.2", - "uniffi-bindgen-react-native": "0.31.0-5" - } - }, "node_modules/@adraffy/ens-normalize": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", @@ -801,9 +787,20 @@ "@types/react": "^19.2.0" } }, - "node_modules/@worldcoin/walletkit-web": { - "resolved": "../../web/walletkit", - "link": true + "node_modules/@ubjs/core": { + "version": "0.31.0-5", + "resolved": "https://registry.npmjs.org/@ubjs/core/-/core-0.31.0-5.tgz", + "integrity": "sha512-oRBRtyYOhaodiOY3rLMZFgAHGFMmD44XefMpsAx4Ja0/rO+45kVdQB1VZsblQMLYxP965i3IHm56eymgo3I5eQ==", + "license": "MPL-2.0" + }, + "node_modules/@ubjs/wasm": { + "version": "0.31.0-5", + "resolved": "https://registry.npmjs.org/@ubjs/wasm/-/wasm-0.31.0-5.tgz", + "integrity": "sha512-dO7i67DQ1UKBSegznLVjVrYowmxY7gaXXluBdtJXPYgcR5vzwYf2ZbxAUqj4qL1JkqxRmeTKgXtuesFI+D5dPg==", + "license": "MPL-2.0", + "peerDependencies": { + "@ubjs/core": "^0.31.0-5" + } }, "node_modules/abitype": { "version": "1.2.3", @@ -1232,6 +1229,15 @@ } } }, + "node_modules/walletkit-web": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/walletkit-web/-/walletkit-web-0.21.3.tgz", + "integrity": "sha512-i6TSdctv40RLVFNiHd8zWLO4VLYNpGDzoLa5s6EcO3cXuKgfoJccZ7KEYisaW9d8rpTL+9driOWNlLLQVUhqdg==", + "dependencies": { + "@ubjs/core": "0.31.0-5", + "@ubjs/wasm": "0.31.0-5" + } + }, "node_modules/ws": { "version": "8.21.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", diff --git a/examples/uniffi-web-authenticator-poc/package.json b/examples/uniffi-web-authenticator-poc/package.json index 40ce55f8a..ccaaa8920 100644 --- a/examples/uniffi-web-authenticator-poc/package.json +++ b/examples/uniffi-web-authenticator-poc/package.json @@ -8,18 +8,16 @@ "url": "https://github.com/worldcoin/walletkit" }, "scripts": { - "predev": "npm --prefix ../../web/walletkit run build", "dev": "next dev", - "prebuild": "npm --prefix ../../web/walletkit run build", "build": "next build", "start": "next start" }, "dependencies": { - "@worldcoin/walletkit-web": "file:../../web/walletkit", "next": "16.3.2", "react": "19.2.8", "react-dom": "19.2.8", - "viem": "^2.56.0" + "viem": "^2.56.0", + "walletkit-web": "0.21.3" }, "devDependencies": { "@types/node": "25.0.3", diff --git a/examples/uniffi-web-authenticator-poc/src/app/page.tsx b/examples/uniffi-web-authenticator-poc/src/app/page.tsx index 9c27e0eca..d0aa9791e 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/page.tsx +++ b/examples/uniffi-web-authenticator-poc/src/app/page.tsx @@ -8,7 +8,7 @@ import type { InitializingAuthenticatorLike, RecoveryData, WalletKit, -} from "@worldcoin/walletkit-web"; +} from "walletkit-web"; import { createStagingProofRequest, issueFauxCredential } from "./staging"; @@ -76,9 +76,7 @@ export default function Home() { void (async () => { try { - const { initializeWalletKit } = await import( - "@worldcoin/walletkit-web" - ); + const { initializeWalletKit } = await import("walletkit-web"); const module = await initializeWalletKit(); bindings.current = module; setRuntime("Ready"); diff --git a/examples/uniffi-web-authenticator-poc/src/app/staging.ts b/examples/uniffi-web-authenticator-poc/src/app/staging.ts index d5d2af7d3..fcdc379ed 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/staging.ts +++ b/examples/uniffi-web-authenticator-poc/src/app/staging.ts @@ -4,7 +4,7 @@ import type { AuthenticatorLike, CredentialStoreLike, WalletKit, -} from "@worldcoin/walletkit-web"; +} from "walletkit-web"; const FAUX_ISSUER_SCHEMA_ID = 128n; const STAGING_RP_ID = 46n; diff --git a/web/walletkit/README.md b/web/walletkit/README.md index a575bb5f9..6ead1374e 100644 --- a/web/walletkit/README.md +++ b/web/walletkit/README.md @@ -1,16 +1,16 @@ -# `@worldcoin/walletkit-web` +# `walletkit-web` Browser WebAssembly bindings for WalletKit. -> PROTOTYPE: this package is private while its generation and publication -> workflow is being validated. +> PROTOTYPE: the package is published while its generation and release workflow +> is being validated. The package owns the compiled WalletKit module, generated TypeScript bindings, UniFFI player setup, and WASM asset resolution. Browser applications initialize it through one interface: ```ts -const { initializeWalletKit } = await import("@worldcoin/walletkit-web"); +const { initializeWalletKit } = await import("walletkit-web"); const walletKit = await initializeWalletKit(); ``` diff --git a/web/walletkit/package-lock.json b/web/walletkit/package-lock.json index 1b67dddc2..b6d81aeb5 100644 --- a/web/walletkit/package-lock.json +++ b/web/walletkit/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@worldcoin/walletkit-web", + "name": "walletkit-web", "version": "0.21.3", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@worldcoin/walletkit-web", + "name": "walletkit-web", "version": "0.21.3", "dependencies": { "@ubjs/core": "0.31.0-5", From 0aee6f46a733df2437be8c81d4b60e3f6fafbf64 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Mon, 31 Aug 2026 14:29:13 +0200 Subject: [PATCH 11/17] use web workers to offload cpu heavy workloads --- .../src/app/globals.css | 87 ++++- .../src/app/page.tsx | 328 +++++------------- .../src/app/walletkit.worker.ts | 188 ++++++++++ 3 files changed, 349 insertions(+), 254 deletions(-) create mode 100644 examples/uniffi-web-authenticator-poc/src/app/walletkit.worker.ts diff --git a/examples/uniffi-web-authenticator-poc/src/app/globals.css b/examples/uniffi-web-authenticator-poc/src/app/globals.css index 132ad75d7..831d4afc0 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/globals.css +++ b/examples/uniffi-web-authenticator-poc/src/app/globals.css @@ -15,15 +15,19 @@ body { main { min-height: 100vh; - display: grid; - grid-template-columns: minmax(0, 1fr); - place-items: center; padding: 1.5rem; } -.card { +.card-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1.5rem; width: 100%; - max-width: 48rem; + max-width: 90rem; + margin: 0 auto; +} + +.card { min-width: 0; padding: 2rem; border: 1px solid #bdcbc3; @@ -44,10 +48,18 @@ h1 { margin: 0.5rem 0 1rem; } +h2 { + margin-top: 0; +} + +h3 { + margin: 1.5rem 0 0; +} + pre { overflow: auto; overflow-wrap: anywhere; - margin: 1.5rem 0 0; + margin: 0.75rem 0 0; padding: 1rem; border-radius: 0.5rem; color: #d9f7e8; @@ -55,6 +67,10 @@ pre { white-space: pre-wrap; } +.action-output { + height: 16rem; +} + dl { display: grid; gap: 0.75rem; @@ -97,18 +113,57 @@ button:disabled { opacity: 0.45; } -details { - margin-top: 1.25rem; - padding: 1rem; - border: 1px solid #d1ddd5; - border-radius: 0.5rem; +.actions-card ol { + display: grid; + gap: 0.5rem; + margin: 1.5rem 0 0; + padding-left: 1.75rem; } -summary { - cursor: pointer; - font-weight: 700; +.progress-track { + position: relative; + overflow: hidden; + width: 100%; + max-width: 90rem; + height: 0.5rem; + margin: 1.5rem auto 0; + border-radius: 999px; + background: #d1ddd5; +} + +.progress-track span { + position: absolute; + width: 35%; + height: 100%; + border-radius: inherit; + background: #167552; + opacity: 0; +} + +.progress-track.is-active span { + opacity: 1; + animation: progress-indeterminate 1.2s ease-in-out infinite; +} + +@keyframes progress-indeterminate { + from { + transform: translateX(-100%); + } + + to { + transform: translateX(386%); + } +} + +@media (prefers-reduced-motion: reduce) { + .progress-track.is-active span { + width: 100%; + animation: none; + } } -ol { - padding-left: 1.5rem; +@media (max-width: 60rem) { + .card-grid { + grid-template-columns: minmax(0, 1fr); + } } diff --git a/examples/uniffi-web-authenticator-poc/src/app/page.tsx b/examples/uniffi-web-authenticator-poc/src/app/page.tsx index d0aa9791e..a7c2b6b7f 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/page.tsx +++ b/examples/uniffi-web-authenticator-poc/src/app/page.tsx @@ -2,273 +2,116 @@ import { useEffect, useRef, useState } from "react"; -import type { - AuthenticatorLike, - CredentialStoreLike, - InitializingAuthenticatorLike, - RecoveryData, - WalletKit, -} from "walletkit-web"; +import type { RecoveryData } from "walletkit-web"; -import { createStagingProofRequest, issueFauxCredential } from "./staging"; +type Action = "derive" | "register" | "initialize" | "issue" | "prove"; -function printableState(state: string, details = {}) { - return JSON.stringify( - { - state, - environment: "staging", - region: "us", - ...details, - }, - (_, value) => (typeof value === "bigint" ? value.toString() : value), - 2, - ); -} - -function printableError(error: unknown) { - if (error instanceof Error && "inner" in error) { - return `${error.message}: ${JSON.stringify(error.inner)}`; - } - - return String(error); -} +type WorkerState = { + runtime?: string; + recovery?: RecoveryData; + registered?: boolean; + authenticatorReady?: boolean; + credentialIssued?: boolean; + busy?: boolean; + status?: string; +}; export default function Home() { - const bindings = useRef(null); - const seed = useRef(new Uint8Array(32)); - const registration = useRef(undefined); - const authenticator = useRef(undefined); - const store = useRef(undefined); - const initialized = useRef(false); + const worker = useRef(null); const [runtime, setRuntime] = useState("Loading…"); const [recovery, setRecovery] = useState(); - const [confirmed, setConfirmed] = useState(false); const [registered, setRegistered] = useState(false); const [authenticatorReady, setAuthenticatorReady] = useState(false); const [credentialIssued, setCredentialIssued] = useState(false); const [busy, setBusy] = useState(false); - const [canPoll, setCanPoll] = useState(false); const [status, setStatus] = useState("Initializing generated bindings…"); - function deriveAuthenticator(module = bindings.current) { - if (!module) return; - seed.current = crypto.getRandomValues(new Uint8Array(32)); - setRecovery( - module.recoveryDataFromSeed(new Uint8Array(seed.current).buffer), - ); - registration.current = undefined; - authenticator.current = undefined; - store.current = undefined; - setCanPoll(false); - setRegistered(false); - setAuthenticatorReady(false); - setCredentialIssued(false); - setStatus( - printableState("authenticator-derived", { - seed: "32 random bytes held only in memory", - }), - ); - } - useEffect(() => { - if (initialized.current) return; - initialized.current = true; - - void (async () => { - try { - const { initializeWalletKit } = await import("walletkit-web"); - const module = await initializeWalletKit(); - bindings.current = module; - setRuntime("Ready"); - deriveAuthenticator(module); - } catch (error) { - setRuntime("Failed"); - setStatus(printableError(error)); + const walletKitWorker = new Worker( + new URL("./walletkit.worker.ts", import.meta.url), + { type: "module" }, + ); + worker.current = walletKitWorker; + walletKitWorker.onmessage = (event: MessageEvent) => { + const state = event.data; + if (state.runtime !== undefined) setRuntime(state.runtime); + if (state.recovery !== undefined) setRecovery(state.recovery); + if (state.registered !== undefined) setRegistered(state.registered); + if (state.authenticatorReady !== undefined) { + setAuthenticatorReady(state.authenticatorReady); } - })(); + if (state.credentialIssued !== undefined) { + setCredentialIssued(state.credentialIssued); + } + if (state.busy !== undefined) setBusy(state.busy); + if (state.status !== undefined) setStatus(state.status); + }; + + return () => { + worker.current = null; + walletKitWorker.terminate(); + }; }, []); - async function registerAuthenticator() { - const module = bindings.current; - if (!module) return; - setBusy(true); - setStatus("Sending registration request to the staging gateway…"); - try { - registration.current = - await module.InitializingAuthenticator.registerWithDefaults( - new Uint8Array(seed.current).buffer, - undefined, - module.Environment.Staging, - module.Region.Us, - undefined, - ); - setCanPoll(true); - setStatus(printableState("registration-requested")); - } catch (error) { - setStatus(printableError(error)); - } finally { - setBusy(false); - } - } - - async function pollRegistration() { - const module = bindings.current; - if (!module || !registration.current) return; - setBusy(true); - try { - const result = await registration.current.pollStatus(); - const finalized = module.RegistrationStatus.Finalized.instanceOf(result); - setRegistered(finalized); - setCanPoll(!finalized); - setStatus( - printableState( - finalized ? "registration-finalized" : "registration-pending", - { status: result.constructor.name }, - ), - ); - } catch (error) { - setStatus(printableError(error)); - } finally { - setBusy(false); - } - } - - async function initializeRegisteredAuthenticator() { - const module = bindings.current; - if (!module) return; - setBusy(true); - setStatus("Initializing the registered authenticator and ephemeral store…"); - try { - const ephemeralStore = module.CredentialStore.newEphemeral(); - const artifacts = new module.EmbeddedZkArtifacts().asZkArtifactSource(); - const initializedAuthenticator = - await module.Authenticator.initWithDefaults( - new Uint8Array(seed.current).buffer, - undefined, - module.Environment.Staging, - module.Region.Us, - artifacts, - ephemeralStore, - ); - initializedAuthenticator.initStorage( - BigInt(Math.floor(Date.now() / 1000)), - ); - store.current = ephemeralStore; - authenticator.current = initializedAuthenticator; - setAuthenticatorReady(true); - setStatus(printableState("authenticator-initialized")); - } catch (error) { - setStatus(printableError(error)); - } finally { - setBusy(false); - } - } - - async function issueCredential() { - const module = bindings.current; - if (!module || !authenticator.current || !store.current) return; - setBusy(true); - setStatus("Requesting a credential from the staging faux issuer…"); - try { - const issued = await issueFauxCredential( - module, - authenticator.current, - store.current, - ); - setCredentialIssued(true); - setStatus(printableState("credential-issued", issued)); - } catch (error) { - setStatus(printableError(error)); - } finally { - setBusy(false); - } - } - - async function generateProof() { - const module = bindings.current; - if (!module || !authenticator.current) return; - setBusy(true); - setStatus("Generating a uniqueness proof in browser WASM…"); - try { - const request = await createStagingProofRequest( - module, - "walletkit-web-example", - ); - const response = await authenticator.current.generateProof( - request, - BigInt(Math.floor(Date.now() / 1000)), - ); - setStatus(response.toJson()); - } catch (error) { - setStatus(printableError(error)); - } finally { - setBusy(false); - } + function perform(action: Action) { + worker.current?.postMessage(action); } return (
-
-

WalletKit web package integration probe

-

WalletKit credential proof in browser WASM

-

- Derive and register a temporary staging authenticator, issue a faux - credential, then generate a proof for it entirely in the browser. -

-
-
-
WASM runtime
-
{runtime}
-
-
-
Authenticator address
-
{recovery?.authenticatorAddress ?? "—"}
-
-
-
Authenticator public key
-
{recovery?.authenticatorPubkey ?? "—"}
-
-
-
Signer commitment
-
{recovery?.offchainSignerCommitment ?? "—"}
-
-
- -
- Staging credential proof +
+
+

WalletKit web package integration probe

+

WalletKit credential proof in browser WASM

+

+ Derive and register a temporary staging authenticator, issue a faux + credential, then generate a proof for it entirely in the browser. +

+
+
+
WASM runtime
+
{runtime}
+
+
+
Authenticator address
+
{recovery?.authenticatorAddress ?? "—"}
+
+
+
Authenticator public key
+
{recovery?.authenticatorPubkey ?? "—"}
+
+
+
Signer commitment
+
{recovery?.offchainSignerCommitment ?? "—"}
+
+
+ +
+ +
+

Staging credential proof

This creates a real temporary account and credential in staging. The seed and credential store are discarded when this tab reloads.

-
  1. -
  2. @@ -276,7 +119,7 @@ export default function Home() {
  3. @@ -284,15 +127,24 @@ export default function Home() {
-
-
{status}
-
+

Action output

+
{status}
+
+ +
+ +
); } diff --git a/examples/uniffi-web-authenticator-poc/src/app/walletkit.worker.ts b/examples/uniffi-web-authenticator-poc/src/app/walletkit.worker.ts new file mode 100644 index 000000000..c00dc8a9d --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/src/app/walletkit.worker.ts @@ -0,0 +1,188 @@ +import type { + AuthenticatorLike, + CredentialStoreLike, + InitializingAuthenticatorLike, + WalletKit, +} from "walletkit-web"; + +import { createStagingProofRequest, issueFauxCredential } from "./staging"; + +type Action = "derive" | "register" | "initialize" | "issue" | "prove"; + +type WorkerState = { + runtime?: string; + recovery?: { + authenticatorAddress: string; + authenticatorPubkey: string; + offchainSignerCommitment: string; + }; + registered?: boolean; + authenticatorReady?: boolean; + credentialIssued?: boolean; + busy?: boolean; + status?: string; +}; + +let bindings: WalletKit; +let seed = new Uint8Array(32); +let registration: InitializingAuthenticatorLike | undefined; +let authenticator: AuthenticatorLike | undefined; +let store: CredentialStoreLike | undefined; + +const REGISTRATION_POLL_INTERVAL_MS = 500; + +function wait(milliseconds: number) { + return new Promise((resolve) => setTimeout(resolve, milliseconds)); +} + +function printableState(state: string, details = {}) { + return JSON.stringify( + { + state, + environment: "staging", + region: "us", + ...details, + }, + (_, value) => (typeof value === "bigint" ? value.toString() : value), + 2, + ); +} + +function printableError(error: unknown) { + if (error instanceof Error && "inner" in error) { + return `${error.message}: ${JSON.stringify(error.inner)}`; + } + + return String(error); +} + +function update(state: WorkerState) { + self.postMessage(state); +} + +function deriveAuthenticator() { + seed = crypto.getRandomValues(new Uint8Array(32)); + const recovery = bindings.recoveryDataFromSeed(new Uint8Array(seed).buffer); + registration = undefined; + authenticator = undefined; + store = undefined; + update({ + recovery: { + authenticatorAddress: recovery.authenticatorAddress, + authenticatorPubkey: recovery.authenticatorPubkey, + offchainSignerCommitment: recovery.offchainSignerCommitment, + }, + registered: false, + authenticatorReady: false, + credentialIssued: false, + status: printableState("authenticator-derived", { + seed: "32 random bytes held only in memory", + }), + }); +} + +async function perform(action: Action) { + update({ busy: true }); + try { + switch (action) { + case "derive": + deriveAuthenticator(); + break; + case "register": + update({ status: "Sending registration request to the staging gateway…" }); + registration = + await bindings.InitializingAuthenticator.registerWithDefaults( + new Uint8Array(seed).buffer, + undefined, + bindings.Environment.Staging, + bindings.Region.Us, + undefined, + ); + update({ status: printableState("registration-requested") }); + while (registration) { + const result = await registration.pollStatus(); + const finalized = + bindings.RegistrationStatus.Finalized.instanceOf(result); + update({ + registered: finalized, + status: printableState( + finalized ? "registration-finalized" : "registration-pending", + { status: result.constructor.name }, + ), + }); + if (finalized) break; + await wait(REGISTRATION_POLL_INTERVAL_MS); + } + break; + case "initialize": { + update({ + status: "Initializing the registered authenticator and ephemeral store…", + }); + const ephemeralStore = bindings.CredentialStore.newEphemeral(); + const artifacts = new bindings.EmbeddedZkArtifacts().asZkArtifactSource(); + const initializedAuthenticator = + await bindings.Authenticator.initWithDefaults( + new Uint8Array(seed).buffer, + undefined, + bindings.Environment.Staging, + bindings.Region.Us, + artifacts, + ephemeralStore, + ); + initializedAuthenticator.initStorage( + BigInt(Math.floor(Date.now() / 1000)), + ); + store = ephemeralStore; + authenticator = initializedAuthenticator; + update({ + authenticatorReady: true, + status: printableState("authenticator-initialized"), + }); + break; + } + case "issue": { + if (!authenticator || !store) return; + update({ status: "Requesting a credential from the staging faux issuer…" }); + const issued = await issueFauxCredential(bindings, authenticator, store); + update({ + credentialIssued: true, + status: printableState("credential-issued", issued), + }); + break; + } + case "prove": { + if (!authenticator) return; + update({ status: "Generating a uniqueness proof in browser WASM…" }); + const request = await createStagingProofRequest( + bindings, + "walletkit-web-example", + ); + const response = await authenticator.generateProof( + request, + BigInt(Math.floor(Date.now() / 1000)), + ); + update({ status: response.toJson() }); + break; + } + } + } catch (error) { + update({ status: printableError(error) }); + } finally { + update({ busy: false }); + } +} + +self.onmessage = (event: MessageEvent) => { + void perform(event.data); +}; + +void (async () => { + try { + const { initializeWalletKit } = await import("walletkit-web"); + bindings = await initializeWalletKit(); + update({ runtime: "Ready" }); + deriveAuthenticator(); + } catch (error) { + update({ runtime: "Failed", status: printableError(error) }); + } +})(); From a92c68e3cd509292bdf351363e5b92453bb3667f Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Mon, 31 Aug 2026 15:27:07 +0200 Subject: [PATCH 12/17] next js dev paths --- examples/uniffi-web-authenticator-poc/next-env.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/uniffi-web-authenticator-poc/next-env.d.ts b/examples/uniffi-web-authenticator-poc/next-env.d.ts index ce4e94a6b..a419cbe4e 100644 --- a/examples/uniffi-web-authenticator-poc/next-env.d.ts +++ b/examples/uniffi-web-authenticator-poc/next-env.d.ts @@ -1,7 +1,7 @@ /// /// -import "./.next/types/routes.d.ts"; -import "./.next/types/root-params.d.ts"; +import "./.next/dev/types/routes.d.ts"; +import "./.next/dev/types/root-params.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. From 8275444d106f8289477383109be2211a72c0d51a Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Mon, 31 Aug 2026 15:27:21 +0200 Subject: [PATCH 13/17] move faux credential issuance to example --- crates/walletkit-core/src/credential.rs | 44 ------------------- .../src/app/staging.ts | 15 +++++-- 2 files changed, 12 insertions(+), 47 deletions(-) diff --git a/crates/walletkit-core/src/credential.rs b/crates/walletkit-core/src/credential.rs index 36123647b..66b57b139 100644 --- a/crates/walletkit-core/src/credential.rs +++ b/crates/walletkit-core/src/credential.rs @@ -7,11 +7,6 @@ use world_id_core::Credential as CoreCredential; use crate::error::WalletKitError; use crate::FieldElement; -#[derive(serde::Deserialize)] -struct IssuanceResponse { - credential: CoreCredential, -} - /// A wrapper around [`CoreCredential`] to enable FFI interoperability. /// /// Encapsulates the credential and exposes accessors for fields that FFI @@ -39,33 +34,6 @@ impl Credential { Ok(Self(credential)) } - /// Deserializes a `Credential` from an issuer response shaped as - /// `{ "credential": ... }`. - /// - /// Accepting the complete response lets JavaScript callers pass its raw - /// bytes to Rust without parsing signed `u64` fields as lossy JS numbers. - /// - /// # Errors - /// - /// Returns an error if the response or its credential cannot be deserialized. - #[uniffi::constructor] - #[expect( - clippy::needless_pass_by_value, - reason = "UniFFI constructors take owned byte buffers" - )] - pub fn from_issuance_response_bytes( - bytes: Vec, - ) -> Result { - let response: IssuanceResponse = - serde_json::from_slice(&bytes).map_err(|e| { - WalletKitError::InvalidInput { - attribute: "issuance_response_bytes".to_string(), - reason: format!("Failed to deserialize issuance response: {e}"), - } - })?; - Ok(Self(response.credential)) - } - /// Returns the credential's `sub` field element. #[must_use] pub fn sub(&self) -> FieldElement { @@ -157,7 +125,6 @@ impl Deref for Credential { &self.0 } } - #[cfg(test)] mod tests { use ruint::aliases::U256; @@ -207,15 +174,4 @@ mod tests { == "0x0000000000000000000000000000000000000000000000000000000000000000")); } - #[test] - fn issuance_response_preserves_u64_fields_above_javascript_safe_integer() { - let credential_id = 9_007_199_254_740_993; - let credential = CoreCredential::new().id(credential_id); - let response = serde_json::json!({ "credential": credential }); - let bytes = serde_json::to_vec(&response).unwrap(); - - let parsed = Credential::from_issuance_response_bytes(bytes).unwrap(); - - assert_eq!(parsed.0.id, credential_id); - } } diff --git a/examples/uniffi-web-authenticator-poc/src/app/staging.ts b/examples/uniffi-web-authenticator-poc/src/app/staging.ts index fcdc379ed..85d3ff4bf 100644 --- a/examples/uniffi-web-authenticator-poc/src/app/staging.ts +++ b/examples/uniffi-web-authenticator-poc/src/app/staging.ts @@ -1,3 +1,4 @@ +import { parse, stringify } from "lossless-json"; import { privateKeyToAccount } from "viem/accounts"; import type { @@ -59,9 +60,17 @@ export async function issueFauxCredential( ); } - const credential = module.Credential.fromIssuanceResponseBytes( - await response.arrayBuffer(), - ); + const body = parse(await response.text()) as { credential?: unknown }; + if (body.credential === undefined) { + throw new Error("Faux issuer response did not contain a credential"); + } + + const serializedCredential = stringify(body.credential); + if (serializedCredential === undefined) { + throw new Error("Faux issuer response contained an invalid credential"); + } + const credentialBytes = new TextEncoder().encode(serializedCredential); + const credential = module.Credential.fromBytes(credentialBytes.buffer); const now = BigInt(Math.floor(Date.now() / 1000)); const credentialId = store.storeCredential( credential, From 295a254947bf9c94618930538603d24f35e886e5 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Mon, 31 Aug 2026 15:27:31 +0200 Subject: [PATCH 14/17] allow local dev with npm run walletkit:local --- examples/uniffi-web-authenticator-poc/package-lock.json | 7 +++++++ examples/uniffi-web-authenticator-poc/package.json | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/uniffi-web-authenticator-poc/package-lock.json b/examples/uniffi-web-authenticator-poc/package-lock.json index 025f6042b..e8eccc838 100644 --- a/examples/uniffi-web-authenticator-poc/package-lock.json +++ b/examples/uniffi-web-authenticator-poc/package-lock.json @@ -8,6 +8,7 @@ "name": "walletkit-uniffi-web-authenticator-poc", "version": "0.0.0", "dependencies": { + "lossless-json": "^4.3.1", "next": "16.3.2", "react": "19.2.8", "react-dom": "19.2.8", @@ -899,6 +900,12 @@ "ws": "*" } }, + "node_modules/lossless-json": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-4.3.1.tgz", + "integrity": "sha512-SqD/Bg3ZfltBJ2Z14hJ/BihnvtV553WO4g9/ePtlp4lrnl9jF3AdIJt53A/Wkg/0Li+LMfxaBqgx1MiFZdQlpQ==", + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.18", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", diff --git a/examples/uniffi-web-authenticator-poc/package.json b/examples/uniffi-web-authenticator-poc/package.json index ccaaa8920..cc4a6eba0 100644 --- a/examples/uniffi-web-authenticator-poc/package.json +++ b/examples/uniffi-web-authenticator-poc/package.json @@ -10,9 +10,12 @@ "scripts": { "dev": "next dev", "build": "next build", - "start": "next start" + "start": "next start", + "walletkit:local": "npm --prefix ../../web/walletkit run build && npm install --no-save ../../web/walletkit", + "walletkit:published": "npm ci" }, "dependencies": { + "lossless-json": "^4.3.1", "next": "16.3.2", "react": "19.2.8", "react-dom": "19.2.8", From eec3fe6ebe893a867f316939e37fed86fa249757 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Tue, 1 Sep 2026 13:16:05 +0200 Subject: [PATCH 15/17] use bun instead of npm --- README.md | 4 +- crates/walletkit-core/src/credential.rs | 1 - .../uniffi-web-authenticator-poc/README.md | 12 +- .../uniffi-web-authenticator-poc/bun.lock | 181 +++ .../package-lock.json | 1270 ----------------- .../uniffi-web-authenticator-poc/package.json | 5 +- flake.nix | 1 + nix/README.md | 2 +- nix/wasm.nix | 1 + web/walletkit/README.md | 4 +- web/walletkit/bun.lock | 84 ++ web/walletkit/package-lock.json | 562 -------- web/walletkit/package.json | 7 +- 13 files changed, 287 insertions(+), 1847 deletions(-) create mode 100644 examples/uniffi-web-authenticator-poc/bun.lock delete mode 100644 examples/uniffi-web-authenticator-poc/package-lock.json create mode 100644 web/walletkit/bun.lock delete mode 100644 web/walletkit/package-lock.json diff --git a/README.md b/README.md index 1818551c0..be1fff89b 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,8 @@ The experimental `walletkit-web` package builds directly from the optimized WASM module. Build it with the pinned WASM toolchain: ```bash -nix develop .#wasm --command npm --prefix web/walletkit install -nix develop .#wasm --command npm --prefix web/walletkit run build +nix develop .#wasm --command bun install --cwd web/walletkit --frozen-lockfile +nix develop .#wasm --command bun run --cwd web/walletkit build ``` The Next.js integration probe under `examples/uniffi-web-authenticator-poc` diff --git a/crates/walletkit-core/src/credential.rs b/crates/walletkit-core/src/credential.rs index 66b57b139..4d1095a68 100644 --- a/crates/walletkit-core/src/credential.rs +++ b/crates/walletkit-core/src/credential.rs @@ -173,5 +173,4 @@ mod tests { assert!(hex[2..].iter().all(|claim| claim == "0x0000000000000000000000000000000000000000000000000000000000000000")); } - } diff --git a/examples/uniffi-web-authenticator-poc/README.md b/examples/uniffi-web-authenticator-poc/README.md index 93bb31aca..01e6a33d8 100644 --- a/examples/uniffi-web-authenticator-poc/README.md +++ b/examples/uniffi-web-authenticator-poc/README.md @@ -9,14 +9,18 @@ generation, WASM optimization, or asset staging. Run it from the repository root: ```sh -npm --prefix examples/uniffi-web-authenticator-poc install -npm --prefix examples/uniffi-web-authenticator-poc run dev +bun install --cwd examples/uniffi-web-authenticator-poc --frozen-lockfile +bun run --cwd examples/uniffi-web-authenticator-poc dev ``` -The example installs `walletkit-web` from npm and does not build the package's -Rust, generated bindings, or WASM locally. Use `npm run build` to prove the +The example installs `walletkit-web` from the npm registry and does not build the +package's Rust, generated bindings, or WASM locally. Use `bun run build` to prove the production bundle as well. +To test the package from this checkout instead, run `bun run walletkit:local` +from the example directory inside the WASM Nix shell. This builds and links the +local package. Run `bun run walletkit:published` to restore the registry package. + ## What the POC proves - `walletkit-web` hides generation and WASM loading behind diff --git a/examples/uniffi-web-authenticator-poc/bun.lock b/examples/uniffi-web-authenticator-poc/bun.lock new file mode 100644 index 000000000..d7969f932 --- /dev/null +++ b/examples/uniffi-web-authenticator-poc/bun.lock @@ -0,0 +1,181 @@ +{ + "lockfileVersion": 1, + "configVersion": 0, + "workspaces": { + "": { + "name": "walletkit-uniffi-web-authenticator-poc", + "dependencies": { + "lossless-json": "^4.3.1", + "next": "16.3.2", + "react": "19.2.8", + "react-dom": "19.2.8", + "viem": "^2.56.0", + "walletkit-web": "0.21.3", + }, + "devDependencies": { + "@types/node": "25.0.3", + "@types/react": "19.2.14", + "@types/react-dom": "19.2.3", + "prettier": "3.6.2", + "typescript": "5.9.2", + }, + }, + }, + "packages": { + "@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.11.1", "", {}, "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="], + + "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], + + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.2" }, "os": "darwin", "cpu": "arm64" }, "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg=="], + + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.3.2" }, "os": "darwin", "cpu": "x64" }, "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w=="], + + "@img/sharp-freebsd-wasm32": ["@img/sharp-freebsd-wasm32@0.35.3", "", { "dependencies": { "@img/sharp-wasm32": "0.35.3" }, "os": "freebsd" }, "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg=="], + + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg=="], + + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw=="], + + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.3.2", "", { "os": "linux", "cpu": "arm" }, "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ=="], + + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA=="], + + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.3.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw=="], + + "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.3.2", "", { "os": "linux", "cpu": "none" }, "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w=="], + + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.3.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ=="], + + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w=="], + + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw=="], + + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ=="], + + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.3.2" }, "os": "linux", "cpu": "arm" }, "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA=="], + + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.3.2" }, "os": "linux", "cpu": "arm64" }, "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ=="], + + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.3.2" }, "os": "linux", "cpu": "ppc64" }, "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA=="], + + "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.3.2" }, "os": "linux", "cpu": "none" }, "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ=="], + + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.3.2" }, "os": "linux", "cpu": "s390x" }, "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw=="], + + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.3.2" }, "os": "linux", "cpu": "x64" }, "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA=="], + + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" }, "os": "linux", "cpu": "arm64" }, "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w=="], + + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.3.2" }, "os": "linux", "cpu": "x64" }, "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg=="], + + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.35.3", "", { "dependencies": { "@emnapi/runtime": "^1.11.1" } }, "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w=="], + + "@img/sharp-webcontainers-wasm32": ["@img/sharp-webcontainers-wasm32@0.35.3", "", { "dependencies": { "@img/sharp-wasm32": "0.35.3" }, "cpu": "none" }, "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q=="], + + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.35.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.35.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.35.3", "", { "os": "win32", "cpu": "x64" }, "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA=="], + + "@next/env": ["@next/env@16.3.2", "", {}, "sha512-8k4YoG8cM7LWlkfzGNYCRBbFNlernLiMw4s0btVl+CmmWqn3VpYypA72/5Feb1UWdxe6tHqr5KHP4p4Y4m9luA=="], + + "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ib5Llm93YCKoKWDh6ZaHq6QWTuOZ2bRkSnUwMmX8dsRIOkBNL1vVlSiUKSfixPL9SSh9pvukzqajk/klkn5vqg=="], + + "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-qd98fX2+I5nYJDioW2o7nSjoxM5KvWdeDefM80igia4+C/qSIEhH4MhTE+hO/7qKM7W37/Mq+dOWp8UePSyLHw=="], + + "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-vqsgb6FAOzcrCccsLXiKtAy5t8EzO+uOazuFaSkQxeY0tNONG3vpHYy8pyBafcI5SNFPTeyard6yTr6SzNGo2A=="], + + "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-xIe1eujfHUB2XcxHGddxJyu6TJRPjC5NpIkQYB/32ESkt5VkQyIAjmLRS38c+s6QY+qjtY/4KarVDzXRuD7lZQ=="], + + "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Fe0SA2j8X0kmc3aveuHD7UktO3AE2+mH3LguP60vGbz7u0z+MrDXbeb5iZFYAwR7EzzzXJ2Yk966w9mGTFMqfA=="], + + "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-TFBipb+gyesI/2Ve4zVu7kGltBWN/R466G5/1gtt2lECfc22G1pjkTxu68Q9aFcOaXiRGTQfvDbQQFe7mYgxiQ=="], + + "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.3.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-rVtmnNpBYIosDnKD/96dKxFsJnwnn1WRGG/HioSe8XCm2ksSHNrd2R6+hSjvTBxeMNhJ9pYeu/90cWB1nQLuNA=="], + + "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.3.2", "", { "os": "win32", "cpu": "x64" }, "sha512-H4Y2o2/JcHu8LtwzD5CXfHhwxwz8gfsx2HXDEw46Mtev5xHnEmB7HNtZtmriw5ReUOjRtcDqo7XSbU01FT9NlA=="], + + "@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="], + + "@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="], + + "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], + + "@scure/base": ["@scure/base@1.2.6", "", {}, "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg=="], + + "@scure/bip32": ["@scure/bip32@1.7.0", "", { "dependencies": { "@noble/curves": "~1.9.0", "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" } }, "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw=="], + + "@scure/bip39": ["@scure/bip39@1.6.0", "", { "dependencies": { "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" } }, "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A=="], + + "@swc/helpers": ["@swc/helpers@0.5.23", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw=="], + + "@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="], + + "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], + + "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], + + "@ubjs/core": ["@ubjs/core@0.31.0-5", "", {}, "sha512-oRBRtyYOhaodiOY3rLMZFgAHGFMmD44XefMpsAx4Ja0/rO+45kVdQB1VZsblQMLYxP965i3IHm56eymgo3I5eQ=="], + + "@ubjs/wasm": ["@ubjs/wasm@0.31.0-5", "", { "peerDependencies": { "@ubjs/core": "^0.31.0-5" } }, "sha512-dO7i67DQ1UKBSegznLVjVrYowmxY7gaXXluBdtJXPYgcR5vzwYf2ZbxAUqj4qL1JkqxRmeTKgXtuesFI+D5dPg=="], + + "abitype": ["abitype@1.2.3", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3.22.0 || ^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg=="], + + "baseline-browser-mapping": ["baseline-browser-mapping@2.11.19", "", { "bin": "dist/cli.cjs" }, "sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001810", "", {}, "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg=="], + + "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], + + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "isows": ["isows@1.0.7", "", { "peerDependencies": { "ws": "*" } }, "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg=="], + + "lossless-json": ["lossless-json@4.3.1", "", {}, "sha512-SqD/Bg3ZfltBJ2Z14hJ/BihnvtV553WO4g9/ePtlp4lrnl9jF3AdIJt53A/Wkg/0Li+LMfxaBqgx1MiFZdQlpQ=="], + + "nanoid": ["nanoid@3.3.18", "", { "bin": "bin/nanoid.cjs" }, "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w=="], + + "next": ["next@16.3.2", "", { "dependencies": { "@next/env": "16.3.2", "@swc/helpers": "0.5.23", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.5.23", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.3.2", "@next/swc-darwin-x64": "16.3.2", "@next/swc-linux-arm64-gnu": "16.3.2", "@next/swc-linux-arm64-musl": "16.3.2", "@next/swc-linux-x64-gnu": "16.3.2", "@next/swc-linux-x64-musl": "16.3.2", "@next/swc-win32-arm64-msvc": "16.3.2", "@next/swc-win32-x64-msvc": "16.3.2", "sharp": "^0.35.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": "dist/bin/next" }, "sha512-/ZCaubUy17Lld1SiPWxuPbCk2ihqAxF2QNQaPZeEaEb7t1I58qhsJN187D7AfpapHAqUPXH0f/thtdW9dWgWFg=="], + + "ox": ["ox@0.14.34", "", { "dependencies": { "@adraffy/ens-normalize": "^1.11.0", "@noble/ciphers": "^1.3.0", "@noble/curves": "1.9.1", "@noble/hashes": "^1.8.0", "@scure/bip32": "^1.7.0", "@scure/bip39": "^1.6.0", "abitype": "^1.2.3", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" } }, "sha512-12seOIk7dv8eAoGQhcWaeKZxNz304IVcDvb9U5Y7JZAEVe21Nm1YMxLjhWah+su5BD4Omx4Zz0z5x3ij9M4GYQ=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "postcss": ["postcss@8.5.23", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg=="], + + "prettier": ["prettier@3.6.2", "", { "bin": "bin/prettier.cjs" }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], + + "react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="], + + "react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="], + + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + + "semver": ["semver@7.8.5", "", { "bin": "bin/semver.js" }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + + "sharp": ["sharp@0.35.3", "", { "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", "semver": "^7.8.5" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.35.3", "@img/sharp-darwin-x64": "0.35.3", "@img/sharp-freebsd-wasm32": "0.35.3", "@img/sharp-libvips-darwin-arm64": "1.3.2", "@img/sharp-libvips-darwin-x64": "1.3.2", "@img/sharp-libvips-linux-arm": "1.3.2", "@img/sharp-libvips-linux-arm64": "1.3.2", "@img/sharp-libvips-linux-ppc64": "1.3.2", "@img/sharp-libvips-linux-riscv64": "1.3.2", "@img/sharp-libvips-linux-s390x": "1.3.2", "@img/sharp-libvips-linux-x64": "1.3.2", "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", "@img/sharp-libvips-linuxmusl-x64": "1.3.2", "@img/sharp-linux-arm": "0.35.3", "@img/sharp-linux-arm64": "0.35.3", "@img/sharp-linux-ppc64": "0.35.3", "@img/sharp-linux-riscv64": "0.35.3", "@img/sharp-linux-s390x": "0.35.3", "@img/sharp-linux-x64": "0.35.3", "@img/sharp-linuxmusl-arm64": "0.35.3", "@img/sharp-linuxmusl-x64": "0.35.3", "@img/sharp-webcontainers-wasm32": "0.35.3", "@img/sharp-win32-arm64": "0.35.3", "@img/sharp-win32-ia32": "0.35.3", "@img/sharp-win32-x64": "0.35.3" } }, "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + + "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "viem": ["viem@2.56.0", "", { "dependencies": { "@noble/curves": "1.9.1", "@noble/hashes": "1.8.0", "@scure/bip32": "1.7.0", "@scure/bip39": "1.6.0", "abitype": "1.2.3", "isows": "1.0.7", "ox": "0.14.34", "ws": "8.21.0" }, "peerDependencies": { "typescript": ">=5.0.4" } }, "sha512-JmkgIk4jN+im4oguLxwPv19pwSaGH9kcGSq25Ilm55106ULBBMNR3eWKKA0wZoeyLPSHIiOwZ4sGceEYEIq7LA=="], + + "walletkit-web": ["walletkit-web@0.21.3", "", { "dependencies": { "@ubjs/core": "0.31.0-5", "@ubjs/wasm": "0.31.0-5" } }, "sha512-i6TSdctv40RLVFNiHd8zWLO4VLYNpGDzoLa5s6EcO3cXuKgfoJccZ7KEYisaW9d8rpTL+9driOWNlLLQVUhqdg=="], + + "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], + } +} diff --git a/examples/uniffi-web-authenticator-poc/package-lock.json b/examples/uniffi-web-authenticator-poc/package-lock.json deleted file mode 100644 index e8eccc838..000000000 --- a/examples/uniffi-web-authenticator-poc/package-lock.json +++ /dev/null @@ -1,1270 +0,0 @@ -{ - "name": "walletkit-uniffi-web-authenticator-poc", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "walletkit-uniffi-web-authenticator-poc", - "version": "0.0.0", - "dependencies": { - "lossless-json": "^4.3.1", - "next": "16.3.2", - "react": "19.2.8", - "react-dom": "19.2.8", - "viem": "^2.56.0", - "walletkit-web": "0.21.3" - }, - "devDependencies": { - "@types/node": "25.0.3", - "@types/react": "19.2.14", - "@types/react-dom": "19.2.3", - "prettier": "3.6.2", - "typescript": "5.9.2" - } - }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", - "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", - "license": "MIT" - }, - "node_modules/@emnapi/runtime": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", - "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@img/colour": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", - "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", - "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.3.2" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", - "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.3.2" - } - }, - "node_modules/@img/sharp-freebsd-wasm32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", - "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", - "license": "Apache-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "dependencies": { - "@img/sharp-wasm32": "0.35.3" - }, - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", - "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", - "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", - "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", - "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", - "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", - "cpu": [ - "ppc64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", - "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", - "cpu": [ - "riscv64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", - "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", - "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", - "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", - "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", - "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.3.2" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", - "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.3.2" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", - "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", - "cpu": [ - "ppc64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.3.2" - } - }, - "node_modules/@img/sharp-linux-riscv64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", - "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", - "cpu": [ - "riscv64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.3.2" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", - "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.3.2" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", - "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.3.2" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", - "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", - "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.3.2" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", - "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.11.1" - }, - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-webcontainers-wasm32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", - "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@img/sharp-wasm32": "0.35.3" - }, - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", - "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", - "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", - "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@next/env": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.2.tgz", - "integrity": "sha512-8k4YoG8cM7LWlkfzGNYCRBbFNlernLiMw4s0btVl+CmmWqn3VpYypA72/5Feb1UWdxe6tHqr5KHP4p4Y4m9luA==", - "license": "MIT" - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.2.tgz", - "integrity": "sha512-ib5Llm93YCKoKWDh6ZaHq6QWTuOZ2bRkSnUwMmX8dsRIOkBNL1vVlSiUKSfixPL9SSh9pvukzqajk/klkn5vqg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.2.tgz", - "integrity": "sha512-qd98fX2+I5nYJDioW2o7nSjoxM5KvWdeDefM80igia4+C/qSIEhH4MhTE+hO/7qKM7W37/Mq+dOWp8UePSyLHw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.2.tgz", - "integrity": "sha512-vqsgb6FAOzcrCccsLXiKtAy5t8EzO+uOazuFaSkQxeY0tNONG3vpHYy8pyBafcI5SNFPTeyard6yTr6SzNGo2A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.2.tgz", - "integrity": "sha512-xIe1eujfHUB2XcxHGddxJyu6TJRPjC5NpIkQYB/32ESkt5VkQyIAjmLRS38c+s6QY+qjtY/4KarVDzXRuD7lZQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.2.tgz", - "integrity": "sha512-Fe0SA2j8X0kmc3aveuHD7UktO3AE2+mH3LguP60vGbz7u0z+MrDXbeb5iZFYAwR7EzzzXJ2Yk966w9mGTFMqfA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.2.tgz", - "integrity": "sha512-TFBipb+gyesI/2Ve4zVu7kGltBWN/R466G5/1gtt2lECfc22G1pjkTxu68Q9aFcOaXiRGTQfvDbQQFe7mYgxiQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.2.tgz", - "integrity": "sha512-rVtmnNpBYIosDnKD/96dKxFsJnwnn1WRGG/HioSe8XCm2ksSHNrd2R6+hSjvTBxeMNhJ9pYeu/90cWB1nQLuNA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.2.tgz", - "integrity": "sha512-H4Y2o2/JcHu8LtwzD5CXfHhwxwz8gfsx2HXDEw46Mtev5xHnEmB7HNtZtmriw5ReUOjRtcDqo7XSbU01FT9NlA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@noble/ciphers": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", - "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", - "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.8.0" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/base": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", - "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", - "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.9.0", - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", - "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@swc/helpers": { - "version": "0.5.23", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", - "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@types/node": { - "version": "25.0.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz", - "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", - "dev": true, - "license": "MIT", - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@ubjs/core": { - "version": "0.31.0-5", - "resolved": "https://registry.npmjs.org/@ubjs/core/-/core-0.31.0-5.tgz", - "integrity": "sha512-oRBRtyYOhaodiOY3rLMZFgAHGFMmD44XefMpsAx4Ja0/rO+45kVdQB1VZsblQMLYxP965i3IHm56eymgo3I5eQ==", - "license": "MPL-2.0" - }, - "node_modules/@ubjs/wasm": { - "version": "0.31.0-5", - "resolved": "https://registry.npmjs.org/@ubjs/wasm/-/wasm-0.31.0-5.tgz", - "integrity": "sha512-dO7i67DQ1UKBSegznLVjVrYowmxY7gaXXluBdtJXPYgcR5vzwYf2ZbxAUqj4qL1JkqxRmeTKgXtuesFI+D5dPg==", - "license": "MPL-2.0", - "peerDependencies": { - "@ubjs/core": "^0.31.0-5" - } - }, - "node_modules/abitype": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.3.tgz", - "integrity": "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3.22.0 || ^4.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.11.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.19.tgz", - "integrity": "sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw==", - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001810", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", - "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", - "license": "MIT" - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/isows": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", - "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/lossless-json": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-4.3.1.tgz", - "integrity": "sha512-SqD/Bg3ZfltBJ2Z14hJ/BihnvtV553WO4g9/ePtlp4lrnl9jF3AdIJt53A/Wkg/0Li+LMfxaBqgx1MiFZdQlpQ==", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.18", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", - "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/next": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/next/-/next-16.3.2.tgz", - "integrity": "sha512-/ZCaubUy17Lld1SiPWxuPbCk2ihqAxF2QNQaPZeEaEb7t1I58qhsJN187D7AfpapHAqUPXH0f/thtdW9dWgWFg==", - "license": "MIT", - "dependencies": { - "@next/env": "16.3.2", - "@swc/helpers": "0.5.23", - "baseline-browser-mapping": "^2.9.19", - "caniuse-lite": "^1.0.30001579", - "postcss": "8.5.23", - "styled-jsx": "5.1.6" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=20.9.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "16.3.2", - "@next/swc-darwin-x64": "16.3.2", - "@next/swc-linux-arm64-gnu": "16.3.2", - "@next/swc-linux-arm64-musl": "16.3.2", - "@next/swc-linux-x64-gnu": "16.3.2", - "@next/swc-linux-x64-musl": "16.3.2", - "@next/swc-win32-arm64-msvc": "16.3.2", - "@next/swc-win32-x64-msvc": "16.3.2", - "sharp": "^0.35.3" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.51.1", - "babel-plugin-react-compiler": "*", - "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", - "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "@playwright/test": { - "optional": true - }, - "babel-plugin-react-compiler": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.5.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", - "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.16", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/ox": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.34.tgz", - "integrity": "sha512-12seOIk7dv8eAoGQhcWaeKZxNz304IVcDvb9U5Y7JZAEVe21Nm1YMxLjhWah+su5BD4Omx4Zz0z5x3ij9M4GYQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "dependencies": { - "@adraffy/ens-normalize": "^1.11.0", - "@noble/ciphers": "^1.3.0", - "@noble/curves": "1.9.1", - "@noble/hashes": "^1.8.0", - "@scure/bip32": "^1.7.0", - "@scure/bip39": "^1.6.0", - "abitype": "^1.2.3", - "eventemitter3": "5.0.1" - }, - "peerDependencies": { - "typescript": ">=5.4.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/react": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", - "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", - "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.8" - } - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sharp": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", - "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@img/colour": "^1.1.0", - "detect-libc": "^2.1.2", - "semver": "^7.8.5" - }, - "engines": { - "node": ">=20.9.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.35.3", - "@img/sharp-darwin-x64": "0.35.3", - "@img/sharp-freebsd-wasm32": "0.35.3", - "@img/sharp-libvips-darwin-arm64": "1.3.2", - "@img/sharp-libvips-darwin-x64": "1.3.2", - "@img/sharp-libvips-linux-arm": "1.3.2", - "@img/sharp-libvips-linux-arm64": "1.3.2", - "@img/sharp-libvips-linux-ppc64": "1.3.2", - "@img/sharp-libvips-linux-riscv64": "1.3.2", - "@img/sharp-libvips-linux-s390x": "1.3.2", - "@img/sharp-libvips-linux-x64": "1.3.2", - "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", - "@img/sharp-libvips-linuxmusl-x64": "1.3.2", - "@img/sharp-linux-arm": "0.35.3", - "@img/sharp-linux-arm64": "0.35.3", - "@img/sharp-linux-ppc64": "0.35.3", - "@img/sharp-linux-riscv64": "0.35.3", - "@img/sharp-linux-s390x": "0.35.3", - "@img/sharp-linux-x64": "0.35.3", - "@img/sharp-linuxmusl-arm64": "0.35.3", - "@img/sharp-linuxmusl-x64": "0.35.3", - "@img/sharp-webcontainers-wasm32": "0.35.3", - "@img/sharp-win32-arm64": "0.35.3", - "@img/sharp-win32-ia32": "0.35.3", - "@img/sharp-win32-x64": "0.35.3" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/styled-jsx": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", - "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", - "license": "MIT", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "devOptional": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "license": "MIT" - }, - "node_modules/viem": { - "version": "2.56.0", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.56.0.tgz", - "integrity": "sha512-JmkgIk4jN+im4oguLxwPv19pwSaGH9kcGSq25Ilm55106ULBBMNR3eWKKA0wZoeyLPSHIiOwZ4sGceEYEIq7LA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "dependencies": { - "@noble/curves": "1.9.1", - "@noble/hashes": "1.8.0", - "@scure/bip32": "1.7.0", - "@scure/bip39": "1.6.0", - "abitype": "1.2.3", - "isows": "1.0.7", - "ox": "0.14.34", - "ws": "8.21.0" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/walletkit-web": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/walletkit-web/-/walletkit-web-0.21.3.tgz", - "integrity": "sha512-i6TSdctv40RLVFNiHd8zWLO4VLYNpGDzoLa5s6EcO3cXuKgfoJccZ7KEYisaW9d8rpTL+9driOWNlLLQVUhqdg==", - "dependencies": { - "@ubjs/core": "0.31.0-5", - "@ubjs/wasm": "0.31.0-5" - } - }, - "node_modules/ws": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", - "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - } -} diff --git a/examples/uniffi-web-authenticator-poc/package.json b/examples/uniffi-web-authenticator-poc/package.json index cc4a6eba0..636a0af2d 100644 --- a/examples/uniffi-web-authenticator-poc/package.json +++ b/examples/uniffi-web-authenticator-poc/package.json @@ -3,6 +3,7 @@ "private": true, "version": "0.0.0", "type": "module", + "packageManager": "bun@1.3.11", "repository": { "type": "git", "url": "https://github.com/worldcoin/walletkit" @@ -11,8 +12,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "walletkit:local": "npm --prefix ../../web/walletkit run build && npm install --no-save ../../web/walletkit", - "walletkit:published": "npm ci" + "walletkit:local": "bun run --cwd ../../web/walletkit build && bun link --cwd ../../web/walletkit && bun link --no-save walletkit-web", + "walletkit:published": "bun install --frozen-lockfile --force" }, "dependencies": { "lossless-json": "^4.3.1", diff --git a/flake.nix b/flake.nix index 49b3ac9d0..d2f317bdc 100644 --- a/flake.nix +++ b/flake.nix @@ -35,6 +35,7 @@ default = pkgs.mkShell { packages = [ rustToolchain + pkgs.bun pkgs.curl pkgs.git pkgs.nargo diff --git a/nix/README.md b/nix/README.md index d8ac07a41..be1c65b30 100644 --- a/nix/README.md +++ b/nix/README.md @@ -28,7 +28,7 @@ Convenience wrappers (they enter the right shell for you): nix/build-android.sh --target aarch64-linux-android nix/build-wasm.sh nix develop .#wasm --command cargo test -p walletkit-sqlite --target wasm32-unknown-unknown -nix develop .#wasm --command npm --prefix web/walletkit run build +nix develop .#wasm --command bun run --cwd web/walletkit build nix develop .#android --command cargo xtask kotlin build # full Android jniLibs + bindings nix develop .#android --command cargo xtask kotlin local 0.3.1 # publish to Maven Local ``` diff --git a/nix/wasm.nix b/nix/wasm.nix index 9e5f69805..a26f5cacc 100644 --- a/nix/wasm.nix +++ b/nix/wasm.nix @@ -18,6 +18,7 @@ in pkgs.mkShell { packages = [ rustToolchain + pkgs.bun llvm.clang-unwrapped llvm.bintools-unwrapped wasmBindgenCli diff --git a/web/walletkit/README.md b/web/walletkit/README.md index 6ead1374e..6257d7902 100644 --- a/web/walletkit/README.md +++ b/web/walletkit/README.md @@ -17,8 +17,8 @@ const walletKit = await initializeWalletKit(); Build it from the repository root with the pinned toolchain: ```sh -nix develop .#wasm --command npm --prefix web/walletkit install -nix develop .#wasm --command npm --prefix web/walletkit run build +nix develop .#wasm --command bun install --cwd web/walletkit --frozen-lockfile +nix develop .#wasm --command bun run --cwd web/walletkit build ``` The release build uses `crates/walletkit` directly, disables its default diff --git a/web/walletkit/bun.lock b/web/walletkit/bun.lock new file mode 100644 index 000000000..3356e880e --- /dev/null +++ b/web/walletkit/bun.lock @@ -0,0 +1,84 @@ +{ + "lockfileVersion": 1, + "configVersion": 0, + "workspaces": { + "": { + "name": "walletkit-web", + "dependencies": { + "@ubjs/core": "0.31.0-5", + "@ubjs/wasm": "0.31.0-5", + }, + "devDependencies": { + "esbuild": "0.25.9", + "prettier": "3.6.2", + "typescript": "5.9.2", + "uniffi-bindgen-react-native": "0.31.0-5", + }, + }, + }, + "packages": { + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.9", "", { "os": "aix", "cpu": "ppc64" }, "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.9", "", { "os": "android", "cpu": "arm" }, "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.9", "", { "os": "android", "cpu": "arm64" }, "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.9", "", { "os": "android", "cpu": "x64" }, "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.9", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.9", "", { "os": "linux", "cpu": "arm" }, "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.9", "", { "os": "linux", "cpu": "ia32" }, "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.9", "", { "os": "linux", "cpu": "x64" }, "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.9", "", { "os": "none", "cpu": "x64" }, "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.9", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.9", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.9", "", { "os": "sunos", "cpu": "x64" }, "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.9", "", { "os": "win32", "cpu": "ia32" }, "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.9", "", { "os": "win32", "cpu": "x64" }, "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ=="], + + "@ubjs/core": ["@ubjs/core@0.31.0-5", "", {}, "sha512-oRBRtyYOhaodiOY3rLMZFgAHGFMmD44XefMpsAx4Ja0/rO+45kVdQB1VZsblQMLYxP965i3IHm56eymgo3I5eQ=="], + + "@ubjs/wasm": ["@ubjs/wasm@0.31.0-5", "", { "peerDependencies": { "@ubjs/core": "^0.31.0-5" } }, "sha512-dO7i67DQ1UKBSegznLVjVrYowmxY7gaXXluBdtJXPYgcR5vzwYf2ZbxAUqj4qL1JkqxRmeTKgXtuesFI+D5dPg=="], + + "esbuild": ["esbuild@0.25.9", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.9", "@esbuild/android-arm": "0.25.9", "@esbuild/android-arm64": "0.25.9", "@esbuild/android-x64": "0.25.9", "@esbuild/darwin-arm64": "0.25.9", "@esbuild/darwin-x64": "0.25.9", "@esbuild/freebsd-arm64": "0.25.9", "@esbuild/freebsd-x64": "0.25.9", "@esbuild/linux-arm": "0.25.9", "@esbuild/linux-arm64": "0.25.9", "@esbuild/linux-ia32": "0.25.9", "@esbuild/linux-loong64": "0.25.9", "@esbuild/linux-mips64el": "0.25.9", "@esbuild/linux-ppc64": "0.25.9", "@esbuild/linux-riscv64": "0.25.9", "@esbuild/linux-s390x": "0.25.9", "@esbuild/linux-x64": "0.25.9", "@esbuild/netbsd-arm64": "0.25.9", "@esbuild/netbsd-x64": "0.25.9", "@esbuild/openbsd-arm64": "0.25.9", "@esbuild/openbsd-x64": "0.25.9", "@esbuild/openharmony-arm64": "0.25.9", "@esbuild/sunos-x64": "0.25.9", "@esbuild/win32-arm64": "0.25.9", "@esbuild/win32-ia32": "0.25.9", "@esbuild/win32-x64": "0.25.9" }, "bin": "bin/esbuild" }, "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g=="], + + "prettier": ["prettier@3.6.2", "", { "bin": "bin/prettier.cjs" }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], + + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + + "uniffi-bindgen-react-native": ["uniffi-bindgen-react-native@0.31.0-5", "", { "bin": { "ubrn": "bin/cli.cjs", "uniffi-bindgen-react-native": "bin/cli.cjs" } }, "sha512-YtL3gTe+RVXAQx/2P2Iuypic/CunRZC65Cs47v//YRfwWNYU4Ufd1jT3rqxSrH5b5QFCYblP89Nf/9ssZRvNgg=="], + } +} diff --git a/web/walletkit/package-lock.json b/web/walletkit/package-lock.json deleted file mode 100644 index b6d81aeb5..000000000 --- a/web/walletkit/package-lock.json +++ /dev/null @@ -1,562 +0,0 @@ -{ - "name": "walletkit-web", - "version": "0.21.3", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "walletkit-web", - "version": "0.21.3", - "dependencies": { - "@ubjs/core": "0.31.0-5", - "@ubjs/wasm": "0.31.0-5" - }, - "devDependencies": { - "esbuild": "0.25.9", - "prettier": "3.6.2", - "typescript": "5.9.2", - "uniffi-bindgen-react-native": "0.31.0-5" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", - "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", - "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", - "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", - "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@ubjs/core": { - "version": "0.31.0-5", - "resolved": "https://registry.npmjs.org/@ubjs/core/-/core-0.31.0-5.tgz", - "integrity": "sha512-oRBRtyYOhaodiOY3rLMZFgAHGFMmD44XefMpsAx4Ja0/rO+45kVdQB1VZsblQMLYxP965i3IHm56eymgo3I5eQ==", - "license": "MPL-2.0" - }, - "node_modules/@ubjs/wasm": { - "version": "0.31.0-5", - "resolved": "https://registry.npmjs.org/@ubjs/wasm/-/wasm-0.31.0-5.tgz", - "integrity": "sha512-dO7i67DQ1UKBSegznLVjVrYowmxY7gaXXluBdtJXPYgcR5vzwYf2ZbxAUqj4qL1JkqxRmeTKgXtuesFI+D5dPg==", - "license": "MPL-2.0", - "peerDependencies": { - "@ubjs/core": "^0.31.0-5" - } - }, - "node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" - } - }, - "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uniffi-bindgen-react-native": { - "version": "0.31.0-5", - "resolved": "https://registry.npmjs.org/uniffi-bindgen-react-native/-/uniffi-bindgen-react-native-0.31.0-5.tgz", - "integrity": "sha512-YtL3gTe+RVXAQx/2P2Iuypic/CunRZC65Cs47v//YRfwWNYU4Ufd1jT3rqxSrH5b5QFCYblP89Nf/9ssZRvNgg==", - "dev": true, - "license": "MPL-2.0", - "bin": { - "ubrn": "bin/cli.cjs", - "uniffi-bindgen-react-native": "bin/cli.cjs" - } - } - } -} diff --git a/web/walletkit/package.json b/web/walletkit/package.json index dcdf894e0..d1422574f 100644 --- a/web/walletkit/package.json +++ b/web/walletkit/package.json @@ -3,6 +3,7 @@ "version": "0.21.3", "description": "Browser WebAssembly bindings for WalletKit.", "type": "module", + "packageManager": "bun@1.3.11", "files": [ "dist/", "README.md" @@ -16,9 +17,9 @@ "scripts": { "clean": "node scripts/clean.mjs", "patch:generator": "node scripts/patch-ubrn-wasm-bindgen.mjs", - "generate": "npm run patch:generator && ubrn build wasm2 --config ubrn.config.yaml --release && node scripts/optimize-wasm.mjs && node scripts/patch-generated-index.mjs", - "build": "npm run clean && npm run generate && tsc -p tsconfig.build.json && esbuild src/index.ts --bundle --format=esm --platform=browser --target=es2022 --outfile=dist/index.js --external:@ubjs/core --external:@ubjs/wasm && node scripts/copy-wasm.mjs", - "pack:check": "npm pack --dry-run" + "generate": "bun run patch:generator && ubrn build wasm2 --config ubrn.config.yaml --release && node scripts/optimize-wasm.mjs && node scripts/patch-generated-index.mjs", + "build": "bun run clean && bun run generate && tsc -p tsconfig.build.json && esbuild src/index.ts --bundle --format=esm --platform=browser --target=es2022 --outfile=dist/index.js --external:@ubjs/core --external:@ubjs/wasm && node scripts/copy-wasm.mjs", + "pack:check": "bun pm pack --dry-run" }, "dependencies": { "@ubjs/core": "0.31.0-5", From 7041f70b9f0a2110bbb7a90bafb64922c4b950b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Tr=C4=85d?= Date: Wed, 2 Sep 2026 12:36:17 +0200 Subject: [PATCH 16/17] Update web/walletkit/package.json Co-authored-by: Paolo D'Amico --- web/walletkit/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/walletkit/package.json b/web/walletkit/package.json index d1422574f..cd070cb64 100644 --- a/web/walletkit/package.json +++ b/web/walletkit/package.json @@ -1,7 +1,7 @@ { "name": "walletkit-web", "version": "0.21.3", - "description": "Browser WebAssembly bindings for WalletKit.", + "description": "WalletKit enables users to hold credentials and prove their humanity with World ID .", "type": "module", "packageManager": "bun@1.3.11", "files": [ From 5cc405a6f3fd0c9aa5e0face8144223335f3d555 Mon Sep 17 00:00:00 2001 From: dzejkop Date: Wed, 9 Sep 2026 15:50:57 +0200 Subject: [PATCH 17/17] Align POC CI with the pinned UniFFI generator version --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23d606062..892ee969a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,9 @@ jobs: - uses: worldcoin/bedrock/.github/actions/version-alignment@857c252013ac52cea24f5d7add3475a909d663f2 # main with: - uniffi_version: ${{ vars.UNIFFI_VERSION }} + # Match the temporary generator compatibility pin in Cargo.toml. + # Restore vars.UNIFFI_VERSION when the web generator supports 0.32. + uniffi_version: "0.31.2" rust_toolchain_channel: ${{ vars.RUST_TOOLCHAIN_CHANNEL }} lint: