Skip to main content
Version: 2.x.x

Sending Virtual Gifts - Flutter

Virtual gifting is a powerful monetization and engagement feature that allows viewers to support hosts or speakers during a livestream by sending them digital tokens or "gifts." These gifts can be visually animated and even linked to leaderboards or reward systems.

This guide explains how to implement a secure and real-time virtual gifting experience using your backend server in combination with VideoSDK PubSub.

How It Works

  1. User Action: A viewer taps on a gift button to send a virtual gift to the host.

  2. Server Verification:

    • A request is made to your business backend to process the gift.
    • The server authenticates the user, checks their wallet balance, deducts the gift value, and returns a success response.
  3. Event Broadcast: Upon success, the client publishes a PubSub message to inform everyone in the livestream (host + other viewers) that a gift has been sent. Clients can then visually show an animation or notification.

Backend Responsibility

Your backend plays a central role in verifying, validating, and processing gift transactions. It should:

  • Authenticate the request (token/session)
  • Verify if the user has sufficient balance
  • Deduct the gift cost
  • Store the transaction in a database (optional but recommended)
  • Respond with success or failure

Frontend Implementation

  • Sending a Gift (Client to Backend + PubSub)
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:videosdk/videosdk.dart';
class GiftSender extends StatelessWidget {
final String senderId;
final String hostId;
final Room room;

GiftSender({
required this.senderId,
required this.hostId,
required this.room,
});

void sendGift(String giftType) async {
try {
final response = await http.post(
Uri.parse("https://your-api.com/send-gift"),
headers: {"Content-Type": "application/json"},
body: jsonEncode({
"senderId": senderId,
"hostId": hostId,
"giftType": giftType,
}),
);

final responseData = jsonDecode(response.body);
if (responseData['success'] == true) {
room.pubSub.publish(
"GIFT",
jsonEncode({
"giftType": giftType,
"from": senderId,
"to": hostId,
}),
const PubSubPublishOptions(persist: true),
);
} else {
debugPrint("Gift could not be sent: ${responseData['message']}");
}
} catch (e) {
debugPrint("Error sending gift: $e");
}
}

@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: () => sendGift("rose"),
child: const Text("🌹 Send Rose"),
),
ElevatedButton(
onPressed: () => sendGift("diamond"),
child: const Text("💎 Send Diamond"),
),
],
);
}
}
  • Displaying the Gift (All Clients)
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class GiftReceiver extends StatefulWidget {
final Room room;

const GiftReceiver({required this.room});

@override
State<GiftReceiver> createState() => _GiftReceiverState();
}

class _GiftReceiverState extends State<GiftReceiver> {
final List<Map<String, dynamic>> _gifts = [];

void handleGift(PubSubMessage pubsubMessage) {
final message = pubsubMessage.message;
setState(() {
print("handle gitft : ${message}");
_gifts.add({
"id": DateTime.now().millisecondsSinceEpoch,
"from": "123",
"to": "456",
"type": "diamond",
});
});
}

@override
void initState() {
super.initState();
widget.room.pubSub.subscribe("GIFT", handleGift);
}

@override
void dispose() {
widget.room.pubSub.unsubscribe("GIFT", handleGift);
super.dispose();
}

@override
Widget build(BuildContext context) {
return Column(
children: _gifts.map((gift) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Text(
"🎁 ${gift['from']} sent a ${gift['type']} to ${gift['to']}"),
);
}).toList(),
);
}
}

API Reference

The API references for all the methods and events utilized in this guide are provided below.

Got a Question? Ask us on discord