Skip to content

Commit

Permalink
feat: add text input frame field (#1639)
Browse files Browse the repository at this point in the history
  • Loading branch information
sanjayprabhu authored Feb 2, 2024
1 parent de63c47 commit 362f580
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 13 deletions.
7 changes: 7 additions & 0 deletions .changeset/smooth-bottles-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@farcaster/hub-nodejs": patch
"@farcaster/hub-web": patch
"@farcaster/core": patch
---

feat: add text input frame field
22 changes: 20 additions & 2 deletions packages/core/src/protobufs/generated/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,11 @@ export interface FrameActionBody {
/** The index of the button pressed (1-4) */
buttonIndex: number;
/** The cast which contained the frame url */
castId: CastId | undefined;
castId:
| CastId
| undefined;
/** Text input from the user, if present */
inputText: Uint8Array;
}

function createBaseMessage(): Message {
Expand Down Expand Up @@ -1763,7 +1767,7 @@ export const LinkBody = {
};

function createBaseFrameActionBody(): FrameActionBody {
return { url: new Uint8Array(), buttonIndex: 0, castId: undefined };
return { url: new Uint8Array(), buttonIndex: 0, castId: undefined, inputText: new Uint8Array() };
}

export const FrameActionBody = {
Expand All @@ -1777,6 +1781,9 @@ export const FrameActionBody = {
if (message.castId !== undefined) {
CastId.encode(message.castId, writer.uint32(26).fork()).ldelim();
}
if (message.inputText.length !== 0) {
writer.uint32(34).bytes(message.inputText);
}
return writer;
},

Expand Down Expand Up @@ -1808,6 +1815,13 @@ export const FrameActionBody = {

message.castId = CastId.decode(reader, reader.uint32());
continue;
case 4:
if (tag != 34) {
break;
}

message.inputText = reader.bytes();
continue;
}
if ((tag & 7) == 4 || tag == 0) {
break;
Expand All @@ -1822,6 +1836,7 @@ export const FrameActionBody = {
url: isSet(object.url) ? bytesFromBase64(object.url) : new Uint8Array(),
buttonIndex: isSet(object.buttonIndex) ? Number(object.buttonIndex) : 0,
castId: isSet(object.castId) ? CastId.fromJSON(object.castId) : undefined,
inputText: isSet(object.inputText) ? bytesFromBase64(object.inputText) : new Uint8Array(),
};
},

Expand All @@ -1831,6 +1846,8 @@ export const FrameActionBody = {
(obj.url = base64FromBytes(message.url !== undefined ? message.url : new Uint8Array()));
message.buttonIndex !== undefined && (obj.buttonIndex = Math.round(message.buttonIndex));
message.castId !== undefined && (obj.castId = message.castId ? CastId.toJSON(message.castId) : undefined);
message.inputText !== undefined &&
(obj.inputText = base64FromBytes(message.inputText !== undefined ? message.inputText : new Uint8Array()));
return obj;
},

Expand All @@ -1845,6 +1862,7 @@ export const FrameActionBody = {
message.castId = (object.castId !== undefined && object.castId !== null)
? CastId.fromPartial(object.castId)
: undefined;
message.inputText = object.inputText ?? new Uint8Array();
return message;
},
};
Expand Down
35 changes: 34 additions & 1 deletion packages/core/src/validations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import * as validations from "./validations";
import { makeVerificationAddressClaim } from "./verifications";
import { UserDataType, UserNameType } from "@farcaster/hub-nodejs";
import { defaultL1PublicClient } from "./eth/clients";
import { optimism } from "viem/chains";
import { jest } from "@jest/globals";

const signer = Factories.Ed25519Signer.build();
Expand Down Expand Up @@ -1043,3 +1042,37 @@ describe("validateMessageData", () => {
});
});
});

