UNPKG

@guildxyz/types

Version:

Types related to the Guild.xyz API

216 lines (197 loc) 5.86 kB
import { z } from "zod"; import { ErrorMessages, NFTRewardSupportedChains, PinSupportedChains, } from "../consts"; import { createZodSafeEnumValues, nonEmptyRefine } from "../utils"; import { AnyAddressSchema, ChainSchema, EvmAddressSchema, PositiveInteger, } from "./common"; const DiscordGuildRewardSchema = z.object({ platformName: z.literal("DISCORD"), platformGuildData: z .object({ inviteChannel: z.string().optional(), // Custom invite link, can be modified on our frontend invite: z.string().optional(), joinButton: z.boolean().optional(), needCaptcha: z.boolean().optional(), name: z.string().optional(), }) .default({}), }); const TelegramGuildRewardSchema = z.object({ platformName: z.literal("TELEGRAM"), }); const GitHubGuildRewardSchema = z.object({ platformName: z.literal("GITHUB"), platformGuildData: z .object({ // Optional, because we don't need to send it when creating a reward, but our backend will save this data here platformUserId: z.number().int().optional(), }) .default({}), }); const GoogleGuildRewardSchema = z.object({ platformName: z.literal("GOOGLE"), platformGuildData: z.object({ role: z .enum(["reader", "commenter", "writer"]) .optional() .default("reader"), mimeType: z.string(), iconLink: z.string(), }), }); export const ContractCallGuildRewardSchema = z.object({ platformName: z.literal("CONTRACT_CALL"), platformGuildData: z.object({ chain: ChainSchema.extract(NFTRewardSupportedChains), contractAddress: EvmAddressSchema, function: z.enum([ "function claim(address payToken, address receiver, bytes calldata signature) payable", "function claim(uint256 amount, address receiver, uint256 userId, uint256 signedAt, bytes calldata signature) payable", ]), argsToSign: z.array(z.string()), name: z.string().optional(), symbol: z.string().optional(), imageUrl: z.string().optional(), description: z.string().optional(), }), }); const UniqueTextGuildRewardSchema = z.object({ platformName: z.literal("UNIQUE_TEXT"), platformGuildData: z.object({ texts: z.array(z.string()), name: z.string().optional(), imageUrl: z.string().optional(), }), }); const TextGuildRewardSchema = z.object({ platformName: z.literal("TEXT"), platformGuildData: z.object({ text: z.string(), name: z.string().optional(), imageUrl: z.string().optional(), }), }); const GuildPinGuildRewardSchema = z.object({ platformName: z.literal("GUILD_PIN"), platformGuildData: z.object({ pinChain: z.enum( createZodSafeEnumValues(Object.values(PinSupportedChains)) ), contractAddress: AnyAddressSchema, }), }); const PointsGuildRewardSchema = z.object({ platformName: z.literal("POINTS"), platformGuildData: z .object({ name: z.string().optional(), imageUrl: z.string().optional(), }) .default({}), }); const PoapGuildRewardSchema = z.object({ platformName: z.literal("POAP"), platformGuildData: z.object({ fancyId: z.string(), eventId: z.number(), name: z.string().optional(), imageUrl: z.string().optional(), }), }); const FormGuildRewardSchema = z.object({ platformName: z.literal("FORM"), platformGuildData: z.object({ formId: z.number(), }), }); const GatherTownGuildRewardSchema = z.object({ platformName: z.literal("GATHER_TOWN"), platformGuildData: z.object({ name: z.string(), gatherSpaceId: z.string(), gatherApiKey: z.string(), gatherAffiliation: z.string(), gatherRole: z.string(), }), }); const ERC20GuildRewardSchema = z.object({ platformName: z.literal("ERC20"), platformGuildData: z.object({ poolId: z.number(), chain: ChainSchema.extract([ "BASE_MAINNET", "BSC", "MANTLE", "OPTIMISM", "POLYGON", "SEPOLIA", ]), contractAddress: EvmAddressSchema, name: z.string(), imageUrl: z.string(), description: z.string(), tokenAddress: EvmAddressSchema, }), }); const FarcasterChannelGuildRewardSchema = z.object({ platformName: z.literal("FARCASTER_CHANNEL"), platformGuildData: z.object({ moderatorUserId: PositiveInteger, }), }); const BasicGuildRewardSchema = z .discriminatedUnion("platformName", [ DiscordGuildRewardSchema, TelegramGuildRewardSchema, GitHubGuildRewardSchema, GoogleGuildRewardSchema, ContractCallGuildRewardSchema, UniqueTextGuildRewardSchema, TextGuildRewardSchema, GuildPinGuildRewardSchema, PointsGuildRewardSchema, PoapGuildRewardSchema, FormGuildRewardSchema, GatherTownGuildRewardSchema, ERC20GuildRewardSchema, FarcasterChannelGuildRewardSchema, ]) .and( z.object({ platformGuildId: z .string() .transform((value) => value.includes("/") ? encodeURIComponent(value) : value ), }) ); export const GuildRewardSchema = BasicGuildRewardSchema.and( z.object({ id: PositiveInteger, // We'll probably deprecate this, left here to support older platforms too platformGuildName: z.string().optional(), // We only append the invite for the Discord reward in our DB in case there's no specified `platformGuildData.invite` invite: z.string().optional(), // In some cases we'll fetch the platform's name request-time, in that case it'll be added here name: z.string().optional(), }) ); export const GuildRewardCreationSchema = BasicGuildRewardSchema.and( z.object({ roleIds: z.array(z.number().int().positive()).optional(), }) ); // TODO: handle validation inside the controller later export const GuildRewardUpdateSchema = z .object({ platformGuildData: z.any(), }) .refine(...nonEmptyRefine(ErrorMessages.REQUIRED_PLATFORM_GUILD_DATA));