Skip to main content

Conditional gating overview

Conditional gating allows you to define rules for the members of the group for different privileges / permissions such as entry or chat. It is driven by Push Chat rules engine which is inspired by json rules engine and allows you to create powerful dynamics guiding communication for your community. Some examples of what you can achieve with it —

  • Creating token gated group - ie: user needs to hold XX token to join the group
  • Creating nft gated group - ie: user needs to hold XX NFT to join the gorup
  • Defining multi-chain conditions - ie: user can join the group if they have 5 tokens on Ethereum or 10 tokens on Polygon
  • Defining sending message conditions - ie: user needs 1 token to join the group but 100 to send message
  • Defining non-web3 conditions using Guild - ie: user needs to follow @pushprotocol on twitter to be able to join the group
  • Creating game theories by combining one or multiple conditions - ie: you need 1 token on any chain to join the group but sending messages require you to hold 1000 tokens or 1 NFT or 20 POAPs, etc

Understanding the rules object

The rules object is an optional parameter that you pass in create group API call to conditional gate joining or sending message in group chat.

Overview

rules
permission - entry or chat
 └ conditions
  └ decider - any or all
   └condition a - any or all
    └criteria 1
    └criteria 2
   └condition b - any or all
    └criteria 3

rules object is made up of individual permissions that define privilages of the group.

permission object contains conditions that needs to be satisfied.

conditions object is an array of one or more condition.

decider the namespace (any or all) decides if all of the conditions or anyone of the condition needs to be fulfilled.

condition contains array of criteria, the namespace (any or all) decides if all criterias or anyone of the criteria needs to be fulfilled.

criteria is the atomic condition that has type, category, subcategory and data, based on which a particular condition is deemed as completed or failed.

To summarize, a list of criteria is created by you that is then defined inside decider to define their logical operation which is then passed in conditions of a particular permission. The list of individual permission is then attached to rules of the group to enable Push Chat rule engine to create dynamic communities with creative game theories.

Rules object Parameters

ParamTypeSubtypeDefaultRemarks
rulesobject--Rules object
rules.[permission]object--Permissions object for specific privilege of the group. Multiple permission object can reside within rules object
-entryobject-Permissions object for specific privilege of the group. entry permission conditionalizes joining a group
-chatobject-Permissions object for specific privilege of the group. chat permission conditionalizes sending a message in that group
rules.[permission].conditions-array of objects-Contains array of all condition objects
rules.[permission].conditions.[decider]-object-Contains namespace any or all by which it's decided whether one condition or all condition needs to be fulfilled
rules.[permission].conditions.[decider].[condition]-array of objects-Contains lists of criteria objects defined by decider key, Valid decider keys are any or all. any will mean only one criteria needs to be fulfilled, all means all criteria should pass
-anyobject-any will mean only one criteria needs to be fulfilled from rules.[permission].conditions.[condition] array
-allobject-all will mean only one criteria needs to be fulfilled from rules.[permission].conditions.[condition] array
rules.[permission].conditions.[decider].[condition].[criteria]-object-Individual criteria inside the rules.[permission].conditions.[condition] array

Criteria object Parameters

Criteria object supports multiple access control protocols which can have different conditions and rules, currently Push Chat supports PUSH and GUILD type in criteria, owing to the way each individual protocol handles their respective type, category, subcategory and data, we are segregating the options and what they do for clarity.

When using type - PUSH

ParamTypeSubtypeDefaultRemarks
[criteria]object---Criteria object
typestring--Define the type of the criteria, needs to be PUSH for below category, subcategory to be applicable
categorystring - can be ERC20, ERC721 or CustomEndpoint--Defines the category of the criteria, ERC20 means ERC-20 or normal token, ERC721 means ERC-721 or NFT tokens, CustomEndpoint means a URL will be provided that results in 200 OK
subcategorystring--Further narrows down the condition that you want to run. For ERC20 or ERC721 - supported conditions are holder or owner which means that the criteria will check if a wallet is owner or holder. For CustomEndpoint, the subcategory is GET or POST depending upon what HTTP request you want to use
dataobject--define the data to be passed for checking conditions of criteria
-contractstring-Only used for ERC20 or ERC721 category. Remember to define the contract in chain agnostic fashion. {chain_standard}:{chain_id}:{contract_address}, for example: eip155:1:0xf418588522d5dd018b425E472991E52EBBeEEEEE points to $PUSH token on Ethereum mainnet while eip155:137:0x58001cC1A9E17A20935079aB40B1B8f4Fc19EFd1 points to $PUSH token on Polygon mainnet
-comparisonstring - supports <=, >=, ==-Only used for ERC20 or ERC721 category. Define what comparison to use while comparing the data
-amountnumber-Only used for ERC20 or ERC721 category. Define the number to be passed in the amount
-urlstring-Only used for CustomEndpoint category. Pass in the URL that when polled will return 200 OK for success. API url are automatically appended with {{user_address}}/checkAccess while checking access

