Hey is a decentralized and permissionless social media app built with Lens Protocol 🌿

refactor: replace getAddr with getAccount in ENS routes and update CCIP resolver to use getLensAccount

yoginth.com 6914e0a3 5d8bbca8

verified
+114 -50
+2 -2
apps/api/src/routes/ens/index.ts
··· 1 1 import { Hono } from "hono"; 2 2 import ccip from "./resolver/ccip"; 3 - import getAddr from "./resolver/getAddr"; 3 + import getAccount from "./resolver/getAccount"; 4 4 5 5 const app = new Hono(); 6 6 7 7 app.get("/ccip/:sender/:data", ccip); 8 - app.get("/addr", getAddr); 8 + app.get("/account", getAccount); 9 9 10 10 export default app;
+41 -4
apps/api/src/routes/ens/resolver/ccip.ts
··· 1 1 import type { Context } from "hono"; 2 2 import { decodeFunctionData, encodeAbiParameters, type Hex } from "viem"; 3 - import getLensAddress from "@/utils/lensAddress"; 3 + import getLensAccount from "@/utils/getLensAccount"; 4 4 5 5 const resolverAbi = [ 6 6 { ··· 56 56 if (!label || label.includes(".")) 57 57 return ctx.json({ error: "Invalid label" }, 400); 58 58 59 - const address = await getLensAddress(label); 59 + const account = await getLensAccount(label); 60 60 61 61 const selector = (inner as string).slice(0, 10).toLowerCase(); 62 62 let result: Hex | null = null; 63 63 64 64 if (selector === "0x3b3b57de") { 65 - const ret = encodeAbiParameters([{ type: "address" }], [address]); 65 + const ret = encodeAbiParameters([{ type: "address" }], [account.address]); 66 66 result = ret as Hex; 67 67 } else if (selector === "0xf1cb7e06") { 68 - const addressBytes = address.toLowerCase() as Hex; 68 + const addressBytes = account.address.toLowerCase() as Hex; 69 69 const raw = `0x${addressBytes.slice(2)}` as Hex; 70 70 const ret = encodeAbiParameters([{ type: "bytes" }], [raw]); 71 71 result = ret as Hex; 72 + } else if (selector === "0x59d1d43c") { 73 + const textAbi = [ 74 + { 75 + inputs: [ 76 + { name: "node", type: "bytes32" }, 77 + { name: "key", type: "string" } 78 + ], 79 + name: "text", 80 + outputs: [{ type: "string" }], 81 + stateMutability: "view", 82 + type: "function" 83 + } 84 + ] as const; 85 + 86 + try { 87 + const decodedText = decodeFunctionData({ 88 + abi: textAbi, 89 + data: inner as Hex 90 + }) as any; 91 + const key = (decodedText.args?.[1] as string)?.toLowerCase(); 92 + 93 + let value = ""; 94 + if (key === "name") { 95 + value = account.name ?? label; 96 + } else if (key === "avatar") { 97 + value = account.avatar ?? ""; 98 + } else if (key === "bio" || key === "description") { 99 + value = account.bio ?? ""; 100 + } else { 101 + value = ""; 102 + } 103 + 104 + const ret = encodeAbiParameters([{ type: "string" }], [value]); 105 + result = ret as Hex; 106 + } catch { 107 + return ctx.json({ error: "Malformed text calldata" }, 400); 108 + } 72 109 } else { 73 110 return ctx.json({ error: "Unsupported function" }, 400); 74 111 }
+23
apps/api/src/routes/ens/resolver/getAccount.ts
··· 1 + import type { Context } from "hono"; 2 + import getLensAccount from "@/utils/getLensAccount"; 3 + 4 + const getAccount = async (ctx: Context) => { 5 + const name = ctx.req.query("name"); 6 + if (!name) return ctx.json({ error: "Missing name" }, 400); 7 + 8 + const lower = name.toLowerCase(); 9 + if (!lower.endsWith(".hey.xyz")) { 10 + return ctx.json({ error: "Unsupported domain" }, 400); 11 + } 12 + 13 + const label = lower.split(".hey.xyz")[0]; 14 + if (!label || label.includes(".")) { 15 + return ctx.json({ error: "Invalid label" }, 400); 16 + } 17 + 18 + const account = await getLensAccount(label); 19 + 20 + return ctx.json({ account }); 21 + }; 22 + 23 + export default getAccount;
-21
apps/api/src/routes/ens/resolver/getAddr.ts
··· 1 - import type { Context } from "hono"; 2 - import getLensAddress from "@/utils/lensAddress"; 3 - 4 - const getAddr = async (ctx: Context) => { 5 - const name = ctx.req.query("name"); 6 - if (!name) return ctx.json({ error: "Missing name" }, 400); 7 - 8 - const lower = name.toLowerCase(); 9 - if (!lower.endsWith(".hey.xyz")) 10 - return ctx.json({ error: "Unsupported domain" }, 400); 11 - 12 - const label = lower.split(".hey.xyz")[0]; 13 - if (!label || label.includes(".")) 14 - return ctx.json({ error: "Invalid label" }, 400); 15 - 16 - const address = await getLensAddress(label); 17 - 18 - return ctx.json({ address }); 19 - }; 20 - 21 - export default getAddr;
+48
apps/api/src/utils/getLensAccount.ts
··· 1 + import getAccount from "@hey/helpers/getAccount"; 2 + import getAvatar from "@hey/helpers/getAvatar"; 3 + import { AccountDocument, type AccountFragment } from "@hey/indexer"; 4 + import apolloClient from "@hey/indexer/apollo/client"; 5 + import type { Hex } from "viem"; 6 + 7 + const getLensAccount = async ( 8 + handle: string 9 + ): Promise<{ 10 + address: Hex; 11 + name: string; 12 + avatar: string; 13 + bio: string; 14 + }> => { 15 + try { 16 + const { data } = await apolloClient.query<{ 17 + account: AccountFragment; 18 + }>({ 19 + fetchPolicy: "no-cache", 20 + query: AccountDocument, 21 + variables: { request: { username: { localName: handle } } } 22 + }); 23 + 24 + const address = data.account.owner; 25 + if (!address) 26 + return { 27 + address: "0x0000000000000000000000000000000000000000", 28 + avatar: "", 29 + bio: "", 30 + name: "" 31 + }; 32 + return { 33 + address: address.toLowerCase() as Hex, 34 + avatar: getAvatar(data.account), 35 + bio: data.account.metadata?.bio ?? "", 36 + name: getAccount(data.account).name 37 + }; 38 + } catch { 39 + return { 40 + address: "0x0000000000000000000000000000000000000000", 41 + avatar: "", 42 + bio: "", 43 + name: "" 44 + }; 45 + } 46 + }; 47 + 48 + export default getLensAccount;
-23
apps/api/src/utils/lensAddress.ts
··· 1 - import { AccountDocument, type AccountFragment } from "@hey/indexer"; 2 - import apolloClient from "@hey/indexer/apollo/client"; 3 - import type { Hex } from "viem"; 4 - 5 - const getLensAddress = async (handle: string): Promise<Hex> => { 6 - try { 7 - const { data } = await apolloClient.query<{ 8 - acount: AccountFragment; 9 - }>({ 10 - fetchPolicy: "no-cache", 11 - query: AccountDocument, 12 - variables: { request: { username: { localName: handle } } } 13 - }); 14 - 15 - const address = data.acount.owner; 16 - if (!address) return "0x0000000000000000000000000000000000000000"; 17 - return address.toLowerCase() as Hex; 18 - } catch { 19 - return "0x0000000000000000000000000000000000000000"; 20 - } 21 - }; 22 - 23 - export default getLensAddress;