Skip to content

Commit

Permalink
feat: add bio field to the Profile struct (#64)
Browse files Browse the repository at this point in the history
* Add bio field to the Profile struct

* Fix build error

* Update bio fields according to pr review

* Fix error check for minimum size

* refactor: clean up profile bio pr

---------

Co-authored-by: Bram Borggreve <beeman@beeman.nl>
  • Loading branch information
DogukanGun and beeman authored Nov 3, 2024
1 parent 3958ec5 commit 5dcca3f
Show file tree
Hide file tree
Showing 16 changed files with 110 additions and 4 deletions.
1 change: 1 addition & 0 deletions anchor/programs/pubkey-protocol/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ pub const MAX_URL_SIZE: usize = 100;
pub const MAX_PROVIDER_ID_SIZE: usize = 50;
pub const MAX_PROVIDER_NAME_SIZE: usize = 50;
pub const MAX_VECTOR_SIZE: u16 = u16::MAX;
pub const MAX_BIO_SIZE: usize = 256;
2 changes: 2 additions & 0 deletions anchor/programs/pubkey-protocol/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,6 @@ pub enum ProtocolError {
UnAuthorizedCommunityAuthority,
#[msg("Account is not a signer for this community")]
UnAuthorizedCommunitySigner,
#[msg("Biography too long. Maximum characters allowed: 256")]
InvalidBioSize,
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ pub fn profile_create(ctx: Context<ProfileCreate>, args: ProfileCreateArgs) -> R
avatar_url,
authorities: vec![authority],
identities: vec![set_primary_wallet],
bio: None,
});

profile.validate()?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ pub fn profile_update(
profile.avatar_url = new_avatar_url;
}

if let Some(new_bio) = args.new_bio {
require!(
new_bio.len() <= MAX_BIO_SIZE,
ProtocolError::InvalidBioSize
);
profile.bio = Some(new_bio);
}
profile.validate()?;

Ok(())
Expand All @@ -58,4 +65,5 @@ pub fn profile_update(
pub struct ProfileUpdateArgs {
pub new_name: Option<String>,
pub new_avatar_url: Option<String>,
pub new_bio: Option<String>,
}
10 changes: 10 additions & 0 deletions anchor/programs/pubkey-protocol/src/state/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub struct Profile {
pub authorities: Vec<Pubkey>,
// Identities user have added onto
pub identities: Vec<Identity>,
// Biography of the user
pub bio: Option<String>,
}

impl Profile {
Expand All @@ -34,6 +36,7 @@ impl Profile {
4 + MAX_USERNAME_SIZE +
4 + MAX_NAME_SIZE +
4 + MAX_URL_SIZE +
4 + MAX_BIO_SIZE +
32 + // fee_payer
authorities_size +
identities_size
Expand All @@ -43,6 +46,7 @@ impl Profile {
let avatar_url_len = self.avatar_url.len();
let identities_len = self.identities.len();
let authorities_len = self.authorities.len();
let bio_len = self.bio.as_ref().map_or(0, |b| b.len());

// Username
require!(
Expand Down Expand Up @@ -74,6 +78,12 @@ impl Profile {
identities_len <= MAX_VECTOR_SIZE.into(),
ProtocolError::MaxSizeReached
);

// Bio validation
require!(
bio_len <= MAX_BIO_SIZE,
ProtocolError::InvalidBioSize
);
for identity in self.identities.clone() {
identity.validate()?;
}
Expand Down
1 change: 1 addition & 0 deletions anchor/src/pubkey-protocol-exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export interface PubKeyProfile {
name: string
publicKey: PublicKeyString
username: string
bio: string | null
}

export interface PubKeyIdentity {
Expand Down
17 changes: 17 additions & 0 deletions anchor/target/idl/pubkey_protocol.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,11 @@
"code": 6041,
"name": "UnAuthorizedCommunitySigner",
"msg": "Account is not a signer for this community"
},
{
"code": 6042,
"name": "InvalidBioSize",
"msg": "Biography too long. Maximum characters allowed: 256"
}
],
"types": [
Expand Down Expand Up @@ -1922,6 +1927,12 @@
}
}
}
},
{
"name": "bio",
"type": {
"option": "string"
}
}
]
}
Expand Down Expand Up @@ -2042,6 +2053,12 @@
"type": {
"option": "string"
}
},
{
"name": "new_bio",
"type": {
"option": "string"
}
}
]
}
Expand Down
17 changes: 17 additions & 0 deletions anchor/target/types/pubkey_protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,11 @@ export type PubkeyProtocol = {
"code": 6041,
"name": "unAuthorizedCommunitySigner",
"msg": "Account is not a signer for this community"
},
{
"code": 6042,
"name": "invalidBioSize",
"msg": "Biography too long. Maximum characters allowed: 256"
}
],
"types": [
Expand Down Expand Up @@ -1928,6 +1933,12 @@ export type PubkeyProtocol = {
}
}
}
},
{
"name": "bio",
"type": {
"option": "string"
}
}
]
}
Expand Down Expand Up @@ -2048,6 +2059,12 @@ export type PubkeyProtocol = {
"type": {
"option": "string"
}
},
{
"name": "newBio",
"type": {
"option": "string"
}
}
]
}
Expand Down
1 change: 1 addition & 0 deletions anchor/tests/pubkey-protocol-profile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ describe('pubkey-protocol-profile', () => {
authority: aliceWalletOne.publicKey,
newName: 'Test Profile',
newAvatarUrl: getProfileAvatarUrl(`${username}_new`),
newBio: 'This is a test bio',
}
await program.methods
.profileUpdate(input)
Expand Down
30 changes: 30 additions & 0 deletions cli/src/commands/provision-sample-data-profiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ProfileCreateOptions,
ProfileIdentityAddOptions,
ProfileIdentityVerifyOptions,
ProfileUpdateOptions,
} from '@pubkey-protocol/sdk'
import { getConfig } from '../utils/get-config'
import { createOrGetConfig } from './create-or-get-config'
Expand All @@ -17,6 +18,7 @@ type ProvisionProfileIdentityVerify = Omit<
ProfileIdentityVerifyOptions,
'authority' | 'community' | 'feePayer' | 'username'
> & { community: string }
type ProvisionProfileUpdate = Omit<ProfileUpdateOptions, 'authority' | 'community' | 'feePayer' | 'username'>