Use Case Example - Token gated community

Problem Statement

We want to create a group that whose content is not visible to anyone outside our community of $PUSH. Furthermore, we want to make sure that the group can be viewed by anyone who has at least 1 $PUSH on Ethereum or on Polygon.

Solution

Let's break down the problem statement into individual requirements

Visibility: Creating a group that is not visible to anyone outside it's member is simple, we need to set up private flag in create group API.

Group Join Permission: We have two criteria over here:

  • Criteria 1: User should have 1 $PUSH on Ethereum
  • Criteria 2: User should have 1 $PUSH on Polygon
// Push token on Ethereum Criteria
{
"type": "PUSH", // define type that rules engine should go for
"category": "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
"subcategory": "holder", // define if you are checking 'holder' or 'owner'
"data": {
"contract": "eip155:1:0xf418588522d5dd018b425E472991E52EBBeEEEEE", // $PUSH address on ETH
"comparison": ">=", // what comparison needs to pass
"amount": 1, // amount that needs to passed
"decimals": 18, // the decimals for the token
}
}
// Push token on Polygon Criteria
{
"type": "PUSH", // define type that rules engine should go for
"category": "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
"subcategory": "holder", // define if you are checking 'holder' or 'owner'
'data': {
"contract": "eip155:137:0x58001cC1A9E17A20935079aB40B1B8f4Fc19EFd1", // $PUSH address on ETH
"comparison": ">=", // what comparison needs to pass
"amount": 1, // amount that needs to passed
"decimals": 18, // the decimals for the token
}
}
  • Either of criteria should be able to allow user to join the group, this means that the condition's namespace to use to combine these criterias would be any
