Skip to content

Commit

Permalink
nit: userdata
Browse files Browse the repository at this point in the history
  • Loading branch information
dalechyn committed Dec 25, 2024
1 parent a725931 commit 518c09c
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/core/Message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export function fromProtobuf(
///
///
if (message.data.type === MessageProtobuf.MessageType.USER_DATA_ADD)
return { type: 'userDataAdd', data: UserData.fromProtobuf(message) }
return { type: 'userDataAdd', data: UserData.fromMessageProtobuf(message) }
if (message.data.type === MessageProtobuf.MessageType.USERNAME_PROOF)
return {
type: 'usernameProof',
Expand Down
164 changes: 145 additions & 19 deletions src/core/UserData.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Hex } from 'ox'
import { toBinary } from '@bufbuild/protobuf'
import { create } from '@bufbuild/protobuf'
import { Hex, type Types } from 'ox'
import { BaseError } from 'ox/Errors'
import type { Omit } from 'ox/Internal'
import { FARCASTER_EPOCH_TIMESTAMP } from './Constants.js'
import type { GlobalErrorType } from './Error.js'
import * as Meta from './Meta.js'
import * as MessageProtobuf from './protobufs/message_pb.js'
Expand All @@ -8,6 +12,8 @@ export type UserData = {
meta: Meta.Meta
type: 'none' | 'pfp' | 'display' | 'bio' | 'url' | 'username' | 'location'
value: string
fid: bigint
timestamp: number
}

// @TODO: replace by our own BaseError
Expand All @@ -21,52 +27,172 @@ export class InvalidMessageTypeError extends BaseError {
}
}

export function fromMessageProtobuf(
message: fromMessageProtobuf.ParametersType,
): fromMessageProtobuf.ReturnType {
const meta = Meta.fromProtobuf(message)
// @TODO: separate error here
if (!message.data) throw new Error('`data` must be defined in Link message.')
if (message.data.body.case !== 'userDataBody')
throw new InvalidMessageTypeError({ hash: meta.hash })
return fromProtobuf({
body: message.data.body.value,
meta,
fid: message.data.fid,
timestamp: message.data.timestamp,
})
}

export declare namespace fromMessageProtobuf {
type ParametersType = MessageProtobuf.Message
type ReturnType = UserData
type ErrorType =
| InvalidMessageTypeError
| Meta.fromProtobuf.ErrorType
| GlobalErrorType
}

fromMessageProtobuf.parseError = (error: unknown) =>
error as fromMessageProtobuf.ErrorType

