diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0709bafd8..e17aca66c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
---
+## [0.1.36] - 2026-07-14
+
+### 🚀 Features
+
+- NormalizeTokenAddress, dualChainConnect, useQuery migration - by @akbarsaputrait [(8dfbf)](https://github.com/RozoAI/intent-pay/commit/8dfbf278)
+- **mobile**: Unified wallet chooser, eager hydration, deposit address loading state - by @akbarsaputrait [(d9117)](https://github.com/RozoAI/intent-pay/commit/d91171c3)
+- **sdk**: Emit payment_no_tokens_available on empty SelectToken - by @akbarsaputrait [(dd983)](https://github.com/RozoAI/intent-pay/commit/dd9838b2)
+
+### 🐞 Bug Fixes
+
+- **connectkit**:
+ - Remove memo requirement from Solana payment flows - by @akbarsaputrait [(c98b4)](https://github.com/RozoAI/intent-pay/commit/c98b46fe)
+ - Update memo requirement for Stellar payments - by @akbarsaputrait [(86934)](https://github.com/RozoAI/intent-pay/commit/869342e2)
+- **dualChainConnect**:
+ - Skip injector page on mobile dual-chain tap - by @akbarsaputrait [(66fbd)](https://github.com/RozoAI/intent-pay/commit/66fbd342)
+- **ios**:
+ - Open deeplink via tag click, skip WAITING_WALLET intermediate page - by @akbarsaputrait [(0bee7)](https://github.com/RozoAI/intent-pay/commit/0bee72f3)
+- **mobile**:
+ - Dedup injected wallets, img dimensions, deposit address order - by @akbarsaputrait [(8aa6c)](https://github.com/RozoAI/intent-pay/commit/8aa6c0ec)
+- **sdk**:
+ - Guard isDNTEnabled against SSR (window undefined) - by @akbarsaputrait [(d9b65)](https://github.com/RozoAI/intent-pay/commit/d9b6566f)
+ - Allow payment options fetch for every appId, incl. default - by @akbarsaputrait [(732a5)](https://github.com/RozoAI/intent-pay/commit/732a5ac4)
+
+---
+
+
## [0.1.34] - 2026-07-07
### 🚀 Features
diff --git a/docs/ANALYTICS.md b/docs/ANALYTICS.md
index ff9e3e198..b25c5a0b2 100644
--- a/docs/ANALYTICS.md
+++ b/docs/ANALYTICS.md
@@ -27,6 +27,7 @@ The SDK sends anonymous payment funnel events to RozoAI's PostHog project. This
| `payment_completed` | On-chain confirmed | `destination_chain`, `app_name` |
| `payment_failed` | Terminal failure | `error_type`, `destination_chain`, `app_name` |
| `payment_cancelled` | Modal closed mid-flow | `last_state`, `reason`, `app_name` |
+| `payment_no_tokens_available` | SelectToken empty state renders (wallet connected, no eligible balances) | `token_mode`, `connected_chains`, `preferred_token_symbols`, `preferred_token_count`, `app_name` |
| `error_occurred` | Error page shown | `error_type`, `error_title`, `can_retry`, `app_name` |
| `payment_validation_error` | Invalid chain/token config | `error_type`, `app_name` |
diff --git a/docs/PROVIDER_SETUP.md b/docs/PROVIDER_SETUP.md
index 74944d258..c2a6a1df4 100644
--- a/docs/PROVIDER_SETUP.md
+++ b/docs/PROVIDER_SETUP.md
@@ -241,6 +241,27 @@ export function Providers({ children }) {
---
+### ⚠️ SSR `ReferenceError: window is not defined` from telemetry (fixed in 0.1.36+)
+
+Before 0.1.36, the SDK's `isDNTEnabled()` telemetry guard touched
+`window.doNotTrack` unconditionally. Under Next.js SSR, `window` is undefined,
+so rendering `` on the server threw and returned HTTP 500 for
+the entire page.
+
+**Workaround (older SDK versions):** pass `telemetry={false}` to disable the
+built-in telemetry path.
+
+```tsx
+
+```
+
+**On 0.1.36+:** the guard is SSR-safe (`typeof window === "undefined"` short-
+circuits before any `window.*` access). Host apps can drop the
+`telemetry={false}` workaround unless they want to opt out of telemetry for
+privacy reasons — see [ANALYTICS.md](./ANALYTICS.md#opting-out).
+
+---
+
### ❌ Using SDK hooks outside the provider
```tsx
diff --git a/docs/e2e/06-wallet-stellar.md b/docs/e2e/06-wallet-stellar.md
index d6171c235..21fe53e67 100644
--- a/docs/e2e/06-wallet-stellar.md
+++ b/docs/e2e/06-wallet-stellar.md
@@ -2,8 +2,10 @@
Stellar uses a different approach: the SDK accepts an injectable `stellarKit` prop,
so instead of automating a browser extension, a secret-key signer runs inside the
-page. Playwright injects the secret at runtime — it never touches the app bundle or
-any env var the app reads — so this signer cannot activate in production.
+page. Playwright injects the secret at runtime and the app only wires the kit
+when it was built with `NEXT_PUBLIC_E2E=1` — so the headless-signer code path
+dead-code-eliminates out of production bundles at build time, and even in an
+E2E build the kit does nothing unless Playwright has already injected a secret.
---
@@ -73,8 +75,21 @@ export function createHeadlessStellarKit(secret: string): StellarWalletsKit {
## 3. Wire the kit into your provider
In the component that renders ``, read the runtime-injected
-window variable and pass the kit as the `stellarKit` prop. Use a `useState`
-initializer so the kit is only constructed once per page load.
+window variable and pass the kit as the `stellarKit` prop. Two safety gates:
+
+1. `NEXT_PUBLIC_E2E` env flag — the Playwright `webServer` config sets this to
+ `1` when starting the dev server. In production builds it's `undefined`,
+ so Next.js's bundler tree-shakes the `require("@/lib/e2e-stellar-kit")`
+ call and the entire `@creit.tech/stellar-wallets-kit` module graph never
+ enters the client chunk.
+2. `window.__E2E_STELLAR_SECRET__` — the actual secret. Even in an E2E build,
+ the kit is only constructed when Playwright injected the secret via
+ `addInitScript`. The provider deletes the property from `window`
+ immediately after reading it, so later scripts on the same page (analytics,
+ third-party widgets) can't scrape it.
+
+Use a `useState` initializer so the kit is only constructed once per page
+load — the kit registers a custom element and throws on a second construction.
```tsx
import { createHeadlessStellarKit } from "@/lib/e2e-stellar-kit"
@@ -83,10 +98,21 @@ import type { StellarWalletsKit } from "@creit.tech/stellar-wallets-kit"
// Inside your provider component:
const [stellarKit] = useState(() => {
if (typeof window === "undefined") return undefined
- const secret = (window as Window & { __E2E_STELLAR_SECRET__?: string })
- .__E2E_STELLAR_SECRET__
+ // Env-flag gate — lets the bundler drop the entire import graph in prod.
+ if (!process.env.NEXT_PUBLIC_E2E) return undefined
+
+ const w = window as Window & { __E2E_STELLAR_SECRET__?: string }
+ const secret = w.__E2E_STELLAR_SECRET__
+ // Delete immediately so the key isn't readable later in the session.
+ delete w.__E2E_STELLAR_SECRET__
if (!secret) return undefined
+
try {
+ // require() inside the guarded branch: only resolved at build time when
+ // NEXT_PUBLIC_E2E=1, so the stellarWalletsKit bundle never enters the
+ // production chunk graph.
+ const { createHeadlessStellarKit } =
+ require("@/lib/e2e-stellar-kit") as typeof import("@/lib/e2e-stellar-kit")
return createHeadlessStellarKit(secret)
} catch (err) {
console.error("[E2E] Failed to create headless Stellar kit:", err)
@@ -101,9 +127,9 @@ return (
)
```
-Because the kit only builds when `__E2E_STELLAR_SECRET__` is on `window` — and
-Playwright is the only thing that sets it — the headless signer is impossible to
-activate in a real user session.
+Both gates must hold to activate the signer: the build must have been started
+with `NEXT_PUBLIC_E2E=1` **and** Playwright must inject the secret before the
+page loads. Neither is reachable from a real user session.
---
@@ -145,5 +171,9 @@ test.describe("Bridge: Stellar → EVM (mainnet, real funds)", () => {
## Notes
- `useStellarSigner` uses `page.addInitScript` — it must be called before navigation.
+- Playwright starts the dev server with `NEXT_PUBLIC_E2E=1` (see
+ `examples/nextjs-app/e2e/playwright.config.ts` → `webServer.command:
+ "NEXT_PUBLIC_E2E=1 pnpm dev"`). Production `pnpm build` runs without the
+ flag, so the headless-kit import is dead-code-eliminated and never ships.
- No browser extension needed; Stellar flows can run headless.
- Source wallet needs XLM for fees and USDC to send. Destination wallet needs a USDC trustline.
diff --git a/examples/nextjs-app/.env.e2e.example b/examples/nextjs-app/.env.e2e.example
index 38c91fc28..a25a21d41 100644
--- a/examples/nextjs-app/.env.e2e.example
+++ b/examples/nextjs-app/.env.e2e.example
@@ -36,7 +36,10 @@ E2E_EVM_ADDRESS=""
# - ADDRESS (G...) receives when Stellar is the DESTINATION → needs a trustline.
#
# The test injects the SECRET into the app at runtime, so you do NOT need to set
-# any NEXT_PUBLIC_ secret by hand. Must be funded and have a USDC trustline.
+# any NEXT_PUBLIC_ secret by hand. The Playwright webServer starts the dev
+# server with NEXT_PUBLIC_E2E=1, which is what wires the headless Stellar kit;
+# production `pnpm build` runs without the flag, so the signer never ships.
+# Must be funded and have a USDC trustline.
E2E_STELLAR_SECRET=""
E2E_STELLAR_ADDRESS=""
diff --git a/examples/nextjs-app/.gitignore b/examples/nextjs-app/.gitignore
index 870efeb4a..401ee6fc3 100644
--- a/examples/nextjs-app/.gitignore
+++ b/examples/nextjs-app/.gitignore
@@ -51,4 +51,4 @@ playwright-report/
# chainwright wallet cache
.wallet-cache/
-
+.wallet-context/
diff --git a/examples/nextjs-app/package.json b/examples/nextjs-app/package.json
index d1e2eb806..d2689048e 100644
--- a/examples/nextjs-app/package.json
+++ b/examples/nextjs-app/package.json
@@ -40,8 +40,8 @@
},
"dependencies": {
"@creit.tech/stellar-wallets-kit": "^1.9.5",
- "@rozoai/intent-common": "0.1.21",
- "@rozoai/intent-pay": "0.1.34",
+ "@rozoai/intent-common": "0.1.23",
+ "@rozoai/intent-pay": "0.1.36",
"@stellar/stellar-sdk": "^14.6.1",
"@tanstack/react-query": "^5.0.0",
"class-variance-authority": "^0.7.1",
diff --git a/package.json b/package.json
index a16550d7f..2cf040bf7 100644
--- a/package.json
+++ b/package.json
@@ -15,14 +15,15 @@
"test:e2e": "pnpm --filter \"examples/nextjs-app\" test:e2e",
"lint": "pnpm --filter @rozoai/intent-common run lint && pnpm --filter @rozoai/intent-pay run lint && pnpm --filter examples/nextjs-app run lint",
"format": "pnpm --filter @rozoai/intent-common run format && pnpm --filter @rozoai/intent-pay run format && pnpm --filter examples/nextjs-app run format",
- "build": "pnpm run build:common && pnpm run build:pay",
+ "build": "pnpm run build:common && pnpm run build:pay && pnpm run build:example",
"build:common": "cd packages/pay-common && pnpm run build",
"build:pay": "cd packages/connectkit && pnpm run build",
+ "build:example": "cd examples/nextjs-app && pnpm run build",
"dev": "pnpm run dev:common & pnpm run dev:pay & pnpm run dev:example:16",
"dev:common": "cd packages/pay-common && pnpm run dev",
"dev:pay": "cd packages/connectkit && pnpm run dev",
"dev:example": "cd examples/nextjs-app && pnpm run dev",
- "dev:example:16": "cd examples/nextjs-16 && pnpm run dev",
+ "start:example": "cd examples/nextjs-app && pnpm run start",
"install:local": "pnpm install",
"prepare": "husky",
"release": "pnpm run build && cd packages/pay-common && pnpm publish && cd ../../packages/connectkit && pnpm run release",
diff --git a/packages/connectkit/bundle-analysis.html b/packages/connectkit/bundle-analysis.html
index fa202deb3..23cc872b0 100644
--- a/packages/connectkit/bundle-analysis.html
+++ b/packages/connectkit/bundle-analysis.html
@@ -4929,7 +4929,7 @@