Video: Token Gated Chat
Watch Calum build an NFT-gated chat app with Polybase DB from scratch.
Deployed app
View a deployed version of the app: Token gated chat app (opens in a new tab)
Code
View the code on Github: Token gated chat app (opens in a new tab)
Schema
collection User {
id: string;
@delegate
@read
publicKey: PublicKey;
// Called when a new record is created db.collection('User').create([])
constructor () {
// ctx.publicKey is populated if the user signs the call
if (!ctx.publicKey) {
error('You must sign the txn');
}
// .toHex() converts the public key to a hex string
this.id = ctx.publicKey.toHex(); // 0x...
// Store the public key so we can use it for permissions
this.publicKey = ctx.publicKey;
}
}
// Anyone can read NFT collection
@read
collection NFT {
id: string;
// The NFT delegates all responsibility it is given to the owner
@delegate
owner: User;
// Called when new NFT created db.collection('User')
// .create(["nft-name", db.collection("User").record(userId)])
constructor (id: string, owner: User) {
this.id = id;
this.owner = owner;
}
}
collection Chat {
id: string;
name: string;
@delegate
@read
members: NFT[];
constructor (id: string, name: string) {
this.id = id;
this.name = name;
this.members = [];
}
// Anyone who with an NFT in members can call this fn
@call(members)
addMember (nft: NFT) {
// Maximum of 5 members
if (this.members.length > 5) {
error('Too many people in the room');
}
this.members.push(nft);
}
// Anyone who with an NFT in members can call this fn
@call(members)
setName (name: string) {
this.name = name;
}
}
collection Message {
id: string;
message: string;
// Currently timestamp must be passed in from the client
// so is untrusted
timestamp: number;
// You can read this record, only if you are
// part of the chat
@read
chat: Chat;
constructor (id: string, message: string, timestamp: number, chat: Chat) {
this.id = id;
this.message = message;
this.timestamp = timestamp;
this.chat = chat;
}
}