{"id":51559292,"url":"https://github.com/mtgo-labs/wasm","last_synced_at":"2026-07-10T09:01:21.499Z","repository":{"id":369537667,"uuid":"1290329129","full_name":"mtgo-labs/wasm","owner":"mtgo-labs","description":"Telegram MTProto client for the browser via WebAssembly — powered by mtgo","archived":false,"fork":false,"pushed_at":"2026-07-06T06:34:56.000Z","size":83,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-06T08:11:15.319Z","etag":null,"topics":["browser","mtgo","mtproto","npm-package","sveltekit","telegram","typescript","wasm","webassembly"],"latest_commit_sha":null,"homepage":"https://mtgo-labs.github.io/website/wasm/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mtgo-labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-05T20:50:49.000Z","updated_at":"2026-07-06T06:35:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mtgo-labs/wasm","commit_stats":null,"previous_names":["mtgo-labs/mtgo-wasm","mtgo-labs/wasm"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/mtgo-labs/wasm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtgo-labs%2Fwasm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtgo-labs%2Fwasm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtgo-labs%2Fwasm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtgo-labs%2Fwasm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtgo-labs","download_url":"https://codeload.github.com/mtgo-labs/wasm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtgo-labs%2Fwasm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35326963,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-10T02:00:06.465Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","mtgo","mtproto","npm-package","sveltekit","telegram","typescript","wasm","webassembly"],"created_at":"2026-07-10T09:01:19.112Z","updated_at":"2026-07-10T09:01:21.470Z","avatar_url":"https://github.com/mtgo-labs.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# @mtgo-labs/wasm\n\n[![Go](https://img.shields.io/badge/Go-1.26+-00ADD8?logo=go)](https://go.dev/)\n[![mtgo](https://img.shields.io/badge/mtgo-v0.12.0+-5684AD)](https://github.com/mtgo-labs/mtgo)\n[![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)\n[![npm](https://img.shields.io/npm/v/@mtgo-labs/wasm)](https://www.npmjs.com/package/@mtgo-labs/wasm)\n\n\u003cp\u003e\u003cstrong\u003e@mtgo-labs/wasm\u003c/strong\u003e brings the \u003ca href=\"https://github.com/mtgo-labs/mtgo\"\u003emtgo\u003c/a\u003e Telegram MTProto client to the browser via WebAssembly. It exposes a small JavaScript API for creating a client, connecting over WebSocket, and invoking arbitrary Telegram TL methods — all running client-side in the browser.\u003c/p\u003e\n\n\u003c/div\u003e\n\n```mermaid\nflowchart LR\n    JS[Your JS code] --\u003e|invoke method| W[\"@mtgo-labs/wasm .wasm\"]\n    W --\u003e|syscall/js| WS[Browser WebSocket]\n    WS --\u003e|wss://| TG[Telegram DC]\n    TG --\u003e WS --\u003e W --\u003e JS\n```\n\n## Install\n\n```bash\nnpm install @mtgo-labs/wasm\n# or\nbun add @mtgo-labs/wasm\n# or\npnpm add @mtgo-labs/wasm\n```\n\n## Quick start (Vite / SvelteKit / Next.js)\n\n```js\nimport { load } from \"@mtgo-labs/wasm\";\nimport wasmUrl from \"@mtgo-labs/wasm/mtgo-wasm.wasm?url\";\nimport wasmExecUrl from \"@mtgo-labs/wasm/wasm_exec.js?url\";\n\nconst mtgo = await load({ wasmUrl, wasmExecUrl });\n\nconst client = mtgo.createClient({\n  apiID: 12345,\n  apiHash: \"your_api_hash\",\n  botToken: \"123:ABCdefGHI\", // or sessionString for a user session\n});\n\nawait client.connect();\nconsole.log(\"Logged in as\", client.me());\n\n// Invoke any TL method by name (snake_case params):\nconst result = await client.invoke(\"users.getUsers\", {\n  id: [{ _: \"inputUserSelf\" }],\n});\nconsole.log(result);\n\nawait client.disconnect();\n```\n\n\u003e **SSR safety**: call `load()` inside `onMount` / `useEffect` only — WASM has\n\u003e no server context.\n\n## Plain HTML (no bundler)\n\nIf you're not using a bundler, use the `browser` subpath export. You can pull\neverything from a CDN — no install needed:\n\n```html\n\u003cscript src=\"https://unpkg.com/@mtgo-labs/wasm/wasm_exec.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"module\"\u003e\n  import { load } from \"https://unpkg.com/@mtgo-labs/wasm/browser\";\n\n  const mtgo = await load(\"https://unpkg.com/@mtgo-labs/wasm/mtgo-wasm.wasm\");\n\n  const client = mtgo.createClient({\n    apiID: 12345,\n    apiHash: \"your_api_hash\",\n    botToken: \"123:ABCdefGHI\",\n  });\n  await client.connect();\n  console.log(client.me());\n\u003c/script\u003e\n```\n\nOr from `node_modules` after `npm install`:\n\n```html\n\u003cscript src=\"node_modules/@mtgo-labs/wasm/wasm_exec.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"module\"\u003e\n  import { load } from \"node_modules/@mtgo-labs/wasm/browser\";\n\n  const mtgo = await load(\"node_modules/@mtgo-labs/wasm/mtgo-wasm.wasm\");\n  const client = mtgo.createClient({ apiID: 12345, apiHash: \"...\", botToken: \"...\" });\n  await client.connect();\n\u003c/script\u003e\n```\n\n## SvelteKit integration\n\n### 1. Install\n\n```bash\nnpm install @mtgo-labs/wasm\n```\n\n### 2. Use in a component\n\n```svelte\n\u003c!-- src/routes/+page.svelte --\u003e\n\u003cscript\u003e\n  import { onMount } from \"svelte\";\n  import { load } from \"@mtgo-labs/wasm\";\n  import wasmUrl from \"@mtgo-labs/wasm/mtgo-wasm.wasm?url\";\n  import wasmExecUrl from \"@mtgo-labs/wasm/wasm_exec.js?url\";\n\n  let client = null;\n\n  onMount(async () =\u003e {\n    // onMount only runs in the browser — SSR-safe.\n    const mtgo = await load({ wasmUrl, wasmExecUrl });\n\n    client = mtgo.createClient({\n      apiID: 12345,\n      apiHash: \"your_hash\",\n      botToken: \"123:ABC\",\n    });\n    await client.connect();\n    const me = await client.invoke(\"users.getUsers\", { id: [{ _: \"inputUserSelf\" }] });\n    console.log(me);\n  });\n\u003c/script\u003e\n```\n\n### Alternative: load `wasm_exec.js` via `app.html`\n\nInstead of the `wasmExecUrl` import, you can load Go's bootstrap script\nglobally in `app.html`:\n\n```html\n\u003c!-- src/app.html — inside \u003chead\u003e --\u003e\n\u003cscript src=\"%sveltekit.assets%/wasm_exec.js\"\u003e\u003c/script\u003e\n```\n\nThen copy `wasm_exec.js` into `static/` and omit `wasmExecUrl`:\n\n```bash\ncp node_modules/@mtgo-labs/wasm/wasm_exec.js static/\n```\n\n```js\nconst mtgo = await load({ wasmUrl }); // wasmExecUrl not needed — Go is already global\n```\n\n### Key points\n\n- **SSR safety**: `onMount` / `useEffect` only. Never call `load()` during SSR.\n- **`Go` global**: `wasm_exec.js` sets `globalThis.Go`. Load it once, not per-component.\n- **`?url` suffix**: Vite resolves `@mtgo-labs/wasm/mtgo-wasm.wasm?url` to a served URL automatically — no need to copy files to `static/`.\n\n## API\n\n### `MTGoWasm.createClient(opts) → client`\n\n| Option           | Type       | Required | Description                                      |\n|------------------|------------|----------|--------------------------------------------------|\n| `apiID`          | `number`   | yes\\*    | Telegram API ID from my.telegram.org             |\n| `apiHash`        | `string`   | yes\\*    | Telegram API hash                                |\n| `botToken`       | `string`   | no       | Bot token — triggers bot auth on connect         |\n| `sessionString`  | `string`   | no       | Pre-authenticated session (Telethon/Pyrogram/etc)|\n| `phoneNumber`    | `string`   | no       | Phone number for interactive user login          |\n| `codeFunc`       | `function` | no       | `async (phone) =\u003e code` — OTP provider           |\n| `passwordFunc`   | `function` | no       | `async (hint) =\u003e password` — 2FA password        |\n\n\\* `apiID`/`apiHash` optional only when `sessionString` carries them.\n\n### `client.connect() → Promise\u003cvoid\u003e`\n\nEstablishes the WebSocket transport, performs the DH key exchange, and\nauthenticates (bot login or session restore). Returns a Promise.\n\n### `client.invoke(method, params) → Promise\u003cobject\u003e`\n\nInvokes a Telegram TL method by name. `method` is the TL function name\n(e.g. `\"messages.sendMessage\"`). `params` is a plain JS object using\nsnake_case keys matching the TL schema. Returns the parsed response.\n\n### `client.me() → object | null`\n\nReturns the authenticated user (`{ id, username, first_name, last_name, is_bot }`),\nor `null` if not connected.\n\n### `client.disconnect() → Promise\u003cvoid\u003e`\n\nCloses the transport and releases the session.\n\n## TL namespace proxy\n\nThe client itself acts as a proxy — any property that isn't a known method\n(`connect`, `invoke`, `me`, `disconnect`) is treated as a TL namespace,\ngiving you `namespace.method(params)` access to **all** Telegram TL methods:\n\n```js\nconst tg = MTGoWasm.createClient({ apiID: 12345, apiHash: \"...\", botToken: \"...\" });\nawait tg.connect();\n\n// Set your username\nawait tg.account.updateUsername({ username: \"new_name\" });\n\n// Update profile\nawait tg.account.updateProfile({\n  first_name: \"John\",\n  last_name: \"Doe\",\n  about: \"Hello from WASM!\",\n});\n\n// Send a message\nawait tg.messages.sendMessage({\n  peer: { _: \"inputPeerSelf\" },\n  message: \"Hello from the browser!\",\n  random_id: Date.now(),\n});\n\n// Get your own user info\nconst result = await tg.users.getUsers({\n  id: [{ _: \"inputUserSelf\" }],\n});\n```\n\nParams use snake_case keys matching the TL schema (same as `invoke`). Each call\nreturns a Promise resolving to the TL response.\n\n## Package exports\n\n| Subpath                            | Description                              |\n|------------------------------------|------------------------------------------|\n| `@mtgo-labs/wasm`                  | Vite/bundler loader (default)            |\n| `@mtgo-labs/wasm/browser`          | Plain-browser loader (no bundler)        |\n| `@mtgo-labs/wasm/wasm_exec.js`     | Go's WASM bootstrap (`globalThis.Go`)    |\n| `@mtgo-labs/wasm/mtgo-wasm.wasm`   | The compiled `.wasm` binary              |\n\n## How it works\n\nmtgo is a pure-Go MTProto client. This package adds two things:\n\n1. **A browser WebSocket transport** — `wasm/wsconn.go` wraps the browser's\n   native `WebSocket` API as a Go `net.Conn`. mtgo's obfuscated2 framing layer\n   sits on top, exactly as it does for server-side WebSocket connections.\n\n2. **A JS bridge** — `wasm/bridge.go` uses `syscall/js` to expose\n   `createClient`/`connect`/`invoke`/`disconnect` to JavaScript. RPC calls go\n   through mtgo's `InvokeJSON`, so **every TL method** is available without\n   per-method glue code.\n\nThe mtgo side needs one hook: `Config.WSDialer` (landed in the mtgo release\nafter v0.12.0) lets this package inject the browser WebSocket as the transport\nwithout reaching into mtgo internals.\n\n## Transport notes\n\n- Traffic flows over **`wss://`** (TLS) to Telegram's WebSocket endpoints\n  (`pluto.web.telegram.org/apiws`, etc.). WebSocket connections are not bound\n  by fetch CORS rules, so browsers can reach Telegram directly — GramJS and\n  Telegram Web do the same.\n- All storage is **in-memory** (`InMemory: true`). No filesystem is used.\n\n## Building from source\n\nIf you need to rebuild the `.wasm` binary (e.g. after modifying the Go code):\n\n```bash\ngit clone https://github.com/mtgo-labs/wasm.git\ncd wasm\nmake build       # produces mtgo-wasm.wasm\nmake copy-exec   # copies Go's wasm_exec.js into lib/\nmake serve       # starts a demo server at http://localhost:8080/\n```\n\nRequires Go 1.22+ (for `math/rand/v2`) and the mtgo version that ships\n`Config.WSDialer` + `telegram.NewWSDialer`.\n\n## License\n\nMIT, same as mtgo.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtgo-labs%2Fwasm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtgo-labs%2Fwasm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtgo-labs%2Fwasm/lists"}