// decider object - 'any' since either condition should allow access
"any": [
{
"type": "PUSH", // define type that rules engine should go for
"category": "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
"subcategory": "holder", // define if you are checking 'holder' or 'owner'
"data": {
"contract": "eip155:137:0x58001cC1A9E17A20935079aB40B1B8f4Fc19EFd1", // $PUSH address on ETH
"comparison": ">=", // what comparison needs to pass
"amount": 1, // amount that needs to passed
"decimals": 18, // the decimals for the token
}
},
{
"type": "PUSH", // define type that rules engine should go for
"category": "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
"subcategory": "holder", // define if you are checking 'holder' or 'owner'
"data": {
"contract": "eip155:137:0x58001cC1A9E17A20935079aB40B1B8f4Fc19EFd1", // $PUSH address on ETH
"comparison": ">=", // what comparison needs to pass
"amount": 1, // amount that needs to passed
"decimals": 18, // the decimals for the token
}
}
]
  • Since there are no other conditions that are required, create the entire rules object, conditions only has one condition in entry so namespace for conditions doesn't matter but to keep things clear, we will mark it as all
  "rules": {
"entry": { // permission object
"conditions": { // conditions object
"any": [ // conditions namespace decider - Either group owner / admin invites the user or the user has $PUSH on Ethereum or Polygon
{ // decider 1 - If admin or owner invites someone
"any": [
{ // criteria 1
"type": "PUSH",
"category": "INVITE",
"subcategory": "DEFAULT",
"data": {
"inviterRoles": [
"ADMIN",
"OWNER"
]
}
}
]
},
{
"any": [ // decider 2 - If user has $PUSH on Ethereum or on Polygon
{ // criteria object
"type": "PUSH", // define type that rules engine should go for
"category": "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
"subcategory": "holder", // define if you are checking 'holder' or 'owner'
"data": {
"contract": "eip155:137:0x58001cC1A9E17A20935079aB40B1B8f4Fc19EFd1", // $PUSH address on ETH
"comparison": ">=", // what comparison needs to pass
"amount": 1, // amount that needs to passed
"decimals": 18, // the decimals for the token
}
},
{ // criteria object
"type": "PUSH", // define type that rules engine should go for
"category": "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
"subcategory": "holder", // define if you are checking 'holder' or 'owner'
"data": {
"contract": "eip155:137:0x58001cC1A9E17A20935079aB40B1B8f4Fc19EFd1", // $PUSH address on ETH
"comparison": ">=", // what comparison needs to pass
"amount": 1, // amount that needs to passed
"decimals": 18, // the decimals for the token
}
}
]
}
]
}
}
// since we are not defining chat permissions, it means that any user who is part of the group can chat
}
// Creating your token gated community
const createTokenGatedGroup = await userAlice.chat.group.create(
"Push Community",
{
description: "Token gated web3 native chat example", // provide short description of group
image: "data:image/png;base64,iVBORw0K...", // provide base64 encoded image
members: [], // not needed, rules define this, can omit
admins: [], // not needed as per problem statement, can omit
private: true,
rules: {
entry: {
// permission object
conditions: {
// conditions object
any: [
// conditions namespace decider - Either group owner / admin invites the user or the user has $PUSH on Ethereum or Polygon
{
// decider 1 - If admin or owner invites someone
any: [
{
// criteria 1
type: "PUSH",
category: "INVITE",
subcategory: "DEFAULT",
data: {
inviterRoles: ["ADMIN", "OWNER"],
},
},
],
},
{
any: [
// decider 2 - If user has $PUSH on Ethereum or on Polygon
{
// criteria object
type: "PUSH", // define type that rules engine should go for
category: "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
subcategory: "holder", // define if you are checking 'holder' or 'owner'
data: {
contract:
"eip155:137:0x58001cC1A9E17A20935079aB40B1B8f4Fc19EFd1", // $PUSH address on ETH
comparison: ">=", // what comparison needs to pass
amount: 1, // amount that needs to passed
decimals: 18, // the decimals for the token
},
},
{
// criteria object
type: "PUSH", // define type that rules engine should go for
category: "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
subcategory: "holder", // define if you are checking 'holder' or 'owner'
data: {
contract:
"eip155:137:0x58001cC1A9E17A20935079aB40B1B8f4Fc19EFd1", // $PUSH address on ETH
comparison: ">=", // what comparison needs to pass
amount: 1, // amount that needs to passed
decimals: 18, // the decimals for the token
},
},
],
},
],
},
},
// since we are not defining chat permissions, it means that any user who is part of the group can chat
},
},
);

Token gated group and send message example

Below is an advance version of gated controls that are applied to both entry to the group as well as sending chat in the group.

// We are going to create a group that is:
// Private - All conversations in this group is encrypted and visible only to members of the group
// Gated entry by either of two rules
// Gated entry - Rule 1 - It takes 10 $XYZ token on Ethereum or on Polygon to join the group
// Gated chat by rule of having $1000 XYZ on Ethereum token to allow sending chat in the group
const myTokenGatedGroup = await userAlice.chat.group.create("BRB Chat", {
description: "This is your DAO community native web3 chat", // provide short description of group
image: "data:image/png;base64,iVBORw0K...", // provide base64 encoded image
members: ["0x123...", "0xABC...", "eip155:0x754..."], // see types of recipient to learn more
admins: [
"nft:eip155:11155111:0x42af3147f17239341477113484752D5D3dda997B:2:1683058528",
], // NFT addresses are supported as well
private: true, // ensures chat within group is encrypted and is only visible to members of the group
rules: {
// define rules to gate different permissions of the group, ie: joining group or sending messages
entry: {
// define condition for joining the group
conditions: {
// set of all conditions that should be fulfilled to join the group
any: [
{
any: [
// set decider to 'any', if 'and' then all rules need to be fulfilled
{
// define criteria 1
type: "PUSH",
category: "INVITE",
subcategory: "DEFAULT",
data: {
inviterRoles: ["ADMIN", "OWNER"],
},
},
{
// define criteria 2
type: "PUSH", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
subcategory: "holder", // define if you are checking 'holder' or 'owner'
data: {
// define the data check
contract:
"eip155:1:0xBE18197d1c071b72fb2460B1652C96C22d40F1D9", // pass {blockchain_standard}:{chain_id}:{address} as a shorthand
comparison: ">=", // what comparison needs to pass
amount: 10, // amount that needs to passed
decimals: 18, // the decimals for the contract
},
},
{
// define criteria 3
type: "PUSH", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
subcategory: "holder", // define if you are checking 'holder' or 'owner'
data: {
// define the data check
contract:
"eip155:137:0xBE18197d1c071b72fb2460B1652C96C22d40F1D9", // assuming $XYZ contract address is 0xBE18197d1c071b72fb2460B1652C96C22d40F1D9
comparison: ">=", // what comparison needs to pass
amount: 10, // amount that needs to passed
decimals: 18, // the decimals for the contract
},
},
],
},
],
},
},
chat: {
conditions: {
// define condition for sending message in the group
all: [
{
any: [
// set decider to 'any', if 'and' then all rules need to be fulfilled
{
// define criteria 1
type: "PUSH", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ERC20", // define it's ERC20 token that you want to check, supports ERC721 as well
subcategory: "holder", // define if you are checking 'holder' or 'owner'
data: {
// define the data check
contract:
"eip155:1:0xBE18197d1c071b72fb2460B1652C96C22d40F1D9", // pass {blockchain_standard}:{chain_id}:{address} as a shorthand
comparison: ">=", // what comparison needs to pass
amount: 1000, // amount that needs to passed
decimals: 18, // the decimals for the contract
},
},
],
},
],
},
},
},
});

