Users and Profiles
Difference between users and profiles in Honeycomb Protocol
In the Honeycomb Protocol, users and profiles are distinct:
-
User: A person with a universal account, allowing access to any Honeycomb app. Users can link their Steam, Twitter, Discord, and Civic IDs for enhanced functionality, with Civic ID used for KYC verification.
-
Profile: Specific to each project within the ecosystem. For instance, a user needs separate profiles for a social media app and a game. The social media profile tracks posts, comments, and friends, while the game profile tracks achievements, scores, and in-game purchases. In order to create profiles, you need to create a profiles tree.
In summary, the same user can have different profiles for different apps within the Honeycomb Protocol.
Users
Before you can create a profile for your project, you need to create a user. Let's cover how you can create a user.
Creating a user
- JavaScript
- GraphQL
- Unity/C#
const {
createNewUserTransaction: txResponse // This is the transaction response, you'll need to sign and send this transaction
} = await client.createNewUserTransaction({
wallet: userPublicKey.toString(), // User's wallet public key
info: {
name: "Test User",
pfp: "https://lh3.googleusercontent.com/-Jsm7S8BHy4nOzrw2f5AryUgp9Fym2buUOkkxgNplGCddTkiKBXPLRytTMXBXwGcHuRr06EvJStmkHj-9JeTfmHsnT0prHg5Mhg",
bio: "This is a test user",
},
payer: adminPublicKey.toString(), // Optional, the transaction payer's public key
});
query CreateNewUserTransaction($wallet: String!, $info: UserInfoInput) {
createNewUserTransaction(wallet: $wallet, info: $info) {
blockhash
lastValidBlockHeight
transaction
}
}
Provide the accompanying data like this:
{
"wallet": "pubkey", // User's wallet address in string format
"info": {
"bio": "string", // User's bio
"name": "string", // User's name
"pfp": "string", // Link to user's profile picture
}
}
// Create parameters for the new user transaction
var createNewUserParams = new CreateNewUserTransactionParams
{
Wallet = userPublicKey.ToString(), // User's wallet public key
Info = new UserInfoInput // Optional, user's information
{
Name = "Test User", // User's name
Pfp = "https://lh3.googleusercontent.com/-Jsm7S8BHy4nOzrw2f5AryUgp9Fym2buUOkkxgNplGCddTkiKBXPLRytTMXBXwGcHuRr06EvJStmkHj-9JeTfmHsnT0prHg5Mhg", // User's profile picture URL
Bio = "This is a test user" // User's bio
},
Payer = adminPublicKey.ToString() // Optional: the transaction payer's public key
};
// Create a new user transaction
var txResponse = await Client.CreateNewUserTransaction(createNewUserParams);
// txResponse now contains the transaction response, which you'll need to sign and send
Create user and profile
You can create a user and a profile in a single transaction. However, please do keep in mind that profiles are stored in a merkle tree, so if your project doesn't have a profiles tree, this operation won't work as intended. Please create a profiles tree before using this operation.
- JavaScript
- GraphQL
- Unity/C#
const {
createNewUserWithProfileTransaction: txResponse // This is the transaction response, you'll need to sign and send this transaction
} = await client.createNewUserWithProfileTransaction({
project: projectAddress.toString(),
wallet: userPublicKey.toString(),
payer: adminPublicKey.toString(),
profileIdentity: "main",
userInfo: {
name: "Honeycomb Developer",
bio: "This user is created for testing purposes",
pfp: "https://lh3.googleusercontent.com/-Jsm7S8BHy4nOzrw2f5AryUgp9Fym2buUOkkxgNplGCddTkiKBXPLRytTMXBXwGcHuRr06EvJStmkHj-9JeTfmHsnT0prHg5Mhg",
},
});
query CreateNewUserWithProfileTransaction($userInfo: UserInfoInput, $project: String!, $profileIdentity: String, \$wallet: String!, $payer: String) {
createNewUserWithProfileTransaction(userInfo: $userInfo, project: $project, profileIdentity: $profileIdentity, wallet: $wallet, payer: $payer) {
blockhash
lastValidBlockHeight
transaction
}
}
Provide data like this:
{
"project": "pubkey", // Project's pubkey address in string format
"wallet": "pubkey", // User's wallet address in string format
"payer": "pubkey", // Transaction payer's wallet address in string format
"profileIdentity": "main", // Identity type of the profile, usually "main" is used, but you can use any string
"userInfo": {
"bio": "string", // User's bio
"name": "string", // User's name
"pfp": "string", // Link to user's profile picture
},
}
// Create parameters for the new user with profile transaction
var createNewUserWithProfileParams = new CreateNewUserWithProfileTransactionParams
{
Project = projectAddress.ToString(), // Project public key
Wallet = userPublicKey.ToString(), // User's wallet public key
Payer = adminPublicKey.ToString(), // Transaction payer's public key
ProfileIdentity = "main", // Identity of the profile to be created
UserInfo = new UserInfoInput // Optional: user's information
{
Name = "Honeycomb Developer", // User's name
Bio = "This user is created for testing purposes", // User's bio
Pfp = "https://lh3.googleusercontent.com/-Jsm7S8BHy4nOzrw2f5AryUgp9Fym2buUOkkxgNplGCddTkiKBXPLRytTMXBXwGcHuRr06EvJStmkHj-9JeTfmHsnT0prHg5Mhg", // User's profile picture URL
},
ProfileInfo = new ProfileInfoInput // Optional: profile information
{
Bio = "Honeycomb Developer's profile bio", // Profile bio
Name = "Honeycomb Developer", // Profile name
Pfp = "https://lh3.googleusercontent.com/-Jsm7S8BHy4nOzrw2f5AryUgp9Fym2buUOkkxgNplGCddTkiKBXPLRytTMXBXwGcHuRr06EvJStmkHj-9JeTfmHsnT0prHg5Mhg" // Profile picture URL
}
};
// Create a new user with profile transaction
var txResponse = await Client.CreateNewUserWithProfileTransaction(createNewUserWithProfileParams); // txResponse now contains the transaction response, which you'll need to sign and send
Update user
The update user operation allows you to not only update a user's previously provided information, but also to get their Civic Pass information.
- JavaScript
- GraphQL
- Unity/C#
const { createUpdateUserTransaction: txResponse } =
await client.createUpdateUserTransaction(
{
payer: userPublicKey.toString(), // The public key of the user who is updating their information
populateCivic: true, // Optional, set to true if you want to populate the Civic Pass information
wallets: { // Optional, add or remove wallets from the user's Honeycomb Protocol account
add: [newPublicKey], // Optional, add any wallets to the user's Honeycomb Protocol account
remove: [oldPublicKey] // Optional, remove any wallets from the user's Honeycomb Protocol account
},
info: { // Optional, user's information
bio: "Updated user bio", // Optional, updated user bio
name: "Honeycomb Developer", // Optional, updated name
pfp: "https://lh3.googleusercontent.com/-Jsm7S8BHy4nOzrw2f5AryUgp9Fym2buUOkkxgNplGCddTkiKBXPLRytTMXBXwGcHuRr06EvJStmkHj-9JeTfmHsnT0prHg5Mhg", // Optional, updated profile picture
}
},
{
fetchOptions: {
headers: {
authorization: `Bearer ${accessToken}`, // Required, you'll need to authenticate the user with our Edge Client and provide the resulting access token here, otherwise this operation will fail
},
},
}
);
query CreateUpdateUserTransaction($info: UserInfoInput, $payer: String, $populateCivic: Boolean, $wallets: WalletsInput) {
createUpdateUserTransaction(info: $info, payer: $payer, populateCivic: $populateCivic, wallets: $wallets) {
blockhash
lastValidBlockHeight
transaction
}
}
Provide the accompanying data like this:
{
"info": {
"bio": "string", // User's bio
"name": "string", // User's name
"pfp": "string", // Link to user's profile picture
},
"payer": "pubkey", // User's public key in string format
"populateCivic": true, // Optional, set to true if you want to populate the Civic Pass information
"wallets": {
"add": ["pubkey"], // Optional, add any wallets to the user's Honeycomb Protocol account
"remove": ["pubkey"] // Optional, remove any wallets from the user's Honeycomb Protocol account
}
}
var updateUserTransaction = await Client.CreateUpdateUserTransaction(new CreateUpdateUserTransactionParams
{
Payer = userPublicKey, // The public key of the user who is updating their information
PopulateCivic = true, // Optional, set to true if you want to populate the Civic Pass information
Wallets = new UpdateWalletInput // Optional, add or remove wallets from the user's Honeycomb Protocol account
{
Add = new List<string> { newPublicKey }, // Optional, add any wallets to the user's Honeycomb Protocol account
Remove = new List<string> { oldPublicKey } // Optional, remove any wallets from the user's Honeycomb Protocol account
},
Info = new PartialUserInfoInput // Optional, user's information
{
Bio = "Updated user bio", // Optional, updated user bio
Name = "Honeycomb Developer", // Optional, updated name
Pfp = "https://lh3.googleusercontent.com/-Jsm7S8BHy4nOzrw2f5AryUgp9Fym2buUOkkxgNplGCddTkiKBXPLRytTMXBXwGcHuRr06EvJStmkHj-9JeTfmHsnT0prHg5Mhg", // Optional, updated profile picture
}
},
authToken: accessToken // Required, you'll need to authenticate the user with our Edge Client and provide the resulting access token here, otherwise this operation will fail
);
var txResponse = updateUserTransaction.CreateUpdateUserTransaction; // This is the transaction response, you'll need to sign and send this transaction
Please see this page to learn how to get an access token.
In order to access the user's updated data after this operation, you'll have to fetch the user again.
Lastly, please note that if the user hasn't done Civic Pass verification on any of their wallets, the civic
array in the fetch user response will be empty.
Find user(s)
The find user operation allows you to search for Honeycomb Protocol users by various filters, all of which are optional.
- JavaScript
- GraphQL
- Unity/C#
const usersArray = await client.findUsers({ // All filters below are optional
wallets: [], // String array of users' wallet addresses
addresses: [], // String array of Honeycomb Protocol user account addresses
ids: [], // Integer array of Honeycomb Protocol user account IDs
includeProof: true, // Optional, set to true if you want to include the proof of the user's account
}).then(({user}) => user); // This will be an array of users
query FindUsers($addresses: [String!], $ids: [Int!], $wallets: [String!], $includeProof: Boolean) {
user(addresses: $addresses, ids: $ids, wallets: $wallets, includeProof: $includeProof) {
address
id
info {
bio
name
pfp
}
leaf_idx
proof {
canopy_depth
leaf
leaf_index
maxDepth
node_index
proof
root
tree_id
}
socialInfo {
civic {
expiry
gatekeeperNetwork
walletIndex
}
discord
steam
twitter
}
tree_id
wallets {
shadow
wallets
}
}
}
Provide the accompanying data like this:
{
"addresses": ["pubkey"], // String array of Honeycomb Protocol user account addresses
"ids": [int], // Integer array of Honeycomb Protocol user account IDs
"wallets": ["pubkey"], // String array of users' wallet addresses
"includeProof": boolean // Optional, set to true if you want to include the proof of the user's account
}
var findUsersParams = new FindUsersParams
{
Wallets = new List<string>(), // String array of users' wallet addresses
Addresses = new List<string>(), // String array of Honeycomb Protocol user account addresses
Ids = new List<int>(), // Integer array of Honeycomb Protocol user account IDs
IncludeProof = true, // Optional, set to true if you want to include the proof of the user's account
};
// Find users based on the specified parameters
var usersArrayResponse = await Client.FindUsers(findUsersParams);
// Extract the user array from the response
var usersArray = usersArrayResponse.User; // This will be an array of users
Profiles
Profiles are specific to each project within the Honeycomb Protocol ecosystem. Let's cover how you can create a profile for your project.
Before you can start creating profiles for your project, you'll need to create a profiles tree. Let's cover that first.
Create a profiles tree
- JavaScript
- GraphQL
- Unity/C#
const {
createCreateProfilesTreeTransaction: txResponse // This is the transaction response, you'll need to sign and send this transaction
} = await client.createCreateProfilesTreeTransaction({
payer: adminPublicKey.toString(),
project: projectAddress.toString(),
treeConfig: {
// Provide either the basic or advanced configuration, we recommend using the basic configuration if you don't know the exact values of maxDepth, maxBufferSize, and canopyDepth (the basic configuration will automatically configure these values for you)
basic: {
numAssets: 100000, // The desired number of profiles this tree will be able to store
},
// Uncomment the following config if you want to configure your own profile tree (also comment out the above config)
// advanced: {
// maxDepth: 20,
// maxBufferSize: 64,
// canopyDepth: 14,
// }
}
});
query CreateCreateProfilesTreeTransaction($treeConfig: TreeSetupConfig!, $project: String!, $authority: String!, $payer: String) {
createCreateProfilesTreeTransaction(treeConfig: $treeConfig, project: $project, authority: $authority, payer: $payer) {
cost
maxTreeCapacity
proofBytes
space
treeAddress
tx {
blockhash
lastValidBlockHeight
transaction
}
}
}
Provide the data like this:
{
"project": "pubkey", // Project public key as a string
"authority": "pubkey", // Authority public key as a string
"payer": "pubkey", // Payer public key as a string
"treeConfig": {
// Provide either the basic or advanced configuration, we recommend using the basic configuration if you don't know the exact values of maxDepth, maxBufferSize, and canopyDepth (the basic configuration will automatically configure these values for you)
"basic": {
"numAssets": int // The desired number of profiles this tree will be able to store
},
// Use the following config if you want to configure your own profile tree (also remove the above basic config)
// "advanced": {
// "canopyDepth": int, // The depth of the canopy
// "maxBufferSize": int, // The maximum buffer size
// "maxDepth": int // The maximum depth of the tree
// }
}
}
// Create parameters for the create profiles tree transaction
var createProfilesTreeParams = new CreateCreateProfilesTreeTransactionParams
{
Payer = adminPublicKey.ToString(), // Public key of the payer
Project = projectAddress.ToString(), // Project public key
TreeConfig = new ProfilesTreeConfig // Configuration for the profiles tree
{
Basic = new BasicTreeConfig // Basic configuration for the profiles tree
{
NumAssets = 100000 // The desired number of profiles this tree will be able to store
}
// Uncomment the following config if you want to configure your own profile tree
// Advanced = new AdvancedTreeConfig
// {
// MaxDepth = 20,
// MaxBufferSize = 64,
// CanopyDepth = 14
// }
}
};
// Create the create profiles tree transaction
var txResponse = await Client.CreateCreateProfilesTreeTransaction(createProfilesTreeParams); // txResponse now contains the transaction response, which you'll need to sign and send
Creating a profile
When creating a profile for an existing user, you'll have to authenticate that user and include an access token in the request. Please see this page to learn how to get an access token.
- JavaScript
- GraphQL
- Unity/C#
const {
createNewProfileTransaction: txResponse // This is the transaction response, you'll need to sign and send this transaction
} = await client.createNewProfileTransaction({
project: projectAddress.toString(), // The project's public key
payer: userPublicKey.toString(), // The transaction payer's public key, the profile will also be created for this payer
identity: "main", // Identity type in string, the value depends on the project's needs
info: { // Optional, profile information, all values in the object are optional
bio: "My name is John Doe",
name: "John Doe",
pfp: "link-to-pfp"
}
},
{
fetchOptions: {
headers: {
authorization: `Bearer ${accessToken}`, // Required, you'll need to authenticate the user with our Edge Client and provide the resulting access token here, otherwise this operation will fail
},
}
});
query CreateNewProfileQuery($project: String!, $identity: String, $info: ProfileInfoInput) {
createNewProfileTransaction(project: $project, identity: $identity, info: $info) {
blockhash
lastValidBlockHeight
transaction
}
}
Provide the accompanying data like this:
{
"project": "pubkey", // Project's pubkey address in string format
"identity": "string", // Identity type of the profile, usually "main" is used, but you can use any string
"info": {
"bio": "string", // User's bio
"name": "string", // User's name
"pfp": "string", // Link to user's profile picture
}
}
var newProfileTransaction = await Client.CreateNewProfileTransaction(new CreateNewProfileTransactionParams
{
Project = projectAddress, // The project's public key
Payer = userPublicKey, // The transaction payer's public key, the profile will also be created for this payer
Identity = "main", // Identity type in string, the value depends on the project's needs
Info = new ProfileInfoInput // Optional, profile information, all values in the object are optional
{
Bio = "My name is John Doe",
Name = "John Doe",
Pfp = "link-to-pfp"
}
},
authToken: accessToken // Required, you'll need to authenticate the user with our Edge Client and provide the resulting access token here, otherwise this operation will fail
);
var txResponse = newProfileTransaction.CreateNewProfileTransaction; // This is the transaction response, you'll need to sign and send this transaction
Update profile
Same as creating a profile, you'll need to authenticate the user and include an access token in the request. Please see this page to learn how to get an access token.
- JavaScript
- GraphQL
- Unity/C#
const {
createUpdateProfileTransaction: txResponse // This is the transaction response, you'll need to sign and send this transaction
} = await client.createUpdateProfileTransaction({
payer: userPublicKey.toString(),
profile: profileAddress.toString(),
info: {
bio: "This is profile of user",
name: "User",
pfp: "link-to-pfp"
},
customData: {
add: { // Here you can add any custom data to a user's profile, the format is given below (please always use key: ["string"])
location: ["San Francisco, CA"],
website: ["https://johndoe.dev"],
github: ["https://github.com/johndoe"],
stars: ["55"]
},
remove: [ // Provide any keys for custom data you want to remove from the profile, the key-value pairs will be removed, the format is given below
"collaborations" // This will remove the key "collaborations" from the profile along with the corresponding value
]
}
},
{
fetchOptions: {
headers: {
authorization: `Bearer ${accessToken}`, // Required, you'll need to authenticate the user with our Edge Client and provide the resulting access token here, otherwise this operation will fail
},
}
});
query CreateUpdateProfileTransaction($profile: String!, $payer: String!, $info: ProfileInfoInput, $customData: CustomDataInput) {
createUpdateProfileTransaction(profile: $profile, payer: $payer, info: $info, customData: $customData) {
transaction
blockhash
lastValidBlockHeight
}
}
Provide data like this:
{
"profile": "pubkey", // Profile's pubkey address in string format
"payer": "pubkey", // Transaction payer's wallet address in string format
"info": {
"bio": "string", // Profile's bio
"name": "string", // Profile name
"pfp": "string", // Link to the profile picture
},
"customData": {
"add": { // Here you can add any custom data to a user's profile, the format is given below (please always use "key": ["string"])
"location": ["San Francisco, CA"],
"website": ["https://johndoe.dev"],
"github": ["https://github.com/johndoe"],
"stars": ["55"]
},
"remove": [ // Provide any keys for custom data you want to remove from the profile, the key-value pairs will be removed, the format is given below
"collaborations" // This will remove the key "collaborations" from the profile along with the corresponding value
]
}
}
var createUpdateProfileTransaction = await Client.CreateUpdateProfileTransaction(
new CreateUpdateProfileTransactionParams
{
Payer = userPublicKey.ToString(), // Payer public key as a string
Profile = profileAddress.ToString(), // Profile address as a string
Info = new ProfileInfoInput
{
Bio = "This is profile of user",
Name = "User",
Pfp = "link-to-pfp"
},
CustomData = new CustomDataInput
{
Add = new Dictionary<string, string[]>
{
{ "location", new[] { "San Francisco, CA" } },
{ "website", new[] { "https://johndoe.dev" } },
{ "github", new[] { "https://github.com/johndoe" } },
{ "stars", new[] { "55" } }
},
Remove = new List<string>
{
"collaborations" // Removes the key "collaborations" from the profile
}
}
},
accessToken
);
var txResponse = createUpdateProfileTransaction.CreateUpdateProfileTransaction; // This is the transaction response, you'll need to sign and send this transaction
After updating the profile, you'll need to fetch the profile again to access the updated data.
Find profile(s)
- JavaScript
- GraphQL
- Unity/C#
const profilesArray = await client.findProfiles({ // All filters below are optional
userIds: [], // Integer array of Honeycomb Protocol user account IDs
projects: [], // String array of project addresses
addresses: [], // String array of Honeycomb Protocol profile account addresses
identities: [], // String array of profile identities
includeProof: true, // Optional, set to true if you want to include the proof of the profile's account
}).then(({profile}) => profile); // This will be an array of profiles,
query FindProfiles($addresses: [String!], $identities: [String!], $includeProof: Boolean, $projects: [String!], $userIds: [Int!]) {
profile(addresses: $addresses, identities: $identities, includeProof: $includeProof, projects: $projects, userIds: $userIds) {
address
customData
identity
info {
bio
name
pfp
}
leaf_idx
platformData {
achievements
custom
xp
}
project
proof {
canopy_depth
leaf
leaf_index
maxDepth
proof
node_index
root
tree_id
}
tree_id
userId
}
}
Provide the accompanying data like this:
{
"addresses": ["pubkey"], // String array of Honeycomb Protocol profile account addresses
"identities": ["string"], // String array of profile identities
"includeProof": boolean, // Optional, set to true if you want to include the proof of the profile's account
"projects": ["pubkey"], // String array of project addresses
"userIds": [int] // Integer array of Honeycomb Protocol user account IDs
}
// Create parameters for finding profiles
var findProfilesParams = new FindProfilesParams
{
UserIds = new List<int>(), // Integer array of Honeycomb Protocol user account IDs
Projects = new List<string>(), // String array of project addresses
Addresses = new List<string>(), // String array of Honeycomb Protocol profile account addresses
Identities = new List<string>(), // String array of profile identities
IncludeProof = true // Optional, set to true if you want to include the proof of the profile's account
};
// Find profiles based on the specified parameters
var profilesArrayResponse = await Client.FindProfiles(findProfilesParams);
// Extract the profile array from the response
var profilesArray = profilesArrayResponse.Profile; // This will be an array of profiles
Add XP and/or achievements to a profile
Developers might want to add XP and/or achievements to a user's profile after they do certain actions in their app/game.
- JavaScript
- GraphQL
const { createUpdatePlatformDataTransaction: txResponse } = await client.createUpdatePlatformDataTransaction({
profile: profileAddress.toString(), // The profile's public key
authority: adminKeypair.publicKey.toString(), // The public key of the project authority
platformData: {
addXp: 100, // Optional, how much XP to award to the player
addAchievements: [1], // Optional, an array containing indexes of the achievements to add
custom: { // Optional, add/remove any custom data to the profile
add: [
["location", "San Francisco, CA"]
],
remove: ["name"],
}
},
});
query CreateUpdatePlatformDataTransaction($authority: String!, $profile: String!, $delegateAuthority: String!, $payer: String!, $platformData: PlatformDataInput) {
createUpdatePlatformDataTransaction(authority: $authority, profile: $profile, delegateAuthority: $delegateAuthority, payer: $payer, platformData: $platformData) {
blockhash
lastValidBlockHeight
transaction
}
}
Provide the accompanying data like this:
{
"authority": "pubkey", // Authority public key as a string
"profile": "pubkey", // Profile public key as a string
"delegateAuthority": "pubkey", // Delegate authority public key as a string
"payer": "pubkey", // Payer public key as a string
"platformData": {
"addAchievements": [int], // An array containing indexes of the achievements to add
"addXp": int, // Optional, how much XP to award to the player
"custom": {
"add": [
["key", "value"] // Optional, add any custom data to the profile, has to be passed in this format; example: ["location", "San Francisco, CA"]
],
"remove": ["string"] // Optional, remove any custom data from the profile, will remove the key-value pair
}
}
}