describe("validateFrameActionBody", () => {
test("succeeds", async () => {
const body = Factories.FrameActionBody.build({
buttonIndex: 1,
url: Buffer.from("https://example.com"),
castId: { fid: Factories.Fid.build(), hash: Factories.MessageHash.build() },
});
const result = validations.validateFrameActionBody(body);
expect(result.isOk()).toBeTruthy();
});

test("fails when url is missing", async () => {
const body = Factories.FrameActionBody.build({
url: Buffer.from(""),
});
const result = validations.validateFrameActionBody(body);
expect(result._unsafeUnwrapErr().message).toMatch("invalid url");
});
test("fails when url is too long", async () => {
const body = Factories.FrameActionBody.build({
url: Buffer.from(faker.datatype.string(257)),
});
const result = validations.validateFrameActionBody(body);
expect(result._unsafeUnwrapErr().message).toMatch("invalid url");
});
test("fails when text input is too long", async () => {
const body = Factories.FrameActionBody.build({
inputText: Buffer.from(faker.datatype.string(257)),
});
const result = validations.validateFrameActionBody(body);
expect(result._unsafeUnwrapErr().message).toMatch("invalid input text");
});
});
21 changes: 15 additions & 6 deletions packages/core/src/validations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -668,12 +668,11 @@ export const validateFrameActionBody = (body: protobufs.FrameActionBody): HubRes
return err(new HubError("bad_request.validation_failure", "invalid button index"));
}