NFT gated group example

Below is an example of how to NFT gate entry to the group.

import { PushAPI, CONSTANTS } from "@pushprotocol/restapi";
import { ethers } from "ethers";

// Creating a random signer from a wallet, ideally this is the wallet you will connect
const signer = ethers.Wallet.createRandom();

console.log(
`Signer address: ${signer.address} | Signer private key: ${signer.privateKey}`,
);

// Initialize wallet user
// 'CONSTANTS.ENV.PROD' -> mainnet apps | 'CONSTANTS.ENV.STAGING' -> testnet apps
const userAlice = await PushAPI.initialize(signer, {
env: CONSTANTS.ENV.STAGING,
});

// Creating your token gated community
const createTokenGatedGroup = await userAlice.chat.group.create(
"Push Community",
{
description: "Token gated web3 native chat example", // provide short description of group
image: "data:image/png;base64,iVBORw0K...", // provide base64 encoded image
members: [], // not needed, rules define this, can omit
admins: [], // not needed as per problem statement, can omit
private: true,
rules: {
entry: {
// entry is based on conditions
conditions: {
any: [
// any of the decider should allow entry
{
// decider 1 - If admin or owner invites someone
any: [
{
// criteria 1
type: "PUSH",
category: "INVITE",
subcategory: "DEFAULT",
data: {
inviterRoles: ["ADMIN", "OWNER"],
},
},
],
},
{
// decicder 2 - If wallet holds 1 NFT on polygon testnet
any: [
{
// criteria 1
type: "PUSH", // define type that rules engine should go for
category: "ERC721", // define it's ERC20 token that you want to check, supports ERC721 as well
subcategory: "holder", // define if you are checking 'holder'
data: {
contract:
"eip155:80001:0x9105D95577575116948F5afcF479254f49F27939",
comparison: ">=", // what comparison needs to pass
amount: 1, // amount that needs to passed
decimals: 18,
},
},
],
},
],
},
},
},
},
);

console.log("Chat created successfully!", createTokenGatedGroup);

NFT gated group github example repo

Follow this token gated example github repo to see and play with the API.

Guild gated group example

Below are the examples of how you can create gated group chats for guilds at guild.xyz using GUILD type in criteria.

Examples for gating entry to the group

Example 1

Allow a user to join the group if they have atleast one role in the guild. Say there are 3 different roles in your guild, and you want to allow a user to be able to join your gated group if they have any one of the guild roles (atleast one role).

import { PushAPI, CONSTANTS } from "@pushprotocol/restapi";
import { ethers } from "ethers";

// Creating a random signer from a wallet, ideally this is the wallet you will connect
const signer = ethers.Wallet.createRandom();

console.log(
`Signer address: ${signer.address} | Signer private key: ${signer.privateKey}`,
);

// Initialize wallet user
// 'CONSTANTS.ENV.PROD' -> mainnet apps | 'CONSTANTS.ENV.STAGING' -> testnet apps
const userAlice = await PushAPI.initialize(signer, {
env: CONSTANTS.ENV.STAGING,
});

