Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
1import trimify from "@hey/helpers/trimify";
2import type {
3 AccountOptions,
4 MetadataAttribute
5} from "@lens-protocol/metadata";
6import { MetadataAttributeType } from "@lens-protocol/metadata";
7
8type ExistingAttribute = {
9 key: string;
10 type: string;
11 value: string;
12};
13
14type ExistingMetadata = {
15 name?: string | null;
16 bio?: string | null;
17 picture?: string | null;
18 coverPicture?: string | null;
19 attributes?: ExistingAttribute[] | null;
20};
21
22type HasMetadata = {
23 metadata?: ExistingMetadata | null;
24};
25
26interface PrepareAccountMetadataInput {
27 attributes: Record<string, string | undefined>;
28 name?: string;
29 bio?: string;
30 picture?: string | undefined;
31 coverPicture?: string | undefined;
32}
33
34const prepareAccountMetadata = (
35 current: HasMetadata,
36 input: PrepareAccountMetadataInput
37): AccountOptions => {
38 const { name, bio, picture, coverPicture, attributes: attrs } = input;
39
40 const prevAttrs: MetadataAttribute[] =
41 current.metadata?.attributes?.map(({ key, type, value }) => ({
42 key,
43 type: (MetadataAttributeType as any)[type],
44 value
45 })) ?? [];
46
47 const keysToDelete = new Set(
48 Object.entries(attrs)
49 .filter(([, v]) => v === undefined)
50 .map(([key]) => key)
51 );
52
53 const newAttrs: MetadataAttribute[] = Object.entries(attrs)
54 .filter(([, v]) => v !== undefined)
55 .map(([key, value]) => ({
56 key,
57 type: MetadataAttributeType.STRING,
58 value: value as string
59 }));
60
61 const finalName = name || current.metadata?.name || undefined;
62 const finalBio = bio || current.metadata?.bio || undefined;
63
64 const mergedByKey = new Map<string, MetadataAttribute>(
65 prevAttrs.filter((a) => !keysToDelete.has(a.key)).map((a) => [a.key, a])
66 );
67
68 for (const a of newAttrs) {
69 mergedByKey.set(a.key, a);
70 }
71 const mergedAttrs = Array.from(mergedByKey.values());
72
73 const prepared: AccountOptions = {
74 ...(finalName ? { name: finalName } : {}),
75 ...(finalBio ? { bio: finalBio } : {}),
76 attributes: mergedAttrs.filter(
77 (a) => a.key !== "" && Boolean(trimify(a.value))
78 ),
79 coverPicture: coverPicture ?? current.metadata?.coverPicture ?? undefined,
80 picture: picture ?? current.metadata?.picture ?? undefined
81 };
82
83 return prepared;
84};
85
86export default prepareAccountMetadata;