if (body.url !== undefined) {
if (body.url.length === 0 || body.url.length > 256) {
return err(new HubError("bad_request.validation_failure", "invalid url"));
}
} else {
return err(new HubError("bad_request.validation_failure", "url provided"));
if (validateBytesAsString(body.url, 256, true).isErr()) {
return err(new HubError("bad_request.validation_failure", "invalid url"));
}
if (validateBytesAsString(body.inputText, 256).isErr()) {
return err(new HubError("bad_request.validation_failure", "invalid input text"));
}

if (body.castId !== undefined) {
Expand All @@ -686,6 +685,16 @@ export const validateFrameActionBody = (body: protobufs.FrameActionBody): HubRes
return ok(body);
};

const validateBytesAsString = (byteArray: Uint8Array, maxLength: number, required = false) => {
if (required && byteArray.length === 0) {
return err(new HubError("bad_request.validation_failure", "value is required"));
}
if (byteArray.length > maxLength) {
return err(new HubError("bad_request.validation_failure", "value is too long"));
}
return ok(byteArray);
};

export const validateUserDataType = (type: number): HubResult<protobufs.UserDataType> => {
if (
!Object.values(protobufs.UserDataType).includes(type) ||
Expand Down
22 changes: 20 additions & 2 deletions packages/hub-nodejs/src/generated/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,11 @@ export interface FrameActionBody {
/** The index of the button pressed (1-4) */
buttonIndex: number;
/** The cast which contained the frame url */
castId: CastId | undefined;
castId:
| CastId
| undefined;
/** Text input from the user, if present */
inputText: Uint8Array;
}

function createBaseMessage(): Message {
Expand Down Expand Up @@ -1763,7 +1767,7 @@ export const LinkBody = {
};

function createBaseFrameActionBody(): FrameActionBody {
return { url: new Uint8Array(), buttonIndex: 0, castId: undefined };
return { url: new Uint8Array(), buttonIndex: 0, castId: undefined, inputText: new Uint8Array() };
}

export const FrameActionBody = {
Expand All @@ -1777,6 +1781,9 @@ export const FrameActionBody = {
if (message.castId !== undefined) {
CastId.encode(message.castId, writer.uint32(26).fork()).ldelim();
}
if (message.inputText.length !== 0) {
writer.uint32(34).bytes(message.inputText);
}
return writer;
},

Expand Down Expand Up @@ -1808,6 +1815,13 @@ export const FrameActionBody = {

message.castId = CastId.decode(reader, reader.uint32());
continue;
case 4:
if (tag != 34) {
break;
}

message.inputText = reader.bytes();
continue;
}
if ((tag & 7) == 4 || tag == 0) {
break;
Expand All @@ -1822,6 +1836,7 @@ export const FrameActionBody = {
url: isSet(object.url) ? bytesFromBase64(object.url) : new Uint8Array(),
buttonIndex: isSet(object.buttonIndex) ? Number(object.buttonIndex) : 0,
castId: isSet(object.castId) ? CastId.fromJSON(object.castId) : undefined,
inputText: isSet(object.inputText) ? bytesFromBase64(object.inputText) : new Uint8Array(),
};
},

Expand All @@ -1831,6 +1846,8 @@ export const FrameActionBody = {
(obj.url = base64FromBytes(message.url !== undefined ? message.url : new Uint8Array()));
message.buttonIndex !== undefined && (obj.buttonIndex = Math.round(message.buttonIndex));
message.castId !== undefined && (obj.castId = message.castId ? CastId.toJSON(message.castId) : undefined);
message.inputText !== undefined &&
(obj.inputText = base64FromBytes(message.inputText !== undefined ? message.inputText : new Uint8Array()));
return obj;
},

Expand All @@ -1845,6 +1862,7 @@ export const FrameActionBody = {
message.castId = (object.castId !== undefined && object.castId !== null)
? CastId.fromPartial(object.castId)
: undefined;
message.inputText = object.inputText ?? new Uint8Array();
return message;
},
};
Expand Down
22 changes: 20 additions & 2 deletions packages/hub-web/src/generated/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,11 @@ export interface FrameActionBody {
/** The index of the button pressed (1-4) */
buttonIndex: number;
/** The cast which contained the frame url */
castId: CastId | undefined;
castId:
| CastId
| undefined;
/** Text input from the user, if present */
inputText: Uint8Array;
}

function createBaseMessage(): Message {
Expand Down Expand Up @@ -1763,7 +1767,7 @@ export const LinkBody = {
};

function createBaseFrameActionBody(): FrameActionBody {
return { url: new Uint8Array(), buttonIndex: 0, castId: undefined };
return { url: new Uint8Array(), buttonIndex: 0, castId: undefined, inputText: new Uint8Array() };
}

export const FrameActionBody = {
Expand All @@ -1777,6 +1781,9 @@ export const FrameActionBody = {
if (message.castId !== undefined) {
CastId.encode(message.castId, writer.uint32(26).fork()).ldelim();
}
if (message.inputText.length !== 0) {
writer.uint32(34).bytes(message.inputText);
}
return writer;
},

Expand Down Expand Up @@ -1808,6 +1815,13 @@ export const FrameActionBody = {

message.castId = CastId.decode(reader, reader.uint32());
continue;
case 4:
if (tag != 34) {
break;
}

message.inputText = reader.bytes();
continue;
}
if ((tag & 7) == 4 || tag == 0) {
break;
Expand All @@ -1822,6 +1836,7 @@ export const FrameActionBody = {
url: isSet(object.url) ? bytesFromBase64(object.url) : new Uint8Array(),
buttonIndex: isSet(object.buttonIndex) ? Number(object.buttonIndex) : 0,
castId: isSet(object.castId) ? CastId.fromJSON(object.castId) : undefined,
inputText: isSet(object.inputText) ? bytesFromBase64(object.inputText) : new Uint8Array(),
};
},

Expand All @@ -1831,6 +1846,8 @@ export const FrameActionBody = {
(obj.url = base64FromBytes(message.url !== undefined ? message.url : new Uint8Array()));
message.buttonIndex !== undefined && (obj.buttonIndex = Math.round(message.buttonIndex));
message.castId !== undefined && (obj.castId = message.castId ? CastId.toJSON(message.castId) : undefined);
message.inputText !== undefined &&
(obj.inputText = base64FromBytes(message.inputText !== undefined ? message.inputText : new Uint8Array()));
return obj;
},

Expand All @@ -1845,6 +1862,7 @@ export const FrameActionBody = {
message.castId = (object.castId !== undefined && object.castId !== null)
? CastId.fromPartial(object.castId)
: undefined;
message.inputText = object.inputText ?? new Uint8Array();
return message;
},
};
Expand Down
1 change: 1 addition & 0 deletions protobufs/schemas/message.proto
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,5 @@ message FrameActionBody {
bytes url = 1; // URL of the Frame triggering the action
uint32 button_index = 2; // The index of the button pressed (1-4)
CastId cast_id = 3; // The cast which contained the frame url
bytes input_text = 4; // Text input from the user, if present
}

0 comments on commit 362f580

Please sign in to comment.