@thru/embedded-provider
v0.2.15
Published
Client-side provider for embedding the Thru wallet into any web application. Manages an iframe that hosts the wallet UI, communicates with it over `postMessage`, and exposes a simple API for connecting, signing transactions, and managing accounts.
Readme
@thru/embedded-provider
Client-side provider for embedding the Thru wallet into any web application. Manages an iframe that hosts the wallet UI, communicates with it over postMessage, and exposes a simple API for connecting, signing transactions, and managing accounts.
Installation
npm install @thru/embedded-providerBasic Usage
import { EmbeddedProvider } from "@thru/embedded-provider";
const provider = new EmbeddedProvider({
iframeUrl: "https://wallet.thru.org",
});
// Initialize iframe (must be called before any other operation)
await provider.initialize();
// Connect to wallet (opens modal)
const result = await provider.connect();
console.log(result.accounts);
// Inspect the signing contract before building a transaction
const signingContext = await provider.thru.getSigningContext();
// Build your Thru transaction using signingContext.feePayerPublicKey, then sign it
const signed = await provider.thru.signTransaction(base64EncodedTx);
// Disconnect
await provider.disconnect();
// Cleanup when done
provider.destroy();API
EmbeddedProvider
Main entry point. Creates and manages the wallet iframe.
Constructor
new EmbeddedProvider(config: EmbeddedProviderConfig)| Option | Type | Default | Description |
| -------------- | --------------- | -------------------- | ------------------------------------ |
| iframeUrl | string | DEFAULT_IFRAME_URL | URL of the hosted wallet application |
| addressTypes | AddressType[] | [AddressType.THRU] | Chain types to enable |
Methods
| Method | Returns | Description |
| -------------------------- | ------------------------ | ------------------------------------------------------------------ |
| initialize() | Promise<void> | Create the iframe and wait for it to signal readiness |
| connect(options?) | Promise<ConnectResult> | Open the wallet modal and request a connection |
| disconnect() | Promise<void> | Disconnect the current session |
| isConnected() | boolean | Whether a wallet session is active |
| getAccounts() | WalletAccount[] | List of connected accounts |
| getSelectedAccount() | WalletAccount \| null | Currently selected account |
| selectAccount(publicKey) | Promise<WalletAccount> | Switch the active account |
| mountInline(container) | Promise<void> | Mount the wallet inline inside a DOM element instead of as a modal |
| on(event, callback) | void | Subscribe to provider events |
| off(event, callback) | void | Unsubscribe from provider events |
| destroy() | void | Remove the iframe and clean up all listeners |
Properties
| Property | Type | Description |
| -------- | ------------ | --------------------------------------------------------------------- |
| thru | IThruChain | Chain-specific interface for signing transactions on the Thru network |
EmbeddedThruChain
Implements IThruChain. Accessed via provider.thru.
| Method | Returns | Description |
| ---------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| connect() | Promise<{ publicKey: string }> | Connect and return the Thru address |
| disconnect() | Promise<void> | Disconnect |
| getSigningContext() | Promise<ThruSigningContext> | Return the current selected account plus the actual fee payer/signer contract used by the embedded wallet |
| signTransaction(serializedTransaction) | Promise<string> | Accept a base64 signing payload or raw transaction and return canonical raw transaction bytes ready for submission |
Events
Subscribe with provider.on(event, callback):
connect-- Wallet connected successfullyconnect:start-- Connection flow initiatedconnect:error-- Connection attempt faileddisconnect-- Wallet disconnectedlock-- Wallet locked by the useraccount:changed-- Active account switchedui:show-- Wallet UI requested to be shown
Display Modes
The provider supports two display modes:
- Modal (default) -- The iframe is appended to
document.bodyas a full-screen overlay. - Inline -- The iframe is mounted inside a container element you provide, useful for embedding a connect button directly in your page layout.
// Inline mode
const container = document.getElementById("wallet-mount");
await provider.mountInline(container);Security
The IframeManager validates that the iframe URL belongs to a set of trusted origins before loading it. Allowed origins:
https://wallet.thru.orghttp://localhost(any port, for development)
Messages are sent with a strict targetOrigin and each iframe instance is tagged with a unique frame ID to prevent cross-talk.
Key Capabilities
- Iframe lifecycle management with automatic readiness detection
- Request/response correlation over
postMessagewith per-request timeouts - Origin validation to prevent unauthorized wallet iframes
- Modal and inline display modes
- Event-driven architecture for connection state changes
- WebAuthn (passkey) support via iframe
allowpolicy - Chain-specific interfaces via the
IThruChainabstraction
Thru Signing Contract
For the embedded passkey wallet, the selected wallet account shown in the UI can
differ from the network fee payer / signer that actually authorizes the Thru
transaction. Call provider.thru.getSigningContext() before building a
transaction to retrieve:
selectedAccountPublicKey- the managed account currently selected in the walletfeePayerPublicKey- the address that must be used as the transaction fee payersignerPublicKey- the cryptographic signer used by the wallet
signTransaction() always returns canonical Transaction.toWire() bytes
encoded as base64, so apps can decode and submit the result directly without
reordering signature bytes.
Dependencies
@thru/chain-interfaces-- Shared chain interface types (IThruChain,WalletAccount)@thru/protocol-- Message type constants, request/response schemas, and helper utilities
