Vanilla JS Use PartyLayer without React by working directly with the PartyLayerClient. This is the foundation the React hooks are built on.
Creating a Client import { createPartyLayer } from '@partylayer/sdk';
const client = createPartyLayer({
network: 'mainnet',
app: {
name: 'My dApp',
origin: window.location.origin,
},
});Configuration Options Prop Type Default Description network "devnet" | "testnet" | "mainnet" — Canton network to connect to. app.name string — Your application name, shown during wallet connection. app.origin string window.location.origin Origin URL for session binding. registryUrl string "https://registry.partylayer.xyz" Wallet registry URL. channel "stable" | "beta" "stable" Registry channel. storage StorageAdapter localStorage Custom storage adapter for session persistence. crypto CryptoAdapter — Custom crypto adapter. registryPublicKeys string[] — Public keys for registry signature verification. adapters (WalletAdapter | AdapterClass)[] Built-in adapters Custom adapter list. telemetry TelemetryConfig | TelemetryAdapter — Telemetry configuration (opt-in). logger LoggerAdapter — Custom logger adapter.
Wallet Management listWallets List all available wallets from the registry and registered adapters. Resilient — falls back to adapter-only list if the registry is unreachable.
const wallets = await client.listWallets();
for (const wallet of wallets) {
console.log(wallet.name, wallet.walletId);
console.log(' Capabilities:', wallet.capabilities);
console.log(' Networks:', wallet.networks);
}
// With filter
const signingWallets = await client.listWallets({
requiredCapabilities: ['signTransaction'],
includeExperimental: false,
});registerAdapter Register a custom wallet adapter at runtime.
import { BronAdapter } from '@partylayer/adapter-bron';
client.registerAdapter(new BronAdapter({ clientId: 'your-client-id' }));Session Management connect Connect to a wallet. Returns a Session on success.
// Connect to a specific wallet
const session = await client.connect({ walletId: 'console' });
console.log('Connected:', session.partyId);
console.log('Session ID:', session.sessionId);
// Let the user choose (when using with a UI)
const session = await client.connect();disconnect Disconnect the active session.
await client.disconnect();getActiveSession Get the current active session, if any.
const session = await client.getActiveSession();
if (session) {
console.log('Active session:', session.walletId, session.partyId);
} else {
console.log('No active session');
}Signing Operations signMessage const signed = await client.signMessage({
message: 'Hello Canton!',
nonce: crypto.randomUUID(),
domain: 'my-dapp.example.com',
});
console.log('Signature:', signed.signature);
console.log('Signed by:', signed.partyId);signTransaction const signed = await client.signTransaction({
tx: {
templateId: 'MyModule:MyTemplate',
choiceId: 'MyChoice',
argument: { amount: '100', recipient: 'party::...' },
},
});
console.log('TX Hash:', signed.transactionHash);
console.log('Signed TX:', signed.signedTx);submitTransaction const receipt = await client.submitTransaction({
signedTx: signedPayload, // Pass the signed transaction from signTransaction()
});
console.log('TX Hash:', receipt.transactionHash);
console.log('Command ID:', receipt.commandId);
console.log('Submitted at:', new Date(receipt.submittedAt));Events Subscribe to SDK events with on. The method returns an unsubscribe function.
// Session events
const unsub1 = client.on('session:connected', (event) => {
console.log('Connected:', event.session.partyId);
});
const unsub2 = client.on('session:disconnected', (event) => {
console.log('Disconnected:', event.sessionId);
});
const unsub3 = client.on('session:expired', (event) => {
console.log('Session expired:', event.sessionId);
});
// Transaction status
const unsub4 = client.on('tx:status', (event) => {
console.log('TX', event.txId, '→', event.status);
// status: 'pending' | 'submitted' | 'committed' | 'rejected' | 'failed'
});
// Registry updates
const unsub5 = client.on('registry:status', (event) => {
console.log('Registry:', event.status.source, event.status.verified);
});
// Errors
const unsub6 = client.on('error', (event) => {
console.error('SDK error:', event.error.message);
});
// Unsubscribe when done
unsub1();
unsub2();CIP-0103 Provider Bridge Get a CIP-0103 compliant provider wrapping the client:
const provider = client.asProvider();
// Use CIP-0103 standard methods
const result = await provider.request({ method: 'connect' });
const accounts = await provider.request({ method: 'listAccounts' });
// Subscribe to CIP-0103 events
provider.on('statusChanged', (status) => {
console.log('Provider status:', status);
});See CIP-0103 Provider for the complete provider API.
Cleanup // Always destroy the client when done
// Flushes telemetry, removes event listeners, cleans up resources
client.destroy();⚠️ Warning
Always call
client.destroy() when your application unmounts or the client is no longer needed. This prevents memory leaks and ensures telemetry data is flushed.
Complete Example vanilla-wallet-app.ts Copyimport { createPartyLayer } from '@partylayer/sdk';
async function main() {
// 1. Create client
const client = createPartyLayer({
network: 'mainnet',
app: { name: 'My Vanilla dApp' },
});
// 2. Listen for events
client.on('session:connected', (e) => {
console.log('Connected to', e.session.walletId);
});
client.on('error', (e) => {
console.error('Error:', e.error.message);
});
// 3. List available wallets
const wallets = await client.listWallets();
console.log('Available wallets:', wallets.map(w => w.name));
// 4. Connect
const session = await client.connect({ walletId: 'console' });
console.log('Party ID:', session.partyId);
// 5. Sign a message
const signed = await client.signMessage({
message: 'Verify ownership',
nonce: crypto.randomUUID(),
});
console.log('Signature:', signed.signature);
// 6. Disconnect
await client.disconnect();
// 7. Cleanup
client.destroy();
}
main().catch(console.error);