// Creating your guild gated community
const createGuildGatedGroup = await userAlice.chat.group.create(
"Guild Community",
{
description: "This is a community chat gated by guild roles", // provide short description of group
image: "data:image/png;base64,iVBORw0K...", // provide base64 encoded image
members: [], // not needed, rules define this, can omit
admins: [], // can adds admins if needed
private: false, // in our case, we are making a public group
rules: {
entry: {
// entry is based on conditions
conditions: {
any: [
// any of the decider should allow entry
{
any: [
{
// criteria 1
// this criteria lets admins or owners invite anyone
type: "PUSH",
category: "INVITE",
subcategory: "DEFAULT",
data: {
inviterRoles: ["ADMIN", "OWNER"],
},
},

{
// define criteria 2
type: "GUILD", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ROLES", // define it's ROLES for GUILD groups
subcategory: "DEFAULT", // its DEFAULT for GUILD groups
data: {
id: "62154", // your guild id
comparison: "any", // in our case, we are allowing if user has atleast one role in the guild mentioned above
role: "*", // useful when you want to target a specific role but in our case, its any role so we are using *
},
},
],
},
],
},
},
},
},
);

console.log("Chat created successfully!", createGuildGatedGroup);

Example 2

Allow a user to join the group only if they have all the roles in the guild. Say there are 3 different roles in your guild, and you want to allow a user to be able to join your gated group only if they have all the 3 of the guild roles.

import { PushAPI, CONSTANTS } from "@pushprotocol/restapi";
import { ethers } from "ethers";

// Creating a random signer from a wallet, ideally this is the wallet you will connect
const signer = ethers.Wallet.createRandom();

console.log(
`Signer address: ${signer.address} | Signer private key: ${signer.privateKey}`,
);

// Initialize wallet user
// 'CONSTANTS.ENV.PROD' -> mainnet apps | 'CONSTANTS.ENV.STAGING' -> testnet apps
const userAlice = await PushAPI.initialize(signer, {
env: CONSTANTS.ENV.STAGING,
});

// Creating your guild gated community
const createGuildGatedGroup = await userAlice.chat.group.create(
"Guild Community",
{
description: "This is a community chat gated by guild roles", // provide short description of group
image: "data:image/png;base64,iVBORw0K...", // provide base64 encoded image
members: [], // not needed, rules define this, can omit
admins: [], // can adds admins if needed
private: false, // in our case, we are making a public group
rules: {
entry: {
// entry is based on conditions
conditions: {
any: [
// any of the decider should allow entry
{
any: [
{
// criteria 1
// this criteria lets admins or owners invite anyone
type: "PUSH",
category: "INVITE",
subcategory: "DEFAULT",
data: {
inviterRoles: ["ADMIN", "OWNER"],
},
},

{
// define criteria 2
type: "GUILD", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ROLES", // define it's ROLES for GUILD groups
subcategory: "DEFAULT", // its DEFAULT for GUILD groups
data: {
id: "62154", // your guild id
comparison: "all", // in our case, we are allowing if user has atleast one role in the guild mentioned above
role: "*", // useful when you want to target a specific role but in our case, its all roles so we are using *
},
},
],
},
],
},
},
},
},
);

console.log("Chat created successfully!", createGuildGatedGroup);

Example 3

Say you want to allow entry only for users that have specific roles in the guild, you can do that by passing the role name in the role key of the data object.

import { PushAPI, CONSTANTS } from "@pushprotocol/restapi";
import { ethers } from "ethers";

// Creating a random signer from a wallet, ideally this is the wallet you will connect
const signer = ethers.Wallet.createRandom();

console.log(
`Signer address: ${signer.address} | Signer private key: ${signer.privateKey}`,
);

// Initialize wallet user
// 'CONSTANTS.ENV.PROD' -> mainnet apps | 'CONSTANTS.ENV.STAGING' -> testnet apps
const userAlice = await PushAPI.initialize(signer, {
env: CONSTANTS.ENV.STAGING,
});

