From telnyx-webrtc-client
Build cross-platform VoIP apps in React Native with Telnyx WebRTC SDK, using reactive RxJS API, native CallKit/ConnectionService UI, push notifications, and auto-lifecycle management.
npx claudepluginhub team-telnyx/skillsThis skill uses the workspace's default tool permissions.
Build real-time voice communication into React Native apps (Android & iOS) using the `@telnyx/react-voice-commons-sdk` library.
Build cross-platform VoIP apps in React Native with Telnyx WebRTC SDK, using reactive RxJS API, native CallKit/ConnectionService UI, push notifications, and auto-lifecycle management.
Implements iOS VoIP calling with CallKit and PushKit for incoming/outgoing flows, VoIP push registration, CXProvider/CXCallController config, audio sessions, and call directory extensions.
Prevents silent decimal mismatch bugs in EVM ERC-20 tokens via runtime decimals lookup, chain-aware caching, bridged-token handling, and normalization. For DeFi bots, dashboards using Python/Web3, TypeScript/ethers, Solidity.
Share bugs, ideas, or general feedback.
Build real-time voice communication into React Native apps (Android & iOS) using the @telnyx/react-voice-commons-sdk library.
Prerequisites: Create WebRTC credentials and generate a login token using the Telnyx server-side SDK. See the
telnyx-webrtc-*skill in your server language plugin (e.g.,telnyx-python,telnyx-javascript).
npm install @telnyx/react-voice-commons-sdk
import { TelnyxVoiceApp, createTelnyxVoipClient } from '@telnyx/react-voice-commons-sdk';
// Create VoIP client instance
const voipClient = createTelnyxVoipClient({
enableAppStateManagement: true, // Auto background/foreground handling
debug: true, // Enable logging
});
export default function App() {
return (
<TelnyxVoiceApp
voipClient={voipClient}
enableAutoReconnect={false}
debug={true}
>
<YourAppContent />
</TelnyxVoiceApp>
);
}
import { createCredentialConfig } from '@telnyx/react-voice-commons-sdk';
const config = createCredentialConfig('sip_username', 'sip_password', {
debug: true,
pushNotificationDeviceToken: 'your_device_token',
});
await voipClient.login(config);
import { createTokenConfig } from '@telnyx/react-voice-commons-sdk';
const config = createTokenConfig('your_jwt_token', {
debug: true,
pushNotificationDeviceToken: 'your_device_token',
});
await voipClient.loginWithToken(config);
The library automatically stores credentials for seamless reconnection:
// Automatically reconnects using stored credentials
const success = await voipClient.loginFromStoredConfig();
if (!success) {
// No stored auth, show login UI
}
import { useEffect, useState } from 'react';
function CallScreen() {
const [connectionState, setConnectionState] = useState(null);
const [calls, setCalls] = useState([]);
useEffect(() => {
// Subscribe to connection state
const connSub = voipClient.connectionState$.subscribe((state) => {
setConnectionState(state);
});
// Subscribe to active calls
const callsSub = voipClient.calls$.subscribe((activeCalls) => {
setCalls(activeCalls);
});
return () => {
connSub.unsubscribe();
callsSub.unsubscribe();
};
}, []);
return (/* UI */);
}
useEffect(() => {
if (call) {
const sub = call.callState$.subscribe((state) => {
console.log('Call state:', state);
});
return () => sub.unsubscribe();
}
}, [call]);
const call = await voipClient.newCall('+18004377950');
Incoming calls are handled automatically via push notifications and the TelnyxVoiceApp wrapper. The native call UI (CallKit/ConnectionService) is displayed automatically.
// Answer incoming call
await call.answer();
// Mute/Unmute
await call.mute();
await call.unmute();
// Hold/Unhold
await call.hold();
await call.unhold();
// End call
await call.hangup();
// Send DTMF
await call.dtmf('1');
google-services.json in project root// MainActivity.kt
import com.telnyx.react_voice_commons.TelnyxMainActivity
class MainActivity : TelnyxMainActivity() {
override fun onHandleIntent(intent: Intent) {
super.onHandleIntent(intent)
// Additional intent processing
}
}
// index.js or App.tsx
import messaging from '@react-native-firebase/messaging';
import { TelnyxVoiceApp } from '@telnyx/react-voice-commons-sdk';
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
await TelnyxVoiceApp.handleBackgroundPush(remoteMessage.data);
});
// AppDelegate.swift
import PushKit
import TelnyxVoiceCommons
@UIApplicationMain
public class AppDelegate: ExpoAppDelegate, PKPushRegistryDelegate {
public override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
// Initialize VoIP push registration
TelnyxVoipPushHandler.initializeVoipRegistration()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// VoIP Push Token Update
public func pushRegistry(_ registry: PKPushRegistry,
didUpdate pushCredentials: PKPushCredentials,
for type: PKPushType) {
TelnyxVoipPushHandler.shared.handleVoipTokenUpdate(pushCredentials, type: type)
}
// VoIP Push Received
public func pushRegistry(_ registry: PKPushRegistry,
didReceiveIncomingPushWith payload: PKPushPayload,
for type: PKPushType,
completion: @escaping () -> Void) {
TelnyxVoipPushHandler.shared.handleVoipPush(payload, type: type, completion: completion)
}
}
Note: CallKit integration is automatically handled by the internal CallBridge component.
| Option | Type | Default | Description |
|---|---|---|---|
enableAppStateManagement | boolean | true | Auto background/foreground handling |
debug | boolean | false | Enable debug logging |
| Prop | Type | Description |
|---|---|---|
voipClient | TelnyxVoipClient | The VoIP client instance |
enableAutoReconnect | boolean | Auto-reconnect on disconnect |
debug | boolean | Enable debug logging |
The library manages these AsyncStorage keys internally:
@telnyx_username - SIP username@telnyx_password - SIP password@credential_token - JWT token@push_token - Push notification tokenYou don't need to manage these manually.
| Issue | Solution |
|---|---|
| Double login | Don't call login() manually when using TelnyxVoiceApp with auto-reconnect |
| Background disconnect | Check enableAutoReconnect setting |
| Android push not working | Verify google-services.json and MainActivity extends TelnyxMainActivity |
| iOS push not working | Ensure AppDelegate implements PKPushRegistryDelegate and calls TelnyxVoipPushHandler |
| Memory leaks | Unsubscribe from RxJS observables in useEffect cleanup |
| Audio issues | iOS audio handled by CallBridge; Android check ConnectionService |
import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.multiRemove([
'@telnyx_username',
'@telnyx_password',
'@credential_token',
'@push_token',
]);
references/webrtc-server-api.md has the server-side WebRTC API — credential creation, token generation, and push notification setup. You MUST read it when setting up authentication or push notifications.
The main public interface for the react-voice-commons module.
This class serves as the Façade for the entire module, providing a simplified API that completely hides the underlying complexity. It is the sole entry point for developers using the react-voice-commons package.
The TelnyxVoipClient is designed to be state-management agnostic, exposing all observable state via RxJS streams. This allows developers to integrate it into their chosen state management solution naturally.
login(
config):Promise<void>
A Promise that completes when the connection attempt is initiated
loginWithToken(
config):Promise<void>
A Promise that completes when the connection attempt is initiated
logout():
Promise<void>
loginFromStoredConfig():
Promise<boolean>
newCall(
destination,callerName?,callerNumber?,customHeaders?):Promise<Call>
The destination number or SIP URI to call
Optional caller name to display
Optional caller ID number
Optional custom headers to include with the call
A Promise that completes with the Call object once the invitation has been sent
handlePushNotification(
payload):Promise<void>
The push notification payload
disablePushNotifications():
void
setCallConnecting(
callId):void
The ID of the call to set to connecting state
findCallByTelnyxCall(
telnyxCall):Call
The Telnyx call object to find
queueAnswerFromCallKit(
customHeaders):void
Optional custom headers to include with the answer
queueEndFromCallKit():
void
dispose():
void
Represents a call with reactive state streams.
This class wraps the underlying Telnyx Call object and provides reactive streams for all call state changes, making it easy to integrate with any state management solution.
answer(
customHeaders?):Promise<void>
Optional custom headers to include with the answer
hangup(
customHeaders?):Promise<void>
Optional custom headers to include with the hangup request
hold():
Promise<void>
resume():
Promise<void>
mute():
Promise<void>
unmute():
Promise<void>
toggleMute():
Promise<void>
setConnecting():
void
dispose():
void
Represents the state of a call in the Telnyx system.
This enum provides a simplified view of call states, abstracting away the complexity of the underlying SIP call states.
RINGING:
"RINGING"
CONNECTING:
"CONNECTING"
ACTIVE:
"ACTIVE"
HELD:
"HELD"
ENDED:
"ENDED"
FAILED:
"FAILED"
DROPPED:
"DROPPED"
Represents the connection state to the Telnyx platform.
This enum provides a simplified view of the connection status, abstracting away the complexity of the underlying WebSocket states.
DISCONNECTED:
"DISCONNECTED"
CONNECTING:
"CONNECTING"
CONNECTED:
"CONNECTED"
RECONNECTING:
"RECONNECTING"
ERROR:
"ERROR"