Skip to main content

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. Honeycomb Protocol supports Civic Passes for KYC/AML compliance and identity/uniqueness verification.

  • Profile: Profiles in Honeycomb Protocol allow users to separate their data according to different projects or applications, for example: social media and gaming. Each project the user engages with creates a specialized profile to store custom data, achievements, and XP for that project. Profiles are stored in a merkle tree for efficient storage and retrieval. We've used Solana's generalized compression to maximize cost savings while still enabling efficient data retrieval.

In summary, the same user can have different profiles for different apps within the Honeycomb Protocol. For example, a user might have one profile dedicated to a social media app, tracking posts, comments, and connections, while another profile is used for a game project to record scores, achievements, and in-game purchases.

Why use Honeycomb Profiles?

There are several reasons why developers prefer using Honeycomb Profiles:

  • Cost savings: We've designed Honeycomb Profiles to be so cost effective that even millions of profiles can be stored for a fraction of the cost of traditional PDA accounts and even databases.
  • Scalability: Scalability is a big concern for developers. When integrated with Honeycomb, your project can scale to millions (or even tens of millions) of users; we'll do the heavy lifting while you concentrate on building your app.
  • Easy retrieval: Despite the low cost, fetching your project's profiles is as simple as making one API call.
  • Custom data: Our profiles support custom data storage. You can store any data you want, like NFTs owned, user preferences, or any other data that's relevant to your project.
  • KYC/AML support: We've partnered with Civic make it easy for developers to verify their users' identities and even perform uniqueness checks.
  • Easy organization of data: Our profiles allow each User to have multiple “domains” where they can store relevant information to the respective app/game such as stats, games played, and scores.
  • Decentralization and interoperability: Honeycomb Profiles are decentralized and interoperable, meaning that they can be used across multiple projects and apps within the Honeycomb ecosystem.

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

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
});

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.

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",
},
});

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.

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
},
},
}
);

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.

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

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

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,
// }
}
});

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.

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
},
}
});

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.

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
},
}
});

After updating the profile, you'll need to fetch the profile again to access the updated data.

Find profile(s)

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,

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.

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"],
}
},
});