// Creating your guild gated community
const createGuildGatedGroup = await userAlice.chat.group.create(
"Guild Community",
{
description: "This is a community chat gated by guild roles", // provide short description of group
image: "data:image/png;base64,iVBORw0K...", // provide base64 encoded image
members: [], // not needed, rules define this, can omit
admins: [], // can adds admins if needed
private: false, // in our case, we are making a public group
rules: {
entry: {
// entry is based on conditions
conditions: {
any: [
// any of the decider should allow entry
{
any: [
{
// criteria 1
// this criteria lets admins or owners invite anyone
type: "PUSH",
category: "INVITE",
subcategory: "DEFAULT",
data: {
inviterRoles: ["ADMIN", "OWNER"],
},
},

{
// define criteria 2
type: "GUILD", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ROLES", // define it's ROLES for GUILD groups
subcategory: "DEFAULT", // its DEFAULT for GUILD groups
data: {
id: "62154", // your guild id
comparison: "all", // in our case, we are allowing if user has atleast one role in the guild mentioned above
role: "111070", // id of the specific role in guild that you want to allow
},
},
],
},
],
},
},
},
},
);

console.log("Chat created successfully!", createGuildGatedGroup);

Examples for gating entry and chat permissions to the group

Example 1

Allow a user to join and send messages in the group if they have atleast one role in the guild. Say there are 3 different roles in your guild, and you want to allow a user to be able to join your gated group if they have any one of the guild roles (atleast one role).

import { PushAPI, CONSTANTS } from "@pushprotocol/restapi";
import { ethers } from "ethers";

// Creating a random signer from a wallet, ideally this is the wallet you will connect
const signer = ethers.Wallet.createRandom();

console.log(
`Signer address: ${signer.address} | Signer private key: ${signer.privateKey}`,
);

// Initialize wallet user
// 'CONSTANTS.ENV.PROD' -> mainnet apps | 'CONSTANTS.ENV.STAGING' -> testnet apps
const userAlice = await PushAPI.initialize(signer, {
env: CONSTANTS.ENV.STAGING,
});

// Creating your guild gated community
const createGuildGatedGroup = await userAlice.chat.group.create(
"Guild Community",
{
description: "This is a community chat gated by guild roles", // provide short description of group
image: "data:image/png;base64,iVBORw0K...", // provide base64 encoded image
members: [], // not needed, rules define this, can omit
admins: [], // can adds admins if needed
private: false, // in our case, we are making a public group
rules: {
entry: {
// entry is based on conditions
conditions: {
any: [
// any of the decider should allow entry
{
any: [
{
// criteria 1
// this criteria lets admins or owners invite anyone
type: "PUSH",
category: "INVITE",
subcategory: "DEFAULT",
data: {
inviterRoles: ["ADMIN", "OWNER"],
},
},

{
// define criteria 2
type: "GUILD", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ROLES", // define it's ROLES for GUILD groups
subcategory: "DEFAULT", // its DEFAULT for GUILD groups
data: {
id: "62154", // your guild id
comparison: "any", // in our case, we are allowing if user has atleast one role in the guild mentioned above
role: "*", // useful when you want to target a specific role but in our case, its any role so we are using *
},
},
],
},
],
},
},
chat: {
// chatting permission is based on conditions
conditions: {
any: [
// any of the decider should allow user to send message in the group
{
any: [
{
// define criteria 2
type: "GUILD", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ROLES", // define it's ROLES for GUILD groups
subcategory: "DEFAULT", // its DEFAULT for GUILD groups
data: {
id: "62154", // your guild id
comparison: "any", // in our case, we are allowing if user has atleast one role in the guild mentioned above
role: "*", // useful when you want to target a specific role but in our case, its any role so we are using *
},
},
],
},
],
},
},
},
},
);

console.log("Chat created successfully!", createGuildGatedGroup);

Example 2

Allow a user to join and send messages in the group only if they have all the roles in the guild. Say there are 3 different roles in your guild, and you want to allow a user to be able to join your gated group only if they have all the 3 of the guild roles.

import { PushAPI, CONSTANTS } from "@pushprotocol/restapi";
import { ethers } from "ethers";

// Creating a random signer from a wallet, ideally this is the wallet you will connect
const signer = ethers.Wallet.createRandom();

console.log(
`Signer address: ${signer.address} | Signer private key: ${signer.privateKey}`,
);

// Initialize wallet user
// 'CONSTANTS.ENV.PROD' -> mainnet apps | 'CONSTANTS.ENV.STAGING' -> testnet apps
const userAlice = await PushAPI.initialize(signer, {
env: CONSTANTS.ENV.STAGING,
});