interface ProfileAuthority {
publicKey: string
Expand All @@ -27,6 +29,7 @@ export interface ProfileMapItem {
authority: ProfileAuthority
create: ProvisionProfileCreate
identities?: ProvisionProfileIdentityAdd[]
update?: ProvisionProfileUpdate
verifications?: ProvisionProfileIdentityVerify[]
}
export type ProfileProvisionMap = Record<string, ProfileMapItem>
Expand All @@ -42,6 +45,9 @@ export const profileProvisionMap: ProfileProvisionMap = {
name: 'Alice',
avatarUrl: `https://api.dicebear.com/9.x/bottts-neutral/svg?seed=alice`,
},
update: {
bio: "Alice's updated bio",
},
identities: [
{ provider: IdentityProvider.Github, providerId: '123123', name: 'pubkey_alice' },
{ provider: IdentityProvider.Discord, providerId: '123123', name: 'pubkey_alice' },
Expand Down Expand Up @@ -70,6 +76,9 @@ export const profileProvisionMap: ProfileProvisionMap = {
name: 'Bob',
avatarUrl: `https://api.dicebear.com/9.x/bottts-neutral/svg?seed=bob`,
},
update: {
bio: "Bob's updated bio",
},
identities: [
{ provider: IdentityProvider.Discord, providerId: '456456', name: 'pubkey_bob' },
{ provider: IdentityProvider.Github, providerId: '456456', name: 'pubkey_bob' },
Expand Down Expand Up @@ -125,6 +134,27 @@ export async function provisionSampleDataProfiles(options: ProvisionSampleDataOp
await sleep(options.timeout)
}

const profilesUpdate = Object.keys(profileProvisionMap)
.filter((username) => Object.keys(profileProvisionMap[username].update ?? {}).length > 0)
.map((username) => ({ update: profileProvisionMap[username].update, username }))

for (const { update, username } of profilesUpdate) {
const authority = getKeypairFromByteArray(profileProvisionMap[username].authority.secretKey)

const transaction = await sdk.profileUpdate({
authority: authority.publicKey,
community: defaultCommunity.publicKey,
feePayer: communityAuthority.publicKey,
username,
...update,
})
transaction.sign([communityAuthority, authority])
const s = await connection.sendRawTransaction(transaction.serialize(), { skipPreflight: true })
console.log(` -> Updated profile: ${username}`, s)
console.log(getExplorerUrl(`tx/${s}?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899`, cluster, endpoint))
await sleep(options.timeout)
}

const profilesIdentitiesAdd = Object.keys(profileProvisionMap)
.filter((username) => Object.keys(profileProvisionMap[username].identities ?? []).length > 0)
.map((username) => ({ identities: profileProvisionMap[username].identities, username }))
Expand Down
5 changes: 3 additions & 2 deletions sdk/src/lib/pubkey-protocol-sdk-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,13 @@ export interface ProfileIdentityVerifyOptions {
}

export interface ProfileUpdateOptions {
avatarUrl: string
avatarUrl?: string
authority: PublicKeyString
community: PublicKeyString
feePayer: PublicKeyString
name: string
name?: string
username: string
bio?: string
}

export interface PubKeyProfileSdkOptions {
Expand Down
3 changes: 2 additions & 1 deletion sdk/src/lib/pubkey-protocol-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,8 @@ export class PubKeyProtocolSdk {
const ix = await this.program.methods
.profileUpdate({
newAvatarUrl: options.avatarUrl ?? null,
newName: options.name,
newName: options.name ?? null,
newBio: options.bio ?? null,
})
.accountsStrict({
authority,
Expand Down
2 changes: 2 additions & 0 deletions web/src/app/features/dev/data-access/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export function createDevProfile({
name: string
publicKey: PublicKeyString
username?: string
bio?: string
}): PubKeyProfile {
const username = props.username ?? slugify(name)
const avatarUrl = getAvatarUrlProfile(username)
Expand All @@ -68,6 +69,7 @@ export function createDevProfile({
username,
authorities: [],
avatarUrl,
bio: props.bio ?? null,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ export function PubkeyProtocolUiProfileCard({
<Group>
<Code>{profile.username}</Code>
</Group>

{profile.bio && (
<Group>
<Code>{profile.bio}</Code>
</Group>
)}
{signAuthority ? (
<UiStack mt="md">
<PubkeyProtocolUiProfileCardIdentities
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ export function PubkeyProtocolUiProfileListItem({
<Group>
<Code>{profile.username}</Code>
</Group>
{profile.bio && (
<Group>
<Code>{profile.bio}</Code>
</Group>
)}
{children}
</Stack>
</Stack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ export function PubkeyProtocolUiProfile({
<Group>
<Code>{profile.username}</Code>
</Group>
{profile.bio && (
<Group>
<Code>{profile.bio}</Code>
</Group>
)}
<Stack gap="xs" mt="md">
{profile.identities?.map((identity) => (
<UiCard key={`${identity.provider}-${identity.providerId}`}>
Expand Down

0 comments on commit 5dcca3f

Please sign in to comment.