From 3f31fb5c620aa8d1d6347df05342e3760489a9b6 Mon Sep 17 00:00:00 2001 From: douglasacost Date: Mon, 5 May 2025 20:41:57 +0200 Subject: [PATCH 1/3] Refactor buildTypedData function to accept a Record type for value parameter. Implement new endpoint for setting text records with enhanced validation for name, key, and value fields. Update existing routes to accommodate new data structure and validation logic. --- clk-gateway/src/helpers.ts | 2 +- clk-gateway/src/routes/names.ts | 92 ++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/clk-gateway/src/helpers.ts b/clk-gateway/src/helpers.ts index 2b3bca3..f543071 100644 --- a/clk-gateway/src/helpers.ts +++ b/clk-gateway/src/helpers.ts @@ -367,7 +367,7 @@ const defaultTypes = { ], }; export function buildTypedData( - value: { name: string; email: string }, + value: Record, types: Record = defaultTypes ) { /* Representative domain for the Name Service, this is a placeholder */ diff --git a/clk-gateway/src/routes/names.ts b/clk-gateway/src/routes/names.ts index 36d1c4f..d0fe115 100644 --- a/clk-gateway/src/routes/names.ts +++ b/clk-gateway/src/routes/names.ts @@ -219,8 +219,9 @@ router.post( const typedData = buildTypedData( { - name: data.name, - email: data.email, + name, + key: data.key, + value: data.value, }, { TextRecord: [ @@ -281,6 +282,93 @@ router.post( }) ); +// POST /name/set-text-record/message +router.post( + "/set-text-record/message", + [ + body("name") + .isLowercase() + .withMessage("Name must be a lowercase string") + .isFQDN() + .withMessage("Name must be a fully qualified domain name") + .custom((name) => { + const [sub, domain, tld] = name.split("."); + if ( + ![ + `${clickNSDomain}.${parentTLD}`, + `${nodleNSDomain}.${parentTLD}`, + ].includes(`${domain}.${tld}`) + ) { + return false; + } + + const subHash = keccak256(toUtf8Bytes(sub)); + if (reservedHashes.includes(subHash)) { + return false; + } + + return true; + }) + .withMessage("Invalid domain or tld or reserved subdomain") + .custom((name) => { + const [sub] = name.split("."); + if (sub.length < 5) { + return false; + } + return true; + }) + .withMessage( + "Current available subdomain names are limited to those with at least 5 characters" + ), + body("key") + .isString() + .isLength({ min: 4, max: 20 }) + .withMessage("Key must be between 4 and 20 characters"), + body("value") + .isString() + .isLength({ min: 1, max: 256 }) + .withMessage("Value must be between 1 and 256 characters"), + body("owner") + ], + asyncHandler(async (req, res) => { + const result = validationResult(req); + if (!result.isEmpty()) { + throw new HttpError( + result + .array() + .map((error) => error.msg) + .join(", "), + 400 + ); + } + const data = matchedData(req); + + const typedData = buildTypedData({ + name: data.name, + key: data.key, + value: data.value, + }, { + TextRecord: [ + { + name: "name", + type: "string", + }, + { + name: "key", + type: "string", + }, + { + name: "value", + type: "string", + }, + ], + }); + res.status(200).send({ + typedData, + }); + }) +); + // POST /name/register/message router.post( "/register/message", From c21a186785f9c39bedae88d5fbbd1ee9f77f6b93 Mon Sep 17 00:00:00 2001 From: douglasacost Date: Wed, 7 May 2025 18:12:10 +0200 Subject: [PATCH 2/3] buildTypedData updated now handle EIP712Domain and primaryType for more strict signers --- clk-gateway/src/helpers.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/clk-gateway/src/helpers.ts b/clk-gateway/src/helpers.ts index f543071..104ea1d 100644 --- a/clk-gateway/src/helpers.ts +++ b/clk-gateway/src/helpers.ts @@ -377,7 +377,17 @@ export function buildTypedData( chainId: Number(process.env.L2_CHAIN_ID!), }; - return { types, domain, value }; + const domainTypes = { + EIP712Domain: [ + { name: "name", type: "string" }, + { name: "version", type: "string" }, + { name: "chainId", type: "uint256" }, + ], + }; + + const primaryType = Object.keys(types)?.[0] || "Transaction"; + + return { types: { ...domainTypes, ...types }, domain, value, primaryType }; } /** From 96a3edbeba48a88539fc3abc1963475566a1448e Mon Sep 17 00:00:00 2001 From: douglasacost Date: Wed, 7 May 2025 19:01:17 +0200 Subject: [PATCH 3/3] add optional email to buildTypedData, return also useful data to client --- clk-gateway/src/routes/names.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/clk-gateway/src/routes/names.ts b/clk-gateway/src/routes/names.ts index d0fe115..f0dc445 100644 --- a/clk-gateway/src/routes/names.ts +++ b/clk-gateway/src/routes/names.ts @@ -97,12 +97,12 @@ router.post( ); } const data = matchedData(req); - const [name, sub] = data.name.split("."); + const [name, sub, tld] = data.name.split("."); const owner = getAddress(data.owner); const typedData = buildTypedData({ name: data.name, - email: data.email, + email: data.email || "example@not-valid.com", }); const isValidSignature = validateSignature({ @@ -140,6 +140,7 @@ router.post( .setCustomUserClaims(decodedToken.uid, { subDomain: sub }); res.status(200).send({ txHash: receipt.hash, + name: `${name}.${sub}.${tld}`, }); }) ); @@ -278,6 +279,8 @@ router.post( res.status(200).send({ txHash: receipt.hash, + key: data.key, + value: data.value, }); }) ); @@ -425,7 +428,7 @@ router.post( const typedData = buildTypedData({ name: data.name, - email: data.email, + email: data.email || "example@not-valid.com", }); res.status(200).send({