// Creating your guild gated community
const createGuildGatedGroup = await userAlice.chat.group.create(
"Guild Community",
{
description: "This is a community chat gated by guild roles", // provide short description of group
image: "data:image/png;base64,iVBORw0K...", // provide base64 encoded image
members: [], // not needed, rules define this, can omit
admins: [], // can adds admins if needed
private: false, // in our case, we are making a public group
rules: {
entry: {
// entry is based on conditions
conditions: {
any: [
// any of the decider should allow entry
{
any: [
{
// criteria 1
// this criteria lets admins or owners invite anyone
type: "PUSH",
category: "INVITE",
subcategory: "DEFAULT",
data: {
inviterRoles: ["ADMIN", "OWNER"],
},
},

{
// define criteria 2
type: "GUILD", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ROLES", // define it's ROLES for GUILD groups
subcategory: "DEFAULT", // its DEFAULT for GUILD groups
data: {
id: "62154", // your guild id
comparison: "all", // in our case, we are allowing if user has atleast one role in the guild mentioned above
role: "*", // useful when you want to target a specific role but in our case, its all roles so we are using *
},
},
],
},
],
},
},
chat: {
// entry is based on conditions
conditions: {
any: [
// any of the decider should allow entry
{
any: [
{
// define criteria 2
type: "GUILD", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ROLES", // define it's ROLES for GUILD groups
subcategory: "DEFAULT", // its DEFAULT for GUILD groups
data: {
id: "62154", // your guild id
comparison: "all", // in our case, we are allowing if user has atleast one role in the guild mentioned above
role: "*", // useful when you want to target a specific role but in our case, its any role so we are using *
},
},
],
},
],
},
},
},
},
);

console.log("Chat created successfully!", createGuildGatedGroup);

Example 3

Say you want to allow entry and messaging capability only for users that have specific roles in the guild, you can do that by passing the role name in the role key of the data object.

import { PushAPI, CONSTANTS } from "@pushprotocol/restapi";
import { ethers } from "ethers";

// Creating a random signer from a wallet, ideally this is the wallet you will connect
const signer = ethers.Wallet.createRandom();

console.log(
`Signer address: ${signer.address} | Signer private key: ${signer.privateKey}`,
);

// Initialize wallet user
// 'CONSTANTS.ENV.PROD' -> mainnet apps | 'CONSTANTS.ENV.STAGING' -> testnet apps
const userAlice = await PushAPI.initialize(signer, {
env: CONSTANTS.ENV.STAGING,
});

// Creating your guild gated community
const createGuildGatedGroup = await userAlice.chat.group.create(
"Guild Community",
{
description: "This is a community chat gated by guild roles", // provide short description of group
image: "data:image/png;base64,iVBORw0K...", // provide base64 encoded image
members: [], // not needed, rules define this, can omit
admins: [], // can adds admins if needed
private: false, // in our case, we are making a public group
rules: {
entry: {
// entry is based on conditions
conditions: {
any: [
// any of the decider should allow entry
{
any: [
{
// criteria 1
// this criteria lets admins or owners invite anyone
type: "PUSH",
category: "INVITE",
subcategory: "DEFAULT",
data: {
inviterRoles: ["ADMIN", "OWNER"],
},
},

{
// define criteria 2
type: "GUILD", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ROLES", // define it's ROLES for GUILD groups
subcategory: "DEFAULT", // its DEFAULT for GUILD groups
data: {
id: "62154", // your guild id
comparison: "", // in our case, we are allowing if user has specific role so no comparison needed
role: "111070", // id of the specific role in guild that you want to allow
},
},
],
},
],
},
},
chat: {
// entry is based on conditions
conditions: {
any: [
// any of the decider should allow entry
{
any: [
{
// define criteria 2
type: "GUILD", // define type that rules engine should go for, currently supports PUSH or GUILD
category: "ROLES", // define it's ROLES for GUILD groups
subcategory: "DEFAULT", // its DEFAULT for GUILD groups
data: {
id: "62154", // your guild id
comparison: "", // in our case, we are allowing if user has specific role so no comparison needed
role: "111070", // id of the specific role in guild that you want to allow
},
},
],
},
],
},
},
},
},
);

console.log("Chat created successfully!", createGuildGatedGroup);