export function fromProtobuf(
message: fromProtobuf.ParametersType,
parameters: fromProtobuf.ParametersType,
): fromProtobuf.ReturnType {
// @TODO: error here
if (message.data?.body.case !== 'userDataBody')
throw new InvalidMessageTypeError({
hash: Hex.fromBytes(message.hash),
})
const type = (() => {
if (message.data.body.value.type === MessageProtobuf.UserDataType.PFP) {
if (parameters.body.type === MessageProtobuf.UserDataType.PFP) {
return 'pfp'
}
if (message.data.body.value.type === MessageProtobuf.UserDataType.BIO) {
if (parameters.body.type === MessageProtobuf.UserDataType.BIO) {
return 'bio'
}
if (message.data.body.value.type === MessageProtobuf.UserDataType.DISPLAY) {
if (parameters.body.type === MessageProtobuf.UserDataType.DISPLAY) {
return 'display'
}
if (message.data.body.value.type === MessageProtobuf.UserDataType.URL) {
if (parameters.body.type === MessageProtobuf.UserDataType.URL) {
return 'url'
}
if (
message.data.body.value.type === MessageProtobuf.UserDataType.USERNAME
) {
if (parameters.body.type === MessageProtobuf.UserDataType.USERNAME) {
return 'username'
}
if (
message.data.body.value.type === MessageProtobuf.UserDataType.LOCATION
) {
if (parameters.body.type === MessageProtobuf.UserDataType.LOCATION) {
return 'location'
}
return 'none'
})()
// @TODO: handle unexpeded type here?
return {
meta: Meta.fromProtobuf(message),
meta: parameters.meta,
type,
value: message.data.body.value.value,
value: parameters.body.value,
fid: parameters.fid,
timestamp: parameters.timestamp,
}
}

export declare namespace fromProtobuf {
type ParametersType = MessageProtobuf.Message
type ParametersType = {
body: MessageProtobuf.UserDataBody
meta: Meta.Meta
fid: bigint
timestamp: number
}
type ReturnType = UserData

type ErrorType = InvalidMessageTypeError | GlobalErrorType
}

fromProtobuf.parseError = (error: unknown) => error as fromProtobuf.ErrorType

export function toMessageDataProtobuf(
body: toMessageDataProtobuf.ParametersType,
): toMessageDataProtobuf.ReturnType {
return create(MessageProtobuf.MessageDataSchema, {
timestamp: body.timestamp - FARCASTER_EPOCH_TIMESTAMP,
type: MessageProtobuf.MessageType.USER_DATA_ADD,
fid: body.fid,
network: MessageProtobuf.FarcasterNetwork.MAINNET,
body: {
case: 'userDataBody',
value: toProtobuf(body),
},
})
}

export declare namespace toMessageDataProtobuf {
type ParametersType = Omit<UserData, 'meta'>
type ReturnType = MessageProtobuf.MessageData

type ErrorType = GlobalErrorType
}

toMessageDataProtobuf.parseError = (error: unknown) =>
error as toMessageDataProtobuf.ErrorType

export function toHex(body: toHex.ParametersType): toHex.ReturnType {
return Hex.fromBytes(
toBinary(MessageProtobuf.MessageDataSchema, toMessageDataProtobuf(body)),
)
}

export declare namespace toHex {
type ParametersType = Omit<UserData, 'meta'>
type ReturnType = Types.Hex
type ErrorType = GlobalErrorType
}

toHex.parseError = (error: unknown) => error as toHex.ErrorType

export function toMessageProtobuf(
parameters: toMessageProtobuf.ParametersType,
): toMessageProtobuf.ReturnType {
return create(MessageProtobuf.MessageSchema, {
...Meta.toProtobuf(
Meta.create({
dataBytes: toHex(parameters.data),
privateKey: parameters.privateKey,
}),
),
data: toMessageDataProtobuf(parameters.data),
})
}

export declare namespace toMessageProtobuf {
type ParametersType = {
data: Omit<UserData, 'meta'>
privateKey: Types.Hex
}
type ReturnType = MessageProtobuf.Message

// @TODO: errors
type ErrorType = GlobalErrorType
}

toMessageProtobuf.parseError = (error: unknown) =>
error as toMessageProtobuf.ErrorType

export function toProtobuf(
body: toProtobuf.ParametersType,
): toProtobuf.ReturnType {
return create(MessageProtobuf.UserDataBodySchema, {
type: (() => {
if (body.type === 'username') return MessageProtobuf.UserDataType.USERNAME
if (body.type === 'location') return MessageProtobuf.UserDataType.LOCATION
if (body.type === 'url') return MessageProtobuf.UserDataType.URL
if (body.type === 'bio') return MessageProtobuf.UserDataType.BIO
if (body.type === 'display') return MessageProtobuf.UserDataType.DISPLAY
if (body.type === 'pfp') return MessageProtobuf.UserDataType.PFP
throw new Error('unknown userdatabody type')
})(),
value: body.value,
})
}

export declare namespace toProtobuf {
type ParametersType = Omit<UserData, 'meta'>
type ReturnType = MessageProtobuf.UserDataBody

type ErrorType = GlobalErrorType
}

toProtobuf.parseError = (error: unknown) => error as toProtobuf.ErrorType
10 changes: 5 additions & 5 deletions src/core/actions/UserData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export async function get(
options?: CallOptions,
): Promise<get.ReturnType> {
const message = await client.connectRpcClient.getUserData(parameters, options)
return UserData.fromProtobuf(message)
return UserData.fromMessageProtobuf(message)
}

get.parseError = (error: unknown) => error as get.ErrorType
Expand All @@ -35,7 +35,7 @@ export declare namespace getAllUserDataMessagesByFid {
nextPageToken: Pagination.NextPageToken
}
// @TODO: proper error handling
type ErrorType = UserData.fromProtobuf.ErrorType | GlobalErrorType
type ErrorType = UserData.fromMessageProtobuf.ErrorType | GlobalErrorType
}
export async function getAllUserDataMessagesByFid(
client: Client.Client,
Expand All @@ -50,7 +50,7 @@ export async function getAllUserDataMessagesByFid(
options,
)
return {
datas: message.messages.map(UserData.fromProtobuf),
datas: message.messages.map(UserData.fromMessageProtobuf),
nextPageToken: Pagination.getPageToken(message.nextPageToken),
}
}
Expand Down Expand Up @@ -91,7 +91,7 @@ export declare namespace getByFid {
datas: UserData.UserData[]
nextPageToken: Pagination.NextPageToken
}
type ErrorType = UserData.fromProtobuf.ErrorType | GlobalErrorType
type ErrorType = UserData.fromMessageProtobuf.ErrorType | GlobalErrorType
}
export async function getByFid(
client: Client.Client,
Expand All @@ -106,7 +106,7 @@ export async function getByFid(
options,
)
return {
datas: message.messages.map(UserData.fromProtobuf),
datas: message.messages.map(UserData.fromMessageProtobuf),
nextPageToken: Pagination.getPageToken(message.nextPageToken),
}
}
Expand Down

0 comments on commit 518c09c

Please sign in to comment.